ts-ioc-container 55.4.1 → 55.6.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 (98) hide show
  1. package/README.md +32 -9
  2. package/cjm/container/AliasMap.js +0 -1
  3. package/cjm/container/Container.js +0 -5
  4. package/cjm/hooks/HookContext.js +0 -3
  5. package/cjm/hooks/hook.js +0 -5
  6. package/cjm/hooks/onContainerDisposed.js +18 -0
  7. package/cjm/index.js +5 -13
  8. package/cjm/injector/IInjector.js +0 -1
  9. package/cjm/injector/MetadataInjector.js +4 -6
  10. package/cjm/utils/fp.js +0 -3
  11. package/cjm/utils/proxy.js +0 -1
  12. package/esm/container/AliasMap.js +0 -1
  13. package/esm/container/Container.js +7 -12
  14. package/esm/container/EmptyContainer.js +3 -3
  15. package/esm/errors/CannonSingletonApplyTwiceError.js +1 -1
  16. package/esm/errors/ContainerDisposedError.js +1 -1
  17. package/esm/errors/ContainerNotFoundError.js +1 -1
  18. package/esm/errors/DependencyMissingKeyError.js +1 -1
  19. package/esm/errors/DependencyNotFoundError.js +1 -1
  20. package/esm/errors/MethodNotImplementedError.js +1 -1
  21. package/esm/errors/ProviderDisposedError.js +1 -1
  22. package/esm/errors/UnexpectedHookResultError.js +1 -1
  23. package/esm/errors/UnsupportedTokenTypeError.js +1 -1
  24. package/esm/hooks/HookContext.js +2 -5
  25. package/esm/hooks/HooksRunner.js +4 -4
  26. package/esm/hooks/hook.js +2 -7
  27. package/esm/hooks/injectProp.js +1 -1
  28. package/esm/hooks/onConstruct.js +2 -2
  29. package/esm/hooks/onContainerDisposed.js +13 -0
  30. package/esm/index.js +43 -51
  31. package/esm/injector/IInjector.js +1 -2
  32. package/esm/injector/MetadataInjector.js +6 -8
  33. package/esm/injector/ProxyInjector.js +1 -1
  34. package/esm/injector/SimpleInjector.js +1 -1
  35. package/esm/metadata/class.js +1 -1
  36. package/esm/metadata/method.js +1 -1
  37. package/esm/metadata/parameter.js +1 -1
  38. package/esm/package.json +3 -0
  39. package/esm/provider/Provider.js +2 -2
  40. package/esm/registration/IRegistration.js +3 -3
  41. package/esm/registration/Registration.js +8 -8
  42. package/esm/select.js +4 -4
  43. package/esm/token/BindToken.js +1 -1
  44. package/esm/token/ClassToken.js +1 -1
  45. package/esm/token/ConstantToken.js +2 -2
  46. package/esm/token/FunctionToken.js +1 -1
  47. package/esm/token/GroupAliasToken.js +1 -1
  48. package/esm/token/GroupInstanceToken.js +2 -2
  49. package/esm/token/InjectionToken.js +1 -1
  50. package/esm/token/SingleAliasToken.js +1 -1
  51. package/esm/token/SingleToken.js +1 -1
  52. package/esm/token/toToken.js +8 -8
  53. package/esm/utils/fp.js +0 -3
  54. package/esm/utils/proxy.js +0 -1
  55. package/package.json +25 -11
  56. package/typings/ExecutionContext.d.ts +1 -1
  57. package/typings/container/AliasMap.d.ts +1 -1
  58. package/typings/container/Container.d.ts +7 -7
  59. package/typings/container/EmptyContainer.d.ts +6 -6
  60. package/typings/container/IContainer.d.ts +5 -5
  61. package/typings/errors/CannonSingletonApplyTwiceError.d.ts +1 -1
  62. package/typings/errors/ContainerDisposedError.d.ts +1 -1
  63. package/typings/errors/ContainerNotFoundError.d.ts +1 -1
  64. package/typings/errors/DependencyMissingKeyError.d.ts +1 -1
  65. package/typings/errors/DependencyNotFoundError.d.ts +1 -1
  66. package/typings/errors/MethodNotImplementedError.d.ts +1 -1
  67. package/typings/errors/ProviderDisposedError.d.ts +1 -1
  68. package/typings/errors/UnexpectedHookResultError.d.ts +1 -1
  69. package/typings/errors/UnsupportedTokenTypeError.d.ts +1 -1
  70. package/typings/hooks/HookContext.d.ts +2 -2
  71. package/typings/hooks/HooksRunner.d.ts +2 -2
  72. package/typings/hooks/hook.d.ts +4 -4
  73. package/typings/hooks/injectProp.d.ts +4 -4
  74. package/typings/hooks/onConstruct.d.ts +5 -5
  75. package/typings/hooks/onContainerDisposed.d.ts +10 -0
  76. package/typings/index.d.ts +45 -45
  77. package/typings/injector/IInjector.d.ts +3 -3
  78. package/typings/injector/MetadataInjector.d.ts +7 -7
  79. package/typings/injector/ProxyInjector.d.ts +3 -3
  80. package/typings/injector/SimpleInjector.d.ts +3 -3
  81. package/typings/provider/IProvider.d.ts +2 -2
  82. package/typings/provider/Provider.d.ts +3 -3
  83. package/typings/registration/IRegistration.d.ts +5 -5
  84. package/typings/registration/Registration.d.ts +6 -6
  85. package/typings/select.d.ts +5 -5
  86. package/typings/token/BindToken.d.ts +1 -1
  87. package/typings/token/ClassToken.d.ts +4 -4
  88. package/typings/token/ConstantToken.d.ts +2 -2
  89. package/typings/token/FunctionToken.d.ts +4 -4
  90. package/typings/token/GroupAliasToken.d.ts +5 -5
  91. package/typings/token/GroupInstanceToken.d.ts +3 -3
  92. package/typings/token/InjectionToken.d.ts +2 -2
  93. package/typings/token/SingleAliasToken.d.ts +5 -5
  94. package/typings/token/SingleToken.d.ts +4 -4
  95. package/typings/token/toToken.d.ts +4 -4
  96. package/cjm/hooks/onDispose.js +0 -18
  97. package/esm/hooks/onDispose.js +0 -13
  98. package/typings/hooks/onDispose.d.ts +0 -10
package/README.md CHANGED
@@ -19,7 +19,7 @@ provider pipelines, aliases, and custom injector strategies.
19
19
  - clean API for classes, keys, tokens, aliases, and scopes
20
20
  - no global container object; pass containers and scopes explicitly
21
21
  - supports tagged application, request, transaction, page, and widget scopes
22
- - decorator support with `@register`, `@inject`, `@onConstruct`, and `@onDispose`
22
+ - decorator support with `@register`, `@inject`, `@onConstruct`, and `@onContainerDisposed`
23
23
  - can [inject properties](#inject-property)
24
24
  - can inject [lazy dependencies](#lazy)
25
25
  - composable provider and registration pipelines
@@ -27,6 +27,7 @@ provider pipelines, aliases, and custom injector strategies.
27
27
  ## Content
28
28
 
29
29
  - [Setup](#setup)
30
+ - [Environment support](#environment-support)
30
31
  - [Quickstart](#quickstart)
31
32
  - [Cheatsheet](#cheatsheet)
32
33
  - [Container](#container)
@@ -52,7 +53,7 @@ provider pipelines, aliases, and custom injector strategies.
52
53
  - [Module](#module)
53
54
  - [Hook](#hook) `@hook`
54
55
  - [OnConstruct](#onconstruct) `@onConstruct`
55
- - [OnDispose](#ondispose) `@onDispose`
56
+ - [OnContainerDisposed](#oncontainerdisposed) `@onContainerDisposed`
56
57
  - [Inject Property](#inject-property)
57
58
  - [Inject Method](#inject-method)
58
59
  - [Mock](#mock)
@@ -85,6 +86,28 @@ And `tsconfig.json` should have next options:
85
86
  }
86
87
  ```
87
88
 
89
+ ## Environment support
90
+
91
+ `ts-ioc-container` ships both CommonJS and ES module builds (selected
92
+ automatically via the package `exports` map) plus TypeScript declarations, so it
93
+ runs anywhere modern JavaScript does. The package is `sideEffects`-free, so
94
+ bundlers tree-shake unused exports.
95
+
96
+ | Environment | Supported | Module format | Notes |
97
+ | --- | :---: | --- | --- |
98
+ | Node.js (ESM, `import`) | ✅ | ESM | Node.js 18+; resolved via the `import` condition. |
99
+ | Node.js (CommonJS, `require`) | ✅ | CJS | Node.js 18+; resolved via the `require` condition. |
100
+ | Browser / Web (via bundlers) | ✅ | ESM | webpack, Vite, Rollup, esbuild, Parcel; tree-shakeable. |
101
+ | TypeScript | ✅ | CJS + ESM | Types shipped for both; needs `experimentalDecorators` for the metadata injector. |
102
+ | Deno | ✅ | ESM | Use the `npm:ts-ioc-container` specifier. |
103
+ | Bun | ✅ | CJS + ESM | Runs the native ESM/CJS builds directly. |
104
+
105
+ > [!NOTE]
106
+ > The default `MetadataInjector` (and the `@inject` / `@onConstruct` /
107
+ > `@onContainerDisposed` decorators) rely on `reflect-metadata`. It is declared as an
108
+ > optional peer dependency — install it and import it once at your entrypoint.
109
+ > `SimpleInjector` and `ProxyInjector` do not need it.
110
+
88
111
  ## Quickstart
89
112
 
90
113
  ```typescript
@@ -426,7 +449,7 @@ describe('Instances', function () {
426
449
  Sometimes you want to dispose a container or scope. For example, when a request, page, widget, or other local lifecycle ends.
427
450
 
428
451
  - container can be disposed
429
- - when container is disposed then it runs its `onDispose` hooks, unregisters its providers, removes its local instances, and detaches from its parent
452
+ - when container is disposed then it runs its `onContainerDisposed` hooks, unregisters its providers, removes its local instances, and detaches from its parent
430
453
 
431
454
  > [!IMPORTANT]
432
455
  > Dispose is local to the container being disposed. Child scopes are not disposed automatically; dispose them explicitly when their own lifecycle ends.
@@ -445,7 +468,7 @@ import { bindTo, Container, ContainerDisposedError, register, Registration as R,
445
468
  * - Cache entries cleared
446
469
  *
447
470
  * The container.dispose() method:
448
- * 1. Executes all onDispose hooks
471
+ * 1. Executes all onContainerDisposed hooks
449
472
  * 2. Clears all instances and registrations
450
473
  * 3. Detaches from parent scope
451
474
  * 4. Prevents further resolution
@@ -1542,7 +1565,7 @@ Constructor parameters that should pick up positional args from `ProviderOptions
1542
1565
  - `@inject(args(0))` — resolves the first element of the `args` array passed at resolution time
1543
1566
  - Works together with `token.args(...)` to pass typed dependencies through the args context
1544
1567
 
1545
- `args(index)` and `argsFn(fn)` are thin shortcuts for an `InjectFn`. Every `InjectFn` receives `(scope, options)`, where `options.args` is the runtime args array so `args(0)` is just `(scope, { args = [] }) => args[0]`, and `argsFn(fn)` is `(scope, { args = [] }) => fn(...args)` (the runtime args are spread into your callback as positional parameters).
1568
+ `argsFn(predicate)` is the general form: it iterates the runtime `args` array and returns the **first argument matching** `predicate(value, index)` think `args.find(predicate)`. `args(index)` is just a shortcut for matching by position: `args(0)` is `argsFn((value, index) => index === 0)`. Every `InjectFn` receives `(scope, options)`, where `options.args` is the runtime args array.
1546
1569
 
1547
1570
  ### Immutable token chaining
1548
1571
 
@@ -2561,7 +2584,7 @@ describe('onConstruct', function () {
2561
2584
 
2562
2585
  ```
2563
2586
 
2564
- ### OnDispose
2587
+ ### OnContainerDisposed
2565
2588
 
2566
2589
  ```typescript
2567
2590
  import 'reflect-metadata';
@@ -2571,7 +2594,7 @@ import {
2571
2594
  Container,
2572
2595
  type HookFn,
2573
2596
  inject,
2574
- onDispose,
2597
+ onContainerDisposed,
2575
2598
  register,
2576
2599
  Registration as R,
2577
2600
  singleton,
@@ -2600,13 +2623,13 @@ class Logger {
2600
2623
  this.messages.push(message);
2601
2624
  }
2602
2625
 
2603
- @onDispose(execute)
2626
+ @onContainerDisposed(execute)
2604
2627
  save() {
2605
2628
  this.logsRepo.saveLogs(this.messages);
2606
2629
  }
2607
2630
  }
2608
2631
 
2609
- describe('onDispose', function () {
2632
+ describe('onContainerDisposed', function () {
2610
2633
  it('should invoke hooks on all instances when container is disposed', function () {
2611
2634
  const container = new Container()
2612
2635
  .useModule(new AddOnDisposeHookModule())
@@ -7,7 +7,6 @@ class AliasMap {
7
7
  return [...(this.aliasToKeySet.get(alias) ?? [])];
8
8
  }
9
9
  setAliasesByKey(key, aliases) {
10
- // reset existing key's aliases
11
10
  for (const [alias, keySet] of this.aliasToKeySet) {
12
11
  keySet.delete(key);
13
12
  if (keySet.size === 0) {
@@ -83,15 +83,12 @@ class Container {
83
83
  dispose() {
84
84
  this.validateContainer();
85
85
  this.isDisposed = true;
86
- // Execute onDispose hooks
87
86
  while (this.onDisposeHookList.length) {
88
87
  const onDispose = this.onDisposeHookList.shift();
89
88
  onDispose(this);
90
89
  }
91
- // Detach from parent
92
90
  this.parent.removeScope(this);
93
91
  this.parent = new EmptyContainer_1.EmptyContainer();
94
- // Reset the state
95
92
  for (const [_, provider] of this.providers) {
96
93
  provider.dispose();
97
94
  }
@@ -99,7 +96,6 @@ class Container {
99
96
  this.aliases.destroy();
100
97
  this.instances = [];
101
98
  this.registrations = [];
102
- // Clear hooks
103
99
  this.onConstructHookList.splice(0, this.onConstructHookList.length);
104
100
  }
105
101
  addRegistration(registration) {
@@ -123,7 +119,6 @@ class Container {
123
119
  }
124
120
  addInstance(instance) {
125
121
  this.instances.push(instance);
126
- // Execute onConstruct hooks
127
122
  for (const onConstruct of this.onConstructHookList) {
128
123
  onConstruct(instance, this);
129
124
  }
@@ -19,15 +19,12 @@ class HookContext {
19
19
  });
20
20
  }
21
21
  invokeMethod({ args = this.resolveArgs() } = {}) {
22
- // @ts-ignore
23
22
  return this.instance[this.methodName](...args);
24
23
  }
25
24
  setProperty(fn) {
26
- // @ts-ignore
27
25
  this.instance[this.methodName] = fn.resolve(this.scope);
28
26
  }
29
27
  getProperty() {
30
- // @ts-ignore
31
28
  return this.instance[this.methodName];
32
29
  }
33
30
  setInitialArgs(...args) {
package/cjm/hooks/hook.js CHANGED
@@ -13,7 +13,6 @@ exports.toHookFn = toHookFn;
13
13
  const getReflectionTarget = (target) => {
14
14
  return (0, proxy_1.isProxy)(target) ? (0, proxy_1.getProxyTarget)(target) : target;
15
15
  };
16
- // Walk the constructor's prototype chain (most-derived first) collecting each class.
17
16
  const getConstructorChain = (ctor) => {
18
17
  const chain = [];
19
18
  let current = ctor;
@@ -23,9 +22,6 @@ const getConstructorChain = (ctor) => {
23
22
  }
24
23
  return chain;
25
24
  };
26
- // Get hooks metadata, merging hooks declared on parent (extended-from) classes.
27
- // Hooks are collected from base to derived so a derived class's hooks for the same
28
- // method name take precedence over (replace) the parent's.
29
25
  function getHooks(target, key) {
30
26
  const reflectionTarget = getReflectionTarget(target);
31
27
  const merged = new Map();
@@ -43,7 +39,6 @@ function hasHooks(target, key) {
43
39
  const reflectionTarget = getReflectionTarget(target);
44
40
  return getConstructorChain(reflectionTarget.constructor).some((ctor) => Reflect.hasOwnMetadata(key, ctor));
45
41
  }
46
- // Hook decorator
47
42
  const hook = (key, ...fns) => (target, propertyKey) => {
48
43
  const hooks = Reflect.hasOwnMetadata(key, target.constructor)
49
44
  ? Reflect.getOwnMetadata(key, target.constructor)
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AddOnDisposeHookModule = exports.onContainerDisposed = exports.onContainerDisposedHooksRunner = void 0;
4
+ const hook_1 = require("./hook");
5
+ const HooksRunner_1 = require("./HooksRunner");
6
+ exports.onContainerDisposedHooksRunner = new HooksRunner_1.HooksRunner('onContainerDisposed');
7
+ const onContainerDisposed = (...fns) => (0, hook_1.hook)('onContainerDisposed', ...fns);
8
+ exports.onContainerDisposed = onContainerDisposed;
9
+ class AddOnDisposeHookModule {
10
+ applyTo(container) {
11
+ container.addOnDisposeHook((scope) => {
12
+ for (const instance of scope.getInstances()) {
13
+ exports.onContainerDisposedHooksRunner.execute(instance, { scope });
14
+ }
15
+ });
16
+ }
17
+ }
18
+ exports.AddOnDisposeHookModule = AddOnDisposeHookModule;
package/cjm/index.js CHANGED
@@ -1,15 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ClassToken = exports.toSingleAlias = exports.SingleAliasToken = exports.toGroupAlias = exports.GroupAliasToken = exports.InjectionToken = exports.HooksRunner = exports.AddOnDisposeHookModule = exports.onDispose = exports.onDisposeHooksRunner = exports.AddOnConstructHookModule = exports.onConstruct = exports.onConstructHooksRunner = exports.injectProp = exports.createHookContext = exports.createHookContextFactory = exports.HookContext = exports.hasHooks = exports.hook = exports.getHooks = exports.CannonSingletonApplyTwiceError = exports.UnexpectedHookResultError = exports.ProviderDisposedError = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyMissingKeyError = exports.ContainerNotFoundError = exports.DependencyNotFoundError = exports.Registration = exports.appendArgsFn = exports.appendArgs = exports.decorate = exports.singleton = exports.lazy = exports.scopeAccess = exports.scope = exports.bindTo = exports.register = exports.Provider = exports.ProxyInjector = exports.SimpleInjector = exports.resolveArgs = exports.argsFn = exports.args = exports.inject = exports.MetadataInjector = exports.Injector = exports.EmptyContainer = exports.Container = exports.isDependencyKey = void 0;
3
+ exports.ClassToken = exports.toSingleAlias = exports.SingleAliasToken = exports.toGroupAlias = exports.GroupAliasToken = exports.InjectionToken = exports.HooksRunner = exports.AddOnDisposeHookModule = exports.onContainerDisposed = exports.onContainerDisposedHooksRunner = exports.AddOnConstructHookModule = exports.onConstruct = exports.onConstructHooksRunner = exports.injectProp = exports.createHookContext = exports.createHookContextFactory = exports.HookContext = exports.hasHooks = exports.hook = exports.getHooks = exports.CannonSingletonApplyTwiceError = exports.UnexpectedHookResultError = exports.ProviderDisposedError = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyMissingKeyError = exports.ContainerNotFoundError = exports.DependencyNotFoundError = exports.Registration = exports.appendArgsFn = exports.appendArgs = exports.decorate = exports.singleton = exports.lazy = exports.scopeAccess = exports.scope = exports.bindTo = exports.register = exports.Provider = exports.ProxyInjector = exports.SimpleInjector = exports.resolveArgs = exports.argsFn = exports.args = exports.inject = exports.MetadataInjector = exports.Injector = exports.EmptyContainer = exports.Container = exports.isDependencyKey = void 0;
4
4
  exports.resolveConstructor = exports.Is = exports.pipe = exports.select = exports.once = exports.shallowCache = exports.debounce = exports.throttle = exports.handleAsyncError = exports.handleError = exports.getMethodTags = exports.addMethodTag = exports.getMethodLabels = exports.addMethodLabel = exports.getMethodMeta = exports.addMethodMeta = exports.getParamTags = exports.addParamTag = exports.getParamLabels = exports.addParamLabel = exports.getParamMeta = exports.addParamMeta = exports.getClassTags = exports.addClassTag = exports.getClassLabels = exports.addClassLabel = exports.getClassMeta = exports.addClassMeta = exports.GroupInstanceToken = exports.ConstantToken = exports.FunctionToken = exports.SingleToken = void 0;
5
- // Containers
6
5
  var IContainer_1 = require("./container/IContainer");
7
6
  Object.defineProperty(exports, "isDependencyKey", { enumerable: true, get: function () { return IContainer_1.isDependencyKey; } });
8
7
  var Container_1 = require("./container/Container");
9
8
  Object.defineProperty(exports, "Container", { enumerable: true, get: function () { return Container_1.Container; } });
10
9
  var EmptyContainer_1 = require("./container/EmptyContainer");
11
10
  Object.defineProperty(exports, "EmptyContainer", { enumerable: true, get: function () { return EmptyContainer_1.EmptyContainer; } });
12
- // Injectors
13
11
  var IInjector_1 = require("./injector/IInjector");
14
12
  Object.defineProperty(exports, "Injector", { enumerable: true, get: function () { return IInjector_1.Injector; } });
15
13
  var MetadataInjector_1 = require("./injector/MetadataInjector");
@@ -24,7 +22,6 @@ var ProxyInjector_1 = require("./injector/ProxyInjector");
24
22
  Object.defineProperty(exports, "ProxyInjector", { enumerable: true, get: function () { return ProxyInjector_1.ProxyInjector; } });
25
23
  var Provider_1 = require("./provider/Provider");
26
24
  Object.defineProperty(exports, "Provider", { enumerable: true, get: function () { return Provider_1.Provider; } });
27
- // Registrations
28
25
  var IRegistration_1 = require("./registration/IRegistration");
29
26
  Object.defineProperty(exports, "register", { enumerable: true, get: function () { return IRegistration_1.register; } });
30
27
  Object.defineProperty(exports, "bindTo", { enumerable: true, get: function () { return IRegistration_1.bindTo; } });
@@ -37,7 +34,6 @@ Object.defineProperty(exports, "appendArgs", { enumerable: true, get: function (
37
34
  Object.defineProperty(exports, "appendArgsFn", { enumerable: true, get: function () { return IRegistration_1.appendArgsFn; } });
38
35
  var Registration_1 = require("./registration/Registration");
39
36
  Object.defineProperty(exports, "Registration", { enumerable: true, get: function () { return Registration_1.Registration; } });
40
- // Errors
41
37
  var DependencyNotFoundError_1 = require("./errors/DependencyNotFoundError");
42
38
  Object.defineProperty(exports, "DependencyNotFoundError", { enumerable: true, get: function () { return DependencyNotFoundError_1.DependencyNotFoundError; } });
43
39
  var ContainerNotFoundError_1 = require("./errors/ContainerNotFoundError");
@@ -54,7 +50,6 @@ var UnexpectedHookResultError_1 = require("./errors/UnexpectedHookResultError");
54
50
  Object.defineProperty(exports, "UnexpectedHookResultError", { enumerable: true, get: function () { return UnexpectedHookResultError_1.UnexpectedHookResultError; } });
55
51
  var CannonSingletonApplyTwiceError_1 = require("./errors/CannonSingletonApplyTwiceError");
56
52
  Object.defineProperty(exports, "CannonSingletonApplyTwiceError", { enumerable: true, get: function () { return CannonSingletonApplyTwiceError_1.CannonSingletonApplyTwiceError; } });
57
- // Hooks
58
53
  var hook_1 = require("./hooks/hook");
59
54
  Object.defineProperty(exports, "getHooks", { enumerable: true, get: function () { return hook_1.getHooks; } });
60
55
  Object.defineProperty(exports, "hook", { enumerable: true, get: function () { return hook_1.hook; } });
@@ -69,13 +64,12 @@ var onConstruct_1 = require("./hooks/onConstruct");
69
64
  Object.defineProperty(exports, "onConstructHooksRunner", { enumerable: true, get: function () { return onConstruct_1.onConstructHooksRunner; } });
70
65
  Object.defineProperty(exports, "onConstruct", { enumerable: true, get: function () { return onConstruct_1.onConstruct; } });
71
66
  Object.defineProperty(exports, "AddOnConstructHookModule", { enumerable: true, get: function () { return onConstruct_1.AddOnConstructHookModule; } });
72
- var onDispose_1 = require("./hooks/onDispose");
73
- Object.defineProperty(exports, "onDisposeHooksRunner", { enumerable: true, get: function () { return onDispose_1.onDisposeHooksRunner; } });
74
- Object.defineProperty(exports, "onDispose", { enumerable: true, get: function () { return onDispose_1.onDispose; } });
75
- Object.defineProperty(exports, "AddOnDisposeHookModule", { enumerable: true, get: function () { return onDispose_1.AddOnDisposeHookModule; } });
67
+ var onContainerDisposed_1 = require("./hooks/onContainerDisposed");
68
+ Object.defineProperty(exports, "onContainerDisposedHooksRunner", { enumerable: true, get: function () { return onContainerDisposed_1.onContainerDisposedHooksRunner; } });
69
+ Object.defineProperty(exports, "onContainerDisposed", { enumerable: true, get: function () { return onContainerDisposed_1.onContainerDisposed; } });
70
+ Object.defineProperty(exports, "AddOnDisposeHookModule", { enumerable: true, get: function () { return onContainerDisposed_1.AddOnDisposeHookModule; } });
76
71
  var HooksRunner_1 = require("./hooks/HooksRunner");
77
72
  Object.defineProperty(exports, "HooksRunner", { enumerable: true, get: function () { return HooksRunner_1.HooksRunner; } });
78
- // Tokens
79
73
  var InjectionToken_1 = require("./token/InjectionToken");
80
74
  Object.defineProperty(exports, "InjectionToken", { enumerable: true, get: function () { return InjectionToken_1.InjectionToken; } });
81
75
  var GroupAliasToken_1 = require("./token/GroupAliasToken");
@@ -94,7 +88,6 @@ var ConstantToken_1 = require("./token/ConstantToken");
94
88
  Object.defineProperty(exports, "ConstantToken", { enumerable: true, get: function () { return ConstantToken_1.ConstantToken; } });
95
89
  var GroupInstanceToken_1 = require("./token/GroupInstanceToken");
96
90
  Object.defineProperty(exports, "GroupInstanceToken", { enumerable: true, get: function () { return GroupInstanceToken_1.GroupInstanceToken; } });
97
- // Metadata
98
91
  var class_1 = require("./metadata/class");
99
92
  Object.defineProperty(exports, "addClassMeta", { enumerable: true, get: function () { return class_1.addClassMeta; } });
100
93
  Object.defineProperty(exports, "getClassMeta", { enumerable: true, get: function () { return class_1.getClassMeta; } });
@@ -127,7 +120,6 @@ var shallowCache_1 = require("./utils/shallowCache");
127
120
  Object.defineProperty(exports, "shallowCache", { enumerable: true, get: function () { return shallowCache_1.shallowCache; } });
128
121
  var once_1 = require("./utils/once");
129
122
  Object.defineProperty(exports, "once", { enumerable: true, get: function () { return once_1.once; } });
130
- // Utils
131
123
  var select_1 = require("./select");
132
124
  Object.defineProperty(exports, "select", { enumerable: true, get: function () { return select_1.select; } });
133
125
  var fp_1 = require("./utils/fp");
@@ -4,7 +4,6 @@ exports.Injector = void 0;
4
4
  const proxy_1 = require("../utils/proxy");
5
5
  class Injector {
6
6
  resolve(scope, Target, { args, lazy } = {}) {
7
- // @ts-ignore
8
7
  return (0, proxy_1.toLazyIf)(() => {
9
8
  const instance = this.createInstance(scope, Target, { args });
10
9
  scope.addInstance(instance);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveArgs = exports.argsFn = exports.args = exports.inject = exports.MetadataInjector = void 0;
3
+ exports.resolveArgs = exports.args = exports.argsFn = exports.inject = exports.MetadataInjector = void 0;
4
4
  const IInjector_1 = require("./IInjector");
5
5
  const basic_1 = require("../utils/basic");
6
6
  const parameter_1 = require("../metadata/parameter");
@@ -17,12 +17,10 @@ const inject = (fn) => (target, propertyKey, parameterIndex) => {
17
17
  (0, parameter_1.addParamMeta)(hookMetaKey(propertyKey), () => (0, toToken_1.toToken)(fn))(basic_1.Is.instance(target) ? target.constructor : target, propertyKey, parameterIndex);
18
18
  };
19
19
  exports.inject = inject;
20
- const args = (index) => (c, { args = [] }) => {
21
- return args[index];
22
- };
23
- exports.args = args;
24
- const argsFn = (fn) => (c, options) => fn(...(options.args ?? []));
20
+ const argsFn = (predicate) => (c, { args = [] }) => args.find((value, index) => predicate(value, index));
25
21
  exports.argsFn = argsFn;
22
+ const args = (index) => (0, exports.argsFn)((value, i) => i === index);
23
+ exports.args = args;
26
24
  const resolveArgs = (Target, methodName) => {
27
25
  const tokens = (0, parameter_1.getParamMeta)(hookMetaKey(methodName), Target);
28
26
  return (scope, { args = [], lazy }) => tokens.map((fn) => fn.resolve(scope, { args: args.map(toToken_1.argToToken).map((t) => t.resolve(scope)), lazy }));
package/cjm/utils/fp.js CHANGED
@@ -1,9 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.pipe = pipe;
4
- // Implementation
5
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
4
  function pipe(...mappers) {
7
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
5
  return (value) => mappers.reduce((acc, current) => current(acc), value);
9
6
  }
@@ -25,7 +25,6 @@ function lazyProxy(resolveInstance) {
25
25
  const proxy = new Proxy({}, {
26
26
  get: (_, prop) => {
27
27
  const target = state.getTarget();
28
- // @ts-ignore
29
28
  return target[prop];
30
29
  },
31
30
  });
@@ -4,7 +4,6 @@ export class AliasMap {
4
4
  return [...(this.aliasToKeySet.get(alias) ?? [])];
5
5
  }
6
6
  setAliasesByKey(key, aliases) {
7
- // reset existing key's aliases
8
7
  for (const [alias, keySet] of this.aliasToKeySet) {
9
8
  keySet.delete(key);
10
9
  if (keySet.size === 0) {
@@ -1,10 +1,10 @@
1
- import { EmptyContainer } from './EmptyContainer';
2
- import { ContainerDisposedError } from '../errors/ContainerDisposedError';
3
- import { MetadataInjector } from '../injector/MetadataInjector';
4
- import { AliasMap } from './AliasMap';
5
- import { DependencyNotFoundError } from '../errors/DependencyNotFoundError';
6
- import { Is } from '../utils/basic';
7
- import { Filter as F } from '../utils/array';
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
8
  export class Container {
9
9
  isDisposed = false;
10
10
  parent;
@@ -80,15 +80,12 @@ export class Container {
80
80
  dispose() {
81
81
  this.validateContainer();
82
82
  this.isDisposed = true;
83
- // Execute onDispose hooks
84
83
  while (this.onDisposeHookList.length) {
85
84
  const onDispose = this.onDisposeHookList.shift();
86
85
  onDispose(this);
87
86
  }
88
- // Detach from parent
89
87
  this.parent.removeScope(this);
90
88
  this.parent = new EmptyContainer();
91
- // Reset the state
92
89
  for (const [_, provider] of this.providers) {
93
90
  provider.dispose();
94
91
  }
@@ -96,7 +93,6 @@ export class Container {
96
93
  this.aliases.destroy();
97
94
  this.instances = [];
98
95
  this.registrations = [];
99
- // Clear hooks
100
96
  this.onConstructHookList.splice(0, this.onConstructHookList.length);
101
97
  }
102
98
  addRegistration(registration) {
@@ -120,7 +116,6 @@ export class Container {
120
116
  }
121
117
  addInstance(instance) {
122
118
  this.instances.push(instance);
123
- // Execute onConstruct hooks
124
119
  for (const onConstruct of this.onConstructHookList) {
125
120
  onConstruct(instance, this);
126
121
  }
@@ -1,6 +1,6 @@
1
- import { MethodNotImplementedError } from '../errors/MethodNotImplementedError';
2
- import { DependencyNotFoundError } from '../errors/DependencyNotFoundError';
3
- import { ContainerNotFoundError } from '../errors/ContainerNotFoundError';
1
+ import { MethodNotImplementedError } from '../errors/MethodNotImplementedError.js';
2
+ import { DependencyNotFoundError } from '../errors/DependencyNotFoundError.js';
3
+ import { ContainerNotFoundError } from '../errors/ContainerNotFoundError.js';
4
4
  export class EmptyContainer {
5
5
  get isDisposed() {
6
6
  throw new MethodNotImplementedError();
@@ -1,4 +1,4 @@
1
- import { ContainerError } from './ContainerError';
1
+ import { ContainerError } from './ContainerError.js';
2
2
  export class CannonSingletonApplyTwiceError extends ContainerError {
3
3
  name = 'CannonSingletonApplyTwiceError';
4
4
  constructor(message) {
@@ -1,4 +1,4 @@
1
- import { ContainerError } from './ContainerError';
1
+ import { ContainerError } from './ContainerError.js';
2
2
  export class ContainerDisposedError extends ContainerError {
3
3
  name = 'ContainerDisposedError';
4
4
  constructor(message) {
@@ -1,4 +1,4 @@
1
- import { ContainerError } from './ContainerError';
1
+ import { ContainerError } from './ContainerError.js';
2
2
  export class ContainerNotFoundError extends ContainerError {
3
3
  name = 'ContainerNotFoundError';
4
4
  constructor(message) {
@@ -1,4 +1,4 @@
1
- import { ContainerError } from './ContainerError';
1
+ import { ContainerError } from './ContainerError.js';
2
2
  export class DependencyMissingKeyError extends ContainerError {
3
3
  name = 'DependencyMissingKeyError';
4
4
  constructor(message) {
@@ -1,4 +1,4 @@
1
- import { ContainerError } from './ContainerError';
1
+ import { ContainerError } from './ContainerError.js';
2
2
  export class DependencyNotFoundError extends ContainerError {
3
3
  name = 'DependencyNotFoundError';
4
4
  constructor(message) {
@@ -1,4 +1,4 @@
1
- import { ContainerError } from './ContainerError';
1
+ import { ContainerError } from './ContainerError.js';
2
2
  export class MethodNotImplementedError extends ContainerError {
3
3
  name = 'MethodNotImplementedError';
4
4
  constructor(message) {
@@ -1,4 +1,4 @@
1
- import { ContainerError } from './ContainerError';
1
+ import { ContainerError } from './ContainerError.js';
2
2
  export class ProviderDisposedError extends ContainerError {
3
3
  name = 'ProviderDisposedError';
4
4
  static assert(isTrue, failMessage) {
@@ -1,4 +1,4 @@
1
- import { ContainerError } from './ContainerError';
1
+ import { ContainerError } from './ContainerError.js';
2
2
  export class UnexpectedHookResultError extends ContainerError {
3
3
  name = 'UnexpectedHookResultError';
4
4
  constructor(message) {
@@ -1,4 +1,4 @@
1
- import { ContainerError } from './ContainerError';
1
+ import { ContainerError } from './ContainerError.js';
2
2
  export class UnsupportedTokenTypeError extends ContainerError {
3
3
  name = 'UnsupportedTokenTypeError';
4
4
  constructor(message) {
@@ -1,5 +1,5 @@
1
- import { getProxyTarget, isProxy } from '../utils/proxy';
2
- import { resolveArgs } from '../injector/MetadataInjector';
1
+ import { getProxyTarget, isProxy } from '../utils/proxy.js';
2
+ import { resolveArgs } from '../injector/MetadataInjector.js';
3
3
  export class HookContext {
4
4
  scope;
5
5
  methodName;
@@ -16,15 +16,12 @@ export class HookContext {
16
16
  });
17
17
  }
18
18
  invokeMethod({ args = this.resolveArgs() } = {}) {
19
- // @ts-ignore
20
19
  return this.instance[this.methodName](...args);
21
20
  }
22
21
  setProperty(fn) {
23
- // @ts-ignore
24
22
  this.instance[this.methodName] = fn.resolve(this.scope);
25
23
  }
26
24
  getProperty() {
27
- // @ts-ignore
28
25
  return this.instance[this.methodName];
29
26
  }
30
27
  setInitialArgs(...args) {
@@ -1,7 +1,7 @@
1
- import { createHookContext } from './HookContext';
2
- import { getHooks, hasHooks, toHookFn } from './hook';
3
- import { UnexpectedHookResultError } from '../errors/UnexpectedHookResultError';
4
- import { promisify } from '../utils/promise';
1
+ import { createHookContext } from './HookContext.js';
2
+ import { getHooks, hasHooks, toHookFn } from './hook.js';
3
+ import { UnexpectedHookResultError } from '../errors/UnexpectedHookResultError.js';
4
+ import { promisify } from '../utils/promise.js';
5
5
  export class HooksRunner {
6
6
  key;
7
7
  constructor(key) {
package/esm/hooks/hook.js CHANGED
@@ -1,5 +1,5 @@
1
- import { Is } from '../utils/basic';
2
- import { getProxyTarget, isProxy } from '../utils/proxy';
1
+ import { Is } from '../utils/basic.js';
2
+ import { getProxyTarget, isProxy } from '../utils/proxy.js';
3
3
  const isHookClassConstructor = (execute) => {
4
4
  return Is.constructor(execute) && execute.prototype.execute;
5
5
  };
@@ -7,7 +7,6 @@ export const toHookFn = (execute) => isHookClassConstructor(execute) ? (context)
7
7
  const getReflectionTarget = (target) => {
8
8
  return isProxy(target) ? getProxyTarget(target) : target;
9
9
  };
10
- // Walk the constructor's prototype chain (most-derived first) collecting each class.
11
10
  const getConstructorChain = (ctor) => {
12
11
  const chain = [];
13
12
  let current = ctor;
@@ -17,9 +16,6 @@ const getConstructorChain = (ctor) => {
17
16
  }
18
17
  return chain;
19
18
  };
20
- // Get hooks metadata, merging hooks declared on parent (extended-from) classes.
21
- // Hooks are collected from base to derived so a derived class's hooks for the same
22
- // method name take precedence over (replace) the parent's.
23
19
  export function getHooks(target, key) {
24
20
  const reflectionTarget = getReflectionTarget(target);
25
21
  const merged = new Map();
@@ -37,7 +33,6 @@ export function hasHooks(target, key) {
37
33
  const reflectionTarget = getReflectionTarget(target);
38
34
  return getConstructorChain(reflectionTarget.constructor).some((ctor) => Reflect.hasOwnMetadata(key, ctor));
39
35
  }
40
- // Hook decorator
41
36
  export const hook = (key, ...fns) => (target, propertyKey) => {
42
37
  const hooks = Reflect.hasOwnMetadata(key, target.constructor)
43
38
  ? Reflect.getOwnMetadata(key, target.constructor)
@@ -1,2 +1,2 @@
1
- import { toToken } from '../token/toToken';
1
+ import { toToken } from '../token/toToken.js';
2
2
  export const injectProp = (fn) => (context) => context.setProperty(toToken(fn));
@@ -1,5 +1,5 @@
1
- import { hook } from './hook';
2
- import { HooksRunner } from './HooksRunner';
1
+ import { hook } from './hook.js';
2
+ import { HooksRunner } from './HooksRunner.js';
3
3
  export const onConstructHooksRunner = new HooksRunner('onConstruct');
4
4
  export const onConstruct = (...fns) => hook('onConstruct', ...fns);
5
5
  export class AddOnConstructHookModule {
@@ -0,0 +1,13 @@
1
+ import { hook } from './hook.js';
2
+ import { HooksRunner } from './HooksRunner.js';
3
+ export const onContainerDisposedHooksRunner = new HooksRunner('onContainerDisposed');
4
+ export const onContainerDisposed = (...fns) => hook('onContainerDisposed', ...fns);
5
+ export class AddOnDisposeHookModule {
6
+ applyTo(container) {
7
+ container.addOnDisposeHook((scope) => {
8
+ for (const instance of scope.getInstances()) {
9
+ onContainerDisposedHooksRunner.execute(instance, { scope });
10
+ }
11
+ });
12
+ }
13
+ }