@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/index.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
+ function isNotFoundError(error) {
178
+ return error instanceof InjectionError && error.code === ERR_CODES.NOT_FOUND;
179
+ }
180
+ __name(isNotFoundError, "isNotFoundError");
181
+
155
182
  // src/lib/api/decorator.ts
183
+ var tokenRegistry = /* @__PURE__ */ new WeakMap();
156
184
  var INJECTION_SYMBOL = Symbol("Injectable");
157
185
  function NodeInjectable() {
158
186
  return (ctor) => {
159
187
  const nodeToken = new NodeToken(`_${ctor.name}`, {
160
188
  factory: /* @__PURE__ */ __name(() => new ctor(), "factory")
161
189
  });
162
- ctor[INJECTION_SYMBOL] = nodeToken;
190
+ registerClassAsInjectable(ctor, nodeToken);
163
191
  return ctor;
164
192
  };
165
193
  }
@@ -168,22 +196,30 @@ function makeInjectable(ctor) {
168
196
  const nodeToken = new NodeToken(`_${ctor.name}`, {
169
197
  factory: /* @__PURE__ */ __name(() => new ctor(), "factory")
170
198
  });
171
- ctor[INJECTION_SYMBOL] = nodeToken;
199
+ registerClassAsInjectable(ctor, nodeToken);
172
200
  return ctor;
173
201
  }
174
202
  __name(makeInjectable, "makeInjectable");
175
203
  function isInjectable(ctor) {
176
- return typeof ctor === "function" && isConstructor(ctor) && INJECTION_SYMBOL in ctor && ctor[INJECTION_SYMBOL] instanceof NodeToken;
204
+ return typeof ctor === "function" && isConstructor(ctor) && (tokenRegistry.has(ctor) || INJECTION_SYMBOL in ctor);
177
205
  }
178
206
  __name(isInjectable, "isInjectable");
179
207
  function getInjectableToken(ctor) {
180
- return ctor[INJECTION_SYMBOL];
208
+ if (tokenRegistry.has(ctor)) return tokenRegistry.get(ctor);
209
+ if (INJECTION_SYMBOL in ctor) {
210
+ return ctor[INJECTION_SYMBOL];
211
+ }
212
+ throw InjectionError.invalidCtor(ctor);
181
213
  }
182
214
  __name(getInjectableToken, "getInjectableToken");
183
215
  function isConstructor(fn) {
184
216
  return typeof fn === "function" && fn.prototype && fn.prototype.constructor === fn;
185
217
  }
186
218
  __name(isConstructor, "isConstructor");
219
+ function registerClassAsInjectable(ctor, token) {
220
+ tokenRegistry.set(ctor, token);
221
+ }
222
+ __name(registerClassAsInjectable, "registerClassAsInjectable");
187
223
 
188
224
  // src/lib/plugins/core/plugin-container.ts
189
225
  var Illuma = class _Illuma {
@@ -435,23 +471,29 @@ var TreeRootNode = class {
435
471
  static {
436
472
  __name(this, "TreeRootNode");
437
473
  }
474
+ instant;
438
475
  _deps = /* @__PURE__ */ new Set();
439
- _treePool = /* @__PURE__ */ new Map();
476
+ _treePool = /* @__PURE__ */ new WeakMap();
477
+ constructor(instant = true) {
478
+ this.instant = instant;
479
+ }
440
480
  get dependencies() {
441
481
  return this._deps;
442
482
  }
443
483
  addDependency(node) {
444
484
  this._deps.add(node);
445
485
  }
446
- instantiate() {
486
+ build() {
447
487
  for (const dep of this._deps) {
448
- dep.instantiate(this._treePool);
449
488
  if ("token" in dep.proto) this._treePool.set(dep.proto.token, dep);
489
+ if (this.instant) dep.instantiate(this._treePool);
490
+ else dep.collectPool(this._treePool);
450
491
  }
451
492
  }
452
493
  find(token) {
453
494
  const node = this._treePool.get(token);
454
495
  if (!node) return null;
496
+ if (!this.instant) node.instantiate(this._treePool);
455
497
  return node;
456
498
  }
457
499
  toString() {
@@ -482,6 +524,11 @@ var TreeNodeSingle = class {
482
524
  else this._deps.set(node.proto.token, node);
483
525
  node.allocations++;
484
526
  }
527
+ collectPool(pool) {
528
+ for (const node of this._deps.values()) node.collectPool(pool);
529
+ for (const dep of this._transparent) dep.collectPool(pool);
530
+ pool.set(this.proto.token, this);
531
+ }
485
532
  instantiate(pool) {
486
533
  if (this._resolved) return;
487
534
  for (const node of this._deps.values()) node.instantiate(pool);
@@ -519,6 +566,10 @@ var TreeNodeTransparent = class _TreeNodeTransparent {
519
566
  else this._deps.set(node.proto.token, node);
520
567
  node.allocations++;
521
568
  }
569
+ collectPool(pool) {
570
+ for (const node of this._deps.values()) node.collectPool(pool);
571
+ for (const dep of this._transparent) dep.collectPool(pool);
572
+ }
522
573
  instantiate(pool) {
523
574
  if (this._resolved) return;
524
575
  for (const dep of this._transparent) dep.instantiate(pool);
@@ -543,6 +594,10 @@ var TreeNodeMulti = class _TreeNodeMulti {
543
594
  constructor(proto) {
544
595
  this.proto = proto;
545
596
  }
597
+ collectPool(pool) {
598
+ for (const dep of this._deps) dep.collectPool(pool);
599
+ pool.set(this.proto.token, this);
600
+ }
546
601
  instantiate(pool) {
547
602
  if (this._resolved) return;
548
603
  for (const dep of this._deps) {
@@ -719,6 +774,37 @@ var InjectorImpl = class {
719
774
  };
720
775
  var Injector = new NodeToken("Injector");
721
776
 
777
+ // src/lib/utils/defer.ts
778
+ function injectDefer(provider, options) {
779
+ const injector = nodeInject(Injector);
780
+ let token = provider;
781
+ if (isInjectable(provider)) token = getInjectableToken(provider);
782
+ if (!isNodeBase(token)) throw InjectionError.invalidProvider(String(token));
783
+ let resolved = false;
784
+ let instance = SHAPE_SHIFTER;
785
+ return () => {
786
+ if (resolved) return instance;
787
+ if (options?.optional) {
788
+ try {
789
+ instance = injector.get(token);
790
+ resolved = true;
791
+ return instance;
792
+ } catch (e) {
793
+ if (isNotFoundError(e)) {
794
+ resolved = true;
795
+ instance = null;
796
+ return instance;
797
+ }
798
+ throw e;
799
+ }
800
+ }
801
+ instance = injector.get(token);
802
+ resolved = true;
803
+ return instance;
804
+ };
805
+ }
806
+ __name(injectDefer, "injectDefer");
807
+
722
808
  // src/lib/utils/inheritance.ts
723
809
  function injectGroupAsync(fn, opts) {
724
810
  const { container: parent } = nodeInject(Injector);
@@ -913,7 +999,7 @@ var NodeContainer = class extends Illuma {
913
999
  return parentNode.findNode(token);
914
1000
  }
915
1001
  _buildInjectionTree() {
916
- const root = new TreeRootNode();
1002
+ const root = new TreeRootNode(this._opts?.instant);
917
1003
  const cache = /* @__PURE__ */ new Map();
918
1004
  const nodes = [
919
1005
  ...this._protoNodes.values(),
@@ -958,7 +1044,7 @@ var NodeContainer = class extends Illuma {
958
1044
  value: new InjectorImpl(this)
959
1045
  });
960
1046
  this._rootNode = this._buildInjectionTree();
961
- this._rootNode.instantiate();
1047
+ this._rootNode.build();
962
1048
  this._bootstrapped = true;
963
1049
  const end = performance.now();
964
1050
  const duration = end - start;
@@ -1028,6 +1114,7 @@ var NodeContainer = class extends Illuma {
1028
1114
  }
1029
1115
  };
1030
1116
  export {
1117
+ ERR_CODES as ILLUMA_ERR_CODES,
1031
1118
  INJECTION_SYMBOL,
1032
1119
  InjectionContext,
1033
1120
  InjectionError,
@@ -1041,12 +1128,14 @@ export {
1041
1128
  extractToken,
1042
1129
  getInjectableToken,
1043
1130
  injectAsync,
1131
+ injectDefer,
1044
1132
  injectEntryAsync,
1045
1133
  injectGroupAsync,
1046
1134
  isConstructor,
1047
1135
  isInjectable,
1048
1136
  isNodeBase,
1049
1137
  makeInjectable,
1050
- nodeInject
1138
+ nodeInject,
1139
+ registerClassAsInjectable
1051
1140
  };
1052
1141
  //# sourceMappingURL=index.js.map