nestjs-custom-injector
Version:
Custom injecting logic for NestJS with support multi providing
339 lines • 17.2 kB
JavaScript
"use strict";
var CustomInjectorService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CustomInjectorService = void 0;
const tslib_1 = require("tslib");
const common_1 = require("@nestjs/common");
const core_1 = require("@nestjs/core");
const constants_1 = require("@nestjs/core/injector/constants");
const custom_injector_types_1 = require("./custom-injector.types");
const custom_injector_utils_1 = require("./custom-injector.utils");
let CustomInjectorService = CustomInjectorService_1 = class CustomInjectorService {
constructor(discoveryService) {
this.discoveryService = discoveryService;
CustomInjectorService_1._instance = this;
}
static getInstance() {
return CustomInjectorService_1._instance;
}
getProvider(token, options) {
return this._getProvider(token, options || {}, undefined);
}
getAsyncProvider(token, options) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
return this._getAsyncProvider(token, options || {}, undefined);
});
}
getProviders(token, options) {
return this._getProviders(token, options || {}, undefined);
}
getAsyncProviders(token, options) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
return this._getAsyncProviders(token, options || {}, undefined);
});
}
createInjectedProvidersStorageItem(token, target, options) {
return {
appiled: false,
instance: null,
init: function () {
var _a, _b;
this.options = Object.assign(Object.assign({}, (this.options || {})), { multi: Boolean(this.options.multi) });
if (!((_a = this.options) === null || _a === void 0 ? void 0 : _a.lazy) && this.appiled) {
return;
}
if ((_b = this.options) === null || _b === void 0 ? void 0 : _b.multi) {
this.instance = CustomInjectorService_1.getInstance()._getProviders(this.token, this.options, this);
}
else {
this.instance = CustomInjectorService_1.getInstance()._getProvider(this.token, this.options, this);
}
this.appiled = true;
},
asyncInit: function () {
var _a, _b;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
this.options = Object.assign(Object.assign({}, (this.options || {})), { multi: Boolean(this.options.multi) });
if (!((_a = this.options) === null || _a === void 0 ? void 0 : _a.lazy) && this.appiled) {
return;
}
if ((_b = this.options) === null || _b === void 0 ? void 0 : _b.multi) {
this.instance =
yield CustomInjectorService_1.getInstance()._getAsyncProviders(this.token, this.options, this);
}
else {
this.instance =
yield CustomInjectorService_1.getInstance()._getAsyncProvider(this.token, this.options, this);
}
this.appiled = true;
});
},
target,
token,
options,
};
}
initAllNeedProviders() {
var _a, _b;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const items = this.discoveryService
.getProviders()
.map((component) => this.toDiscoveredClass(component))
.filter(Boolean)
.map((c) => {
try {
return Reflect.getMetadataKeys(c)
.filter((k) => k.indexOf(custom_injector_types_1.CUSTOM_INJECTOR_METADATA) === 0)
.map((k) => Reflect.getMetadata(k, c));
}
catch (err) {
// todo: add support debug for library and catch all errors
if (process.env.DEBUG) {
console.debug(c);
console.error(err);
}
return [];
}
})
.reduce((all, cur) => [...all, ...cur], []);
for (let index = 0; index < items.length; index++) {
if (!((_b = (_a = items[index]) === null || _a === void 0 ? void 0 : _a.options) === null || _b === void 0 ? void 0 : _b.lazy) && items[index].asyncInit) {
yield items[index].asyncInit();
}
}
});
}
_getProvider(token, options, injectedProvidersStorageItem) {
var _a, _b;
const object = this.getOneProvider(token, options, injectedProvidersStorageItem);
if (Object.getOwnPropertyDescriptor(options || {}, 'propertyName')) {
const propertyName = (_a = Object.getOwnPropertyDescriptor(options || {}, 'propertyName')) === null || _a === void 0 ? void 0 : _a.value;
if (Object.getOwnPropertyDescriptor(object || {}, propertyName)) {
const propertyObject = (_b = Object.getOwnPropertyDescriptor(object || {}, propertyName)) === null || _b === void 0 ? void 0 : _b.value;
return propertyObject;
}
throw this.errorFactory(token, injectedProvidersStorageItem, options === null || options === void 0 ? void 0 : options.errorFactory);
}
return object;
}
_getAsyncProvider(token, options, injectedProvidersStorageItem) {
var _a, _b;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
let object = this.getOneProvider(token, options, injectedProvidersStorageItem);
if (Object.getOwnPropertyDescriptor(options || {}, 'propertyName')) {
const propertyName = (_a = Object.getOwnPropertyDescriptor(options || {}, 'propertyName')) === null || _a === void 0 ? void 0 : _a.value;
if ((0, custom_injector_utils_1.isPromise)(object)) {
object = yield object;
}
if (Object.getOwnPropertyDescriptor(object || {}, propertyName)) {
const propertyObject = (_b = Object.getOwnPropertyDescriptor(object || {}, propertyName)) === null || _b === void 0 ? void 0 : _b.value;
if ((0, custom_injector_utils_1.isPromise)(propertyObject)) {
return yield propertyObject;
}
else {
return propertyObject;
}
}
throw this.errorFactory(token, injectedProvidersStorageItem, options === null || options === void 0 ? void 0 : options.errorFactory);
}
if ((0, custom_injector_utils_1.isPromise)(object)) {
return yield object;
}
else {
return object;
}
});
}
getOneProvider(token, options, injectedProvidersStorageItem) {
return typeof token === 'string' ||
typeof token === 'symbol' ||
String(token).includes('Abstract') ||
String(token).includes('abstract')
? this._getLastComponentByName(token, options, injectedProvidersStorageItem)
: this._getLastComponentsByClass(token, options, injectedProvidersStorageItem);
}
_getProviders(token, options, injectedProvidersStorageItem) {
var _a;
const objects = this.getManyProviders(token, options, injectedProvidersStorageItem);
if (Object.getOwnPropertyDescriptor(options || {}, 'propertyName')) {
const propertyName = (_a = Object.getOwnPropertyDescriptor(options || {}, 'propertyName')) === null || _a === void 0 ? void 0 : _a.value;
const resolvedObjects = [];
for (let index = 0; index < objects.length; index++) {
resolvedObjects.push(objects[index]);
}
return resolvedObjects
.filter((o) => Object.getOwnPropertyDescriptor(o || {}, propertyName))
.map((o) => { var _a; return (_a = Object.getOwnPropertyDescriptor(o || {}, propertyName)) === null || _a === void 0 ? void 0 : _a.value; });
}
const resolvedObjects = [];
for (let index = 0; index < objects.length; index++) {
resolvedObjects.push(objects[index]);
}
return resolvedObjects;
}
getManyProviders(token, options, injectedProvidersStorageItem) {
return typeof token === 'string' ||
typeof token === 'symbol' ||
String(token).includes('Abstract') ||
String(token).includes('abstract')
? this._getComponentsByName(token, options, injectedProvidersStorageItem)
: this._getComponentsByClass(token, options, injectedProvidersStorageItem);
}
_getAsyncProviders(token, options, injectedProvidersStorageItem) {
var _a;
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const objects = this.getManyProviders(token, options, injectedProvidersStorageItem);
if (Object.getOwnPropertyDescriptor(options || {}, 'propertyName')) {
const propertyName = (_a = Object.getOwnPropertyDescriptor(options || {}, 'propertyName')) === null || _a === void 0 ? void 0 : _a.value;
const resolvedObjects = [];
for (let index = 0; index < objects.length; index++) {
let object;
if ((0, custom_injector_utils_1.isPromise)(objects[index])) {
object = yield objects[index];
}
else {
object = objects[index];
}
resolvedObjects.push(object);
}
return resolvedObjects
.filter((o) => Object.getOwnPropertyDescriptor(o || {}, propertyName))
.map((o) => { var _a; return (_a = Object.getOwnPropertyDescriptor(o || {}, propertyName)) === null || _a === void 0 ? void 0 : _a.value; });
}
const resolvedObjects = [];
for (let index = 0; index < objects.length; index++) {
let object;
if ((0, custom_injector_utils_1.isPromise)(objects[index])) {
object = yield objects[index];
}
else {
object = objects[index];
}
resolvedObjects.push(object);
}
return resolvedObjects;
});
}
_getLastComponentByName(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
token, options, injectedProvidersStorageItem) {
let components;
try {
components = this._getComponentsByName(token, options, injectedProvidersStorageItem);
}
catch (err) {
components = [];
}
const defaultProviderValue = options === null || options === void 0 ? void 0 : options.defaultProviderValue;
const component = components.length === 0 ? undefined : components[0];
if (component === undefined) {
if (defaultProviderValue === undefined) {
throw this.errorFactory(token, injectedProvidersStorageItem, options === null || options === void 0 ? void 0 : options.errorFactory);
}
return defaultProviderValue;
}
return component;
}
_getLastComponentsByClass(
// eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/no-explicit-any
token, options, injectedProvidersStorageItem) {
let components;
try {
components = this._getComponentsByClass(token, options, injectedProvidersStorageItem);
}
catch (err) {
components = [];
}
const defaultProviderValue = options === null || options === void 0 ? void 0 : options.defaultProviderValue;
const component = components.length === 0 ? undefined : components[0];
if (component === undefined) {
if (defaultProviderValue === undefined) {
throw this.errorFactory(token, injectedProvidersStorageItem, options === null || options === void 0 ? void 0 : options.errorFactory);
}
return defaultProviderValue;
}
return component;
}
_getComponentsByName(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
token, options, injectedProvidersStorageItem) {
if (!this.discoveryService) {
throw new custom_injector_types_1.CustomInjectorError(`this.discoveryService not set`);
}
let values = this.discoveryService
.getProviders()
.filter((component) => component.scope !== common_1.Scope.REQUEST &&
(component.name === token || component.token === token))
.map((component) => this.toDiscoveredClass(component))
.map((component) => (options === null || options === void 0 ? void 0 : options.providerFactory)
? options === null || options === void 0 ? void 0 : options.providerFactory(component)
: component);
if (values.length === 0 &&
!Object.getOwnPropertyDescriptor(options, 'providersFactory') &&
!Object.getOwnPropertyDescriptor(options, 'defaultProvidersValue')) {
throw this.errorFactory(token, injectedProvidersStorageItem, options === null || options === void 0 ? void 0 : options.errorFactory);
}
if (options === null || options === void 0 ? void 0 : options.providersFactory) {
values = options.providersFactory(values);
}
if (options === null || options === void 0 ? void 0 : options.defaultProvidersValue) {
values = options.defaultProvidersValue;
}
return values;
}
_getComponentsByClass(
// eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/no-explicit-any
cls, options, injectedProvidersStorageItem) {
if (!this.discoveryService) {
throw new custom_injector_types_1.CustomInjectorError(`this.discoveryService not set`);
}
let values = this.discoveryService
.getProviders()
.filter((component) => component.scope !== common_1.Scope.REQUEST)
.map((component) => this.toDiscoveredClass(component))
.filter((obj) => {
try {
return obj && obj instanceof cls;
}
catch (err) {
return false;
}
})
.map((component) => (options === null || options === void 0 ? void 0 : options.providerFactory)
? options === null || options === void 0 ? void 0 : options.providerFactory(component)
: component);
if (values.length === 0 &&
!Object.getOwnPropertyDescriptor(options, 'providersFactory') &&
!Object.getOwnPropertyDescriptor(options, 'defaultProvidersValue')) {
throw this.errorFactory(cls, injectedProvidersStorageItem, options === null || options === void 0 ? void 0 : options.errorFactory);
}
if (options === null || options === void 0 ? void 0 : options.providersFactory) {
values = options.providersFactory(values);
}
if (options === null || options === void 0 ? void 0 : options.defaultProvidersValue) {
values = options.defaultProvidersValue;
}
return values;
}
errorFactory(token, injectedProvidersStorageItem, errorFactory) {
var _a, _b;
return errorFactory
? errorFactory(`${((_a = injectedProvidersStorageItem === null || injectedProvidersStorageItem === void 0 ? void 0 : injectedProvidersStorageItem.options) === null || _a === void 0 ? void 0 : _a.multi)
? 'Providers'
: 'Provider'} "${token.toString()}" not found!`, injectedProvidersStorageItem)
: new custom_injector_types_1.CustomInjectorError(`${((_b = injectedProvidersStorageItem === null || injectedProvidersStorageItem === void 0 ? void 0 : injectedProvidersStorageItem.options) === null || _b === void 0 ? void 0 : _b.multi)
? 'Providers'
: 'Provider'} "${token.toString()}" not found!`, injectedProvidersStorageItem);
}
toDiscoveredClass(wrapper) {
const instanceHost = wrapper.getInstanceByContextId(constants_1.STATIC_CONTEXT, wrapper && wrapper.id ? wrapper.id : undefined);
return instanceHost.instance;
}
};
CustomInjectorService._instance = new CustomInjectorService_1(new core_1.DiscoveryService(new core_1.ModulesContainer()));
CustomInjectorService = CustomInjectorService_1 = tslib_1.__decorate([
(0, common_1.Injectable)(),
tslib_1.__metadata("design:paramtypes", [core_1.DiscoveryService])
], CustomInjectorService);
exports.CustomInjectorService = CustomInjectorService;
//# sourceMappingURL=custom-injector.service.js.map