ts-ioc-container 65.0.0 → 67.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +51 -28
  2. package/cjm/hooks/HookExecutionStrategy.js +4 -24
  3. package/cjm/hooks/ParallelAsync.js +4 -10
  4. package/cjm/hooks/SequentialAsync.js +5 -9
  5. package/cjm/hooks/SequentialSync.js +2 -4
  6. package/cjm/hooks/combinators.js +27 -0
  7. package/cjm/hooks/hook.js +5 -11
  8. package/cjm/hooks/onConstruct.js +1 -1
  9. package/cjm/hooks/onResolved.js +1 -1
  10. package/cjm/hooks/onScopeDisposed.js +1 -1
  11. package/cjm/index.js +10 -10
  12. package/cjm/utils/task.js +23 -0
  13. package/esm/hooks/HookExecutionStrategy.js +3 -21
  14. package/esm/hooks/ParallelAsync.js +4 -10
  15. package/esm/hooks/SequentialAsync.js +5 -9
  16. package/esm/hooks/SequentialSync.js +2 -4
  17. package/esm/hooks/combinators.js +21 -0
  18. package/esm/hooks/hook.js +4 -8
  19. package/esm/hooks/onConstruct.js +2 -2
  20. package/esm/hooks/onResolved.js +2 -2
  21. package/esm/hooks/onScopeDisposed.js +2 -2
  22. package/esm/index.js +3 -3
  23. package/esm/utils/task.js +18 -0
  24. package/package.json +1 -1
  25. package/typings/hooks/HookExecutionStrategy.d.ts +3 -5
  26. package/typings/hooks/ParallelAsync.d.ts +3 -4
  27. package/typings/hooks/SequentialAsync.d.ts +3 -4
  28. package/typings/hooks/SequentialSync.d.ts +2 -2
  29. package/typings/hooks/{resolveHooks.d.ts → combinators.d.ts} +2 -0
  30. package/typings/hooks/hook.d.ts +2 -7
  31. package/typings/hooks/onConstruct.d.ts +1 -1
  32. package/typings/hooks/onResolved.d.ts +1 -1
  33. package/typings/hooks/onScopeDisposed.d.ts +1 -1
  34. package/typings/index.d.ts +4 -4
  35. package/typings/utils/task.d.ts +3 -0
  36. package/cjm/hooks/AsyncHookExecutionStrategy.js +0 -15
  37. package/cjm/hooks/resolveHooks.js +0 -15
  38. package/esm/hooks/AsyncHookExecutionStrategy.js +0 -11
  39. package/esm/hooks/resolveHooks.js +0 -11
  40. package/typings/hooks/AsyncHookExecutionStrategy.d.ts +0 -10
package/README.md CHANGED
@@ -162,7 +162,7 @@ describe('Quickstart', function () {
162
162
  - Lazy token: `select.token('Service').lazy()`
163
163
  - Inject decorator: `@inject('Key')`
164
164
  - Map an injected value: `@inject('Key', sanitize(), validate())`
165
- - Property inject: `@hook('onInit', append(injectProp('Key')))`
165
+ - Property inject: `@hook('onInit', injectProp('Key'))`
166
166
 
167
167
  > [!TIP]
168
168
  > For classes, prefer the `@register(bindTo('Key'))` decorator over the fluent
@@ -2385,6 +2385,8 @@ Sometimes you don't want to change the dependency, only to react to it. Use the
2385
2385
 
2386
2386
  Hooks run after the whole `decorate(...)` chain, so they always observe the fully decorated dependency, and their return value is ignored — `onResolve` can never swap the dependency out. They fire per resolution, which means a `singleton()` provider runs them only on the resolve that fills the cache.
2387
2387
 
2388
+ This — or the `@onResolved` decorator over the same provider event — is the recommended way to react to a dependency; see [OnConstruct](#onconstruct) for why `@onConstruct` is the narrower tool.
2389
+
2388
2390
  ```typescript
2389
2391
  import 'reflect-metadata';
2390
2392
  import { Container, type IContainer, onResolve, register, Registration as R, singleton } from 'ts-ioc-container';
@@ -2809,41 +2811,51 @@ describe('Container Modules', function () {
2809
2811
 
2810
2812
  Sometimes you need to invoke methods after construct or dispose of class. This is what hooks are for.
2811
2813
 
2812
- The generic `@hook` decorator takes a hook key and a map function
2813
- `(...prev: HookType[]) => HookType[]`, where `prev` is the list of hooks already
2814
- registered on the class for the decorated member. Use `appendHooks` /
2815
- `prependHooks` (exported as `append` / `prepend` too) to place new hooks around
2816
- the existing ones:
2814
+ Every hook decorator — the generic `@hook(key, hook)` and `@onConstruct`,
2815
+ `@onScopeDisposed`, `@onResolved` — takes **one** hook for the decorated member.
2816
+ Several hooks are combined at the declaration site, by the combinator that says
2817
+ how they relate:
2817
2818
 
2818
2819
  ```typescript
2819
2820
  class OrderService {
2820
- @hook('actions', append(validate, persist))
2821
- @hook('actions', prepend(authorize))
2821
+ @hook('actions', sequential(authorize, validate, persist))
2822
2822
  submit() {}
2823
+
2824
+ @onScopeDisposed(parallel(flushMetrics, closeSocket))
2825
+ destroy() {}
2823
2826
  }
2824
2827
  ```
2825
2828
 
2826
- Decorators are applied bottom-up, so `authorize` runs first, then `validate` and
2827
- `persist`. Any other map function works as well — for example
2828
- `(...prev) => [...prev].reverse()` to reorder, or `() => [onlyThisOne]` to
2829
- replace the accumulated hooks.
2829
+ - `sequential(...hooks)` runs them in declaration order, awaiting each one that
2830
+ goes async before the next.
2831
+ - `parallel(...hooks)` starts them all at once and settles when every one has.
2832
+ - `oncePerInstance(hook)` runs its hook a single time per instance, however
2833
+ often the event fires.
2830
2834
 
2831
- `@onConstruct` and `@onScopeDisposed` keep their variadic signature and
2832
- compensate for the bottom-up application order, so stacked decorators run in
2833
- declaration order: `@onConstruct(h1) @onConstruct(h2)` runs `h1` before `h2`.
2835
+ They compose, because each returns an ordinary `HookFn`:
2836
+ `oncePerInstance(sequential(connect, warmUp))`, or a `parallel(...)` nested
2837
+ inside a `sequential(...)`. A hook class (`HookType`) may be passed anywhere a
2838
+ hook function can. Writing your own combinator needs nothing from the library
2839
+ beyond `toHookFn`.
2840
+
2841
+ A member carries exactly one hook per key, so decorating the same member twice
2842
+ under one key replaces the earlier hook rather than adding to it — decorators
2843
+ are applied bottom-up, so the topmost one is the one that stays.
2834
2844
 
2835
2845
  Every hook may be sync or async — one decorator and one module take both, so
2836
2846
  there is no separate async form to reach for. *How* the hooks run is a separate
2837
2847
  choice: each module takes a `HookExecutionStrategy`, keyed to the hooks it runs
2838
- (`onConstruct`, `onScopeDisposed`, `onResolved`, or a custom key), and the
2839
- strategy decides the order, what is awaited, and where a failure goes
2840
- ([ADR 0014](../../adr/0014-hook-execution-strategy.md)):
2841
-
2842
- | Strategy | Members (decorated methods) | Hooks of one member | Awaits |
2843
- | ----------------- | --------------------------- | ------------------------------------------- | ------ |
2844
- | `SequentialSync` | one after another | in declaration order | no |
2845
- | `SequentialAsync` | one after another | in order, or all at once (`methodStrategy`) | yes |
2846
- | `ParallelAsync` | all at once | in order, or all at once (`methodStrategy`) | yes |
2848
+ (`onConstruct`, `onScopeDisposed`, `onResolved`, or a custom key). A strategy
2849
+ decides how the **members** — the decorated methods — relate to each other,
2850
+ what is awaited, and where a failure goes
2851
+ ([ADR 0015](../../adr/0015-one-hook-per-member.md)); how the hooks *within* one
2852
+ member relate is the combinator's job, not the strategy's:
2853
+
2854
+ | Strategy | Members (decorated methods) | Awaits |
2855
+ | ----------------- | --------------------------- | ------ |
2856
+ | `SequentialSync` | one after another | no |
2857
+ | `SequentialAsync` | one after another | yes |
2858
+ | `ParallelAsync` | all at once | yes |
2847
2859
 
2848
2860
  ```typescript
2849
2861
  const container = new Container()
@@ -2915,15 +2927,26 @@ and `OnResolvedModule` reaches every provider through `registered`.
2915
2927
 
2916
2928
  ### OnConstruct
2917
2929
 
2930
+ > **Prefer `@onResolved` — or the [`onResolve`](#on-resolve) pipe — over
2931
+ > `@onConstruct`.** Construction is the *injector's* event, so `@onConstruct`
2932
+ > fires only for dependencies the injector builds: a `fromValue` constant or a
2933
+ > factory registration never triggers it. It also observes the instance before
2934
+ > the provider's `decorate(...)` chain wraps it, so a hook sees the bare
2935
+ > instance rather than what the caller receives. `@onResolved` runs on every
2936
+ > dependency leaving a provider, after the whole decorate chain — the same
2937
+ > ordering, awaiting and error handling, on what the caller actually gets.
2938
+ > Reach for `@onConstruct` only when you mean "this class was just constructed"
2939
+ > specifically.
2940
+
2918
2941
  ```typescript
2919
2942
  import 'reflect-metadata';
2920
2943
  import {
2921
- OnConstructModule,
2922
2944
  Container,
2923
2945
  type HookFn,
2924
2946
  type IContainer,
2925
2947
  inject,
2926
2948
  onConstruct,
2949
+ OnConstructModule,
2927
2950
  Registration as R,
2928
2951
  SequentialAsync,
2929
2952
  SequentialSync,
@@ -3154,7 +3177,7 @@ describe('onScopeDisposed', function () {
3154
3177
 
3155
3178
  ```typescript
3156
3179
  import 'reflect-metadata';
3157
- import { append, Container, hook, SequentialSync, injectProp, Registration } from 'ts-ioc-container';
3180
+ import { Container, hook, injectProp, Registration, sequential, SequentialSync } from 'ts-ioc-container';
3158
3181
 
3159
3182
  /**
3160
3183
  * UI Components - Property Injection
@@ -3174,7 +3197,7 @@ describe('inject property', () => {
3174
3197
 
3175
3198
  class UserViewModel {
3176
3199
  // Inject 'GreetingService' into 'greeting' property during 'onInit'
3177
- @hook('onInit', append(injectProp('GreetingService')))
3200
+ @hook('onInit', injectProp('GreetingService'))
3178
3201
  greetingService!: string;
3179
3202
 
3180
3203
  display(): string {
@@ -3202,7 +3225,7 @@ describe('inject property', () => {
3202
3225
  class UserViewModel {
3203
3226
  @hook(
3204
3227
  'onInit',
3205
- append(injectProp('GreetingService'), (context) => {
3228
+ sequential(injectProp('GreetingService'), (context) => {
3206
3229
  injectedValue = context.getProperty();
3207
3230
  }),
3208
3231
  )
@@ -1,29 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HookExecutionStrategy = exports.runAtOnce = exports.runInOrder = void 0;
3
+ exports.HookExecutionStrategy = void 0;
4
4
  const target_1 = require("../metadata/target");
5
5
  const hook_1 = require("./hook");
6
6
  const HookContext_1 = require("./HookContext");
7
- const runInOrder = (hooks, context, from = 0) => {
8
- for (let i = from; i < hooks.length; i++) {
9
- const result = hooks[i](context);
10
- if (result instanceof Promise) {
11
- return result.then(() => (0, exports.runInOrder)(hooks, context, i + 1));
12
- }
13
- }
14
- };
15
- exports.runInOrder = runInOrder;
16
- const runAtOnce = (hooks, context) => {
17
- const pending = [];
18
- for (const hook of hooks) {
19
- const result = hook(context);
20
- if (result instanceof Promise) {
21
- pending.push(result);
22
- }
23
- }
24
- return pending.length > 0 ? Promise.all(pending).then(() => undefined) : undefined;
25
- };
26
- exports.runAtOnce = runAtOnce;
27
7
  class HookExecutionStrategy {
28
8
  key;
29
9
  onError;
@@ -48,9 +28,9 @@ class HookExecutionStrategy {
48
28
  }
49
29
  collect(target, scope, { createExecutionContext = this.options.createExecutionContext, mapExecutionContext = this.options.mapExecutionContext, predicate = this.options.predicate, }) {
50
30
  const members = [];
51
- for (const { methodName, hooks } of this.hooksOf(target)) {
31
+ for (const { methodName, hook } of this.hooksOf(target)) {
52
32
  if (predicate(methodName)) {
53
- members.push({ hooks, context: mapExecutionContext(createExecutionContext(target, scope, methodName)) });
33
+ members.push({ hook, context: mapExecutionContext(createExecutionContext(target, scope, methodName)) });
54
34
  }
55
35
  }
56
36
  return members;
@@ -59,7 +39,7 @@ class HookExecutionStrategy {
59
39
  const Target = (0, target_1.resolveConstructor)(target);
60
40
  let hooks = this.hooksByClass.get(Target);
61
41
  if (!hooks) {
62
- hooks = Array.from((0, hook_1.getHooks)(Target, this.key), ([methodName, fns]) => ({ methodName, hooks: fns.map(hook_1.toHookFn) }));
42
+ hooks = Array.from((0, hook_1.getHooks)(Target, this.key), ([methodName, fn]) => ({ methodName, hook: (0, hook_1.toHookFn)(fn) }));
63
43
  this.hooksByClass.set(Target, hooks);
64
44
  }
65
45
  return hooks;
@@ -1,17 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ParallelAsync = void 0;
4
- const AsyncHookExecutionStrategy_1 = require("./AsyncHookExecutionStrategy");
5
- class ParallelAsync extends AsyncHookExecutionStrategy_1.AsyncHookExecutionStrategy {
4
+ const HookExecutionStrategy_1 = require("./HookExecutionStrategy");
5
+ const task_1 = require("../utils/task");
6
+ class ParallelAsync extends HookExecutionStrategy_1.HookExecutionStrategy {
6
7
  processHooks(members) {
7
- const pending = [];
8
- for (const member of members) {
9
- const result = this.runMember(member);
10
- if (result) {
11
- pending.push(result);
12
- }
13
- }
14
- return pending.length > 0 ? Promise.all(pending).then(() => undefined) : undefined;
8
+ return (0, task_1.runAtOnce)(members.map(({ hook, context }) => () => hook(context)));
15
9
  }
16
10
  }
17
11
  exports.ParallelAsync = ParallelAsync;
@@ -1,15 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SequentialAsync = void 0;
4
- const AsyncHookExecutionStrategy_1 = require("./AsyncHookExecutionStrategy");
5
- class SequentialAsync extends AsyncHookExecutionStrategy_1.AsyncHookExecutionStrategy {
6
- processHooks(members, from = 0) {
7
- for (let i = from; i < members.length; i++) {
8
- const result = this.runMember(members[i]);
9
- if (result) {
10
- return result.then(() => this.processHooks(members, i + 1));
11
- }
12
- }
4
+ const HookExecutionStrategy_1 = require("./HookExecutionStrategy");
5
+ const task_1 = require("../utils/task");
6
+ class SequentialAsync extends HookExecutionStrategy_1.HookExecutionStrategy {
7
+ processHooks(members) {
8
+ return (0, task_1.runInOrder)(members.map(({ hook, context }) => () => hook(context)));
13
9
  }
14
10
  }
15
11
  exports.SequentialAsync = SequentialAsync;
@@ -4,10 +4,8 @@ exports.SequentialSync = void 0;
4
4
  const HookExecutionStrategy_1 = require("./HookExecutionStrategy");
5
5
  class SequentialSync extends HookExecutionStrategy_1.HookExecutionStrategy {
6
6
  processHooks(members) {
7
- for (const { hooks, context } of members) {
8
- for (const hook of hooks) {
9
- hook(context);
10
- }
7
+ for (const { hook, context } of members) {
8
+ hook(context);
11
9
  }
12
10
  }
13
11
  }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.oncePerInstance = exports.parallel = exports.sequential = void 0;
4
+ const task_1 = require("../utils/task");
5
+ const hook_1 = require("./hook");
6
+ const sequential = (...hooks) => {
7
+ const fns = hooks.map(hook_1.toHookFn);
8
+ return (context) => (0, task_1.runInOrder)(fns.map((fn) => () => fn(context)));
9
+ };
10
+ exports.sequential = sequential;
11
+ const parallel = (...hooks) => {
12
+ const fns = hooks.map(hook_1.toHookFn);
13
+ return (context) => (0, task_1.runAtOnce)(fns.map((fn) => () => fn(context)));
14
+ };
15
+ exports.parallel = parallel;
16
+ const oncePerInstance = (execute) => {
17
+ const invokedInstances = new WeakSet();
18
+ const fn = (0, hook_1.toHookFn)(execute);
19
+ return (context) => {
20
+ if (invokedInstances.has(context.instance)) {
21
+ return;
22
+ }
23
+ invokedInstances.add(context.instance);
24
+ return fn(context);
25
+ };
26
+ };
27
+ exports.oncePerInstance = oncePerInstance;
package/cjm/hooks/hook.js CHANGED
@@ -1,16 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.hook = exports.toHookFn = exports.prepend = exports.append = exports.prependHooks = exports.appendHooks = void 0;
3
+ exports.hook = exports.toHookFn = void 0;
4
4
  exports.getHooks = getHooks;
5
5
  exports.hasHooks = hasHooks;
6
6
  const basic_1 = require("../utils/basic");
7
7
  const target_1 = require("../metadata/target");
8
- const appendHooks = (...fns) => (...prev) => [...prev, ...fns];
9
- exports.appendHooks = appendHooks;
10
- const prependHooks = (...fns) => (...prev) => [...fns, ...prev];
11
- exports.prependHooks = prependHooks;
12
- exports.append = exports.appendHooks;
13
- exports.prepend = exports.prependHooks;
14
8
  const isHookClassConstructor = (execute) => {
15
9
  return basic_1.Is.constructor(execute) && execute.prototype.execute;
16
10
  };
@@ -30,8 +24,8 @@ function getHooks(target, key) {
30
24
  for (const ctor of getConstructorChain((0, target_1.resolveConstructor)(target)).reverse()) {
31
25
  const ownHooks = Reflect.getOwnMetadata(key, ctor);
32
26
  if (ownHooks) {
33
- for (const [methodName, fns] of ownHooks) {
34
- merged.set(methodName, fns);
27
+ for (const [methodName, fn] of ownHooks) {
28
+ merged.set(methodName, fn);
35
29
  }
36
30
  }
37
31
  }
@@ -40,11 +34,11 @@ function getHooks(target, key) {
40
34
  function hasHooks(target, key) {
41
35
  return getConstructorChain((0, target_1.resolveConstructor)(target)).some((ctor) => Reflect.hasOwnMetadata(key, ctor));
42
36
  }
43
- const hook = (key, mapFn) => (target, propertyKey) => {
37
+ const hook = (key, fn) => (target, propertyKey) => {
44
38
  const hooks = Reflect.hasOwnMetadata(key, target.constructor)
45
39
  ? Reflect.getOwnMetadata(key, target.constructor)
46
40
  : new Map();
47
- hooks.set(propertyKey, mapFn(...(hooks.get(propertyKey) ?? [])));
41
+ hooks.set(propertyKey, fn);
48
42
  Reflect.defineMetadata(key, hooks, target.constructor);
49
43
  };
50
44
  exports.hook = hook;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OnConstructModule = exports.onConstruct = void 0;
4
4
  const hook_1 = require("./hook");
5
- const onConstruct = (...fns) => (0, hook_1.hook)('onConstruct', (0, hook_1.prependHooks)(...fns));
5
+ const onConstruct = (fn) => (0, hook_1.hook)('onConstruct', fn);
6
6
  exports.onConstruct = onConstruct;
7
7
  class OnConstructModule {
8
8
  strategy;
@@ -4,7 +4,7 @@ exports.resolved = exports.OnResolvedModule = exports.onResolved = void 0;
4
4
  const IRegistration_1 = require("../registration/IRegistration");
5
5
  const basic_1 = require("../utils/basic");
6
6
  const hook_1 = require("./hook");
7
- const onResolved = (...hooks) => (0, hook_1.hook)('onResolved', (0, hook_1.prependHooks)(...hooks));
7
+ const onResolved = (fn) => (0, hook_1.hook)('onResolved', fn);
8
8
  exports.onResolved = onResolved;
9
9
  const runHooks = (strategy) => (dependency, scope) => {
10
10
  if (basic_1.Is.object(dependency)) {
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OnDisposeModule = exports.onScopeDisposed = void 0;
4
4
  const hook_1 = require("./hook");
5
- const onScopeDisposed = (...fns) => (0, hook_1.hook)('onScopeDisposed', (0, hook_1.prependHooks)(...fns));
5
+ const onScopeDisposed = (fn) => (0, hook_1.hook)('onScopeDisposed', fn);
6
6
  exports.onScopeDisposed = onScopeDisposed;
7
7
  class OnDisposeModule {
8
8
  strategy;
package/cjm/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createHookContextFactory = exports.HookContext = exports.prepend = exports.append = exports.prependHooks = exports.appendHooks = exports.hasHooks = exports.hook = exports.getHooks = exports.TypedEventDisposedError = exports.UnsupportedTokenTypeError = exports.CannonSingletonApplyTwiceError = exports.ProviderDisposedError = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyMissingKeyError = exports.ContainerNotFoundError = exports.DependencyNotFoundError = exports.ContainerError = exports.Registration = exports.onResolve = exports.appendArgsFn = exports.appendArgs = exports.decorate = exports.singleton = exports.autoResolve = exports.lazy = exports.scopeAccess = exports.scope = exports.bindTo = exports.register = exports.toRegistrationFn = exports.toProviderFn = exports.toBindToken = exports.registerPipe = exports.isProviderPipe = exports.Provider = exports.ProxyInjector = exports.SimpleInjector = exports.resolveArgs = exports.argsFn = exports.args = exports.arg = exports.inject = exports.MetadataInjector = exports.Injector = exports.EmptyContainer = exports.AutoResolveModule = exports.Container = exports.isDependencyKey = void 0;
4
- 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.resolveConstructor = exports.GroupInstanceToken = exports.ConstantToken = exports.FunctionToken = exports.SingleToken = exports.ClassToken = exports.toSingleAlias = exports.SingleAliasToken = exports.toGroupAlias = exports.GroupAliasToken = exports.argToToken = exports.toMappedToken = exports.toToken = exports.InjectionToken = exports.ParallelAsync = exports.SequentialAsync = exports.SequentialSync = exports.AsyncHookExecutionStrategy = exports.HookExecutionStrategy = exports.oncePerInstance = exports.resolved = exports.OnResolvedModule = exports.onResolved = exports.OnDisposeModule = exports.onScopeDisposed = exports.OnConstructModule = exports.onConstruct = exports.injectProp = exports.createHookExecutionContext = void 0;
3
+ exports.onConstruct = exports.injectProp = exports.createHookExecutionContext = exports.createHookContextFactory = exports.HookContext = exports.toHookFn = exports.hasHooks = exports.hook = exports.getHooks = exports.TypedEventDisposedError = exports.UnsupportedTokenTypeError = exports.CannonSingletonApplyTwiceError = exports.ProviderDisposedError = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyMissingKeyError = exports.ContainerNotFoundError = exports.DependencyNotFoundError = exports.ContainerError = exports.Registration = exports.onResolve = exports.appendArgsFn = exports.appendArgs = exports.decorate = exports.singleton = exports.autoResolve = exports.lazy = exports.scopeAccess = exports.scope = exports.bindTo = exports.register = exports.toRegistrationFn = exports.toProviderFn = exports.toBindToken = exports.registerPipe = exports.isProviderPipe = exports.Provider = exports.ProxyInjector = exports.SimpleInjector = exports.resolveArgs = exports.argsFn = exports.args = exports.arg = exports.inject = exports.MetadataInjector = exports.Injector = exports.EmptyContainer = exports.AutoResolveModule = exports.Container = exports.isDependencyKey = void 0;
4
+ exports.throttle = exports.runAtOnce = exports.runInOrder = 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.resolveConstructor = exports.GroupInstanceToken = exports.ConstantToken = exports.FunctionToken = exports.SingleToken = exports.ClassToken = exports.toSingleAlias = exports.SingleAliasToken = exports.toGroupAlias = exports.GroupAliasToken = exports.argToToken = exports.toMappedToken = exports.toToken = exports.InjectionToken = exports.ParallelAsync = exports.SequentialAsync = exports.SequentialSync = exports.HookExecutionStrategy = exports.oncePerInstance = exports.parallel = exports.sequential = exports.resolved = exports.OnResolvedModule = exports.onResolved = exports.OnDisposeModule = exports.onScopeDisposed = exports.OnConstructModule = void 0;
5
5
  exports.Is = exports.unwrapProxy = exports.ProxyRegistry = exports.pipe = exports.select = exports.TypedEvent = exports.once = exports.shallowCache = exports.debounce = void 0;
6
6
  var IContainer_1 = require("./container/IContainer");
7
7
  Object.defineProperty(exports, "isDependencyKey", { enumerable: true, get: function () { return IContainer_1.isDependencyKey; } });
@@ -69,10 +69,7 @@ var hook_1 = require("./hooks/hook");
69
69
  Object.defineProperty(exports, "getHooks", { enumerable: true, get: function () { return hook_1.getHooks; } });
70
70
  Object.defineProperty(exports, "hook", { enumerable: true, get: function () { return hook_1.hook; } });
71
71
  Object.defineProperty(exports, "hasHooks", { enumerable: true, get: function () { return hook_1.hasHooks; } });
72
- Object.defineProperty(exports, "appendHooks", { enumerable: true, get: function () { return hook_1.appendHooks; } });
73
- Object.defineProperty(exports, "prependHooks", { enumerable: true, get: function () { return hook_1.prependHooks; } });
74
- Object.defineProperty(exports, "append", { enumerable: true, get: function () { return hook_1.append; } });
75
- Object.defineProperty(exports, "prepend", { enumerable: true, get: function () { return hook_1.prepend; } });
72
+ Object.defineProperty(exports, "toHookFn", { enumerable: true, get: function () { return hook_1.toHookFn; } });
76
73
  var HookContext_1 = require("./hooks/HookContext");
77
74
  Object.defineProperty(exports, "HookContext", { enumerable: true, get: function () { return HookContext_1.HookContext; } });
78
75
  Object.defineProperty(exports, "createHookContextFactory", { enumerable: true, get: function () { return HookContext_1.createHookContextFactory; } });
@@ -89,12 +86,12 @@ var onResolved_1 = require("./hooks/onResolved");
89
86
  Object.defineProperty(exports, "onResolved", { enumerable: true, get: function () { return onResolved_1.onResolved; } });
90
87
  Object.defineProperty(exports, "OnResolvedModule", { enumerable: true, get: function () { return onResolved_1.OnResolvedModule; } });
91
88
  Object.defineProperty(exports, "resolved", { enumerable: true, get: function () { return onResolved_1.resolved; } });
92
- var resolveHooks_1 = require("./hooks/resolveHooks");
93
- Object.defineProperty(exports, "oncePerInstance", { enumerable: true, get: function () { return resolveHooks_1.oncePerInstance; } });
89
+ var combinators_1 = require("./hooks/combinators");
90
+ Object.defineProperty(exports, "sequential", { enumerable: true, get: function () { return combinators_1.sequential; } });
91
+ Object.defineProperty(exports, "parallel", { enumerable: true, get: function () { return combinators_1.parallel; } });
92
+ Object.defineProperty(exports, "oncePerInstance", { enumerable: true, get: function () { return combinators_1.oncePerInstance; } });
94
93
  var HookExecutionStrategy_1 = require("./hooks/HookExecutionStrategy");
95
94
  Object.defineProperty(exports, "HookExecutionStrategy", { enumerable: true, get: function () { return HookExecutionStrategy_1.HookExecutionStrategy; } });
96
- var AsyncHookExecutionStrategy_1 = require("./hooks/AsyncHookExecutionStrategy");
97
- Object.defineProperty(exports, "AsyncHookExecutionStrategy", { enumerable: true, get: function () { return AsyncHookExecutionStrategy_1.AsyncHookExecutionStrategy; } });
98
95
  var SequentialSync_1 = require("./hooks/SequentialSync");
99
96
  Object.defineProperty(exports, "SequentialSync", { enumerable: true, get: function () { return SequentialSync_1.SequentialSync; } });
100
97
  var SequentialAsync_1 = require("./hooks/SequentialAsync");
@@ -149,6 +146,9 @@ Object.defineProperty(exports, "getMethodTags", { enumerable: true, get: functio
149
146
  var errorHandler_1 = require("./utils/errorHandler");
150
147
  Object.defineProperty(exports, "handleError", { enumerable: true, get: function () { return errorHandler_1.handleError; } });
151
148
  Object.defineProperty(exports, "handleAsyncError", { enumerable: true, get: function () { return errorHandler_1.handleAsyncError; } });
149
+ var task_1 = require("./utils/task");
150
+ Object.defineProperty(exports, "runInOrder", { enumerable: true, get: function () { return task_1.runInOrder; } });
151
+ Object.defineProperty(exports, "runAtOnce", { enumerable: true, get: function () { return task_1.runAtOnce; } });
152
152
  var throttle_1 = require("./utils/throttle");
153
153
  Object.defineProperty(exports, "throttle", { enumerable: true, get: function () { return throttle_1.throttle; } });
154
154
  var debounce_1 = require("./utils/debounce");
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runAtOnce = exports.runInOrder = void 0;
4
+ const runInOrder = (tasks, from = 0) => {
5
+ for (let i = from; i < tasks.length; i++) {
6
+ const result = tasks[i]();
7
+ if (result instanceof Promise) {
8
+ return result.then(() => (0, exports.runInOrder)(tasks, i + 1));
9
+ }
10
+ }
11
+ };
12
+ exports.runInOrder = runInOrder;
13
+ const runAtOnce = (tasks) => {
14
+ const pending = [];
15
+ for (const task of tasks) {
16
+ const result = task();
17
+ if (result instanceof Promise) {
18
+ pending.push(result);
19
+ }
20
+ }
21
+ return pending.length > 0 ? Promise.all(pending).then(() => undefined) : undefined;
22
+ };
23
+ exports.runAtOnce = runAtOnce;
@@ -1,24 +1,6 @@
1
1
  import { resolveConstructor } from '../metadata/target.js';
2
2
  import { getHooks, hasHooks, toHookFn } from './hook.js';
3
3
  import { createHookExecutionContext } from './HookContext.js';
4
- export const runInOrder = (hooks, context, from = 0) => {
5
- for (let i = from; i < hooks.length; i++) {
6
- const result = hooks[i](context);
7
- if (result instanceof Promise) {
8
- return result.then(() => runInOrder(hooks, context, i + 1));
9
- }
10
- }
11
- };
12
- export const runAtOnce = (hooks, context) => {
13
- const pending = [];
14
- for (const hook of hooks) {
15
- const result = hook(context);
16
- if (result instanceof Promise) {
17
- pending.push(result);
18
- }
19
- }
20
- return pending.length > 0 ? Promise.all(pending).then(() => undefined) : undefined;
21
- };
22
4
  export class HookExecutionStrategy {
23
5
  key;
24
6
  onError;
@@ -43,9 +25,9 @@ export class HookExecutionStrategy {
43
25
  }
44
26
  collect(target, scope, { createExecutionContext = this.options.createExecutionContext, mapExecutionContext = this.options.mapExecutionContext, predicate = this.options.predicate, }) {
45
27
  const members = [];
46
- for (const { methodName, hooks } of this.hooksOf(target)) {
28
+ for (const { methodName, hook } of this.hooksOf(target)) {
47
29
  if (predicate(methodName)) {
48
- members.push({ hooks, context: mapExecutionContext(createExecutionContext(target, scope, methodName)) });
30
+ members.push({ hook, context: mapExecutionContext(createExecutionContext(target, scope, methodName)) });
49
31
  }
50
32
  }
51
33
  return members;
@@ -54,7 +36,7 @@ export class HookExecutionStrategy {
54
36
  const Target = resolveConstructor(target);
55
37
  let hooks = this.hooksByClass.get(Target);
56
38
  if (!hooks) {
57
- hooks = Array.from(getHooks(Target, this.key), ([methodName, fns]) => ({ methodName, hooks: fns.map(toHookFn) }));
39
+ hooks = Array.from(getHooks(Target, this.key), ([methodName, fn]) => ({ methodName, hook: toHookFn(fn) }));
58
40
  this.hooksByClass.set(Target, hooks);
59
41
  }
60
42
  return hooks;
@@ -1,13 +1,7 @@
1
- import { AsyncHookExecutionStrategy } from './AsyncHookExecutionStrategy.js';
2
- export class ParallelAsync extends AsyncHookExecutionStrategy {
1
+ import { HookExecutionStrategy } from './HookExecutionStrategy.js';
2
+ import { runAtOnce } from '../utils/task.js';
3
+ export class ParallelAsync extends HookExecutionStrategy {
3
4
  processHooks(members) {
4
- const pending = [];
5
- for (const member of members) {
6
- const result = this.runMember(member);
7
- if (result) {
8
- pending.push(result);
9
- }
10
- }
11
- return pending.length > 0 ? Promise.all(pending).then(() => undefined) : undefined;
5
+ return runAtOnce(members.map(({ hook, context }) => () => hook(context)));
12
6
  }
13
7
  }
@@ -1,11 +1,7 @@
1
- import { AsyncHookExecutionStrategy } from './AsyncHookExecutionStrategy.js';
2
- export class SequentialAsync extends AsyncHookExecutionStrategy {
3
- processHooks(members, from = 0) {
4
- for (let i = from; i < members.length; i++) {
5
- const result = this.runMember(members[i]);
6
- if (result) {
7
- return result.then(() => this.processHooks(members, i + 1));
8
- }
9
- }
1
+ import { HookExecutionStrategy } from './HookExecutionStrategy.js';
2
+ import { runInOrder } from '../utils/task.js';
3
+ export class SequentialAsync extends HookExecutionStrategy {
4
+ processHooks(members) {
5
+ return runInOrder(members.map(({ hook, context }) => () => hook(context)));
10
6
  }
11
7
  }
@@ -1,10 +1,8 @@
1
1
  import { HookExecutionStrategy } from './HookExecutionStrategy.js';
2
2
  export class SequentialSync extends HookExecutionStrategy {
3
3
  processHooks(members) {
4
- for (const { hooks, context } of members) {
5
- for (const hook of hooks) {
6
- hook(context);
7
- }
4
+ for (const { hook, context } of members) {
5
+ hook(context);
8
6
  }
9
7
  }
10
8
  }
@@ -0,0 +1,21 @@
1
+ import { runAtOnce, runInOrder } from '../utils/task.js';
2
+ import { toHookFn } from './hook.js';
3
+ export const sequential = (...hooks) => {
4
+ const fns = hooks.map(toHookFn);
5
+ return (context) => runInOrder(fns.map((fn) => () => fn(context)));
6
+ };
7
+ export const parallel = (...hooks) => {
8
+ const fns = hooks.map(toHookFn);
9
+ return (context) => runAtOnce(fns.map((fn) => () => fn(context)));
10
+ };
11
+ export const oncePerInstance = (execute) => {
12
+ const invokedInstances = new WeakSet();
13
+ const fn = toHookFn(execute);
14
+ return (context) => {
15
+ if (invokedInstances.has(context.instance)) {
16
+ return;
17
+ }
18
+ invokedInstances.add(context.instance);
19
+ return fn(context);
20
+ };
21
+ };
package/esm/hooks/hook.js CHANGED
@@ -1,9 +1,5 @@
1
1
  import { Is } from '../utils/basic.js';
2
2
  import { resolveConstructor } from '../metadata/target.js';
3
- export const appendHooks = (...fns) => (...prev) => [...prev, ...fns];
4
- export const prependHooks = (...fns) => (...prev) => [...fns, ...prev];
5
- export const append = appendHooks;
6
- export const prepend = prependHooks;
7
3
  const isHookClassConstructor = (execute) => {
8
4
  return Is.constructor(execute) && execute.prototype.execute;
9
5
  };
@@ -22,8 +18,8 @@ export function getHooks(target, key) {
22
18
  for (const ctor of getConstructorChain(resolveConstructor(target)).reverse()) {
23
19
  const ownHooks = Reflect.getOwnMetadata(key, ctor);
24
20
  if (ownHooks) {
25
- for (const [methodName, fns] of ownHooks) {
26
- merged.set(methodName, fns);
21
+ for (const [methodName, fn] of ownHooks) {
22
+ merged.set(methodName, fn);
27
23
  }
28
24
  }
29
25
  }
@@ -32,10 +28,10 @@ export function getHooks(target, key) {
32
28
  export function hasHooks(target, key) {
33
29
  return getConstructorChain(resolveConstructor(target)).some((ctor) => Reflect.hasOwnMetadata(key, ctor));
34
30
  }
35
- export const hook = (key, mapFn) => (target, propertyKey) => {
31
+ export const hook = (key, fn) => (target, propertyKey) => {
36
32
  const hooks = Reflect.hasOwnMetadata(key, target.constructor)
37
33
  ? Reflect.getOwnMetadata(key, target.constructor)
38
34
  : new Map();
39
- hooks.set(propertyKey, mapFn(...(hooks.get(propertyKey) ?? [])));
35
+ hooks.set(propertyKey, fn);
40
36
  Reflect.defineMetadata(key, hooks, target.constructor);
41
37
  };
@@ -1,5 +1,5 @@
1
- import { hook, prependHooks } from './hook.js';
2
- export const onConstruct = (...fns) => hook('onConstruct', prependHooks(...fns));
1
+ import { hook } from './hook.js';
2
+ export const onConstruct = (fn) => hook('onConstruct', fn);
3
3
  export class OnConstructModule {
4
4
  strategy;
5
5
  constructor(strategy) {
@@ -1,7 +1,7 @@
1
1
  import { registerPipe } from '../registration/IRegistration.js';
2
2
  import { Is } from '../utils/basic.js';
3
- import { hook, prependHooks } from './hook.js';
4
- export const onResolved = (...hooks) => hook('onResolved', prependHooks(...hooks));
3
+ import { hook } from './hook.js';
4
+ export const onResolved = (fn) => hook('onResolved', fn);
5
5
  const runHooks = (strategy) => (dependency, scope) => {
6
6
  if (Is.object(dependency)) {
7
7
  strategy.execute(dependency, { scope });
@@ -1,5 +1,5 @@
1
- import { hook, prependHooks } from './hook.js';
2
- export const onScopeDisposed = (...fns) => hook('onScopeDisposed', prependHooks(...fns));
1
+ import { hook } from './hook.js';
2
+ export const onScopeDisposed = (fn) => hook('onScopeDisposed', fn);
3
3
  export class OnDisposeModule {
4
4
  strategy;
5
5
  constructor(strategy) {
package/esm/index.js CHANGED
@@ -19,15 +19,14 @@ export { ProviderDisposedError } from './errors/ProviderDisposedError.js';
19
19
  export { CannonSingletonApplyTwiceError } from './errors/CannonSingletonApplyTwiceError.js';
20
20
  export { UnsupportedTokenTypeError } from './errors/UnsupportedTokenTypeError.js';
21
21
  export { TypedEventDisposedError } from './errors/TypedEventDisposedError.js';
22
- export { getHooks, hook, hasHooks, appendHooks, prependHooks, append, prepend, } from './hooks/hook.js';
22
+ export { getHooks, hook, hasHooks, toHookFn, } from './hooks/hook.js';
23
23
  export { HookContext, createHookContextFactory, createHookExecutionContext, } from './hooks/HookContext.js';
24
24
  export { injectProp } from './hooks/injectProp.js';
25
25
  export { onConstruct, OnConstructModule } from './hooks/onConstruct.js';
26
26
  export { onScopeDisposed, OnDisposeModule } from './hooks/onScopeDisposed.js';
27
27
  export { onResolved, OnResolvedModule, resolved } from './hooks/onResolved.js';
28
- export { oncePerInstance } from './hooks/resolveHooks.js';
28
+ export { sequential, parallel, oncePerInstance } from './hooks/combinators.js';
29
29
  export { HookExecutionStrategy, } from './hooks/HookExecutionStrategy.js';
30
- export { AsyncHookExecutionStrategy, } from './hooks/AsyncHookExecutionStrategy.js';
31
30
  export { SequentialSync } from './hooks/SequentialSync.js';
32
31
  export { SequentialAsync } from './hooks/SequentialAsync.js';
33
32
  export { ParallelAsync } from './hooks/ParallelAsync.js';
@@ -45,6 +44,7 @@ export { addClassMeta, getClassMeta, addClassLabel, getClassLabels, addClassTag,
45
44
  export { addParamMeta, getParamMeta, addParamLabel, getParamLabels, addParamTag, getParamTags, } from './metadata/parameter.js';
46
45
  export { addMethodMeta, getMethodMeta, addMethodLabel, getMethodLabels, addMethodTag, getMethodTags, } from './metadata/method.js';
47
46
  export { handleError, handleAsyncError } from './utils/errorHandler.js';
47
+ export { runInOrder, runAtOnce } from './utils/task.js';
48
48
  export { throttle } from './utils/throttle.js';
49
49
  export { debounce } from './utils/debounce.js';
50
50
  export { shallowCache } from './utils/shallowCache.js';
@@ -0,0 +1,18 @@
1
+ export const runInOrder = (tasks, from = 0) => {
2
+ for (let i = from; i < tasks.length; i++) {
3
+ const result = tasks[i]();
4
+ if (result instanceof Promise) {
5
+ return result.then(() => runInOrder(tasks, i + 1));
6
+ }
7
+ }
8
+ };
9
+ export const runAtOnce = (tasks) => {
10
+ const pending = [];
11
+ for (const task of tasks) {
12
+ const result = task();
13
+ if (result instanceof Promise) {
14
+ pending.push(result);
15
+ }
16
+ }
17
+ return pending.length > 0 ? Promise.all(pending).then(() => undefined) : undefined;
18
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-ioc-container",
3
- "version": "65.0.0",
3
+ "version": "67.0.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",
@@ -15,12 +15,10 @@ export type HookExecutionStrategyProps = HookExecutionOptions & {
15
15
  key: string | symbol;
16
16
  onError?: OnErrorHandler;
17
17
  };
18
- export type MemberHooks = {
19
- hooks: HookFn[];
18
+ export type MemberHook = {
19
+ hook: HookFn;
20
20
  context: IHookContext;
21
21
  };
22
- export declare const runInOrder: (hooks: HookFn[], context: IHookContext, from?: number) => void | Promise<void>;
23
- export declare const runAtOnce: (hooks: HookFn[], context: IHookContext) => void | Promise<void>;
24
22
  export declare abstract class HookExecutionStrategy {
25
23
  private readonly key;
26
24
  private readonly onError?;
@@ -29,7 +27,7 @@ export declare abstract class HookExecutionStrategy {
29
27
  constructor({ key, onError, createExecutionContext, mapExecutionContext, predicate, }: HookExecutionStrategyProps);
30
28
  hasHooks(target: Instance): boolean;
31
29
  execute(target: Instance, { scope, ...overrides }: HookExecutionContext): void;
32
- protected abstract processHooks(members: MemberHooks[]): void | Promise<void>;
30
+ protected abstract processHooks(members: MemberHook[]): void | Promise<void>;
33
31
  private collect;
34
32
  private hooksOf;
35
33
  }
@@ -1,5 +1,4 @@
1
- import { AsyncHookExecutionStrategy } from './AsyncHookExecutionStrategy.js';
2
- import { type MemberHooks } from './HookExecutionStrategy.js';
3
- export declare class ParallelAsync extends AsyncHookExecutionStrategy {
4
- protected processHooks(members: MemberHooks[]): void | Promise<void>;
1
+ import { HookExecutionStrategy, type MemberHook } from './HookExecutionStrategy.js';
2
+ export declare class ParallelAsync extends HookExecutionStrategy {
3
+ protected processHooks(members: MemberHook[]): void | Promise<void>;
5
4
  }
@@ -1,5 +1,4 @@
1
- import { AsyncHookExecutionStrategy } from './AsyncHookExecutionStrategy.js';
2
- import { type MemberHooks } from './HookExecutionStrategy.js';
3
- export declare class SequentialAsync extends AsyncHookExecutionStrategy {
4
- protected processHooks(members: MemberHooks[], from?: number): void | Promise<void>;
1
+ import { HookExecutionStrategy, type MemberHook } from './HookExecutionStrategy.js';
2
+ export declare class SequentialAsync extends HookExecutionStrategy {
3
+ protected processHooks(members: MemberHook[]): void | Promise<void>;
5
4
  }
@@ -1,4 +1,4 @@
1
- import { HookExecutionStrategy, type MemberHooks } from './HookExecutionStrategy.js';
1
+ import { HookExecutionStrategy, type MemberHook } from './HookExecutionStrategy.js';
2
2
  export declare class SequentialSync extends HookExecutionStrategy {
3
- protected processHooks(members: MemberHooks[]): void;
3
+ protected processHooks(members: MemberHook[]): void;
4
4
  }
@@ -1,4 +1,6 @@
1
1
  import type { IContainer } from '../container/IContainer.js';
2
2
  import { type HookFn, type HookType } from './hook.js';
3
3
  export type ResolvedObjectHook = (dependency: object, scope: IContainer) => void;
4
+ export declare const sequential: (...hooks: HookType[]) => HookFn;
5
+ export declare const parallel: (...hooks: HookType[]) => HookFn;
4
6
  export declare const oncePerInstance: (execute: HookType) => HookFn;
@@ -8,13 +8,8 @@ export interface HookClass<T extends IHookContext = IHookContext> {
8
8
  execute(context: Omit<T, 'scope'>): void | Promise<void>;
9
9
  }
10
10
  export type HookType<T extends IHookContext = IHookContext> = HookFn<T> | constructor<HookClass<T>>;
11
- export type MapHooksFn = (...prev: HookType[]) => HookType[];
12
- export type HooksOfClass = Map<string, HookType[]>;
13
- export declare const appendHooks: (...fns: HookType[]) => MapHooksFn;
14
- export declare const prependHooks: (...fns: HookType[]) => MapHooksFn;
15
- export declare const append: (...fns: HookType[]) => MapHooksFn;
16
- export declare const prepend: (...fns: HookType[]) => MapHooksFn;
11
+ export type HooksOfClass = Map<string, HookType>;
17
12
  export declare const toHookFn: <C extends IHookContext>(execute: HookFn<C> | constructor<HookClass<C>>) => HookFn<C>;
18
13
  export declare function getHooks(target: Instance | constructor<unknown>, key: string | symbol): HooksOfClass;
19
14
  export declare function hasHooks(target: Instance | constructor<unknown>, key: string | symbol): boolean;
20
- export declare const hook: (key: string | symbol, mapFn: MapHooksFn) => (target: object, propertyKey: string | symbol) => void;
15
+ export declare const hook: (key: string | symbol, fn: HookType) => (target: object, propertyKey: string | symbol) => void;
@@ -1,7 +1,7 @@
1
1
  import { type HookType } from './hook.js';
2
2
  import type { IContainer, IContainerModule } from '../container/IContainer.js';
3
3
  import { type HookExecutionStrategy } from './HookExecutionStrategy.js';
4
- export declare const onConstruct: (...fns: HookType[]) => (target: object, propertyKey: string | symbol) => void;
4
+ export declare const onConstruct: (fn: HookType) => (target: object, propertyKey: string | symbol) => void;
5
5
  export declare class OnConstructModule implements IContainerModule {
6
6
  private readonly strategy;
7
7
  constructor(strategy: HookExecutionStrategy);
@@ -1,7 +1,7 @@
1
1
  import type { IContainer, IContainerModule } from '../container/IContainer.js';
2
2
  import { type HookExecutionStrategy } from './HookExecutionStrategy.js';
3
3
  import { type HookType } from './hook.js';
4
- export declare const onResolved: (...hooks: HookType[]) => (target: object, propertyKey: string | symbol) => void;
4
+ export declare const onResolved: (fn: HookType) => (target: object, propertyKey: string | symbol) => void;
5
5
  export declare class OnResolvedModule implements IContainerModule {
6
6
  private readonly runHooks;
7
7
  constructor(strategy: HookExecutionStrategy);
@@ -1,7 +1,7 @@
1
1
  import { type HookType } from './hook.js';
2
2
  import type { IContainer, IContainerModule } from '../container/IContainer.js';
3
3
  import { type HookExecutionStrategy } from './HookExecutionStrategy.js';
4
- export declare const onScopeDisposed: (...fns: HookType[]) => (target: object, propertyKey: string | symbol) => void;
4
+ export declare const onScopeDisposed: (fn: HookType) => (target: object, propertyKey: string | symbol) => void;
5
5
  export declare class OnDisposeModule implements IContainerModule {
6
6
  private readonly strategy;
7
7
  constructor(strategy: HookExecutionStrategy);
@@ -20,15 +20,14 @@ export { ProviderDisposedError } from './errors/ProviderDisposedError.js';
20
20
  export { CannonSingletonApplyTwiceError } from './errors/CannonSingletonApplyTwiceError.js';
21
21
  export { UnsupportedTokenTypeError } from './errors/UnsupportedTokenTypeError.js';
22
22
  export { TypedEventDisposedError } from './errors/TypedEventDisposedError.js';
23
- export { getHooks, hook, hasHooks, appendHooks, prependHooks, append, prepend, type HookFn, type HookClass, type HookType, type MapHooksFn, type InjectFn, type HooksOfClass, } from './hooks/hook.js';
23
+ export { getHooks, hook, hasHooks, toHookFn, type HookFn, type HookClass, type HookType, type InjectFn, type HooksOfClass, } from './hooks/hook.js';
24
24
  export { HookContext, createHookContextFactory, createHookExecutionContext, type CreateHookExecutionContext, type IHookContext, } from './hooks/HookContext.js';
25
25
  export { injectProp } from './hooks/injectProp.js';
26
26
  export { onConstruct, OnConstructModule } from './hooks/onConstruct.js';
27
27
  export { onScopeDisposed, OnDisposeModule } from './hooks/onScopeDisposed.js';
28
28
  export { onResolved, OnResolvedModule, resolved } from './hooks/onResolved.js';
29
- export { oncePerInstance, type ResolvedObjectHook } from './hooks/resolveHooks.js';
30
- export { HookExecutionStrategy, type HookExecutionContext, type HookExecutionOptions, type HookExecutionStrategyProps, type MapHookExecutionContext, type MemberHooks, type OnErrorHandler, } from './hooks/HookExecutionStrategy.js';
31
- export { AsyncHookExecutionStrategy, type AsyncHookExecutionStrategyProps, type MethodStrategy, } from './hooks/AsyncHookExecutionStrategy.js';
29
+ export { sequential, parallel, oncePerInstance, type ResolvedObjectHook } from './hooks/combinators.js';
30
+ export { HookExecutionStrategy, type HookExecutionContext, type HookExecutionOptions, type HookExecutionStrategyProps, type MapHookExecutionContext, type MemberHook, type OnErrorHandler, } from './hooks/HookExecutionStrategy.js';
32
31
  export { SequentialSync } from './hooks/SequentialSync.js';
33
32
  export { SequentialAsync } from './hooks/SequentialAsync.js';
34
33
  export { ParallelAsync } from './hooks/ParallelAsync.js';
@@ -46,6 +45,7 @@ export { addClassMeta, getClassMeta, addClassLabel, getClassLabels, addClassTag,
46
45
  export { addParamMeta, getParamMeta, addParamLabel, getParamLabels, addParamTag, getParamTags, } from './metadata/parameter.js';
47
46
  export { addMethodMeta, getMethodMeta, addMethodLabel, getMethodLabels, addMethodTag, getMethodTags, } from './metadata/method.js';
48
47
  export { handleError, handleAsyncError, type HandleErrorParams } from './utils/errorHandler.js';
48
+ export { runInOrder, runAtOnce, type Task } from './utils/task.js';
49
49
  export { throttle } from './utils/throttle.js';
50
50
  export { debounce } from './utils/debounce.js';
51
51
  export { shallowCache } from './utils/shallowCache.js';
@@ -0,0 +1,3 @@
1
+ export type Task = () => void | Promise<void>;
2
+ export declare const runInOrder: (tasks: Task[], from?: number) => void | Promise<void>;
3
+ export declare const runAtOnce: (tasks: Task[]) => void | Promise<void>;
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AsyncHookExecutionStrategy = void 0;
4
- const HookExecutionStrategy_1 = require("./HookExecutionStrategy");
5
- class AsyncHookExecutionStrategy extends HookExecutionStrategy_1.HookExecutionStrategy {
6
- methodStrategy;
7
- constructor({ methodStrategy = 'sequential', ...props }) {
8
- super(props);
9
- this.methodStrategy = methodStrategy;
10
- }
11
- runMember({ hooks, context }) {
12
- return this.methodStrategy === 'parallel' ? (0, HookExecutionStrategy_1.runAtOnce)(hooks, context) : (0, HookExecutionStrategy_1.runInOrder)(hooks, context);
13
- }
14
- }
15
- exports.AsyncHookExecutionStrategy = AsyncHookExecutionStrategy;
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.oncePerInstance = void 0;
4
- const hook_1 = require("./hook");
5
- const oncePerInstance = (execute) => {
6
- const invokedInstances = new WeakSet();
7
- return (context) => {
8
- if (invokedInstances.has(context.instance)) {
9
- return;
10
- }
11
- invokedInstances.add(context.instance);
12
- return (0, hook_1.toHookFn)(execute)(context);
13
- };
14
- };
15
- exports.oncePerInstance = oncePerInstance;
@@ -1,11 +0,0 @@
1
- import { HookExecutionStrategy, runAtOnce, runInOrder, } from './HookExecutionStrategy.js';
2
- export class AsyncHookExecutionStrategy extends HookExecutionStrategy {
3
- methodStrategy;
4
- constructor({ methodStrategy = 'sequential', ...props }) {
5
- super(props);
6
- this.methodStrategy = methodStrategy;
7
- }
8
- runMember({ hooks, context }) {
9
- return this.methodStrategy === 'parallel' ? runAtOnce(hooks, context) : runInOrder(hooks, context);
10
- }
11
- }
@@ -1,11 +0,0 @@
1
- import { toHookFn } from './hook.js';
2
- export const oncePerInstance = (execute) => {
3
- const invokedInstances = new WeakSet();
4
- return (context) => {
5
- if (invokedInstances.has(context.instance)) {
6
- return;
7
- }
8
- invokedInstances.add(context.instance);
9
- return toHookFn(execute)(context);
10
- };
11
- };
@@ -1,10 +0,0 @@
1
- import { HookExecutionStrategy, type HookExecutionStrategyProps, type MemberHooks } from './HookExecutionStrategy.js';
2
- export type MethodStrategy = 'sequential' | 'parallel';
3
- export type AsyncHookExecutionStrategyProps = HookExecutionStrategyProps & {
4
- methodStrategy?: MethodStrategy;
5
- };
6
- export declare abstract class AsyncHookExecutionStrategy extends HookExecutionStrategy {
7
- private readonly methodStrategy;
8
- constructor({ methodStrategy, ...props }: AsyncHookExecutionStrategyProps);
9
- protected runMember({ hooks, context }: MemberHooks): void | Promise<void>;
10
- }