@needle-di/core 0.11.0 → 0.11.1
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.d.ts +2 -38
- package/dist/container.js +40 -139
- package/dist/container.js.map +1 -1
- package/dist/context.d.ts +52 -0
- package/dist/context.js +89 -0
- package/dist/context.js.map +1 -0
- package/dist/decorators.d.ts +5 -5
- package/dist/decorators.js +1 -1
- package/dist/decorators.js.map +1 -1
- package/dist/factory.d.ts +13 -0
- package/dist/factory.js +67 -0
- package/dist/factory.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +20 -10
- package/dist/providers.js +3 -3
- package/dist/providers.js.map +1 -1
- package/dist/tokens.d.ts +10 -0
- package/dist/tokens.js +13 -0
- package/dist/tokens.js.map +1 -1
- package/dist/utils.d.ts +24 -0
- package/dist/utils.js +46 -0
- package/dist/utils.js.map +1 -1
- package/package.json +8 -9
- package/LICENSE +0 -21
- package/README.md +0 -91
package/dist/container.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Token } from "./tokens.ts";
|
|
2
|
-
import {
|
|
2
|
+
import type { Provider } 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.
|
|
@@ -8,6 +8,7 @@ export declare class Container {
|
|
|
8
8
|
private readonly providers;
|
|
9
9
|
private readonly singletons;
|
|
10
10
|
private readonly parent?;
|
|
11
|
+
private readonly factory;
|
|
11
12
|
constructor(parent?: Container);
|
|
12
13
|
/**
|
|
13
14
|
* Binds multiple providers to this container.
|
|
@@ -78,46 +79,9 @@ export declare class Container {
|
|
|
78
79
|
* Returns whether the container has one or more providers for this token.
|
|
79
80
|
*/
|
|
80
81
|
has<T>(token: Token<T>): boolean;
|
|
81
|
-
private construct;
|
|
82
|
-
private constructAsync;
|
|
83
|
-
private doConstructAsync;
|
|
84
82
|
private autoBindIfNeeded;
|
|
85
83
|
private existingProviderAlreadyProvided;
|
|
86
84
|
}
|
|
87
|
-
/**
|
|
88
|
-
* Injects a service within the current injection context, using the token provided.
|
|
89
|
-
*/
|
|
90
|
-
export declare function inject<T>(token: Token<T>, options: {
|
|
91
|
-
multi: true;
|
|
92
|
-
}): T[];
|
|
93
|
-
export declare function inject<T>(token: Token<T>, options: {
|
|
94
|
-
optional: true;
|
|
95
|
-
}): T | undefined;
|
|
96
|
-
export declare function inject<T>(token: Token<T>, options: {
|
|
97
|
-
multi: true;
|
|
98
|
-
optional: true;
|
|
99
|
-
}): T[] | undefined;
|
|
100
|
-
export declare function inject<T>(token: Token<T>, options?: {
|
|
101
|
-
optional?: boolean;
|
|
102
|
-
multi?: boolean;
|
|
103
|
-
}): T;
|
|
104
|
-
/**
|
|
105
|
-
* Injects a service asynchronously within the current injection context, using the token provided.
|
|
106
|
-
*/
|
|
107
|
-
export declare function injectAsync<T>(token: Token<T>, options: {
|
|
108
|
-
multi: true;
|
|
109
|
-
}): Promise<T[]>;
|
|
110
|
-
export declare function injectAsync<T>(token: Token<T>, options: {
|
|
111
|
-
optional: true;
|
|
112
|
-
}): Promise<T | undefined>;
|
|
113
|
-
export declare function injectAsync<T>(token: Token<T>, options: {
|
|
114
|
-
multi: true;
|
|
115
|
-
optional: true;
|
|
116
|
-
}): Promise<T[] | undefined>;
|
|
117
|
-
export declare function injectAsync<T>(token: Token<T>, options?: {
|
|
118
|
-
optional?: boolean;
|
|
119
|
-
multi?: boolean;
|
|
120
|
-
}): Promise<T>;
|
|
121
85
|
/**
|
|
122
86
|
* Bootstraps a new container and obtains a service using the provided token.
|
|
123
87
|
*/
|
package/dist/container.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { isClassToken, toString, isInjectionToken } from "./tokens.js";
|
|
2
|
-
import
|
|
1
|
+
import { isClassToken, toString, isInjectionToken, getToken } from "./tokens.js";
|
|
2
|
+
import * as Guards from "./providers.js";
|
|
3
3
|
import { getInjectableTargets, isInjectable } from "./decorators.js";
|
|
4
|
-
import { assertPresent, getParentClasses, windowedSlice } from "./utils.js";
|
|
4
|
+
import { assertPresent, assertSingle, getParentClasses, windowedSlice } from "./utils.js";
|
|
5
|
+
import { Factory } from "./factory.js";
|
|
6
|
+
import { injectionContext } from "./context.js";
|
|
5
7
|
/**
|
|
6
8
|
* A dependency injection (DI) container will keep track of all bindings
|
|
7
9
|
* and hold the actual instances of your services.
|
|
@@ -10,8 +12,10 @@ export class Container {
|
|
|
10
12
|
providers = new Map();
|
|
11
13
|
singletons = new Map();
|
|
12
14
|
parent;
|
|
15
|
+
factory;
|
|
13
16
|
constructor(parent) {
|
|
14
17
|
this.parent = parent;
|
|
18
|
+
this.factory = new Factory(this);
|
|
15
19
|
this.bind({
|
|
16
20
|
provide: Container,
|
|
17
21
|
useValue: this,
|
|
@@ -28,32 +32,35 @@ export class Container {
|
|
|
28
32
|
* {@link https://needle-di.io/concepts/binding.html#binding}
|
|
29
33
|
*/
|
|
30
34
|
bind(provider) {
|
|
31
|
-
const token =
|
|
32
|
-
|
|
33
|
-
if (isExistingProvider(provider) && provider.provide === provider.useExisting) {
|
|
35
|
+
const token = getToken(provider);
|
|
36
|
+
// running some validations...
|
|
37
|
+
if (Guards.isExistingProvider(provider) && provider.provide === provider.useExisting) {
|
|
34
38
|
throw Error(`The provider for token ${toString(token)} with "useExisting" cannot refer to itself.`);
|
|
35
39
|
}
|
|
36
|
-
if (!isExistingProvider(provider) && this.singletons.has(token)) {
|
|
40
|
+
if (!Guards.isExistingProvider(provider) && this.singletons.has(token)) {
|
|
37
41
|
throw Error(`Cannot bind a new provider for ${toString(token)}, since the existing provider was already constructed.`);
|
|
38
42
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
isMultiProvider(provider) &&
|
|
43
|
+
// ignore the new provider if it was already provided
|
|
44
|
+
if (Guards.isExistingProvider(provider) &&
|
|
45
|
+
Guards.isMultiProvider(provider) &&
|
|
43
46
|
this.existingProviderAlreadyProvided(token, provider.useExisting)) {
|
|
44
47
|
return this;
|
|
45
48
|
}
|
|
46
|
-
|
|
49
|
+
const providers = this.providers.get(token) ?? [];
|
|
50
|
+
// validating multi-provider inconsistencies...
|
|
51
|
+
const multi = Guards.isMultiProvider(provider);
|
|
52
|
+
if (multi && providers.some((it) => !Guards.isMultiProvider(it))) {
|
|
47
53
|
throw Error(`Cannot bind ${toString(token)} as multi-provider, since there is already a provider which is not a multi-provider.`);
|
|
48
54
|
}
|
|
49
|
-
else if (!multi &&
|
|
50
|
-
if (!
|
|
55
|
+
else if (!multi && providers.some((it) => Guards.isMultiProvider(it))) {
|
|
56
|
+
if (!providers.every(Guards.isExistingProvider)) {
|
|
51
57
|
throw Error(`Cannot bind ${toString(token)} as provider, since there are already provider(s) that are multi-providers.`);
|
|
52
58
|
}
|
|
53
59
|
}
|
|
54
|
-
|
|
60
|
+
// appending or replacing providers...
|
|
61
|
+
this.providers.set(token, multi ? [...providers, provider] : [provider]);
|
|
55
62
|
// inheritance support: also bind parent classes to their immediate child classes
|
|
56
|
-
if (isClassToken(token) && (isClassProvider(provider) || isConstructorProvider(provider))) {
|
|
63
|
+
if (isClassToken(token) && (Guards.isClassProvider(provider) || Guards.isConstructorProvider(provider))) {
|
|
57
64
|
windowedSlice([token, ...getParentClasses(token)]).forEach(([childClass, parentClass]) => {
|
|
58
65
|
const parentProvider = {
|
|
59
66
|
provide: parentClass,
|
|
@@ -71,7 +78,6 @@ export class Container {
|
|
|
71
78
|
get(token, options) {
|
|
72
79
|
this.autoBindIfNeeded(token);
|
|
73
80
|
const optional = options?.optional ?? false;
|
|
74
|
-
const multi = options?.multi ?? false;
|
|
75
81
|
if (!this.providers.has(token)) {
|
|
76
82
|
if (this.parent) {
|
|
77
83
|
return this.parent.get(token, options);
|
|
@@ -83,48 +89,45 @@ export class Container {
|
|
|
83
89
|
}
|
|
84
90
|
const providers = assertPresent(this.providers.get(token));
|
|
85
91
|
if (!this.singletons.has(token)) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
injectionContext(this).run(() => {
|
|
93
|
+
const values = providers.flatMap((provider) => this.factory.construct(provider, token));
|
|
94
|
+
this.singletons.set(token, values);
|
|
95
|
+
});
|
|
90
96
|
}
|
|
91
97
|
const singletons = assertPresent(this.singletons.get(token));
|
|
98
|
+
const multi = options?.multi ?? false;
|
|
92
99
|
if (multi) {
|
|
93
100
|
return singletons;
|
|
94
101
|
}
|
|
95
|
-
else if (singletons.length > 1) {
|
|
96
|
-
throw Error(`Requesting a single value for ${toString(token)}, but multiple values were provided. ` +
|
|
97
|
-
`Consider passing "{ multi: true }" to inject all values, or adjust your bindings accordingly.`);
|
|
98
|
-
}
|
|
99
102
|
else {
|
|
100
|
-
return
|
|
103
|
+
return assertSingle(singletons, () => Error(`Requesting a single value for ${toString(token)}, but multiple values were provided. ` +
|
|
104
|
+
`Consider passing "{ multi: true }" to inject all values, or adjust your bindings accordingly.`));
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
107
|
async getAsync(token, options) {
|
|
104
108
|
this.autoBindIfNeeded(token);
|
|
105
109
|
const optional = options?.optional ?? false;
|
|
106
|
-
const multi = options?.multi ?? false;
|
|
107
110
|
if (!this.providers.has(token)) {
|
|
108
111
|
if (optional) {
|
|
109
112
|
return undefined;
|
|
110
113
|
}
|
|
111
114
|
throw Error(`No provider(s) found for ${toString(token)}`);
|
|
112
115
|
}
|
|
113
|
-
const
|
|
116
|
+
const providers = assertPresent(this.providers.get(token));
|
|
114
117
|
if (!this.singletons.has(token)) {
|
|
115
|
-
|
|
116
|
-
|
|
118
|
+
await injectionContext(this).runAsync(async () => {
|
|
119
|
+
const values = await Promise.all(providers.map((it) => this.factory.constructAsync(it)));
|
|
120
|
+
this.singletons.set(token, values.flat());
|
|
121
|
+
});
|
|
117
122
|
}
|
|
118
123
|
const singletons = assertPresent(this.singletons.get(token));
|
|
124
|
+
const multi = options?.multi ?? false;
|
|
119
125
|
if (multi) {
|
|
120
|
-
return
|
|
121
|
-
}
|
|
122
|
-
else if (singletons.length > 1) {
|
|
123
|
-
throw Error(`Requesting a single value for ${toString(token)}, but multiple values were provided. ` +
|
|
124
|
-
`Consider passing "{ multi: true }" to inject all values, or adjust your bindings accordingly.`);
|
|
126
|
+
return singletons;
|
|
125
127
|
}
|
|
126
128
|
else {
|
|
127
|
-
return
|
|
129
|
+
return assertSingle(singletons, () => new Error(`Requesting a single value for ${toString(token)}, but multiple values were provided. ` +
|
|
130
|
+
`Consider passing "{ multi: true }" to inject all values, or adjust your bindings accordingly.`));
|
|
128
131
|
}
|
|
129
132
|
}
|
|
130
133
|
/**
|
|
@@ -141,55 +144,6 @@ export class Container {
|
|
|
141
144
|
has(token) {
|
|
142
145
|
return this.providers.has(token);
|
|
143
146
|
}
|
|
144
|
-
construct(provider, scope = this) {
|
|
145
|
-
const originalScope = currentScope;
|
|
146
|
-
try {
|
|
147
|
-
currentScope = scope;
|
|
148
|
-
return doConstruct(provider, scope);
|
|
149
|
-
}
|
|
150
|
-
finally {
|
|
151
|
-
currentScope = originalScope;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
async constructAsync(provider, scope = this) {
|
|
155
|
-
const originalScope = currentScope;
|
|
156
|
-
try {
|
|
157
|
-
currentScope = scope;
|
|
158
|
-
return await this.doConstructAsync(provider, scope);
|
|
159
|
-
}
|
|
160
|
-
finally {
|
|
161
|
-
currentScope = originalScope;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
async doConstructAsync(provider, scope) {
|
|
165
|
-
if (isAsyncFactoryProvider(provider)) {
|
|
166
|
-
return [await provider.useFactory(scope)];
|
|
167
|
-
}
|
|
168
|
-
else if (isExistingProvider(provider)) {
|
|
169
|
-
return scope.getAsync(provider.useExisting, { multi: true });
|
|
170
|
-
}
|
|
171
|
-
else if (isClassProvider(provider) || isConstructorProvider(provider)) {
|
|
172
|
-
while (true) {
|
|
173
|
-
try {
|
|
174
|
-
return doConstruct(provider, scope);
|
|
175
|
-
}
|
|
176
|
-
catch (error) {
|
|
177
|
-
if (error instanceof AsyncProvidersInSyncInjectionContextError) {
|
|
178
|
-
const values = await injectAsync(error.token, { multi: true, optional: true });
|
|
179
|
-
if (values) {
|
|
180
|
-
this.singletons.set(error.token, values);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
else {
|
|
184
|
-
throw error;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
else {
|
|
190
|
-
return doConstruct(provider, scope);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
147
|
autoBindIfNeeded(token) {
|
|
194
148
|
if (this.singletons.has(token)) {
|
|
195
149
|
return;
|
|
@@ -225,48 +179,7 @@ export class Container {
|
|
|
225
179
|
}
|
|
226
180
|
}
|
|
227
181
|
existingProviderAlreadyProvided(token, existingToken) {
|
|
228
|
-
return (this.providers.get(token) ?? []).some((it) => isExistingProvider(it) && it.provide === token && it.useExisting === existingToken);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
let currentScope = undefined;
|
|
232
|
-
export function inject(token, options) {
|
|
233
|
-
if (currentScope === undefined) {
|
|
234
|
-
if (options?.optional)
|
|
235
|
-
return undefined;
|
|
236
|
-
throw new Error("You can only invoke inject() from the injection context");
|
|
237
|
-
}
|
|
238
|
-
return currentScope.get(token, options);
|
|
239
|
-
}
|
|
240
|
-
export async function injectAsync(token, options) {
|
|
241
|
-
if (currentScope === undefined) {
|
|
242
|
-
if (options?.optional)
|
|
243
|
-
return undefined;
|
|
244
|
-
throw new Error("You can only invoke injectAsync() from the injection context");
|
|
245
|
-
}
|
|
246
|
-
return currentScope.getAsync(token, options);
|
|
247
|
-
}
|
|
248
|
-
// see: https://github.com/tc39/proposal-promise-try
|
|
249
|
-
async function promisify(value) {
|
|
250
|
-
return new Promise((resolve) => resolve(value));
|
|
251
|
-
}
|
|
252
|
-
function doConstruct(provider, scope) {
|
|
253
|
-
if (isConstructorProvider(provider)) {
|
|
254
|
-
return [new provider()];
|
|
255
|
-
}
|
|
256
|
-
else if (isClassProvider(provider)) {
|
|
257
|
-
return [new provider.useClass()];
|
|
258
|
-
}
|
|
259
|
-
else if (isValueProvider(provider)) {
|
|
260
|
-
return [provider.useValue];
|
|
261
|
-
}
|
|
262
|
-
else if (isFactoryProvider(provider)) {
|
|
263
|
-
return [provider.useFactory(scope)];
|
|
264
|
-
}
|
|
265
|
-
else if (isAsyncFactoryProvider(provider)) {
|
|
266
|
-
throw Error("Invalid state");
|
|
267
|
-
}
|
|
268
|
-
else {
|
|
269
|
-
return scope.get(provider.useExisting, { multi: true });
|
|
182
|
+
return (this.providers.get(token) ?? []).some((it) => Guards.isExistingProvider(it) && it.provide === token && it.useExisting === existingToken);
|
|
270
183
|
}
|
|
271
184
|
}
|
|
272
185
|
/**
|
|
@@ -281,16 +194,4 @@ export function bootstrap(token) {
|
|
|
281
194
|
export function bootstrapAsync(token) {
|
|
282
195
|
return new Container().getAsync(token);
|
|
283
196
|
}
|
|
284
|
-
/**
|
|
285
|
-
* An error that occurs when an async provider is requested in a synchronous context.
|
|
286
|
-
*
|
|
287
|
-
* @internal
|
|
288
|
-
*/
|
|
289
|
-
class AsyncProvidersInSyncInjectionContextError extends Error {
|
|
290
|
-
token;
|
|
291
|
-
constructor(token) {
|
|
292
|
-
super(`Some providers for token ${toString(token)} are async, please use injectAsync() or container.getAsync() instead`);
|
|
293
|
-
this.token = token;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
197
|
//# sourceMappingURL=container.js.map
|
package/dist/container.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container.js","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,YAAY,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"container.js","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Container } from "./container.ts";
|
|
2
|
+
import type { Token } from "./tokens.ts";
|
|
3
|
+
/**
|
|
4
|
+
* Injects a service within the current injection context, using the token provided.
|
|
5
|
+
*/
|
|
6
|
+
export declare function inject<T>(token: Token<T>, options: {
|
|
7
|
+
multi: true;
|
|
8
|
+
}): T[];
|
|
9
|
+
export declare function inject<T>(token: Token<T>, options: {
|
|
10
|
+
optional: true;
|
|
11
|
+
}): T | undefined;
|
|
12
|
+
export declare function inject<T>(token: Token<T>, options: {
|
|
13
|
+
multi: true;
|
|
14
|
+
optional: true;
|
|
15
|
+
}): T[] | undefined;
|
|
16
|
+
export declare function inject<T>(token: Token<T>, options?: {
|
|
17
|
+
optional?: boolean;
|
|
18
|
+
multi?: boolean;
|
|
19
|
+
}): T;
|
|
20
|
+
/**
|
|
21
|
+
* Injects a service asynchronously within the current injection context, using the token provided.
|
|
22
|
+
*/
|
|
23
|
+
export declare function injectAsync<T>(token: Token<T>, options: {
|
|
24
|
+
multi: true;
|
|
25
|
+
}): Promise<T[]>;
|
|
26
|
+
export declare function injectAsync<T>(token: Token<T>, options: {
|
|
27
|
+
optional: true;
|
|
28
|
+
}): Promise<T | undefined>;
|
|
29
|
+
export declare function injectAsync<T>(token: Token<T>, options: {
|
|
30
|
+
multi: true;
|
|
31
|
+
optional: true;
|
|
32
|
+
}): Promise<T[] | undefined>;
|
|
33
|
+
export declare function injectAsync<T>(token: Token<T>, options?: {
|
|
34
|
+
optional?: boolean;
|
|
35
|
+
multi?: boolean;
|
|
36
|
+
}): Promise<T>;
|
|
37
|
+
/**
|
|
38
|
+
* A context has a specific container associated to it and allows you to run sync or async code.
|
|
39
|
+
*
|
|
40
|
+
* @internal
|
|
41
|
+
*/
|
|
42
|
+
interface Context {
|
|
43
|
+
run<T>(block: (container: Container) => T): T;
|
|
44
|
+
runAsync<T>(block: (container: Container) => Promise<T>): Promise<T>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Creates a new injection context.
|
|
48
|
+
*
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
export declare function injectionContext(container: Container): Context;
|
|
52
|
+
export {};
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Container } from "./container.js";
|
|
2
|
+
export function inject(token, options) {
|
|
3
|
+
try {
|
|
4
|
+
return _currentContext.run((container) => container.get(token, options));
|
|
5
|
+
}
|
|
6
|
+
catch (error) {
|
|
7
|
+
if (error instanceof NeedsInjectionContextError && options?.optional === true) {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
throw error;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export async function injectAsync(token, options) {
|
|
14
|
+
try {
|
|
15
|
+
return _currentContext.runAsync((container) => container.getAsync(token, options));
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
if (error instanceof NeedsInjectionContextError && options?.optional === true) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The global context does not allow dependency injection.
|
|
26
|
+
*
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
class GlobalContext {
|
|
30
|
+
run() {
|
|
31
|
+
throw new NeedsInjectionContextError();
|
|
32
|
+
}
|
|
33
|
+
runAsync() {
|
|
34
|
+
throw new NeedsInjectionContextError();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* An injection context allows to perform dependency injection with `inject()` and `injectAsync()`.
|
|
39
|
+
*
|
|
40
|
+
* @internal
|
|
41
|
+
*/
|
|
42
|
+
class InjectionContext {
|
|
43
|
+
container;
|
|
44
|
+
constructor(container) {
|
|
45
|
+
this.container = container;
|
|
46
|
+
}
|
|
47
|
+
run(block) {
|
|
48
|
+
const originalContext = _currentContext;
|
|
49
|
+
try {
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
51
|
+
_currentContext = this;
|
|
52
|
+
return block(this.container);
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
_currentContext = originalContext;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async runAsync(block) {
|
|
59
|
+
const originalContext = _currentContext;
|
|
60
|
+
try {
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
62
|
+
_currentContext = this;
|
|
63
|
+
return await block(this.container);
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
_currentContext = originalContext;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
let _currentContext = new GlobalContext();
|
|
71
|
+
/**
|
|
72
|
+
* Creates a new injection context.
|
|
73
|
+
*
|
|
74
|
+
* @internal
|
|
75
|
+
*/
|
|
76
|
+
export function injectionContext(container) {
|
|
77
|
+
return new InjectionContext(container);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* An error that occurs when `inject()` or `injectAsync()` is used outside an injection context.
|
|
81
|
+
*
|
|
82
|
+
* @internal
|
|
83
|
+
*/
|
|
84
|
+
class NeedsInjectionContextError extends Error {
|
|
85
|
+
constructor() {
|
|
86
|
+
super(`You can only invoke inject() or injectAsync() within an injection context`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAU3C,MAAM,UAAU,MAAM,CAAI,KAAe,EAAE,OAAiD;IAC1F,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;AAYD,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAAe,EACf,OAGC;IAED,IAAI,CAAC;QACH,OAAO,eAAe,CAAC,QAAQ,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;IACrF,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;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,KAA2C;QAC3D,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,GAAY,IAAI,aAAa,EAAE,CAAC;AAEnD;;;;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"}
|
package/dist/decorators.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { type AbstractClass, type Class } from "./utils.ts";
|
|
2
|
-
type ClassDecorator<C extends Class<unknown>> = (target: C) => C | void;
|
|
3
|
-
export declare const injectableSymbol: unique symbol;
|
|
4
|
-
export type InjectableClass<T = unknown> = (Class<T> | AbstractClass<T>) & {
|
|
5
|
-
[injectableSymbol]: Class<unknown>[];
|
|
6
|
-
};
|
|
7
2
|
/**
|
|
8
3
|
* The @injectable() decorator allows you to automatically bind a class as singleton service
|
|
9
4
|
* when requesting it from a DI container.
|
|
10
5
|
*/
|
|
11
6
|
export declare function injectable<C extends Class<unknown>>(): ClassDecorator<C>;
|
|
7
|
+
export type InjectableClass<T = unknown> = (Class<T> | AbstractClass<T>) & {
|
|
8
|
+
[injectableSymbol]: Class<unknown>[];
|
|
9
|
+
};
|
|
10
|
+
export declare const injectableSymbol: unique symbol;
|
|
11
|
+
type ClassDecorator<C extends Class<unknown>> = (target: C) => C | void;
|
|
12
12
|
export declare function isInjectable<T>(target: AbstractClass<T>): target is InjectableClass<T>;
|
|
13
13
|
export declare function getInjectableTargets<T>(target: InjectableClass<T>): Class<unknown>[];
|
|
14
14
|
export {};
|
package/dist/decorators.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { getParentClasses } from "./utils.js";
|
|
2
|
-
export const injectableSymbol = Symbol("injectable");
|
|
3
2
|
/**
|
|
4
3
|
* The @injectable() decorator allows you to automatically bind a class as singleton service
|
|
5
4
|
* when requesting it from a DI container.
|
|
@@ -25,6 +24,7 @@ export function injectable() {
|
|
|
25
24
|
});
|
|
26
25
|
};
|
|
27
26
|
}
|
|
27
|
+
export const injectableSymbol = Symbol("injectable");
|
|
28
28
|
export function isInjectable(target) {
|
|
29
29
|
// eslint-disable-next-line no-prototype-builtins
|
|
30
30
|
return target.hasOwnProperty(injectableSymbol);
|
package/dist/decorators.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,gBAAgB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9E;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,gBAAgB,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,EAAE;YAC/C,IAAI,CAAC,MAAM,CAAC,wBAAwB,CAAC,WAAW,EAAE,gBAAgB,CAAC,EAAE,CAAC;gBACpE,MAAM,CAAC,cAAc,CAAC,WAAW,EAAE,gBAAgB,EAAE;oBACnD,KAAK,EAAE,CAAC,MAAM,CAAC;oBACf,QAAQ,EAAE,IAAI;oBACd,UAAU,EAAE,KAAK;iBAClB,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,MAAM,qBAAqB,GAAG,WAA8B,CAAC;gBAC7D,qBAAqB,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,qBAAqB,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC,CAAC;YACjG,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,gBAAgB,EAAE;YAC9C,KAAK,EAAE,CAAC,MAAM,CAAC;YACf,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAID,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;AAKrD,MAAM,UAAU,YAAY,CAAI,MAAwB;IACtD,iDAAiD;IACjD,OAAO,MAAM,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAI,MAA0B;IAChE,OAAO,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Provider } from "./providers.ts";
|
|
2
|
+
import { type Token } from "./tokens.ts";
|
|
3
|
+
import { Container } from "./container.ts";
|
|
4
|
+
/**
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export declare class Factory {
|
|
8
|
+
private readonly container;
|
|
9
|
+
constructor(container: Container);
|
|
10
|
+
construct<T>(provider: Provider<T>, token: Token<T>): T[];
|
|
11
|
+
constructAsync<T>(provider: Provider<T>): Promise<T[]>;
|
|
12
|
+
private doConstruct;
|
|
13
|
+
}
|
package/dist/factory.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {} from "./providers.js";
|
|
2
|
+
import { toString } from "./tokens.js";
|
|
3
|
+
import * as Guards from "./providers.js";
|
|
4
|
+
import { assertNever, retryOn } from "./utils.js";
|
|
5
|
+
import { Container } from "./container.js";
|
|
6
|
+
/**
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export class Factory {
|
|
10
|
+
container;
|
|
11
|
+
constructor(container) {
|
|
12
|
+
this.container = container;
|
|
13
|
+
}
|
|
14
|
+
construct(provider, token) {
|
|
15
|
+
if (Guards.isAsyncProvider(provider)) {
|
|
16
|
+
throw new AsyncProvidersInSyncInjectionContextError(token);
|
|
17
|
+
}
|
|
18
|
+
return this.doConstruct(provider);
|
|
19
|
+
}
|
|
20
|
+
async constructAsync(provider) {
|
|
21
|
+
if (Guards.isAsyncProvider(provider)) {
|
|
22
|
+
return [await provider.useFactory(this.container)];
|
|
23
|
+
}
|
|
24
|
+
// in class and constructor providers, we allow stuff to be synchronously injected,
|
|
25
|
+
// by just retrying when we encounter an async dependency down the road.
|
|
26
|
+
// todo: this feels like an ugly workaround, so let's create something nice for this.
|
|
27
|
+
if (Guards.isClassProvider(provider) || Guards.isConstructorProvider(provider)) {
|
|
28
|
+
const create = Guards.isConstructorProvider(provider) ? () => [new provider()] : () => [new provider.useClass()];
|
|
29
|
+
return retryOn(AsyncProvidersInSyncInjectionContextError, async () => create(), async (error) => {
|
|
30
|
+
await this.container.getAsync(error.token, { multi: true, optional: true });
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
// all other types of providers are constructed synchronously anyway.
|
|
34
|
+
return this.doConstruct(provider);
|
|
35
|
+
}
|
|
36
|
+
doConstruct(provider) {
|
|
37
|
+
if (Guards.isConstructorProvider(provider)) {
|
|
38
|
+
return [new provider()];
|
|
39
|
+
}
|
|
40
|
+
else if (Guards.isClassProvider(provider)) {
|
|
41
|
+
return [new provider.useClass()];
|
|
42
|
+
}
|
|
43
|
+
else if (Guards.isValueProvider(provider)) {
|
|
44
|
+
return [provider.useValue];
|
|
45
|
+
}
|
|
46
|
+
else if (Guards.isFactoryProvider(provider)) {
|
|
47
|
+
return [provider.useFactory(this.container)];
|
|
48
|
+
}
|
|
49
|
+
else if (Guards.isExistingProvider(provider)) {
|
|
50
|
+
return this.container.get(provider.useExisting, { multi: true });
|
|
51
|
+
}
|
|
52
|
+
return assertNever(provider);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* An error that occurs when an async provider is requested in a synchronous context.
|
|
57
|
+
*
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
class AsyncProvidersInSyncInjectionContextError extends Error {
|
|
61
|
+
token;
|
|
62
|
+
constructor(token) {
|
|
63
|
+
super(`Some providers for token ${toString(token)} are async, please use injectAsync() or container.getAsync() instead`);
|
|
64
|
+
this.token = token;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { Container, bootstrap, bootstrapAsync } from "./container.ts";
|
|
2
|
+
export { inject, injectAsync } from "./context.ts";
|
|
2
3
|
export { injectable } from "./decorators.ts";
|
|
3
|
-
export type {
|
|
4
|
+
export type { Provider, SyncProvider, AsyncProvider, ExistingProvider, ConstructorProvider, ClassProvider, ValueProvider, FactoryProvider, AsyncFactoryProvider, SyncFactoryProvider, } from "./providers.ts";
|
|
4
5
|
export { InjectionToken } from "./tokens.ts";
|
|
5
6
|
export type { Token } from "./tokens.ts";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { Container, bootstrap, bootstrapAsync } from "./container.js";
|
|
2
|
+
export { inject, injectAsync } from "./context.js";
|
|
2
3
|
export { injectable } from "./decorators.js";
|
|
3
4
|
export { InjectionToken } from "./tokens.js";
|
|
4
5
|
//# 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,
|
|
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"}
|
package/dist/providers.d.ts
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
import type { Token } from "./tokens.ts";
|
|
2
2
|
import { type Class } from "./utils.ts";
|
|
3
|
-
import type { Container } from
|
|
3
|
+
import type { Container } from "./container.ts";
|
|
4
4
|
/**
|
|
5
5
|
* A provider states how, for a given token, a service should be constructed.
|
|
6
6
|
*/
|
|
7
|
-
export type Provider<T> =
|
|
7
|
+
export type Provider<T> = SyncProvider<T> | AsyncProvider<T>;
|
|
8
|
+
/**
|
|
9
|
+
* A provider that provides synchronously, allowing a non-blocking process.
|
|
10
|
+
*/
|
|
11
|
+
export type SyncProvider<T> = ConstructorProvider<T> | ClassProvider<T> | ValueProvider<T> | SyncFactoryProvider<T> | ExistingProvider<T>;
|
|
12
|
+
/**
|
|
13
|
+
* A provider that provides asynchronously, enforcing an awaitable process.
|
|
14
|
+
*/
|
|
15
|
+
export type AsyncProvider<T> = AsyncFactoryProvider<T>;
|
|
16
|
+
/**
|
|
17
|
+
* A factory provider refers to a value which is lazily returned.
|
|
18
|
+
*/
|
|
19
|
+
export type FactoryProvider<T> = SyncFactoryProvider<T> | AsyncFactoryProvider<T>;
|
|
8
20
|
/**
|
|
9
21
|
* A constructor provider refers to a class constructor,
|
|
10
22
|
* which is the same class as the token itself.
|
|
@@ -20,7 +32,7 @@ export interface ClassProvider<T> {
|
|
|
20
32
|
multi?: true;
|
|
21
33
|
}
|
|
22
34
|
/**
|
|
23
|
-
*
|
|
35
|
+
* Provides a static value.
|
|
24
36
|
*/
|
|
25
37
|
export interface ValueProvider<T> {
|
|
26
38
|
provide: Token<T>;
|
|
@@ -28,18 +40,16 @@ export interface ValueProvider<T> {
|
|
|
28
40
|
multi?: true;
|
|
29
41
|
}
|
|
30
42
|
/**
|
|
31
|
-
*
|
|
32
|
-
* by a synchronous factory function.
|
|
43
|
+
* Provides a value which is lazily returned by a synchronous factory function.
|
|
33
44
|
*/
|
|
34
|
-
export interface
|
|
45
|
+
export interface SyncFactoryProvider<T> {
|
|
35
46
|
provide: Token<T>;
|
|
36
47
|
async?: false;
|
|
37
48
|
multi?: true;
|
|
38
49
|
useFactory: (container: Container) => NoInfer<T>;
|
|
39
50
|
}
|
|
40
51
|
/**
|
|
41
|
-
*
|
|
42
|
-
* by an asynchronous factory function.
|
|
52
|
+
* Provides a value which is lazily returned by an asynchronous factory function.
|
|
43
53
|
*/
|
|
44
54
|
export interface AsyncFactoryProvider<T> {
|
|
45
55
|
provide: Token<T>;
|
|
@@ -48,7 +58,7 @@ export interface AsyncFactoryProvider<T> {
|
|
|
48
58
|
useFactory: (container: Container) => Promise<NoInfer<T>>;
|
|
49
59
|
}
|
|
50
60
|
/**
|
|
51
|
-
*
|
|
61
|
+
* Provides a value that is provided by another provider.
|
|
52
62
|
*/
|
|
53
63
|
export interface ExistingProvider<T> {
|
|
54
64
|
provide: Token<T>;
|
|
@@ -59,6 +69,6 @@ export declare function isConstructorProvider<T>(provider: Provider<T>): provide
|
|
|
59
69
|
export declare function isClassProvider<T>(provider: Provider<T>): provider is ClassProvider<T>;
|
|
60
70
|
export declare function isValueProvider<T>(provider: Provider<T>): provider is ValueProvider<T>;
|
|
61
71
|
export declare function isFactoryProvider<T>(provider: Provider<T>): provider is FactoryProvider<T>;
|
|
62
|
-
export declare function
|
|
72
|
+
export declare function isAsyncProvider<T>(provider: Provider<T>): provider is AsyncProvider<T>;
|
|
63
73
|
export declare function isExistingProvider<T>(provider: Provider<T>): provider is ExistingProvider<T>;
|
|
64
74
|
export declare function isMultiProvider<T>(provider: Provider<T>): boolean;
|
package/dist/providers.js
CHANGED
|
@@ -9,10 +9,10 @@ export function isValueProvider(provider) {
|
|
|
9
9
|
return "provide" in provider && "useValue" in provider;
|
|
10
10
|
}
|
|
11
11
|
export function isFactoryProvider(provider) {
|
|
12
|
-
return "provide" in provider && "useFactory" in provider
|
|
12
|
+
return "provide" in provider && "useFactory" in provider;
|
|
13
13
|
}
|
|
14
|
-
export function
|
|
15
|
-
return
|
|
14
|
+
export function isAsyncProvider(provider) {
|
|
15
|
+
return isFactoryProvider(provider) && provider.async === true;
|
|
16
16
|
}
|
|
17
17
|
export function isExistingProvider(provider) {
|
|
18
18
|
return "provide" in provider && "useExisting" in provider;
|
package/dist/providers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
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"}
|
package/dist/tokens.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type AbstractClass, type Class } from "./utils.ts";
|
|
2
|
+
import { type Provider } from "./providers.ts";
|
|
2
3
|
/**
|
|
3
4
|
* A token is a reference to a service in the dependency injection (DI) container.
|
|
4
5
|
* When obtaining a service from the container, you should use this token.
|
|
@@ -23,17 +24,26 @@ type InjectionTokenOptions<T> = {
|
|
|
23
24
|
};
|
|
24
25
|
/**
|
|
25
26
|
* Type-guard to check if a token is a class reference.
|
|
27
|
+
*
|
|
26
28
|
* @internal
|
|
27
29
|
*/
|
|
28
30
|
export declare function isClassToken<T>(token: Token<T>): token is Class<T>;
|
|
29
31
|
/**
|
|
30
32
|
* Type-guard to check if a token is an InjectionToken
|
|
33
|
+
*
|
|
31
34
|
* @internal
|
|
32
35
|
*/
|
|
33
36
|
export declare function isInjectionToken<T>(token: Token<T>): token is InjectionToken<T>;
|
|
34
37
|
/**
|
|
35
38
|
* Describes a token, useful for error messages.
|
|
39
|
+
*
|
|
36
40
|
* @internal
|
|
37
41
|
*/
|
|
38
42
|
export declare function toString<T>(token: Token<T>): string;
|
|
43
|
+
/**
|
|
44
|
+
* Returns the token for a provider.
|
|
45
|
+
*
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
48
|
+
export declare function getToken<T>(provider: Provider<T>): Token<T>;
|
|
39
49
|
export {};
|
package/dist/tokens.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { isClassLike } from "./utils.js";
|
|
2
|
+
import {} from "./providers.js";
|
|
3
|
+
import * as Guards from "./providers.js";
|
|
2
4
|
/**
|
|
3
5
|
* A unique injection token object, that is used by reference. Can hold a generic type.
|
|
4
6
|
* Can optionally hold an (async) factory.
|
|
@@ -16,6 +18,7 @@ export class InjectionToken {
|
|
|
16
18
|
}
|
|
17
19
|
/**
|
|
18
20
|
* Type-guard to check if a token is a class reference.
|
|
21
|
+
*
|
|
19
22
|
* @internal
|
|
20
23
|
*/
|
|
21
24
|
export function isClassToken(token) {
|
|
@@ -23,6 +26,7 @@ export function isClassToken(token) {
|
|
|
23
26
|
}
|
|
24
27
|
/**
|
|
25
28
|
* Type-guard to check if a token is an InjectionToken
|
|
29
|
+
*
|
|
26
30
|
* @internal
|
|
27
31
|
*/
|
|
28
32
|
export function isInjectionToken(token) {
|
|
@@ -30,6 +34,7 @@ export function isInjectionToken(token) {
|
|
|
30
34
|
}
|
|
31
35
|
/**
|
|
32
36
|
* Describes a token, useful for error messages.
|
|
37
|
+
*
|
|
33
38
|
* @internal
|
|
34
39
|
*/
|
|
35
40
|
export function toString(token) {
|
|
@@ -46,4 +51,12 @@ export function toString(token) {
|
|
|
46
51
|
return token;
|
|
47
52
|
}
|
|
48
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Returns the token for a provider.
|
|
56
|
+
*
|
|
57
|
+
* @internal
|
|
58
|
+
*/
|
|
59
|
+
export function getToken(provider) {
|
|
60
|
+
return Guards.isConstructorProvider(provider) ? provider : provider.provide;
|
|
61
|
+
}
|
|
49
62
|
//# sourceMappingURL=tokens.js.map
|
package/dist/tokens.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,WAAW,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EAAiB,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AAQzC;;;GAGG;AACH,MAAM,OAAO,cAAc;IAEf;IACD;IAFT,YACU,WAA4B,EAC7B,OAAkC;QADjC,gBAAW,GAAX,WAAW,CAAiB;QAC7B,YAAO,GAAP,OAAO,CAA2B;IACxC,CAAC;IAEG,QAAQ;QACb,OAAO,mBAAmB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;IACxD,CAAC;CACF;AAYD;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAI,KAAe;IAC7C,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAI,KAAe;IACjD,OAAO,KAAK,YAAY,cAAc,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAI,KAAe;IACzC,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;SAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACrC,OAAO,KAAK,CAAC,WAAW,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;SAAM,IAAI,KAAK,YAAY,cAAc,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;SAAM,CAAC;QACN,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAI,QAAqB;IAC/C,OAAO,MAAM,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;AAC9E,CAAC"}
|
package/dist/utils.d.ts
CHANGED
|
@@ -5,21 +5,45 @@ export interface AbstractClass<T> {
|
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
7
|
* Type-guard to assert if the given object is an (abstract) class.
|
|
8
|
+
*
|
|
8
9
|
* @internal
|
|
9
10
|
*/
|
|
10
11
|
export declare function isClassLike(target: unknown): target is Class<unknown> | AbstractClass<unknown>;
|
|
11
12
|
/**
|
|
12
13
|
* Returns all parent classes of a given class.
|
|
14
|
+
*
|
|
13
15
|
* @internal
|
|
14
16
|
*/
|
|
15
17
|
export declare function getParentClasses(target: Class<unknown>): Class<unknown>[];
|
|
16
18
|
/**
|
|
17
19
|
* Ensures a given value is not null or undefined.
|
|
20
|
+
*
|
|
18
21
|
* @internal
|
|
19
22
|
*/
|
|
20
23
|
export declare function assertPresent<T>(value: T | null | undefined): T;
|
|
21
24
|
/**
|
|
25
|
+
* Creates slices of an array.
|
|
26
|
+
*
|
|
22
27
|
* @internal
|
|
23
28
|
*/
|
|
24
29
|
export declare function windowedSlice<T>(array: T[], step?: 2): [T, T][];
|
|
25
30
|
export declare function windowedSlice<T>(array: T[], step: number): T[][];
|
|
31
|
+
/**
|
|
32
|
+
* Retries as long as it encounters any error that is instance of `errorClass`.
|
|
33
|
+
* Awaits the result of the `onError` callback before retrying.
|
|
34
|
+
*
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
export declare function retryOn<TError, TReturn>(errorClass: Class<TError>, block: () => Promise<TReturn>, onError: (error: TError) => Promise<void>): Promise<TReturn>;
|
|
38
|
+
/**
|
|
39
|
+
* Assert that there is a single element in an array. Throws the error from error provider if not.
|
|
40
|
+
*
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
export declare function assertSingle<T>(array: T[], errorProvider: () => unknown): T;
|
|
44
|
+
/**
|
|
45
|
+
* Type-guard for `never` types, can be used to create exhaustive branches.
|
|
46
|
+
*
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
49
|
+
export declare function assertNever(_: never): never;
|
package/dist/utils.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Type-guard to assert if the given object is an (abstract) class.
|
|
3
|
+
*
|
|
3
4
|
* @internal
|
|
4
5
|
*/
|
|
5
6
|
export function isClassLike(target) {
|
|
@@ -7,6 +8,7 @@ export function isClassLike(target) {
|
|
|
7
8
|
}
|
|
8
9
|
/**
|
|
9
10
|
* Returns all parent classes of a given class.
|
|
11
|
+
*
|
|
10
12
|
* @internal
|
|
11
13
|
*/
|
|
12
14
|
export function getParentClasses(target) {
|
|
@@ -21,6 +23,7 @@ export function getParentClasses(target) {
|
|
|
21
23
|
}
|
|
22
24
|
/**
|
|
23
25
|
* Ensures a given value is not null or undefined.
|
|
26
|
+
*
|
|
24
27
|
* @internal
|
|
25
28
|
*/
|
|
26
29
|
export function assertPresent(value) {
|
|
@@ -38,4 +41,47 @@ export function windowedSlice(array, step = 2) {
|
|
|
38
41
|
});
|
|
39
42
|
return result;
|
|
40
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Retries as long as it encounters any error that is instance of `errorClass`.
|
|
46
|
+
* Awaits the result of the `onError` callback before retrying.
|
|
47
|
+
*
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
export async function retryOn(errorClass, block, onError) {
|
|
51
|
+
while (true) {
|
|
52
|
+
try {
|
|
53
|
+
return await block();
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
if (!(error instanceof errorClass)) {
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
await onError(error);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Assert that there is a single element in an array. Throws the error from error provider if not.
|
|
65
|
+
*
|
|
66
|
+
* @internal
|
|
67
|
+
*/
|
|
68
|
+
export function assertSingle(array, errorProvider) {
|
|
69
|
+
if (array.length > 1) {
|
|
70
|
+
throw errorProvider();
|
|
71
|
+
}
|
|
72
|
+
const first = array.at(0);
|
|
73
|
+
if (first === undefined) {
|
|
74
|
+
throw errorProvider();
|
|
75
|
+
}
|
|
76
|
+
return first;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Type-guard for `never` types, can be used to create exhaustive branches.
|
|
80
|
+
*
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
84
|
+
export function assertNever(_) {
|
|
85
|
+
throw new Error("invalid state");
|
|
86
|
+
}
|
|
41
87
|
//# 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
|
|
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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@needle-di/core",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "A simple TypeScript library for dependency injection",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|
|
25
|
-
"url": "git+https://github.com/needle-di/
|
|
25
|
+
"url": "git+https://github.com/needle-di/needle-di.git"
|
|
26
26
|
},
|
|
27
27
|
"type": "module",
|
|
28
28
|
"module": "./dist/index.js",
|
|
@@ -42,22 +42,21 @@
|
|
|
42
42
|
"test:ci": "vitest run --silent --coverage --coverage.reporter=json-summary",
|
|
43
43
|
"lint": "eslint src",
|
|
44
44
|
"lint:fix": "eslint src --fix",
|
|
45
|
-
"
|
|
46
|
-
"docs:dev": "vitepress dev docs",
|
|
47
|
-
"docs:build": "vitepress build docs",
|
|
48
|
-
"docs:preview": "vitepress preview docs"
|
|
45
|
+
"format": "prettier src/**/*.ts README.md --write"
|
|
49
46
|
},
|
|
50
47
|
"devDependencies": {
|
|
51
48
|
"@eslint/js": "^9.10.0",
|
|
52
49
|
"@release-it/bumper": "^6.0.1",
|
|
53
50
|
"@tsconfig/node20": "^20.1.4",
|
|
54
51
|
"@types/node": "^22.9.1",
|
|
52
|
+
"@typescript-eslint/parser": "^8.15.0",
|
|
55
53
|
"@vitest/coverage-v8": "^2.1.1",
|
|
56
|
-
"eslint": "
|
|
54
|
+
"eslint": "^9.14.0",
|
|
55
|
+
"eslint-plugin-import": "^2.31.0",
|
|
56
|
+
"eslint-import-resolver-typescript": "^3.6.3",
|
|
57
57
|
"prettier": "^3.3.3",
|
|
58
|
-
"typescript": "5.7.0
|
|
58
|
+
"typescript": "~5.7.0",
|
|
59
59
|
"typescript-eslint": "^8.6.0",
|
|
60
|
-
"vitepress": "^1.3.4",
|
|
61
60
|
"vitest": "^2.1.1"
|
|
62
61
|
}
|
|
63
62
|
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024 - 2025 Dirk Luijk
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/README.md
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# Needle DI 💉
|
|
2
|
-
|
|
3
|
-
> A lightweight, type-safe Dependency Injection (DI) library for JavaScript and TypeScript projects.
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/@needle-di/core)
|
|
6
|
-
[](https://jsr.io/@needle-di/core)
|
|
7
|
-
[](https://www.npmjs.com/package/@needle-di/core)
|
|
8
|
-
[](https://github.com/needle-di/core/actions/workflows/ci.yml)
|
|
9
|
-
[](https://github.com/needle-di/core/actions/workflows/ci.yml)
|
|
10
|
-
|
|
11
|
-
Needle DI is a lightweight, TypeScript-first library for dependency injection (DI). It is designed to be both easy to use and highly efficient.
|
|
12
|
-
|
|
13
|
-
### Key Features
|
|
14
|
-
|
|
15
|
-
- Stand-alone: No additional dependencies required
|
|
16
|
-
- Intended for both JavaScript-only and TypeScript projects
|
|
17
|
-
- Supports [tree-shakeable injection tokens](https://needle-di.io/advanced/tree-shaking.html): optimize your builds for production.
|
|
18
|
-
- Inspired by [Angular](https://angular.dev/) and [InversifyJS](https://github.com/inversify/InversifyJS), familiar to developers coming from these frameworks.
|
|
19
|
-
- Uses native [ECMAScript decorators](https://github.com/tc39/proposal-decorators) (currently stage 3)
|
|
20
|
-
- No need for `experimentalDecorators` and `emitDecoratorMetadata`
|
|
21
|
-
- No reflection libraries needed, like `reflect-metadata` or other reflection mechanisms.
|
|
22
|
-
|
|
23
|
-
## Basic example
|
|
24
|
-
|
|
25
|
-
Here’s a simple example using constructor injection to inject one service into another.
|
|
26
|
-
|
|
27
|
-
```typescript
|
|
28
|
-
import { injectable, inject } from "@needle-di/core";
|
|
29
|
-
|
|
30
|
-
@injectable()
|
|
31
|
-
class FooService {}
|
|
32
|
-
|
|
33
|
-
@injectable()
|
|
34
|
-
class BarService {
|
|
35
|
-
constructor(private fooService = inject(FooService)) {}
|
|
36
|
-
// ^? Type will be inferred as `FooService`
|
|
37
|
-
}
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
The `@injectable` decorator eliminates the need to manually register services. To construct the `BarService`, create a
|
|
41
|
-
dependency injection container, and use the `container.get()` method:
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
import { Container } from "@needle-di/core";
|
|
45
|
-
|
|
46
|
-
const container = new Container();
|
|
47
|
-
const barService = container.get(BarService);
|
|
48
|
-
// ^? Type will be inferred as `BarService`
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Check out the [docs](https://needle-di.io/concepts/binding.html) to learn more!
|
|
52
|
-
|
|
53
|
-
## Installation
|
|
54
|
-
|
|
55
|
-
```
|
|
56
|
-
npm install --save @needle-di/core
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
Needle DI also works with [Deno](https://deno.com/) and is published to [JSR](https://jsr.io/@needle-di/core) as well:
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
deno add jsr:@needle-di/core
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Docs
|
|
66
|
-
|
|
67
|
-
Check out our docs on [https://needle-di.io](https://needle-di.io/concepts/binding.html).
|
|
68
|
-
|
|
69
|
-
## License
|
|
70
|
-
|
|
71
|
-
License under the MIT License (MIT)
|
|
72
|
-
|
|
73
|
-
Copyright (c) 2024 - 2025 Dirk Luijk
|
|
74
|
-
|
|
75
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
76
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
77
|
-
in the Software without restriction, including without limitation the rights
|
|
78
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
79
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
80
|
-
furnished to do so, subject to the following conditions:
|
|
81
|
-
|
|
82
|
-
The above copyright notice and this permission notice shall be included in all
|
|
83
|
-
copies or substantial portions of the Software.
|
|
84
|
-
|
|
85
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
86
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
87
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
88
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
89
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
90
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
91
|
-
SOFTWARE.
|