@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/index.js CHANGED
@@ -228,6 +228,7 @@ var Illuma = class _Illuma {
228
228
  }
229
229
  static _diagnostics = [];
230
230
  static _scanners = [];
231
+ static _middlewares = [];
231
232
  /** @internal */
232
233
  static get contextScanners() {
233
234
  return _Illuma._scanners;
@@ -250,6 +251,20 @@ var Illuma = class _Illuma {
250
251
  static extendContextScanner(scanner) {
251
252
  _Illuma._scanners.push(scanner);
252
253
  }
254
+ /**
255
+ * Registers a global middleware to be applied during instance creation.
256
+ * Typically used for cross-cutting concerns like logging, profiling, or custom instantiation logic.
257
+ * Function should accept instantiation parameters and a `next` function to proceed with the next middleware or actual instantiation.
258
+ *
259
+ * @param m - The middleware function to register
260
+ */
261
+ static registerGlobalMiddleware(m) {
262
+ _Illuma._middlewares.push(m);
263
+ }
264
+ middlewares = [];
265
+ registerMiddleware(m) {
266
+ this.middlewares.push(m);
267
+ }
253
268
  static onReport(report) {
254
269
  for (const diag of _Illuma._diagnostics) diag.onReport(report);
255
270
  }
@@ -454,7 +469,34 @@ function isNotTransparentProto(proto) {
454
469
  }
455
470
  __name(isNotTransparentProto, "isNotTransparentProto");
456
471
 
472
+ // src/lib/utils/injector.ts
473
+ var InjectorImpl = class {
474
+ static {
475
+ __name(this, "InjectorImpl");
476
+ }
477
+ container;
478
+ constructor(container) {
479
+ this.container = container;
480
+ }
481
+ get(token) {
482
+ return this.container.get(token);
483
+ }
484
+ produce(fn) {
485
+ return this.container.produce(fn);
486
+ }
487
+ };
488
+ var Injector = new NodeToken("Injector");
489
+
457
490
  // src/lib/provider/tree-node.ts
491
+ function runMiddlewares(middlewares, params) {
492
+ const ms = middlewares;
493
+ const next = /* @__PURE__ */ __name((i, current) => {
494
+ if (i >= ms.length) return current.factory();
495
+ return ms[i](current, (nextParams) => next(i + 1, nextParams));
496
+ }, "next");
497
+ return next(0, params);
498
+ }
499
+ __name(runMiddlewares, "runMiddlewares");
458
500
  function retrieverFactory(node, deps, transparentDeps) {
459
501
  return (token, optional) => {
460
502
  const depNode = deps.get(token);
@@ -472,10 +514,12 @@ var TreeRootNode = class {
472
514
  __name(this, "TreeRootNode");
473
515
  }
474
516
  instant;
517
+ middlewares;
475
518
  _deps = /* @__PURE__ */ new Set();
476
519
  _treePool = /* @__PURE__ */ new WeakMap();
477
- constructor(instant = true) {
520
+ constructor(instant = true, middlewares = []) {
478
521
  this.instant = instant;
522
+ this.middlewares = middlewares;
479
523
  }
480
524
  get dependencies() {
481
525
  return this._deps;
@@ -486,14 +530,14 @@ var TreeRootNode = class {
486
530
  build() {
487
531
  for (const dep of this._deps) {
488
532
  if ("token" in dep.proto) this._treePool.set(dep.proto.token, dep);
489
- if (this.instant) dep.instantiate(this._treePool);
533
+ if (this.instant) dep.instantiate(this._treePool, this.middlewares);
490
534
  else dep.collectPool(this._treePool);
491
535
  }
492
536
  }
493
537
  find(token) {
494
538
  const node = this._treePool.get(token);
495
539
  if (!node) return null;
496
- if (!this.instant) node.instantiate(this._treePool);
540
+ if (!this.instant) node.instantiate(this._treePool, this.middlewares);
497
541
  return node;
498
542
  }
499
543
  toString() {
@@ -518,6 +562,10 @@ var TreeNodeSingle = class {
518
562
  }
519
563
  constructor(proto) {
520
564
  this.proto = proto;
565
+ if (proto.token === Injector) {
566
+ this._instance = proto.factory();
567
+ this._resolved = true;
568
+ }
521
569
  }
522
570
  addDependency(node) {
523
571
  if (node instanceof TreeNodeTransparent) this._transparent.add(node);
@@ -529,14 +577,18 @@ var TreeNodeSingle = class {
529
577
  for (const dep of this._transparent) dep.collectPool(pool);
530
578
  pool.set(this.proto.token, this);
531
579
  }
532
- instantiate(pool) {
580
+ instantiate(pool, middlewares = []) {
533
581
  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);
582
+ for (const node of this._deps.values()) node.instantiate(pool, middlewares);
583
+ for (const dep of this._transparent) dep.instantiate(pool, middlewares);
536
584
  const retriever = retrieverFactory(this.proto.token, this._deps, this._transparent);
537
585
  const factory = this.proto.factory ?? this.proto.token.opts?.factory;
538
586
  if (!factory) throw InjectionError.notFound(this.proto.token);
539
- this._instance = InjectionContext.instantiate(factory, retriever);
587
+ const contextFactory = /* @__PURE__ */ __name(() => InjectionContext.instantiate(factory, retriever), "contextFactory");
588
+ this._instance = runMiddlewares(middlewares, {
589
+ token: this.proto.token,
590
+ factory: contextFactory
591
+ });
540
592
  this._resolved = true;
541
593
  if (pool) pool.set(this.proto.token, this);
542
594
  }
@@ -570,12 +622,16 @@ var TreeNodeTransparent = class _TreeNodeTransparent {
570
622
  for (const node of this._deps.values()) node.collectPool(pool);
571
623
  for (const dep of this._transparent) dep.collectPool(pool);
572
624
  }
573
- instantiate(pool) {
625
+ instantiate(pool, middlewares = []) {
574
626
  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);
627
+ for (const dep of this._transparent) dep.instantiate(pool, middlewares);
628
+ for (const node of this._deps.values()) node.instantiate(pool, middlewares);
577
629
  const retriever = retrieverFactory(this.proto.parent.token, this._deps, this._transparent);
578
- this._instance = InjectionContext.instantiate(this.proto.factory, retriever);
630
+ const refFactory = /* @__PURE__ */ __name(() => InjectionContext.instantiate(this.proto.factory, retriever), "refFactory");
631
+ this._instance = runMiddlewares(middlewares, {
632
+ token: this.proto.parent.token,
633
+ factory: refFactory
634
+ });
579
635
  this._resolved = true;
580
636
  }
581
637
  toString() {
@@ -598,10 +654,10 @@ var TreeNodeMulti = class _TreeNodeMulti {
598
654
  for (const dep of this._deps) dep.collectPool(pool);
599
655
  pool.set(this.proto.token, this);
600
656
  }
601
- instantiate(pool) {
657
+ instantiate(pool, middlewares = []) {
602
658
  if (this._resolved) return;
603
659
  for (const dep of this._deps) {
604
- dep.instantiate(pool);
660
+ dep.instantiate(pool, middlewares);
605
661
  if (dep instanceof TreeNodeSingle) {
606
662
  this.instance.push(dep.instance);
607
663
  } else if (dep instanceof _TreeNodeMulti) {
@@ -756,24 +812,6 @@ function resolveTreeNode(rootProto, cache, singleNodes, multiNodes, upstreamGett
756
812
  }
757
813
  __name(resolveTreeNode, "resolveTreeNode");
758
814
 
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
815
  // src/lib/utils/defer.ts
778
816
  function injectDefer(provider, options) {
779
817
  const injector = nodeInject(Injector);
@@ -999,7 +1037,11 @@ var NodeContainer = class extends Illuma {
999
1037
  return parentNode.findNode(token);
1000
1038
  }
1001
1039
  _buildInjectionTree() {
1002
- const root = new TreeRootNode(this._opts?.instant);
1040
+ const middlewares = [
1041
+ ...Illuma._middlewares,
1042
+ ...this.collectMiddlewares()
1043
+ ];
1044
+ const root = new TreeRootNode(this._opts?.instant, middlewares);
1003
1045
  const cache = /* @__PURE__ */ new Map();
1004
1046
  const nodes = [
1005
1047
  ...this._protoNodes.values(),
@@ -1016,6 +1058,12 @@ var NodeContainer = class extends Illuma {
1016
1058
  this._multiProtoNodes.clear();
1017
1059
  return root;
1018
1060
  }
1061
+ collectMiddlewares() {
1062
+ return [
1063
+ ...this._parent && "collectMiddlewares" in this._parent && typeof this._parent.collectMiddlewares === "function" ? this._parent.collectMiddlewares() : [],
1064
+ ...this.middlewares
1065
+ ];
1066
+ }
1019
1067
  /**
1020
1068
  * Bootstraps the container by resolving the dependency trees and instantiating all providers.
1021
1069
  * This must be called after all providers are registered and before calling {@link get}.