@illuma/core 1.1.0 → 1.3.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
@@ -1,79 +1,6 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
- // src/lib/errors.ts
5
- var InjectionError = class _InjectionError extends Error {
6
- static {
7
- __name(this, "InjectionError");
8
- }
9
- code;
10
- constructor(code, message) {
11
- super(`[i${code}] ${message}`), this.code = code;
12
- this.name = "InjectionError";
13
- }
14
- // Provider errors
15
- static duplicate(token) {
16
- return new _InjectionError(100, `Duplicate provider for token "${token.toString()}" detected.`);
17
- }
18
- static duplicateFactory(token) {
19
- return new _InjectionError(101, `Tried to re-provide factory for token "${token.toString()}" detected.`);
20
- }
21
- static invalidCtor(ctor) {
22
- return new _InjectionError(102, `Cannot use constructor for token "${ctor.name}". Please make sure to use @nodeInjectable() decorator`);
23
- }
24
- static invalidProvider(provider) {
25
- return new _InjectionError(103, `Cannot use provider as it is neither a NodeToken nor MultiNodeToken nor a valid constructor.:
26
- ${provider}`);
27
- }
28
- // Alias errors
29
- static invalidAlias(alias) {
30
- const aliasStr = typeof alias === "function" ? alias.name || "Unknown" : String(alias);
31
- return new _InjectionError(200, `Invalid alias target "${aliasStr}". Alias must be a NodeToken, MultiNodeToken, or a class decorated with @NodeInjectable().`);
32
- }
33
- static loopAlias(alias) {
34
- return new _InjectionError(201, `Token "${alias.toString()}" cannot alias itself in a loop.`);
35
- }
36
- // Bootstrap errors
37
- static notBootstrapped() {
38
- return new _InjectionError(300, "Cannot retrieve providers before the container has been bootstrapped.");
39
- }
40
- static bootstrapped() {
41
- return new _InjectionError(301, "Cannot modify providers after the container has been bootstrapped.");
42
- }
43
- static doubleBootstrap() {
44
- return new _InjectionError(302, "Container has already been bootstrapped and cannot be bootstrapped again.");
45
- }
46
- // Retrieval errors
47
- static notFound(token) {
48
- return new _InjectionError(400, `No provider found for "${token.toString()}".`);
49
- }
50
- static circularDependency(provider, path) {
51
- const providerStr = provider instanceof NodeBase ? provider.toString() : provider.name;
52
- const pathStr = path.map((p) => p instanceof NodeBase ? p.toString() : p.name).join(" -> ");
53
- return new _InjectionError(401, `Circular dependency detected while resolving "${providerStr}":
54
- ${pathStr}`);
55
- }
56
- // Instantiation errors
57
- static untracked(token, parent) {
58
- const tokenStr = token instanceof NodeBase ? token.toString() : token.name;
59
- const parentStr = parent instanceof NodeBase ? parent.toString() : parent.name;
60
- return new _InjectionError(500, `Cannot instantiate ${parentStr} because it depends on untracked injection ${tokenStr}. Please make sure all injections are properly tracked.`);
61
- }
62
- static outsideContext(token) {
63
- const tokenStr = token instanceof NodeBase ? token.toString() : token.name;
64
- return new _InjectionError(501, `Cannot inject "${tokenStr}" outside of an injection context.`);
65
- }
66
- static calledUtilsOutsideContext() {
67
- return new _InjectionError(502, "Cannot call injection utilities outside of an injection context.");
68
- }
69
- static instanceAccessFailed(token) {
70
- return new _InjectionError(503, `Failed to access instance for token "${token.toString()}". It was not properly instantiated.`);
71
- }
72
- static accessFailed() {
73
- return new _InjectionError(504, "Failed to access the requested instance due to an unknown error.");
74
- }
75
- };
76
-
77
4
  // src/lib/api/token.ts
78
5
  var NodeBase = class {
79
6
  static {
@@ -152,14 +79,115 @@ function extractToken(provider, isAlias = false) {
152
79
  }
153
80
  __name(extractToken, "extractToken");
154
81
 
82
+ // src/lib/errors.ts
83
+ var ERR_CODES = {
84
+ // Provider errors
85
+ DUPLICATE_PROVIDER: 100,
86
+ DUPLICATE_FACTORY: 101,
87
+ INVALID_CTOR: 102,
88
+ INVALID_PROVIDER: 103,
89
+ // Alias errors
90
+ INVALID_ALIAS: 200,
91
+ LOOP_ALIAS: 201,
92
+ // Bootstrap errors
93
+ NOT_BOOTSTRAPPED: 300,
94
+ BOOTSTRAPPED: 301,
95
+ DOUBLE_BOOTSTRAP: 302,
96
+ // Retrieval errors
97
+ NOT_FOUND: 400,
98
+ CIRCULAR_DEPENDENCY: 401,
99
+ // Instantiation errors
100
+ UNTRACKED: 500,
101
+ OUTSIDE_CONTEXT: 501,
102
+ CALLED_UTILS_OUTSIDE_CONTEXT: 502,
103
+ INSTANCE_ACCESS_FAILED: 503,
104
+ ACCESS_FAILED: 504
105
+ };
106
+ var InjectionError = class _InjectionError extends Error {
107
+ static {
108
+ __name(this, "InjectionError");
109
+ }
110
+ code;
111
+ constructor(code, message) {
112
+ super(`[i${code}] ${message}`), this.code = code;
113
+ this.name = "InjectionError";
114
+ }
115
+ // Provider errors
116
+ static duplicate(token) {
117
+ return new _InjectionError(ERR_CODES.DUPLICATE_PROVIDER, `Duplicate provider for token "${token.toString()}" detected.`);
118
+ }
119
+ static duplicateFactory(token) {
120
+ return new _InjectionError(ERR_CODES.DUPLICATE_FACTORY, `Tried to re-provide factory for token "${token.toString()}" detected.`);
121
+ }
122
+ static invalidCtor(ctor) {
123
+ return new _InjectionError(ERR_CODES.INVALID_CTOR, `Cannot use constructor for token "${ctor.name}". Please make sure to use @nodeInjectable() decorator`);
124
+ }
125
+ static invalidProvider(provider) {
126
+ return new _InjectionError(ERR_CODES.INVALID_PROVIDER, `Cannot use provider as it is neither a NodeToken nor MultiNodeToken nor a valid constructor.:
127
+ ${provider}`);
128
+ }
129
+ // Alias errors
130
+ static invalidAlias(alias) {
131
+ const aliasStr = typeof alias === "function" ? alias.name || "Unknown" : String(alias);
132
+ return new _InjectionError(ERR_CODES.INVALID_ALIAS, `Invalid alias target "${aliasStr}". Alias must be a NodeToken, MultiNodeToken, or a class decorated with @NodeInjectable().`);
133
+ }
134
+ static loopAlias(alias) {
135
+ return new _InjectionError(ERR_CODES.LOOP_ALIAS, `Token "${alias.toString()}" cannot alias itself in a loop.`);
136
+ }
137
+ // Bootstrap errors
138
+ static notBootstrapped() {
139
+ return new _InjectionError(ERR_CODES.NOT_BOOTSTRAPPED, "Cannot retrieve providers before the container has been bootstrapped.");
140
+ }
141
+ static bootstrapped() {
142
+ return new _InjectionError(ERR_CODES.BOOTSTRAPPED, "Cannot modify providers after the container has been bootstrapped.");
143
+ }
144
+ static doubleBootstrap() {
145
+ return new _InjectionError(ERR_CODES.DOUBLE_BOOTSTRAP, "Container has already been bootstrapped and cannot be bootstrapped again.");
146
+ }
147
+ // Retrieval errors
148
+ static notFound(token) {
149
+ return new _InjectionError(ERR_CODES.NOT_FOUND, `No provider found for "${token.toString()}".`);
150
+ }
151
+ static circularDependency(provider, path) {
152
+ const providerStr = provider instanceof NodeBase ? provider.toString() : provider.name;
153
+ const pathStr = path.map((p) => p instanceof NodeBase ? p.toString() : p.name).join(" -> ");
154
+ return new _InjectionError(ERR_CODES.CIRCULAR_DEPENDENCY, `Circular dependency detected while resolving "${providerStr}":
155
+ ${pathStr}`);
156
+ }
157
+ // Instantiation errors
158
+ static untracked(token, parent) {
159
+ const tokenStr = token instanceof NodeBase ? token.toString() : token.name;
160
+ const parentStr = parent instanceof NodeBase ? parent.toString() : parent.name;
161
+ return new _InjectionError(ERR_CODES.UNTRACKED, `Cannot instantiate ${parentStr} because it depends on untracked injection ${tokenStr}. Please make sure all injections are properly tracked.`);
162
+ }
163
+ static outsideContext(token) {
164
+ const tokenStr = token instanceof NodeBase ? token.toString() : token.name;
165
+ return new _InjectionError(ERR_CODES.OUTSIDE_CONTEXT, `Cannot inject "${tokenStr}" outside of an injection context.`);
166
+ }
167
+ static calledUtilsOutsideContext() {
168
+ return new _InjectionError(ERR_CODES.CALLED_UTILS_OUTSIDE_CONTEXT, "Cannot call injection utilities outside of an injection context.");
169
+ }
170
+ static instanceAccessFailed(token) {
171
+ return new _InjectionError(ERR_CODES.INSTANCE_ACCESS_FAILED, `Failed to access instance for token "${token.toString()}". It was not properly instantiated.`);
172
+ }
173
+ static accessFailed() {
174
+ return new _InjectionError(ERR_CODES.ACCESS_FAILED, "Failed to access the requested instance due to an unknown error.");
175
+ }
176
+ };
177
+
155
178
  // src/lib/api/decorator.ts
179
+ var tokenRegistry = /* @__PURE__ */ new WeakMap();
156
180
  var INJECTION_SYMBOL = Symbol("Injectable");
157
181
  function isInjectable(ctor) {
158
- return typeof ctor === "function" && isConstructor(ctor) && INJECTION_SYMBOL in ctor && ctor[INJECTION_SYMBOL] instanceof NodeToken;
182
+ return typeof ctor === "function" && isConstructor(ctor) && (tokenRegistry.has(ctor) || INJECTION_SYMBOL in ctor);
159
183
  }
160
184
  __name(isInjectable, "isInjectable");
161
185
  function getInjectableToken(ctor) {
162
- return ctor[INJECTION_SYMBOL];
186
+ if (tokenRegistry.has(ctor)) return tokenRegistry.get(ctor);
187
+ if (INJECTION_SYMBOL in ctor) {
188
+ return ctor[INJECTION_SYMBOL];
189
+ }
190
+ throw InjectionError.invalidCtor(ctor);
163
191
  }
164
192
  __name(getInjectableToken, "getInjectableToken");
165
193
  function isConstructor(fn) {
@@ -417,23 +445,29 @@ var TreeRootNode = class {
417
445
  static {
418
446
  __name(this, "TreeRootNode");
419
447
  }
448
+ instant;
420
449
  _deps = /* @__PURE__ */ new Set();
421
- _treePool = /* @__PURE__ */ new Map();
450
+ _treePool = /* @__PURE__ */ new WeakMap();
451
+ constructor(instant = true) {
452
+ this.instant = instant;
453
+ }
422
454
  get dependencies() {
423
455
  return this._deps;
424
456
  }
425
457
  addDependency(node) {
426
458
  this._deps.add(node);
427
459
  }
428
- instantiate() {
460
+ build() {
429
461
  for (const dep of this._deps) {
430
- dep.instantiate(this._treePool);
431
462
  if ("token" in dep.proto) this._treePool.set(dep.proto.token, dep);
463
+ if (this.instant) dep.instantiate(this._treePool);
464
+ else dep.collectPool(this._treePool);
432
465
  }
433
466
  }
434
467
  find(token) {
435
468
  const node = this._treePool.get(token);
436
469
  if (!node) return null;
470
+ if (!this.instant) node.instantiate(this._treePool);
437
471
  return node;
438
472
  }
439
473
  toString() {
@@ -464,6 +498,11 @@ var TreeNodeSingle = class {
464
498
  else this._deps.set(node.proto.token, node);
465
499
  node.allocations++;
466
500
  }
501
+ collectPool(pool) {
502
+ for (const node of this._deps.values()) node.collectPool(pool);
503
+ for (const dep of this._transparent) dep.collectPool(pool);
504
+ pool.set(this.proto.token, this);
505
+ }
467
506
  instantiate(pool) {
468
507
  if (this._resolved) return;
469
508
  for (const node of this._deps.values()) node.instantiate(pool);
@@ -501,6 +540,10 @@ var TreeNodeTransparent = class _TreeNodeTransparent {
501
540
  else this._deps.set(node.proto.token, node);
502
541
  node.allocations++;
503
542
  }
543
+ collectPool(pool) {
544
+ for (const node of this._deps.values()) node.collectPool(pool);
545
+ for (const dep of this._transparent) dep.collectPool(pool);
546
+ }
504
547
  instantiate(pool) {
505
548
  if (this._resolved) return;
506
549
  for (const dep of this._transparent) dep.instantiate(pool);
@@ -525,6 +568,10 @@ var TreeNodeMulti = class _TreeNodeMulti {
525
568
  constructor(proto) {
526
569
  this.proto = proto;
527
570
  }
571
+ collectPool(pool) {
572
+ for (const dep of this._deps) dep.collectPool(pool);
573
+ pool.set(this.proto.token, this);
574
+ }
528
575
  instantiate(pool) {
529
576
  if (this._resolved) return;
530
577
  for (const dep of this._deps) {
@@ -830,7 +877,7 @@ var NodeContainer = class extends Illuma {
830
877
  return parentNode.findNode(token);
831
878
  }
832
879
  _buildInjectionTree() {
833
- const root = new TreeRootNode();
880
+ const root = new TreeRootNode(this._opts?.instant);
834
881
  const cache = /* @__PURE__ */ new Map();
835
882
  const nodes = [
836
883
  ...this._protoNodes.values(),
@@ -875,7 +922,7 @@ var NodeContainer = class extends Illuma {
875
922
  value: new InjectorImpl(this)
876
923
  });
877
924
  this._rootNode = this._buildInjectionTree();
878
- this._rootNode.instantiate();
925
+ this._rootNode.build();
879
926
  this._bootstrapped = true;
880
927
  const end = performance.now();
881
928
  const duration = end - start;