ts-ioc-container 56.1.0 → 56.2.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.
Files changed (167) hide show
  1. package/cjm/ExecutionContext.js +2 -0
  2. package/cjm/container/AliasMap.js +25 -0
  3. package/cjm/container/Container.js +175 -0
  4. package/cjm/container/EmptyContainer.js +71 -0
  5. package/cjm/container/IContainer.js +6 -0
  6. package/cjm/errors/CannonSingletonApplyTwiceError.js +17 -0
  7. package/cjm/errors/ContainerDisposedError.js +12 -0
  8. package/cjm/errors/ContainerError.js +11 -0
  9. package/cjm/errors/ContainerNotFoundError.js +12 -0
  10. package/cjm/errors/DependencyMissingKeyError.js +12 -0
  11. package/cjm/errors/DependencyNotFoundError.js +12 -0
  12. package/cjm/errors/MethodNotImplementedError.js +12 -0
  13. package/cjm/errors/ProviderDisposedError.js +17 -0
  14. package/cjm/errors/UnexpectedHookResultError.js +12 -0
  15. package/cjm/errors/UnsupportedTokenTypeError.js +12 -0
  16. package/cjm/hooks/HookContext.js +42 -0
  17. package/cjm/hooks/HooksRunner.js +42 -0
  18. package/cjm/hooks/hook.js +55 -0
  19. package/cjm/hooks/injectProp.js +6 -0
  20. package/cjm/hooks/onConstruct.js +28 -0
  21. package/cjm/hooks/onConstructAsync.js +28 -0
  22. package/cjm/hooks/onContainerDisposed.js +18 -0
  23. package/cjm/index.js +141 -0
  24. package/cjm/injector/IInjector.js +14 -0
  25. package/cjm/injector/MetadataInjector.js +33 -0
  26. package/cjm/injector/ProxyInjector.js +18 -0
  27. package/cjm/injector/SimpleInjector.js +10 -0
  28. package/cjm/metadata/class.js +21 -0
  29. package/cjm/metadata/method.js +19 -0
  30. package/cjm/metadata/parameter.js +34 -0
  31. package/cjm/provider/IProvider.js +2 -0
  32. package/cjm/provider/Provider.js +80 -0
  33. package/cjm/registration/IRegistration.js +50 -0
  34. package/cjm/registration/Registration.js +85 -0
  35. package/cjm/select.js +16 -0
  36. package/cjm/token/BindToken.js +7 -0
  37. package/cjm/token/ClassToken.js +45 -0
  38. package/cjm/token/ConstantToken.js +25 -0
  39. package/cjm/token/FunctionToken.js +42 -0
  40. package/cjm/token/GroupAliasToken.js +50 -0
  41. package/cjm/token/GroupInstanceToken.js +33 -0
  42. package/cjm/token/InjectionToken.js +11 -0
  43. package/cjm/token/SingleAliasToken.js +50 -0
  44. package/cjm/token/SingleToken.js +48 -0
  45. package/cjm/token/toToken.js +29 -0
  46. package/cjm/utils/array.js +9 -0
  47. package/cjm/utils/basic.js +13 -0
  48. package/cjm/utils/debounce.js +16 -0
  49. package/cjm/utils/errorHandler.js +29 -0
  50. package/cjm/utils/fp.js +6 -0
  51. package/cjm/utils/once.js +20 -0
  52. package/cjm/utils/promise.js +5 -0
  53. package/cjm/utils/proxy.js +39 -0
  54. package/cjm/utils/shallowCache.js +23 -0
  55. package/cjm/utils/throttle.js +18 -0
  56. package/esm/ExecutionContext.js +1 -0
  57. package/esm/container/AliasMap.js +21 -0
  58. package/esm/container/Container.js +171 -0
  59. package/esm/container/EmptyContainer.js +67 -0
  60. package/esm/container/IContainer.js +3 -0
  61. package/esm/errors/CannonSingletonApplyTwiceError.js +13 -0
  62. package/esm/errors/ContainerDisposedError.js +8 -0
  63. package/esm/errors/ContainerError.js +7 -0
  64. package/esm/errors/ContainerNotFoundError.js +8 -0
  65. package/esm/errors/DependencyMissingKeyError.js +8 -0
  66. package/esm/errors/DependencyNotFoundError.js +8 -0
  67. package/esm/errors/MethodNotImplementedError.js +8 -0
  68. package/esm/errors/ProviderDisposedError.js +13 -0
  69. package/esm/errors/UnexpectedHookResultError.js +8 -0
  70. package/esm/errors/UnsupportedTokenTypeError.js +8 -0
  71. package/esm/hooks/HookContext.js +36 -0
  72. package/esm/hooks/HooksRunner.js +38 -0
  73. package/esm/hooks/hook.js +46 -0
  74. package/esm/hooks/injectProp.js +2 -0
  75. package/esm/hooks/onConstruct.js +23 -0
  76. package/esm/hooks/onConstructAsync.js +23 -0
  77. package/esm/hooks/onContainerDisposed.js +13 -0
  78. package/esm/index.js +46 -0
  79. package/esm/injector/IInjector.js +10 -0
  80. package/esm/injector/MetadataInjector.js +25 -0
  81. package/esm/injector/ProxyInjector.js +14 -0
  82. package/esm/injector/SimpleInjector.js +6 -0
  83. package/esm/metadata/class.js +12 -0
  84. package/esm/metadata/method.js +10 -0
  85. package/esm/metadata/parameter.js +25 -0
  86. package/esm/package.json +3 -0
  87. package/esm/provider/IProvider.js +1 -0
  88. package/esm/provider/Provider.js +76 -0
  89. package/esm/registration/IRegistration.js +35 -0
  90. package/esm/registration/Registration.js +81 -0
  91. package/esm/select.js +13 -0
  92. package/esm/token/BindToken.js +4 -0
  93. package/esm/token/ClassToken.js +41 -0
  94. package/esm/token/ConstantToken.js +21 -0
  95. package/esm/token/FunctionToken.js +38 -0
  96. package/esm/token/GroupAliasToken.js +45 -0
  97. package/esm/token/GroupInstanceToken.js +29 -0
  98. package/esm/token/InjectionToken.js +6 -0
  99. package/esm/token/SingleAliasToken.js +45 -0
  100. package/esm/token/SingleToken.js +44 -0
  101. package/esm/token/toToken.js +24 -0
  102. package/esm/utils/array.js +6 -0
  103. package/esm/utils/basic.js +9 -0
  104. package/esm/utils/debounce.js +12 -0
  105. package/esm/utils/errorHandler.js +24 -0
  106. package/esm/utils/fp.js +3 -0
  107. package/esm/utils/once.js +16 -0
  108. package/esm/utils/promise.js +1 -0
  109. package/esm/utils/proxy.js +33 -0
  110. package/esm/utils/shallowCache.js +19 -0
  111. package/esm/utils/throttle.js +14 -0
  112. package/package.json +1 -1
  113. package/typings/ExecutionContext.d.ts +4 -0
  114. package/typings/container/AliasMap.d.ts +8 -0
  115. package/typings/container/Container.d.ts +48 -0
  116. package/typings/container/EmptyContainer.d.ts +30 -0
  117. package/typings/container/IContainer.d.ts +56 -0
  118. package/typings/errors/CannonSingletonApplyTwiceError.d.ts +6 -0
  119. package/typings/errors/ContainerDisposedError.d.ts +5 -0
  120. package/typings/errors/ContainerError.d.ts +4 -0
  121. package/typings/errors/ContainerNotFoundError.d.ts +5 -0
  122. package/typings/errors/DependencyMissingKeyError.d.ts +5 -0
  123. package/typings/errors/DependencyNotFoundError.d.ts +5 -0
  124. package/typings/errors/MethodNotImplementedError.d.ts +5 -0
  125. package/typings/errors/ProviderDisposedError.d.ts +6 -0
  126. package/typings/errors/UnexpectedHookResultError.d.ts +5 -0
  127. package/typings/errors/UnsupportedTokenTypeError.d.ts +5 -0
  128. package/typings/hooks/HookContext.d.ts +35 -0
  129. package/typings/hooks/HooksRunner.d.ts +16 -0
  130. package/typings/hooks/hook.d.ts +20 -0
  131. package/typings/hooks/injectProp.d.ts +5 -0
  132. package/typings/hooks/onConstruct.d.ts +14 -0
  133. package/typings/hooks/onConstructAsync.d.ts +11 -0
  134. package/typings/hooks/onContainerDisposed.d.ts +9 -0
  135. package/typings/index.d.ts +48 -0
  136. package/typings/injector/IInjector.d.ts +17 -0
  137. package/typings/injector/MetadataInjector.d.ts +13 -0
  138. package/typings/injector/ProxyInjector.d.ts +6 -0
  139. package/typings/injector/SimpleInjector.d.ts +6 -0
  140. package/typings/metadata/class.d.ts +6 -0
  141. package/typings/metadata/method.d.ts +6 -0
  142. package/typings/metadata/parameter.d.ts +6 -0
  143. package/typings/provider/IProvider.d.ts +26 -0
  144. package/typings/provider/Provider.d.ts +26 -0
  145. package/typings/registration/IRegistration.d.ts +31 -0
  146. package/typings/registration/Registration.d.ts +28 -0
  147. package/typings/select.d.ts +12 -0
  148. package/typings/token/BindToken.d.ts +5 -0
  149. package/typings/token/ClassToken.d.ts +18 -0
  150. package/typings/token/ConstantToken.d.ts +10 -0
  151. package/typings/token/FunctionToken.d.ts +17 -0
  152. package/typings/token/GroupAliasToken.d.ts +21 -0
  153. package/typings/token/GroupInstanceToken.d.ts +15 -0
  154. package/typings/token/InjectionToken.d.ts +9 -0
  155. package/typings/token/SingleAliasToken.d.ts +21 -0
  156. package/typings/token/SingleToken.d.ts +19 -0
  157. package/typings/token/toToken.d.ts +6 -0
  158. package/typings/utils/array.d.ts +3 -0
  159. package/typings/utils/basic.d.ts +11 -0
  160. package/typings/utils/debounce.d.ts +1 -0
  161. package/typings/utils/errorHandler.d.ts +6 -0
  162. package/typings/utils/fp.d.ts +13 -0
  163. package/typings/utils/once.d.ts +8 -0
  164. package/typings/utils/promise.d.ts +1 -0
  165. package/typings/utils/proxy.d.ts +4 -0
  166. package/typings/utils/shallowCache.d.ts +1 -0
  167. package/typings/utils/throttle.d.ts +1 -0
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FunctionToken = void 0;
4
+ const InjectionToken_1 = require("./InjectionToken");
5
+ class FunctionToken extends InjectionToken_1.InjectionToken {
6
+ fn;
7
+ _getArgsFn;
8
+ _isLazy;
9
+ constructor(fn, { getArgsFn = (_, { args = [] } = {}) => args, isLazy = false } = {}) {
10
+ super();
11
+ this.fn = fn;
12
+ this._getArgsFn = getArgsFn;
13
+ this._isLazy = isLazy;
14
+ }
15
+ resolve(s, { args = [], lazy } = {}) {
16
+ return this.fn(s, {
17
+ args: this._getArgsFn(s, { args }),
18
+ lazy: this._isLazy || lazy,
19
+ });
20
+ }
21
+ args(...newArgs) {
22
+ const parentFn = this._getArgsFn;
23
+ return new FunctionToken(this.fn, {
24
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...newArgs],
25
+ isLazy: this._isLazy,
26
+ });
27
+ }
28
+ argsFn(fn) {
29
+ const parentFn = this._getArgsFn;
30
+ return new FunctionToken(this.fn, {
31
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...fn(s)],
32
+ isLazy: this._isLazy,
33
+ });
34
+ }
35
+ lazy() {
36
+ return new FunctionToken(this.fn, {
37
+ getArgsFn: this._getArgsFn,
38
+ isLazy: true,
39
+ });
40
+ }
41
+ }
42
+ exports.FunctionToken = FunctionToken;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toGroupAlias = exports.GroupAliasToken = void 0;
4
+ const InjectionToken_1 = require("./InjectionToken");
5
+ class GroupAliasToken extends InjectionToken_1.InjectionToken {
6
+ token;
7
+ _getArgsFn;
8
+ _isLazy;
9
+ constructor(token, { getArgsFn = () => [], isLazy = false } = {}) {
10
+ super();
11
+ this.token = token;
12
+ this._getArgsFn = getArgsFn;
13
+ this._isLazy = isLazy;
14
+ }
15
+ select(fn) {
16
+ return (s) => fn(this.resolve(s));
17
+ }
18
+ resolve(s, { args = [], lazy } = {}) {
19
+ return s.resolveByAlias(this.token, {
20
+ args: this._getArgsFn(s, { args }),
21
+ lazy: this._isLazy || lazy,
22
+ });
23
+ }
24
+ bindTo(r) {
25
+ r.bindToAlias(this.token);
26
+ }
27
+ args(...newArgs) {
28
+ const parentFn = this._getArgsFn;
29
+ return new GroupAliasToken(this.token, {
30
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...newArgs],
31
+ isLazy: this._isLazy,
32
+ });
33
+ }
34
+ argsFn(fn) {
35
+ const parentFn = this._getArgsFn;
36
+ return new GroupAliasToken(this.token, {
37
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...fn(s)],
38
+ isLazy: this._isLazy,
39
+ });
40
+ }
41
+ lazy() {
42
+ return new GroupAliasToken(this.token, {
43
+ getArgsFn: this._getArgsFn,
44
+ isLazy: true,
45
+ });
46
+ }
47
+ }
48
+ exports.GroupAliasToken = GroupAliasToken;
49
+ const toGroupAlias = (token) => new GroupAliasToken(token);
50
+ exports.toGroupAlias = toGroupAlias;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GroupInstanceToken = void 0;
4
+ const InjectionToken_1 = require("./InjectionToken");
5
+ const MethodNotImplementedError_1 = require("../errors/MethodNotImplementedError");
6
+ class GroupInstanceToken extends InjectionToken_1.InjectionToken {
7
+ predicate;
8
+ isCascade = true;
9
+ constructor(predicate) {
10
+ super();
11
+ this.predicate = predicate;
12
+ }
13
+ select(fn) {
14
+ return (s) => this.resolve(s).map(fn);
15
+ }
16
+ args(...deps) {
17
+ throw new MethodNotImplementedError_1.MethodNotImplementedError('not implemented');
18
+ }
19
+ argsFn(getArgsFn) {
20
+ throw new MethodNotImplementedError_1.MethodNotImplementedError('not implemented');
21
+ }
22
+ lazy() {
23
+ throw new MethodNotImplementedError_1.MethodNotImplementedError('not implemented');
24
+ }
25
+ cascade(isTrue) {
26
+ this.isCascade = isTrue;
27
+ return this;
28
+ }
29
+ resolve(c) {
30
+ return c.getInstances(this.isCascade).filter(this.predicate);
31
+ }
32
+ }
33
+ exports.GroupInstanceToken = GroupInstanceToken;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InjectionToken = void 0;
4
+ exports.isInjectionToken = isInjectionToken;
5
+ const basic_1 = require("../utils/basic");
6
+ class InjectionToken {
7
+ }
8
+ exports.InjectionToken = InjectionToken;
9
+ function isInjectionToken(target) {
10
+ return basic_1.Is.object(target) && 'resolve' in target && 'args' in target && 'argsFn' in target && 'lazy' in target;
11
+ }
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toSingleAlias = exports.SingleAliasToken = void 0;
4
+ const InjectionToken_1 = require("./InjectionToken");
5
+ class SingleAliasToken extends InjectionToken_1.InjectionToken {
6
+ token;
7
+ _getArgsFn;
8
+ _isLazy;
9
+ constructor(token, { getArgsFn = () => [], isLazy = false } = {}) {
10
+ super();
11
+ this.token = token;
12
+ this._getArgsFn = getArgsFn;
13
+ this._isLazy = isLazy;
14
+ }
15
+ select(fn) {
16
+ return (s) => fn(this.resolve(s));
17
+ }
18
+ resolve(s, { args = [], lazy } = {}) {
19
+ return s.resolveOneByAlias(this.token, {
20
+ args: this._getArgsFn(s, { args }),
21
+ lazy: this._isLazy || lazy,
22
+ });
23
+ }
24
+ bindTo(r) {
25
+ r.bindToAlias(this.token);
26
+ }
27
+ args(...newArgs) {
28
+ const parentFn = this._getArgsFn;
29
+ return new SingleAliasToken(this.token, {
30
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...newArgs],
31
+ isLazy: this._isLazy,
32
+ });
33
+ }
34
+ argsFn(fn) {
35
+ const parentFn = this._getArgsFn;
36
+ return new SingleAliasToken(this.token, {
37
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...fn(s)],
38
+ isLazy: this._isLazy,
39
+ });
40
+ }
41
+ lazy() {
42
+ return new SingleAliasToken(this.token, {
43
+ getArgsFn: this._getArgsFn,
44
+ isLazy: true,
45
+ });
46
+ }
47
+ }
48
+ exports.SingleAliasToken = SingleAliasToken;
49
+ const toSingleAlias = (token) => new SingleAliasToken(token);
50
+ exports.toSingleAlias = toSingleAlias;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SingleToken = void 0;
4
+ const InjectionToken_1 = require("./InjectionToken");
5
+ class SingleToken extends InjectionToken_1.InjectionToken {
6
+ token;
7
+ _getArgsFn;
8
+ _isLazy;
9
+ constructor(token, { getArgsFn = () => [], isLazy = false } = {}) {
10
+ super();
11
+ this.token = token;
12
+ this._getArgsFn = getArgsFn;
13
+ this._isLazy = isLazy;
14
+ }
15
+ select(fn) {
16
+ return (s) => fn(this.resolve(s));
17
+ }
18
+ resolve(s, { args = [], lazy } = {}) {
19
+ return s.resolve(this.token, {
20
+ args: this._getArgsFn(s, { args }),
21
+ lazy: this._isLazy || lazy,
22
+ });
23
+ }
24
+ bindTo(r) {
25
+ r.bindToKey(this.token);
26
+ }
27
+ args(...newArgs) {
28
+ const parentFn = this._getArgsFn;
29
+ return new SingleToken(this.token, {
30
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...newArgs],
31
+ isLazy: this._isLazy,
32
+ });
33
+ }
34
+ argsFn(fn) {
35
+ const parentFn = this._getArgsFn;
36
+ return new SingleToken(this.token, {
37
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...fn(s)],
38
+ isLazy: this._isLazy,
39
+ });
40
+ }
41
+ lazy() {
42
+ return new SingleToken(this.token, {
43
+ getArgsFn: this._getArgsFn,
44
+ isLazy: true,
45
+ });
46
+ }
47
+ }
48
+ exports.SingleToken = SingleToken;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.argToToken = exports.toToken = void 0;
4
+ const IContainer_1 = require("../container/IContainer");
5
+ const SingleToken_1 = require("./SingleToken");
6
+ const ClassToken_1 = require("./ClassToken");
7
+ const FunctionToken_1 = require("./FunctionToken");
8
+ const UnsupportedTokenTypeError_1 = require("../errors/UnsupportedTokenTypeError");
9
+ const InjectionToken_1 = require("./InjectionToken");
10
+ const basic_1 = require("../utils/basic");
11
+ const ConstantToken_1 = require("./ConstantToken");
12
+ const toToken = (token) => {
13
+ if (token instanceof InjectionToken_1.InjectionToken) {
14
+ return token;
15
+ }
16
+ if ((0, IContainer_1.isDependencyKey)(token)) {
17
+ return new SingleToken_1.SingleToken(token);
18
+ }
19
+ if (basic_1.Is.constructor(token)) {
20
+ return new ClassToken_1.ClassToken(token);
21
+ }
22
+ if (typeof token === 'function') {
23
+ return new FunctionToken_1.FunctionToken(token);
24
+ }
25
+ throw new UnsupportedTokenTypeError_1.UnsupportedTokenTypeError(`Unknown token ${token}`);
26
+ };
27
+ exports.toToken = toToken;
28
+ const argToToken = (v) => ((0, InjectionToken_1.isInjectionToken)(v) ? v : new ConstantToken_1.ConstantToken(v));
29
+ exports.argToToken = argToToken;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Filter = void 0;
4
+ exports.Filter = {
5
+ exclude: (arr) => {
6
+ const excludeSet = arr instanceof Array ? new Set(arr) : arr;
7
+ return (v) => !excludeSet.has(v);
8
+ },
9
+ };
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Is = void 0;
4
+ exports.resolveConstructor = resolveConstructor;
5
+ exports.Is = {
6
+ nullish: (value) => value === undefined || value === null,
7
+ object: (target) => target !== null && typeof target === 'object',
8
+ instance: (target) => Object.prototype.hasOwnProperty.call(target, 'constructor'),
9
+ constructor: (target) => typeof target === 'function' && !!target.prototype,
10
+ };
11
+ function resolveConstructor(target) {
12
+ return exports.Is.constructor(target) ? target : target.constructor;
13
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.debounce = void 0;
4
+ const debounce = (ms) => (target, propertyKey, descriptor) => {
5
+ const originalMethod = descriptor.value;
6
+ const timerMap = new WeakMap();
7
+ descriptor.value = function (...args) {
8
+ const prev = timerMap.get(this);
9
+ if (prev !== undefined) {
10
+ clearTimeout(prev);
11
+ }
12
+ timerMap.set(this, setTimeout(() => originalMethod.apply(this, args), ms));
13
+ };
14
+ return descriptor;
15
+ };
16
+ exports.debounce = debounce;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleError = exports.handleAsyncError = void 0;
4
+ const handleAsyncError = (errorHandler) => (target, propertyKey, descriptor) => {
5
+ const originalMethod = descriptor.value;
6
+ descriptor.value = async function (...args) {
7
+ try {
8
+ return await originalMethod.apply(this, args);
9
+ }
10
+ catch (e) {
11
+ errorHandler(e, { target: target.constructor.name, method: propertyKey });
12
+ }
13
+ };
14
+ return descriptor;
15
+ };
16
+ exports.handleAsyncError = handleAsyncError;
17
+ const handleError = (errorHandler) => (target, propertyKey, descriptor) => {
18
+ const originalMethod = descriptor.value;
19
+ descriptor.value = function (...args) {
20
+ try {
21
+ return originalMethod.apply(this, args);
22
+ }
23
+ catch (e) {
24
+ errorHandler(e, { target: target.constructor.name, method: propertyKey });
25
+ }
26
+ };
27
+ return descriptor;
28
+ };
29
+ exports.handleError = handleError;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pipe = pipe;
4
+ function pipe(...mappers) {
5
+ return (value) => mappers.reduce((acc, current) => current(acc), value);
6
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.once = void 0;
4
+ const once = ({ onRepeat } = {}) => (target, propertyKey, descriptor) => {
5
+ const originalMethod = descriptor.value;
6
+ const cacheMap = new WeakMap();
7
+ let index = 0;
8
+ descriptor.value = function (...args) {
9
+ index++;
10
+ if (cacheMap.has(this)) {
11
+ onRepeat?.({ index: index - 1, args });
12
+ return cacheMap.get(this);
13
+ }
14
+ const result = originalMethod.apply(this, args);
15
+ cacheMap.set(this, result);
16
+ return result;
17
+ };
18
+ return descriptor;
19
+ };
20
+ exports.once = once;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.promisify = void 0;
4
+ const promisify = (arg) => (arg instanceof Promise ? arg : Promise.resolve(arg));
5
+ exports.promisify = promisify;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isProxy = isProxy;
4
+ exports.getProxyTarget = getProxyTarget;
5
+ exports.lazyProxy = lazyProxy;
6
+ exports.toLazyIf = toLazyIf;
7
+ const proxyStateMap = new WeakMap();
8
+ const unwrapProxyTarget = (value) => {
9
+ return isProxy(value) ? getProxyTarget(value) : value;
10
+ };
11
+ function isProxy(value) {
12
+ return proxyStateMap.has(value);
13
+ }
14
+ function getProxyTarget(value) {
15
+ return proxyStateMap.get(value).getTarget();
16
+ }
17
+ function lazyProxy(resolveInstance) {
18
+ let instance;
19
+ const state = {
20
+ getTarget: () => {
21
+ instance = instance ?? unwrapProxyTarget(resolveInstance());
22
+ return instance;
23
+ },
24
+ };
25
+ const proxy = new Proxy({}, {
26
+ get: (_, prop) => {
27
+ const target = state.getTarget();
28
+ return target[prop];
29
+ },
30
+ });
31
+ proxyStateMap.set(proxy, state);
32
+ return proxy;
33
+ }
34
+ function toLazyIf(resolveInstance, isLazy = false) {
35
+ if (isLazy) {
36
+ return lazyProxy(resolveInstance);
37
+ }
38
+ return resolveInstance();
39
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.shallowCache = void 0;
4
+ const shallowCache = (getKeyByArgs) => (target, propertyKey, descriptor) => {
5
+ const originalMethod = descriptor.value;
6
+ const cacheMap = new WeakMap();
7
+ descriptor.value = function (...args) {
8
+ let cache = cacheMap.get(this);
9
+ if (cache === undefined) {
10
+ cache = new Map();
11
+ cacheMap.set(this, cache);
12
+ }
13
+ const key = getKeyByArgs(...args);
14
+ if (cache.has(key)) {
15
+ return cache.get(key);
16
+ }
17
+ const result = originalMethod.apply(this, args);
18
+ cache.set(key, result);
19
+ return result;
20
+ };
21
+ return descriptor;
22
+ };
23
+ exports.shallowCache = shallowCache;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.throttle = void 0;
4
+ const throttle = (ms) => (target, propertyKey, descriptor) => {
5
+ const originalMethod = descriptor.value;
6
+ const lastCalledMap = new WeakMap();
7
+ descriptor.value = function (...args) {
8
+ const now = Date.now();
9
+ const lastCalled = lastCalledMap.get(this) ?? -Infinity;
10
+ if (now - lastCalled < ms) {
11
+ return undefined;
12
+ }
13
+ lastCalledMap.set(this, now);
14
+ return originalMethod.apply(this, args);
15
+ };
16
+ return descriptor;
17
+ };
18
+ exports.throttle = throttle;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ export class AliasMap {
2
+ aliasToKeySet = new Map();
3
+ getKeysByAlias(alias) {
4
+ return [...(this.aliasToKeySet.get(alias) ?? [])];
5
+ }
6
+ setAliasesByKey(key, aliases) {
7
+ for (const [alias, keySet] of this.aliasToKeySet) {
8
+ keySet.delete(key);
9
+ if (keySet.size === 0) {
10
+ this.aliasToKeySet.delete(alias);
11
+ }
12
+ }
13
+ for (const alias of aliases) {
14
+ const dependencyKeySet = this.aliasToKeySet.get(alias) ?? new Set();
15
+ this.aliasToKeySet.set(alias, dependencyKeySet.add(key));
16
+ }
17
+ }
18
+ destroy() {
19
+ this.aliasToKeySet.clear();
20
+ }
21
+ }
@@ -0,0 +1,171 @@
1
+ import { EmptyContainer } from './EmptyContainer.js';
2
+ import { ContainerDisposedError } from '../errors/ContainerDisposedError.js';
3
+ import { MetadataInjector } from '../injector/MetadataInjector.js';
4
+ import { AliasMap } from './AliasMap.js';
5
+ import { DependencyNotFoundError } from '../errors/DependencyNotFoundError.js';
6
+ import { Is } from '../utils/basic.js';
7
+ import { Filter as F } from '../utils/array.js';
8
+ export class Container {
9
+ isDisposed = false;
10
+ parent;
11
+ scopes = [];
12
+ instances = [];
13
+ registrations = [];
14
+ tags;
15
+ providers = new Map();
16
+ aliases = new AliasMap();
17
+ injector;
18
+ onConstructHookList = [];
19
+ onDisposeHookList = [];
20
+ constructor(options = {}) {
21
+ this.injector = options.injector ?? new MetadataInjector();
22
+ this.parent = options.parent ?? new EmptyContainer();
23
+ this.tags = new Set(options.tags ?? []);
24
+ }
25
+ register(key, provider, { aliases = [] } = {}) {
26
+ this.validateContainer();
27
+ this.providers.set(key, provider);
28
+ this.aliases.setAliasesByKey(key, aliases);
29
+ return this;
30
+ }
31
+ resolve(target, { args = [], child = this, lazy } = {}) {
32
+ this.validateContainer();
33
+ if (Is.constructor(target)) {
34
+ return this.injector.resolve(this, target, { args, lazy });
35
+ }
36
+ const provider = this.providers.get(target);
37
+ return provider?.hasAccess({ invocationScope: child, providerScope: this, args })
38
+ ? provider.resolve(this, { args, lazy })
39
+ : this.parent.resolve(target, { args, child, lazy });
40
+ }
41
+ resolveByAlias(alias, { args = [], child = this, lazy, excludedKeys = [] } = {}) {
42
+ this.validateContainer();
43
+ const keys = [];
44
+ const deps = [];
45
+ for (const key of this.aliases.getKeysByAlias(alias).filter(F.exclude(excludedKeys))) {
46
+ const provider = this.findProviderByKeyOrFail(key);
47
+ if (!provider.hasAccess({ invocationScope: child, providerScope: this, args })) {
48
+ continue;
49
+ }
50
+ keys.push(key);
51
+ deps.push(provider.resolve(this, { args, lazy }));
52
+ }
53
+ const parentDeps = this.parent.resolveByAlias(alias, {
54
+ args,
55
+ child,
56
+ lazy,
57
+ excludedKeys: [...excludedKeys, ...keys],
58
+ });
59
+ return [...deps, ...parentDeps];
60
+ }
61
+ resolveOneByAlias(alias, { args = [], child = this, lazy } = {}) {
62
+ this.validateContainer();
63
+ const [key] = this.aliases.getKeysByAlias(alias);
64
+ const provider = key ? this.findProviderByKeyOrFail(key) : undefined;
65
+ return provider?.hasAccess({ invocationScope: child, providerScope: this, args })
66
+ ? provider.resolve(this, { args, lazy })
67
+ : this.parent.resolveOneByAlias(alias, { args, child, lazy });
68
+ }
69
+ createScope({ tags } = {}) {
70
+ this.validateContainer();
71
+ const scope = new Container({ injector: this.injector, parent: this, tags })
72
+ .addOnConstructHook(...this.onConstructHookList)
73
+ .addOnDisposeHook(...this.onDisposeHookList);
74
+ for (const registration of this.getRegistrations()) {
75
+ registration.applyTo(scope);
76
+ }
77
+ this.scopes.push(scope);
78
+ return scope;
79
+ }
80
+ dispose() {
81
+ this.validateContainer();
82
+ this.isDisposed = true;
83
+ while (this.onDisposeHookList.length) {
84
+ const onDispose = this.onDisposeHookList.shift();
85
+ onDispose(this);
86
+ }
87
+ this.parent.removeScope(this);
88
+ this.parent = new EmptyContainer();
89
+ for (const provider of this.providers.values()) {
90
+ provider.dispose();
91
+ }
92
+ this.providers.clear();
93
+ this.aliases.destroy();
94
+ this.instances = [];
95
+ this.registrations = [];
96
+ this.onConstructHookList.length = 0;
97
+ }
98
+ addRegistration(registration) {
99
+ this.registrations.push(registration);
100
+ registration.applyTo(this);
101
+ return this;
102
+ }
103
+ getRegistrations() {
104
+ return [...this.parent.getRegistrations(), ...this.registrations];
105
+ }
106
+ hasRegistration(key) {
107
+ return this.registrations.some((r) => r.getKeyOrFail() === key) || this.parent.hasRegistration(key);
108
+ }
109
+ addOnConstructHook(...hooks) {
110
+ this.onConstructHookList.push(...hooks);
111
+ return this;
112
+ }
113
+ addOnDisposeHook(...hooks) {
114
+ this.onDisposeHookList.push(...hooks);
115
+ return this;
116
+ }
117
+ addInstance(instance) {
118
+ this.instances.push(instance);
119
+ for (const onConstruct of this.onConstructHookList) {
120
+ onConstruct(instance, this);
121
+ }
122
+ }
123
+ getScopes() {
124
+ return [...this.scopes];
125
+ }
126
+ hasInstance(instance) {
127
+ return this.instances.includes(instance);
128
+ }
129
+ getScopeByInstanceOrFail(instance) {
130
+ this.validateContainer();
131
+ if (this.hasInstance(instance)) {
132
+ return this;
133
+ }
134
+ return this.parent.getScopeByInstanceOrFail(instance);
135
+ }
136
+ removeScope(child) {
137
+ this.scopes = this.scopes.filter((s) => s !== child);
138
+ }
139
+ useModule(module) {
140
+ module.applyTo(this);
141
+ return this;
142
+ }
143
+ getParent() {
144
+ return this.parent;
145
+ }
146
+ getInstances(cascade = false) {
147
+ if (!cascade) {
148
+ return [...this.instances];
149
+ }
150
+ return [...this.instances, ...this.scopes.flatMap((s) => s.getInstances(true))];
151
+ }
152
+ hasTag(tag) {
153
+ return this.tags.has(tag);
154
+ }
155
+ addTags(...tags) {
156
+ for (const tag of tags) {
157
+ this.tags.add(tag);
158
+ }
159
+ }
160
+ validateContainer() {
161
+ if (this.isDisposed) {
162
+ throw new ContainerDisposedError('Container is already disposed');
163
+ }
164
+ }
165
+ findProviderByKeyOrFail(key) {
166
+ if (!this.providers.has(key)) {
167
+ throw new DependencyNotFoundError(`Provider ${key.toString()} does not exist`);
168
+ }
169
+ return this.providers.get(key);
170
+ }
171
+ }