ts-ioc-container 65.0.0 → 66.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.
package/README.md CHANGED
@@ -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';
@@ -2845,10 +2847,14 @@ strategy decides the order, what is awaited, and where a failure goes
2845
2847
  | `SequentialAsync` | one after another | in order, or all at once (`methodStrategy`) | yes |
2846
2848
  | `ParallelAsync` | all at once | in order, or all at once (`methodStrategy`) | yes |
2847
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.
2853
+
2848
2854
  ```typescript
2849
2855
  const container = new Container()
2850
2856
  .useModule(new OnConstructModule(new SequentialSync({ key: 'onConstruct' })))
2851
- .useModule(new OnDisposeModule(new ParallelAsync({ key: 'onScopeDisposed' })));
2857
+ .useModule(new OnDisposeModule(new ParallelAsync({ key: 'onScopeDisposed', methodStrategy: 'parallel' })));
2852
2858
  ```
2853
2859
 
2854
2860
  Resolution and disposal stay synchronous under every strategy: a run stays
@@ -2915,6 +2921,17 @@ and `OnResolvedModule` reaches every provider through `registered`.
2915
2921
 
2916
2922
  ### OnConstruct
2917
2923
 
2924
+ > **Prefer `@onResolved` — or the [`onResolve`](#on-resolve) pipe — over
2925
+ > `@onConstruct`.** Construction is the *injector's* event, so `@onConstruct`
2926
+ > fires only for dependencies the injector builds: a `fromValue` constant or a
2927
+ > factory registration never triggers it. It also observes the instance before
2928
+ > the provider's `decorate(...)` chain wraps it, so a hook sees the bare
2929
+ > instance rather than what the caller receives. `@onResolved` runs on every
2930
+ > dependency leaving a provider, after the whole decorate chain — the same
2931
+ > ordering, awaiting and error handling, on what the caller actually gets.
2932
+ > Reach for `@onConstruct` only when you mean "this class was just constructed"
2933
+ > specifically.
2934
+
2918
2935
  ```typescript
2919
2936
  import 'reflect-metadata';
2920
2937
  import {
@@ -3039,7 +3056,7 @@ describe('onConstruct', function () {
3039
3056
 
3040
3057
  // An async strategy awaits the hooks; resolution itself still does not wait for them.
3041
3058
  const container = new Container()
3042
- .useModule(new OnConstructModule(new SequentialAsync({ key: 'onConstruct' })))
3059
+ .useModule(new OnConstructModule(new SequentialAsync({ key: 'onConstruct', methodStrategy: 'sequential' })))
3043
3060
  .addRegistration(R.fromValue('postgres://localhost:5432').bindTo('ConnectionString'));
3044
3061
 
3045
3062
  const db = container.resolve(DatabaseConnection);
@@ -3066,6 +3083,7 @@ describe('onConstruct', function () {
3066
3083
  new OnConstructModule(
3067
3084
  new SequentialAsync({
3068
3085
  key: 'onConstruct',
3086
+ methodStrategy: 'sequential',
3069
3087
  onError: (scope) => (ex) => {
3070
3088
  captured = { ex, scope };
3071
3089
  },
@@ -4,7 +4,7 @@ exports.AsyncHookExecutionStrategy = void 0;
4
4
  const HookExecutionStrategy_1 = require("./HookExecutionStrategy");
5
5
  class AsyncHookExecutionStrategy extends HookExecutionStrategy_1.HookExecutionStrategy {
6
6
  methodStrategy;
7
- constructor({ methodStrategy = 'sequential', ...props }) {
7
+ constructor({ methodStrategy, ...props }) {
8
8
  super(props);
9
9
  this.methodStrategy = methodStrategy;
10
10
  }
@@ -1,7 +1,7 @@
1
1
  import { HookExecutionStrategy, runAtOnce, runInOrder, } from './HookExecutionStrategy.js';
2
2
  export class AsyncHookExecutionStrategy extends HookExecutionStrategy {
3
3
  methodStrategy;
4
- constructor({ methodStrategy = 'sequential', ...props }) {
4
+ constructor({ methodStrategy, ...props }) {
5
5
  super(props);
6
6
  this.methodStrategy = methodStrategy;
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-ioc-container",
3
- "version": "65.0.0",
3
+ "version": "66.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",
@@ -1,7 +1,7 @@
1
1
  import { HookExecutionStrategy, type HookExecutionStrategyProps, type MemberHooks } from './HookExecutionStrategy.js';
2
2
  export type MethodStrategy = 'sequential' | 'parallel';
3
3
  export type AsyncHookExecutionStrategyProps = HookExecutionStrategyProps & {
4
- methodStrategy?: MethodStrategy;
4
+ methodStrategy: MethodStrategy;
5
5
  };
6
6
  export declare abstract class AsyncHookExecutionStrategy extends HookExecutionStrategy {
7
7
  private readonly methodStrategy;