@illuma/core 1.3.1 → 1.5.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/dist/index.js CHANGED
@@ -1,5 +1,171 @@
1
1
  var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
2
5
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
6
+ var __esm = (fn, res) => function __init() {
7
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
+ };
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
+
23
+ // src/lib/plugins/core/plugin-container.ts
24
+ var Illuma;
25
+ var init_plugin_container = __esm({
26
+ "src/lib/plugins/core/plugin-container.ts"() {
27
+ "use strict";
28
+ Illuma = class _Illuma {
29
+ static {
30
+ __name(this, "Illuma");
31
+ }
32
+ static _diagnostics = /* @__PURE__ */ new Set();
33
+ static _scanners = [];
34
+ static _middlewares = [];
35
+ /** @internal */
36
+ static get contextScanners() {
37
+ return _Illuma._scanners;
38
+ }
39
+ /**
40
+ * Extends the diagnostics with a new diagnostics module.
41
+ * These will be run on diagnostics reports after container bootstrap.
42
+ *
43
+ * @param m - The diagnostics module instance to add
44
+ */
45
+ static extendDiagnostics(m) {
46
+ _Illuma._diagnostics.add(m);
47
+ }
48
+ /**
49
+ * Extends the context scanners with a new context scanner.
50
+ * These will be run in injection context scans to detect additional injections (alongside `nodeInject` calls).
51
+ *
52
+ * @param scanner - The context scanner instance to add
53
+ */
54
+ static extendContextScanner(scanner) {
55
+ _Illuma._scanners.push(scanner);
56
+ }
57
+ /**
58
+ * Registers a global middleware to be applied during instance creation.
59
+ * Typically used for cross-cutting concerns like logging, profiling, or custom instantiation logic.
60
+ * Function should accept instantiation parameters and a `next` function to proceed with the next middleware or actual instantiation.
61
+ *
62
+ * @param m - The middleware function to register
63
+ */
64
+ static registerGlobalMiddleware(m) {
65
+ _Illuma._middlewares.push(m);
66
+ }
67
+ middlewares = [];
68
+ registerMiddleware(m) {
69
+ this.middlewares.push(m);
70
+ }
71
+ static onReport(report) {
72
+ for (const diag of _Illuma._diagnostics) diag.onReport(report);
73
+ }
74
+ /**
75
+ * @internal
76
+ * Check if diagnostics modules are registered
77
+ */
78
+ static hasDiagnostics() {
79
+ return _Illuma._diagnostics.size > 0;
80
+ }
81
+ /**
82
+ * @internal
83
+ * Reset all plugin registrations
84
+ */
85
+ static __resetPlugins() {
86
+ _Illuma._diagnostics.clear();
87
+ _Illuma._scanners.length = 0;
88
+ _Illuma._middlewares.length = 0;
89
+ }
90
+ };
91
+ }
92
+ });
93
+
94
+ // src/lib/plugins/core/index.ts
95
+ var init_core = __esm({
96
+ "src/lib/plugins/core/index.ts"() {
97
+ "use strict";
98
+ init_plugin_container();
99
+ }
100
+ });
101
+
102
+ // src/lib/plugins/middlewares/diagnostics.middleware.ts
103
+ var performanceDiagnostics;
104
+ var init_diagnostics_middleware = __esm({
105
+ "src/lib/plugins/middlewares/diagnostics.middleware.ts"() {
106
+ "use strict";
107
+ performanceDiagnostics = /* @__PURE__ */ __name((params, next) => {
108
+ if (!params.deps.size) {
109
+ return next(params);
110
+ }
111
+ const start = performance.now();
112
+ const instance = next(params);
113
+ const end = performance.now();
114
+ const duration = end - start;
115
+ console.log(`Instantiated ${params.token.name} in ${duration.toFixed(2)} ms`);
116
+ return instance;
117
+ }, "performanceDiagnostics");
118
+ }
119
+ });
120
+
121
+ // src/lib/plugins/diagnostics/default-impl.ts
122
+ var DiagnosticsDefaultReporter;
123
+ var init_default_impl = __esm({
124
+ "src/lib/plugins/diagnostics/default-impl.ts"() {
125
+ "use strict";
126
+ DiagnosticsDefaultReporter = class {
127
+ static {
128
+ __name(this, "DiagnosticsDefaultReporter");
129
+ }
130
+ onReport(report) {
131
+ console.log("[Illuma] \u{1F9F9} Diagnostics:");
132
+ console.log(` Total: ${report.totalNodes} node(s)`);
133
+ console.log(` ${report.unusedNodes.length} were not used while bootstrap:`);
134
+ for (const node of report.unusedNodes) console.log(` - ${node.toString()}`);
135
+ }
136
+ };
137
+ }
138
+ });
139
+
140
+ // src/lib/plugins/diagnostics/built-in.ts
141
+ var built_in_exports = {};
142
+ __export(built_in_exports, {
143
+ __resetDiagnosticsState: () => __resetDiagnosticsState,
144
+ enableIllumaDiagnostics: () => enableIllumaDiagnostics
145
+ });
146
+ function enableIllumaDiagnostics() {
147
+ if (state.enabled) return;
148
+ state.enabled = true;
149
+ Illuma.extendDiagnostics(new DiagnosticsDefaultReporter());
150
+ Illuma.registerGlobalMiddleware(performanceDiagnostics);
151
+ }
152
+ function __resetDiagnosticsState() {
153
+ state.enabled = false;
154
+ }
155
+ var state;
156
+ var init_built_in = __esm({
157
+ "src/lib/plugins/diagnostics/built-in.ts"() {
158
+ "use strict";
159
+ init_core();
160
+ init_diagnostics_middleware();
161
+ init_default_impl();
162
+ state = {
163
+ enabled: false
164
+ };
165
+ __name(enableIllumaDiagnostics, "enableIllumaDiagnostics");
166
+ __name(__resetDiagnosticsState, "__resetDiagnosticsState");
167
+ }
168
+ });
3
169
 
4
170
  // src/lib/api/token.ts
5
171
  var NodeBase = class {
@@ -221,41 +387,8 @@ function registerClassAsInjectable(ctor, token) {
221
387
  }
222
388
  __name(registerClassAsInjectable, "registerClassAsInjectable");
223
389
 
224
- // src/lib/plugins/core/plugin-container.ts
225
- var Illuma = class _Illuma {
226
- static {
227
- __name(this, "Illuma");
228
- }
229
- static _diagnostics = [];
230
- static _scanners = [];
231
- /** @internal */
232
- static get contextScanners() {
233
- return _Illuma._scanners;
234
- }
235
- /**
236
- * Extends the diagnostics with a new diagnostics module.
237
- * These will be run on diagnostics reports after container bootstrap.
238
- *
239
- * @param m - The diagnostics module instance to add
240
- */
241
- static extendDiagnostics(m) {
242
- _Illuma._diagnostics.push(m);
243
- }
244
- /**
245
- * Extends the context scanners with a new context scanner.
246
- * These will be run in injection context scans to detect additional injections (alongside `nodeInject` calls).
247
- *
248
- * @param scanner - The context scanner instance to add
249
- */
250
- static extendContextScanner(scanner) {
251
- _Illuma._scanners.push(scanner);
252
- }
253
- static onReport(report) {
254
- for (const diag of _Illuma._diagnostics) diag.onReport(report);
255
- }
256
- };
257
-
258
390
  // src/lib/context/context.ts
391
+ init_plugin_container();
259
392
  var InjectionContext = class _InjectionContext {
260
393
  static {
261
394
  __name(this, "InjectionContext");
@@ -355,18 +488,8 @@ function nodeInject(provider, options) {
355
488
  }
356
489
  __name(nodeInject, "nodeInject");
357
490
 
358
- // src/lib/plugins/diagnostics/default-impl.ts
359
- var DiagnosticsDefaultReporter = class {
360
- static {
361
- __name(this, "DiagnosticsDefaultReporter");
362
- }
363
- onReport(report) {
364
- console.log("[Illuma] \u{1F9F9} Diagnostics:");
365
- console.log(` Total: ${report.totalNodes} node(s)`);
366
- console.log(` ${report.unusedNodes.length} were not used while bootstrap:`);
367
- for (const node of report.unusedNodes) console.log(` - ${node.toString()}`);
368
- }
369
- };
491
+ // src/lib/container/container.ts
492
+ init_plugin_container();
370
493
 
371
494
  // src/lib/provider/extractor.ts
372
495
  function extractProvider(provider) {
@@ -454,7 +577,34 @@ function isNotTransparentProto(proto) {
454
577
  }
455
578
  __name(isNotTransparentProto, "isNotTransparentProto");
456
579
 
580
+ // src/lib/utils/injector.ts
581
+ var InjectorImpl = class {
582
+ static {
583
+ __name(this, "InjectorImpl");
584
+ }
585
+ container;
586
+ constructor(container) {
587
+ this.container = container;
588
+ }
589
+ get(token) {
590
+ return this.container.get(token);
591
+ }
592
+ produce(fn) {
593
+ return this.container.produce(fn);
594
+ }
595
+ };
596
+ var Injector = new NodeToken("Injector");
597
+
457
598
  // src/lib/provider/tree-node.ts
599
+ function runMiddlewares(middlewares, params) {
600
+ const ms = middlewares;
601
+ const next = /* @__PURE__ */ __name((i, current) => {
602
+ if (i >= ms.length) return current.factory();
603
+ return ms[i](current, (nextParams) => next(i + 1, nextParams));
604
+ }, "next");
605
+ return next(0, params);
606
+ }
607
+ __name(runMiddlewares, "runMiddlewares");
458
608
  function retrieverFactory(node, deps, transparentDeps) {
459
609
  return (token, optional) => {
460
610
  const depNode = deps.get(token);
@@ -472,10 +622,12 @@ var TreeRootNode = class {
472
622
  __name(this, "TreeRootNode");
473
623
  }
474
624
  instant;
625
+ middlewares;
475
626
  _deps = /* @__PURE__ */ new Set();
476
627
  _treePool = /* @__PURE__ */ new WeakMap();
477
- constructor(instant = true) {
628
+ constructor(instant = true, middlewares = []) {
478
629
  this.instant = instant;
630
+ this.middlewares = middlewares;
479
631
  }
480
632
  get dependencies() {
481
633
  return this._deps;
@@ -486,14 +638,14 @@ var TreeRootNode = class {
486
638
  build() {
487
639
  for (const dep of this._deps) {
488
640
  if ("token" in dep.proto) this._treePool.set(dep.proto.token, dep);
489
- if (this.instant) dep.instantiate(this._treePool);
641
+ if (this.instant) dep.instantiate(this._treePool, this.middlewares);
490
642
  else dep.collectPool(this._treePool);
491
643
  }
492
644
  }
493
645
  find(token) {
494
646
  const node = this._treePool.get(token);
495
647
  if (!node) return null;
496
- if (!this.instant) node.instantiate(this._treePool);
648
+ if (!this.instant) node.instantiate(this._treePool, this.middlewares);
497
649
  return node;
498
650
  }
499
651
  toString() {
@@ -518,6 +670,10 @@ var TreeNodeSingle = class {
518
670
  }
519
671
  constructor(proto) {
520
672
  this.proto = proto;
673
+ if (proto.token === Injector) {
674
+ this._instance = proto.factory();
675
+ this._resolved = true;
676
+ }
521
677
  }
522
678
  addDependency(node) {
523
679
  if (node instanceof TreeNodeTransparent) this._transparent.add(node);
@@ -529,14 +685,22 @@ var TreeNodeSingle = class {
529
685
  for (const dep of this._transparent) dep.collectPool(pool);
530
686
  pool.set(this.proto.token, this);
531
687
  }
532
- instantiate(pool) {
688
+ instantiate(pool, middlewares = []) {
533
689
  if (this._resolved) return;
534
- for (const node of this._deps.values()) node.instantiate(pool);
535
- for (const dep of this._transparent) dep.instantiate(pool);
690
+ for (const node of this._deps.values()) node.instantiate(pool, middlewares);
691
+ for (const dep of this._transparent) dep.instantiate(pool, middlewares);
536
692
  const retriever = retrieverFactory(this.proto.token, this._deps, this._transparent);
537
693
  const factory = this.proto.factory ?? this.proto.token.opts?.factory;
538
694
  if (!factory) throw InjectionError.notFound(this.proto.token);
539
- this._instance = InjectionContext.instantiate(factory, retriever);
695
+ const contextFactory = /* @__PURE__ */ __name(() => InjectionContext.instantiate(factory, retriever), "contextFactory");
696
+ this._instance = runMiddlewares(middlewares, {
697
+ token: this.proto.token,
698
+ factory: contextFactory,
699
+ deps: /* @__PURE__ */ new Set([
700
+ ...this._deps.keys(),
701
+ ...Array.from(this._transparent).map((n) => n.proto.parent.token)
702
+ ])
703
+ });
540
704
  this._resolved = true;
541
705
  if (pool) pool.set(this.proto.token, this);
542
706
  }
@@ -570,12 +734,20 @@ var TreeNodeTransparent = class _TreeNodeTransparent {
570
734
  for (const node of this._deps.values()) node.collectPool(pool);
571
735
  for (const dep of this._transparent) dep.collectPool(pool);
572
736
  }
573
- instantiate(pool) {
737
+ instantiate(pool, middlewares = []) {
574
738
  if (this._resolved) return;
575
- for (const dep of this._transparent) dep.instantiate(pool);
576
- for (const node of this._deps.values()) node.instantiate(pool);
739
+ for (const dep of this._transparent) dep.instantiate(pool, middlewares);
740
+ for (const node of this._deps.values()) node.instantiate(pool, middlewares);
577
741
  const retriever = retrieverFactory(this.proto.parent.token, this._deps, this._transparent);
578
- this._instance = InjectionContext.instantiate(this.proto.factory, retriever);
742
+ const refFactory = /* @__PURE__ */ __name(() => InjectionContext.instantiate(this.proto.factory, retriever), "refFactory");
743
+ this._instance = runMiddlewares(middlewares, {
744
+ token: this.proto.parent.token,
745
+ factory: refFactory,
746
+ deps: /* @__PURE__ */ new Set([
747
+ ...this._deps.keys(),
748
+ ...Array.from(this._transparent).map((n) => n.proto.parent.token)
749
+ ])
750
+ });
579
751
  this._resolved = true;
580
752
  }
581
753
  toString() {
@@ -598,10 +770,10 @@ var TreeNodeMulti = class _TreeNodeMulti {
598
770
  for (const dep of this._deps) dep.collectPool(pool);
599
771
  pool.set(this.proto.token, this);
600
772
  }
601
- instantiate(pool) {
773
+ instantiate(pool, middlewares = []) {
602
774
  if (this._resolved) return;
603
775
  for (const dep of this._deps) {
604
- dep.instantiate(pool);
776
+ dep.instantiate(pool, middlewares);
605
777
  if (dep instanceof TreeNodeSingle) {
606
778
  this.instance.push(dep.instance);
607
779
  } else if (dep instanceof _TreeNodeMulti) {
@@ -756,24 +928,6 @@ function resolveTreeNode(rootProto, cache, singleNodes, multiNodes, upstreamGett
756
928
  }
757
929
  __name(resolveTreeNode, "resolveTreeNode");
758
930
 
759
- // src/lib/utils/injector.ts
760
- var InjectorImpl = class {
761
- static {
762
- __name(this, "InjectorImpl");
763
- }
764
- container;
765
- constructor(container) {
766
- this.container = container;
767
- }
768
- get(token) {
769
- return this.container.get(token);
770
- }
771
- produce(fn) {
772
- return this.container.produce(fn);
773
- }
774
- };
775
- var Injector = new NodeToken("Injector");
776
-
777
931
  // src/lib/utils/defer.ts
778
932
  function injectDefer(provider, options) {
779
933
  const injector = nodeInject(Injector);
@@ -883,10 +1037,13 @@ var NodeContainer = class extends Illuma {
883
1037
  _multiProtoNodes = /* @__PURE__ */ new Map();
884
1038
  constructor(_opts) {
885
1039
  super(), this._opts = _opts;
886
- this._parent = _opts?.parent;
887
1040
  if (_opts?.diagnostics) {
888
- Illuma.extendDiagnostics(new DiagnosticsDefaultReporter());
1041
+ console.warn("[Illuma] Deprecation Warning: The 'diagnostics' option in iContainerOptions is deprecated and will be removed in future versions. Please use the `enableIllumaDiagnostics` from '@illuma/core/plugins` instead.");
1042
+ const m = (init_built_in(), __toCommonJS(built_in_exports));
1043
+ if (m.enabled) return;
1044
+ m.enableIllumaDiagnostics();
889
1045
  }
1046
+ this._parent = _opts?.parent;
890
1047
  }
891
1048
  /**
892
1049
  * Registers a provider in the container.
@@ -999,7 +1156,11 @@ var NodeContainer = class extends Illuma {
999
1156
  return parentNode.findNode(token);
1000
1157
  }
1001
1158
  _buildInjectionTree() {
1002
- const root = new TreeRootNode(this._opts?.instant);
1159
+ const middlewares = [
1160
+ ...Illuma._middlewares,
1161
+ ...this.collectMiddlewares()
1162
+ ];
1163
+ const root = new TreeRootNode(this._opts?.instant, middlewares);
1003
1164
  const cache = /* @__PURE__ */ new Map();
1004
1165
  const nodes = [
1005
1166
  ...this._protoNodes.values(),
@@ -1016,6 +1177,12 @@ var NodeContainer = class extends Illuma {
1016
1177
  this._multiProtoNodes.clear();
1017
1178
  return root;
1018
1179
  }
1180
+ collectMiddlewares() {
1181
+ return [
1182
+ ...this._parent && "collectMiddlewares" in this._parent && typeof this._parent.collectMiddlewares === "function" ? this._parent.collectMiddlewares() : [],
1183
+ ...this.middlewares
1184
+ ];
1185
+ }
1019
1186
  /**
1020
1187
  * Bootstraps the container by resolving the dependency trees and instantiating all providers.
1021
1188
  * This must be called after all providers are registered and before calling {@link get}.
@@ -1051,7 +1218,7 @@ var NodeContainer = class extends Illuma {
1051
1218
  if (this._opts?.measurePerformance) {
1052
1219
  console.log(`[Illuma] \u{1F680} Bootstrapped in ${duration.toFixed(2)} ms`);
1053
1220
  }
1054
- if (this._opts?.diagnostics) {
1221
+ if (this._opts?.diagnostics || Illuma.hasDiagnostics()) {
1055
1222
  const allNodes = this._rootNode.dependencies.size;
1056
1223
  const unusedNodes = Array.from(this._rootNode.dependencies).filter((node) => node.allocations === 0).filter((node) => {
1057
1224
  if (!(node.proto instanceof ProtoNodeSingle)) return true;