UNPKG

@asuka/di

Version:
368 lines (354 loc) 13.9 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var tslib = require('tslib'); var React = require('react'); var React__default = _interopDefault(React); var ReflectiveProvider = (function () { function ReflectiveProvider(provider) { this.provider = provider; if (typeof provider === 'function') { this.name = provider.name; this.token = provider; } else { this.name = provider.provide.toString(); this.token = provider.provide; } } ReflectiveProvider.prototype.toString = function () { return this.name; }; return ReflectiveProvider; }()); var InjectionProvider = (function () { function InjectionProvider() { this.providersMap = new Map(); } InjectionProvider.prototype.addProvider = function (provider) { var _a; this.providersMap.set((_a = provider.provide, (_a !== null && _a !== void 0 ? _a : provider)), provider); return provider; }; InjectionProvider.prototype.findProviderByToken = function (token) { if (!this.providersMap.has(token)) { return null; } return this.providersMap.get(token); }; return InjectionProvider; }()); var Injector = (function () { function Injector(parent) { if (parent === void 0) { parent = null; } this.parent = parent; this.provider = new InjectionProvider(); this.resolvedProviders = new Map(); this.providersCache = new Map(); } Injector.prototype.addProvider = function (provider) { return this.provider.addProvider(provider); }; Injector.prototype.addProviders = function (providers) { var e_1, _a; try { for (var providers_1 = tslib.__values(providers), providers_1_1 = providers_1.next(); !providers_1_1.done; providers_1_1 = providers_1.next()) { var provider = providers_1_1.value; this.provider.addProvider(provider); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (providers_1_1 && !providers_1_1.done && (_a = providers_1.return)) _a.call(providers_1); } finally { if (e_1) throw e_1.error; } } return this; }; Injector.prototype.getInstance = function (provider) { return this._getInstance(provider, true); }; Injector.prototype.resolveAndInstantiate = function (provider) { return this._getInstance(provider, false); }; Injector.prototype.createChild = function (providers) { var e_2, _a; var childInjector = new Injector(this); try { for (var providers_2 = tslib.__values(providers), providers_2_1 = providers_2.next(); !providers_2_1.done; providers_2_1 = providers_2.next()) { var provider = providers_2_1.value; childInjector.provider.addProvider(provider); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (providers_2_1 && !providers_2_1.done && (_a = providers_2.return)) _a.call(providers_2); } finally { if (e_2) throw e_2.error; } } return childInjector; }; Injector.prototype.resolveReflectiveProvider = function (provider) { var _a; var reflectiveProvider = null; if (this.provider.findProviderByToken((_a = provider.provide, (_a !== null && _a !== void 0 ? _a : provider)))) { if (this.providersCache.has(provider)) { return this.providersCache.get(provider); } reflectiveProvider = new ReflectiveProvider(provider); this.providersCache.set(provider, reflectiveProvider); } return reflectiveProvider; }; Injector.prototype._getInstance = function (provider, useCache) { var injector = this; var instance = null; var reflectiveProvider = null; var deps = this._findDeps(provider); while (injector) { reflectiveProvider = injector.resolveReflectiveProvider(provider); if (!reflectiveProvider) { injector = injector.parent; continue; } if (injector.resolvedProviders.has(reflectiveProvider)) { if (deps) { if (useCache && (injector === this || this._checkDepenciesClean(injector, deps))) { instance = injector.resolvedProviders.get(reflectiveProvider); } else { instance = this._resolveByReflectiveProvider(reflectiveProvider, false, this); if (useCache) { this.resolvedProviders.set(reflectiveProvider, instance); } } } else { instance = injector.resolvedProviders.get(reflectiveProvider); } break; } instance = injector._resolveByReflectiveProvider(reflectiveProvider, useCache, this); if (instance) { if (useCache) { injector.resolvedProviders.set(reflectiveProvider, instance); } break; } injector = injector.parent; } if (!instance) { reflectiveProvider = new ReflectiveProvider(provider); throw new TypeError("No provider for " + reflectiveProvider.name + "!"); } return instance; }; Injector.prototype._resolveByReflectiveProvider = function (reflectiveProvider, useCache, leaf) { var _a; if (useCache === void 0) { useCache = true; } if (leaf === void 0) { leaf = this; } var _b; var instance = null; var provider = reflectiveProvider.provider, name = reflectiveProvider.name; if (typeof provider === 'function') { var deps = (_b = Reflect.getMetadata('design:paramtypes', provider), (_b !== null && _b !== void 0 ? _b : [])); var depsInstance = deps.map(function (dep) { return leaf._getInstance(leaf._findExisting(dep), useCache); }); instance = new (provider.bind.apply(provider, tslib.__spread([void 0], depsInstance)))(); } else if (provider.useValue) { instance = provider.useValue; } else if (provider.useClass) { instance = leaf._getInstance(provider.useClass, useCache); } else if (provider.useFactory) { var deps = []; if (provider.deps) { deps = provider.deps.map(function (dep) { return leaf._getInstance(leaf._findExisting(dep), useCache); }); } instance = (_a = provider).useFactory.apply(_a, tslib.__spread(deps)); } else if (provider.useExisting) { instance = leaf._getInstance(this._findExisting(provider.useExisting), useCache); } if (!instance) { throw new TypeError("Can not resolve " + name + ", it's not a valid provider"); } return instance; }; Injector.prototype._findExisting = function (token) { var _a; var provider = null; var injector = this; while (injector) { provider = injector.provider.findProviderByToken(token); if (provider) { break; } injector = injector.parent; } if (!provider) { throw new TypeError("No provider for " + (_a = token.name, (_a !== null && _a !== void 0 ? _a : token.toString()))); } return provider; }; Injector.prototype._findDeps = function (provider) { return typeof provider === 'function' ? Reflect.getMetadata('design:paramtypes', provider) : provider.useClass ? Reflect.getMetadata('design:paramtypes', provider.useClass) : provider.deps ? provider.deps : null; }; Injector.prototype._checkDepenciesClean = function (leaf, deps) { var _this = this; return deps.every(function (dep) { var depInLeaf = leaf._findExisting(dep); var depInRoot = _this._findExisting(dep); var isEqual = depInLeaf === depInRoot; var deps = _this._findDeps(depInLeaf); if (deps) { return _this._checkDepenciesClean(leaf, deps) && isEqual; } return isEqual; }); }; return Injector; }()); var RootInjector = (function (_super) { tslib.__extends(RootInjector, _super); function RootInjector() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.provider = new InjectionProvider(); return _this; } RootInjector.prototype.reset = function () { this.provider = new InjectionProvider(); this.providersCache.clear(); this.resolvedProviders.clear(); }; return RootInjector; }(Injector)); var rootInjector = new RootInjector(); function Injectable() { return function (target) { rootInjector.addProvider({ useClass: target, provide: target, }); return target; }; } var _InjectableContext = React.createContext(rootInjector); function InjectableContext(_a) { var children = _a.children; return React__default.createElement(_InjectableContext.Provider, { value: rootInjector }, children); } var ProvidersContext = React.createContext([]); var InjectionProvidersContext = React.memo(function (_a) { var _b = _a.providers, providers = _b === void 0 ? [] : _b, children = _a.children; var parentInjector = React.useContext(_InjectableContext); var childInjectableFactory = React.useMemo(function () { return parentInjector.createChild(providers); }, [providers]); return (React__default.createElement(_InjectableContext.Provider, { value: childInjectableFactory }, React__default.createElement(ProvidersContext.Provider, { value: providers }, children))); }); function useInstance(provider) { var childInjector = React.useContext(_InjectableContext); return childInjector.getInstance(provider); } var InjectionToken = (function () { function InjectionToken(desc) { this.desc = desc; } InjectionToken.prototype.toString = function () { return this.desc; }; return InjectionToken; }()); function Inject(token) { return function (target, _key, paramIndex) { var deps = Reflect.getMetadata('design:paramtypes', target); deps[paramIndex] = token; }; } var Test = (function () { function Test(providers, TestModule) { var e_1, _a; var _b; this.TestModule = TestModule; this.providersMap = new Map(); try { for (var providers_1 = tslib.__values(providers), providers_1_1 = providers_1.next(); !providers_1_1.done; providers_1_1 = providers_1.next()) { var provier = providers_1_1.value; this.providersMap.set((_b = provier.provide, (_b !== null && _b !== void 0 ? _b : provier)), provier); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (providers_1_1 && !providers_1_1.done && (_a = providers_1.return)) _a.call(providers_1); } finally { if (e_1) throw e_1.error; } } } Test.createTestingModule = function (overrideConfig) { return new Test(overrideConfig && overrideConfig.providers ? overrideConfig.providers : [], overrideConfig && overrideConfig.TestModule ? overrideConfig.TestModule : TestModule); }; Test.prototype.overrideProvider = function (token) { return new MockProvider(this, token); }; Test.prototype.compile = function () { var childInjector = rootInjector.createChild(Array.from(this.providersMap.values())); return new this.TestModule(childInjector); }; return Test; }()); var MockProvider = (function () { function MockProvider(test, token) { this.test = test; this.token = token; } MockProvider.prototype.useClass = function (value) { this.test.providersMap.set(this.token, { provide: this.token, useClass: value }); return this.test; }; MockProvider.prototype.useValue = function (value) { this.test.providersMap.set(this.token, { provide: this.token, useValue: value }); return this.test; }; MockProvider.prototype.useFactory = function (value) { this.test.providersMap.set(this.token, { provide: this.token, useFactory: value }); return this.test; }; return MockProvider; }()); var AbstractTestModule = (function () { function AbstractTestModule() { } return AbstractTestModule; }()); var TestModule = (function () { function TestModule(injector) { this.injector = injector; } TestModule.prototype.getInstance = function (token) { return this.injector.getInstance(token); }; return TestModule; }()); exports.AbstractTestModule = AbstractTestModule; exports.Inject = Inject; exports.Injectable = Injectable; exports.InjectableContext = InjectableContext; exports.InjectionProvidersContext = InjectionProvidersContext; exports.InjectionToken = InjectionToken; exports.Injector = Injector; exports.MockProvider = MockProvider; exports.RootInjector = RootInjector; exports.Test = Test; exports.TestModule = TestModule; exports.rootInjector = rootInjector; exports.useInstance = useInstance;