ts-ioc-container 66.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 +40 -35
  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
@@ -2811,50 +2811,56 @@ describe('Container Modules', function () {
2811
2811
 
2812
2812
  Sometimes you need to invoke methods after construct or dispose of class. This is what hooks are for.
2813
2813
 
2814
- The generic `@hook` decorator takes a hook key and a map function
2815
- `(...prev: HookType[]) => HookType[]`, where `prev` is the list of hooks already
2816
- registered on the class for the decorated member. Use `appendHooks` /
2817
- `prependHooks` (exported as `append` / `prepend` too) to place new hooks around
2818
- 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:
2819
2818
 
2820
2819
  ```typescript
2821
2820
  class OrderService {
2822
- @hook('actions', append(validate, persist))
2823
- @hook('actions', prepend(authorize))
2821
+ @hook('actions', sequential(authorize, validate, persist))
2824
2822
  submit() {}
2823
+
2824
+ @onScopeDisposed(parallel(flushMetrics, closeSocket))
2825
+ destroy() {}
2825
2826
  }
2826
2827
  ```
2827
2828
 
2828
- Decorators are applied bottom-up, so `authorize` runs first, then `validate` and
2829
- `persist`. Any other map function works as well — for example
2830
- `(...prev) => [...prev].reverse()` to reorder, or `() => [onlyThisOne]` to
2831
- 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.
2834
+
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`.
2832
2840
 
2833
- `@onConstruct` and `@onScopeDisposed` keep their variadic signature and
2834
- compensate for the bottom-up application order, so stacked decorators run in
2835
- declaration order: `@onConstruct(h1) @onConstruct(h2)` runs `h1` before `h2`.
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.
2836
2844
 
2837
2845
  Every hook may be sync or async — one decorator and one module take both, so
2838
2846
  there is no separate async form to reach for. *How* the hooks run is a separate
2839
2847
  choice: each module takes a `HookExecutionStrategy`, keyed to the hooks it runs
2840
- (`onConstruct`, `onScopeDisposed`, `onResolved`, or a custom key), and the
2841
- strategy decides the order, what is awaited, and where a failure goes
2842
- ([ADR 0014](../../adr/0014-hook-execution-strategy.md)):
2843
-
2844
- | Strategy | Members (decorated methods) | Hooks of one member | Awaits |
2845
- | ----------------- | --------------------------- | ------------------------------------------- | ------ |
2846
- | `SequentialSync` | one after another | in declaration order | no |
2847
- | `SequentialAsync` | one after another | in order, or all at once (`methodStrategy`) | yes |
2848
- | `ParallelAsync` | all at once | in order, or all at once (`methodStrategy`) | yes |
2849
-
2850
- The async strategies require `methodStrategy` (`'sequential'` or `'parallel'`):
2851
- how the hooks of one member relate is named at the construction site rather
2852
- than left to a default.
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 |
2853
2859
 
2854
2860
  ```typescript
2855
2861
  const container = new Container()
2856
2862
  .useModule(new OnConstructModule(new SequentialSync({ key: 'onConstruct' })))
2857
- .useModule(new OnDisposeModule(new ParallelAsync({ key: 'onScopeDisposed', methodStrategy: 'parallel' })));
2863
+ .useModule(new OnDisposeModule(new ParallelAsync({ key: 'onScopeDisposed' })));
2858
2864
  ```
2859
2865
 
2860
2866
  Resolution and disposal stay synchronous under every strategy: a run stays
@@ -2935,12 +2941,12 @@ and `OnResolvedModule` reaches every provider through `registered`.
2935
2941
  ```typescript
2936
2942
  import 'reflect-metadata';
2937
2943
  import {
2938
- OnConstructModule,
2939
2944
  Container,
2940
2945
  type HookFn,
2941
2946
  type IContainer,
2942
2947
  inject,
2943
2948
  onConstruct,
2949
+ OnConstructModule,
2944
2950
  Registration as R,
2945
2951
  SequentialAsync,
2946
2952
  SequentialSync,
@@ -3056,7 +3062,7 @@ describe('onConstruct', function () {
3056
3062
 
3057
3063
  // An async strategy awaits the hooks; resolution itself still does not wait for them.
3058
3064
  const container = new Container()
3059
- .useModule(new OnConstructModule(new SequentialAsync({ key: 'onConstruct', methodStrategy: 'sequential' })))
3065
+ .useModule(new OnConstructModule(new SequentialAsync({ key: 'onConstruct' })))
3060
3066
  .addRegistration(R.fromValue('postgres://localhost:5432').bindTo('ConnectionString'));
3061
3067
 
3062
3068
  const db = container.resolve(DatabaseConnection);
@@ -3083,7 +3089,6 @@ describe('onConstruct', function () {
3083
3089
  new OnConstructModule(
3084
3090
  new SequentialAsync({
3085
3091
  key: 'onConstruct',
3086
- methodStrategy: 'sequential',
3087
3092
  onError: (scope) => (ex) => {
3088
3093
  captured = { ex, scope };
3089
3094
  },
@@ -3172,7 +3177,7 @@ describe('onScopeDisposed', function () {
3172
3177
 
3173
3178
  ```typescript
3174
3179
  import 'reflect-metadata';
3175
- import { append, Container, hook, SequentialSync, injectProp, Registration } from 'ts-ioc-container';
3180
+ import { Container, hook, injectProp, Registration, sequential, SequentialSync } from 'ts-ioc-container';
3176
3181
 
3177
3182
  /**
3178
3183
  * UI Components - Property Injection
@@ -3192,7 +3197,7 @@ describe('inject property', () => {
3192
3197
 
3193
3198
  class UserViewModel {
3194
3199
  // Inject 'GreetingService' into 'greeting' property during 'onInit'
3195
- @hook('onInit', append(injectProp('GreetingService')))
3200
+ @hook('onInit', injectProp('GreetingService'))
3196
3201
  greetingService!: string;
3197
3202
 
3198
3203
  display(): string {
@@ -3220,7 +3225,7 @@ describe('inject property', () => {
3220
3225
  class UserViewModel {
3221
3226
  @hook(
3222
3227
  'onInit',
3223
- append(injectProp('GreetingService'), (context) => {
3228
+ sequential(injectProp('GreetingService'), (context) => {
3224
3229
  injectedValue = context.getProperty();
3225
3230
  }),
3226
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": "66.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, ...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, ...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
- }