@illuma/core 1.3.0 → 1.4.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.
@@ -1,4 +1,4 @@
1
- import { N as NodeToken, M as MultiNodeToken, a as NodeBase } from './types-5mX9F_24.js';
1
+ import { N as NodeToken, M as MultiNodeToken, a as NodeBase } from './types-zryyqrii.cjs';
2
2
 
3
3
  /**
4
4
  * Represents a single dependency injection point in the dependency graph.
@@ -29,6 +29,16 @@ interface iContextScanner {
29
29
  scan(factory: any): Set<iInjectionNode<any>>;
30
30
  }
31
31
 
32
+ /**
33
+ * Instantiation parameters for creating a new instance of a type `T`.
34
+ * @template T - The type of the instance to be created.
35
+ */
36
+ interface iInstantiationParams<T = unknown> {
37
+ readonly token: NodeBase<T>;
38
+ readonly factory: () => T;
39
+ }
40
+ type iMiddleware<T = unknown> = (params: iInstantiationParams<T>, next: (params: iInstantiationParams<T>) => T) => T;
41
+
32
42
  declare class ProtoNodeSingle<T = any> {
33
43
  readonly token: NodeToken<T>;
34
44
  readonly injections: Set<iInjectionNode<any>>;
@@ -67,7 +77,7 @@ declare class TreeNodeSingle<T = any> {
67
77
  constructor(proto: ProtoNodeSingle<T>);
68
78
  addDependency(node: TreeNode<any>): void;
69
79
  collectPool(pool: InjectionPool): void;
70
- instantiate(pool?: InjectionPool): void;
80
+ instantiate(pool?: InjectionPool, middlewares?: iMiddleware[]): void;
71
81
  toString(): string;
72
82
  }
73
83
  declare class TreeNodeTransparent<T = any> {
@@ -81,7 +91,7 @@ declare class TreeNodeTransparent<T = any> {
81
91
  constructor(proto: ProtoNodeTransparent<T>);
82
92
  addDependency(node: TreeNode<any>): void;
83
93
  collectPool(pool: InjectionPool): void;
84
- instantiate(pool?: InjectionPool): void;
94
+ instantiate(pool?: InjectionPool, middlewares?: iMiddleware[]): void;
85
95
  toString(): string;
86
96
  }
87
97
  declare class TreeNodeMulti<T = any> {
@@ -92,7 +102,7 @@ declare class TreeNodeMulti<T = any> {
92
102
  allocations: number;
93
103
  constructor(proto: ProtoNodeMulti<T>);
94
104
  collectPool(pool: InjectionPool): void;
95
- instantiate(pool?: InjectionPool): void;
105
+ instantiate(pool?: InjectionPool, middlewares?: iMiddleware[]): void;
96
106
  addDependency(...nodes: TreeNode[]): void;
97
107
  toString(): string;
98
108
  }
@@ -117,6 +127,7 @@ interface iDiagnosticsModule {
117
127
  declare abstract class Illuma {
118
128
  private static readonly _diagnostics;
119
129
  private static readonly _scanners;
130
+ protected static readonly _middlewares: iMiddleware[];
120
131
  /** @internal */
121
132
  static get contextScanners(): ReadonlyArray<iContextScanner>;
122
133
  /**
@@ -133,7 +144,17 @@ declare abstract class Illuma {
133
144
  * @param scanner - The context scanner instance to add
134
145
  */
135
146
  static extendContextScanner(scanner: iContextScanner): void;
147
+ /**
148
+ * Registers a global middleware to be applied during instance creation.
149
+ * Typically used for cross-cutting concerns like logging, profiling, or custom instantiation logic.
150
+ * Function should accept instantiation parameters and a `next` function to proceed with the next middleware or actual instantiation.
151
+ *
152
+ * @param m - The middleware function to register
153
+ */
154
+ static registerGlobalMiddleware(m: iMiddleware): void;
155
+ protected readonly middlewares: iMiddleware[];
156
+ registerMiddleware(m: iMiddleware): void;
136
157
  protected static onReport(report: iDiagnosticsReport): void;
137
158
  }
138
159
 
139
- export { Illuma as I, type TreeNode as T, type iDiagnosticsModule as a, type iDiagnosticsReport as b, type iContextScanner as c, type iInjectionNode as i };
160
+ export { Illuma as I, type TreeNode as T, type iInjectionNode as a, type iDiagnosticsModule as b, type iDiagnosticsReport as c, type iContextScanner as d, type iInstantiationParams as e, type iMiddleware as i };
package/dist/plugins.cjs CHANGED
@@ -33,6 +33,7 @@ var Illuma = class _Illuma {
33
33
  }
34
34
  static _diagnostics = [];
35
35
  static _scanners = [];
36
+ static _middlewares = [];
36
37
  /** @internal */
37
38
  static get contextScanners() {
38
39
  return _Illuma._scanners;
@@ -55,6 +56,20 @@ var Illuma = class _Illuma {
55
56
  static extendContextScanner(scanner) {
56
57
  _Illuma._scanners.push(scanner);
57
58
  }
59
+ /**
60
+ * Registers a global middleware to be applied during instance creation.
61
+ * Typically used for cross-cutting concerns like logging, profiling, or custom instantiation logic.
62
+ * Function should accept instantiation parameters and a `next` function to proceed with the next middleware or actual instantiation.
63
+ *
64
+ * @param m - The middleware function to register
65
+ */
66
+ static registerGlobalMiddleware(m) {
67
+ _Illuma._middlewares.push(m);
68
+ }
69
+ middlewares = [];
70
+ registerMiddleware(m) {
71
+ this.middlewares.push(m);
72
+ }
58
73
  static onReport(report) {
59
74
  for (const diag of _Illuma._diagnostics) diag.onReport(report);
60
75
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/plugins.ts","../src/lib/plugins/core/plugin-container.ts","../src/lib/plugins/diagnostics/default-impl.ts"],"sourcesContent":["export * from \"./lib/plugins\";\n","import type { iContextScanner } from \"../context\";\nimport type { iDiagnosticsModule, iDiagnosticsReport } from \"../diagnostics/types\";\n\n/**\n * Global plugin container for managing core plugins such as diagnostics and context scanners.\n */\nexport abstract class Illuma {\n private static readonly _diagnostics = [] as iDiagnosticsModule[];\n private static readonly _scanners = [] as iContextScanner[];\n\n /** @internal */\n public static get contextScanners(): ReadonlyArray<iContextScanner> {\n return Illuma._scanners;\n }\n\n /**\n * Extends the diagnostics with a new diagnostics module.\n * These will be run on diagnostics reports after container bootstrap.\n *\n * @param m - The diagnostics module instance to add\n */\n public static extendDiagnostics(m: iDiagnosticsModule): void {\n Illuma._diagnostics.push(m);\n }\n\n /**\n * Extends the context scanners with a new context scanner.\n * These will be run in injection context scans to detect additional injections (alongside `nodeInject` calls).\n *\n * @param scanner - The context scanner instance to add\n */\n public static extendContextScanner(scanner: iContextScanner): void {\n Illuma._scanners.push(scanner);\n }\n\n protected static onReport(report: iDiagnosticsReport): void {\n for (const diag of Illuma._diagnostics) diag.onReport(report);\n }\n}\n","import type { iDiagnosticsModule, iDiagnosticsReport } from \"./types\";\n\nexport class DiagnosticsDefaultReporter implements iDiagnosticsModule {\n public onReport(report: iDiagnosticsReport): void {\n console.log(\"[Illuma] 🧹 Diagnostics:\");\n console.log(` Total: ${report.totalNodes} node(s)`);\n console.log(` ${report.unusedNodes.length} were not used while bootstrap:`);\n for (const node of report.unusedNodes) console.log(` - ${node.toString()}`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;ACMO,IAAeA,SAAf,MAAeA,QAAAA;EAHtB,OAGsBA;;;EACpB,OAAwBC,eAAe,CAAA;EACvC,OAAwBC,YAAY,CAAA;;EAGpC,WAAkBC,kBAAkD;AAClE,WAAOH,QAAOE;EAChB;;;;;;;EAQA,OAAcE,kBAAkBC,GAA6B;AAC3DL,YAAOC,aAAaK,KAAKD,CAAAA;EAC3B;;;;;;;EAQA,OAAcE,qBAAqBC,SAAgC;AACjER,YAAOE,UAAUI,KAAKE,OAAAA;EACxB;EAEA,OAAiBC,SAASC,QAAkC;AAC1D,eAAWC,QAAQX,QAAOC,aAAcU,MAAKF,SAASC,MAAAA;EACxD;AACF;;;ACpCO,IAAME,6BAAN,MAAMA;EAAb,OAAaA;;;EACJC,SAASC,QAAkC;AAChDC,YAAQC,IAAI,iCAAA;AACZD,YAAQC,IAAI,YAAYF,OAAOG,UAAU,UAAU;AACnDF,YAAQC,IAAI,KAAKF,OAAOI,YAAYC,MAAM,iCAAiC;AAC3E,eAAWC,QAAQN,OAAOI,YAAaH,SAAQC,IAAI,SAASI,KAAKC,SAAQ,CAAA,EAAI;EAC/E;AACF;","names":["Illuma","_diagnostics","_scanners","contextScanners","extendDiagnostics","m","push","extendContextScanner","scanner","onReport","report","diag","DiagnosticsDefaultReporter","onReport","report","console","log","totalNodes","unusedNodes","length","node","toString"]}
1
+ {"version":3,"sources":["../src/plugins.ts","../src/lib/plugins/core/plugin-container.ts","../src/lib/plugins/diagnostics/default-impl.ts"],"sourcesContent":["export * from \"./lib/plugins\";\n","import type { iContextScanner } from \"../context\";\nimport type { iDiagnosticsModule, iDiagnosticsReport } from \"../diagnostics/types\";\nimport type { iMiddleware } from \"../middlewares/types\";\n\n/**\n * Global plugin container for managing core plugins such as diagnostics and context scanners.\n */\nexport abstract class Illuma {\n private static readonly _diagnostics = [] as iDiagnosticsModule[];\n private static readonly _scanners = [] as iContextScanner[];\n protected static readonly _middlewares = [] as iMiddleware[];\n\n /** @internal */\n public static get contextScanners(): ReadonlyArray<iContextScanner> {\n return Illuma._scanners;\n }\n\n /**\n * Extends the diagnostics with a new diagnostics module.\n * These will be run on diagnostics reports after container bootstrap.\n *\n * @param m - The diagnostics module instance to add\n */\n public static extendDiagnostics(m: iDiagnosticsModule): void {\n Illuma._diagnostics.push(m);\n }\n\n /**\n * Extends the context scanners with a new context scanner.\n * These will be run in injection context scans to detect additional injections (alongside `nodeInject` calls).\n *\n * @param scanner - The context scanner instance to add\n */\n public static extendContextScanner(scanner: iContextScanner): void {\n Illuma._scanners.push(scanner);\n }\n\n /**\n * Registers a global middleware to be applied during instance creation.\n * Typically used for cross-cutting concerns like logging, profiling, or custom instantiation logic.\n * Function should accept instantiation parameters and a `next` function to proceed with the next middleware or actual instantiation.\n *\n * @param m - The middleware function to register\n */\n public static registerGlobalMiddleware(m: iMiddleware): void {\n Illuma._middlewares.push(m);\n }\n\n protected readonly middlewares = [] as iMiddleware[];\n public registerMiddleware(m: iMiddleware): void {\n this.middlewares.push(m);\n }\n\n protected static onReport(report: iDiagnosticsReport): void {\n for (const diag of Illuma._diagnostics) diag.onReport(report);\n }\n}\n","import type { iDiagnosticsModule, iDiagnosticsReport } from \"./types\";\n\nexport class DiagnosticsDefaultReporter implements iDiagnosticsModule {\n public onReport(report: iDiagnosticsReport): void {\n console.log(\"[Illuma] 🧹 Diagnostics:\");\n console.log(` Total: ${report.totalNodes} node(s)`);\n console.log(` ${report.unusedNodes.length} were not used while bootstrap:`);\n for (const node of report.unusedNodes) console.log(` - ${node.toString()}`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;ACOO,IAAeA,SAAf,MAAeA,QAAAA;EAHtB,OAGsBA;;;EACpB,OAAwBC,eAAe,CAAA;EACvC,OAAwBC,YAAY,CAAA;EACpC,OAA0BC,eAAe,CAAA;;EAGzC,WAAkBC,kBAAkD;AAClE,WAAOJ,QAAOE;EAChB;;;;;;;EAQA,OAAcG,kBAAkBC,GAA6B;AAC3DN,YAAOC,aAAaM,KAAKD,CAAAA;EAC3B;;;;;;;EAQA,OAAcE,qBAAqBC,SAAgC;AACjET,YAAOE,UAAUK,KAAKE,OAAAA;EACxB;;;;;;;;EASA,OAAcC,yBAAyBJ,GAAsB;AAC3DN,YAAOG,aAAaI,KAAKD,CAAAA;EAC3B;EAEmBK,cAAc,CAAA;EAC1BC,mBAAmBN,GAAsB;AAC9C,SAAKK,YAAYJ,KAAKD,CAAAA;EACxB;EAEA,OAAiBO,SAASC,QAAkC;AAC1D,eAAWC,QAAQf,QAAOC,aAAcc,MAAKF,SAASC,MAAAA;EACxD;AACF;;;ACtDO,IAAME,6BAAN,MAAMA;EAAb,OAAaA;;;EACJC,SAASC,QAAkC;AAChDC,YAAQC,IAAI,iCAAA;AACZD,YAAQC,IAAI,YAAYF,OAAOG,UAAU,UAAU;AACnDF,YAAQC,IAAI,KAAKF,OAAOI,YAAYC,MAAM,iCAAiC;AAC3E,eAAWC,QAAQN,OAAOI,YAAaH,SAAQC,IAAI,SAASI,KAAKC,SAAQ,CAAA,EAAI;EAC/E;AACF;","names":["Illuma","_diagnostics","_scanners","_middlewares","contextScanners","extendDiagnostics","m","push","extendContextScanner","scanner","registerGlobalMiddleware","middlewares","registerMiddleware","onReport","report","diag","DiagnosticsDefaultReporter","onReport","report","console","log","totalNodes","unusedNodes","length","node","toString"]}
@@ -1,6 +1,6 @@
1
- import { a as iDiagnosticsModule, b as iDiagnosticsReport } from './plugin-container-DkECHcvu.cjs';
2
- export { I as Illuma, c as iContextScanner } from './plugin-container-DkECHcvu.cjs';
3
- import './types-5mX9F_24.cjs';
1
+ import { b as iDiagnosticsModule, c as iDiagnosticsReport } from './plugin-container-CXuie89o.cjs';
2
+ export { I as Illuma, d as iContextScanner, e as iInstantiationParams, i as iMiddleware } from './plugin-container-CXuie89o.cjs';
3
+ import './types-zryyqrii.cjs';
4
4
 
5
5
  declare class DiagnosticsDefaultReporter implements iDiagnosticsModule {
6
6
  onReport(report: iDiagnosticsReport): void;
package/dist/plugins.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { a as iDiagnosticsModule, b as iDiagnosticsReport } from './plugin-container-GF2OqmiJ.js';
2
- export { I as Illuma, c as iContextScanner } from './plugin-container-GF2OqmiJ.js';
3
- import './types-5mX9F_24.js';
1
+ import { b as iDiagnosticsModule, c as iDiagnosticsReport } from './plugin-container-CG_kjb35.js';
2
+ export { I as Illuma, d as iContextScanner, e as iInstantiationParams, i as iMiddleware } from './plugin-container-CG_kjb35.js';
3
+ import './types-zryyqrii.js';
4
4
 
5
5
  declare class DiagnosticsDefaultReporter implements iDiagnosticsModule {
6
6
  onReport(report: iDiagnosticsReport): void;
package/dist/plugins.js CHANGED
@@ -8,6 +8,7 @@ var Illuma = class _Illuma {
8
8
  }
9
9
  static _diagnostics = [];
10
10
  static _scanners = [];
11
+ static _middlewares = [];
11
12
  /** @internal */
12
13
  static get contextScanners() {
13
14
  return _Illuma._scanners;
@@ -30,6 +31,20 @@ var Illuma = class _Illuma {
30
31
  static extendContextScanner(scanner) {
31
32
  _Illuma._scanners.push(scanner);
32
33
  }
34
+ /**
35
+ * Registers a global middleware to be applied during instance creation.
36
+ * Typically used for cross-cutting concerns like logging, profiling, or custom instantiation logic.
37
+ * Function should accept instantiation parameters and a `next` function to proceed with the next middleware or actual instantiation.
38
+ *
39
+ * @param m - The middleware function to register
40
+ */
41
+ static registerGlobalMiddleware(m) {
42
+ _Illuma._middlewares.push(m);
43
+ }
44
+ middlewares = [];
45
+ registerMiddleware(m) {
46
+ this.middlewares.push(m);
47
+ }
33
48
  static onReport(report) {
34
49
  for (const diag of _Illuma._diagnostics) diag.onReport(report);
35
50
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/plugins/core/plugin-container.ts","../src/lib/plugins/diagnostics/default-impl.ts"],"sourcesContent":["import type { iContextScanner } from \"../context\";\nimport type { iDiagnosticsModule, iDiagnosticsReport } from \"../diagnostics/types\";\n\n/**\n * Global plugin container for managing core plugins such as diagnostics and context scanners.\n */\nexport abstract class Illuma {\n private static readonly _diagnostics = [] as iDiagnosticsModule[];\n private static readonly _scanners = [] as iContextScanner[];\n\n /** @internal */\n public static get contextScanners(): ReadonlyArray<iContextScanner> {\n return Illuma._scanners;\n }\n\n /**\n * Extends the diagnostics with a new diagnostics module.\n * These will be run on diagnostics reports after container bootstrap.\n *\n * @param m - The diagnostics module instance to add\n */\n public static extendDiagnostics(m: iDiagnosticsModule): void {\n Illuma._diagnostics.push(m);\n }\n\n /**\n * Extends the context scanners with a new context scanner.\n * These will be run in injection context scans to detect additional injections (alongside `nodeInject` calls).\n *\n * @param scanner - The context scanner instance to add\n */\n public static extendContextScanner(scanner: iContextScanner): void {\n Illuma._scanners.push(scanner);\n }\n\n protected static onReport(report: iDiagnosticsReport): void {\n for (const diag of Illuma._diagnostics) diag.onReport(report);\n }\n}\n","import type { iDiagnosticsModule, iDiagnosticsReport } from \"./types\";\n\nexport class DiagnosticsDefaultReporter implements iDiagnosticsModule {\n public onReport(report: iDiagnosticsReport): void {\n console.log(\"[Illuma] 🧹 Diagnostics:\");\n console.log(` Total: ${report.totalNodes} node(s)`);\n console.log(` ${report.unusedNodes.length} were not used while bootstrap:`);\n for (const node of report.unusedNodes) console.log(` - ${node.toString()}`);\n }\n}\n"],"mappings":";;;;AAMO,IAAeA,SAAf,MAAeA,QAAAA;EAHtB,OAGsBA;;;EACpB,OAAwBC,eAAe,CAAA;EACvC,OAAwBC,YAAY,CAAA;;EAGpC,WAAkBC,kBAAkD;AAClE,WAAOH,QAAOE;EAChB;;;;;;;EAQA,OAAcE,kBAAkBC,GAA6B;AAC3DL,YAAOC,aAAaK,KAAKD,CAAAA;EAC3B;;;;;;;EAQA,OAAcE,qBAAqBC,SAAgC;AACjER,YAAOE,UAAUI,KAAKE,OAAAA;EACxB;EAEA,OAAiBC,SAASC,QAAkC;AAC1D,eAAWC,QAAQX,QAAOC,aAAcU,MAAKF,SAASC,MAAAA;EACxD;AACF;;;ACpCO,IAAME,6BAAN,MAAMA;EAAb,OAAaA;;;EACJC,SAASC,QAAkC;AAChDC,YAAQC,IAAI,iCAAA;AACZD,YAAQC,IAAI,YAAYF,OAAOG,UAAU,UAAU;AACnDF,YAAQC,IAAI,KAAKF,OAAOI,YAAYC,MAAM,iCAAiC;AAC3E,eAAWC,QAAQN,OAAOI,YAAaH,SAAQC,IAAI,SAASI,KAAKC,SAAQ,CAAA,EAAI;EAC/E;AACF;","names":["Illuma","_diagnostics","_scanners","contextScanners","extendDiagnostics","m","push","extendContextScanner","scanner","onReport","report","diag","DiagnosticsDefaultReporter","onReport","report","console","log","totalNodes","unusedNodes","length","node","toString"]}
1
+ {"version":3,"sources":["../src/lib/plugins/core/plugin-container.ts","../src/lib/plugins/diagnostics/default-impl.ts"],"sourcesContent":["import type { iContextScanner } from \"../context\";\nimport type { iDiagnosticsModule, iDiagnosticsReport } from \"../diagnostics/types\";\nimport type { iMiddleware } from \"../middlewares/types\";\n\n/**\n * Global plugin container for managing core plugins such as diagnostics and context scanners.\n */\nexport abstract class Illuma {\n private static readonly _diagnostics = [] as iDiagnosticsModule[];\n private static readonly _scanners = [] as iContextScanner[];\n protected static readonly _middlewares = [] as iMiddleware[];\n\n /** @internal */\n public static get contextScanners(): ReadonlyArray<iContextScanner> {\n return Illuma._scanners;\n }\n\n /**\n * Extends the diagnostics with a new diagnostics module.\n * These will be run on diagnostics reports after container bootstrap.\n *\n * @param m - The diagnostics module instance to add\n */\n public static extendDiagnostics(m: iDiagnosticsModule): void {\n Illuma._diagnostics.push(m);\n }\n\n /**\n * Extends the context scanners with a new context scanner.\n * These will be run in injection context scans to detect additional injections (alongside `nodeInject` calls).\n *\n * @param scanner - The context scanner instance to add\n */\n public static extendContextScanner(scanner: iContextScanner): void {\n Illuma._scanners.push(scanner);\n }\n\n /**\n * Registers a global middleware to be applied during instance creation.\n * Typically used for cross-cutting concerns like logging, profiling, or custom instantiation logic.\n * Function should accept instantiation parameters and a `next` function to proceed with the next middleware or actual instantiation.\n *\n * @param m - The middleware function to register\n */\n public static registerGlobalMiddleware(m: iMiddleware): void {\n Illuma._middlewares.push(m);\n }\n\n protected readonly middlewares = [] as iMiddleware[];\n public registerMiddleware(m: iMiddleware): void {\n this.middlewares.push(m);\n }\n\n protected static onReport(report: iDiagnosticsReport): void {\n for (const diag of Illuma._diagnostics) diag.onReport(report);\n }\n}\n","import type { iDiagnosticsModule, iDiagnosticsReport } from \"./types\";\n\nexport class DiagnosticsDefaultReporter implements iDiagnosticsModule {\n public onReport(report: iDiagnosticsReport): void {\n console.log(\"[Illuma] 🧹 Diagnostics:\");\n console.log(` Total: ${report.totalNodes} node(s)`);\n console.log(` ${report.unusedNodes.length} were not used while bootstrap:`);\n for (const node of report.unusedNodes) console.log(` - ${node.toString()}`);\n }\n}\n"],"mappings":";;;;AAOO,IAAeA,SAAf,MAAeA,QAAAA;EAHtB,OAGsBA;;;EACpB,OAAwBC,eAAe,CAAA;EACvC,OAAwBC,YAAY,CAAA;EACpC,OAA0BC,eAAe,CAAA;;EAGzC,WAAkBC,kBAAkD;AAClE,WAAOJ,QAAOE;EAChB;;;;;;;EAQA,OAAcG,kBAAkBC,GAA6B;AAC3DN,YAAOC,aAAaM,KAAKD,CAAAA;EAC3B;;;;;;;EAQA,OAAcE,qBAAqBC,SAAgC;AACjET,YAAOE,UAAUK,KAAKE,OAAAA;EACxB;;;;;;;;EASA,OAAcC,yBAAyBJ,GAAsB;AAC3DN,YAAOG,aAAaI,KAAKD,CAAAA;EAC3B;EAEmBK,cAAc,CAAA;EAC1BC,mBAAmBN,GAAsB;AAC9C,SAAKK,YAAYJ,KAAKD,CAAAA;EACxB;EAEA,OAAiBO,SAASC,QAAkC;AAC1D,eAAWC,QAAQf,QAAOC,aAAcc,MAAKF,SAASC,MAAAA;EACxD;AACF;;;ACtDO,IAAME,6BAAN,MAAMA;EAAb,OAAaA;;;EACJC,SAASC,QAAkC;AAChDC,YAAQC,IAAI,iCAAA;AACZD,YAAQC,IAAI,YAAYF,OAAOG,UAAU,UAAU;AACnDF,YAAQC,IAAI,KAAKF,OAAOI,YAAYC,MAAM,iCAAiC;AAC3E,eAAWC,QAAQN,OAAOI,YAAaH,SAAQC,IAAI,SAASI,KAAKC,SAAQ,CAAA,EAAI;EAC/E;AACF;","names":["Illuma","_diagnostics","_scanners","_middlewares","contextScanners","extendDiagnostics","m","push","extendContextScanner","scanner","registerGlobalMiddleware","middlewares","registerMiddleware","onReport","report","diag","DiagnosticsDefaultReporter","onReport","report","console","log","totalNodes","unusedNodes","length","node","toString"]}
package/dist/testkit.cjs CHANGED
@@ -226,6 +226,7 @@ var Illuma = class _Illuma {
226
226
  }
227
227
  static _diagnostics = [];
228
228
  static _scanners = [];
229
+ static _middlewares = [];
229
230
  /** @internal */
230
231
  static get contextScanners() {
231
232
  return _Illuma._scanners;
@@ -248,6 +249,20 @@ var Illuma = class _Illuma {
248
249
  static extendContextScanner(scanner) {
249
250
  _Illuma._scanners.push(scanner);
250
251
  }
252
+ /**
253
+ * Registers a global middleware to be applied during instance creation.
254
+ * Typically used for cross-cutting concerns like logging, profiling, or custom instantiation logic.
255
+ * Function should accept instantiation parameters and a `next` function to proceed with the next middleware or actual instantiation.
256
+ *
257
+ * @param m - The middleware function to register
258
+ */
259
+ static registerGlobalMiddleware(m) {
260
+ _Illuma._middlewares.push(m);
261
+ }
262
+ middlewares = [];
263
+ registerMiddleware(m) {
264
+ this.middlewares.push(m);
265
+ }
251
266
  static onReport(report) {
252
267
  for (const diag of _Illuma._diagnostics) diag.onReport(report);
253
268
  }
@@ -452,7 +467,34 @@ function isNotTransparentProto(proto) {
452
467
  }
453
468
  __name(isNotTransparentProto, "isNotTransparentProto");
454
469
 
470
+ // src/lib/utils/injector.ts
471
+ var InjectorImpl = class {
472
+ static {
473
+ __name(this, "InjectorImpl");
474
+ }
475
+ container;
476
+ constructor(container) {
477
+ this.container = container;
478
+ }
479
+ get(token) {
480
+ return this.container.get(token);
481
+ }
482
+ produce(fn) {
483
+ return this.container.produce(fn);
484
+ }
485
+ };
486
+ var Injector = new NodeToken("Injector");
487
+
455
488
  // src/lib/provider/tree-node.ts
489
+ function runMiddlewares(middlewares, params) {
490
+ const ms = middlewares;
491
+ const next = /* @__PURE__ */ __name((i, current) => {
492
+ if (i >= ms.length) return current.factory();
493
+ return ms[i](current, (nextParams) => next(i + 1, nextParams));
494
+ }, "next");
495
+ return next(0, params);
496
+ }
497
+ __name(runMiddlewares, "runMiddlewares");
456
498
  function retrieverFactory(node, deps, transparentDeps) {
457
499
  return (token, optional) => {
458
500
  const depNode = deps.get(token);
@@ -470,10 +512,12 @@ var TreeRootNode = class {
470
512
  __name(this, "TreeRootNode");
471
513
  }
472
514
  instant;
515
+ middlewares;
473
516
  _deps = /* @__PURE__ */ new Set();
474
517
  _treePool = /* @__PURE__ */ new WeakMap();
475
- constructor(instant = true) {
518
+ constructor(instant = true, middlewares = []) {
476
519
  this.instant = instant;
520
+ this.middlewares = middlewares;
477
521
  }
478
522
  get dependencies() {
479
523
  return this._deps;
@@ -484,14 +528,14 @@ var TreeRootNode = class {
484
528
  build() {
485
529
  for (const dep of this._deps) {
486
530
  if ("token" in dep.proto) this._treePool.set(dep.proto.token, dep);
487
- if (this.instant) dep.instantiate(this._treePool);
531
+ if (this.instant) dep.instantiate(this._treePool, this.middlewares);
488
532
  else dep.collectPool(this._treePool);
489
533
  }
490
534
  }
491
535
  find(token) {
492
536
  const node = this._treePool.get(token);
493
537
  if (!node) return null;
494
- if (!this.instant) node.instantiate(this._treePool);
538
+ if (!this.instant) node.instantiate(this._treePool, this.middlewares);
495
539
  return node;
496
540
  }
497
541
  toString() {
@@ -516,6 +560,10 @@ var TreeNodeSingle = class {
516
560
  }
517
561
  constructor(proto) {
518
562
  this.proto = proto;
563
+ if (proto.token === Injector) {
564
+ this._instance = proto.factory();
565
+ this._resolved = true;
566
+ }
519
567
  }
520
568
  addDependency(node) {
521
569
  if (node instanceof TreeNodeTransparent) this._transparent.add(node);
@@ -527,14 +575,18 @@ var TreeNodeSingle = class {
527
575
  for (const dep of this._transparent) dep.collectPool(pool);
528
576
  pool.set(this.proto.token, this);
529
577
  }
530
- instantiate(pool) {
578
+ instantiate(pool, middlewares = []) {
531
579
  if (this._resolved) return;
532
- for (const node of this._deps.values()) node.instantiate(pool);
533
- for (const dep of this._transparent) dep.instantiate(pool);
580
+ for (const node of this._deps.values()) node.instantiate(pool, middlewares);
581
+ for (const dep of this._transparent) dep.instantiate(pool, middlewares);
534
582
  const retriever = retrieverFactory(this.proto.token, this._deps, this._transparent);
535
583
  const factory = this.proto.factory ?? this.proto.token.opts?.factory;
536
584
  if (!factory) throw InjectionError.notFound(this.proto.token);
537
- this._instance = InjectionContext.instantiate(factory, retriever);
585
+ const contextFactory = /* @__PURE__ */ __name(() => InjectionContext.instantiate(factory, retriever), "contextFactory");
586
+ this._instance = runMiddlewares(middlewares, {
587
+ token: this.proto.token,
588
+ factory: contextFactory
589
+ });
538
590
  this._resolved = true;
539
591
  if (pool) pool.set(this.proto.token, this);
540
592
  }
@@ -568,12 +620,16 @@ var TreeNodeTransparent = class _TreeNodeTransparent {
568
620
  for (const node of this._deps.values()) node.collectPool(pool);
569
621
  for (const dep of this._transparent) dep.collectPool(pool);
570
622
  }
571
- instantiate(pool) {
623
+ instantiate(pool, middlewares = []) {
572
624
  if (this._resolved) return;
573
- for (const dep of this._transparent) dep.instantiate(pool);
574
- for (const node of this._deps.values()) node.instantiate(pool);
625
+ for (const dep of this._transparent) dep.instantiate(pool, middlewares);
626
+ for (const node of this._deps.values()) node.instantiate(pool, middlewares);
575
627
  const retriever = retrieverFactory(this.proto.parent.token, this._deps, this._transparent);
576
- this._instance = InjectionContext.instantiate(this.proto.factory, retriever);
628
+ const refFactory = /* @__PURE__ */ __name(() => InjectionContext.instantiate(this.proto.factory, retriever), "refFactory");
629
+ this._instance = runMiddlewares(middlewares, {
630
+ token: this.proto.parent.token,
631
+ factory: refFactory
632
+ });
577
633
  this._resolved = true;
578
634
  }
579
635
  toString() {
@@ -596,10 +652,10 @@ var TreeNodeMulti = class _TreeNodeMulti {
596
652
  for (const dep of this._deps) dep.collectPool(pool);
597
653
  pool.set(this.proto.token, this);
598
654
  }
599
- instantiate(pool) {
655
+ instantiate(pool, middlewares = []) {
600
656
  if (this._resolved) return;
601
657
  for (const dep of this._deps) {
602
- dep.instantiate(pool);
658
+ dep.instantiate(pool, middlewares);
603
659
  if (dep instanceof TreeNodeSingle) {
604
660
  this.instance.push(dep.instance);
605
661
  } else if (dep instanceof _TreeNodeMulti) {
@@ -754,24 +810,6 @@ function resolveTreeNode(rootProto, cache, singleNodes, multiNodes, upstreamGett
754
810
  }
755
811
  __name(resolveTreeNode, "resolveTreeNode");
756
812
 
757
- // src/lib/utils/injector.ts
758
- var InjectorImpl = class {
759
- static {
760
- __name(this, "InjectorImpl");
761
- }
762
- container;
763
- constructor(container) {
764
- this.container = container;
765
- }
766
- get(token) {
767
- return this.container.get(token);
768
- }
769
- produce(fn) {
770
- return this.container.produce(fn);
771
- }
772
- };
773
- var Injector = new NodeToken("Injector");
774
-
775
813
  // src/lib/container/container.ts
776
814
  var NodeContainer = class extends Illuma {
777
815
  static {
@@ -901,7 +939,11 @@ var NodeContainer = class extends Illuma {
901
939
  return parentNode.findNode(token);
902
940
  }
903
941
  _buildInjectionTree() {
904
- const root = new TreeRootNode(this._opts?.instant);
942
+ const middlewares = [
943
+ ...Illuma._middlewares,
944
+ ...this.collectMiddlewares()
945
+ ];
946
+ const root = new TreeRootNode(this._opts?.instant, middlewares);
905
947
  const cache = /* @__PURE__ */ new Map();
906
948
  const nodes = [
907
949
  ...this._protoNodes.values(),
@@ -918,6 +960,12 @@ var NodeContainer = class extends Illuma {
918
960
  this._multiProtoNodes.clear();
919
961
  return root;
920
962
  }
963
+ collectMiddlewares() {
964
+ return [
965
+ ...this._parent && "collectMiddlewares" in this._parent && typeof this._parent.collectMiddlewares === "function" ? this._parent.collectMiddlewares() : [],
966
+ ...this.middlewares
967
+ ];
968
+ }
921
969
  /**
922
970
  * Bootstraps the container by resolving the dependency trees and instantiating all providers.
923
971
  * This must be called after all providers are registered and before calling {@link get}.