@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.
package/dist/testkit.js CHANGED
@@ -202,6 +202,7 @@ var Illuma = class _Illuma {
202
202
  }
203
203
  static _diagnostics = [];
204
204
  static _scanners = [];
205
+ static _middlewares = [];
205
206
  /** @internal */
206
207
  static get contextScanners() {
207
208
  return _Illuma._scanners;
@@ -224,6 +225,20 @@ var Illuma = class _Illuma {
224
225
  static extendContextScanner(scanner) {
225
226
  _Illuma._scanners.push(scanner);
226
227
  }
228
+ /**
229
+ * Registers a global middleware to be applied during instance creation.
230
+ * Typically used for cross-cutting concerns like logging, profiling, or custom instantiation logic.
231
+ * Function should accept instantiation parameters and a `next` function to proceed with the next middleware or actual instantiation.
232
+ *
233
+ * @param m - The middleware function to register
234
+ */
235
+ static registerGlobalMiddleware(m) {
236
+ _Illuma._middlewares.push(m);
237
+ }
238
+ middlewares = [];
239
+ registerMiddleware(m) {
240
+ this.middlewares.push(m);
241
+ }
227
242
  static onReport(report) {
228
243
  for (const diag of _Illuma._diagnostics) diag.onReport(report);
229
244
  }
@@ -428,7 +443,34 @@ function isNotTransparentProto(proto) {
428
443
  }
429
444
  __name(isNotTransparentProto, "isNotTransparentProto");
430
445
 
446
+ // src/lib/utils/injector.ts
447
+ var InjectorImpl = class {
448
+ static {
449
+ __name(this, "InjectorImpl");
450
+ }
451
+ container;
452
+ constructor(container) {
453
+ this.container = container;
454
+ }
455
+ get(token) {
456
+ return this.container.get(token);
457
+ }
458
+ produce(fn) {
459
+ return this.container.produce(fn);
460
+ }
461
+ };
462
+ var Injector = new NodeToken("Injector");
463
+
431
464
  // src/lib/provider/tree-node.ts
465
+ function runMiddlewares(middlewares, params) {
466
+ const ms = middlewares;
467
+ const next = /* @__PURE__ */ __name((i, current) => {
468
+ if (i >= ms.length) return current.factory();
469
+ return ms[i](current, (nextParams) => next(i + 1, nextParams));
470
+ }, "next");
471
+ return next(0, params);
472
+ }
473
+ __name(runMiddlewares, "runMiddlewares");
432
474
  function retrieverFactory(node, deps, transparentDeps) {
433
475
  return (token, optional) => {
434
476
  const depNode = deps.get(token);
@@ -446,10 +488,12 @@ var TreeRootNode = class {
446
488
  __name(this, "TreeRootNode");
447
489
  }
448
490
  instant;
491
+ middlewares;
449
492
  _deps = /* @__PURE__ */ new Set();
450
493
  _treePool = /* @__PURE__ */ new WeakMap();
451
- constructor(instant = true) {
494
+ constructor(instant = true, middlewares = []) {
452
495
  this.instant = instant;
496
+ this.middlewares = middlewares;
453
497
  }
454
498
  get dependencies() {
455
499
  return this._deps;
@@ -460,14 +504,14 @@ var TreeRootNode = class {
460
504
  build() {
461
505
  for (const dep of this._deps) {
462
506
  if ("token" in dep.proto) this._treePool.set(dep.proto.token, dep);
463
- if (this.instant) dep.instantiate(this._treePool);
507
+ if (this.instant) dep.instantiate(this._treePool, this.middlewares);
464
508
  else dep.collectPool(this._treePool);
465
509
  }
466
510
  }
467
511
  find(token) {
468
512
  const node = this._treePool.get(token);
469
513
  if (!node) return null;
470
- if (!this.instant) node.instantiate(this._treePool);
514
+ if (!this.instant) node.instantiate(this._treePool, this.middlewares);
471
515
  return node;
472
516
  }
473
517
  toString() {
@@ -492,6 +536,10 @@ var TreeNodeSingle = class {
492
536
  }
493
537
  constructor(proto) {
494
538
  this.proto = proto;
539
+ if (proto.token === Injector) {
540
+ this._instance = proto.factory();
541
+ this._resolved = true;
542
+ }
495
543
  }
496
544
  addDependency(node) {
497
545
  if (node instanceof TreeNodeTransparent) this._transparent.add(node);
@@ -503,14 +551,18 @@ var TreeNodeSingle = class {
503
551
  for (const dep of this._transparent) dep.collectPool(pool);
504
552
  pool.set(this.proto.token, this);
505
553
  }
506
- instantiate(pool) {
554
+ instantiate(pool, middlewares = []) {
507
555
  if (this._resolved) return;
508
- for (const node of this._deps.values()) node.instantiate(pool);
509
- for (const dep of this._transparent) dep.instantiate(pool);
556
+ for (const node of this._deps.values()) node.instantiate(pool, middlewares);
557
+ for (const dep of this._transparent) dep.instantiate(pool, middlewares);
510
558
  const retriever = retrieverFactory(this.proto.token, this._deps, this._transparent);
511
559
  const factory = this.proto.factory ?? this.proto.token.opts?.factory;
512
560
  if (!factory) throw InjectionError.notFound(this.proto.token);
513
- this._instance = InjectionContext.instantiate(factory, retriever);
561
+ const contextFactory = /* @__PURE__ */ __name(() => InjectionContext.instantiate(factory, retriever), "contextFactory");
562
+ this._instance = runMiddlewares(middlewares, {
563
+ token: this.proto.token,
564
+ factory: contextFactory
565
+ });
514
566
  this._resolved = true;
515
567
  if (pool) pool.set(this.proto.token, this);
516
568
  }
@@ -544,12 +596,16 @@ var TreeNodeTransparent = class _TreeNodeTransparent {
544
596
  for (const node of this._deps.values()) node.collectPool(pool);
545
597
  for (const dep of this._transparent) dep.collectPool(pool);
546
598
  }
547
- instantiate(pool) {
599
+ instantiate(pool, middlewares = []) {
548
600
  if (this._resolved) return;
549
- for (const dep of this._transparent) dep.instantiate(pool);
550
- for (const node of this._deps.values()) node.instantiate(pool);
601
+ for (const dep of this._transparent) dep.instantiate(pool, middlewares);
602
+ for (const node of this._deps.values()) node.instantiate(pool, middlewares);
551
603
  const retriever = retrieverFactory(this.proto.parent.token, this._deps, this._transparent);
552
- this._instance = InjectionContext.instantiate(this.proto.factory, retriever);
604
+ const refFactory = /* @__PURE__ */ __name(() => InjectionContext.instantiate(this.proto.factory, retriever), "refFactory");
605
+ this._instance = runMiddlewares(middlewares, {
606
+ token: this.proto.parent.token,
607
+ factory: refFactory
608
+ });
553
609
  this._resolved = true;
554
610
  }
555
611
  toString() {
@@ -572,10 +628,10 @@ var TreeNodeMulti = class _TreeNodeMulti {
572
628
  for (const dep of this._deps) dep.collectPool(pool);
573
629
  pool.set(this.proto.token, this);
574
630
  }
575
- instantiate(pool) {
631
+ instantiate(pool, middlewares = []) {
576
632
  if (this._resolved) return;
577
633
  for (const dep of this._deps) {
578
- dep.instantiate(pool);
634
+ dep.instantiate(pool, middlewares);
579
635
  if (dep instanceof TreeNodeSingle) {
580
636
  this.instance.push(dep.instance);
581
637
  } else if (dep instanceof _TreeNodeMulti) {
@@ -730,24 +786,6 @@ function resolveTreeNode(rootProto, cache, singleNodes, multiNodes, upstreamGett
730
786
  }
731
787
  __name(resolveTreeNode, "resolveTreeNode");
732
788
 
733
- // src/lib/utils/injector.ts
734
- var InjectorImpl = class {
735
- static {
736
- __name(this, "InjectorImpl");
737
- }
738
- container;
739
- constructor(container) {
740
- this.container = container;
741
- }
742
- get(token) {
743
- return this.container.get(token);
744
- }
745
- produce(fn) {
746
- return this.container.produce(fn);
747
- }
748
- };
749
- var Injector = new NodeToken("Injector");
750
-
751
789
  // src/lib/container/container.ts
752
790
  var NodeContainer = class extends Illuma {
753
791
  static {
@@ -877,7 +915,11 @@ var NodeContainer = class extends Illuma {
877
915
  return parentNode.findNode(token);
878
916
  }
879
917
  _buildInjectionTree() {
880
- const root = new TreeRootNode(this._opts?.instant);
918
+ const middlewares = [
919
+ ...Illuma._middlewares,
920
+ ...this.collectMiddlewares()
921
+ ];
922
+ const root = new TreeRootNode(this._opts?.instant, middlewares);
881
923
  const cache = /* @__PURE__ */ new Map();
882
924
  const nodes = [
883
925
  ...this._protoNodes.values(),
@@ -894,6 +936,12 @@ var NodeContainer = class extends Illuma {
894
936
  this._multiProtoNodes.clear();
895
937
  return root;
896
938
  }
939
+ collectMiddlewares() {
940
+ return [
941
+ ...this._parent && "collectMiddlewares" in this._parent && typeof this._parent.collectMiddlewares === "function" ? this._parent.collectMiddlewares() : [],
942
+ ...this.middlewares
943
+ ];
944
+ }
897
945
  /**
898
946
  * Bootstraps the container by resolving the dependency trees and instantiating all providers.
899
947
  * This must be called after all providers are registered and before calling {@link get}.