ditox 2.4.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -13
- package/dist/browser/index.d.ts +6 -5
- package/dist/browser/index.js +1 -1
- package/dist/cjs/container.d.ts +2 -4
- package/dist/cjs/container.js +10 -14
- package/dist/cjs/container.js.map +1 -1
- package/dist/cjs/modules.d.ts +4 -3
- package/dist/cjs/modules.js +54 -20
- package/dist/cjs/modules.js.map +1 -1
- package/dist/esm/container.d.ts +2 -4
- package/dist/esm/container.js +9 -12
- package/dist/esm/container.js.map +1 -1
- package/dist/esm/modules.d.ts +4 -3
- package/dist/esm/modules.js +53 -19
- package/dist/esm/modules.js.map +1 -1
- package/dist/umd/index.d.ts +6 -5
- package/dist/umd/index.js +1 -1
- package/package.json +2 -3
- package/src/container.test.ts +60 -35
- package/src/container.ts +10 -17
- package/src/modules.test.ts +69 -6
- package/src/modules.ts +69 -27
package/README.md
CHANGED
|
@@ -31,14 +31,6 @@ The package can be used as [UMD](https://github.com/umdjs/umd) module. Use
|
|
|
31
31
|
</script>
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
Using in Deno environment:
|
|
35
|
-
|
|
36
|
-
```ts
|
|
37
|
-
import {createContainer} from 'https://deno.land/x/ditox/mod.ts';
|
|
38
|
-
|
|
39
|
-
const container = createContainer();
|
|
40
|
-
```
|
|
41
|
-
|
|
42
34
|
## General description
|
|
43
35
|
|
|
44
36
|
DI pattern in general allows to declare and construct a code graph of an
|
|
@@ -127,7 +119,7 @@ container.bindFactory(
|
|
|
127
119
|
const logger = container.get(LOGGER_TOKEN);
|
|
128
120
|
|
|
129
121
|
// Resolve a value, it throws `ResolverError` in case a value is not found.
|
|
130
|
-
const userService = container.resolve(
|
|
122
|
+
const userService = container.resolve(USER_SERVICE_TOKEN);
|
|
131
123
|
|
|
132
124
|
// Remove a value from the container.
|
|
133
125
|
container.remove(LOGGER_TOKEN);
|
|
@@ -164,15 +156,15 @@ Ditox.js supports managing the lifetime of values which are produced by
|
|
|
164
156
|
factories. There are the following types:
|
|
165
157
|
|
|
166
158
|
- `singleton` - **This is the default**. The value is created and cached by the
|
|
167
|
-
container which
|
|
168
|
-
- `scoped` - The value is created and cached by the container which
|
|
169
|
-
|
|
159
|
+
most distant parent container which owns the factory function.
|
|
160
|
+
- `scoped` - The value is created and cached by the nearest container which owns
|
|
161
|
+
the factory function.
|
|
170
162
|
- `transient` - The value is created every time it is resolved.
|
|
171
163
|
|
|
172
164
|
### `singleton`
|
|
173
165
|
|
|
174
166
|
**This is the default scope**. "Singleton" allows to cache a produced value by a
|
|
175
|
-
parent container which registered the factory:
|
|
167
|
+
most distant parent container which registered the factory function:
|
|
176
168
|
|
|
177
169
|
```js
|
|
178
170
|
import {creatContainer, token} from 'ditox';
|
package/dist/browser/index.d.ts
CHANGED
|
@@ -69,8 +69,8 @@ type FactoryScope = 'scoped' | 'singleton' | 'transient';
|
|
|
69
69
|
* Options for factory binding.
|
|
70
70
|
*
|
|
71
71
|
* `scope` types:
|
|
72
|
-
* - `singleton` - **This is the default**. The value is created and cached by the container which
|
|
73
|
-
* - `scoped` - The value is created and cached by the container which
|
|
72
|
+
* - `singleton` - **This is the default**. The value is created and cached by the most distant parent container which owns the factory function.
|
|
73
|
+
* - `scoped` - The value is created and cached by the nearest container which owns the factory function.
|
|
74
74
|
* - `transient` - The value is created every time it is resolved.
|
|
75
75
|
*
|
|
76
76
|
* `scoped` and `singleton` scopes can have `onRemoved` callback. It is called when a token is removed from the container.
|
|
@@ -316,16 +316,17 @@ type ModuleDeclaration<T extends Module<AnyObject>> = {
|
|
|
316
316
|
* Options for module binding.
|
|
317
317
|
*
|
|
318
318
|
* `scope` types:
|
|
319
|
-
* - `singleton` - **This is the default**. The
|
|
320
|
-
* - `scoped` - The
|
|
319
|
+
* - `singleton` - **This is the default**. The value is created and cached by the most distant parent container which owns the factory function.
|
|
320
|
+
* - `scoped` - The value is created and cached by the nearest container which owns the factory function.
|
|
321
321
|
*/
|
|
322
322
|
type BindModuleOptions = {
|
|
323
323
|
scope?: 'scoped' | 'singleton';
|
|
324
324
|
};
|
|
325
|
-
type
|
|
325
|
+
type ModuleDeclarationWithOptions = {
|
|
326
326
|
module: ModuleDeclaration<AnyObject>;
|
|
327
327
|
options: BindModuleOptions;
|
|
328
328
|
};
|
|
329
|
+
type ModuleBindingEntry = ModuleDeclaration<AnyObject> | ModuleDeclarationWithOptions;
|
|
329
330
|
/**
|
|
330
331
|
* Binds the dependency module to the container
|
|
331
332
|
* @param container - Dependency container.
|
package/dist/browser/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function o(o){var n="string"==typeof o?{description:o}:o;return{symbol:(null==n?void 0:n.key)?Symbol.for(n.key):Symbol(null==n?void 0:n.description)}}function n(o,n){return{symbol:o.symbol,isOptional:!0,optionalValue:n}}var t=function(o,n){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(o,n){o.__proto__=n}||function(o,n){for(var t in n)Object.prototype.hasOwnProperty.call(n,t)&&(o[t]=n[t])},t(o,n)};var r=function(){return r=Object.assign||function(o){for(var n,t=1,r=arguments.length;t<r;t++)for(var e in n=arguments[t])Object.prototype.hasOwnProperty.call(n,e)&&(o[e]=n[e]);return o},r.apply(this,arguments)};function e(o,n,t){if(t||2===arguments.length)for(var r,e=0,i=n.length;e<i;e++)!r&&e in n||(r||(r=Array.prototype.slice.call(n,0,e)),r[e]=n[e]);return o.concat(r||Array.prototype.slice.call(n))}var i=function(o){function n(n){var t=this.constructor,r=o.call(this,n)||this;return Object.setPrototypeOf(r,t.prototype),r.name="ResolverError",r}return function(o,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}(n,o),n}(Error),
|
|
1
|
+
function o(o){var n="string"==typeof o?{description:o}:o;return{symbol:(null==n?void 0:n.key)?Symbol.for(n.key):Symbol(null==n?void 0:n.description)}}function n(o,n){return{symbol:o.symbol,isOptional:!0,optionalValue:n}}var t=function(o,n){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(o,n){o.__proto__=n}||function(o,n){for(var t in n)Object.prototype.hasOwnProperty.call(n,t)&&(o[t]=n[t])},t(o,n)};var r=function(){return r=Object.assign||function(o){for(var n,t=1,r=arguments.length;t<r;t++)for(var e in n=arguments[t])Object.prototype.hasOwnProperty.call(n,e)&&(o[e]=n[e]);return o},r.apply(this,arguments)};function e(o,n,t){if(t||2===arguments.length)for(var r,e=0,i=n.length;e<i;e++)!r&&e in n||(r||(r=Array.prototype.slice.call(n,0,e)),r[e]=n[e]);return o.concat(r||Array.prototype.slice.call(n))}var i=function(o){function n(n){var t=this.constructor,r=o.call(this,n)||this;return Object.setPrototypeOf(r,t.prototype),r.name="ResolverError",r}return function(o,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}(n,o),n}(Error),l=o("ditox.Container"),u=o("ditox.ParentContainer"),a=o("ditox.Resolver"),c=Symbol(),s="singleton",f=o("ditox.FactoriesMap");function v(o){return o.symbol===l.symbol||o.symbol===u.symbol||o.symbol===a.symbol}function p(o){var n=new Map,t=new Map,r={bindValue:function(o,t){v(o)||n.set(o.symbol,t)},bindFactory:function(o,n,r){v(o)||t.set(o.symbol,{factory:n,options:r})},remove:function(o){var r;if(!v(o)){var e=null===(r=t.get(o.symbol))||void 0===r?void 0:r.options;e&&p(o.symbol,e),n.delete(o.symbol),t.delete(o.symbol)}},removeAll:function(){t.forEach((function(o,n){o.options&&p(n,o.options)})),n.clear(),t.clear(),y()},hasToken:function(r){var e;return n.has(r.symbol)||t.has(r.symbol)||null!==(e=null==o?void 0:o.hasToken(r))&&void 0!==e&&e},get:function(o){var n=e(o,r);return n!==c?n:o.isOptional?o.optionalValue:void 0},resolve:function(o){var n,t=e(o,r);if(t!==c)return t;if(o.isOptional)return o.optionalValue;throw new i('Token "'.concat(null!==(n=o.symbol.description)&&void 0!==n?n:"",'" is not provided'))}};function e(e,i){var l=n.get(e.symbol),u=void 0!==l||n.has(e.symbol);if(u&&i===r)return l;var f,v,p=t.get(e.symbol);if(p)switch(f=p.options,null!==(v=null==f?void 0:f.scope)&&void 0!==v?v:s){case"singleton":if(u)return l;if(null==o?void 0:o.hasToken(e))break;var y=p.factory(r);return r.bindValue(e,y),y;case"scoped":if(u)return l;var d=p.factory(r);return r.bindValue(e,d),d;case"transient":return p.factory(i)}if(u)return l;var m=null==o?void 0:o.get(a);return m?m(e,i):c}function p(o,t){var r=function(o){return void 0===o.scope||"scoped"===o.scope||"singleton"===o.scope?o.onRemoved:void 0}(t);if(r){var e=n.get(o);(void 0!==e||n.has(o))&&r(e)}}function y(){n.set(l.symbol,r),n.set(a.symbol,e),n.set(f.symbol,t),o&&n.set(u.symbol,o)}return y(),r}function y(o){return null!=o&&"object"==typeof o&&"symbol"in o&&"symbol"==typeof o.symbol}function d(o,n,t){var r,i=e(e([],null!==(r=o.get(n))&&void 0!==r?r:[],!0),[t],!1);o.bindValue(n,i)}function m(o,n){if(y(n))return o.get(n);var t={};return Object.keys(n).forEach((function(r){return t[r]=o.get(n[r])})),t}function b(o){for(var n=[],t=1;t<arguments.length;t++)n[t-1]=arguments[t];return n.map((function(n){return m(o,n)}))}function h(o,n){if(y(n))return o.resolve(n);var t={};return Object.keys(n).forEach((function(r){return t[r]=o.resolve(n[r])})),t}function g(o){for(var n=[],t=1;t<arguments.length;t++)n[t-1]=arguments[t];return n.map((function(n){return h(o,n)}))}function O(o){for(var n=this,t=[],r=1;r<arguments.length;r++)t[r-1]=arguments[r];return function(r){var i=g.apply(void 0,e([r],t,!1));return o.apply(n,i)}}function k(o){for(var n=[],t=1;t<arguments.length;t++)n[t-1]=arguments[t];return O.apply(void 0,e([function(){for(var n=[],t=0;t<arguments.length;t++)n[t]=arguments[t];return new(o.bind.apply(o,e([void 0],n,!1)))}],n,!1))}function w(o,n,t){for(var r,e,i,l={module:n,options:null!=t?t:{}},u=new Set([l]),a=[l],c=0;c<a.length;){null===(r=(v="module"in(f=a[c])?f.module:f).imports)||void 0===r||r.forEach((function(o){u.has(o)||(u.add(o),a.push(o))})),c++}for(var s=0;s<a.length;s++){null===(e=(v="module"in(f=a[s])?f.module:f).beforeBinding)||void 0===e||e.call(v,o)}for(s=0;s<a.length;s++){j(o,f=a[s])}for(s=a.length-1;s>=0;s--){var f,v;null===(i=(v="module"in(f=a[s])?f.module:f).afterBinding)||void 0===i||i.call(v,o)}}function j(o,n){var t,r;"module"in n?(t=n.module,r=n.options):t=n;var e=null==r?void 0:r.scope,i=new Set,l=t.exports;l&&Object.keys(l).forEach((function(n){var r=l[n];r&&(i.add(r),o.bindFactory(r,O((function(o){return o[n]}),t.token),{scope:e}))}));o.bindFactory(t.token,t.factory,{scope:e,onRemoved:function(n){n.destroy&&n.destroy(),i.forEach((function(n){return o.remove(n)})),i.clear()}})}function E(o,n){n.forEach((function(n){"module"in n?w(o,n.module,n.options):w(o,n)}))}function _(n){var t;return r(r({},n),{token:null!==(t=n.token)&&void 0!==t?t:o()})}function x(o){return _({factory:function(){return{}},imports:o})}export{i as ResolverError,w as bindModule,E as bindModules,d as bindMultiValue,p as createContainer,_ as declareModule,x as declareModuleBindings,O as injectable,k as injectableClass,y as isToken,n as optional,h as resolveValue,g as resolveValues,o as token,m as tryResolveValue,b as tryResolveValues};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/cjs/container.d.ts
CHANGED
|
@@ -13,8 +13,8 @@ export type FactoryScope = 'scoped' | 'singleton' | 'transient';
|
|
|
13
13
|
* Options for factory binding.
|
|
14
14
|
*
|
|
15
15
|
* `scope` types:
|
|
16
|
-
* - `singleton` - **This is the default**. The value is created and cached by the container which
|
|
17
|
-
* - `scoped` - The value is created and cached by the container which
|
|
16
|
+
* - `singleton` - **This is the default**. The value is created and cached by the most distant parent container which owns the factory function.
|
|
17
|
+
* - `scoped` - The value is created and cached by the nearest container which owns the factory function.
|
|
18
18
|
* - `transient` - The value is created every time it is resolved.
|
|
19
19
|
*
|
|
20
20
|
* `scoped` and `singleton` scopes can have `onRemoved` callback. It is called when a token is removed from the container.
|
|
@@ -67,8 +67,6 @@ export declare const RESOLVER: Token<Resolver>;
|
|
|
67
67
|
/** @internal */
|
|
68
68
|
declare const NOT_FOUND: unique symbol;
|
|
69
69
|
/** @internal */
|
|
70
|
-
export declare const FAKE_FACTORY: () => never;
|
|
71
|
-
/** @internal */
|
|
72
70
|
type FactoryContext<T> = {
|
|
73
71
|
factory: (container: Container) => T;
|
|
74
72
|
options?: FactoryOptions<T>;
|
package/dist/cjs/container.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createContainer = exports.FACTORIES_MAP = exports.
|
|
3
|
+
exports.createContainer = exports.FACTORIES_MAP = exports.RESOLVER = exports.PARENT_CONTAINER = exports.CONTAINER = exports.ResolverError = void 0;
|
|
4
4
|
const tokens_1 = require("./tokens");
|
|
5
5
|
/**
|
|
6
6
|
* ResolverError is thrown by the resolver when a token is not found in a container.
|
|
@@ -22,11 +22,6 @@ exports.RESOLVER = (0, tokens_1.token)('ditox.Resolver');
|
|
|
22
22
|
/** @internal */
|
|
23
23
|
const NOT_FOUND = Symbol();
|
|
24
24
|
/** @internal */
|
|
25
|
-
const FAKE_FACTORY = () => {
|
|
26
|
-
throw new Error('FAKE_FACTORY');
|
|
27
|
-
};
|
|
28
|
-
exports.FAKE_FACTORY = FAKE_FACTORY;
|
|
29
|
-
/** @internal */
|
|
30
25
|
const DEFAULT_SCOPE = 'singleton';
|
|
31
26
|
/** @internal */
|
|
32
27
|
exports.FACTORIES_MAP = (0, tokens_1.token)('ditox.FactoriesMap');
|
|
@@ -129,7 +124,7 @@ function createContainer(parentContainer) {
|
|
|
129
124
|
return value;
|
|
130
125
|
}
|
|
131
126
|
const factoryContext = factories.get(token.symbol);
|
|
132
|
-
if (factoryContext
|
|
127
|
+
if (factoryContext) {
|
|
133
128
|
const scope = getScope(factoryContext.options);
|
|
134
129
|
switch (scope) {
|
|
135
130
|
case 'singleton': {
|
|
@@ -147,14 +142,15 @@ function createContainer(parentContainer) {
|
|
|
147
142
|
}
|
|
148
143
|
}
|
|
149
144
|
case 'scoped': {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
//
|
|
155
|
-
|
|
145
|
+
if (hasValue) {
|
|
146
|
+
return value;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
// Create a value within the factory's container and cache it.
|
|
150
|
+
const value = factoryContext.factory(container);
|
|
151
|
+
container.bindValue(token, value);
|
|
152
|
+
return value;
|
|
156
153
|
}
|
|
157
|
-
return value;
|
|
158
154
|
}
|
|
159
155
|
case 'transient': {
|
|
160
156
|
// Create a value within the origin container and don't cache it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/container.ts"],"names":[],"mappings":";;;AAAA,qCAAsC;AAEtC;;GAEG;AACH,MAAa,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAND,sCAMC;AAsED,gBAAgB;AACH,QAAA,SAAS,GAAqB,IAAA,cAAK,EAAC,iBAAiB,CAAC,CAAC;AACpE,gBAAgB;AACH,QAAA,gBAAgB,GAAqB,IAAA,cAAK,EACrD,uBAAuB,CACxB,CAAC;AACF,gBAAgB;AACH,QAAA,QAAQ,GAAoB,IAAA,cAAK,EAAC,gBAAgB,CAAC,CAAC;AAEjE,gBAAgB;AAChB,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC;AAE3B,gBAAgB;
|
|
1
|
+
{"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/container.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/modules.d.ts
CHANGED
|
@@ -59,16 +59,17 @@ export type AnyModuleDeclaration = ModuleDeclaration<Module<AnyObject>>;
|
|
|
59
59
|
* Options for module binding.
|
|
60
60
|
*
|
|
61
61
|
* `scope` types:
|
|
62
|
-
* - `singleton` - **This is the default**. The
|
|
63
|
-
* - `scoped` - The
|
|
62
|
+
* - `singleton` - **This is the default**. The value is created and cached by the most distant parent container which owns the factory function.
|
|
63
|
+
* - `scoped` - The value is created and cached by the nearest container which owns the factory function.
|
|
64
64
|
*/
|
|
65
65
|
export type BindModuleOptions = {
|
|
66
66
|
scope?: 'scoped' | 'singleton';
|
|
67
67
|
};
|
|
68
|
-
|
|
68
|
+
type ModuleDeclarationWithOptions = {
|
|
69
69
|
module: ModuleDeclaration<AnyObject>;
|
|
70
70
|
options: BindModuleOptions;
|
|
71
71
|
};
|
|
72
|
+
export type ModuleBindingEntry = ModuleDeclaration<AnyObject> | ModuleDeclarationWithOptions;
|
|
72
73
|
/**
|
|
73
74
|
* Binds the dependency module to the container
|
|
74
75
|
* @param container - Dependency container.
|
package/dist/cjs/modules.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.declareModuleBindings = exports.declareModule = exports.bindModules = exports.bindModule = void 0;
|
|
4
|
-
const utils_1 = require("./utils");
|
|
5
4
|
const tokens_1 = require("./tokens");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
6
|
/**
|
|
7
7
|
* Binds the dependency module to the container
|
|
8
8
|
* @param container - Dependency container.
|
|
@@ -15,41 +15,75 @@ const tokens_1 = require("./tokens");
|
|
|
15
15
|
* ```
|
|
16
16
|
*/
|
|
17
17
|
function bindModule(container, moduleDeclaration, options) {
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
var _a, _b, _c;
|
|
19
|
+
const rootEntry = {
|
|
20
|
+
module: moduleDeclaration,
|
|
21
|
+
options: options !== null && options !== void 0 ? options : {},
|
|
22
|
+
};
|
|
23
|
+
const bfsVisits = new Set([rootEntry]);
|
|
24
|
+
const bfsQueue = [rootEntry];
|
|
25
|
+
let bfsIndex = 0;
|
|
26
|
+
while (bfsIndex < bfsQueue.length) {
|
|
27
|
+
const entry = bfsQueue[bfsIndex];
|
|
28
|
+
const m = 'module' in entry ? entry.module : entry;
|
|
29
|
+
(_a = m.imports) === null || _a === void 0 ? void 0 : _a.forEach((depEntry) => {
|
|
30
|
+
if (!bfsVisits.has(depEntry)) {
|
|
31
|
+
bfsVisits.add(depEntry);
|
|
32
|
+
bfsQueue.push(depEntry);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
bfsIndex++;
|
|
36
|
+
}
|
|
37
|
+
for (let i = 0; i < bfsQueue.length; i++) {
|
|
38
|
+
const entry = bfsQueue[i];
|
|
39
|
+
const m = 'module' in entry ? entry.module : entry;
|
|
40
|
+
(_b = m.beforeBinding) === null || _b === void 0 ? void 0 : _b.call(m, container);
|
|
41
|
+
}
|
|
42
|
+
for (let i = 0; i < bfsQueue.length; i++) {
|
|
43
|
+
const entry = bfsQueue[i];
|
|
44
|
+
bindModuleEntry(container, entry);
|
|
23
45
|
}
|
|
24
|
-
|
|
25
|
-
|
|
46
|
+
for (let i = bfsQueue.length - 1; i >= 0; i--) {
|
|
47
|
+
const entry = bfsQueue[i];
|
|
48
|
+
const m = 'module' in entry ? entry.module : entry;
|
|
49
|
+
(_c = m.afterBinding) === null || _c === void 0 ? void 0 : _c.call(m, container);
|
|
26
50
|
}
|
|
51
|
+
}
|
|
52
|
+
exports.bindModule = bindModule;
|
|
53
|
+
function bindModuleEntry(container, entry) {
|
|
54
|
+
let module;
|
|
55
|
+
let options;
|
|
56
|
+
if ('module' in entry) {
|
|
57
|
+
module = entry.module;
|
|
58
|
+
options = entry.options;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
module = entry;
|
|
62
|
+
}
|
|
63
|
+
const scope = options === null || options === void 0 ? void 0 : options.scope;
|
|
27
64
|
const exportedValueTokens = new Set();
|
|
28
|
-
|
|
29
|
-
|
|
65
|
+
const moduleExports = module.exports;
|
|
66
|
+
if (moduleExports) {
|
|
67
|
+
const keys = Object.keys(moduleExports);
|
|
30
68
|
keys.forEach((valueKey) => {
|
|
31
|
-
const valueToken =
|
|
69
|
+
const valueToken = moduleExports[valueKey];
|
|
32
70
|
if (valueToken) {
|
|
33
71
|
exportedValueTokens.add(valueToken);
|
|
34
|
-
container.bindFactory(valueToken, (0, utils_1.injectable)((module) => module[valueKey], token), { scope });
|
|
72
|
+
container.bindFactory(valueToken, (0, utils_1.injectable)((module) => module[valueKey], module.token), { scope });
|
|
35
73
|
}
|
|
36
74
|
});
|
|
37
75
|
}
|
|
38
|
-
container.bindFactory(token, factory, {
|
|
76
|
+
container.bindFactory(module.token, module.factory, {
|
|
39
77
|
scope,
|
|
40
|
-
onRemoved: (
|
|
41
|
-
if (
|
|
42
|
-
|
|
78
|
+
onRemoved: (moduleInstance) => {
|
|
79
|
+
if (moduleInstance.destroy) {
|
|
80
|
+
moduleInstance.destroy();
|
|
43
81
|
}
|
|
44
82
|
exportedValueTokens.forEach((valueToken) => container.remove(valueToken));
|
|
45
83
|
exportedValueTokens.clear();
|
|
46
84
|
},
|
|
47
85
|
});
|
|
48
|
-
if (afterBinding) {
|
|
49
|
-
afterBinding(container);
|
|
50
|
-
}
|
|
51
86
|
}
|
|
52
|
-
exports.bindModule = bindModule;
|
|
53
87
|
/**
|
|
54
88
|
* Binds dependency modules to the container
|
|
55
89
|
*
|
package/dist/cjs/modules.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modules.js","sourceRoot":"","sources":["../../src/modules.ts"],"names":[],"mappings":";;;AACA,
|
|
1
|
+
{"version":3,"file":"modules.js","sourceRoot":"","sources":["../../src/modules.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/container.d.ts
CHANGED
|
@@ -13,8 +13,8 @@ export type FactoryScope = 'scoped' | 'singleton' | 'transient';
|
|
|
13
13
|
* Options for factory binding.
|
|
14
14
|
*
|
|
15
15
|
* `scope` types:
|
|
16
|
-
* - `singleton` - **This is the default**. The value is created and cached by the container which
|
|
17
|
-
* - `scoped` - The value is created and cached by the container which
|
|
16
|
+
* - `singleton` - **This is the default**. The value is created and cached by the most distant parent container which owns the factory function.
|
|
17
|
+
* - `scoped` - The value is created and cached by the nearest container which owns the factory function.
|
|
18
18
|
* - `transient` - The value is created every time it is resolved.
|
|
19
19
|
*
|
|
20
20
|
* `scoped` and `singleton` scopes can have `onRemoved` callback. It is called when a token is removed from the container.
|
|
@@ -67,8 +67,6 @@ export declare const RESOLVER: Token<Resolver>;
|
|
|
67
67
|
/** @internal */
|
|
68
68
|
declare const NOT_FOUND: unique symbol;
|
|
69
69
|
/** @internal */
|
|
70
|
-
export declare const FAKE_FACTORY: () => never;
|
|
71
|
-
/** @internal */
|
|
72
70
|
type FactoryContext<T> = {
|
|
73
71
|
factory: (container: Container) => T;
|
|
74
72
|
options?: FactoryOptions<T>;
|
package/dist/esm/container.js
CHANGED
|
@@ -18,10 +18,6 @@ export const RESOLVER = token('ditox.Resolver');
|
|
|
18
18
|
/** @internal */
|
|
19
19
|
const NOT_FOUND = Symbol();
|
|
20
20
|
/** @internal */
|
|
21
|
-
export const FAKE_FACTORY = () => {
|
|
22
|
-
throw new Error('FAKE_FACTORY');
|
|
23
|
-
};
|
|
24
|
-
/** @internal */
|
|
25
21
|
const DEFAULT_SCOPE = 'singleton';
|
|
26
22
|
/** @internal */
|
|
27
23
|
export const FACTORIES_MAP = token('ditox.FactoriesMap');
|
|
@@ -124,7 +120,7 @@ export function createContainer(parentContainer) {
|
|
|
124
120
|
return value;
|
|
125
121
|
}
|
|
126
122
|
const factoryContext = factories.get(token.symbol);
|
|
127
|
-
if (factoryContext
|
|
123
|
+
if (factoryContext) {
|
|
128
124
|
const scope = getScope(factoryContext.options);
|
|
129
125
|
switch (scope) {
|
|
130
126
|
case 'singleton': {
|
|
@@ -142,14 +138,15 @@ export function createContainer(parentContainer) {
|
|
|
142
138
|
}
|
|
143
139
|
}
|
|
144
140
|
case 'scoped': {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
//
|
|
150
|
-
|
|
141
|
+
if (hasValue) {
|
|
142
|
+
return value;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
// Create a value within the factory's container and cache it.
|
|
146
|
+
const value = factoryContext.factory(container);
|
|
147
|
+
container.bindValue(token, value);
|
|
148
|
+
return value;
|
|
151
149
|
}
|
|
152
|
-
return value;
|
|
153
150
|
}
|
|
154
151
|
case 'transient': {
|
|
155
152
|
// Create a value within the origin container and don't cache it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/container.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,EAAC,MAAM,UAAU,CAAC;AAEtC;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAsED,gBAAgB;AAChB,MAAM,CAAC,MAAM,SAAS,GAAqB,KAAK,CAAC,iBAAiB,CAAC,CAAC;AACpE,gBAAgB;AAChB,MAAM,CAAC,MAAM,gBAAgB,GAAqB,KAAK,CACrD,uBAAuB,CACxB,CAAC;AACF,gBAAgB;AAChB,MAAM,CAAC,MAAM,QAAQ,GAAoB,KAAK,CAAC,gBAAgB,CAAC,CAAC;AAEjE,gBAAgB;AAChB,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC;AAE3B,gBAAgB;AAChB,MAAM,
|
|
1
|
+
{"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/container.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/modules.d.ts
CHANGED
|
@@ -59,16 +59,17 @@ export type AnyModuleDeclaration = ModuleDeclaration<Module<AnyObject>>;
|
|
|
59
59
|
* Options for module binding.
|
|
60
60
|
*
|
|
61
61
|
* `scope` types:
|
|
62
|
-
* - `singleton` - **This is the default**. The
|
|
63
|
-
* - `scoped` - The
|
|
62
|
+
* - `singleton` - **This is the default**. The value is created and cached by the most distant parent container which owns the factory function.
|
|
63
|
+
* - `scoped` - The value is created and cached by the nearest container which owns the factory function.
|
|
64
64
|
*/
|
|
65
65
|
export type BindModuleOptions = {
|
|
66
66
|
scope?: 'scoped' | 'singleton';
|
|
67
67
|
};
|
|
68
|
-
|
|
68
|
+
type ModuleDeclarationWithOptions = {
|
|
69
69
|
module: ModuleDeclaration<AnyObject>;
|
|
70
70
|
options: BindModuleOptions;
|
|
71
71
|
};
|
|
72
|
+
export type ModuleBindingEntry = ModuleDeclaration<AnyObject> | ModuleDeclarationWithOptions;
|
|
72
73
|
/**
|
|
73
74
|
* Binds the dependency module to the container
|
|
74
75
|
* @param container - Dependency container.
|
package/dist/esm/modules.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { injectable } from './utils';
|
|
2
1
|
import { token } from './tokens';
|
|
2
|
+
import { injectable } from './utils';
|
|
3
3
|
/**
|
|
4
4
|
* Binds the dependency module to the container
|
|
5
5
|
* @param container - Dependency container.
|
|
@@ -12,39 +12,73 @@ import { token } from './tokens';
|
|
|
12
12
|
* ```
|
|
13
13
|
*/
|
|
14
14
|
export function bindModule(container, moduleDeclaration, options) {
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
var _a, _b, _c;
|
|
16
|
+
const rootEntry = {
|
|
17
|
+
module: moduleDeclaration,
|
|
18
|
+
options: options !== null && options !== void 0 ? options : {},
|
|
19
|
+
};
|
|
20
|
+
const bfsVisits = new Set([rootEntry]);
|
|
21
|
+
const bfsQueue = [rootEntry];
|
|
22
|
+
let bfsIndex = 0;
|
|
23
|
+
while (bfsIndex < bfsQueue.length) {
|
|
24
|
+
const entry = bfsQueue[bfsIndex];
|
|
25
|
+
const m = 'module' in entry ? entry.module : entry;
|
|
26
|
+
(_a = m.imports) === null || _a === void 0 ? void 0 : _a.forEach((depEntry) => {
|
|
27
|
+
if (!bfsVisits.has(depEntry)) {
|
|
28
|
+
bfsVisits.add(depEntry);
|
|
29
|
+
bfsQueue.push(depEntry);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
bfsIndex++;
|
|
33
|
+
}
|
|
34
|
+
for (let i = 0; i < bfsQueue.length; i++) {
|
|
35
|
+
const entry = bfsQueue[i];
|
|
36
|
+
const m = 'module' in entry ? entry.module : entry;
|
|
37
|
+
(_b = m.beforeBinding) === null || _b === void 0 ? void 0 : _b.call(m, container);
|
|
20
38
|
}
|
|
21
|
-
|
|
22
|
-
|
|
39
|
+
for (let i = 0; i < bfsQueue.length; i++) {
|
|
40
|
+
const entry = bfsQueue[i];
|
|
41
|
+
bindModuleEntry(container, entry);
|
|
23
42
|
}
|
|
43
|
+
for (let i = bfsQueue.length - 1; i >= 0; i--) {
|
|
44
|
+
const entry = bfsQueue[i];
|
|
45
|
+
const m = 'module' in entry ? entry.module : entry;
|
|
46
|
+
(_c = m.afterBinding) === null || _c === void 0 ? void 0 : _c.call(m, container);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function bindModuleEntry(container, entry) {
|
|
50
|
+
let module;
|
|
51
|
+
let options;
|
|
52
|
+
if ('module' in entry) {
|
|
53
|
+
module = entry.module;
|
|
54
|
+
options = entry.options;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
module = entry;
|
|
58
|
+
}
|
|
59
|
+
const scope = options === null || options === void 0 ? void 0 : options.scope;
|
|
24
60
|
const exportedValueTokens = new Set();
|
|
25
|
-
|
|
26
|
-
|
|
61
|
+
const moduleExports = module.exports;
|
|
62
|
+
if (moduleExports) {
|
|
63
|
+
const keys = Object.keys(moduleExports);
|
|
27
64
|
keys.forEach((valueKey) => {
|
|
28
|
-
const valueToken =
|
|
65
|
+
const valueToken = moduleExports[valueKey];
|
|
29
66
|
if (valueToken) {
|
|
30
67
|
exportedValueTokens.add(valueToken);
|
|
31
|
-
container.bindFactory(valueToken, injectable((module) => module[valueKey], token), { scope });
|
|
68
|
+
container.bindFactory(valueToken, injectable((module) => module[valueKey], module.token), { scope });
|
|
32
69
|
}
|
|
33
70
|
});
|
|
34
71
|
}
|
|
35
|
-
container.bindFactory(token, factory, {
|
|
72
|
+
container.bindFactory(module.token, module.factory, {
|
|
36
73
|
scope,
|
|
37
|
-
onRemoved: (
|
|
38
|
-
if (
|
|
39
|
-
|
|
74
|
+
onRemoved: (moduleInstance) => {
|
|
75
|
+
if (moduleInstance.destroy) {
|
|
76
|
+
moduleInstance.destroy();
|
|
40
77
|
}
|
|
41
78
|
exportedValueTokens.forEach((valueToken) => container.remove(valueToken));
|
|
42
79
|
exportedValueTokens.clear();
|
|
43
80
|
},
|
|
44
81
|
});
|
|
45
|
-
if (afterBinding) {
|
|
46
|
-
afterBinding(container);
|
|
47
|
-
}
|
|
48
82
|
}
|
|
49
83
|
/**
|
|
50
84
|
* Binds dependency modules to the container
|
package/dist/esm/modules.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modules.js","sourceRoot":"","sources":["../../src/modules.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"modules.js","sourceRoot":"","sources":["../../src/modules.ts"],"names":[],"mappings":"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"}
|
package/dist/umd/index.d.ts
CHANGED
|
@@ -69,8 +69,8 @@ type FactoryScope = 'scoped' | 'singleton' | 'transient';
|
|
|
69
69
|
* Options for factory binding.
|
|
70
70
|
*
|
|
71
71
|
* `scope` types:
|
|
72
|
-
* - `singleton` - **This is the default**. The value is created and cached by the container which
|
|
73
|
-
* - `scoped` - The value is created and cached by the container which
|
|
72
|
+
* - `singleton` - **This is the default**. The value is created and cached by the most distant parent container which owns the factory function.
|
|
73
|
+
* - `scoped` - The value is created and cached by the nearest container which owns the factory function.
|
|
74
74
|
* - `transient` - The value is created every time it is resolved.
|
|
75
75
|
*
|
|
76
76
|
* `scoped` and `singleton` scopes can have `onRemoved` callback. It is called when a token is removed from the container.
|
|
@@ -316,16 +316,17 @@ type ModuleDeclaration<T extends Module<AnyObject>> = {
|
|
|
316
316
|
* Options for module binding.
|
|
317
317
|
*
|
|
318
318
|
* `scope` types:
|
|
319
|
-
* - `singleton` - **This is the default**. The
|
|
320
|
-
* - `scoped` - The
|
|
319
|
+
* - `singleton` - **This is the default**. The value is created and cached by the most distant parent container which owns the factory function.
|
|
320
|
+
* - `scoped` - The value is created and cached by the nearest container which owns the factory function.
|
|
321
321
|
*/
|
|
322
322
|
type BindModuleOptions = {
|
|
323
323
|
scope?: 'scoped' | 'singleton';
|
|
324
324
|
};
|
|
325
|
-
type
|
|
325
|
+
type ModuleDeclarationWithOptions = {
|
|
326
326
|
module: ModuleDeclaration<AnyObject>;
|
|
327
327
|
options: BindModuleOptions;
|
|
328
328
|
};
|
|
329
|
+
type ModuleBindingEntry = ModuleDeclaration<AnyObject> | ModuleDeclarationWithOptions;
|
|
329
330
|
/**
|
|
330
331
|
* Binds the dependency module to the container
|
|
331
332
|
* @param container - Dependency container.
|
package/dist/umd/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!function(o,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((o="undefined"!=typeof globalThis?globalThis:o||self).Ditox={})}(this,(function(o){"use strict";function n(o){var n="string"==typeof o?{description:o}:o;return{symbol:(null==n?void 0:n.key)?Symbol.for(n.key):Symbol(null==n?void 0:n.description)}}var t=function(o,n){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(o,n){o.__proto__=n}||function(o,n){for(var t in n)Object.prototype.hasOwnProperty.call(n,t)&&(o[t]=n[t])},t(o,n)};var e=function(){return e=Object.assign||function(o){for(var n,t=1,e=arguments.length;t<e;t++)for(var r in n=arguments[t])Object.prototype.hasOwnProperty.call(n,r)&&(o[r]=n[r]);return o},e.apply(this,arguments)};function r(o,n,t){if(t||2===arguments.length)for(var e,r=0,i=n.length;r<i;r++)!e&&r in n||(e||(e=Array.prototype.slice.call(n,0,r)),e[r]=n[r]);return o.concat(e||Array.prototype.slice.call(n))}var i=function(o){function n(n){var t=this.constructor,e=o.call(this,n)||this;return Object.setPrototypeOf(e,t.prototype),e.name="ResolverError",e}return function(o,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function e(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(e.prototype=n.prototype,new e)}(n,o),n}(Error),l=n("ditox.Container"),u=n("ditox.ParentContainer"),a=n("ditox.Resolver"),s=Symbol(),c=
|
|
1
|
+
!function(o,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((o="undefined"!=typeof globalThis?globalThis:o||self).Ditox={})}(this,(function(o){"use strict";function n(o){var n="string"==typeof o?{description:o}:o;return{symbol:(null==n?void 0:n.key)?Symbol.for(n.key):Symbol(null==n?void 0:n.description)}}var t=function(o,n){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(o,n){o.__proto__=n}||function(o,n){for(var t in n)Object.prototype.hasOwnProperty.call(n,t)&&(o[t]=n[t])},t(o,n)};var e=function(){return e=Object.assign||function(o){for(var n,t=1,e=arguments.length;t<e;t++)for(var r in n=arguments[t])Object.prototype.hasOwnProperty.call(n,r)&&(o[r]=n[r]);return o},e.apply(this,arguments)};function r(o,n,t){if(t||2===arguments.length)for(var e,r=0,i=n.length;r<i;r++)!e&&r in n||(e||(e=Array.prototype.slice.call(n,0,r)),e[r]=n[r]);return o.concat(e||Array.prototype.slice.call(n))}var i=function(o){function n(n){var t=this.constructor,e=o.call(this,n)||this;return Object.setPrototypeOf(e,t.prototype),e.name="ResolverError",e}return function(o,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function e(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(e.prototype=n.prototype,new e)}(n,o),n}(Error),l=n("ditox.Container"),u=n("ditox.ParentContainer"),a=n("ditox.Resolver"),s=Symbol(),c="singleton",f=n("ditox.FactoriesMap");function d(o){return o.symbol===l.symbol||o.symbol===u.symbol||o.symbol===a.symbol}function p(o){return null!=o&&"object"==typeof o&&"symbol"in o&&"symbol"==typeof o.symbol}function v(o,n){if(p(n))return o.get(n);var t={};return Object.keys(n).forEach((function(e){return t[e]=o.get(n[e])})),t}function y(o,n){if(p(n))return o.resolve(n);var t={};return Object.keys(n).forEach((function(e){return t[e]=o.resolve(n[e])})),t}function b(o){for(var n=[],t=1;t<arguments.length;t++)n[t-1]=arguments[t];return n.map((function(n){return y(o,n)}))}function m(o){for(var n=this,t=[],e=1;e<arguments.length;e++)t[e-1]=arguments[e];return function(e){var i=b.apply(void 0,r([e],t,!1));return o.apply(n,i)}}function h(o,n,t){for(var e,r,i,l={module:n,options:null!=t?t:{}},u=new Set([l]),a=[l],s=0;s<a.length;){null===(e=(d="module"in(f=a[s])?f.module:f).imports)||void 0===e||e.forEach((function(o){u.has(o)||(u.add(o),a.push(o))})),s++}for(var c=0;c<a.length;c++){null===(r=(d="module"in(f=a[c])?f.module:f).beforeBinding)||void 0===r||r.call(d,o)}for(c=0;c<a.length;c++){g(o,f=a[c])}for(c=a.length-1;c>=0;c--){var f,d;null===(i=(d="module"in(f=a[c])?f.module:f).afterBinding)||void 0===i||i.call(d,o)}}function g(o,n){var t,e;"module"in n?(t=n.module,e=n.options):t=n;var r=null==e?void 0:e.scope,i=new Set,l=t.exports;l&&Object.keys(l).forEach((function(n){var e=l[n];e&&(i.add(e),o.bindFactory(e,m((function(o){return o[n]}),t.token),{scope:r}))}));o.bindFactory(t.token,t.factory,{scope:r,onRemoved:function(n){n.destroy&&n.destroy(),i.forEach((function(n){return o.remove(n)})),i.clear()}})}function k(o){var t;return e(e({},o),{token:null!==(t=o.token)&&void 0!==t?t:n()})}o.ResolverError=i,o.bindModule=h,o.bindModules=function(o,n){n.forEach((function(n){"module"in n?h(o,n.module,n.options):h(o,n)}))},o.bindMultiValue=function(o,n,t){var e,i=r(r([],null!==(e=o.get(n))&&void 0!==e?e:[],!0),[t],!1);o.bindValue(n,i)},o.createContainer=function(o){var n=new Map,t=new Map,e={bindValue:function(o,t){d(o)||n.set(o.symbol,t)},bindFactory:function(o,n,e){d(o)||t.set(o.symbol,{factory:n,options:e})},remove:function(o){var e;if(!d(o)){var r=null===(e=t.get(o.symbol))||void 0===e?void 0:e.options;r&&p(o.symbol,r),n.delete(o.symbol),t.delete(o.symbol)}},removeAll:function(){t.forEach((function(o,n){o.options&&p(n,o.options)})),n.clear(),t.clear(),v()},hasToken:function(e){var r;return n.has(e.symbol)||t.has(e.symbol)||null!==(r=null==o?void 0:o.hasToken(e))&&void 0!==r&&r},get:function(o){var n=r(o,e);return n!==s?n:o.isOptional?o.optionalValue:void 0},resolve:function(o){var n,t=r(o,e);if(t!==s)return t;if(o.isOptional)return o.optionalValue;throw new i('Token "'.concat(null!==(n=o.symbol.description)&&void 0!==n?n:"",'" is not provided'))}};function r(r,i){var l=n.get(r.symbol),u=void 0!==l||n.has(r.symbol);if(u&&i===e)return l;var f,d,p=t.get(r.symbol);if(p)switch(f=p.options,null!==(d=null==f?void 0:f.scope)&&void 0!==d?d:c){case"singleton":if(u)return l;if(null==o?void 0:o.hasToken(r))break;var v=p.factory(e);return e.bindValue(r,v),v;case"scoped":if(u)return l;var y=p.factory(e);return e.bindValue(r,y),y;case"transient":return p.factory(i)}if(u)return l;var b=null==o?void 0:o.get(a);return b?b(r,i):s}function p(o,t){var e=function(o){return void 0===o.scope||"scoped"===o.scope||"singleton"===o.scope?o.onRemoved:void 0}(t);if(e){var r=n.get(o);(void 0!==r||n.has(o))&&e(r)}}function v(){n.set(l.symbol,e),n.set(a.symbol,r),n.set(f.symbol,t),o&&n.set(u.symbol,o)}return v(),e},o.declareModule=k,o.declareModuleBindings=function(o){return k({factory:function(){return{}},imports:o})},o.injectable=m,o.injectableClass=function(o){for(var n=[],t=1;t<arguments.length;t++)n[t-1]=arguments[t];return m.apply(void 0,r([function(){for(var n=[],t=0;t<arguments.length;t++)n[t]=arguments[t];return new(o.bind.apply(o,r([void 0],n,!1)))}],n,!1))},o.isToken=p,o.optional=function(o,n){return{symbol:o.symbol,isOptional:!0,optionalValue:n}},o.resolveValue=y,o.resolveValues=b,o.token=n,o.tryResolveValue=v,o.tryResolveValues=function(o){for(var n=[],t=1;t<arguments.length;t++)n[t-1]=arguments[t];return n.map((function(n){return v(o,n)}))}}));
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ditox",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Dependency injection for modular web applications",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Mikhail Nasyrov <mikhail@mnasyrov.com> (https://github.com/mnasyrov)",
|
|
@@ -45,12 +45,11 @@
|
|
|
45
45
|
],
|
|
46
46
|
"scripts": {
|
|
47
47
|
"clean": "shx rm -rf dist lib",
|
|
48
|
-
"test-deno": "npm run build:rollup && deno test test-deno",
|
|
49
48
|
"build": "npm run build:cjs && npm run build:esm && npm run build:rollup",
|
|
50
49
|
"build:cjs": "tsc -p tsconfig.build.json --outDir dist/cjs --module commonjs",
|
|
51
50
|
"build:esm": "tsc -p tsconfig.build.json --outDir dist/esm --module es2015",
|
|
52
51
|
"build:rollup": "rollup -c",
|
|
53
52
|
"typedoc": "typedoc"
|
|
54
53
|
},
|
|
55
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "886d98ce7e8c78ba1392b36651f4e242f611a637"
|
|
56
55
|
}
|
package/src/container.test.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CONTAINER,
|
|
3
3
|
createContainer,
|
|
4
|
-
FACTORIES_MAP,
|
|
5
|
-
FAKE_FACTORY,
|
|
6
4
|
PARENT_CONTAINER,
|
|
7
5
|
ResolverError,
|
|
8
6
|
} from './container';
|
|
9
|
-
import {injectable} from './utils';
|
|
10
7
|
import {optional, token} from './tokens';
|
|
8
|
+
import {injectable} from './utils';
|
|
11
9
|
|
|
12
10
|
const NUMBER = token<number>('number');
|
|
13
11
|
const STRING = token<string>('string');
|
|
@@ -120,24 +118,40 @@ describe('Container', () => {
|
|
|
120
118
|
scope: 'scoped',
|
|
121
119
|
});
|
|
122
120
|
|
|
123
|
-
expect(container.get(NUMBER)).toBe(
|
|
124
|
-
expect(container.get(NUMBER)).toBe(
|
|
125
|
-
expect(parent.get(NUMBER)).toBe(
|
|
126
|
-
expect(container.get(NUMBER)).toBe(
|
|
121
|
+
expect(container.get(NUMBER)).toBe(11);
|
|
122
|
+
expect(container.get(NUMBER)).toBe(11);
|
|
123
|
+
expect(parent.get(NUMBER)).toBe(11);
|
|
124
|
+
expect(container.get(NUMBER)).toBe(11);
|
|
125
|
+
|
|
126
|
+
expect(factory).toBeCalledTimes(1);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('should inherit a factory with "scoped" scope', async () => {
|
|
130
|
+
const parentParent = createContainer();
|
|
131
|
+
let counter = 0;
|
|
132
|
+
const factory = jest.fn(() => ++counter);
|
|
133
|
+
|
|
134
|
+
parentParent.bindFactory(NUMBER, factory);
|
|
135
|
+
|
|
136
|
+
expect(parentParent.get(NUMBER)).toBe(1);
|
|
137
|
+
|
|
138
|
+
const parent = createContainer(parentParent);
|
|
139
|
+
|
|
140
|
+
parent.bindFactory(NUMBER, injectable(factory), {
|
|
141
|
+
scope: 'scoped',
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
expect(parent.get(NUMBER)).toBe(2);
|
|
145
|
+
|
|
146
|
+
const container = createContainer(parent);
|
|
147
|
+
|
|
148
|
+
expect(container.get(NUMBER)).toBe(2);
|
|
149
|
+
expect(parent.get(NUMBER)).toBe(2);
|
|
127
150
|
|
|
128
151
|
expect(factory).toBeCalledTimes(2);
|
|
129
152
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const fakeContext = internalFactories.get(NUMBER.symbol);
|
|
133
|
-
expect(fakeContext?.factory).toBe(FAKE_FACTORY);
|
|
134
|
-
expect(() => fakeContext?.factory?.(container)).toThrowError(
|
|
135
|
-
'FAKE_FACTORY',
|
|
136
|
-
);
|
|
137
|
-
const internalOnRemoved =
|
|
138
|
-
fakeContext?.options?.scope === 'scoped' &&
|
|
139
|
-
fakeContext?.options?.onRemoved;
|
|
140
|
-
expect(internalOnRemoved).toBeUndefined();
|
|
153
|
+
container.removeAll();
|
|
154
|
+
expect(parent.get(NUMBER)).toBe(2);
|
|
141
155
|
});
|
|
142
156
|
|
|
143
157
|
it('should bind a factory with "singleton" scope by default', () => {
|
|
@@ -165,6 +179,9 @@ describe('Container', () => {
|
|
|
165
179
|
const container1 = createContainer(parent);
|
|
166
180
|
const container2 = createContainer(parent);
|
|
167
181
|
const container3 = createContainer(parent);
|
|
182
|
+
const childContainer1 = createContainer(container1);
|
|
183
|
+
const childContainer2 = createContainer(container2);
|
|
184
|
+
const childContainer3 = createContainer(container3);
|
|
168
185
|
|
|
169
186
|
const START = token<number>();
|
|
170
187
|
parent.bindValue(START, 0);
|
|
@@ -178,13 +195,33 @@ describe('Container', () => {
|
|
|
178
195
|
scope: 'scoped',
|
|
179
196
|
});
|
|
180
197
|
|
|
181
|
-
|
|
198
|
+
container1.bindFactory(NUMBER, injectable(factory, START), {
|
|
199
|
+
scope: 'scoped',
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
container2.bindFactory(NUMBER, injectable(factory, START), {
|
|
203
|
+
scope: 'scoped',
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
container3.bindFactory(NUMBER, injectable(factory, START), {
|
|
207
|
+
scope: 'scoped',
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
childContainer1.bindValue(START, 1);
|
|
211
|
+
childContainer2.bindValue(START, 2);
|
|
212
|
+
childContainer3.bindValue(START, 3);
|
|
213
|
+
|
|
182
214
|
expect(container1.get(NUMBER)).toBe(11);
|
|
183
215
|
expect(container2.get(NUMBER)).toBe(22);
|
|
184
|
-
expect(
|
|
216
|
+
expect(container3.get(NUMBER)).toBe(33);
|
|
217
|
+
expect(parent.get(NUMBER)).toBe(4);
|
|
185
218
|
expect(container1.get(NUMBER)).toBe(11);
|
|
186
219
|
expect(container2.get(NUMBER)).toBe(22);
|
|
187
|
-
expect(container3.get(NUMBER)).toBe(
|
|
220
|
+
expect(container3.get(NUMBER)).toBe(33);
|
|
221
|
+
|
|
222
|
+
expect(childContainer1.get(NUMBER)).toBe(11);
|
|
223
|
+
expect(childContainer2.get(NUMBER)).toBe(22);
|
|
224
|
+
expect(childContainer3.get(NUMBER)).toBe(33);
|
|
188
225
|
|
|
189
226
|
expect(factory).toBeCalledTimes(4);
|
|
190
227
|
});
|
|
@@ -284,25 +321,13 @@ describe('Container', () => {
|
|
|
284
321
|
parent.bindFactory(NUMBER, factory, {scope: 'scoped', onRemoved});
|
|
285
322
|
|
|
286
323
|
expect(parent.get(NUMBER)).toBe(1);
|
|
287
|
-
expect(container.get(NUMBER)).toBe(
|
|
288
|
-
|
|
289
|
-
// Check for using the internal FAKE_FACTORY
|
|
290
|
-
const internalFactories = container.resolve(FACTORIES_MAP);
|
|
291
|
-
const fakeContext = internalFactories.get(NUMBER.symbol);
|
|
292
|
-
expect(fakeContext?.factory).toBe(FAKE_FACTORY);
|
|
293
|
-
expect(() => fakeContext?.factory?.(container)).toThrowError(
|
|
294
|
-
'FAKE_FACTORY',
|
|
295
|
-
);
|
|
296
|
-
const internalOnRemoved =
|
|
297
|
-
fakeContext?.options?.scope === 'scoped' &&
|
|
298
|
-
fakeContext?.options?.onRemoved;
|
|
299
|
-
expect(internalOnRemoved).toBe(onRemoved);
|
|
324
|
+
expect(container.get(NUMBER)).toBe(1);
|
|
300
325
|
|
|
301
326
|
// Continue the main test
|
|
302
327
|
parent.remove(NUMBER);
|
|
303
328
|
container.remove(NUMBER);
|
|
304
329
|
expect(onRemoved).toHaveBeenNthCalledWith(1, 1);
|
|
305
|
-
expect(onRemoved).
|
|
330
|
+
expect(onRemoved).toHaveBeenCalledTimes(1);
|
|
306
331
|
});
|
|
307
332
|
|
|
308
333
|
it('should remove "transient" factory in case its value has never been resolved', () => {
|
package/src/container.ts
CHANGED
|
@@ -20,8 +20,8 @@ export type FactoryScope = 'scoped' | 'singleton' | 'transient';
|
|
|
20
20
|
* Options for factory binding.
|
|
21
21
|
*
|
|
22
22
|
* `scope` types:
|
|
23
|
-
* - `singleton` - **This is the default**. The value is created and cached by the container which
|
|
24
|
-
* - `scoped` - The value is created and cached by the container which
|
|
23
|
+
* - `singleton` - **This is the default**. The value is created and cached by the most distant parent container which owns the factory function.
|
|
24
|
+
* - `scoped` - The value is created and cached by the nearest container which owns the factory function.
|
|
25
25
|
* - `transient` - The value is created every time it is resolved.
|
|
26
26
|
*
|
|
27
27
|
* `scoped` and `singleton` scopes can have `onRemoved` callback. It is called when a token is removed from the container.
|
|
@@ -91,11 +91,6 @@ export const RESOLVER: Token<Resolver> = token('ditox.Resolver');
|
|
|
91
91
|
/** @internal */
|
|
92
92
|
const NOT_FOUND = Symbol();
|
|
93
93
|
|
|
94
|
-
/** @internal */
|
|
95
|
-
export const FAKE_FACTORY = (): never => {
|
|
96
|
-
throw new Error('FAKE_FACTORY');
|
|
97
|
-
};
|
|
98
|
-
|
|
99
94
|
/** @internal */
|
|
100
95
|
const DEFAULT_SCOPE: FactoryScope = 'singleton';
|
|
101
96
|
|
|
@@ -247,7 +242,7 @@ export function createContainer(parentContainer?: Container): Container {
|
|
|
247
242
|
}
|
|
248
243
|
|
|
249
244
|
const factoryContext = factories.get(token.symbol);
|
|
250
|
-
if (factoryContext
|
|
245
|
+
if (factoryContext) {
|
|
251
246
|
const scope = getScope(factoryContext.options);
|
|
252
247
|
|
|
253
248
|
switch (scope) {
|
|
@@ -265,16 +260,14 @@ export function createContainer(parentContainer?: Container): Container {
|
|
|
265
260
|
}
|
|
266
261
|
|
|
267
262
|
case 'scoped': {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
263
|
+
if (hasValue) {
|
|
264
|
+
return value;
|
|
265
|
+
} else {
|
|
266
|
+
// Create a value within the factory's container and cache it.
|
|
267
|
+
const value = factoryContext.factory(container);
|
|
268
|
+
container.bindValue(token, value);
|
|
269
|
+
return value;
|
|
275
270
|
}
|
|
276
|
-
|
|
277
|
-
return value;
|
|
278
271
|
}
|
|
279
272
|
|
|
280
273
|
case 'transient': {
|
package/src/modules.test.ts
CHANGED
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
Module,
|
|
8
8
|
ModuleDeclaration,
|
|
9
9
|
} from './modules';
|
|
10
|
-
import {injectable} from './utils';
|
|
11
10
|
import {token} from './tokens';
|
|
11
|
+
import {injectable} from './utils';
|
|
12
12
|
|
|
13
13
|
describe('bindModule()', () => {
|
|
14
14
|
type TestQueries = {getValue: () => number};
|
|
@@ -107,8 +107,8 @@ describe('bindModule()', () => {
|
|
|
107
107
|
const container = createContainer(parent);
|
|
108
108
|
|
|
109
109
|
bindModule(parent, MODULE, {scope: 'scoped'});
|
|
110
|
-
expect(parent.get(MODULE_TOKEN)).
|
|
111
|
-
expect(parent.get(QUERIES_TOKEN)).
|
|
110
|
+
expect(parent.get(MODULE_TOKEN)).toBe(container.get(MODULE_TOKEN));
|
|
111
|
+
expect(parent.get(QUERIES_TOKEN)).toBe(container.get(QUERIES_TOKEN));
|
|
112
112
|
});
|
|
113
113
|
|
|
114
114
|
it('should remove "singleton" module when a container is cleaning', () => {
|
|
@@ -149,11 +149,12 @@ describe('bindModule()', () => {
|
|
|
149
149
|
parent.resolve(MODULE_TOKEN);
|
|
150
150
|
container.resolve(MODULE_TOKEN);
|
|
151
151
|
|
|
152
|
-
parent.removeAll();
|
|
153
|
-
expect(destroy).toBeCalledTimes(1);
|
|
154
|
-
|
|
155
152
|
destroy.mockClear();
|
|
156
153
|
container.removeAll();
|
|
154
|
+
expect(destroy).toBeCalledTimes(0);
|
|
155
|
+
|
|
156
|
+
destroy.mockClear();
|
|
157
|
+
parent.removeAll();
|
|
157
158
|
expect(destroy).toBeCalledTimes(1);
|
|
158
159
|
});
|
|
159
160
|
|
|
@@ -227,6 +228,68 @@ describe('bindModule()', () => {
|
|
|
227
228
|
expect(container.resolve(ARG_TOKEN)).toBe('12');
|
|
228
229
|
expect(container.resolve(RESULT_TOKEN)).toBe('123');
|
|
229
230
|
});
|
|
231
|
+
|
|
232
|
+
it('should call beforeBinding() and afterBinding() in deep-first order', () => {
|
|
233
|
+
const route: string[] = [];
|
|
234
|
+
|
|
235
|
+
const declareTestModule = (
|
|
236
|
+
id: string,
|
|
237
|
+
imports?: ModuleDeclaration<Record<string, any>>[],
|
|
238
|
+
) =>
|
|
239
|
+
declareModule({
|
|
240
|
+
imports,
|
|
241
|
+
beforeBinding: () => route.push(`${id}:before`),
|
|
242
|
+
factory: (container) => {
|
|
243
|
+
imports?.forEach((m) => container.resolve(m.token));
|
|
244
|
+
route.push(`${id}:factory`);
|
|
245
|
+
return {};
|
|
246
|
+
},
|
|
247
|
+
afterBinding: () => route.push(`${id}:after`),
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* m1
|
|
252
|
+
* / | \
|
|
253
|
+
* m2 m3 m4
|
|
254
|
+
* / \ \ |
|
|
255
|
+
* m5 m6 m7
|
|
256
|
+
*/
|
|
257
|
+
const m7 = declareTestModule('m7');
|
|
258
|
+
const m6 = declareTestModule('m6');
|
|
259
|
+
const m5 = declareTestModule('m5');
|
|
260
|
+
const m4 = declareTestModule('m4', [m7]);
|
|
261
|
+
const m3 = declareTestModule('m3', [m7]);
|
|
262
|
+
const m2 = declareTestModule('m2', [m5, m6]);
|
|
263
|
+
const m1 = declareTestModule('m1', [m2, m3, m4]);
|
|
264
|
+
|
|
265
|
+
const container = createContainer();
|
|
266
|
+
bindModule(container, m1);
|
|
267
|
+
container.resolve(m1.token);
|
|
268
|
+
|
|
269
|
+
expect(route).toEqual([
|
|
270
|
+
'm1:before',
|
|
271
|
+
'm2:before',
|
|
272
|
+
'm3:before',
|
|
273
|
+
'm4:before',
|
|
274
|
+
'm5:before',
|
|
275
|
+
'm6:before',
|
|
276
|
+
'm7:before',
|
|
277
|
+
'm7:after',
|
|
278
|
+
'm6:after',
|
|
279
|
+
'm5:after',
|
|
280
|
+
'm4:after',
|
|
281
|
+
'm3:after',
|
|
282
|
+
'm2:after',
|
|
283
|
+
'm1:after',
|
|
284
|
+
'm5:factory',
|
|
285
|
+
'm6:factory',
|
|
286
|
+
'm2:factory',
|
|
287
|
+
'm7:factory',
|
|
288
|
+
'm3:factory',
|
|
289
|
+
'm4:factory',
|
|
290
|
+
'm1:factory',
|
|
291
|
+
]);
|
|
292
|
+
});
|
|
230
293
|
});
|
|
231
294
|
|
|
232
295
|
describe('bindModules()', () => {
|
package/src/modules.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Container} from './container';
|
|
2
|
-
import {injectable} from './utils';
|
|
3
2
|
import {Token, token} from './tokens';
|
|
3
|
+
import {injectable} from './utils';
|
|
4
4
|
|
|
5
5
|
type AnyObject = Record<string, any>;
|
|
6
6
|
type EmptyObject = Record<string, never>;
|
|
@@ -73,19 +73,21 @@ export type AnyModuleDeclaration = ModuleDeclaration<Module<AnyObject>>;
|
|
|
73
73
|
* Options for module binding.
|
|
74
74
|
*
|
|
75
75
|
* `scope` types:
|
|
76
|
-
* - `singleton` - **This is the default**. The
|
|
77
|
-
* - `scoped` - The
|
|
76
|
+
* - `singleton` - **This is the default**. The value is created and cached by the most distant parent container which owns the factory function.
|
|
77
|
+
* - `scoped` - The value is created and cached by the nearest container which owns the factory function.
|
|
78
78
|
*/
|
|
79
79
|
export type BindModuleOptions = {
|
|
80
80
|
scope?: 'scoped' | 'singleton';
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
+
type ModuleDeclarationWithOptions = {
|
|
84
|
+
module: ModuleDeclaration<AnyObject>;
|
|
85
|
+
options: BindModuleOptions;
|
|
86
|
+
};
|
|
87
|
+
|
|
83
88
|
export type ModuleBindingEntry =
|
|
84
89
|
| ModuleDeclaration<AnyObject>
|
|
85
|
-
|
|
|
86
|
-
module: ModuleDeclaration<AnyObject>;
|
|
87
|
-
options: BindModuleOptions;
|
|
88
|
-
};
|
|
90
|
+
| ModuleDeclarationWithOptions;
|
|
89
91
|
|
|
90
92
|
/**
|
|
91
93
|
* Binds the dependency module to the container
|
|
@@ -103,54 +105,94 @@ export function bindModule<T extends Module<AnyObject>>(
|
|
|
103
105
|
moduleDeclaration: ModuleDeclaration<T>,
|
|
104
106
|
options?: BindModuleOptions,
|
|
105
107
|
): void {
|
|
106
|
-
const
|
|
107
|
-
moduleDeclaration
|
|
108
|
-
|
|
108
|
+
const rootEntry: ModuleBindingEntry = {
|
|
109
|
+
module: moduleDeclaration,
|
|
110
|
+
options: options ?? {},
|
|
111
|
+
};
|
|
109
112
|
|
|
110
|
-
const
|
|
113
|
+
const bfsVisits = new Set<ModuleBindingEntry>([rootEntry]);
|
|
114
|
+
const bfsQueue: ModuleBindingEntry[] = [rootEntry];
|
|
115
|
+
|
|
116
|
+
let bfsIndex = 0;
|
|
117
|
+
while (bfsIndex < bfsQueue.length) {
|
|
118
|
+
const entry = bfsQueue[bfsIndex];
|
|
119
|
+
|
|
120
|
+
const m = 'module' in entry ? entry.module : entry;
|
|
121
|
+
|
|
122
|
+
m.imports?.forEach((depEntry) => {
|
|
123
|
+
if (!bfsVisits.has(depEntry)) {
|
|
124
|
+
bfsVisits.add(depEntry);
|
|
125
|
+
bfsQueue.push(depEntry);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
bfsIndex++;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
for (let i = 0; i < bfsQueue.length; i++) {
|
|
133
|
+
const entry = bfsQueue[i];
|
|
134
|
+
const m = 'module' in entry ? entry.module : entry;
|
|
135
|
+
m.beforeBinding?.(container);
|
|
136
|
+
}
|
|
111
137
|
|
|
112
|
-
|
|
113
|
-
|
|
138
|
+
for (let i = 0; i < bfsQueue.length; i++) {
|
|
139
|
+
const entry = bfsQueue[i];
|
|
140
|
+
bindModuleEntry(container, entry);
|
|
114
141
|
}
|
|
115
142
|
|
|
116
|
-
|
|
117
|
-
|
|
143
|
+
for (let i = bfsQueue.length - 1; i >= 0; i--) {
|
|
144
|
+
const entry = bfsQueue[i];
|
|
145
|
+
const m = 'module' in entry ? entry.module : entry;
|
|
146
|
+
m.afterBinding?.(container);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function bindModuleEntry(
|
|
151
|
+
container: Container,
|
|
152
|
+
entry: ModuleBindingEntry,
|
|
153
|
+
): void {
|
|
154
|
+
let module: ModuleDeclaration<AnyObject>;
|
|
155
|
+
let options: BindModuleOptions | undefined;
|
|
156
|
+
|
|
157
|
+
if ('module' in entry) {
|
|
158
|
+
module = entry.module;
|
|
159
|
+
options = entry.options;
|
|
160
|
+
} else {
|
|
161
|
+
module = entry;
|
|
118
162
|
}
|
|
119
163
|
|
|
164
|
+
const scope = options?.scope;
|
|
120
165
|
const exportedValueTokens = new Set<Token<unknown>>();
|
|
166
|
+
const moduleExports = module.exports;
|
|
121
167
|
|
|
122
|
-
if (
|
|
123
|
-
const keys = Object.keys(
|
|
168
|
+
if (moduleExports) {
|
|
169
|
+
const keys = Object.keys(moduleExports);
|
|
124
170
|
|
|
125
171
|
keys.forEach((valueKey) => {
|
|
126
|
-
const valueToken =
|
|
172
|
+
const valueToken = moduleExports[valueKey];
|
|
127
173
|
if (valueToken) {
|
|
128
174
|
exportedValueTokens.add(valueToken);
|
|
129
175
|
|
|
130
176
|
container.bindFactory(
|
|
131
177
|
valueToken,
|
|
132
|
-
injectable((module) => module[valueKey], token),
|
|
178
|
+
injectable((module) => module[valueKey], module.token),
|
|
133
179
|
{scope},
|
|
134
180
|
);
|
|
135
181
|
}
|
|
136
182
|
});
|
|
137
183
|
}
|
|
138
184
|
|
|
139
|
-
container.bindFactory(token, factory, {
|
|
185
|
+
container.bindFactory(module.token, module.factory, {
|
|
140
186
|
scope,
|
|
141
|
-
onRemoved: (
|
|
142
|
-
if (
|
|
143
|
-
|
|
187
|
+
onRemoved: (moduleInstance) => {
|
|
188
|
+
if (moduleInstance.destroy) {
|
|
189
|
+
moduleInstance.destroy();
|
|
144
190
|
}
|
|
145
191
|
|
|
146
192
|
exportedValueTokens.forEach((valueToken) => container.remove(valueToken));
|
|
147
193
|
exportedValueTokens.clear();
|
|
148
194
|
},
|
|
149
195
|
});
|
|
150
|
-
|
|
151
|
-
if (afterBinding) {
|
|
152
|
-
afterBinding(container);
|
|
153
|
-
}
|
|
154
196
|
}
|
|
155
197
|
|
|
156
198
|
/**
|