116 lines
3.2 KiB
JavaScript
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
|
|
};
|