assemblerjs 1.0.1 → 1.1.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 (89) hide show
  1. package/README.md +8 -5
  2. package/dist/index.d.ts +430 -9
  3. package/dist/index.js +24 -12
  4. package/dist/index.mjs +16 -12
  5. package/dist/index11.js +82 -20
  6. package/dist/index11.mjs +78 -20
  7. package/dist/index12.js +17 -8
  8. package/dist/index12.mjs +16 -8
  9. package/dist/index13.js +148 -73
  10. package/dist/index13.mjs +148 -73
  11. package/dist/index14.js +4 -17
  12. package/dist/index14.mjs +4 -17
  13. package/dist/index15.js +21 -16
  14. package/dist/index15.mjs +21 -16
  15. package/dist/index16.js +10 -16
  16. package/dist/index16.mjs +10 -16
  17. package/dist/index17.js +88 -16
  18. package/dist/index17.mjs +88 -16
  19. package/dist/index18.js +11 -20
  20. package/dist/index18.mjs +11 -19
  21. package/dist/index19.js +11 -20
  22. package/dist/index19.mjs +11 -19
  23. package/dist/index2.js +3 -3
  24. package/dist/index2.mjs +3 -3
  25. package/dist/index20.js +11 -20
  26. package/dist/index20.mjs +11 -20
  27. package/dist/index21.js +14 -25
  28. package/dist/index21.mjs +14 -21
  29. package/dist/index22.js +24 -46
  30. package/dist/index22.mjs +23 -45
  31. package/dist/index23.js +22 -37
  32. package/dist/index23.mjs +21 -36
  33. package/dist/index24.js +26 -15
  34. package/dist/index24.mjs +26 -13
  35. package/dist/index25.js +24 -10
  36. package/dist/index25.mjs +20 -8
  37. package/dist/index26.js +45 -92
  38. package/dist/index26.mjs +44 -90
  39. package/dist/index27.js +2 -66
  40. package/dist/index27.mjs +2 -64
  41. package/dist/index28.js +17 -32
  42. package/dist/index28.mjs +15 -32
  43. package/dist/index29.js +53 -55
  44. package/dist/index29.mjs +53 -55
  45. package/dist/index3.js +2 -2
  46. package/dist/index3.mjs +2 -2
  47. package/dist/index30.js +28 -28
  48. package/dist/index30.mjs +28 -28
  49. package/dist/index31.js +62 -28
  50. package/dist/index31.mjs +62 -28
  51. package/dist/index32.js +28 -19
  52. package/dist/index32.mjs +28 -19
  53. package/dist/index33.js +32 -49
  54. package/dist/index33.mjs +32 -49
  55. package/dist/index34.js +17 -8
  56. package/dist/index34.mjs +14 -8
  57. package/dist/index35.js +18 -24
  58. package/dist/index35.mjs +18 -23
  59. package/dist/index36.js +37 -108
  60. package/dist/index36.mjs +36 -108
  61. package/dist/index37.js +98 -10
  62. package/dist/index37.mjs +96 -10
  63. package/dist/index38.js +95 -20
  64. package/dist/index38.mjs +95 -20
  65. package/dist/index39.js +23 -44
  66. package/dist/index39.mjs +23 -43
  67. package/dist/index4.js +5 -5
  68. package/dist/index4.mjs +5 -5
  69. package/dist/index40.js +34 -0
  70. package/dist/index40.mjs +29 -0
  71. package/dist/index41.js +14 -0
  72. package/dist/index41.mjs +10 -0
  73. package/dist/index42.js +54 -0
  74. package/dist/index42.mjs +50 -0
  75. package/dist/index43.js +177 -0
  76. package/dist/index43.mjs +173 -0
  77. package/dist/index44.js +947 -0
  78. package/dist/index44.mjs +943 -0
  79. package/dist/index45.js +7 -0
  80. package/dist/index45.mjs +3 -0
  81. package/dist/index46.js +7 -0
  82. package/dist/index46.mjs +3 -0
  83. package/dist/index47.js +19 -0
  84. package/dist/index47.mjs +15 -0
  85. package/dist/index48.js +33 -0
  86. package/dist/index48.mjs +29 -0
  87. package/dist/index49.js +67 -0
  88. package/dist/index49.mjs +62 -0
  89. package/package.json +2 -2
package/README.md CHANGED
@@ -4,14 +4,14 @@ A modern, type-safe, and lightweight [Dependency Injection](https://en.wikipedia
4
4
 
5
5
  > ✨ **Universal Library**: Works seamlessly in Node.js, browsers, and any JavaScript environment that supports ES2020+
6
6
 
7
- ![Statements](https://img.shields.io/badge/statements-91.01%25-brightgreen.svg?style=flat) ![Branches](https://img.shields.io/badge/branches-79.6%25-red.svg?style=flat) ![Functions](https://img.shields.io/badge/functions-87.62%25-yellow.svg?style=flat) ![Lines](https://img.shields.io/badge/lines-90.76%25-brightgreen.svg?style=flat)
7
+ ![Statements](https://img.shields.io/badge/statements-93.78%25-brightgreen.svg?style=flat) ![Branches](https://img.shields.io/badge/branches-83.87%25-yellow.svg?style=flat) ![Functions](https://img.shields.io/badge/functions-93.63%25-brightgreen.svg?style=flat) ![Lines](https://img.shields.io/badge/lines-93.96%25-brightgreen.svg?style=flat)
8
8
 
9
9
  ## Performance Metrics
10
10
 
11
- ![Assembler Building](https://img.shields.io/badge/assembler%20building-156k%20ops%2Fsec-brightgreen.svg?style=flat)
12
- ![Injectable Resolution](https://img.shields.io/badge/singleton%20cache-1.2M%20ops%2Fsec-brightgreen.svg?style=flat)
13
- ![Event System](https://img.shields.io/badge/event%20emit-432k%20ops%2Fsec-brightgreen.svg?style=flat)
14
- ![Decorators](https://img.shields.io/badge/decorators-890k%20ops%2Fsec-brightgreen.svg?style=flat)
11
+ ![assembler building](https://img.shields.io/badge/assembler%20building-11k%20ops%2Fsec-green.svg?style=flat)
12
+ ![singleton cache](https://img.shields.io/badge/singleton%20cache-104k%20ops%2Fsec-brightgreen.svg?style=flat)
13
+ ![event emit](https://img.shields.io/badge/event%20emit-558k%20ops%2Fsec-brightgreen.svg?style=flat)
14
+ ![decorators](https://img.shields.io/badge/decorators-588k%20ops%2Fsec-brightgreen.svg?style=flat)
15
15
 
16
16
  [→ Full Benchmarks](https://github.com/benoitlahoz/assemblerjs/blob/main/docs/assemblerjs/performance/benchmarks.md)
17
17
 
@@ -24,6 +24,7 @@ A modern, type-safe, and lightweight [Dependency Injection](https://en.wikipedia
24
24
  - 🌳 **Tree-Shakable** - Optimized bundle size (~5-6 KB for minimal usage)
25
25
  - ♻️ **Lifecycle Hooks** - `onRegister`, `onInit`, `onDispose`
26
26
  - 📡 **Built-in Event System** - Integrated EventManager
27
+ - 🔀 **AOP/Transversals** - Cross-cutting concerns (logging, security, caching, performance)
27
28
  - 🎨 **Custom Decorators** - Easy creation with `ParameterDecoratorFactory` and `createConstructorDecorator`
28
29
  - 🔧 **Flexible Configuration** - Runtime configuration override
29
30
  - 🏷️ **Tags Support** - Group and retrieve dependencies by tags
@@ -114,11 +115,13 @@ Comprehensive documentation is available at:
114
115
  - [Dependency Injection](https://github.com/benoitlahoz/assemblerjs/blob/main/docs/assemblerjs/core-concepts/dependency-injection.md) - DI patterns
115
116
  - [Abstraction Pattern](https://github.com/benoitlahoz/assemblerjs/blob/main/docs/assemblerjs/core-concepts/abstraction-pattern.md) - Interface-based design
116
117
  - [Lifecycle Hooks](https://github.com/benoitlahoz/assemblerjs/blob/main/docs/assemblerjs/core-concepts/lifecycle-hooks.md) - Initialization & cleanup
118
+ - [Transversals (AOP)](https://github.com/benoitlahoz/assemblerjs/blob/main/docs/assemblerjs/core-concepts/transversals-aop.md) - Aspect-Oriented Programming
117
119
 
118
120
  #### Decorators
119
121
  - [Parameter Decorators](https://github.com/benoitlahoz/assemblerjs/blob/main/docs/assemblerjs/decorators/parameter-decorators.md) - Built-in decorators
120
122
  - [Custom Parameter Decorators](https://github.com/benoitlahoz/assemblerjs/blob/main/docs/assemblerjs/decorators/custom-parameter.md) - Create your own
121
123
  - [Custom Class Decorators](https://github.com/benoitlahoz/assemblerjs/blob/main/docs/assemblerjs/decorators/custom-class.md) - Type-safe class decorators
124
+ - [AOP Decorators](https://github.com/benoitlahoz/assemblerjs/blob/main/docs/assemblerjs/decorators/aop-decorators.md) - @Transversal, @Before, @After, @Around, @Affect
122
125
 
123
126
  #### Features
124
127
  - [Event System](https://github.com/benoitlahoz/assemblerjs/blob/main/docs/assemblerjs/features/events.md) - Event-driven architecture
package/dist/index.d.ts CHANGED
@@ -108,6 +108,181 @@ export declare abstract class AbstractListenerCollection {
108
108
  abstract [Symbol.iterator](): Iterator<EventChannel>;
109
109
  }
110
110
 
111
+ /**
112
+ * Base abstract class to implement an transversal.
113
+ * A transversal is a special kind of assemblage that provides cross-cutting concerns.
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * @Transversal()
118
+ * class LoggingTransversal extends AbstractTransversal {
119
+ * onInit() {
120
+ * console.log('Transversal initialized');
121
+ * }
122
+ *
123
+ * @Before('execution(UserService.*)')
124
+ * logBefore(context: AdviceContext) {
125
+ * console.log('Before:', context.methodName);
126
+ * }
127
+ * }
128
+ * ```
129
+ */
130
+ export declare abstract class AbstractTransversal {
131
+ [key: string]: any;
132
+ /**
133
+ * Called on transversal class registration by assembler.
134
+ * This is called when the transversal is registered, not when it is instantiated.
135
+ *
136
+ * @param context The assembler's context.
137
+ * @param configuration The configuration object.
138
+ */
139
+ static onRegister(context: AssemblerContext, configuration?: Record<string, any>): void;
140
+ /**
141
+ * Called on transversal instantiation in less dependent to more dependent order
142
+ * after the dependency tree is fully resolved.
143
+ *
144
+ * @param context The assembler's context.
145
+ * @param configuration The configuration object.
146
+ */
147
+ abstract onInit?(context: AssemblerContext, configuration?: Record<string, any>): void | Promise<void>;
148
+ /**
149
+ * Called by the Assembler when all aspects have been initialized with onInit,
150
+ * in more dependent to less dependent order (reverse of onInit).
151
+ *
152
+ * @param context The assembler's context.
153
+ * @param configuration The configuration object.
154
+ */
155
+ abstract onInited?(context: AssemblerContext, configuration?: Record<string, any>): void | Promise<void>;
156
+ /**
157
+ * Called when transversal instance is disposed.
158
+ *
159
+ * @param context The assembler's context.
160
+ * @param configuration The configuration object.
161
+ */
162
+ abstract onDispose?(context: AssemblerContext, configuration?: Record<string, any>): void;
163
+ /**
164
+ * Dispose the transversal instance.
165
+ * Called to clean up resources when the transversal is no longer needed.
166
+ */
167
+ abstract dispose?(): void;
168
+ /**
169
+ * When decorated with '@Waitable', waits for a specific property to be truthy before resolving.
170
+ * This can be used to ensure the transversal is fully initialized before use.
171
+ */
172
+ abstract whenReady?(): Promise<void>;
173
+ }
174
+
175
+ /**
176
+ * Advice definition.
177
+ * Represents a single advice to be applied at a join point.
178
+ */
179
+ export declare interface Advice {
180
+ /** The type of advice */
181
+ type: AdviceType;
182
+ /** The pointcut expression */
183
+ pointcut: string;
184
+ /** The advice method to execute */
185
+ method: Function;
186
+ /** The transversal instance that owns this advice */
187
+ transversalInstance: any;
188
+ /** The priority of this advice (higher values execute first) */
189
+ priority: number;
190
+ /** Whether this advice is enabled */
191
+ enabled: boolean;
192
+ /** Optional role identifier extracted from pointcut */
193
+ role?: string;
194
+ /** Optional config specific to this advice (from @Affect) */
195
+ config?: Record<string, any>;
196
+ }
197
+
198
+ /**
199
+ * Advice execution context.
200
+ * Extends JoinPoint with the proceed function for around advice.
201
+ */
202
+ export declare interface AdviceContext extends JoinPoint {
203
+ /** Function to proceed to the next advice or the original method (for around advice) */
204
+ proceed?: () => any;
205
+ /** Optional config specific to this advice execution (from @Affect) */
206
+ config?: Record<string, any>;
207
+ }
208
+
209
+ /**
210
+ * Type of advice: before, after, or around.
211
+ */
212
+ export declare type AdviceType = 'before' | 'after' | 'around';
213
+
214
+ /**
215
+ * Method decorator to explicitly apply a transversal to a specific method.
216
+ * This bypasses the automatic pointcut matching and forces the transversal on this method.
217
+ *
218
+ * @example
219
+ * ```typescript
220
+ * @Assemblage()
221
+ * class UserService {
222
+ * @Affect(LoggingTransversal)
223
+ * create(data: any) { ... }
224
+ *
225
+ * @Affect(LoggingTransversal, { role: 'audit' })
226
+ * @Affect(ValidationTransversal)
227
+ * update(id: string, data: any) { ... }
228
+ * }
229
+ * ```
230
+ */
231
+ export declare function Affect(transversal: Identifier<any>, config?: Record<string, any>): MethodDecorator;
232
+
233
+ /**
234
+ * Configuration for explicitly applying an transversal to a method.
235
+ */
236
+ export declare interface AffectedMethodConfig {
237
+ /** The transversal class to apply */
238
+ transversal: Identifier<any>;
239
+ /** Optional role to filter which advices from the transversal should apply */
240
+ role?: string;
241
+ /** Optional configuration for the transversal */
242
+ config?: Record<string, any>;
243
+ }
244
+
245
+ /**
246
+ * Decorator to define an after advice.
247
+ * The advice will be executed after the target method completes.
248
+ * The advice receives the method result in context.result.
249
+ *
250
+ * @param pointcut The pointcut expression
251
+ * @param priority Optional priority (higher values execute first, default: 0)
252
+ * @returns Method decorator
253
+ *
254
+ * @example
255
+ * ```typescript
256
+ * @After('execution(UserService.*)')
257
+ * logAfter(context: AdviceContext) {
258
+ * console.log('Result:', context.result);
259
+ * }
260
+ * ```
261
+ */
262
+ export declare function After(pointcut: string, priority?: number): (target: any, propertyKey: string, _descriptor: PropertyDescriptor) => void;
263
+
264
+ /**
265
+ * Decorator to define an around advice.
266
+ * The advice wraps the target method and can control its execution.
267
+ * Call context.proceed() to continue to the next advice or the original method.
268
+ *
269
+ * @param pointcut The pointcut expression
270
+ * @param priority Optional priority (higher values execute first, default: 0)
271
+ * @returns Method decorator
272
+ *
273
+ * @example
274
+ * ```typescript
275
+ * @Around('execution(UserService.save)')
276
+ * async measureTime(context: AdviceContext) {
277
+ * const start = Date.now();
278
+ * const result = await context.proceed();
279
+ * console.log(`Took ${Date.now() - start}ms`);
280
+ * return result;
281
+ * }
282
+ * ```
283
+ */
284
+ export declare function Around(pointcut: string, priority?: number): (target: any, propertyKey: string, _descriptor: PropertyDescriptor) => void;
285
+
111
286
  /**
112
287
  * Mark a class as `Assemblage` and cache its definition.
113
288
  *
@@ -116,11 +291,16 @@ export declare abstract class AbstractListenerCollection {
116
291
  */
117
292
  export declare const Assemblage: <T>(definition?: AssemblageDefinition) => ClassDecorator;
118
293
 
294
+ /**
295
+ * Assemblage definition interface.
296
+ * Defines the configuration options for the @Assemblage decorator.
297
+ */
119
298
  export declare interface AssemblageDefinition {
120
- singleton?: false;
299
+ singleton?: boolean;
121
300
  events?: string[];
122
301
  inject?: Injection<unknown>[];
123
302
  use?: InstanceInjection<unknown>[];
303
+ engage?: TransversalInjection<unknown>[];
124
304
  tags?: string | string[];
125
305
  metadata?: Record<string, any>;
126
306
  global?: Record<string, any>;
@@ -226,6 +406,24 @@ export declare const Await: (property: string, interval?: number) => MethodDecor
226
406
  */
227
407
  declare type BaseInjection<T> = Tuple<[Abstract<T>, Concrete<T>]>;
228
408
 
409
+ /**
410
+ * Decorator to define a before advice.
411
+ * The advice will be executed before the target method.
412
+ *
413
+ * @param pointcut The pointcut expression (e.g., "execution(ClassName.methodName)")
414
+ * @param priority Optional priority (higher values execute first, default: 0)
415
+ * @returns Method decorator
416
+ *
417
+ * @example
418
+ * ```typescript
419
+ * @Before('execution(UserService.save)', 100)
420
+ * validateInput(context: AdviceContext) {
421
+ * // Validate before saving
422
+ * }
423
+ * ```
424
+ */
425
+ export declare function Before(pointcut: string, priority?: number): (target: any, propertyKey: string, _descriptor: PropertyDescriptor) => void;
426
+
229
427
  /**
230
428
  * Describes a buildable object.
231
429
  */
@@ -254,7 +452,7 @@ declare type ConcreteInjection<T> = Tuple<[Concrete<T>]>;
254
452
  * Injects the injectable's configuration object.
255
453
  * @returns A parameter decorator
256
454
  */
257
- export declare const Configuration: (param: void) => ParameterDecorator;
455
+ export declare const Configuration: (param?: void | undefined) => ParameterDecorator;
258
456
 
259
457
  /**
260
458
  * Injectable binds a concrete class to an abstract class as identifier
@@ -295,7 +493,7 @@ export declare type ConstructorDecoratorFunction = <T extends new (...args: any[
295
493
  * Injects the injectable's public context.
296
494
  * @returns A parameter decorator
297
495
  */
298
- export declare const Context: (param: void) => ParameterDecorator;
496
+ export declare const Context: (param?: void | undefined) => ParameterDecorator;
299
497
 
300
498
  /**
301
499
  * Create a custom decorator that adds a function called after the original constructor
@@ -388,13 +586,13 @@ declare interface DecoratorMetadata_2 {
388
586
  * Injects the injectable's definition object.
389
587
  * @returns A parameter decorator
390
588
  */
391
- export declare const Definition: (param: void) => ParameterDecorator;
589
+ export declare const Definition: (param?: void | undefined) => ParameterDecorator;
392
590
 
393
591
  /**
394
592
  * Injects the injectable's dispose function.
395
593
  * @returns A parameter decorator
396
594
  */
397
- export declare const Dispose: (param: void) => ParameterDecorator;
595
+ export declare const Dispose: (param?: void | undefined) => ParameterDecorator;
398
596
 
399
597
  /**
400
598
  * `EventChannel` extends `string`.
@@ -468,7 +666,7 @@ export declare const getParamValueKey: (decoratorName: string) => string;
468
666
  * @param identifier The identifier of the global object to inject
469
667
  * @returns A parameter decorator
470
668
  */
471
- declare const Global_2: (param: string | symbol) => ParameterDecorator;
669
+ declare const Global_2: (param?: string | symbol | undefined) => ParameterDecorator;
472
670
  export { Global_2 as Global }
473
671
 
474
672
  declare class HookManager {
@@ -511,6 +709,8 @@ declare class Injectable<T> implements AbstractInjectable<T> {
511
709
  private cachedInjections?;
512
710
  /** Cached objects to avoid repeated definition access. */
513
711
  private cachedObjects?;
712
+ /** Cached aspects to avoid repeated definition access. */
713
+ private cachedTransversals?;
514
714
  /** Cached tags to avoid repeated definition access. */
515
715
  private cachedTags?;
516
716
  /** Cached events to avoid repeated definition access. */
@@ -522,6 +722,18 @@ declare class Injectable<T> implements AbstractInjectable<T> {
522
722
  private builder;
523
723
  static of<TNew>(buildable: Buildable<TNew>, privateContext: AssemblerPrivateContext, publicContext: AssemblerContext): Injectable<TNew>;
524
724
  private constructor();
725
+ /**
726
+ * Converts an TransversalInjection to an Injection format for registration.
727
+ * Supports all TransversalInjection formats:
728
+ * - [Concrete]
729
+ * - [Concrete, config]
730
+ * - [Abstract, Concrete]
731
+ * - [Abstract, Concrete, config]
732
+ *
733
+ * @param transversal The transversal injection to convert
734
+ * @returns An Injection that can be registered in the context
735
+ */
736
+ private resolveTransversalToInjection;
525
737
  /**
526
738
  * Dispose the injectable by deleting its singleton if exists
527
739
  * and deleting all injectable's properties.
@@ -567,6 +779,10 @@ declare class Injectable<T> implements AbstractInjectable<T> {
567
779
  * Injectable assemblage's own objects (e.g. instances) injections defined in its decorator's definition.
568
780
  */
569
781
  get objects(): InstanceInjection<unknown>[];
782
+ /**
783
+ * Injectable assemblage's transversals defined in its decorator's definition.
784
+ */
785
+ get transversals(): any[];
570
786
  /**
571
787
  * Tags passed in assemblage's definition.
572
788
  */
@@ -630,6 +846,30 @@ declare type InstanceInjection<T> = Tuple<[Identifier<T> | string | symbol, T]>;
630
846
  */
631
847
  export declare const isAssemblage: <T>(target: Concrete<T>) => boolean;
632
848
 
849
+ /**
850
+ * Checks if a class is decorated with @Transversal
851
+ * @param target The class to check
852
+ * @returns True if the class is a transversal
853
+ */
854
+ export declare function isTransversal(target: any): boolean;
855
+
856
+ /**
857
+ * Join point information.
858
+ * Represents the point of execution where an advice is applied.
859
+ */
860
+ export declare interface JoinPoint {
861
+ /** The target instance */
862
+ target: any;
863
+ /** The name of the method being called */
864
+ methodName: string;
865
+ /** The arguments passed to the method */
866
+ args: any[];
867
+ /** The result of the method (for after advice) */
868
+ result?: any;
869
+ /** The error thrown by the method (if any) */
870
+ error?: any;
871
+ }
872
+
633
873
  declare interface LifecycleManager {
634
874
  prepareInitHook<T = AbstractAssemblage>(instance: T, configuration?: Record<string, any>): unknown[];
635
875
  }
@@ -773,7 +1013,7 @@ declare interface ObjectProvider {
773
1013
  * ) {}
774
1014
  * }
775
1015
  */
776
- export declare const Optional: (param: any) => ParameterDecorator;
1016
+ export declare const Optional: (param?: any) => ParameterDecorator;
777
1017
 
778
1018
  /**
779
1019
  * Configuration for creating a parameter decorator.
@@ -802,7 +1042,7 @@ export declare class ParameterDecoratorFactory {
802
1042
  * @param config The decorator configuration
803
1043
  * @returns A parameter decorator function
804
1044
  */
805
- static create<T>(config: ParameterDecoratorConfig): (param: T) => ParameterDecorator;
1045
+ static create<T>(config: ParameterDecoratorConfig): (param?: T | undefined) => ParameterDecorator;
806
1046
  /**
807
1047
  * Creates the actual decorator function.
808
1048
  */
@@ -885,11 +1125,192 @@ declare interface TagResolver {
885
1125
  tagged(...tags: string[]): any[];
886
1126
  }
887
1127
 
1128
+ /**
1129
+ * Decorator to define a class as an Transversal.
1130
+ * An Transversal is a specialized Assemblage that:
1131
+ * - Cannot have inject or use properties (must be empty)
1132
+ * - Receives dependencies through constructor parameters resolved from parent context
1133
+ * - Is singleton by default
1134
+ * - Cannot be combined with @Assemblage decorator
1135
+ *
1136
+ * @param definition Optional assemblage definition (inject and use will be ignored)
1137
+ * @returns Class decorator
1138
+ *
1139
+ * @example
1140
+ * ```typescript
1141
+ * @Transversal()
1142
+ * class LoggingTransversal extends AbstractTransversal {
1143
+ * constructor(private logger: Logger) {
1144
+ * super();
1145
+ * }
1146
+ *
1147
+ * @Before('execution(UserService.*)')
1148
+ * logBefore(context: AdviceContext) {
1149
+ * this.logger.log('Before:', context.methodName);
1150
+ * }
1151
+ * }
1152
+ * ```
1153
+ */
1154
+ export declare function Transversal(definition?: Omit<AssemblageDefinition, 'inject' | 'use'>): <T extends new (...args: any[]) => any>(target: T) => void | T;
1155
+
1156
+ /**
1157
+ * Transversal injection definition.
1158
+ * A transversal can be injected with or without configuration.
1159
+ * Supports both direct injection, abstraction pattern, and advanced configuration with roles.
1160
+ *
1161
+ * @example
1162
+ * ```typescript
1163
+ * // Without configuration (backward compatible)
1164
+ * transversals: [[LoggingTransversal]]
1165
+ *
1166
+ * // With configuration (backward compatible)
1167
+ * transversals: [[LoggingTransversal, { level: 'debug' }]]
1168
+ *
1169
+ * // With abstraction (like inject[])
1170
+ * transversals: [[AbstractLoggingTransversal, LoggingTransversal]]
1171
+ *
1172
+ * // With abstraction and configuration
1173
+ * transversals: [[AbstractLoggingTransversal, LoggingTransversal, { level: 'debug' }]]
1174
+ *
1175
+ * // NEW: With role and method filtering
1176
+ * transversals: [
1177
+ * {
1178
+ * transversal: LoggingTransversal,
1179
+ * role: 'method-entry',
1180
+ * methods: ['create', 'update']
1181
+ * },
1182
+ * {
1183
+ * transversal: LoggingTransversal, // Same transversal, different config
1184
+ * role: 'method-exit',
1185
+ * methods: '*'
1186
+ * }
1187
+ * ]
1188
+ *
1189
+ * // NEW: With abstraction and role configuration
1190
+ * transversals: [
1191
+ * {
1192
+ * transversal: [AbstractLoggingTransversal, LoggingTransversal],
1193
+ * role: 'audit',
1194
+ * methods: (name) => name.startsWith('delete')
1195
+ * }
1196
+ * ]
1197
+ * ```
1198
+ */
1199
+ declare type TransversalInjection<T> = [Identifier<T>] | [Identifier<T>, Record<string, any>] | [Abstract<T>, Concrete<T>] | [Abstract<T>, Concrete<T>, Record<string, any>];
1200
+
1201
+ /**
1202
+ * TransversalManager manages transversal registration and advice resolution.
1203
+ */
1204
+ export declare class TransversalManager {
1205
+ private context;
1206
+ private static instances;
1207
+ private static transversalInstances;
1208
+ private static transversalMetadata;
1209
+ private constructor();
1210
+ /**
1211
+ * Gets or creates an TransversalManager instance for a given context.
1212
+ *
1213
+ * @param context The assembler context
1214
+ * @returns The TransversalManager instance for this context
1215
+ */
1216
+ static getInstance(context: AssemblerContext): TransversalManager;
1217
+ /**
1218
+ * Gets the singleton transversal instance by class name.
1219
+ * CRITICAL: This ensures that aspects injected in constructors use the same instance as weaving.
1220
+ *
1221
+ * @param transversalClassName The name of the transversal class
1222
+ * @returns The transversal instance or undefined if not registered
1223
+ */
1224
+ getTransversalInstance(transversalClassName: string): any | undefined;
1225
+ /**
1226
+ * Clears all global transversal instances and metadata.
1227
+ * Useful for testing to reset state between tests.
1228
+ * WARNING: This will clear ALL aspects globally across all contexts.
1229
+ */
1230
+ static resetGlobalState(): void;
1231
+ /**
1232
+ * Registers a transversal from its injection definition.
1233
+ * The transversal is resolved from the context and its advices are extracted.
1234
+ *
1235
+ * - [TransversalClass] - Simple injection
1236
+ * - [TransversalClass, config] - With configuration
1237
+ * - [AbstractClass, ConcreteClass] - With abstraction
1238
+ * - [AbstractClass, ConcreteClass, config] - With abstraction and config
1239
+ *
1240
+ * @param transversalInjection The transversal injection tuple or config object
1241
+ * @param resolveContext Optional context to use for resolving the transversal (if different from manager's context)
1242
+ * @param assemblageIdentifier Optional identifier for the assemblage context (for configuration tracking)
1243
+ */
1244
+ registerTransversal(transversalInjection: TransversalInjection<any>, resolveContext?: AssemblerContext): void;
1245
+ /**
1246
+ * Extracts advices from a transversal class instance.
1247
+ * Advices are stored in definition.metadata.advices by the decorators.
1248
+ * Now also extracts role information from the pointcut.
1249
+ *
1250
+ * @param TransversalClass The transversal class
1251
+ * @param transversalInstance The transversal instance
1252
+ * @returns Array of extracted advices
1253
+ */
1254
+ private extractAdvices;
1255
+ /**
1256
+ * Gets applicable aspects for a target class.
1257
+ * Uses both global transversal metadata and local context configuration.
1258
+ *
1259
+ * @param concrete The target class
1260
+ * @param contextId Optional assemblage context identifier for local filtering
1261
+ * @returns Array of applicable transversal metadata with local configuration applied
1262
+ */
1263
+ getAspectsForTarget(concrete: Concrete<any>): TransversalMetadata[];
1264
+ /**
1265
+ * Checks if a transversal has any advice matching the target class.
1266
+ *
1267
+ * @param metadata The transversal metadata
1268
+ * @param concrete The target class
1269
+ * @returns True if any advice matches
1270
+ */
1271
+ private hasMatchingAdviceForClass;
1272
+ /**
1273
+ * Converts a wildcard pattern to a regular expression.
1274
+ * Reused from PointcutMatcher logic.
1275
+ *
1276
+ * @param pattern The pattern with wildcards
1277
+ * @returns A RegExp for matching
1278
+ */
1279
+ private patternToRegex;
1280
+ /**
1281
+ * Gets advices applicable to a specific join point.
1282
+ * Includes advices from:
1283
+ * 1. Aspects matched by pointcut regex (automatic)
1284
+ * 2. Aspects explicitly applied via @Affect decorator (manual)
1285
+ *
1286
+ * @param joinPoint The join point to match
1287
+ * @param aspects The aspects to search (from pointcut matching)
1288
+ * @param contextId Optional context identifier for method filtering
1289
+ * @param target Optional target instance (for @Affect lookup)
1290
+ * @param propertyKey Optional property key (for @Affect lookup)
1291
+ * @returns Array of applicable advices, sorted by priority (highest first)
1292
+ */
1293
+ getAdvicesForJoinPoint(joinPoint: JoinPoint, transversals: TransversalMetadata[], target?: any, propertyKey?: string | symbol): Advice[];
1294
+ }
1295
+
1296
+ /**
1297
+ * Transversal metadata.
1298
+ * Contains information about a registered transversal.
1299
+ */
1300
+ export declare interface TransversalMetadata {
1301
+ /** The assemblage definition of the transversal */
1302
+ definition: any;
1303
+ /** The advices defined in this transversal */
1304
+ advices: Advice[];
1305
+ /** The transversal instance */
1306
+ instance?: any;
1307
+ }
1308
+
888
1309
  /**
889
1310
  * Injects an object passed with `string` or `symbol` identifier.
890
1311
  * @param identifier The identifier of the object to inject
891
1312
  * @returns A parameter decorator
892
1313
  */
893
- export declare const Use: (param: string | symbol) => ParameterDecorator;
1314
+ export declare const Use: (param?: string | symbol | undefined) => ParameterDecorator;
894
1315
 
895
1316
  export { }
package/dist/index.js CHANGED
@@ -11,18 +11,22 @@ const abstract = require('./index7.js');
11
11
  const types = require('./index8.js');
12
12
  const listenerCollection_abstract = require('./index9.js');
13
13
  const eventManager_abstract = require('./index10.js');
14
- const _await = require('./index11.js');
15
- const indexFactory = require('./index12.js');
16
- const parameterDecoratorFactory = require('./index13.js');
17
- const context = require('./index14.js');
18
- const configuration = require('./index15.js');
19
- const definition = require('./index16.js');
20
- const dispose = require('./index17.js');
21
- const use = require('./index18.js');
22
- const global = require('./index19.js');
23
- const optional = require('./index20.js');
24
- const helpers$1 = require('./index21.js');
25
- const constructorDecorator = require('./index22.js');
14
+ const decorators = require('./index11.js');
15
+ const affect = require('./index12.js');
16
+ const transversalManager = require('./index13.js');
17
+ const abstract$1 = require('./index14.js');
18
+ const _await = require('./index15.js');
19
+ const indexFactory = require('./index16.js');
20
+ const parameterDecoratorFactory = require('./index17.js');
21
+ const context = require('./index18.js');
22
+ const configuration = require('./index19.js');
23
+ const definition = require('./index20.js');
24
+ const dispose = require('./index21.js');
25
+ const use = require('./index22.js');
26
+ const global = require('./index23.js');
27
+ const optional = require('./index24.js');
28
+ const helpers$1 = require('./index25.js');
29
+ const constructorDecorator = require('./index26.js');
26
30
 
27
31
 
28
32
 
@@ -38,6 +42,14 @@ exports.AbstractAssemblage = abstract.AbstractAssemblage;
38
42
  exports.AbstractAssembler = types.AbstractAssembler;
39
43
  exports.AbstractListenerCollection = listenerCollection_abstract.AbstractListenerCollection;
40
44
  exports.AbstractEventManager = eventManager_abstract.AbstractEventManager;
45
+ exports.After = decorators.After;
46
+ exports.Around = decorators.Around;
47
+ exports.Before = decorators.Before;
48
+ exports.Transversal = decorators.Transversal;
49
+ exports.isTransversal = decorators.isTransversal;
50
+ exports.Affect = affect.Affect;
51
+ exports.TransversalManager = transversalManager.TransversalManager;
52
+ exports.AbstractTransversal = abstract$1.AbstractTransversal;
41
53
  exports.Await = _await.Await;
42
54
  exports.createParamIndexDecorator = indexFactory.createParamIndexDecorator;
43
55
  exports.ParameterDecoratorFactory = parameterDecoratorFactory.ParameterDecoratorFactory;
package/dist/index.mjs CHANGED
@@ -7,15 +7,19 @@ export { AbstractAssemblage } from './index7.mjs';
7
7
  export { AbstractAssembler } from './index8.mjs';
8
8
  export { AbstractListenerCollection } from './index9.mjs';
9
9
  export { AbstractEventManager } from './index10.mjs';
10
- export { Await } from './index11.mjs';
11
- export { createParamIndexDecorator } from './index12.mjs';
12
- export { ParameterDecoratorFactory } from './index13.mjs';
13
- export { Context } from './index14.mjs';
14
- export { Configuration } from './index15.mjs';
15
- export { Definition } from './index16.mjs';
16
- export { Dispose } from './index17.mjs';
17
- export { Use, decorateUse } from './index18.mjs';
18
- export { Global, decorateGlobal } from './index19.mjs';
19
- export { Optional } from './index20.mjs';
20
- export { getDecoratedParametersIndexes, getParamIndexKey, getParamValueKey, getParameterIndexes, getParameterValues } from './index21.mjs';
21
- export { ConstructorDecorator, createConstructorDecorator } from './index22.mjs';
10
+ export { After, Around, Before, Transversal, isTransversal } from './index11.mjs';
11
+ export { Affect } from './index12.mjs';
12
+ export { TransversalManager } from './index13.mjs';
13
+ export { AbstractTransversal } from './index14.mjs';
14
+ export { Await } from './index15.mjs';
15
+ export { createParamIndexDecorator } from './index16.mjs';
16
+ export { ParameterDecoratorFactory } from './index17.mjs';
17
+ export { Context } from './index18.mjs';
18
+ export { Configuration } from './index19.mjs';
19
+ export { Definition } from './index20.mjs';
20
+ export { Dispose } from './index21.mjs';
21
+ export { Use, decorateUse } from './index22.mjs';
22
+ export { Global, decorateGlobal } from './index23.mjs';
23
+ export { Optional } from './index24.mjs';
24
+ export { getDecoratedParametersIndexes, getParamIndexKey, getParamValueKey, getParameterIndexes, getParameterValues } from './index25.mjs';
25
+ export { ConstructorDecorator, createConstructorDecorator } from './index26.mjs';