@needle-di/core 1.1.2 → 1.2.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/README.md CHANGED
@@ -66,6 +66,15 @@ deno add jsr:@needle-di/core
66
66
 
67
67
  Check out our docs on [https://needle-di.io](https://needle-di.io/concepts/binding.html).
68
68
 
69
+ ## Using AI coding agents?
70
+
71
+ Our documentation is available in an LLM-friendly format:
72
+
73
+ - [https://needle-di.io/llms.txt](https://needle-di.io/llms.txt) - a compact index of all documentation pages
74
+ - [https://needle-di.io/llms-full.txt](https://needle-di.io/llms-full.txt) - the full documentation as a single file
75
+
76
+ See [AI agent instructions](https://needle-di.io/ai/agents.html) for guidance on using Needle DI with AI coding agents.
77
+
69
78
  ## License
70
79
 
71
80
  License under the MIT License (MIT)
@@ -1,5 +1,5 @@
1
1
  import { type Token } from "./tokens.ts";
2
- import type { Provider } from "./providers.ts";
2
+ import type { Provider, ProviderList } from "./providers.ts";
3
3
  /**
4
4
  * A dependency injection (DI) container will keep track of all bindings
5
5
  * and hold the actual instances of your services.
@@ -7,24 +7,27 @@ import type { Provider } from "./providers.ts";
7
7
  export declare class Container {
8
8
  private readonly providers;
9
9
  private readonly singletons;
10
+ /**
11
+ * Async constructions that have been started but have not settled yet, keyed by token.
12
+ *
13
+ * Without this, two overlapping `getAsync()` calls for the same token would both see an
14
+ * empty `singletons` entry and construct it twice, breaking singleton semantics.
15
+ */
16
+ private readonly pending;
10
17
  private readonly parent?;
11
18
  private readonly factory;
12
19
  constructor(parent?: Container);
13
20
  /**
14
21
  * Binds multiple providers to this container.
15
22
  *
16
- * {@link https://needle-di.io/concepts/binding.html#binding}
23
+ * Providers may be passed individually or as (nested) arrays. To define a list of providers
24
+ * upfront, outside of a container, use `defineProviders()`.
25
+ *
26
+ * @param providers one or more providers, optionally nested in arrays
27
+ *
28
+ * {@link https://needle-di.io/concepts/binding.html#binding-multiple-providers}
17
29
  */
18
- bindAll<A>(p1: Provider<A>): this;
19
- bindAll<A, B>(p1: Provider<A>, p2: Provider<B>): this;
20
- bindAll<A, B, C>(p1: Provider<A>, p2: Provider<B>, p3: Provider<C>): this;
21
- bindAll<A, B, C, D>(p1: Provider<A>, p2: Provider<B>, p3: Provider<C>, p4: Provider<D>): this;
22
- bindAll<A, B, C, D, E>(p1: Provider<A>, p2: Provider<B>, p3: Provider<C>, p4: Provider<D>, p5: Provider<E>): this;
23
- bindAll<A, B, C, D, E, F>(p1: Provider<A>, p2: Provider<B>, p3: Provider<C>, p4: Provider<D>, p5: Provider<E>, p6: Provider<F>): this;
24
- bindAll<A, B, C, D, E, F, G>(p1: Provider<A>, p2: Provider<B>, p3: Provider<C>, p4: Provider<D>, p5: Provider<E>, p6: Provider<F>, p7: Provider<G>): this;
25
- bindAll<A, B, C, D, E, F, G, H>(p1: Provider<A>, p2: Provider<B>, p3: Provider<C>, p4: Provider<D>, p5: Provider<E>, p6: Provider<F>, p7: Provider<G>, p8: Provider<H>): this;
26
- bindAll<A, B, C, D, E, F, G, H, I>(p1: Provider<A>, p2: Provider<B>, p3: Provider<C>, p4: Provider<D>, p5: Provider<E>, p6: Provider<F>, p7: Provider<G>, p8: Provider<H>, p9: Provider<I>): this;
27
- bindAll<A, B, C, D, E, F, G, H, I>(p1: Provider<A>, p2: Provider<B>, p3: Provider<C>, p4: Provider<D>, p5: Provider<E>, p6: Provider<F>, p7: Provider<G>, p8: Provider<H>, p9: Provider<I>, ...providers: Provider<any>[]): this;
30
+ bindAll<T extends readonly unknown[]>(...providers: ProviderList<T>): this;
28
31
  /**
29
32
  * Binds a provider to this container.
30
33
  *
@@ -32,11 +35,14 @@ export declare class Container {
32
35
  */
33
36
  bind<T>(provider: Provider<T>): this;
34
37
  /**
35
- * Unbinds a provider.
38
+ * Unbinds a token.
36
39
  *
37
- * {@link https://needle-di.io/concepts/binding.html#binding}
40
+ * This removes all providers for that token, including multi-providers,
41
+ * as well as any instances that were already constructed.
42
+ *
43
+ * {@link https://needle-di.io/concepts/binding.html#clear-binding}
38
44
  */
39
- unbind<T>(provider: Provider<T>): this;
45
+ unbind<T>(token: Token<T>): this;
40
46
  /**
41
47
  * Unbinds all providers.
42
48
  *
@@ -127,6 +133,18 @@ export declare class Container {
127
133
  multi?: boolean;
128
134
  lazy?: boolean;
129
135
  }): Promise<T | T[] | undefined> | (() => Promise<T | T[] | undefined>);
136
+ /**
137
+ * Runs a function within an injection context backed by this container, so that it
138
+ * can use `inject()` and `injectAsync()` instead of `container.get()`. The return
139
+ * value of the function is passed through.
140
+ *
141
+ * The injection context is only active for as long as the function runs
142
+ * synchronously. When passing an async function, `inject()` and `injectAsync()`
143
+ * must therefore be called before its first `await`.
144
+ *
145
+ * {@link https://needle-di.io/concepts/injection.html#running-in-an-injection-context}
146
+ */
147
+ runInInjectionContext<T>(block: (container: Container) => T): T;
130
148
  /**
131
149
  * Creates a child container.
132
150
  *
@@ -137,6 +155,13 @@ export declare class Container {
137
155
  * Returns whether the container has one or more providers for this token.
138
156
  */
139
157
  has<T>(token: Token<T>): boolean;
158
+ /**
159
+ * Constructs the providers for a token asynchronously, ensuring that concurrent
160
+ * requests for the same token share a single construction and therefore a single
161
+ * instance. Callers that join an already running construction inherit its result,
162
+ * not its chain: their own chain has already been checked for cycles by the caller.
163
+ */
164
+ private constructOnce;
140
165
  private autoBindIfNeeded;
141
166
  private existingProviderAlreadyProvided;
142
167
  }
package/dist/container.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { isClassToken, toString, isInjectionToken, getToken } from "./tokens.js";
2
2
  import * as Guards from "./providers.js";
3
3
  import { getInjectableTargets, isInjectable } from "./decorators.js";
4
- import { assertPresent, assertSingle, getParentClasses, promiseTry, windowedSlice } from "./utils.js";
5
- import { Factory } from "./factory.js";
6
- import { injectionContext } from "./context.js";
4
+ import { assertPresent, assertSingle, flattenDeep, getParentClasses, promiseTry, windowedSlice } from "./utils.js";
5
+ import { assertNoCycle, Factory } from "./factory.js";
6
+ import { currentResolutionChain, injectionContext } from "./context.js";
7
7
  /**
8
8
  * A dependency injection (DI) container will keep track of all bindings
9
9
  * and hold the actual instances of your services.
@@ -11,6 +11,13 @@ import { injectionContext } from "./context.js";
11
11
  export class Container {
12
12
  providers = new Map();
13
13
  singletons = new Map();
14
+ /**
15
+ * Async constructions that have been started but have not settled yet, keyed by token.
16
+ *
17
+ * Without this, two overlapping `getAsync()` calls for the same token would both see an
18
+ * empty `singletons` entry and construct it twice, breaking singleton semantics.
19
+ */
20
+ pending = new Map();
14
21
  parent;
15
22
  factory;
16
23
  constructor(parent) {
@@ -21,9 +28,18 @@ export class Container {
21
28
  useValue: this,
22
29
  });
23
30
  }
24
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
+ /**
32
+ * Binds multiple providers to this container.
33
+ *
34
+ * Providers may be passed individually or as (nested) arrays. To define a list of providers
35
+ * upfront, outside of a container, use `defineProviders()`.
36
+ *
37
+ * @param providers one or more providers, optionally nested in arrays
38
+ *
39
+ * {@link https://needle-di.io/concepts/binding.html#binding-multiple-providers}
40
+ */
25
41
  bindAll(...providers) {
26
- providers.forEach((it) => this.bind(it));
42
+ flattenDeep(providers).forEach((it) => this.bind(it));
27
43
  return this;
28
44
  }
29
45
  /**
@@ -76,14 +92,17 @@ export class Container {
76
92
  return this;
77
93
  }
78
94
  /**
79
- * Unbinds a provider.
95
+ * Unbinds a token.
80
96
  *
81
- * {@link https://needle-di.io/concepts/binding.html#binding}
97
+ * This removes all providers for that token, including multi-providers,
98
+ * as well as any instances that were already constructed.
99
+ *
100
+ * {@link https://needle-di.io/concepts/binding.html#clear-binding}
82
101
  */
83
- unbind(provider) {
84
- const token = getToken(provider);
102
+ unbind(token) {
85
103
  this.providers.delete(token);
86
104
  this.singletons.delete(token);
105
+ this.pending.delete(token);
87
106
  return this;
88
107
  }
89
108
  /**
@@ -94,17 +113,25 @@ export class Container {
94
113
  unbindAll() {
95
114
  this.providers.clear();
96
115
  this.singletons.clear();
116
+ this.pending.clear();
97
117
  return this;
98
118
  }
99
119
  get(token, options) {
100
120
  const lazy = options?.lazy ?? false;
101
121
  if (lazy) {
122
+ // Lazy injection deliberately starts a new resolution when the getter is invoked,
123
+ // which is exactly what makes it usable to break a cycle.
102
124
  return () => this.get(token, { ...options, lazy: false });
103
125
  }
126
+ // The resolution we are part of, if any. Read from the active injection context
127
+ // rather than passed as an argument, so that the public API stays unchanged.
128
+ const chain = currentResolutionChain();
104
129
  this.autoBindIfNeeded(token);
105
130
  const optional = options?.optional ?? false;
106
131
  if (!this.providers.has(token)) {
107
132
  if (this.parent) {
133
+ // Delegation happens synchronously, so the context this chain was read from is
134
+ // still active and the parent observes the very same chain.
108
135
  return this.parent.get(token, { ...options, lazy: false });
109
136
  }
110
137
  if (optional) {
@@ -114,10 +141,8 @@ export class Container {
114
141
  }
115
142
  const providers = assertPresent(this.providers.get(token));
116
143
  if (!this.singletons.has(token)) {
117
- injectionContext(this).run(() => {
118
- const values = providers.flatMap((provider) => this.factory.construct(provider, token));
119
- this.singletons.set(token, values);
120
- });
144
+ const values = providers.flatMap((provider) => this.factory.construct(provider, token, chain));
145
+ this.singletons.set(token, values);
121
146
  }
122
147
  const singletons = assertPresent(this.singletons.get(token));
123
148
  const multi = options?.multi ?? false;
@@ -132,13 +157,20 @@ export class Container {
132
157
  getAsync(token, options) {
133
158
  const lazy = options?.lazy ?? false;
134
159
  if (lazy) {
160
+ // Lazy injection deliberately starts a new resolution when the getter is invoked,
161
+ // which is exactly what makes it usable to break a cycle.
135
162
  return () => this.getAsync(token, { ...options, lazy: false });
136
163
  }
164
+ // Must be read here, before the first `await`: the injection context we inherit this
165
+ // from is restored as soon as our caller's synchronous block returns.
166
+ const chain = currentResolutionChain();
137
167
  return promiseTry(async () => {
138
168
  this.autoBindIfNeeded(token);
139
169
  const optional = options?.optional ?? false;
140
170
  if (!this.providers.has(token)) {
141
171
  if (this.parent) {
172
+ // Still part of the synchronous prefix, so the context is active and the parent
173
+ // observes the very same chain.
142
174
  return this.parent.getAsync(token, { ...options, lazy: false });
143
175
  }
144
176
  if (optional) {
@@ -147,13 +179,17 @@ export class Container {
147
179
  throw Error(`No provider(s) found for ${toString(token)}`);
148
180
  }
149
181
  const providers = assertPresent(this.providers.get(token));
150
- if (!this.singletons.has(token)) {
151
- await injectionContext(this).runAsync(async () => {
152
- const values = await Promise.all(providers.map((it) => this.factory.constructAsync(it)));
153
- this.singletons.set(token, values.flat());
154
- });
182
+ let singletons = this.singletons.get(token);
183
+ if (!singletons) {
184
+ // Cycle detection has to happen before we join an in-flight construction below:
185
+ // a genuine cycle would otherwise await the pending promise of a token that is
186
+ // waiting on us, and hang instead of reporting itself.
187
+ providers.forEach((provider) => assertNoCycle(chain, provider));
188
+ // We use the values the construction produced instead of reading `singletons`
189
+ // back, so that a token that was unbound while we were suspended still resolves
190
+ // to the result of the construction we started.
191
+ singletons = await this.constructOnce(token, providers, chain);
155
192
  }
156
- const singletons = assertPresent(this.singletons.get(token));
157
193
  const multi = options?.multi ?? false;
158
194
  if (multi) {
159
195
  return singletons;
@@ -164,6 +200,27 @@ export class Container {
164
200
  }
165
201
  });
166
202
  }
203
+ /**
204
+ * Runs a function within an injection context backed by this container, so that it
205
+ * can use `inject()` and `injectAsync()` instead of `container.get()`. The return
206
+ * value of the function is passed through.
207
+ *
208
+ * The injection context is only active for as long as the function runs
209
+ * synchronously. When passing an async function, `inject()` and `injectAsync()`
210
+ * must therefore be called before its first `await`.
211
+ *
212
+ * {@link https://needle-di.io/concepts/injection.html#running-in-an-injection-context}
213
+ */
214
+ runInInjectionContext(block) {
215
+ // A fresh context per call, never one cached per container: contexts are scoped to
216
+ // a single resolution, and sharing one would interleave concurrent resolutions.
217
+ //
218
+ // The chain is inherited rather than reset. Called from user code it is empty
219
+ // anyway, but called from within a construction the block is part of that
220
+ // resolution, so continuing its chain is what keeps circular dependencies
221
+ // detectable instead of recursing until the stack overflows.
222
+ return injectionContext(this, currentResolutionChain()).run(block);
223
+ }
167
224
  /**
168
225
  * Creates a child container.
169
226
  *
@@ -178,6 +235,39 @@ export class Container {
178
235
  has(token) {
179
236
  return this.providers.has(token) || (this.parent?.has(token) ?? false);
180
237
  }
238
+ /**
239
+ * Constructs the providers for a token asynchronously, ensuring that concurrent
240
+ * requests for the same token share a single construction and therefore a single
241
+ * instance. Callers that join an already running construction inherit its result,
242
+ * not its chain: their own chain has already been checked for cycles by the caller.
243
+ */
244
+ constructOnce(token, providers, chain) {
245
+ const existing = this.pending.get(token);
246
+ if (existing) {
247
+ return existing;
248
+ }
249
+ const pending = promiseTry(async () => {
250
+ const values = await Promise.all(providers.map((it) => this.factory.constructAsync(it, chain)));
251
+ return values.flat();
252
+ });
253
+ this.pending.set(token, pending);
254
+ // A construction may only write back if it is still the current one for this token.
255
+ // If it was unbound or superseded while in flight, the container has moved on and
256
+ // storing the result would resurrect a token that is no longer bound.
257
+ const isCurrent = () => this.pending.get(token) === pending;
258
+ pending.then((values) => {
259
+ if (isCurrent()) {
260
+ this.pending.delete(token);
261
+ this.singletons.set(token, values);
262
+ }
263
+ }, () => {
264
+ // A failed construction must not be cached, so a later attempt can retry.
265
+ if (isCurrent()) {
266
+ this.pending.delete(token);
267
+ }
268
+ });
269
+ return pending;
270
+ }
181
271
  autoBindIfNeeded(token) {
182
272
  if (this.singletons.has(token)) {
183
273
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"container.js","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"container.js","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"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"}
package/dist/context.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Container } from "./container.ts";
2
+ import type { ResolutionChain } from "./factory.ts";
2
3
  import type { Token } from "./tokens.ts";
3
4
  /**
4
5
  * Injects a service within the current injection context, using the token provided.
@@ -63,9 +64,14 @@ export declare function injectAsync<T>(token: Token<T>, options: {
63
64
  /**
64
65
  * A context has a specific container associated to it and allows you to run sync or async code.
65
66
  *
67
+ * It also carries the {@link ResolutionChain} of the resolution it belongs to, so that
68
+ * `inject()` and `injectAsync()` calls made by user code continue that chain instead of
69
+ * starting a new one.
70
+ *
66
71
  * @internal
67
72
  */
68
- interface Context {
73
+ export interface Context {
74
+ readonly chain: ResolutionChain;
69
75
  run<T>(block: (container: Container) => T): T;
70
76
  runAsync<T>(block: (container: Container) => Promise<T>): Promise<T>;
71
77
  }
@@ -74,5 +80,15 @@ interface Context {
74
80
  *
75
81
  * @internal
76
82
  */
77
- export declare function injectionContext(container: Container): Context;
78
- export {};
83
+ export declare function injectionContext(container: Container, chain?: ResolutionChain): Context;
84
+ /**
85
+ * Returns the resolution chain of the injection context that is currently active, or an
86
+ * empty chain when there is none (i.e., when a resolution is started from user code).
87
+ *
88
+ * Like `inject()` and `injectAsync()`, this must be read synchronously while the context
89
+ * is still active: the context is restored as soon as the current synchronous block
90
+ * returns, so it cannot be read after an `await`.
91
+ *
92
+ * @internal
93
+ */
94
+ export declare function currentResolutionChain(): ResolutionChain;
package/dist/context.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Container } from "./container.js";
2
+ import { promiseTry } from "./utils.js";
2
3
  export function inject(token, options) {
3
4
  try {
4
5
  return _currentContext.run((container) => container.get(token, options));
@@ -24,12 +25,17 @@ export function injectAsync(token, options) {
24
25
  return Promise.reject(error);
25
26
  }
26
27
  }
28
+ /**
29
+ * The chain of a resolution that has no parent, i.e., one started from user code.
30
+ */
31
+ const EMPTY_RESOLUTION_CHAIN = Object.freeze([]);
27
32
  /**
28
33
  * The global context does not allow dependency injection.
29
34
  *
30
35
  * @internal
31
36
  */
32
37
  class GlobalContext {
38
+ chain = EMPTY_RESOLUTION_CHAIN;
33
39
  run() {
34
40
  throw new NeedsInjectionContextError();
35
41
  }
@@ -44,8 +50,10 @@ class GlobalContext {
44
50
  */
45
51
  class InjectionContext {
46
52
  container;
47
- constructor(container) {
53
+ chain;
54
+ constructor(container, chain) {
48
55
  this.container = container;
56
+ this.chain = chain;
49
57
  }
50
58
  run(block) {
51
59
  const originalContext = _currentContext;
@@ -58,14 +66,18 @@ class InjectionContext {
58
66
  _currentContext = originalContext;
59
67
  }
60
68
  }
61
- async runAsync(block) {
69
+ runAsync(block) {
62
70
  const originalContext = _currentContext;
63
71
  try {
64
72
  // eslint-disable-next-line @typescript-eslint/no-this-alias
65
73
  _currentContext = this;
66
- return await block(this.container);
74
+ return promiseTry(() => block(this.container));
67
75
  }
68
76
  finally {
77
+ // The context must be restored synchronously, as soon as the block's synchronous
78
+ // prefix has returned its promise. Holding it across the `await` (i.e. until the
79
+ // promise settles) leaks this context to unrelated code that runs while the block
80
+ // is suspended, making `inject()`/`injectAsync()` resolve from the wrong container.
69
81
  _currentContext = originalContext;
70
82
  }
71
83
  }
@@ -76,8 +88,21 @@ let _currentContext = new GlobalContext();
76
88
  *
77
89
  * @internal
78
90
  */
79
- export function injectionContext(container) {
80
- return new InjectionContext(container);
91
+ export function injectionContext(container, chain = EMPTY_RESOLUTION_CHAIN) {
92
+ return new InjectionContext(container, chain);
93
+ }
94
+ /**
95
+ * Returns the resolution chain of the injection context that is currently active, or an
96
+ * empty chain when there is none (i.e., when a resolution is started from user code).
97
+ *
98
+ * Like `inject()` and `injectAsync()`, this must be read synchronously while the context
99
+ * is still active: the context is restored as soon as the current synchronous block
100
+ * returns, so it cannot be read after an `await`.
101
+ *
102
+ * @internal
103
+ */
104
+ export function currentResolutionChain() {
105
+ return _currentContext.chain;
81
106
  }
82
107
  /**
83
108
  * An error that occurs when `inject()` or `injectAsync()` is used outside an injection context.
@@ -86,7 +111,10 @@ export function injectionContext(container) {
86
111
  */
87
112
  class NeedsInjectionContextError extends Error {
88
113
  constructor() {
89
- super(`You can only invoke inject() or injectAsync() within an injection context`);
114
+ super(`You can only invoke inject() or injectAsync() within an injection context. ` +
115
+ `If you entered one using container.runInInjectionContext(), note that it is no longer ` +
116
+ `active after its first await. ` +
117
+ `See https://needle-di.io/concepts/injection.html#running-in-an-injection-context`);
90
118
  }
91
119
  }
92
120
  //# sourceMappingURL=context.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAc3C,MAAM,UAAU,MAAM,CACpB,KAAe,EACf,OAAiE;IAEjE,IAAI,CAAC;QACH,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,0BAA0B,IAAI,OAAO,EAAE,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC9E,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAgBD,MAAM,UAAU,WAAW,CACzB,KAAe,EACf,OAIC;IAED,IAAI,CAAC;QACH,IAAI,OAAO,EAAE,IAAI,EAAE,CAAC;YAClB,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACnG,CAAC;QACD,OAAO,eAAe,CAAC,QAAQ,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACzG,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,0BAA0B,IAAI,OAAO,EAAE,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC9E,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACpC,CAAC;QAED,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC;AAYD;;;;GAIG;AACH,MAAM,aAAa;IACjB,GAAG;QACD,MAAM,IAAI,0BAA0B,EAAE,CAAC;IACzC,CAAC;IAED,QAAQ;QACN,MAAM,IAAI,0BAA0B,EAAE,CAAC;IACzC,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,gBAAgB;IACS;IAA7B,YAA6B,SAAoB;QAApB,cAAS,GAAT,SAAS,CAAW;IAAG,CAAC;IAErD,GAAG,CAAI,KAAkC;QACvC,MAAM,eAAe,GAAG,eAAe,CAAC;QACxC,IAAI,CAAC;YACH,4DAA4D;YAC5D,eAAe,GAAG,IAAI,CAAC;YACvB,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/B,CAAC;gBAAS,CAAC;YACT,eAAe,GAAG,eAAe,CAAC;QACpC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAI,KAA+C;QAC/D,MAAM,eAAe,GAAG,eAAe,CAAC;QACxC,IAAI,CAAC;YACH,4DAA4D;YAC5D,eAAe,GAAG,IAAI,CAAC;YACvB,OAAO,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACrC,CAAC;gBAAS,CAAC;YACT,eAAe,GAAG,eAAe,CAAC;QACpC,CAAC;IACH,CAAC;CACF;AAED,IAAI,eAAe,GAAqC,IAAI,aAAa,EAAE,CAAC;AAE5E;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAoB;IACnD,OAAO,IAAI,gBAAgB,CAAC,SAAS,CAAC,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,MAAM,0BAA2B,SAAQ,KAAK;IAC5C;QACE,KAAK,CAAC,2EAA2E,CAAC,CAAC;IACrF,CAAC;CACF"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
package/dist/factory.d.ts CHANGED
@@ -1,14 +1,34 @@
1
1
  import { type Provider } from "./providers.ts";
2
2
  import { type Token } from "./tokens.ts";
3
3
  import { Container } from "./container.ts";
4
+ /**
5
+ * The providers that are currently being constructed, ordered from the root of a
6
+ * resolution down to the provider that is being constructed right now.
7
+ *
8
+ * A chain belongs to a single resolution and is treated as immutable: every nested
9
+ * injection receives its own extended copy. This is what keeps concurrent resolutions
10
+ * isolated. A single mutable stack shared by the whole container would interleave
11
+ * them, and any provider two overlapping resolutions have in common would be reported
12
+ * as a circular dependency.
13
+ *
14
+ * @internal
15
+ */
16
+ export type ResolutionChain = readonly Provider<unknown>[];
17
+ /**
18
+ * Asserts that constructing `provider` as the next step of `chain` does not close a
19
+ * cycle, i.e., that the provider does not (transitively) depend on itself.
20
+ *
21
+ * @internal
22
+ */
23
+ export declare function assertNoCycle(chain: ResolutionChain, provider: Provider<unknown>): void;
4
24
  /**
5
25
  * @internal
6
26
  */
7
27
  export declare class Factory {
8
28
  private readonly container;
9
- private readonly underConstruction;
10
29
  constructor(container: Container);
11
- construct<T>(provider: Provider<T>, token: Token<T>): T[];
12
- constructAsync<T>(provider: Provider<T>): Promise<T[]>;
30
+ construct<T>(provider: Provider<T>, token: Token<T>, chain: ResolutionChain): T[];
31
+ constructAsync<T>(provider: Provider<T>, chain: ResolutionChain): Promise<T[]>;
13
32
  private doConstruct;
33
+ private enter;
14
34
  }
package/dist/factory.js CHANGED
@@ -3,79 +3,94 @@ import { getToken, toString } from "./tokens.js";
3
3
  import * as Guards from "./providers.js";
4
4
  import { assertNever, retryOn } from "./utils.js";
5
5
  import { Container } from "./container.js";
6
+ import { injectionContext } from "./context.js";
7
+ /**
8
+ * Asserts that constructing `provider` as the next step of `chain` does not close a
9
+ * cycle, i.e., that the provider does not (transitively) depend on itself.
10
+ *
11
+ * @internal
12
+ */
13
+ export function assertNoCycle(chain, provider) {
14
+ if (chain.includes(provider)) {
15
+ throw new CircularDependencyError([...chain, provider].map(getToken).map(toString));
16
+ }
17
+ }
18
+ /**
19
+ * Returns the chain that the dependencies of `provider` should be resolved with.
20
+ * Throws a {@link CircularDependencyError} if `provider` is already part of `chain`.
21
+ */
22
+ function extend(chain, provider) {
23
+ assertNoCycle(chain, provider);
24
+ return [...chain, provider];
25
+ }
6
26
  /**
7
27
  * @internal
8
28
  */
9
29
  export class Factory {
10
30
  container;
11
- underConstruction = [];
12
31
  constructor(container) {
13
32
  this.container = container;
14
33
  }
15
- construct(provider, token) {
34
+ construct(provider, token, chain) {
16
35
  if (Guards.isAsyncProvider(provider)) {
17
36
  throw new AsyncProvidersInSyncInjectionContextError(token);
18
37
  }
19
- try {
20
- if (this.underConstruction.includes(provider)) {
21
- const dependencyGraph = [...this.underConstruction, provider].map(getToken).map(toString);
22
- throw new CircularDependencyError(dependencyGraph);
23
- }
24
- this.underConstruction.push(provider);
25
- return this.doConstruct(provider);
38
+ return this.doConstruct(provider, extend(chain, provider));
39
+ }
40
+ async constructAsync(provider, chain) {
41
+ // The chain that this provider's own dependencies are resolved with. Since it is a
42
+ // fresh array rather than a shared stack, there is nothing to unwind afterwards:
43
+ // it simply goes out of scope, no matter when (or whether) this construction settles.
44
+ const nested = extend(chain, provider);
45
+ if (Guards.isAsyncProvider(provider)) {
46
+ return [await this.enter(nested).runAsync(() => provider.useFactory(this.container))];
47
+ }
48
+ // in class and constructor providers, we allow stuff to be synchronously injected,
49
+ // by just retrying when we encounter an async dependency down the road.
50
+ // todo: this feels like an ugly workaround, so let's create something nice for this.
51
+ if (Guards.isClassProvider(provider) || Guards.isConstructorProvider(provider)) {
52
+ const create = Guards.isConstructorProvider(provider) ? () => [new provider()] : () => [new provider.useClass()];
53
+ return retryOn(AsyncProvidersInSyncInjectionContextError,
54
+ // retries run in a later tick, when the original injection context is no longer
55
+ // active, so each attempt must explicitly (re-)enter the injection context for
56
+ // the field initializers' inject() calls to work.
57
+ async () => this.enter(nested).run(() => create()), async (error) => {
58
+ // Resolving the async dependency is part of this construction, so it has to
59
+ // continue this chain. Entering the context again is what carries it across
60
+ // the tick boundary introduced by the retry.
61
+ await this.enter(nested).runAsync(() => this.container.getAsync(error.token, { multi: true, optional: true }));
62
+ });
26
63
  }
27
- finally {
28
- this.underConstruction.pop();
64
+ if (Guards.isExistingProvider(provider)) {
65
+ return await this.enter(nested).runAsync(() => this.container.getAsync(provider.useExisting, { multi: true }));
29
66
  }
67
+ // all other types of providers are constructed synchronously anyway.
68
+ return this.doConstruct(provider, nested);
30
69
  }
31
- async constructAsync(provider) {
32
- try {
33
- if (this.underConstruction.includes(provider)) {
34
- const dependencyGraph = [...this.underConstruction, provider].map(getToken).map(toString);
35
- throw new CircularDependencyError(dependencyGraph);
70
+ doConstruct(provider, chain) {
71
+ // User code runs inside the injection context, so that the inject() calls it makes
72
+ // resolve from the right container and continue this resolution's chain.
73
+ return this.enter(chain).run(() => {
74
+ if (Guards.isConstructorProvider(provider)) {
75
+ return [new provider()];
36
76
  }
37
- this.underConstruction.push(provider);
38
- if (Guards.isAsyncProvider(provider)) {
39
- return [await provider.useFactory(this.container)];
77
+ else if (Guards.isClassProvider(provider)) {
78
+ return [new provider.useClass()];
40
79
  }
41
- // in class and constructor providers, we allow stuff to be synchronously injected,
42
- // by just retrying when we encounter an async dependency down the road.
43
- // todo: this feels like an ugly workaround, so let's create something nice for this.
44
- if (Guards.isClassProvider(provider) || Guards.isConstructorProvider(provider)) {
45
- const create = Guards.isConstructorProvider(provider)
46
- ? () => [new provider()]
47
- : () => [new provider.useClass()];
48
- return retryOn(AsyncProvidersInSyncInjectionContextError, async () => create(), async (error) => {
49
- await this.container.getAsync(error.token, { multi: true, optional: true });
50
- });
80
+ else if (Guards.isValueProvider(provider)) {
81
+ return [provider.useValue];
51
82
  }
52
- if (Guards.isExistingProvider(provider)) {
53
- return await this.container.getAsync(provider.useExisting, { multi: true });
83
+ else if (Guards.isFactoryProvider(provider)) {
84
+ return [provider.useFactory(this.container)];
54
85
  }
55
- // all other types of providers are constructed synchronously anyway.
56
- return this.doConstruct(provider);
57
- }
58
- finally {
59
- this.underConstruction.pop();
60
- }
86
+ else if (Guards.isExistingProvider(provider)) {
87
+ return this.container.get(provider.useExisting, { multi: true });
88
+ }
89
+ return assertNever(provider);
90
+ });
61
91
  }
62
- doConstruct(provider) {
63
- if (Guards.isConstructorProvider(provider)) {
64
- return [new provider()];
65
- }
66
- else if (Guards.isClassProvider(provider)) {
67
- return [new provider.useClass()];
68
- }
69
- else if (Guards.isValueProvider(provider)) {
70
- return [provider.useValue];
71
- }
72
- else if (Guards.isFactoryProvider(provider)) {
73
- return [provider.useFactory(this.container)];
74
- }
75
- else if (Guards.isExistingProvider(provider)) {
76
- return this.container.get(provider.useExisting, { multi: true });
77
- }
78
- return assertNever(provider);
92
+ enter(chain) {
93
+ return injectionContext(this.container, chain);
79
94
  }
80
95
  }
81
96
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"factory.js","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAc,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;GAEG;AACH,MAAM,OAAO,OAAO;IAGW;IAFZ,iBAAiB,GAAwB,EAAE,CAAC;IAE7D,YAA6B,SAAoB;QAApB,cAAS,GAAT,SAAS,CAAW;IAAG,CAAC;IAErD,SAAS,CAAI,QAAqB,EAAE,KAAe;QACjD,IAAI,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,yCAAyC,CAAC,KAAK,CAAC,CAAC;QAC7D,CAAC;QAED,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC9C,MAAM,eAAe,GAAG,CAAC,GAAG,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAC1F,MAAM,IAAI,uBAAuB,CAAC,eAAe,CAAC,CAAC;YACrD,CAAC;YAED,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACtC,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QACpC,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,cAAc,CAAI,QAAqB;QAC3C,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC9C,MAAM,eAAe,GAAG,CAAC,GAAG,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAC1F,MAAM,IAAI,uBAAuB,CAAC,eAAe,CAAC,CAAC;YACrD,CAAC;YAED,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAEtC,IAAI,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACrC,OAAO,CAAC,MAAM,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;YACrD,CAAC;YAED,mFAAmF;YACnF,wEAAwE;YACxE,qFAAqF;YACrF,IAAI,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC/E,MAAM,MAAM,GAAG,MAAM,CAAC,qBAAqB,CAAC,QAAQ,CAAC;oBACnD,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,QAAQ,EAAE,CAAC;oBACxB,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAEpC,OAAO,OAAO,CACZ,yCAAyC,EACzC,KAAK,IAAI,EAAE,CAAC,MAAM,EAAE,EACpB,KAAK,EAAE,KAAK,EAAE,EAAE;oBACd,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC9E,CAAC,CACF,CAAC;YACJ,CAAC;YAED,IAAI,MAAM,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACxC,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9E,CAAC;YAED,qEAAqE;YACrE,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QACpC,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAEO,WAAW,CAAI,QAAyB;QAC9C,IAAI,MAAM,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3C,OAAO,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC;QAC1B,CAAC;aAAM,IAAI,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5C,OAAO,CAAC,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QACnC,CAAC;aAAM,IAAI,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC7B,CAAC;aAAM,IAAI,MAAM,CAAC,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QAC/C,CAAC;aAAM,IAAI,MAAM,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/C,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,OAAO,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,yCAA6C,SAAQ,KAAK;IAC3C;IAAnB,YAAmB,KAAe;QAChC,KAAK,CACH,4BAA4B,QAAQ,CAAC,KAAK,CAAC,sEAAsE,CAClH,CAAC;QAHe,UAAK,GAAL,KAAK,CAAU;IAIlC,CAAC;CACF;AAED,MAAM,uBAAwB,SAAQ,KAAK;IACzC,YAAY,KAAe;QACzB,KAAK,CACH,iCAAiC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,sEAAsE,CAC1H,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { Container, bootstrap, bootstrapAsync } from "./container.ts";
2
2
  export { inject, injectAsync } from "./context.ts";
3
3
  export { injectable } from "./decorators.ts";
4
- export type { Provider, SyncProvider, AsyncProvider, ExistingProvider, ConstructorProvider, ClassProvider, ValueProvider, FactoryProvider, AsyncFactoryProvider, SyncFactoryProvider, } from "./providers.ts";
4
+ export type { Provider, SyncProvider, AsyncProvider, ExistingProvider, ConstructorProvider, ClassProvider, ValueProvider, FactoryProvider, AsyncFactoryProvider, SyncFactoryProvider, ProviderList, } from "./providers.ts";
5
+ export { defineProviders } from "./providers.ts";
5
6
  export { InjectionToken } from "./tokens.ts";
6
7
  export type { Token } from "./tokens.ts";
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { Container, bootstrap, bootstrapAsync } from "./container.js";
2
2
  export { inject, injectAsync } from "./context.js";
3
3
  export { injectable } from "./decorators.js";
4
+ export { defineProviders } from "./providers.js";
4
5
  export { InjectionToken } from "./tokens.js";
5
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAa7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAc7C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
@@ -72,3 +72,69 @@ export declare function isFactoryProvider<T>(provider: Provider<T>): provider is
72
72
  export declare function isAsyncProvider<T>(provider: Provider<T>): provider is AsyncProvider<T>;
73
73
  export declare function isExistingProvider<T>(provider: Provider<T>): provider is ExistingProvider<T>;
74
74
  export declare function isMultiProvider<T>(provider: Provider<T>): boolean;
75
+ /**
76
+ * A single provider, or an arbitrarily nested array of providers.
77
+ */
78
+ type ProviderNode = Provider<unknown> | readonly ProviderNode[];
79
+ /**
80
+ * Recursively unwraps nested arrays, yielding the union of all leaf types.
81
+ */
82
+ type ExtractProviders<T> = T extends readonly unknown[] ? ExtractProviders<T[number]> : T;
83
+ /**
84
+ * Every provider variant that is an object literal, i.e. all of them except
85
+ * {@link ConstructorProvider}, which is a class reference.
86
+ */
87
+ type ObjectProvider<T> = ClassProvider<T> | ValueProvider<T> | SyncFactoryProvider<T> | AsyncFactoryProvider<T> | ExistingProvider<T>;
88
+ /**
89
+ * `keyof` distributed over the members of a union, rather than the keys they have in common.
90
+ */
91
+ type KeysOfUnion<T> = T extends unknown ? keyof T : never;
92
+ /**
93
+ * Every property name that may appear on an object-based provider.
94
+ */
95
+ type ProviderKey = KeysOfUnion<ObjectProvider<unknown>>;
96
+ /**
97
+ * Rejects properties that do not exist on any provider, by requiring them to be `never`.
98
+ *
99
+ * TypeScript only applies its built-in excess property check to *fresh* object literals.
100
+ * Since {@link ProviderList} first captures the arguments in an inferred type parameter,
101
+ * that freshness is lost, so the check is reproduced here explicitly.
102
+ */
103
+ type NoExcessProperties<T> = Record<Exclude<keyof T, ProviderKey>, never>;
104
+ /**
105
+ * Type-checks a single element: either a nested array, or a provider whose value type
106
+ * is correlated with the token it is provided for.
107
+ */
108
+ type CheckProviderNode<T> = T extends readonly unknown[] ? CheckedProviderList<T> : T extends {
109
+ provide: Token<infer U>;
110
+ } ? Exclude<keyof T, ProviderKey> extends never ? Provider<U> : Provider<U> & NoExcessProperties<T> : Provider<unknown>;
111
+ /**
112
+ * Type-checks every element of an (arbitrarily nested) list of providers.
113
+ */
114
+ type CheckedProviderList<T extends readonly unknown[]> = {
115
+ [K in keyof T]: CheckProviderNode<T[K]>;
116
+ };
117
+ /**
118
+ * The list of arguments accepted by {@link Container.bindAll} and {@link defineProviders}:
119
+ * one or more providers, optionally nested in arrays, preserving the correlation between each
120
+ * token and the value it provides.
121
+ *
122
+ * When the given arguments already satisfy this, they are accepted as-is. Otherwise this type
123
+ * resolves to the expected shape, so that TypeScript reports the mismatch on the offending
124
+ * element rather than on the call as a whole.
125
+ */
126
+ export type ProviderList<T extends readonly unknown[]> = T extends readonly [] ? readonly [ProviderNode] : T extends CheckedProviderList<T> ? T : CheckedProviderList<T>;
127
+ /**
128
+ * Defines a list of providers upfront, outside of a container.
129
+ *
130
+ * Providers may be passed individually or as (nested) arrays, and are returned as a single
131
+ * flattened array. Unlike annotating a variable as `Provider<unknown>[]`, this preserves the
132
+ * correlation between each token and the value it provides.
133
+ *
134
+ * @param providers one or more providers, optionally nested in arrays
135
+ * @returns a flat array containing every given provider
136
+ *
137
+ * {@link https://needle-di.io/concepts/binding.html#defining-providers-upfront}
138
+ */
139
+ export declare function defineProviders<T extends readonly unknown[]>(...providers: ProviderList<T>): ExtractProviders<T>[];
140
+ export {};
package/dist/providers.js CHANGED
@@ -1,4 +1,4 @@
1
- import { isClassLike } from "./utils.js";
1
+ import { flattenDeep, isClassLike } from "./utils.js";
2
2
  export function isConstructorProvider(provider) {
3
3
  return isClassLike(provider);
4
4
  }
@@ -20,4 +20,19 @@ export function isExistingProvider(provider) {
20
20
  export function isMultiProvider(provider) {
21
21
  return "provide" in provider && "multi" in provider && provider.multi === true;
22
22
  }
23
+ /**
24
+ * Defines a list of providers upfront, outside of a container.
25
+ *
26
+ * Providers may be passed individually or as (nested) arrays, and are returned as a single
27
+ * flattened array. Unlike annotating a variable as `Provider<unknown>[]`, this preserves the
28
+ * correlation between each token and the value it provides.
29
+ *
30
+ * @param providers one or more providers, optionally nested in arrays
31
+ * @returns a flat array containing every given provider
32
+ *
33
+ * {@link https://needle-di.io/concepts/binding.html#defining-providers-upfront}
34
+ */
35
+ export function defineProviders(...providers) {
36
+ return flattenDeep(providers);
37
+ }
23
38
  //# sourceMappingURL=providers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,WAAW,EAAE,MAAM,YAAY,CAAC;AAkFrD,MAAM,UAAU,qBAAqB,CAAI,QAAqB;IAC5D,OAAO,WAAW,CAAC,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,eAAe,CAAI,QAAqB;IACtD,OAAO,SAAS,IAAI,QAAQ,IAAI,UAAU,IAAI,QAAQ,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,eAAe,CAAI,QAAqB;IACtD,OAAO,SAAS,IAAI,QAAQ,IAAI,UAAU,IAAI,QAAQ,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAI,QAAqB;IACxD,OAAO,SAAS,IAAI,QAAQ,IAAI,YAAY,IAAI,QAAQ,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,eAAe,CAAI,QAAqB;IACtD,OAAO,iBAAiB,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,KAAK,KAAK,IAAI,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAI,QAAqB;IACzD,OAAO,SAAS,IAAI,QAAQ,IAAI,aAAa,IAAI,QAAQ,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,eAAe,CAAI,QAAqB;IACtD,OAAO,SAAS,IAAI,QAAQ,IAAI,OAAO,IAAI,QAAQ,IAAI,QAAQ,CAAC,KAAK,KAAK,IAAI,CAAC;AACjF,CAAC"}
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAkFlE,MAAM,UAAU,qBAAqB,CAAI,QAAqB;IAC5D,OAAO,WAAW,CAAC,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,eAAe,CAAI,QAAqB;IACtD,OAAO,SAAS,IAAI,QAAQ,IAAI,UAAU,IAAI,QAAQ,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,eAAe,CAAI,QAAqB;IACtD,OAAO,SAAS,IAAI,QAAQ,IAAI,UAAU,IAAI,QAAQ,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAI,QAAqB;IACxD,OAAO,SAAS,IAAI,QAAQ,IAAI,YAAY,IAAI,QAAQ,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,eAAe,CAAI,QAAqB;IACtD,OAAO,iBAAiB,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,KAAK,KAAK,IAAI,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAI,QAAqB;IACzD,OAAO,SAAS,IAAI,QAAQ,IAAI,aAAa,IAAI,QAAQ,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,eAAe,CAAI,QAAqB;IACtD,OAAO,SAAS,IAAI,QAAQ,IAAI,OAAO,IAAI,QAAQ,IAAI,QAAQ,CAAC,KAAK,KAAK,IAAI,CAAC;AACjF,CAAC;AA6ED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAA+B,GAAG,SAA0B;IACzF,OAAO,WAAW,CAAC,SAA+B,CAAC,CAAC;AACtD,CAAC"}
package/dist/utils.d.ts CHANGED
@@ -15,6 +15,12 @@ export declare function isClassLike(target: unknown): target is Class<unknown> |
15
15
  * @internal
16
16
  */
17
17
  export declare function getParentClasses(target: Class<unknown>): Class<unknown>[];
18
+ /**
19
+ * Recursively flattens an arbitrarily nested array into a flat array.
20
+ *
21
+ * @internal
22
+ */
23
+ export declare function flattenDeep<T>(values: readonly unknown[]): T[];
18
24
  /**
19
25
  * Ensures a given value is not null or undefined.
20
26
  *
@@ -55,9 +61,3 @@ export declare function assertNever(_: never): never;
55
61
  * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/try
56
62
  */
57
63
  export declare function promiseTry<T>(block: () => T | PromiseLike<T>): Promise<Awaited<T>>;
58
- /**
59
- * Simple function that returns a Promise with a certain delay.
60
- *
61
- * @internal
62
- */
63
- export declare function delay(delayInMs: number): Promise<void>;
package/dist/utils.js CHANGED
@@ -21,6 +21,14 @@ export function getParentClasses(target) {
21
21
  }
22
22
  return parentClasses;
23
23
  }
24
+ /**
25
+ * Recursively flattens an arbitrarily nested array into a flat array.
26
+ *
27
+ * @internal
28
+ */
29
+ export function flattenDeep(values) {
30
+ return values.flat(Infinity);
31
+ }
24
32
  /**
25
33
  * Ensures a given value is not null or undefined.
26
34
  *
@@ -94,12 +102,4 @@ export function assertNever(_) {
94
102
  export async function promiseTry(block) {
95
103
  return await new Promise((resolve) => resolve(block()));
96
104
  }
97
- /**
98
- * Simple function that returns a Promise with a certain delay.
99
- *
100
- * @internal
101
- */
102
- export function delay(delayInMs) {
103
- return new Promise((resolve) => setTimeout(resolve, delayInMs));
104
- }
105
105
  //# sourceMappingURL=utils.js.map
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,MAAe;IACzC,OAAO,OAAO,MAAM,KAAK,UAAU,CAAC;AACtC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAsB;IACrD,MAAM,aAAa,GAAqB,EAAE,CAAC;IAC3C,IAAI,YAAY,GAAG,MAAM,CAAC;IAC1B,OAAO,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC;QAChD,MAAM,WAAW,GAAmB,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;QACxE,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAChC,YAAY,GAAG,WAAW,CAAC;IAC7B,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAI,KAA2B;IAC1D,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1C,MAAM,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AASD,MAAM,UAAU,aAAa,CAAI,KAAU,EAAE,IAAI,GAAG,CAAC;IACnD,MAAM,MAAM,GAAU,EAAE,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAClB,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,UAAyB,EACzB,KAA6B,EAC7B,OAAyC;IAEzC,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,OAAO,MAAM,KAAK,EAAE,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,CAAC,KAAK,YAAY,UAAU,CAAC,EAAE,CAAC;gBACnC,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAI,KAAU,EAAE,aAA4B;IACtE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,aAAa,EAAE,CAAC;IACxB,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,aAAa,EAAE,CAAC;IACxB,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,6DAA6D;AAC7D,MAAM,UAAU,WAAW,CAAC,CAAQ;IAClC,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAI,KAA+B;IACjE,OAAO,MAAM,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,KAAK,CAAC,SAAiB;IACrC,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;AACxE,CAAC"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,MAAe;IACzC,OAAO,OAAO,MAAM,KAAK,UAAU,CAAC;AACtC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAsB;IACrD,MAAM,aAAa,GAAqB,EAAE,CAAC;IAC3C,IAAI,YAAY,GAAG,MAAM,CAAC;IAC1B,OAAO,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC;QAChD,MAAM,WAAW,GAAmB,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;QACxE,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAChC,YAAY,GAAG,WAAW,CAAC;IAC7B,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAI,MAA0B;IACvD,OAAO,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAQ,CAAC;AACtC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAI,KAA2B;IAC1D,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1C,MAAM,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AASD,MAAM,UAAU,aAAa,CAAI,KAAU,EAAE,IAAI,GAAG,CAAC;IACnD,MAAM,MAAM,GAAU,EAAE,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAClB,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,UAAyB,EACzB,KAA6B,EAC7B,OAAyC;IAEzC,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,OAAO,MAAM,KAAK,EAAE,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,CAAC,KAAK,YAAY,UAAU,CAAC,EAAE,CAAC;gBACnC,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAI,KAAU,EAAE,aAA4B;IACtE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,aAAa,EAAE,CAAC;IACxB,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,aAAa,EAAE,CAAC;IACxB,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,6DAA6D;AAC7D,MAAM,UAAU,WAAW,CAAC,CAAQ;IAClC,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAI,KAA+B;IACjE,OAAO,MAAM,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAC7D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-di/core",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "description": "A simple TypeScript library for dependency injection",
5
5
  "license": "MIT",
6
6
  "keywords": [