@vulcan-sql/core
Version:
Core package of VulcanSQL
97 lines • 5.11 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExtensionLoader = void 0;
const tslib_1 = require("tslib");
const utils_1 = require("../utils");
const decorators_1 = require("../../models/extensions/decorators");
require("reflect-metadata");
const types_1 = require("../../containers/types");
const utils_2 = require("../utils");
const lodash_1 = require("lodash");
class ExtensionLoader {
constructor(config) {
this.extensionRegistry = new Map();
this.bound = false;
this.config = config;
}
/** Load external extensions (should be called by core package) */
loadExternalExtensionModules() {
var _a;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
if (this.bound)
throw new utils_1.InternalError(`We must load all extensions before call bindExtension function`);
const extensionModules =
// {moduleA: 'nameA', moduleB: ['nameB', 'nameC']}
(0, lodash_1.chain)(((_a = this.config) === null || _a === void 0 ? void 0 : _a.extensions) || {})
// [['moduleA', 'nameA'], ['moduleB',['nameB', 'nameC']]]
.toPairs()
// [{alias: 'moduleA', path: 'nameA'}, {alias: 'moduleB', path: 'nameB'}, {alias: 'moduleB', path: 'nameC'}]
.flatMap(([alias, path]) => (typeof path === 'string' ? [path] : path).map((p) => ({
alias,
path: p,
})))
.value();
for (const module of extensionModules) {
const moduleEntry = (yield (0, utils_1.defaultImport)(module.path))[0];
const extensions = (0, utils_2.flattenElements)(moduleEntry);
extensions.forEach((extension) => this.loadExtension(module.alias, extension));
}
});
}
loadInternalExtensionModule(moduleEntry) {
if (this.bound)
throw new utils_1.InternalError(`We must load all extensions before call bindExtension function`);
const extensions = (0, utils_2.flattenElements)(moduleEntry);
for (const extension of extensions) {
const name = Reflect.getMetadata(decorators_1.EXTENSION_NAME_METADATA_KEY, extension);
if (name === undefined)
throw new utils_1.InternalError(`Internal extension must have @VulcanInternalExtension decorator`);
this.loadExtension(name, extension);
}
}
bindExtensions(bind) {
for (const type of this.extensionRegistry.keys()) {
this.extensionRegistry.get(type).forEach(({ name, extension }) => {
const extensionBinding = bind(type).to(extension).inSingletonScope();
const { extensionId } = this.getExtensionMetadata(extension);
if (extensionId)
extensionBinding.when((request) => {
// If request contains named tag, i.e. @named or getNamed(), we check the extensionId, otherwise we fulfill the request.
// It makes both @named tag and @multiInject work at same time.
const namedTag = request.target.getNamedTag();
if (namedTag)
return namedTag.value === extensionId;
return true;
});
bind(types_1.TYPES.ExtensionConfig)
// Note they we can't bind undefined to container or it throw error while unbinding.
// https://github.com/inversify/InversifyJS/issues/1462#issuecomment-1202099036
.toConstantValue(name.length > 0 ? this.config[name] || {} : {})
.whenInjectedInto(extension);
bind(types_1.TYPES.ExtensionName)
.toConstantValue(name || '')
.whenInjectedInto(extension);
});
}
this.bound = true;
}
getExtensionMetadata(extension) {
const extensionId = Reflect.getMetadata(decorators_1.EXTENSION_IDENTIFIER_METADATA_KEY, extension);
const enforcedId = Reflect.getMetadata(decorators_1.EXTENSION_ENFORCED_ID_METADATA_KEY, extension);
if (enforcedId && !extensionId)
throw new utils_1.InternalError(`Extension ${extension.name} needed an extension id but was not found, please use the decorator @VulcanExtensionId to set the id.`);
return {
extensionId,
};
}
loadExtension(name, extension) {
const extensionType = Reflect.getMetadata(decorators_1.EXTENSION_TYPE_METADATA_KEY, extension);
if (!extensionType)
throw new utils_1.InternalError(`Extension must have @VulcanExtension decorator, have you use extend the correct super class?`);
if (!this.extensionRegistry.has(extensionType))
this.extensionRegistry.set(extensionType, []);
this.extensionRegistry.get(extensionType).push({ name, extension });
}
}
exports.ExtensionLoader = ExtensionLoader;
//# sourceMappingURL=extensionLoader.js.map