@xoid/feature
Version:
A plugin system to compose JavaScript classes
62 lines (58 loc) • 2.11 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
const defaultFrom = (a) => {
throw new Error('`this.from` cannot be used outside the `compose` context.');
};
const current = {
from: defaultFrom,
};
class Feature {
constructor(options, from) {
this.from = function (a) {
return current.from(a);
};
this.getOptions = (defaultOptions) => (Object.assign(Object.assign({}, defaultOptions), this.externalOptions));
this.options = options;
this.externalOptions = options;
if (from)
this.from = from;
}
}
const traversePrototypeChain = (instance, fn) => {
const prototype = Object.getPrototypeOf(instance);
const { constructor } = prototype;
if (constructor === Feature || constructor === Function)
return;
fn(constructor);
traversePrototypeChain(prototype, fn);
};
function registerFeature(contextMap, instance) {
traversePrototypeChain(instance, (ctor) => contextMap.set(ctor, instance));
if (instance.id)
contextMap.set(instance.id, instance);
}
const compose = (config, getResult) => (options, overrides) => {
const contextMap = new Map();
function from(input) {
const output = contextMap.get(typeof input === 'object' ? input.id : input);
if (!output) {
throw new Error(`Dependency '${input.name}' was not found in '${this.constructor.name}'.`);
}
return output;
}
current.from = from;
// @ts-ignore
if (overrides)
config = [...config, ...overrides];
config
.map((item) => {
const instance = new item(options, from);
registerFeature(contextMap, instance);
return instance;
})
.forEach((instance) => { var _a; return (_a = instance === null || instance === void 0 ? void 0 : instance.main) === null || _a === void 0 ? void 0 : _a.call(instance); });
current.from = defaultFrom;
return getResult(from, {});
};
exports.Feature = Feature;
exports.compose = compose;