accelerator-core
Version:
[](https://travis-ci.org/furkleindustries/accelerator-core)
100 lines (83 loc) • 2.56 kB
text/typescript
import {
checkPluginAsset,
} from './checkPluginAsset';
import {
IPlugin,
} from './IPlugin';
import {
IPluginExport,
} from './IPluginExport';
import {
assert,
} from 'ts-assertions';
import manifest from '../../plugins/plugins-manifest';
export const strings = {
PLUGINS_MANIFEST_INVALID:
'The plugins-manifest.json file was not parseable into an array.',
PLUGIN_OBJECT_INVALID:
'One of the plugin objects, found at %FILEPATH%, was invalid. ' +
'%REASON%',
};
assert(Array.isArray(manifest), strings.PLUGINS_MANIFEST_INVALID);
/* Memoize results and return them without computation on repeat calls. */
let pluginsList: readonly IPlugin[] | null = null;
export const getPluginsList = (): readonly IPlugin[] => {
/* Return the memoized list if it exists. */
if (pluginsList) {
return pluginsList;
}
type temp = { [key: string]: IPluginExport[] } & { none: IPluginExport[] };
const pluginsPrecedenceMap: temp = { none: [] };
manifest.forEach(({
asset,
filepath,
}) => {
const pluginObj = asset;
try {
checkPluginAsset(pluginObj);
} catch (err) {
const errStr = strings.PLUGIN_OBJECT_INVALID
.replace('%FILEPATH%', filepath)
.replace('%REASON%', err);
throw new Error(errStr);
}
if (typeof pluginObj.precedence === 'number' &&
!Number.isNaN(pluginObj.precedence))
{
const precedence = String(pluginObj.precedence);
if (!pluginsPrecedenceMap[precedence]) {
pluginsPrecedenceMap[precedence] = [];
}
pluginsPrecedenceMap[precedence].push(pluginObj);
} else {
pluginsPrecedenceMap.none.push(pluginObj);
}
});
/* Sort precedence in descending lexicographic order. In practice, this means
* 4, 3, 2, 1, and then 'none' is always appended. */
const keys = Object.keys(pluginsPrecedenceMap).sort((aa, bb) => {
if (aa !== 'none' && (bb === 'none' || aa > bb)) {
return -1;
} else if (aa === bb) {
return 0;
}
return 1;
});
pluginsList = keys.map<readonly IPluginExport[]>((key) => (
/* Sort the plugins in each precedence in ascending lexicographic
* order. */
pluginsPrecedenceMap[key]
.filter(((exp) => exp.content))
.sort((aa, bb) => {
if (aa.name === bb.name) {
return 0;
} else if (aa.name > bb.name) {
return 1;
}
return -1;
})
)).reduce<readonly IPlugin[]>((prev, curr) => (
prev.concat(curr.map((aa) => aa.content!))
), []);
return pluginsList;
};