@vielzeug/conduit 1.0.3 → 2.0.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/container.js CHANGED
@@ -1,262 +1,165 @@
1
- import { error as e } from "./_dev.js";
2
- import { ConduitCircularDependencyError as t, ConduitDisposedError as n, ConduitDuplicateRegistrationError as r, ConduitFrozenError as i, ConduitProviderNotFoundError as a, ConduitScopedResolutionError as o, ConduitSyncResolutionError as s, tokenName as c } from "./errors.js";
1
+ import { ConduitCircularDependencyError as e, ConduitDisposeError as t, ConduitDisposedError as n, ConduitDuplicateRegistrationError as r, ConduitProviderNotFoundError as i, ConduitScopedResolutionError as a } from "./errors.js";
3
2
  //#region src/container.ts
4
- var l = class l {
3
+ var o = class o {
5
4
  #e = /* @__PURE__ */ new Map();
6
- #t = /* @__PURE__ */ new Map();
7
- #n;
8
- #r;
5
+ #t = /* @__PURE__ */ new Set();
6
+ #n = [];
7
+ #r = new AbortController();
9
8
  #i = /* @__PURE__ */ new Set();
10
- #a = /* @__PURE__ */ new Set();
11
- #o = new AbortController();
12
- #s = !1;
13
- #c = !1;
9
+ #a = "active";
10
+ #o;
11
+ #s = [];
12
+ #c;
13
+ #l = /* @__PURE__ */ new Map();
14
+ #u;
14
15
  name;
15
16
  constructor(e, t = {}) {
16
- this.#n = e, this.#r = t.scopeTag, this.name = t.name ?? (e ? t.scopeTag ? `${e.name}:${t.scopeTag.description ?? "scope"}` : `${e.name}:child` : "root");
17
- }
18
- #l() {
19
- if (this.#s) throw new n(this.name);
20
- }
21
- #u() {
22
- if (this.#c) throw new i(this.name);
23
- }
24
- #d(e) {
25
- for (let t of this.#i) try {
26
- t(e);
27
- } catch {}
28
- this.#n && this.#n.#d(e);
17
+ this.#c = e, this.#u = t.scope, e && e.#t.add(this), this.name = t.name ?? (e ? `${e.name}:${t.scope?.description ?? "child"}` : "root");
29
18
  }
30
19
  get disposalSignal() {
31
- return this.#o.signal;
20
+ return this.#r.signal;
32
21
  }
33
22
  get disposed() {
34
- return this.#s;
23
+ return this.#a === "disposed";
35
24
  }
36
- value(e, t, n) {
37
- if (this.#l(), this.#u(), this.#e.has(e)) throw new r(e);
38
- let i = {
39
- dispose: n?.dispose,
25
+ value(e, t, n = {}) {
26
+ this.#f(), this.#p(e);
27
+ let r = {
28
+ dispose: n.dispose,
40
29
  kind: "value",
41
30
  value: t
42
31
  };
43
- return this.#e.set(e, i), this.#d({
44
- description: c(e),
45
- kind: "value",
46
- source: this.name,
47
- type: "register"
32
+ return this.#l.set(e, r), n.dispose && this.#s.push({
33
+ dispose: n.dispose,
34
+ value: t
48
35
  }), this;
49
36
  }
50
- factory(e, t, n) {
51
- if (this.#l(), this.#u(), this.#e.has(e)) throw new r(e);
37
+ factory(e, t, n, r = {}) {
38
+ this.#f(), this.#p(e);
52
39
  let i = {
53
- deps: n?.deps,
54
- dispose: n?.dispose,
55
- factory: t,
40
+ create: n,
41
+ dependencies: Object.freeze([...t]),
42
+ dispose: r.dispose,
56
43
  kind: "factory",
57
- lifetime: n?.lifetime ?? "singleton"
44
+ lifetime: r.lifetime ?? "singleton"
58
45
  };
59
- return this.#e.set(e, i), this.#d({
60
- description: c(e),
61
- kind: "factory",
62
- source: this.name,
63
- type: "register"
64
- }), this;
46
+ return this.#l.set(e, i), this;
65
47
  }
66
48
  has(e) {
67
- return this.#l(), this.#p(e) !== void 0;
49
+ return this.#f(), this.#m(e) !== void 0;
68
50
  }
69
51
  async resolve(e) {
70
- this.#l();
71
- let t = await this.#b(e, /* @__PURE__ */ new Set(), []);
72
- return this.#d({
73
- description: c(e),
74
- source: this.name,
75
- type: "resolve"
76
- }), this.#f(e, t), t;
77
- }
78
- resolveSync(e) {
79
- this.#l();
80
- let t = this.#p(e);
81
- if (!t) throw new a(e, this.name);
82
- let n = this.#S(e, t);
83
- return this.#d({
84
- description: c(e),
85
- source: this.name,
86
- type: "resolve"
87
- }), this.#f(e, n), n;
88
- }
89
- async resolveMany(e) {
90
- return Promise.all(e.map((e) => this.resolve(e)));
91
- }
92
- async resolveAll(e) {
93
- this.#l();
94
- let t = /* @__PURE__ */ new Set(), n = [], r = async (e) => {
95
- let t = await this.#b(e, /* @__PURE__ */ new Set(), []);
96
- this.#d({
97
- description: c(e),
98
- source: this.name,
99
- type: "resolve"
100
- }), this.#f(e, t);
101
- };
102
- for (let i of this.#h()) for (let [a, o] of i.#e) t.has(a) || o.kind !== "factory" || (t.add(a), (o.lifetime === "singleton" || e?.includeScoped && typeof o.lifetime == "symbol" && this.#g(o.lifetime)) && n.push(r(a)));
103
- await Promise.all(n);
104
- }
105
- inspect(e) {
106
- this.#l();
107
- let t = e?.deep ?? !0, n = [], r = /* @__PURE__ */ new Set();
108
- for (let e of this.#h()) {
109
- for (let [t, i] of e.#e) if (!r.has(t)) if (r.add(t), i.kind === "value") n.push({
110
- description: c(t),
111
- kind: "value"
112
- });
113
- else {
114
- let e = typeof i.lifetime == "symbol" ? `scope:${i.lifetime.description ?? "anonymous"}` : i.lifetime;
115
- n.push({
116
- deps: i.deps?.map((e) => c(e)),
117
- description: c(t),
118
- kind: "factory",
119
- lifetime: e
120
- });
121
- }
122
- if (!t) break;
123
- }
124
- return { nodes: n };
52
+ return this.#f(), this.#_(e, []);
125
53
  }
126
54
  validate() {
127
- this.#l();
128
- let e = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Map();
129
- for (let t of this.#h()) for (let [r, i] of t.#e) if (!e.has(r) && (e.add(r), i.kind === "factory" && i.deps && i.deps.length > 0)) {
130
- n.set(r, i.deps);
131
- for (let e of i.deps) if (this.#p(e) === void 0) throw new a(e, this.name);
132
- }
133
- if (n.size > 0) {
134
- let e = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = (a, o) => {
135
- if (e.has(a)) throw new t([...o, a]);
136
- if (!r.has(a)) {
137
- e.add(a);
138
- for (let e of n.get(a) ?? []) i(e, [...o, a]);
139
- e.delete(a), r.add(a);
140
- }
141
- };
142
- for (let e of n.keys()) r.has(e) || i(e, []);
143
- }
55
+ this.#f();
56
+ for (let { owner: e, registration: t, token: n } of this.#h()) e.#g(n, t, /* @__PURE__ */ new Set(), []);
144
57
  return this;
145
58
  }
146
- freeze() {
147
- return this.#l(), this.#c ? this : (this.validate(), this.#c = !0, this);
148
- }
149
59
  createScope(e, t) {
150
- return this.#l(), new l(this, {
60
+ return this.#f(), new o(this, {
151
61
  name: t?.name,
152
- scopeTag: e
62
+ scope: e
153
63
  });
154
64
  }
155
- on(e) {
156
- return this.#l(), this.#i.add(e), () => this.#i.delete(e);
157
- }
158
- onResolve(e) {
159
- return this.#l(), this.#a.add(e), () => this.#a.delete(e);
160
- }
161
- async dispose() {
162
- if (this.#s) return;
163
- this.#s = !0, this.#o.abort(), this.#d({
164
- source: this.name,
165
- type: "dispose"
166
- });
167
- let t = [], n = /* @__PURE__ */ new Set();
168
- for (let e of this.#e.values()) if (e.kind === "value") e.dispose && t.push(Promise.resolve().then(() => e.dispose(e.value)));
169
- else if (n.add(e), e.dispose) {
170
- let n = this.#t.get(e);
171
- n?.resolved && t.push(Promise.resolve().then(() => e.dispose(n.instance)));
65
+ dispose() {
66
+ return this.#a === "disposed" ? Promise.resolve() : this.#o ? this.#o : (this.#a = "disposing", this.#r.abort(), this.#o = this.#d(), this.#o);
67
+ }
68
+ async #d() {
69
+ let e = await Promise.allSettled([...this.#t].map((e) => e.dispose()));
70
+ await Promise.allSettled([...this.#i]);
71
+ let n = [...this.#n, ...e.flatMap((e) => e.status === "rejected" ? e.reason instanceof t ? e.reason.errors : [e.reason] : [])];
72
+ for (let e of [...this.#s].reverse()) if (e.dispose) try {
73
+ await e.dispose(e.value);
74
+ } catch (e) {
75
+ n.push(e);
172
76
  }
173
- for (let [e, r] of this.#t) !n.has(e) && e.dispose && r.resolved && t.push(Promise.resolve().then(() => e.dispose(r.instance)));
174
- let r = await Promise.allSettled(t);
175
- this.#t.clear(), this.#e.clear(), this.#i.clear(), this.#a.clear();
176
- for (let t of r) t.status === "rejected" && e(`dispose hook failed in container '${this.name}':`, t.reason);
77
+ if (this.#e.clear(), this.#t.clear(), this.#n = [], this.#s = [], this.#l.clear(), this.#c && this.#c.#t.delete(this), this.#a = "disposed", n.length) throw new t(n);
177
78
  }
178
- [Symbol.asyncDispose]() {
179
- return this.dispose();
79
+ async [Symbol.asyncDispose]() {
80
+ await this.dispose();
180
81
  }
181
- #f(e, t) {
182
- for (let n of this.#a) try {
183
- n(e, t);
184
- } catch {}
185
- this.#n && this.#n.#f(e, t);
82
+ #f() {
83
+ if (this.#a !== "active") throw new n(this.name);
186
84
  }
187
85
  #p(e) {
188
- let t = this.#e.get(e);
189
- if (t) return t;
190
- if (this.#n) return this.#n.#l(), this.#n.#p(e);
86
+ if (this.#l.has(e)) throw new r(e);
191
87
  }
192
88
  #m(e) {
193
- for (let t of this.#h()) if (t.#e.has(e)) return t;
194
- return this;
195
- }
196
- *#h() {
197
- yield this;
198
- let e = this.#n;
199
- for (; e;) yield e, e = e.#n;
200
- }
201
- #g(e) {
202
- if (this.#r === e) return this;
203
- if (this.#n) return this.#n.#g(e);
204
- }
205
- #_(e) {
206
- let t = this.#t.get(e);
207
- return t || (t = { resolved: !1 }, this.#t.set(e, t)), t;
208
- }
209
- #v(e, t) {
210
- return {
211
- resolve: (n) => this.#b(n, new Set(e), t),
212
- resolveSync: (e) => this.resolveSync(e)
89
+ let t = this.#l.get(e);
90
+ if (t) return {
91
+ owner: this,
92
+ registration: t
213
93
  };
214
- }
215
- #y(e, t, n, r) {
216
- return e.resolved ? Promise.resolve(e.instance) : (e.promise ||= Promise.resolve(t.factory(this.#v(n, r))).then((t) => (e.instance = t, e.resolved = !0, t)).catch((t) => {
217
- throw e.rejection = t, t;
218
- }), e.promise);
219
- }
220
- async #b(e, n, r) {
221
- if (n.has(e)) throw new t([...r, e]);
222
- let i = this.#p(e);
223
- if (!i) throw new a(e, this.name);
224
- n.add(e);
225
- let o = await this.#x(e, i, n, [...r, e]);
226
- return n.delete(e), o;
227
- }
228
- async #x(e, t, n, r) {
229
- if (t.kind === "value") return t.value;
230
- let { lifetime: i } = t;
231
- if (typeof i == "symbol") {
232
- let a = this.#g(i);
233
- if (!a) throw new o(e, i);
234
- return this.#y(a.#_(t), t, n, r);
94
+ if (this.#c) return this.#c.#m(e);
95
+ }
96
+ #h() {
97
+ let e = this.#c ? this.#c.#h() : [], t = [...this.#l].flatMap(([e, t]) => t.kind === "factory" ? [{
98
+ owner: this,
99
+ registration: t,
100
+ token: e
101
+ }] : []);
102
+ return [...e, ...t];
103
+ }
104
+ #g(t, n, r, a) {
105
+ if (r.has(t)) throw new e([...a, t]);
106
+ r.add(t);
107
+ for (let e of n.dependencies) {
108
+ let n = this.#m(e);
109
+ if (!n) throw new i(e, this.name);
110
+ n.registration.kind === "factory" && n.owner.#g(e, n.registration, r, [...a, t]);
235
111
  }
236
- if (i === "transient") return t.factory(this.#v(n, r));
237
- let a = this.#m(e);
238
- return this.#y(a.#_(t), t, n, r);
239
- }
240
- #S(e, t) {
241
- if (t.kind === "value") return t.value;
242
- let { lifetime: n } = t;
243
- if (typeof n == "symbol") {
244
- let r = this.#g(n);
245
- if (!r) throw new o(e, n);
246
- let i = r.#t.get(t);
247
- if (i?.resolved) return i.instance;
248
- throw i?.rejection === void 0 ? new s(e, n) : i.rejection;
112
+ r.delete(t);
113
+ }
114
+ async #_(t, n) {
115
+ if (n.includes(t)) throw new e([...n, t]);
116
+ let r = this.#m(t);
117
+ if (!r) throw new i(t, this.name);
118
+ if (r.registration.kind === "value") return r.registration.value;
119
+ let a = this.#v(r.owner, r.registration, t);
120
+ if (r.registration.lifetime === "transient") return this.#b(r.registration, a, [...n, t]);
121
+ let o = a.#e.get(r.registration);
122
+ if (o?.value !== void 0) return o.value;
123
+ if (o?.promise) return o.promise;
124
+ let s = {}, c = a.#b(r.registration, a, [...n, t]).then((e) => (s.value = e, e));
125
+ return s.promise = c, a.#e.set(r.registration, s), c;
126
+ }
127
+ #v(e, t, n) {
128
+ if (t.lifetime === "singleton") return e;
129
+ if (t.lifetime === "transient") return this;
130
+ let r = this.#y(t.lifetime);
131
+ if (!r) throw new a(n, t.lifetime);
132
+ return r;
133
+ }
134
+ #y(e) {
135
+ return this.#u === e ? this : this.#c ? this.#c.#y(e) : void 0;
136
+ }
137
+ async #b(e, t, r) {
138
+ let i = Promise.all(e.dependencies.map((e) => t.#_(e, r))).then((t) => e.create(...t));
139
+ t.#i.add(i);
140
+ try {
141
+ let r = await i;
142
+ if (t.#a !== "active") {
143
+ if (e.dispose) try {
144
+ await e.dispose(r);
145
+ } catch (e) {
146
+ t.#n.push(e);
147
+ }
148
+ throw new n(t.name);
149
+ }
150
+ return e.dispose && t.#s.push({
151
+ dispose: e.dispose,
152
+ value: r
153
+ }), r;
154
+ } finally {
155
+ t.#i.delete(i);
249
156
  }
250
- if (n === "transient") throw new s(e, n);
251
- let r = this.#m(e).#t.get(t);
252
- if (r?.resolved) return r.instance;
253
- throw r?.rejection === void 0 ? new s(e, n) : r.rejection;
254
157
  }
255
158
  };
256
- function u(e) {
257
- return new l(void 0, { name: e?.name ?? "root" });
159
+ function s(e) {
160
+ return new o(void 0, e);
258
161
  }
259
162
  //#endregion
260
- export { u as createContainer };
163
+ export { s as createContainer };
261
164
 
262
165
  //# sourceMappingURL=container.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"container.js","names":["#parent","#scopeTag","#disposed","#frozen","#listeners","#emit","#disposeController","#assertNotDisposed","#assertNotFrozen","#registry","#getRegistration","#resolveToken","#fireInterceptors","#resolveSyncReg","#ancestors","#findScope","#resolveInterceptors","#cache","#makeResolver","#resolveReg","#populate","#getCache","#findOwnerContainer"],"sources":["../src/container.ts"],"sourcesContent":["import type {\n Container,\n ContainerEvent,\n ContainerEventListener,\n ContainerGraph,\n ContainerNode,\n FactoryOptions,\n FactoryResolver,\n Lifetime,\n ResolveInterceptor,\n ScopeToken,\n Token,\n ValueOptions,\n} from './types.js';\n\nimport { error } from './_dev';\nimport {\n ConduitCircularDependencyError,\n ConduitDisposedError,\n ConduitFrozenError,\n ConduitDuplicateRegistrationError,\n ConduitProviderNotFoundError,\n ConduitScopedResolutionError,\n ConduitSyncResolutionError,\n tokenName,\n} from './errors.js';\n\n// ---------------------------------------------------------------------------\n// Internal registration types\n// ---------------------------------------------------------------------------\n\ntype ValueRegistration<T> = {\n dispose?: (instance: T) => Promise<void> | void;\n kind: 'value';\n value: T;\n};\n\ntype FactoryDescriptor<T> = {\n deps?: readonly Token<any>[];\n dispose?: (instance: T) => Promise<void> | void;\n factory: (resolver: FactoryResolver) => Promise<T> | T;\n kind: 'factory';\n lifetime: Lifetime;\n};\n\ntype Registration<T = unknown> = FactoryDescriptor<T> | ValueRegistration<T>;\n\n// Cache state is separate from the immutable factory descriptor.\ntype CacheEntry<T = unknown> = {\n instance?: T;\n // Retained on failure — subsequent calls rethrow the same rejection (no silent retry).\n promise?: Promise<T>;\n // Stored on rejection so resolveSync() can rethrow the original error synchronously.\n rejection?: unknown;\n resolved: boolean;\n};\n\n// ---------------------------------------------------------------------------\n// ContainerImpl\n// ---------------------------------------------------------------------------\n\nclass ContainerImpl implements Container {\n #registry = new Map<Token<any>, Registration<any>>();\n #cache = new Map<FactoryDescriptor<any>, CacheEntry<any>>();\n #parent?: ContainerImpl;\n #scopeTag?: ScopeToken;\n #listeners = new Set<ContainerEventListener>();\n #resolveInterceptors = new Set<ResolveInterceptor>();\n #disposeController = new AbortController();\n #disposed = false;\n #frozen = false;\n readonly name: string;\n\n constructor(parent?: ContainerImpl, opts: { name?: string; scopeTag?: ScopeToken } = {}) {\n this.#parent = parent;\n this.#scopeTag = opts.scopeTag;\n this.name =\n opts.name ??\n (parent\n ? opts.scopeTag\n ? `${parent.name}:${opts.scopeTag.description ?? 'scope'}`\n : `${parent.name}:child`\n : 'root');\n }\n\n #assertNotDisposed(): void {\n if (this.#disposed) throw new ConduitDisposedError(this.name);\n }\n\n #assertNotFrozen(): void {\n if (this.#frozen) throw new ConduitFrozenError(this.name);\n }\n\n // Emit to local listeners then propagate up to parent.\n #emit(event: ContainerEvent): void {\n for (const listener of this.#listeners) {\n try {\n listener(event);\n } catch {\n // swallowed — listener errors must not disrupt container operation\n }\n }\n\n if (this.#parent) this.#parent.#emit(event);\n }\n\n get disposalSignal(): AbortSignal {\n return this.#disposeController.signal;\n }\n\n get disposed(): boolean {\n return this.#disposed;\n }\n\n value<T>(tok: Token<T>, val: T, opts?: ValueOptions<T>): this {\n this.#assertNotDisposed();\n this.#assertNotFrozen();\n\n if (this.#registry.has(tok)) throw new ConduitDuplicateRegistrationError(tok);\n\n const reg: ValueRegistration<T> = { dispose: opts?.dispose, kind: 'value', value: val };\n\n this.#registry.set(tok, reg);\n this.#emit({ description: tokenName(tok), kind: 'value', source: this.name, type: 'register' });\n\n return this;\n }\n\n factory<T>(tok: Token<T>, fn: (resolver: FactoryResolver) => Promise<T> | T, opts?: FactoryOptions<T>): this {\n this.#assertNotDisposed();\n this.#assertNotFrozen();\n\n if (this.#registry.has(tok)) throw new ConduitDuplicateRegistrationError(tok);\n\n const reg: FactoryDescriptor<T> = {\n deps: opts?.deps,\n dispose: opts?.dispose,\n factory: fn,\n kind: 'factory',\n lifetime: opts?.lifetime ?? 'singleton',\n };\n\n this.#registry.set(tok, reg);\n this.#emit({ description: tokenName(tok), kind: 'factory', source: this.name, type: 'register' });\n\n return this;\n }\n\n has<T>(tok: Token<T>): boolean {\n this.#assertNotDisposed();\n\n return this.#getRegistration(tok) !== undefined;\n }\n\n async resolve<T>(tok: Token<T>): Promise<T> {\n this.#assertNotDisposed();\n\n const result = await this.#resolveToken(tok, new Set(), []);\n\n this.#emit({ description: tokenName(tok), source: this.name, type: 'resolve' });\n this.#fireInterceptors(tok, result);\n\n return result;\n }\n\n resolveSync<T>(tok: Token<T>): T {\n this.#assertNotDisposed();\n\n const reg = this.#getRegistration(tok) as Registration<T> | undefined;\n\n if (!reg) throw new ConduitProviderNotFoundError(tok, this.name);\n\n const result = this.#resolveSyncReg(tok, reg);\n\n this.#emit({ description: tokenName(tok), source: this.name, type: 'resolve' });\n this.#fireInterceptors(tok, result);\n\n return result;\n }\n\n async resolveMany<const D extends Token<any>[]>(\n toks: D,\n ): Promise<{ [K in keyof D]: D[K] extends Token<infer U> ? U : never }> {\n return Promise.all(toks.map((t) => this.resolve(t))) as Promise<{\n [K in keyof D]: D[K] extends Token<infer U> ? U : never;\n }>;\n }\n\n async resolveAll(opts?: { includeScoped?: boolean }): Promise<void> {\n this.#assertNotDisposed();\n\n const seen = new Set<Token<any>>();\n const work: Promise<unknown>[] = [];\n\n const resolveAndNotify = async (tok: Token<unknown>): Promise<void> => {\n const value = await this.#resolveToken(tok, new Set(), []);\n\n this.#emit({ description: tokenName(tok), source: this.name, type: 'resolve' });\n this.#fireInterceptors(tok, value);\n };\n\n for (const c of this.#ancestors()) {\n for (const [tok, reg] of c.#registry) {\n if (seen.has(tok as Token<any>) || reg.kind !== 'factory') continue;\n\n seen.add(tok as Token<any>);\n\n if (reg.lifetime === 'singleton') {\n work.push(resolveAndNotify(tok as Token<unknown>));\n } else if (opts?.includeScoped && typeof reg.lifetime === 'symbol') {\n const scopeContainer = this.#findScope(reg.lifetime);\n\n if (scopeContainer) work.push(resolveAndNotify(tok as Token<unknown>));\n }\n }\n }\n\n await Promise.all(work);\n }\n\n inspect(opts?: { deep?: boolean }): ContainerGraph {\n this.#assertNotDisposed();\n\n const deep = opts?.deep ?? true;\n const nodes: ContainerNode[] = [];\n const seen = new Set<Token<any>>();\n\n for (const c of this.#ancestors()) {\n for (const [tok, reg] of c.#registry) {\n if (!seen.has(tok as Token<any>)) {\n seen.add(tok as Token<any>);\n\n if (reg.kind === 'value') {\n nodes.push({ description: tokenName(tok as Token<any>), kind: 'value' });\n } else {\n const lifetime: ContainerNode['lifetime'] =\n typeof reg.lifetime === 'symbol'\n ? `scope:${(reg.lifetime as symbol).description ?? 'anonymous'}`\n : (reg.lifetime as 'singleton' | 'transient');\n\n nodes.push({\n deps: reg.deps?.map((d) => tokenName(d)),\n description: tokenName(tok as Token<any>),\n kind: 'factory',\n lifetime,\n });\n }\n }\n }\n\n if (!deep) break;\n }\n\n return { nodes };\n }\n\n /**\n * Validate the registration graph without freezing it.\n * Checks statically-declared `deps`: throws `ConduitProviderNotFoundError` if a\n * declared dep is missing, or `ConduitCircularDependencyError` if they form a cycle.\n * Throws `ConduitDisposedError` if the container is already disposed.\n */\n validate(): this {\n this.#assertNotDisposed();\n\n const visited = new Set<Token<any>>();\n\n // Build token→deps map for static cycle detection.\n const staticDeps = new Map<Token<any>, readonly Token<any>[]>();\n\n for (const c of this.#ancestors()) {\n for (const [tok, reg] of c.#registry) {\n if (visited.has(tok as Token<any>)) continue;\n\n visited.add(tok as Token<any>);\n\n if (reg.kind === 'factory' && reg.deps && reg.deps.length > 0) {\n staticDeps.set(tok as Token<any>, reg.deps);\n\n for (const dep of reg.deps) {\n if (this.#getRegistration(dep) === undefined) {\n throw new ConduitProviderNotFoundError(dep, this.name);\n }\n }\n }\n }\n }\n\n // Static cycle detection over declared deps.\n if (staticDeps.size > 0) {\n const visiting = new Set<Token<any>>();\n const done = new Set<Token<any>>();\n\n const dfs = (tok: Token<any>, path: Token<any>[]): void => {\n if (visiting.has(tok)) throw new ConduitCircularDependencyError([...path, tok]);\n\n if (done.has(tok)) return;\n\n visiting.add(tok);\n\n for (const dep of staticDeps.get(tok) ?? []) {\n dfs(dep, [...path, tok]);\n }\n\n visiting.delete(tok);\n done.add(tok);\n };\n\n for (const tok of staticDeps.keys()) {\n if (!done.has(tok)) dfs(tok, []);\n }\n }\n\n return this;\n }\n\n freeze(): this {\n this.#assertNotDisposed();\n\n if (this.#frozen) return this;\n\n this.validate();\n this.#frozen = true;\n\n return this;\n }\n\n createScope(scopeToken?: ScopeToken, opts?: { name?: string }): Container {\n this.#assertNotDisposed();\n\n return new ContainerImpl(this, { name: opts?.name, scopeTag: scopeToken });\n }\n\n on(listener: ContainerEventListener): () => void {\n this.#assertNotDisposed();\n this.#listeners.add(listener);\n\n return () => this.#listeners.delete(listener);\n }\n\n onResolve(interceptor: ResolveInterceptor): () => void {\n this.#assertNotDisposed();\n this.#resolveInterceptors.add(interceptor);\n\n return () => this.#resolveInterceptors.delete(interceptor);\n }\n\n async dispose(): Promise<void> {\n if (this.#disposed) return;\n\n this.#disposed = true;\n this.#disposeController.abort();\n this.#emit({ source: this.name, type: 'dispose' });\n\n const hooks: Promise<void>[] = [];\n const ownDescriptors = new Set<FactoryDescriptor<any>>();\n\n for (const reg of this.#registry.values()) {\n if (reg.kind === 'value') {\n if (reg.dispose) hooks.push(Promise.resolve().then(() => reg.dispose!(reg.value)));\n } else {\n ownDescriptors.add(reg);\n\n if (reg.dispose) {\n const entry = this.#cache.get(reg);\n\n if (entry?.resolved) hooks.push(Promise.resolve().then(() => reg.dispose!(entry.instance as any)));\n }\n }\n }\n\n // Inherited scope instances cached locally (not in #registry)\n for (const [descriptor, entry] of this.#cache) {\n if (!ownDescriptors.has(descriptor) && descriptor.dispose && entry.resolved) {\n hooks.push(Promise.resolve().then(() => descriptor.dispose!(entry.instance as any)));\n }\n }\n\n const outcomes = await Promise.allSettled(hooks);\n\n this.#cache.clear();\n this.#registry.clear();\n this.#listeners.clear();\n this.#resolveInterceptors.clear();\n\n for (const outcome of outcomes) {\n if (outcome.status === 'rejected') {\n error(`dispose hook failed in container '${this.name}':`, outcome.reason);\n }\n }\n }\n\n [Symbol.asyncDispose](): Promise<void> {\n return this.dispose();\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n #fireInterceptors<T>(tok: Token<T>, value: T): void {\n for (const interceptor of this.#resolveInterceptors) {\n try {\n interceptor(tok, value);\n } catch {\n // swallowed — interceptor errors must not disrupt resolution\n }\n }\n\n if (this.#parent) this.#parent.#fireInterceptors(tok, value);\n }\n\n #getRegistration<T>(tok: Token<T>): Registration<T> | undefined {\n const local = this.#registry.get(tok) as Registration<T> | undefined;\n\n if (local) return local;\n\n if (!this.#parent) return undefined;\n\n this.#parent.#assertNotDisposed();\n\n return this.#parent.#getRegistration(tok);\n }\n\n #findOwnerContainer<T>(tok: Token<T>): ContainerImpl {\n for (const c of this.#ancestors()) {\n if (c.#registry.has(tok)) return c;\n }\n\n return this;\n }\n\n *#ancestors(): Generator<ContainerImpl> {\n yield this;\n\n let parent = this.#parent;\n\n while (parent) {\n yield parent;\n parent = parent.#parent;\n }\n }\n\n #findScope(scopeToken: ScopeToken): ContainerImpl | undefined {\n if (this.#scopeTag === scopeToken) return this;\n\n if (!this.#parent) return undefined;\n\n return this.#parent.#findScope(scopeToken);\n }\n\n #getCache<T>(descriptor: FactoryDescriptor<T>): CacheEntry<T> {\n let entry = this.#cache.get(descriptor) as CacheEntry<T> | undefined;\n\n if (!entry) {\n entry = { resolved: false };\n this.#cache.set(descriptor, entry);\n }\n\n return entry;\n }\n\n /** Build a FactoryResolver scoped to the current resolution context. */\n #makeResolver(visiting: Set<Token<any>>, path: Token<any>[]): FactoryResolver {\n return {\n resolve: <T>(tok: Token<T>): Promise<T> => this.#resolveToken(tok, new Set(visiting), path),\n resolveSync: <T>(tok: Token<T>): T => this.resolveSync(tok),\n };\n }\n\n /** Populate a cache entry for a factory, deduplicating concurrent calls. */\n #populate<T>(\n entry: CacheEntry<T>,\n reg: FactoryDescriptor<T>,\n visiting: Set<Token<any>>,\n path: Token<any>[],\n ): Promise<T> {\n if (entry.resolved) return Promise.resolve(entry.instance as T);\n\n if (entry.promise) return entry.promise;\n\n entry.promise = Promise.resolve(reg.factory(this.#makeResolver(visiting, path)))\n .then((instance) => {\n entry.instance = instance;\n entry.resolved = true;\n\n return instance;\n })\n .catch((err) => {\n entry.rejection = err;\n throw err;\n });\n\n return entry.promise;\n }\n\n async #resolveToken<T>(tok: Token<T>, visiting: Set<Token<any>>, path: Token<any>[]): Promise<T> {\n if (visiting.has(tok)) throw new ConduitCircularDependencyError([...path, tok]);\n\n const reg = this.#getRegistration(tok) as Registration<T> | undefined;\n\n if (!reg) throw new ConduitProviderNotFoundError(tok, this.name);\n\n visiting.add(tok);\n\n const result = await this.#resolveReg(tok, reg, visiting, [...path, tok]);\n\n visiting.delete(tok);\n\n return result;\n }\n\n async #resolveReg<T>(tok: Token<T>, reg: Registration<T>, visiting: Set<Token<any>>, path: Token<any>[]): Promise<T> {\n if (reg.kind === 'value') return reg.value;\n\n const { lifetime } = reg;\n\n // Named scope token\n if (typeof lifetime === 'symbol') {\n const scopeContainer = this.#findScope(lifetime);\n\n if (!scopeContainer) throw new ConduitScopedResolutionError(tok, lifetime);\n\n return this.#populate(scopeContainer.#getCache(reg), reg, visiting, path);\n }\n\n if (lifetime === 'transient') {\n return reg.factory(this.#makeResolver(visiting, path));\n }\n\n // singleton — cache in owner container\n const cacheContainer = this.#findOwnerContainer(tok);\n\n return this.#populate(cacheContainer.#getCache(reg), reg, visiting, path);\n }\n\n #resolveSyncReg<T>(tok: Token<T>, reg: Registration<T>): T {\n if (reg.kind === 'value') return reg.value;\n\n const { lifetime } = reg;\n\n if (typeof lifetime === 'symbol') {\n const scopeContainer = this.#findScope(lifetime);\n\n if (!scopeContainer) throw new ConduitScopedResolutionError(tok, lifetime);\n\n const entry = scopeContainer.#cache.get(reg);\n\n if (entry?.resolved) return entry.instance as T;\n\n if (entry?.rejection !== undefined) throw entry.rejection;\n\n throw new ConduitSyncResolutionError(tok, lifetime);\n }\n\n if (lifetime === 'transient') throw new ConduitSyncResolutionError(tok, lifetime);\n\n const cacheContainer = this.#findOwnerContainer(tok);\n const entry = cacheContainer.#cache.get(reg);\n\n if (entry?.resolved) return entry.instance as T;\n\n if (entry?.rejection !== undefined) throw entry.rejection;\n\n throw new ConduitSyncResolutionError(tok, lifetime);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public factory\n// ---------------------------------------------------------------------------\n\nexport function createContainer(opts?: { name?: string }): Container {\n return new ContainerImpl(undefined, { name: opts?.name ?? 'root' });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"container.js","names":["#parent","#scope","#children","#disposalController","#lifecycle","#assertActive","#assertUnregistered","#registry","#owned","#lookup","#resolve","#factories","#validatePath","#disposePromise","#finishDisposal","#inFlight","#cleanupFailures","#cache","#ownerFor","#create","#scopeOwner"],"sources":["../src/container.ts"],"sourcesContent":["import type { Container, FactoryOptions, InferTokens, Lifetime, ScopeToken, Token, ValueOptions } from './types.js';\n\nimport {\n ConduitCircularDependencyError,\n ConduitDisposeError,\n ConduitDisposedError,\n ConduitDuplicateRegistrationError,\n ConduitProviderNotFoundError,\n ConduitScopedResolutionError,\n} from './errors.js';\n\ntype Disposer = (value: never) => Promise<void> | void;\n\ntype ValueRegistration<T> = Readonly<{\n dispose?: Disposer;\n kind: 'value';\n value: T;\n}>;\n\ntype FactoryRegistration<T = unknown> = Readonly<{\n create: (...values: unknown[]) => Promise<T> | T;\n dependencies: readonly Token<unknown>[];\n dispose?: Disposer;\n kind: 'factory';\n lifetime: Lifetime;\n}>;\n\ntype Registration<T = unknown> = FactoryRegistration<T> | ValueRegistration<T>;\ntype OwnedResource = Readonly<{ dispose?: Disposer; value: unknown }>;\ntype CacheEntry = { promise?: Promise<unknown>; value?: unknown };\ntype Lifecycle = 'active' | 'disposed' | 'disposing';\n\nclass ContainerImpl implements Container {\n #cache = new Map<FactoryRegistration<any>, CacheEntry>();\n #children = new Set<ContainerImpl>();\n #cleanupFailures: unknown[] = [];\n #disposalController = new AbortController();\n #inFlight = new Set<Promise<unknown>>();\n #lifecycle: Lifecycle = 'active';\n #disposePromise?: Promise<void>;\n #owned: OwnedResource[] = [];\n #parent?: ContainerImpl;\n #registry = new Map<Token<any>, Registration<any>>();\n #scope?: ScopeToken;\n readonly name: string;\n\n constructor(parent?: ContainerImpl, options: { name?: string; scope?: ScopeToken } = {}) {\n this.#parent = parent;\n this.#scope = options.scope;\n\n if (parent) parent.#children.add(this);\n\n this.name = options.name ?? (parent ? `${parent.name}:${options.scope?.description ?? 'child'}` : 'root');\n }\n\n get disposalSignal(): AbortSignal {\n return this.#disposalController.signal;\n }\n\n get disposed(): boolean {\n return this.#lifecycle === 'disposed';\n }\n\n value<T>(token: Token<T>, value: T, options: ValueOptions<T> = {}): this {\n this.#assertActive();\n this.#assertUnregistered(token);\n\n const registration: ValueRegistration<T> = {\n dispose: options.dispose as Disposer | undefined,\n kind: 'value',\n value,\n };\n\n this.#registry.set(token, registration);\n\n if (options.dispose) this.#owned.push({ dispose: options.dispose, value });\n\n return this;\n }\n\n factory<T, Dependencies extends readonly Token<unknown>[]>(\n token: Token<T>,\n dependencies: Dependencies,\n create: (...values: InferTokens<Dependencies>) => Promise<T> | T,\n options: FactoryOptions<T> = {},\n ): this {\n this.#assertActive();\n this.#assertUnregistered(token);\n\n const registration: FactoryRegistration<T> = {\n create: create as (...values: unknown[]) => Promise<T> | T,\n dependencies: Object.freeze([...dependencies]),\n dispose: options.dispose as Disposer | undefined,\n kind: 'factory',\n lifetime: options.lifetime ?? 'singleton',\n };\n\n this.#registry.set(token, registration);\n\n return this;\n }\n\n has<T>(token: Token<T>): boolean {\n this.#assertActive();\n\n return this.#lookup(token) !== undefined;\n }\n\n async resolve<T>(token: Token<T>): Promise<T> {\n this.#assertActive();\n\n return this.#resolve(token, []);\n }\n\n validate(): this {\n this.#assertActive();\n\n for (const { owner, registration, token } of this.#factories()) {\n owner.#validatePath(token, registration, new Set(), []);\n }\n\n return this;\n }\n\n createScope(scope?: ScopeToken, options?: { name?: string }): Container {\n this.#assertActive();\n\n return new ContainerImpl(this, { name: options?.name, scope });\n }\n\n dispose(): Promise<void> {\n if (this.#lifecycle === 'disposed') return Promise.resolve();\n\n if (this.#disposePromise) return this.#disposePromise;\n\n this.#lifecycle = 'disposing';\n this.#disposalController.abort();\n this.#disposePromise = this.#finishDisposal();\n\n return this.#disposePromise;\n }\n\n async #finishDisposal(): Promise<void> {\n const childOutcomes = await Promise.allSettled([...this.#children].map((child) => child.dispose()));\n\n await Promise.allSettled([...this.#inFlight]);\n\n const failures = [\n ...this.#cleanupFailures,\n ...childOutcomes.flatMap((outcome) => {\n if (outcome.status !== 'rejected') return [];\n\n return outcome.reason instanceof ConduitDisposeError ? outcome.reason.errors : [outcome.reason];\n }),\n ];\n\n for (const resource of [...this.#owned].reverse()) {\n if (!resource.dispose) continue;\n\n try {\n await resource.dispose(resource.value as never);\n } catch (error) {\n failures.push(error);\n }\n }\n\n this.#cache.clear();\n this.#children.clear();\n this.#cleanupFailures = [];\n this.#owned = [];\n this.#registry.clear();\n\n if (this.#parent) this.#parent.#children.delete(this);\n\n this.#lifecycle = 'disposed';\n\n if (failures.length) throw new ConduitDisposeError(failures);\n }\n\n async [Symbol.asyncDispose](): Promise<void> {\n await this.dispose();\n }\n\n #assertActive(): void {\n if (this.#lifecycle !== 'active') throw new ConduitDisposedError(this.name);\n }\n\n #assertUnregistered(token: Token<unknown>): void {\n if (this.#registry.has(token)) throw new ConduitDuplicateRegistrationError(token);\n }\n\n #lookup<T>(token: Token<T>): { owner: ContainerImpl; registration: Registration<T> } | undefined {\n const local = this.#registry.get(token) as Registration<T> | undefined;\n\n if (local) return { owner: this, registration: local };\n\n if (!this.#parent) return undefined;\n\n return this.#parent.#lookup(token);\n }\n\n #factories(): { owner: ContainerImpl; registration: FactoryRegistration; token: Token<unknown> }[] {\n const parentFactories = this.#parent ? this.#parent.#factories() : [];\n const localFactories = [...this.#registry].flatMap(([token, registration]) =>\n registration.kind === 'factory' ? [{ owner: this, registration, token }] : [],\n );\n\n return [...parentFactories, ...localFactories];\n }\n\n #validatePath(\n token: Token<unknown>,\n registration: FactoryRegistration,\n visiting: Set<Token<unknown>>,\n path: Token<unknown>[],\n ): void {\n if (visiting.has(token)) throw new ConduitCircularDependencyError([...path, token]);\n\n visiting.add(token);\n\n for (const dependency of registration.dependencies) {\n const found = this.#lookup(dependency);\n\n if (!found) throw new ConduitProviderNotFoundError(dependency, this.name);\n\n if (found.registration.kind === 'factory') {\n found.owner.#validatePath(dependency, found.registration, visiting, [...path, token]);\n }\n }\n\n visiting.delete(token);\n }\n\n async #resolve<T>(token: Token<T>, path: Token<unknown>[]): Promise<T> {\n if (path.includes(token)) throw new ConduitCircularDependencyError([...path, token]);\n\n const found = this.#lookup(token);\n\n if (!found) throw new ConduitProviderNotFoundError(token, this.name);\n\n if (found.registration.kind === 'value') return found.registration.value as T;\n\n const owner = this.#ownerFor(found.owner, found.registration, token);\n\n if (found.registration.lifetime === 'transient') {\n return this.#create(found.registration, owner, [...path, token]) as Promise<T>;\n }\n\n const existing = owner.#cache.get(found.registration);\n\n if (existing?.value !== undefined) return existing.value as T;\n\n if (existing?.promise) return existing.promise as Promise<T>;\n\n const entry: CacheEntry = {};\n const promise = owner.#create(found.registration, owner, [...path, token]).then((value) => {\n entry.value = value;\n\n return value;\n });\n\n entry.promise = promise;\n owner.#cache.set(found.registration, entry);\n\n return promise as Promise<T>;\n }\n\n #ownerFor(owner: ContainerImpl, registration: FactoryRegistration, token: Token<unknown>): ContainerImpl {\n if (registration.lifetime === 'singleton') return owner;\n\n if (registration.lifetime === 'transient') return this;\n\n const scope = this.#scopeOwner(registration.lifetime);\n\n if (!scope) throw new ConduitScopedResolutionError(token, registration.lifetime);\n\n return scope;\n }\n\n #scopeOwner(scope: ScopeToken): ContainerImpl | undefined {\n if (this.#scope === scope) return this;\n\n return this.#parent ? this.#parent.#scopeOwner(scope) : undefined;\n }\n\n async #create(registration: FactoryRegistration, owner: ContainerImpl, path: Token<unknown>[]): Promise<unknown> {\n const promise = Promise.all(registration.dependencies.map((dependency) => owner.#resolve(dependency, path))).then(\n (dependencies) => registration.create(...dependencies),\n );\n\n owner.#inFlight.add(promise);\n\n try {\n const value = await promise;\n\n if (owner.#lifecycle !== 'active') {\n if (registration.dispose) {\n try {\n await registration.dispose(value as never);\n } catch (error) {\n owner.#cleanupFailures.push(error);\n }\n }\n\n throw new ConduitDisposedError(owner.name);\n }\n\n if (registration.dispose) owner.#owned.push({ dispose: registration.dispose, value });\n\n return value;\n } finally {\n owner.#inFlight.delete(promise);\n }\n }\n}\n\nexport function createContainer(options?: { name?: string }): Container {\n return new ContainerImpl(undefined, options);\n}\n"],"mappings":"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"}
package/dist/errors.cjs CHANGED
@@ -1,2 +1,2 @@
1
- var e=e=>e.description??`anonymous`,t=class e extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}static is(t){return t instanceof e}},n=class extends t{cycle;constructor(t){super(`Circular dependency detected: ${t.map(e).join(` -> `)}`),this.cycle=t}},r=class extends t{token;containerName;constructor(t,n=`unknown`){super(`No provider registered for token: ${e(t)} (in container '${n}')`),this.token=t,this.containerName=n}},i=class extends t{token;constructor(t){super(`Token "${e(t)}" is already registered.`),this.token=t}},a=class extends t{token;lifetime;constructor(t,n){let r=n===`transient`?`transient factories are never cached`:typeof n==`symbol`?`named-scope "${n.description??`anonymous`}" instance has not been resolved yet in this scope`:`the instance has not been resolved yet; call await container.resolve() or container.resolveAll() first`;super(`Token "${e(t)}" cannot be resolved synchronously: ${r}.`),this.token=t,this.lifetime=n}},o=class extends t{token;requiredScope;constructor(t,n){let r=n?.description??`anonymous`;super(n?`Token "${e(t)}" requires scope "${r}" but no matching scope container was found in the hierarchy.`:`Token "${e(t)}" requires a scope container but was resolved from the root.`),this.token=t,this.requiredScope=n}},s=class extends t{containerName;constructor(e=`unknown`){super(`Cannot use a disposed container (container '${e}').`),this.containerName=e}},c=class extends t{containerName;constructor(e){super(`Container '${e}' is frozen and cannot accept new registrations.`),this.containerName=e}};exports.ConduitCircularDependencyError=n,exports.ConduitDisposedError=s,exports.ConduitDuplicateRegistrationError=i,exports.ConduitError=t,exports.ConduitFrozenError=c,exports.ConduitProviderNotFoundError=r,exports.ConduitScopedResolutionError=o,exports.ConduitSyncResolutionError=a,exports.tokenName=e;
1
+ function e(e){return e.description??`anonymous`}var t=class e extends Error{static is(t){return t instanceof e}constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},n=class extends t{cycle;constructor(t){super(`Circular dependency detected: ${t.map(e).join(` -> `)}`),this.cycle=t}},r=class extends t{containerName;token;constructor(t,n){super(`No provider registered for token: ${e(t)} (in container '${n}')`),this.containerName=n,this.token=t}},i=class extends t{token;constructor(t){super(`Token "${e(t)}" is already registered.`),this.token=t}},a=class extends t{requiredScope;token;constructor(t,n){super(`Token "${e(t)}" requires scope "${n.description??`anonymous`}".`),this.requiredScope=n,this.token=t}},o=class extends t{containerName;constructor(e){super(`Cannot use disposed container '${e}'.`),this.containerName=e}},s=class extends t{errors;constructor(e){super(`Container disposal failed with ${e.length} cleanup error${e.length===1?``:`s`}.`),this.errors=e}};exports.ConduitCircularDependencyError=n,exports.ConduitDisposeError=s,exports.ConduitDisposedError=o,exports.ConduitDuplicateRegistrationError=i,exports.ConduitError=t,exports.ConduitProviderNotFoundError=r,exports.ConduitScopedResolutionError=a,exports.tokenName=e;
2
2
  //# sourceMappingURL=errors.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["import type { Lifetime, ScopeToken, Token } from './types.js';\n\nexport const tokenName = (t: Token<any>): string => t.description ?? 'anonymous';\n\n/** Base class for all conduit errors. Use `instanceof ConduitError` to catch any conduit-originated error. */\nexport class ConduitError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n static is(err: unknown): err is ConduitError {\n return err instanceof ConduitError;\n }\n}\n\nexport class ConduitCircularDependencyError extends ConduitError {\n /** The token path that forms the cycle. */\n readonly cycle: Token<any>[];\n\n constructor(path: Token<any>[]) {\n super(`Circular dependency detected: ${path.map(tokenName).join(' -> ')}`);\n this.cycle = path;\n }\n}\n\nexport class ConduitProviderNotFoundError extends ConduitError {\n /** The token that could not be found. */\n readonly token: Token<any>;\n /** The container name at the time of the lookup. */\n readonly containerName: string;\n\n constructor(tok: Token<any>, containerName = 'unknown') {\n super(`No provider registered for token: ${tokenName(tok)} (in container '${containerName}')`);\n this.token = tok;\n this.containerName = containerName;\n }\n}\n\nexport class ConduitDuplicateRegistrationError extends ConduitError {\n /** The token that was registered twice. */\n readonly token: Token<any>;\n\n constructor(tok: Token<any>) {\n super(`Token \"${tokenName(tok)}\" is already registered.`);\n this.token = tok;\n }\n}\n\nexport class ConduitSyncResolutionError extends ConduitError {\n /** The token that could not be resolved synchronously. */\n readonly token: Token<any>;\n /** The lifetime that prevented synchronous resolution. */\n readonly lifetime: Lifetime;\n\n constructor(tok: Token<any>, lifetime: Lifetime) {\n const reason =\n lifetime === 'transient'\n ? 'transient factories are never cached'\n : typeof lifetime === 'symbol'\n ? `named-scope \"${(lifetime as symbol).description ?? 'anonymous'}\" instance has not been resolved yet in this scope`\n : 'the instance has not been resolved yet; call await container.resolve() or container.resolveAll() first';\n\n super(`Token \"${tokenName(tok)}\" cannot be resolved synchronously: ${reason}.`);\n this.token = tok;\n this.lifetime = lifetime;\n }\n}\n\nexport class ConduitScopedResolutionError extends ConduitError {\n /** The token that required a scope container. */\n readonly token: Token<any>;\n /** The required scope token, if any. */\n readonly requiredScope: ScopeToken | undefined;\n\n constructor(tok: Token<any>, requiredScope?: ScopeToken) {\n const scopeName = requiredScope?.description ?? 'anonymous';\n\n super(\n requiredScope\n ? `Token \"${tokenName(tok)}\" requires scope \"${scopeName}\" but no matching scope container was found in the hierarchy.`\n : `Token \"${tokenName(tok)}\" requires a scope container but was resolved from the root.`,\n );\n this.token = tok;\n this.requiredScope = requiredScope;\n }\n}\n\nexport class ConduitDisposedError extends ConduitError {\n /** The name of the container that was already disposed. */\n readonly containerName: string;\n\n constructor(containerName = 'unknown') {\n super(`Cannot use a disposed container (container '${containerName}').`);\n this.containerName = containerName;\n }\n}\n\nexport class ConduitFrozenError extends ConduitError {\n /** The name of the container that is frozen. */\n readonly containerName: string;\n\n constructor(containerName: string) {\n super(`Container '${containerName}' is frozen and cannot accept new registrations.`);\n this.containerName = containerName;\n }\n}\n"],"mappings":"AAEA,IAAa,EAAa,GAA0B,EAAE,aAAe,YAGxD,EAAb,MAAa,UAAqB,KAAM,CACtC,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAO,IAAI,OAAO,KACvB,OAAO,eAAe,KAAM,IAAI,OAAO,SAAS,CAClD,CAEA,OAAO,GAAG,EAAmC,CAC3C,OAAO,aAAe,CACxB,CACF,EAEa,EAAb,cAAoD,CAAa,CAE/D,MAEA,YAAY,EAAoB,CAC9B,MAAM,iCAAiC,EAAK,IAAI,CAAS,CAAC,CAAC,KAAK,MAAM,GAAG,EACzE,KAAK,MAAQ,CACf,CACF,EAEa,EAAb,cAAkD,CAAa,CAE7D,MAEA,cAEA,YAAY,EAAiB,EAAgB,UAAW,CACtD,MAAM,qCAAqC,EAAU,CAAG,EAAE,kBAAkB,EAAc,GAAG,EAC7F,KAAK,MAAQ,EACb,KAAK,cAAgB,CACvB,CACF,EAEa,EAAb,cAAuD,CAAa,CAElE,MAEA,YAAY,EAAiB,CAC3B,MAAM,UAAU,EAAU,CAAG,EAAE,yBAAyB,EACxD,KAAK,MAAQ,CACf,CACF,EAEa,EAAb,cAAgD,CAAa,CAE3D,MAEA,SAEA,YAAY,EAAiB,EAAoB,CAC/C,IAAM,EACJ,IAAa,YACT,uCACA,OAAO,GAAa,SAClB,gBAAiB,EAAoB,aAAe,YAAY,oDAChE,yGAER,MAAM,UAAU,EAAU,CAAG,EAAE,sCAAsC,EAAO,EAAE,EAC9E,KAAK,MAAQ,EACb,KAAK,SAAW,CAClB,CACF,EAEa,EAAb,cAAkD,CAAa,CAE7D,MAEA,cAEA,YAAY,EAAiB,EAA4B,CACvD,IAAM,EAAY,GAAe,aAAe,YAEhD,MACE,EACI,UAAU,EAAU,CAAG,EAAE,oBAAoB,EAAU,+DACvD,UAAU,EAAU,CAAG,EAAE,6DAC/B,EACA,KAAK,MAAQ,EACb,KAAK,cAAgB,CACvB,CACF,EAEa,EAAb,cAA0C,CAAa,CAErD,cAEA,YAAY,EAAgB,UAAW,CACrC,MAAM,+CAA+C,EAAc,IAAI,EACvE,KAAK,cAAgB,CACvB,CACF,EAEa,EAAb,cAAwC,CAAa,CAEnD,cAEA,YAAY,EAAuB,CACjC,MAAM,cAAc,EAAc,iDAAiD,EACnF,KAAK,cAAgB,CACvB,CACF"}
1
+ {"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["import type { ScopeToken, Token } from './types.js';\n\nexport function tokenName(token: Token<unknown>): string {\n return token.description ?? 'anonymous';\n}\n\nexport class ConduitError extends Error {\n static is(error: unknown): error is ConduitError {\n return error instanceof ConduitError;\n }\n\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class ConduitCircularDependencyError extends ConduitError {\n readonly cycle: Token<unknown>[];\n\n constructor(cycle: Token<unknown>[]) {\n super(`Circular dependency detected: ${cycle.map(tokenName).join(' -> ')}`);\n this.cycle = cycle;\n }\n}\n\nexport class ConduitProviderNotFoundError extends ConduitError {\n readonly containerName: string;\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>, containerName: string) {\n super(`No provider registered for token: ${tokenName(token)} (in container '${containerName}')`);\n this.containerName = containerName;\n this.token = token;\n }\n}\n\nexport class ConduitDuplicateRegistrationError extends ConduitError {\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>) {\n super(`Token \"${tokenName(token)}\" is already registered.`);\n this.token = token;\n }\n}\n\nexport class ConduitScopedResolutionError extends ConduitError {\n readonly requiredScope: ScopeToken;\n readonly token: Token<unknown>;\n\n constructor(token: Token<unknown>, requiredScope: ScopeToken) {\n super(`Token \"${tokenName(token)}\" requires scope \"${requiredScope.description ?? 'anonymous'}\".`);\n this.requiredScope = requiredScope;\n this.token = token;\n }\n}\n\nexport class ConduitDisposedError extends ConduitError {\n readonly containerName: string;\n\n constructor(containerName: string) {\n super(`Cannot use disposed container '${containerName}'.`);\n this.containerName = containerName;\n }\n}\n\nexport class ConduitDisposeError extends ConduitError {\n readonly errors: unknown[];\n\n constructor(errors: unknown[]) {\n super(`Container disposal failed with ${errors.length} cleanup error${errors.length === 1 ? '' : 's'}.`);\n this.errors = errors;\n }\n}\n"],"mappings":"AAEA,SAAgB,EAAU,EAA+B,CACvD,OAAO,EAAM,aAAe,WAC9B,CAEA,IAAa,EAAb,MAAa,UAAqB,KAAM,CACtC,OAAO,GAAG,EAAuC,CAC/C,OAAO,aAAiB,CAC1B,CAEA,YAAY,EAAiB,EAAwB,CACnD,MAAM,EAAS,CAAO,EACtB,KAAK,KAAO,WAAW,KACvB,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CACF,EAEa,EAAb,cAAoD,CAAa,CAC/D,MAEA,YAAY,EAAyB,CACnC,MAAM,iCAAiC,EAAM,IAAI,CAAS,CAAC,CAAC,KAAK,MAAM,GAAG,EAC1E,KAAK,MAAQ,CACf,CACF,EAEa,EAAb,cAAkD,CAAa,CAC7D,cACA,MAEA,YAAY,EAAuB,EAAuB,CACxD,MAAM,qCAAqC,EAAU,CAAK,EAAE,kBAAkB,EAAc,GAAG,EAC/F,KAAK,cAAgB,EACrB,KAAK,MAAQ,CACf,CACF,EAEa,EAAb,cAAuD,CAAa,CAClE,MAEA,YAAY,EAAuB,CACjC,MAAM,UAAU,EAAU,CAAK,EAAE,yBAAyB,EAC1D,KAAK,MAAQ,CACf,CACF,EAEa,EAAb,cAAkD,CAAa,CAC7D,cACA,MAEA,YAAY,EAAuB,EAA2B,CAC5D,MAAM,UAAU,EAAU,CAAK,EAAE,oBAAoB,EAAc,aAAe,YAAY,GAAG,EACjG,KAAK,cAAgB,EACrB,KAAK,MAAQ,CACf,CACF,EAEa,EAAb,cAA0C,CAAa,CACrD,cAEA,YAAY,EAAuB,CACjC,MAAM,kCAAkC,EAAc,GAAG,EACzD,KAAK,cAAgB,CACvB,CACF,EAEa,EAAb,cAAyC,CAAa,CACpD,OAEA,YAAY,EAAmB,CAC7B,MAAM,kCAAkC,EAAO,OAAO,gBAAgB,EAAO,SAAW,EAAI,GAAK,IAAI,EAAE,EACvG,KAAK,OAAS,CAChB,CACF"}
package/dist/errors.d.ts CHANGED
@@ -1,49 +1,33 @@
1
- import type { Lifetime, ScopeToken, Token } from './types.js';
2
- export declare const tokenName: (t: Token<any>) => string;
3
- /** Base class for all conduit errors. Use `instanceof ConduitError` to catch any conduit-originated error. */
1
+ import type { ScopeToken, Token } from './types.js';
2
+ export declare function tokenName(token: Token<unknown>): string;
4
3
  export declare class ConduitError extends Error {
5
- constructor(message: string, opts?: ErrorOptions);
6
- static is(err: unknown): err is ConduitError;
4
+ static is(error: unknown): error is ConduitError;
5
+ constructor(message: string, options?: ErrorOptions);
7
6
  }
8
7
  export declare class ConduitCircularDependencyError extends ConduitError {
9
- /** The token path that forms the cycle. */
10
- readonly cycle: Token<any>[];
11
- constructor(path: Token<any>[]);
8
+ readonly cycle: Token<unknown>[];
9
+ constructor(cycle: Token<unknown>[]);
12
10
  }
13
11
  export declare class ConduitProviderNotFoundError extends ConduitError {
14
- /** The token that could not be found. */
15
- readonly token: Token<any>;
16
- /** The container name at the time of the lookup. */
17
12
  readonly containerName: string;
18
- constructor(tok: Token<any>, containerName?: string);
13
+ readonly token: Token<unknown>;
14
+ constructor(token: Token<unknown>, containerName: string);
19
15
  }
20
16
  export declare class ConduitDuplicateRegistrationError extends ConduitError {
21
- /** The token that was registered twice. */
22
- readonly token: Token<any>;
23
- constructor(tok: Token<any>);
24
- }
25
- export declare class ConduitSyncResolutionError extends ConduitError {
26
- /** The token that could not be resolved synchronously. */
27
- readonly token: Token<any>;
28
- /** The lifetime that prevented synchronous resolution. */
29
- readonly lifetime: Lifetime;
30
- constructor(tok: Token<any>, lifetime: Lifetime);
17
+ readonly token: Token<unknown>;
18
+ constructor(token: Token<unknown>);
31
19
  }
32
20
  export declare class ConduitScopedResolutionError extends ConduitError {
33
- /** The token that required a scope container. */
34
- readonly token: Token<any>;
35
- /** The required scope token, if any. */
36
- readonly requiredScope: ScopeToken | undefined;
37
- constructor(tok: Token<any>, requiredScope?: ScopeToken);
21
+ readonly requiredScope: ScopeToken;
22
+ readonly token: Token<unknown>;
23
+ constructor(token: Token<unknown>, requiredScope: ScopeToken);
38
24
  }
39
25
  export declare class ConduitDisposedError extends ConduitError {
40
- /** The name of the container that was already disposed. */
41
- readonly containerName: string;
42
- constructor(containerName?: string);
43
- }
44
- export declare class ConduitFrozenError extends ConduitError {
45
- /** The name of the container that is frozen. */
46
26
  readonly containerName: string;
47
27
  constructor(containerName: string);
48
28
  }
29
+ export declare class ConduitDisposeError extends ConduitError {
30
+ readonly errors: unknown[];
31
+ constructor(errors: unknown[]);
32
+ }
49
33
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAE9D,eAAO,MAAM,SAAS,GAAI,GAAG,KAAK,CAAC,GAAG,CAAC,KAAG,MAAsC,CAAC;AAEjF,8GAA8G;AAC9G,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;IAMhD,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,YAAY;CAG7C;AAED,qBAAa,8BAA+B,SAAQ,YAAY;IAC9D,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;gBAEjB,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE;CAI/B;AAED,qBAAa,4BAA6B,SAAQ,YAAY;IAC5D,yCAAyC;IACzC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,oDAAoD;IACpD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;gBAEnB,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,aAAa,SAAY;CAKvD;AAED,qBAAa,iCAAkC,SAAQ,YAAY;IACjE,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;gBAEf,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC;CAI5B;AAED,qBAAa,0BAA2B,SAAQ,YAAY;IAC1D,0DAA0D;IAC1D,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;gBAEhB,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,QAAQ;CAYhD;AAED,qBAAa,4BAA6B,SAAQ,YAAY;IAC5D,iDAAiD;IACjD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,wCAAwC;IACxC,QAAQ,CAAC,aAAa,EAAE,UAAU,GAAG,SAAS,CAAC;gBAEnC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC,EAAE,UAAU;CAWxD;AAED,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,2DAA2D;IAC3D,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;gBAEnB,aAAa,SAAY;CAItC;AAED,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,gDAAgD;IAChD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;gBAEnB,aAAa,EAAE,MAAM;CAIlC"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEpD,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,MAAM,CAEvD;AAED,qBAAa,YAAa,SAAQ,KAAK;IACrC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY;gBAIpC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAKpD;AAED,qBAAa,8BAA+B,SAAQ,YAAY;IAC9D,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;gBAErB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE;CAIpC;AAED,qBAAa,4BAA6B,SAAQ,YAAY;IAC5D,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;gBAEnB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,aAAa,EAAE,MAAM;CAKzD;AAED,qBAAa,iCAAkC,SAAQ,YAAY;IACjE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;gBAEnB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;CAIlC;AAED,qBAAa,4BAA6B,SAAQ,YAAY;IAC5D,QAAQ,CAAC,aAAa,EAAE,UAAU,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;gBAEnB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,aAAa,EAAE,UAAU;CAK7D;AAED,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;gBAEnB,aAAa,EAAE,MAAM;CAIlC;AAED,qBAAa,mBAAoB,SAAQ,YAAY;IACnD,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;gBAEf,MAAM,EAAE,OAAO,EAAE;CAI9B"}