UNPKG

graphql-modules

Version:

Create reusable, maintainable, testable and extendable GraphQL modules

174 lines (173 loc) • 5.81 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ReflectiveInjector = exports.Injector = void 0; const resolution_1 = require("./resolution"); const registry_1 = require("./registry"); const errors_1 = require("./errors"); const _THROW_IF_NOT_FOUND = new Object(); const UNDEFINED = new Object(); const NOT_FOUND = new Object(); function notInExecutionContext() { throw new Error('Not in execution context'); } // Publicly available Injector. // We use ReflectiveInjector everywhere // but we don't want to leak its API to everyone class Injector { } exports.Injector = Injector; class ReflectiveInjector { constructor({ name, providers, parent, fallbackParent, globalProvidersMap = new Map(), }) { this._constructionCounter = 0; this._executionContextGetter = notInExecutionContext; this.displayName = name; this._parent = parent || null; this._fallbackParent = fallbackParent || null; this._providers = providers; this._globalProvidersMap = globalProvidersMap; const len = this._providers.length; this._keyIds = new Array(len); this._objs = new Array(len); for (let i = 0; i < len; i++) { this._keyIds[i] = this._providers[i].key.id; this._objs[i] = UNDEFINED; } } static createFromResolved({ name, providers, parent, fallbackParent, globalProvidersMap, }) { return new ReflectiveInjector({ name, providers, parent, fallbackParent, globalProvidersMap, }); } static resolve(providers) { return (0, resolution_1.resolveProviders)(providers); } get parent() { return this._parent; } get fallbackParent() { return this._fallbackParent; } get(token, notFoundValue = _THROW_IF_NOT_FOUND) { return this._getByKey(registry_1.Key.get(token), notFoundValue); } setExecutionContextGetter(getter) { this._executionContextGetter = getter; } _getByKey(key, notFoundValue) { let inj = this; function getObj() { while (inj instanceof ReflectiveInjector) { const inj_ = inj; const obj = inj_._getObjByKeyId(key.id); if (obj !== UNDEFINED) { return obj; } inj = inj_._parent; } return NOT_FOUND; } const resolvedValue = getObj(); if (resolvedValue !== NOT_FOUND) { return resolvedValue; } // search in fallback Injector if (this._fallbackParent) { inj = this._fallbackParent; const resolvedFallbackValue = getObj(); if (resolvedFallbackValue !== NOT_FOUND) { return resolvedFallbackValue; } } if (inj !== null) { return inj.get(key.token, notFoundValue); } return this._throwOrNull(key, notFoundValue); } _isObjectDefinedByKeyId(keyId) { for (let i = 0; i < this._keyIds.length; i++) { if (this._keyIds[i] === keyId) { return this._objs[i] !== UNDEFINED; } } return false; } _getObjByKeyId(keyId) { var _a, _b; if ((_a = this._globalProvidersMap) === null || _a === void 0 ? void 0 : _a.has(keyId)) { return (_b = this._globalProvidersMap.get(keyId)) === null || _b === void 0 ? void 0 : _b._getObjByKeyId(keyId); } for (let i = 0; i < this._keyIds.length; i++) { if (this._keyIds[i] === keyId) { if (this._objs[i] === UNDEFINED) { this._objs[i] = this._new(this._providers[i]); } return this._objs[i]; } } return UNDEFINED; } _throwOrNull(key, notFoundValue) { if (notFoundValue !== _THROW_IF_NOT_FOUND) { return notFoundValue; } else { throw (0, errors_1.noProviderError)(this, key); } } instantiateAll() { this._providers.forEach((provider) => { this._getByKey(provider.key, _THROW_IF_NOT_FOUND); }); } _instantiateProvider(provider) { const factory = provider.factory.factory; let deps; try { deps = provider.factory.dependencies.map((dep) => this._getByDependency(dep)); } catch (e) { if (e.addKey) { e.addKey(provider.key); } throw e; } let obj; try { obj = factory(...deps); // attach execution context getter if (provider.factory.executionContextIn.length > 0) { for (const prop of provider.factory.executionContextIn) { Object.defineProperty(obj, prop, { get: () => { return this._executionContextGetter(); }, }); } } } catch (e) { throw (0, errors_1.instantiationError)(this, e, provider.key); } return obj; } _getByDependency(dep) { return this._getByKey(dep.key, dep.optional ? null : _THROW_IF_NOT_FOUND); } _new(provider) { if (this._constructionCounter++ > this._getMaxNumberOfObjects()) { throw (0, errors_1.cyclicDependencyError)(this, provider.key); } return this._instantiateProvider(provider); } _getMaxNumberOfObjects() { return this._objs.length; } toString() { return this.displayName; } } exports.ReflectiveInjector = ReflectiveInjector;