Files
Zos/Skills/@be/be/menu/menu-providers.js

116 lines
3.2 KiB
JavaScript

"use strict";
const fs = require("fs");
const path = require("path");
function isDirectory(p) {
try {
return fs.statSync(p).isDirectory();
} catch (e) {
return false;
}
}
function safeReadJson(filePath, logFn) {
try {
const txt = fs.readFileSync(filePath, "utf8");
if (!txt || txt.trim().length === 0) return null;
return JSON.parse(txt);
} catch (e) {
if (logFn) logFn("provider json read failed", filePath, e && e.message ? e.message : e);
return null;
}
}
function loadFromJson(filePath, ctx) {
const obj = safeReadJson(filePath, ctx && ctx.log);
if (!obj) return [];
if (Array.isArray(obj)) return obj;
if (obj && Array.isArray(obj.entries)) return obj.entries;
if (obj && Array.isArray(obj.buttons)) return obj.buttons;
return [];
}
function loadFromJs(filePath, ctx) {
try {
// eslint-disable-next-line global-require, import/no-dynamic-require
const mod = require(filePath);
if (!mod) return [];
if (typeof mod === "function") return mod(ctx) || [];
if (typeof mod.getEntries === "function") return mod.getEntries(ctx) || [];
if (Array.isArray(mod.entries)) return mod.entries;
return [];
} catch (e) {
if (ctx && ctx.log) ctx.log("provider js load failed", filePath, e && e.message ? e.message : e);
return [];
}
}
function loadProviderEntries(providersDir, ctx) {
const out = [];
if (!providersDir || !fs.existsSync(providersDir) || !isDirectory(providersDir)) {
return out;
}
let files;
try {
files = fs.readdirSync(providersDir);
} catch (e) {
return out;
}
files.sort();
files.forEach(function (name) {
if (!name || name.charAt(0) === ".") return;
const full = path.join(providersDir, name);
if (isDirectory(full)) return;
if (name.indexOf(".json", name.length - 5) !== -1) {
const entries = loadFromJson(full, ctx);
entries.forEach(function (e) { out.push(e); });
return;
}
if (name.indexOf(".js", name.length - 3) !== -1) {
const entries = loadFromJs(full, ctx);
entries.forEach(function (e) { out.push(e); });
}
});
return out;
}
// Merge provider entries into scanned entries by id.
// Provider entries win on conflicts.
function mergeById(scannedEntries, providerEntries) {
const byId = {};
(scannedEntries || []).forEach(function (e) {
if (!e || !e.id) return;
byId[e.id] = e;
});
(providerEntries || []).forEach(function (p) {
if (!p || !p.id) return;
byId[p.id] = p;
});
const merged = Object.keys(byId).map(function (k) { return byId[k]; });
merged.sort(function (a, b) {
const ao = typeof a.order === "number" ? a.order : 100;
const bo = typeof b.order === "number" ? b.order : 100;
if (ao !== bo) return ao - bo;
return String(a.title || a.label || a.id).localeCompare(String(b.title || b.label || b.id));
});
return merged;
}
module.exports = {
loadProviderEntries: loadProviderEntries,
mergeById: mergeById
};