@illuma/core 1.4.0 → 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/CHANGELOG.md CHANGED
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## Unreleased
9
9
 
10
+ ## 1.5.0 - 2026-01-10
11
+
10
12
  ## 1.4.0 - 2026-01-10
11
13
 
12
14
  ## 1.3.1 - 2026-01-10
package/README.md CHANGED
@@ -12,11 +12,11 @@ A lightweight, type-safe dependency injection container for TypeScript. Zero dep
12
12
  - 🎯 **Type-Safe** – Full TypeScript support with excellent type inference
13
13
  - 🪶 **Lightweight** – Zero dependencies, minimal bundle size
14
14
  - 🔄 **Flexible** – Classes, factories, values, and aliases
15
- - 🎨 **Decorators** – Optional Angular-style `@NodeInjectable()` decorator
15
+ - 🎨 **Optional decorators** – Angular-style `@NodeInjectable()` decorator
16
16
  - 🔗 **Multi-Tokens** – Built-in multi-provider support
17
- - 🔌 **Plugin System** – Extensible architecture with custom scanners and diagnostics
17
+ - 🔌 **Plugin System** – Extensible architecture with custom middlewares, scanners, and diagnostics
18
+ - 🧪 **Testkit** – Utilities for easy unit testing and mocking
18
19
  - 🌍 **Universal** – Node.js, Deno, browser, and Electron
19
-
20
20
  ## 📦 Installation
21
21
 
22
22
  ```bash
package/dist/index.cjs CHANGED
@@ -4,6 +4,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
6
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ var __esm = (fn, res) => function __init() {
8
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
9
+ };
7
10
  var __export = (target, all) => {
8
11
  for (var name in all)
9
12
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -18,6 +21,153 @@ var __copyProps = (to, from, except, desc) => {
18
21
  };
19
22
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
23
 
24
+ // src/lib/plugins/core/plugin-container.ts
25
+ var Illuma;
26
+ var init_plugin_container = __esm({
27
+ "src/lib/plugins/core/plugin-container.ts"() {
28
+ "use strict";
29
+ Illuma = class _Illuma {
30
+ static {
31
+ __name(this, "Illuma");
32
+ }
33
+ static _diagnostics = /* @__PURE__ */ new Set();
34
+ static _scanners = [];
35
+ static _middlewares = [];
36
+ /** @internal */
37
+ static get contextScanners() {
38
+ return _Illuma._scanners;
39
+ }
40
+ /**
41
+ * Extends the diagnostics with a new diagnostics module.
42
+ * These will be run on diagnostics reports after container bootstrap.
43
+ *
44
+ * @param m - The diagnostics module instance to add
45
+ */
46
+ static extendDiagnostics(m) {
47
+ _Illuma._diagnostics.add(m);
48
+ }
49
+ /**
50
+ * Extends the context scanners with a new context scanner.
51
+ * These will be run in injection context scans to detect additional injections (alongside `nodeInject` calls).
52
+ *
53
+ * @param scanner - The context scanner instance to add
54
+ */
55
+ static extendContextScanner(scanner) {
56
+ _Illuma._scanners.push(scanner);
57
+ }
58
+ /**
59
+ * Registers a global middleware to be applied during instance creation.
60
+ * Typically used for cross-cutting concerns like logging, profiling, or custom instantiation logic.
61
+ * Function should accept instantiation parameters and a `next` function to proceed with the next middleware or actual instantiation.
62
+ *
63
+ * @param m - The middleware function to register
64
+ */
65
+ static registerGlobalMiddleware(m) {
66
+ _Illuma._middlewares.push(m);
67
+ }
68
+ middlewares = [];
69
+ registerMiddleware(m) {
70
+ this.middlewares.push(m);
71
+ }
72
+ static onReport(report) {
73
+ for (const diag of _Illuma._diagnostics) diag.onReport(report);
74
+ }
75
+ /**
76
+ * @internal
77
+ * Check if diagnostics modules are registered
78
+ */
79
+ static hasDiagnostics() {
80
+ return _Illuma._diagnostics.size > 0;
81
+ }
82
+ /**
83
+ * @internal
84
+ * Reset all plugin registrations
85
+ */
86
+ static __resetPlugins() {
87
+ _Illuma._diagnostics.clear();
88
+ _Illuma._scanners.length = 0;
89
+ _Illuma._middlewares.length = 0;
90
+ }
91
+ };
92
+ }
93
+ });
94
+
95
+ // src/lib/plugins/core/index.ts
96
+ var init_core = __esm({
97
+ "src/lib/plugins/core/index.ts"() {
98
+ "use strict";
99
+ init_plugin_container();
100
+ }
101
+ });
102
+
103
+ // src/lib/plugins/middlewares/diagnostics.middleware.ts
104
+ var performanceDiagnostics;
105
+ var init_diagnostics_middleware = __esm({
106
+ "src/lib/plugins/middlewares/diagnostics.middleware.ts"() {
107
+ "use strict";
108
+ performanceDiagnostics = /* @__PURE__ */ __name((params, next) => {
109
+ if (!params.deps.size) {
110
+ return next(params);
111
+ }
112
+ const start = performance.now();
113
+ const instance = next(params);
114
+ const end = performance.now();
115
+ const duration = end - start;
116
+ console.log(`Instantiated ${params.token.name} in ${duration.toFixed(2)} ms`);
117
+ return instance;
118
+ }, "performanceDiagnostics");
119
+ }
120
+ });
121
+
122
+ // src/lib/plugins/diagnostics/default-impl.ts
123
+ var DiagnosticsDefaultReporter;
124
+ var init_default_impl = __esm({
125
+ "src/lib/plugins/diagnostics/default-impl.ts"() {
126
+ "use strict";
127
+ DiagnosticsDefaultReporter = class {
128
+ static {
129
+ __name(this, "DiagnosticsDefaultReporter");
130
+ }
131
+ onReport(report) {
132
+ console.log("[Illuma] \u{1F9F9} Diagnostics:");
133
+ console.log(` Total: ${report.totalNodes} node(s)`);
134
+ console.log(` ${report.unusedNodes.length} were not used while bootstrap:`);
135
+ for (const node of report.unusedNodes) console.log(` - ${node.toString()}`);
136
+ }
137
+ };
138
+ }
139
+ });
140
+
141
+ // src/lib/plugins/diagnostics/built-in.ts
142
+ var built_in_exports = {};
143
+ __export(built_in_exports, {
144
+ __resetDiagnosticsState: () => __resetDiagnosticsState,
145
+ enableIllumaDiagnostics: () => enableIllumaDiagnostics
146
+ });
147
+ function enableIllumaDiagnostics() {
148
+ if (state.enabled) return;
149
+ state.enabled = true;
150
+ Illuma.extendDiagnostics(new DiagnosticsDefaultReporter());
151
+ Illuma.registerGlobalMiddleware(performanceDiagnostics);
152
+ }
153
+ function __resetDiagnosticsState() {
154
+ state.enabled = false;
155
+ }
156
+ var state;
157
+ var init_built_in = __esm({
158
+ "src/lib/plugins/diagnostics/built-in.ts"() {
159
+ "use strict";
160
+ init_core();
161
+ init_diagnostics_middleware();
162
+ init_default_impl();
163
+ state = {
164
+ enabled: false
165
+ };
166
+ __name(enableIllumaDiagnostics, "enableIllumaDiagnostics");
167
+ __name(__resetDiagnosticsState, "__resetDiagnosticsState");
168
+ }
169
+ });
170
+
21
171
  // src/index.ts
22
172
  var index_exports = {};
23
173
  __export(index_exports, {
@@ -267,56 +417,8 @@ function registerClassAsInjectable(ctor, token) {
267
417
  }
268
418
  __name(registerClassAsInjectable, "registerClassAsInjectable");
269
419
 
270
- // src/lib/plugins/core/plugin-container.ts
271
- var Illuma = class _Illuma {
272
- static {
273
- __name(this, "Illuma");
274
- }
275
- static _diagnostics = [];
276
- static _scanners = [];
277
- static _middlewares = [];
278
- /** @internal */
279
- static get contextScanners() {
280
- return _Illuma._scanners;
281
- }
282
- /**
283
- * Extends the diagnostics with a new diagnostics module.
284
- * These will be run on diagnostics reports after container bootstrap.
285
- *
286
- * @param m - The diagnostics module instance to add
287
- */
288
- static extendDiagnostics(m) {
289
- _Illuma._diagnostics.push(m);
290
- }
291
- /**
292
- * Extends the context scanners with a new context scanner.
293
- * These will be run in injection context scans to detect additional injections (alongside `nodeInject` calls).
294
- *
295
- * @param scanner - The context scanner instance to add
296
- */
297
- static extendContextScanner(scanner) {
298
- _Illuma._scanners.push(scanner);
299
- }
300
- /**
301
- * Registers a global middleware to be applied during instance creation.
302
- * Typically used for cross-cutting concerns like logging, profiling, or custom instantiation logic.
303
- * Function should accept instantiation parameters and a `next` function to proceed with the next middleware or actual instantiation.
304
- *
305
- * @param m - The middleware function to register
306
- */
307
- static registerGlobalMiddleware(m) {
308
- _Illuma._middlewares.push(m);
309
- }
310
- middlewares = [];
311
- registerMiddleware(m) {
312
- this.middlewares.push(m);
313
- }
314
- static onReport(report) {
315
- for (const diag of _Illuma._diagnostics) diag.onReport(report);
316
- }
317
- };
318
-
319
420
  // src/lib/context/context.ts
421
+ init_plugin_container();
320
422
  var InjectionContext = class _InjectionContext {
321
423
  static {
322
424
  __name(this, "InjectionContext");
@@ -416,18 +518,8 @@ function nodeInject(provider, options) {
416
518
  }
417
519
  __name(nodeInject, "nodeInject");
418
520
 
419
- // src/lib/plugins/diagnostics/default-impl.ts
420
- var DiagnosticsDefaultReporter = class {
421
- static {
422
- __name(this, "DiagnosticsDefaultReporter");
423
- }
424
- onReport(report) {
425
- console.log("[Illuma] \u{1F9F9} Diagnostics:");
426
- console.log(` Total: ${report.totalNodes} node(s)`);
427
- console.log(` ${report.unusedNodes.length} were not used while bootstrap:`);
428
- for (const node of report.unusedNodes) console.log(` - ${node.toString()}`);
429
- }
430
- };
521
+ // src/lib/container/container.ts
522
+ init_plugin_container();
431
523
 
432
524
  // src/lib/provider/extractor.ts
433
525
  function extractProvider(provider) {
@@ -633,7 +725,11 @@ var TreeNodeSingle = class {
633
725
  const contextFactory = /* @__PURE__ */ __name(() => InjectionContext.instantiate(factory, retriever), "contextFactory");
634
726
  this._instance = runMiddlewares(middlewares, {
635
727
  token: this.proto.token,
636
- factory: contextFactory
728
+ factory: contextFactory,
729
+ deps: /* @__PURE__ */ new Set([
730
+ ...this._deps.keys(),
731
+ ...Array.from(this._transparent).map((n) => n.proto.parent.token)
732
+ ])
637
733
  });
638
734
  this._resolved = true;
639
735
  if (pool) pool.set(this.proto.token, this);
@@ -676,7 +772,11 @@ var TreeNodeTransparent = class _TreeNodeTransparent {
676
772
  const refFactory = /* @__PURE__ */ __name(() => InjectionContext.instantiate(this.proto.factory, retriever), "refFactory");
677
773
  this._instance = runMiddlewares(middlewares, {
678
774
  token: this.proto.parent.token,
679
- factory: refFactory
775
+ factory: refFactory,
776
+ deps: /* @__PURE__ */ new Set([
777
+ ...this._deps.keys(),
778
+ ...Array.from(this._transparent).map((n) => n.proto.parent.token)
779
+ ])
680
780
  });
681
781
  this._resolved = true;
682
782
  }
@@ -967,10 +1067,13 @@ var NodeContainer = class extends Illuma {
967
1067
  _multiProtoNodes = /* @__PURE__ */ new Map();
968
1068
  constructor(_opts) {
969
1069
  super(), this._opts = _opts;
970
- this._parent = _opts?.parent;
971
1070
  if (_opts?.diagnostics) {
972
- Illuma.extendDiagnostics(new DiagnosticsDefaultReporter());
1071
+ 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.");
1072
+ const m = (init_built_in(), __toCommonJS(built_in_exports));
1073
+ if (m.enabled) return;
1074
+ m.enableIllumaDiagnostics();
973
1075
  }
1076
+ this._parent = _opts?.parent;
974
1077
  }
975
1078
  /**
976
1079
  * Registers a provider in the container.
@@ -1145,7 +1248,7 @@ var NodeContainer = class extends Illuma {
1145
1248
  if (this._opts?.measurePerformance) {
1146
1249
  console.log(`[Illuma] \u{1F680} Bootstrapped in ${duration.toFixed(2)} ms`);
1147
1250
  }
1148
- if (this._opts?.diagnostics) {
1251
+ if (this._opts?.diagnostics || Illuma.hasDiagnostics()) {
1149
1252
  const allNodes = this._rootNode.dependencies.size;
1150
1253
  const unusedNodes = Array.from(this._rootNode.dependencies).filter((node) => node.allocations === 0).filter((node) => {
1151
1254
  if (!(node.proto instanceof ProtoNodeSingle)) return true;