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,81 @@
1
+ import { isDependencyKey } from '../container/IContainer.js';
2
+ import { Provider } from '../provider/Provider.js';
3
+ import { DependencyMissingKeyError } from '../errors/DependencyMissingKeyError.js';
4
+ import { isProviderPipe } from './IRegistration.js';
5
+ import { getTransformers } from './IRegistration.js';
6
+ import { SingleToken } from '../token/SingleToken.js';
7
+ import { pipe } from '../utils/fp.js';
8
+ import { Is } from '../utils/basic.js';
9
+ export class Registration {
10
+ createProvider;
11
+ key;
12
+ scopeRules;
13
+ static fromClass(Target, { name } = {}) {
14
+ const transform = pipe(...getTransformers(Target));
15
+ return transform(new Registration(() => Provider.fromClass(Target), name ?? Target.name));
16
+ }
17
+ static fromValue(value) {
18
+ if (Is.constructor(value)) {
19
+ const transform = pipe(...getTransformers(value));
20
+ return transform(new Registration(() => Provider.fromValue(value), value.name));
21
+ }
22
+ return new Registration(() => Provider.fromValue(value));
23
+ }
24
+ static fromFn(fn) {
25
+ return new Registration(() => new Provider(fn));
26
+ }
27
+ static fromKey(key) {
28
+ return new Registration(() => Provider.fromKey(key));
29
+ }
30
+ mappers = [];
31
+ aliases = new Set();
32
+ constructor(createProvider, key, scopeRules = []) {
33
+ this.createProvider = createProvider;
34
+ this.key = key;
35
+ this.scopeRules = scopeRules;
36
+ }
37
+ bindToKey(key) {
38
+ this.key = key;
39
+ return this;
40
+ }
41
+ bindToAlias(alias) {
42
+ this.aliases.add(alias);
43
+ return this;
44
+ }
45
+ pipe(...mappers) {
46
+ const fns = mappers.map((m) => (isProviderPipe(m) ? m.mapProvider.bind(m) : m));
47
+ this.mappers.push(...fns);
48
+ return this;
49
+ }
50
+ when(...predicates) {
51
+ this.scopeRules.push(...predicates);
52
+ return this;
53
+ }
54
+ bindTo(key) {
55
+ if (isDependencyKey(key)) {
56
+ new SingleToken(key).bindTo(this);
57
+ return this;
58
+ }
59
+ key.bindTo(this);
60
+ return this;
61
+ }
62
+ matchScope(container) {
63
+ return this.scopeRules.reduce((prev, curr) => curr(container, prev), true);
64
+ }
65
+ applyTo(container) {
66
+ if (!this.matchScope(container)) {
67
+ return;
68
+ }
69
+ if (!this.key) {
70
+ throw new DependencyMissingKeyError('No key provided for registration');
71
+ }
72
+ const provider = this.mappers.reduce((p, m) => m(p), this.createProvider());
73
+ container.register(this.key, provider, { aliases: [...this.aliases] });
74
+ }
75
+ getKeyOrFail() {
76
+ if (!this.key) {
77
+ throw new DependencyMissingKeyError('No key provided for registration');
78
+ }
79
+ return this.key;
80
+ }
81
+ }
package/esm/select.js ADDED
@@ -0,0 +1,13 @@
1
+ import { toGroupAlias } from './token/GroupAliasToken.js';
2
+ import { FunctionToken } from './token/FunctionToken.js';
3
+ import { GroupInstanceToken } from './token/GroupInstanceToken.js';
4
+ import { toToken } from './token/toToken.js';
5
+ export const select = {
6
+ alias: toGroupAlias,
7
+ token: toToken,
8
+ instances: (predicate = () => true) => new GroupInstanceToken(predicate),
9
+ scope: {
10
+ current: new FunctionToken((s) => s),
11
+ create: (options) => new FunctionToken((s) => s.createScope(options)),
12
+ },
13
+ };
@@ -0,0 +1,4 @@
1
+ import { Is } from '../utils/basic.js';
2
+ export function isBindToken(token) {
3
+ return !Is.nullish(token) && typeof token === 'object' && 'bindTo' in token;
4
+ }
@@ -0,0 +1,41 @@
1
+ import { InjectionToken } from './InjectionToken.js';
2
+ export class ClassToken extends InjectionToken {
3
+ target;
4
+ _getArgsFn;
5
+ _isLazy;
6
+ constructor(target, { getArgsFn = () => [], isLazy = false } = {}) {
7
+ super();
8
+ this.target = target;
9
+ this._getArgsFn = getArgsFn;
10
+ this._isLazy = isLazy;
11
+ }
12
+ select(fn) {
13
+ return (s) => fn(this.resolve(s));
14
+ }
15
+ resolve(s, { args = [], lazy } = {}) {
16
+ return s.resolve(this.target, {
17
+ args: this._getArgsFn(s, { args }),
18
+ lazy: this._isLazy || lazy,
19
+ });
20
+ }
21
+ args(...newArgs) {
22
+ const parentFn = this._getArgsFn;
23
+ return new ClassToken(this.target, {
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 ClassToken(this.target, {
31
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...fn(s)],
32
+ isLazy: this._isLazy,
33
+ });
34
+ }
35
+ lazy() {
36
+ return new ClassToken(this.target, {
37
+ getArgsFn: this._getArgsFn,
38
+ isLazy: true,
39
+ });
40
+ }
41
+ }
@@ -0,0 +1,21 @@
1
+ import { InjectionToken } from './InjectionToken.js';
2
+ import { MethodNotImplementedError } from '../errors/MethodNotImplementedError.js';
3
+ export class ConstantToken extends InjectionToken {
4
+ token;
5
+ constructor(token) {
6
+ super();
7
+ this.token = token;
8
+ }
9
+ resolve(s) {
10
+ return this.token;
11
+ }
12
+ args(...deps) {
13
+ throw new MethodNotImplementedError('not implemented');
14
+ }
15
+ argsFn(getArgsFn) {
16
+ throw new MethodNotImplementedError('not implemented');
17
+ }
18
+ lazy() {
19
+ throw new MethodNotImplementedError('not implemented');
20
+ }
21
+ }
@@ -0,0 +1,38 @@
1
+ import { InjectionToken } from './InjectionToken.js';
2
+ export class FunctionToken extends InjectionToken {
3
+ fn;
4
+ _getArgsFn;
5
+ _isLazy;
6
+ constructor(fn, { getArgsFn = (_, { args = [] } = {}) => args, isLazy = false } = {}) {
7
+ super();
8
+ this.fn = fn;
9
+ this._getArgsFn = getArgsFn;
10
+ this._isLazy = isLazy;
11
+ }
12
+ resolve(s, { args = [], lazy } = {}) {
13
+ return this.fn(s, {
14
+ args: this._getArgsFn(s, { args }),
15
+ lazy: this._isLazy || lazy,
16
+ });
17
+ }
18
+ args(...newArgs) {
19
+ const parentFn = this._getArgsFn;
20
+ return new FunctionToken(this.fn, {
21
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...newArgs],
22
+ isLazy: this._isLazy,
23
+ });
24
+ }
25
+ argsFn(fn) {
26
+ const parentFn = this._getArgsFn;
27
+ return new FunctionToken(this.fn, {
28
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...fn(s)],
29
+ isLazy: this._isLazy,
30
+ });
31
+ }
32
+ lazy() {
33
+ return new FunctionToken(this.fn, {
34
+ getArgsFn: this._getArgsFn,
35
+ isLazy: true,
36
+ });
37
+ }
38
+ }
@@ -0,0 +1,45 @@
1
+ import { InjectionToken } from './InjectionToken.js';
2
+ export class GroupAliasToken extends InjectionToken {
3
+ token;
4
+ _getArgsFn;
5
+ _isLazy;
6
+ constructor(token, { getArgsFn = () => [], isLazy = false } = {}) {
7
+ super();
8
+ this.token = token;
9
+ this._getArgsFn = getArgsFn;
10
+ this._isLazy = isLazy;
11
+ }
12
+ select(fn) {
13
+ return (s) => fn(this.resolve(s));
14
+ }
15
+ resolve(s, { args = [], lazy } = {}) {
16
+ return s.resolveByAlias(this.token, {
17
+ args: this._getArgsFn(s, { args }),
18
+ lazy: this._isLazy || lazy,
19
+ });
20
+ }
21
+ bindTo(r) {
22
+ r.bindToAlias(this.token);
23
+ }
24
+ args(...newArgs) {
25
+ const parentFn = this._getArgsFn;
26
+ return new GroupAliasToken(this.token, {
27
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...newArgs],
28
+ isLazy: this._isLazy,
29
+ });
30
+ }
31
+ argsFn(fn) {
32
+ const parentFn = this._getArgsFn;
33
+ return new GroupAliasToken(this.token, {
34
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...fn(s)],
35
+ isLazy: this._isLazy,
36
+ });
37
+ }
38
+ lazy() {
39
+ return new GroupAliasToken(this.token, {
40
+ getArgsFn: this._getArgsFn,
41
+ isLazy: true,
42
+ });
43
+ }
44
+ }
45
+ export const toGroupAlias = (token) => new GroupAliasToken(token);
@@ -0,0 +1,29 @@
1
+ import { InjectionToken } from './InjectionToken.js';
2
+ import { MethodNotImplementedError } from '../errors/MethodNotImplementedError.js';
3
+ export class GroupInstanceToken extends InjectionToken {
4
+ predicate;
5
+ isCascade = true;
6
+ constructor(predicate) {
7
+ super();
8
+ this.predicate = predicate;
9
+ }
10
+ select(fn) {
11
+ return (s) => this.resolve(s).map(fn);
12
+ }
13
+ args(...deps) {
14
+ throw new MethodNotImplementedError('not implemented');
15
+ }
16
+ argsFn(getArgsFn) {
17
+ throw new MethodNotImplementedError('not implemented');
18
+ }
19
+ lazy() {
20
+ throw new MethodNotImplementedError('not implemented');
21
+ }
22
+ cascade(isTrue) {
23
+ this.isCascade = isTrue;
24
+ return this;
25
+ }
26
+ resolve(c) {
27
+ return c.getInstances(this.isCascade).filter(this.predicate);
28
+ }
29
+ }
@@ -0,0 +1,6 @@
1
+ import { Is } from '../utils/basic.js';
2
+ export class InjectionToken {
3
+ }
4
+ export function isInjectionToken(target) {
5
+ return Is.object(target) && 'resolve' in target && 'args' in target && 'argsFn' in target && 'lazy' in target;
6
+ }
@@ -0,0 +1,45 @@
1
+ import { InjectionToken } from './InjectionToken.js';
2
+ export class SingleAliasToken extends InjectionToken {
3
+ token;
4
+ _getArgsFn;
5
+ _isLazy;
6
+ constructor(token, { getArgsFn = () => [], isLazy = false } = {}) {
7
+ super();
8
+ this.token = token;
9
+ this._getArgsFn = getArgsFn;
10
+ this._isLazy = isLazy;
11
+ }
12
+ select(fn) {
13
+ return (s) => fn(this.resolve(s));
14
+ }
15
+ resolve(s, { args = [], lazy } = {}) {
16
+ return s.resolveOneByAlias(this.token, {
17
+ args: this._getArgsFn(s, { args }),
18
+ lazy: this._isLazy || lazy,
19
+ });
20
+ }
21
+ bindTo(r) {
22
+ r.bindToAlias(this.token);
23
+ }
24
+ args(...newArgs) {
25
+ const parentFn = this._getArgsFn;
26
+ return new SingleAliasToken(this.token, {
27
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...newArgs],
28
+ isLazy: this._isLazy,
29
+ });
30
+ }
31
+ argsFn(fn) {
32
+ const parentFn = this._getArgsFn;
33
+ return new SingleAliasToken(this.token, {
34
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...fn(s)],
35
+ isLazy: this._isLazy,
36
+ });
37
+ }
38
+ lazy() {
39
+ return new SingleAliasToken(this.token, {
40
+ getArgsFn: this._getArgsFn,
41
+ isLazy: true,
42
+ });
43
+ }
44
+ }
45
+ export const toSingleAlias = (token) => new SingleAliasToken(token);
@@ -0,0 +1,44 @@
1
+ import { InjectionToken } from './InjectionToken.js';
2
+ export class SingleToken extends InjectionToken {
3
+ token;
4
+ _getArgsFn;
5
+ _isLazy;
6
+ constructor(token, { getArgsFn = () => [], isLazy = false } = {}) {
7
+ super();
8
+ this.token = token;
9
+ this._getArgsFn = getArgsFn;
10
+ this._isLazy = isLazy;
11
+ }
12
+ select(fn) {
13
+ return (s) => fn(this.resolve(s));
14
+ }
15
+ resolve(s, { args = [], lazy } = {}) {
16
+ return s.resolve(this.token, {
17
+ args: this._getArgsFn(s, { args }),
18
+ lazy: this._isLazy || lazy,
19
+ });
20
+ }
21
+ bindTo(r) {
22
+ r.bindToKey(this.token);
23
+ }
24
+ args(...newArgs) {
25
+ const parentFn = this._getArgsFn;
26
+ return new SingleToken(this.token, {
27
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...newArgs],
28
+ isLazy: this._isLazy,
29
+ });
30
+ }
31
+ argsFn(fn) {
32
+ const parentFn = this._getArgsFn;
33
+ return new SingleToken(this.token, {
34
+ getArgsFn: (s, opts) => [...parentFn(s, opts), ...fn(s)],
35
+ isLazy: this._isLazy,
36
+ });
37
+ }
38
+ lazy() {
39
+ return new SingleToken(this.token, {
40
+ getArgsFn: this._getArgsFn,
41
+ isLazy: true,
42
+ });
43
+ }
44
+ }
@@ -0,0 +1,24 @@
1
+ import { isDependencyKey } from '../container/IContainer.js';
2
+ import { SingleToken } from './SingleToken.js';
3
+ import { ClassToken } from './ClassToken.js';
4
+ import { FunctionToken } from './FunctionToken.js';
5
+ import { UnsupportedTokenTypeError } from '../errors/UnsupportedTokenTypeError.js';
6
+ import { InjectionToken, isInjectionToken } from './InjectionToken.js';
7
+ import { Is } from '../utils/basic.js';
8
+ import { ConstantToken } from './ConstantToken.js';
9
+ export const toToken = (token) => {
10
+ if (token instanceof InjectionToken) {
11
+ return token;
12
+ }
13
+ if (isDependencyKey(token)) {
14
+ return new SingleToken(token);
15
+ }
16
+ if (Is.constructor(token)) {
17
+ return new ClassToken(token);
18
+ }
19
+ if (typeof token === 'function') {
20
+ return new FunctionToken(token);
21
+ }
22
+ throw new UnsupportedTokenTypeError(`Unknown token ${token}`);
23
+ };
24
+ export const argToToken = (v) => (isInjectionToken(v) ? v : new ConstantToken(v));
@@ -0,0 +1,6 @@
1
+ export const Filter = {
2
+ exclude: (arr) => {
3
+ const excludeSet = arr instanceof Array ? new Set(arr) : arr;
4
+ return (v) => !excludeSet.has(v);
5
+ },
6
+ };
@@ -0,0 +1,9 @@
1
+ export const Is = {
2
+ nullish: (value) => value === undefined || value === null,
3
+ object: (target) => target !== null && typeof target === 'object',
4
+ instance: (target) => Object.prototype.hasOwnProperty.call(target, 'constructor'),
5
+ constructor: (target) => typeof target === 'function' && !!target.prototype,
6
+ };
7
+ export function resolveConstructor(target) {
8
+ return Is.constructor(target) ? target : target.constructor;
9
+ }
@@ -0,0 +1,12 @@
1
+ export const debounce = (ms) => (target, propertyKey, descriptor) => {
2
+ const originalMethod = descriptor.value;
3
+ const timerMap = new WeakMap();
4
+ descriptor.value = function (...args) {
5
+ const prev = timerMap.get(this);
6
+ if (prev !== undefined) {
7
+ clearTimeout(prev);
8
+ }
9
+ timerMap.set(this, setTimeout(() => originalMethod.apply(this, args), ms));
10
+ };
11
+ return descriptor;
12
+ };
@@ -0,0 +1,24 @@
1
+ export const handleAsyncError = (errorHandler) => (target, propertyKey, descriptor) => {
2
+ const originalMethod = descriptor.value;
3
+ descriptor.value = async function (...args) {
4
+ try {
5
+ return await originalMethod.apply(this, args);
6
+ }
7
+ catch (e) {
8
+ errorHandler(e, { target: target.constructor.name, method: propertyKey });
9
+ }
10
+ };
11
+ return descriptor;
12
+ };
13
+ export const handleError = (errorHandler) => (target, propertyKey, descriptor) => {
14
+ const originalMethod = descriptor.value;
15
+ descriptor.value = function (...args) {
16
+ try {
17
+ return originalMethod.apply(this, args);
18
+ }
19
+ catch (e) {
20
+ errorHandler(e, { target: target.constructor.name, method: propertyKey });
21
+ }
22
+ };
23
+ return descriptor;
24
+ };
@@ -0,0 +1,3 @@
1
+ export function pipe(...mappers) {
2
+ return (value) => mappers.reduce((acc, current) => current(acc), value);
3
+ }
@@ -0,0 +1,16 @@
1
+ export const once = ({ onRepeat } = {}) => (target, propertyKey, descriptor) => {
2
+ const originalMethod = descriptor.value;
3
+ const cacheMap = new WeakMap();
4
+ let index = 0;
5
+ descriptor.value = function (...args) {
6
+ index++;
7
+ if (cacheMap.has(this)) {
8
+ onRepeat?.({ index: index - 1, args });
9
+ return cacheMap.get(this);
10
+ }
11
+ const result = originalMethod.apply(this, args);
12
+ cacheMap.set(this, result);
13
+ return result;
14
+ };
15
+ return descriptor;
16
+ };
@@ -0,0 +1 @@
1
+ export const promisify = (arg) => (arg instanceof Promise ? arg : Promise.resolve(arg));
@@ -0,0 +1,33 @@
1
+ const proxyStateMap = new WeakMap();
2
+ const unwrapProxyTarget = (value) => {
3
+ return isProxy(value) ? getProxyTarget(value) : value;
4
+ };
5
+ export function isProxy(value) {
6
+ return proxyStateMap.has(value);
7
+ }
8
+ export function getProxyTarget(value) {
9
+ return proxyStateMap.get(value).getTarget();
10
+ }
11
+ export function lazyProxy(resolveInstance) {
12
+ let instance;
13
+ const state = {
14
+ getTarget: () => {
15
+ instance = instance ?? unwrapProxyTarget(resolveInstance());
16
+ return instance;
17
+ },
18
+ };
19
+ const proxy = new Proxy({}, {
20
+ get: (_, prop) => {
21
+ const target = state.getTarget();
22
+ return target[prop];
23
+ },
24
+ });
25
+ proxyStateMap.set(proxy, state);
26
+ return proxy;
27
+ }
28
+ export function toLazyIf(resolveInstance, isLazy = false) {
29
+ if (isLazy) {
30
+ return lazyProxy(resolveInstance);
31
+ }
32
+ return resolveInstance();
33
+ }
@@ -0,0 +1,19 @@
1
+ export const shallowCache = (getKeyByArgs) => (target, propertyKey, descriptor) => {
2
+ const originalMethod = descriptor.value;
3
+ const cacheMap = new WeakMap();
4
+ descriptor.value = function (...args) {
5
+ let cache = cacheMap.get(this);
6
+ if (cache === undefined) {
7
+ cache = new Map();
8
+ cacheMap.set(this, cache);
9
+ }
10
+ const key = getKeyByArgs(...args);
11
+ if (cache.has(key)) {
12
+ return cache.get(key);
13
+ }
14
+ const result = originalMethod.apply(this, args);
15
+ cache.set(key, result);
16
+ return result;
17
+ };
18
+ return descriptor;
19
+ };
@@ -0,0 +1,14 @@
1
+ export const throttle = (ms) => (target, propertyKey, descriptor) => {
2
+ const originalMethod = descriptor.value;
3
+ const lastCalledMap = new WeakMap();
4
+ descriptor.value = function (...args) {
5
+ const now = Date.now();
6
+ const lastCalled = lastCalledMap.get(this) ?? -Infinity;
7
+ if (now - lastCalled < ms) {
8
+ return undefined;
9
+ }
10
+ lastCalledMap.set(this, now);
11
+ return originalMethod.apply(this, args);
12
+ };
13
+ return descriptor;
14
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-ioc-container",
3
- "version": "56.1.0",
3
+ "version": "56.2.0",
4
4
  "description": "Fast, lightweight TypeScript dependency injection container with a clean API, scoped lifecycles, decorators, tokens, hooks, lazy injection, customizable providers, and no global container objects.",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -0,0 +1,4 @@
1
+ import type { IContainer } from './container/IContainer.js';
2
+ export interface ExecutionContext {
3
+ scope: IContainer;
4
+ }
@@ -0,0 +1,8 @@
1
+ import { type DependencyKey } from './IContainer.js';
2
+ export type Alias = DependencyKey;
3
+ export declare class AliasMap {
4
+ private readonly aliasToKeySet;
5
+ getKeysByAlias(alias: DependencyKey): DependencyKey[];
6
+ setAliasesByKey(key: DependencyKey, aliases: DependencyKey[]): void;
7
+ destroy(): void;
8
+ }
@@ -0,0 +1,48 @@
1
+ import { type CreateScopeOptions, type DependencyKey, type IContainer, type IContainerModule, type RegisterOptions, ResolveManyOptions, type ResolveOneOptions, type Tag } from './IContainer.js';
2
+ import { type IInjector } from '../injector/IInjector.js';
3
+ import { type IProvider } from '../provider/IProvider.js';
4
+ import { type IRegistration } from '../registration/IRegistration.js';
5
+ import { OnConstructHook } from '../hooks/onConstruct.js';
6
+ import { OnDisposeHook } from '../hooks/onContainerDisposed.js';
7
+ import { constructor, Instance } from '../utils/basic.js';
8
+ export declare class Container implements IContainer {
9
+ isDisposed: boolean;
10
+ private parent;
11
+ private scopes;
12
+ private instances;
13
+ private registrations;
14
+ private readonly tags;
15
+ private readonly providers;
16
+ private readonly aliases;
17
+ private readonly injector;
18
+ private readonly onConstructHookList;
19
+ private readonly onDisposeHookList;
20
+ constructor(options?: {
21
+ injector?: IInjector;
22
+ parent?: IContainer;
23
+ tags?: Tag[];
24
+ });
25
+ register(key: DependencyKey, provider: IProvider, { aliases }?: RegisterOptions): this;
26
+ resolve<T>(target: constructor<T> | DependencyKey, { args, child, lazy }?: ResolveOneOptions): T;
27
+ resolveByAlias<T>(alias: DependencyKey, { args, child, lazy, excludedKeys }?: ResolveManyOptions): T[];
28
+ resolveOneByAlias<T>(alias: DependencyKey, { args, child, lazy }?: ResolveOneOptions): T;
29
+ createScope({ tags }?: CreateScopeOptions): IContainer;
30
+ dispose(): void;
31
+ addRegistration(registration: IRegistration): this;
32
+ getRegistrations(): IRegistration[];
33
+ hasRegistration(key: DependencyKey): boolean;
34
+ addOnConstructHook(...hooks: OnConstructHook[]): this;
35
+ addOnDisposeHook(...hooks: OnDisposeHook[]): this;
36
+ addInstance(instance: Instance): void;
37
+ getScopes(): IContainer[];
38
+ hasInstance(instance: object): boolean;
39
+ getScopeByInstanceOrFail(instance: object): IContainer;
40
+ removeScope(child: IContainer): void;
41
+ useModule(module: IContainerModule): this;
42
+ getParent(): IContainer;
43
+ getInstances(cascade?: boolean): Instance<unknown>[];
44
+ hasTag(tag: Tag): boolean;
45
+ addTags(...tags: Tag[]): void;
46
+ private validateContainer;
47
+ private findProviderByKeyOrFail;
48
+ }
@@ -0,0 +1,30 @@
1
+ import { type DependencyKey, type IContainer, type IContainerModule, type ResolveManyOptions, type ResolveOneOptions, type Tag } from './IContainer.js';
2
+ import { type IProvider } from '../provider/IProvider.js';
3
+ import { type IRegistration } from '../registration/IRegistration.js';
4
+ import { OnDisposeHook } from '../hooks/onContainerDisposed.js';
5
+ import { OnConstructHook } from '../hooks/onConstruct.js';
6
+ import { type constructor, type Instance } from '../utils/basic.js';
7
+ export declare class EmptyContainer implements IContainer {
8
+ get isDisposed(): boolean;
9
+ addInstance(instance: Instance): void;
10
+ getParent(): undefined;
11
+ getScopes(): never[];
12
+ getScopeByInstanceOrFail(instance: object): IContainer;
13
+ getInstances(): never[];
14
+ hasInstance(instance: object): boolean;
15
+ createScope(): IContainer;
16
+ dispose(): void;
17
+ register(key: DependencyKey, value: IProvider): this;
18
+ hasTag(tag: Tag): boolean;
19
+ addTags(...tags: Tag[]): void;
20
+ getRegistrations(): never[];
21
+ hasRegistration(key: DependencyKey): boolean;
22
+ removeScope(): void;
23
+ useModule(module: IContainerModule): this;
24
+ addRegistration(registration: IRegistration): this;
25
+ resolve<T>(key: constructor<T> | DependencyKey, options?: ResolveOneOptions): T;
26
+ resolveByAlias<T>(alias: DependencyKey, options?: ResolveManyOptions): T[];
27
+ resolveOneByAlias<T>(alias: DependencyKey, options?: ResolveOneOptions): T;
28
+ addOnDisposeHook(...hooks: OnDisposeHook[]): this;
29
+ addOnConstructHook(...hooks: OnConstructHook[]): this;
30
+ }