@resolid/di 0.5.1 → 0.6.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/README.md +209 -97
- package/dist/index.d.ts +116 -40
- package/dist/index.js +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
#
|
|
1
|
+
# TypeScript Dependency Injection Container
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|

|
|
5
5
|
|
|
6
6
|
<b>[Documentation](https://www.resolid.tech/docs/di)</b> | [Framework Bundle](https://github.com/resolid/framework)
|
|
7
7
|
|
|
8
|
-
## TypeScript Dependency Injection Container
|
|
9
|
-
|
|
10
8
|
A lightweight, fully-typed Dependency Injection (DI) container for TypeScript.
|
|
11
|
-
Supports singleton & transient scopes, lazy resolution, and disposable resources. Fully functional with async factories
|
|
9
|
+
Supports singleton & transient scopes, lazy resolution, optional dependencies, and disposable resources. Fully functional with async factories
|
|
12
10
|
and avoids circular dependency issues.
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
## Features
|
|
15
13
|
|
|
16
14
|
- Fully typed with TypeScript, no any.
|
|
17
15
|
- Supports singleton and transient scopes.
|
|
18
|
-
- Lazy resolution for
|
|
16
|
+
- Lazy resolution for dependencies.
|
|
17
|
+
- Optional dependency resolution.
|
|
19
18
|
- Detects circular dependencies.
|
|
20
19
|
- Handles disposable instances with dispose() support.
|
|
21
|
-
- Fully async-compatible.
|
|
20
|
+
- Fully async-compatible with inject() and injectAsync() functions.
|
|
21
|
+
- Context-aware injection with InjectionContext.
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
## Installation
|
|
24
24
|
|
|
25
25
|
```shell
|
|
26
26
|
pnpm add @resolid/di
|
|
@@ -32,125 +32,237 @@ yarn add @resolid/di
|
|
|
32
32
|
bun add @resolid/di
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
## Usage
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
import { createContainer } from "@resolid/di";
|
|
37
|
+
### Basic
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const FACTORY = "FACTORY";
|
|
39
|
+
```typescript
|
|
40
|
+
import { Container, inject } from "@resolid/di";
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return value + " " + config.message || "from factory!";
|
|
58
|
-
},
|
|
59
|
-
/**
|
|
60
|
-
* Scope of a binding.
|
|
61
|
-
* singleton (default): Only one instance is created and shared for all resolves.
|
|
62
|
-
* transient: A new instance is created on each resolve.
|
|
63
|
-
*/
|
|
64
|
-
scope: "singleton",
|
|
65
|
-
/**
|
|
66
|
-
* Optional configuration object passed to a factory.
|
|
67
|
-
* Type is inferred from the factory definition.
|
|
68
|
-
* Used to provide parameters for instance creation.
|
|
69
|
-
*/
|
|
70
|
-
config: { message: " from factory with config" },
|
|
71
|
-
},
|
|
72
|
-
]);
|
|
42
|
+
class LogService {
|
|
43
|
+
log(message: string): void {
|
|
44
|
+
console.log(`[LOG]: ${message}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
class UserService {
|
|
49
|
+
private logger: LogService;
|
|
50
|
+
|
|
51
|
+
constructor(logger: LogService) {
|
|
52
|
+
this.logger = logger;
|
|
53
|
+
}
|
|
73
54
|
|
|
74
|
-
|
|
75
|
-
|
|
55
|
+
createUser(name: string): void {
|
|
56
|
+
this.logger.log(`Creating user: ${name}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const container = new Container();
|
|
61
|
+
|
|
62
|
+
container.add({
|
|
63
|
+
token: LogService,
|
|
64
|
+
factory: () => new LogService(),
|
|
65
|
+
});
|
|
76
66
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
67
|
+
container.add({
|
|
68
|
+
token: UserService,
|
|
69
|
+
factory: () => new UserService(inject(LogService)),
|
|
70
|
+
});
|
|
80
71
|
|
|
81
|
-
const
|
|
82
|
-
|
|
72
|
+
const userService = container.get(USER_SERVICE);
|
|
73
|
+
|
|
74
|
+
userService.createUser("John Doe"); // Output: [LOG]: Creating user: John Doe
|
|
83
75
|
```
|
|
84
76
|
|
|
85
|
-
###
|
|
77
|
+
### Scopes
|
|
78
|
+
|
|
79
|
+
The container supports two scopes:
|
|
86
80
|
|
|
87
|
-
|
|
81
|
+
- **singleton** (default): Only one instance is created and shared for all resolutions.
|
|
82
|
+
- **transient**: A new instance is created on each resolution.
|
|
88
83
|
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
|
|
84
|
+
```typescript
|
|
85
|
+
container.add({
|
|
86
|
+
token: LogService,
|
|
87
|
+
factory: () => new LogService(),
|
|
88
|
+
scope: "singleton", // Default scope
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
container.add({
|
|
92
|
+
token: Symbol("REQUEST_ID"),
|
|
93
|
+
factory: () => Math.random(),
|
|
94
|
+
scope: "transient", // New instance each time
|
|
95
|
+
});
|
|
96
|
+
```
|
|
92
97
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
### Asynchronous Dependencies
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { Container, injectAsync } from "@resolid/di";
|
|
102
|
+
|
|
103
|
+
class AsyncDatabaseService {
|
|
104
|
+
async connect(): Promise<void> {
|
|
105
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
106
|
+
console.log("Database connected");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
class AsyncUserService {
|
|
111
|
+
private db: AsyncDatabaseService;
|
|
112
|
+
|
|
113
|
+
constructor(db: AsyncDatabaseService) {
|
|
114
|
+
this.db = db;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async getUser(id: number): Promise<string> {
|
|
118
|
+
return `User ${id}`;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const container = new Container();
|
|
123
|
+
|
|
124
|
+
container.add({
|
|
125
|
+
token: AsyncDatabaseService,
|
|
126
|
+
factory: async () => {
|
|
127
|
+
const db = new AsyncDatabaseService();
|
|
128
|
+
await db.connect();
|
|
129
|
+
return db;
|
|
100
130
|
},
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
131
|
+
async: true,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
container.add({
|
|
135
|
+
token: AsyncUserService,
|
|
136
|
+
factory: async () => {
|
|
137
|
+
const db = await injectAsync(AsyncDatabaseService);
|
|
138
|
+
return new AsyncUserService(db);
|
|
107
139
|
},
|
|
108
|
-
|
|
140
|
+
async: true,
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Resolve async services
|
|
144
|
+
const userService = await container.getAsync(AsyncUserService);
|
|
145
|
+
const user = await userService.getUser(1);
|
|
146
|
+
|
|
147
|
+
console.log(user); // Output: User 1
|
|
148
|
+
```
|
|
109
149
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
150
|
+
### Optional Dependencies
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { Container, inject } from "@resolid/di";
|
|
154
|
+
|
|
155
|
+
class AnalyticsService {
|
|
156
|
+
private logger?: LogService;
|
|
157
|
+
|
|
158
|
+
constructor(logger?: LogService) {
|
|
159
|
+
this.logger = logger;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
track(event: string): void {
|
|
163
|
+
if (this.logger) {
|
|
164
|
+
this.logger.log(`Analytics: ${event}`);
|
|
165
|
+
} else {
|
|
166
|
+
console.log(`Analytics (no logger): ${event}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const container = new Container();
|
|
172
|
+
|
|
173
|
+
// Logger is optional
|
|
174
|
+
container.add({
|
|
175
|
+
token: AnalyticsService,
|
|
176
|
+
factory: () => new AnalyticsService(inject(LOG_SERVICE, { optional: true })),
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
const analytics = container.get(AnalyticsService);
|
|
180
|
+
analytics.track("page_view"); // Output: Analytics (no logger): page_view
|
|
113
181
|
```
|
|
114
182
|
|
|
115
|
-
|
|
183
|
+
### Lazy Resolution
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
import { Container, inject } from "@resolid/di";
|
|
187
|
+
|
|
188
|
+
class ReportService {
|
|
189
|
+
private getLogger: () => LogService;
|
|
190
|
+
|
|
191
|
+
constructor(private getLogger: () => LogService) {
|
|
192
|
+
this.getLogger = getLogger;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
generateReport(): void {
|
|
196
|
+
const logger = this.getLogger();
|
|
197
|
+
logger.log("Report generated");
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const container = new Container();
|
|
202
|
+
|
|
203
|
+
container.add({
|
|
204
|
+
token: LogService,
|
|
205
|
+
factory: () => new LogService(),
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
container.add({
|
|
209
|
+
token: ReportService,
|
|
210
|
+
factory: () => new ReportService(inject(LogService, { lazy: true })),
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
const reportService = container.get(ReportService);
|
|
214
|
+
reportService.generateReport(); // Output: [LOG]: Report generated
|
|
215
|
+
```
|
|
116
216
|
|
|
117
217
|
### Circular Dependency Detection
|
|
118
218
|
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
|
|
219
|
+
```typescript
|
|
220
|
+
class ApiService {
|
|
221
|
+
constructor(private auth: AuthService) {}
|
|
222
|
+
}
|
|
122
223
|
|
|
123
|
-
|
|
124
|
-
{
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
224
|
+
class AuthService {
|
|
225
|
+
constructor(private api: ApiService) {}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const container = new Container();
|
|
229
|
+
|
|
230
|
+
container.add({
|
|
231
|
+
token: ApiService,
|
|
232
|
+
factory: () => new ApiService(inject(AuthService)),
|
|
233
|
+
});
|
|
133
234
|
|
|
134
|
-
|
|
135
|
-
|
|
235
|
+
container.add({
|
|
236
|
+
token: AuthService,
|
|
237
|
+
factory: () => new AuthService(inject(ApiService)),
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
container.get(ApiService); // Throws: Circular dependency detected ApiService -> AuthService -> ApiService
|
|
136
241
|
```
|
|
137
242
|
|
|
138
|
-
###
|
|
243
|
+
### Disposable Resources
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
import { Container } from "@resolid/di";
|
|
139
247
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
console.log("Resource disposed");
|
|
248
|
+
class DatabaseConnection {
|
|
249
|
+
async dispose(): Promise<void> {
|
|
250
|
+
console.log("Database connection closed");
|
|
144
251
|
}
|
|
145
252
|
}
|
|
146
253
|
|
|
147
|
-
const
|
|
254
|
+
const container = new Container();
|
|
255
|
+
|
|
256
|
+
container.add({
|
|
257
|
+
token: DatabaseConnection,
|
|
258
|
+
factory: async () => new DatabaseConnection(),
|
|
259
|
+
async: true,
|
|
260
|
+
});
|
|
148
261
|
|
|
149
|
-
const
|
|
262
|
+
const db = await container.getAsync(DatabaseConnection);
|
|
150
263
|
|
|
151
264
|
// Dispose all singleton instances
|
|
152
|
-
await container.dispose();
|
|
153
|
-
// Output: "Resource disposed"
|
|
265
|
+
await container.dispose(); // Output: Database connection closed
|
|
154
266
|
```
|
|
155
267
|
|
|
156
268
|
## License
|
package/dist/index.d.ts
CHANGED
|
@@ -1,45 +1,121 @@
|
|
|
1
|
-
//#region src/index.d.ts
|
|
2
|
-
type
|
|
3
|
-
|
|
4
|
-
value: T;
|
|
5
|
-
}>;
|
|
6
|
-
type Scope = "singleton" | "transient";
|
|
7
|
-
type Resolver = {
|
|
8
|
-
resolve: Resolve;
|
|
9
|
-
lazyResolve: LazyResolve;
|
|
10
|
-
};
|
|
11
|
-
type FactoryConfig = Record<string, unknown>;
|
|
12
|
-
type BindingDefinition<T$1 = unknown, C extends FactoryConfig = FactoryConfig> = {
|
|
13
|
-
name: string;
|
|
14
|
-
value: T$1;
|
|
15
|
-
callable?: never;
|
|
16
|
-
factory?: never;
|
|
17
|
-
scope?: never;
|
|
18
|
-
config?: never;
|
|
19
|
-
} | {
|
|
1
|
+
//#region src/shared/index.d.ts
|
|
2
|
+
type Token<T = unknown> = symbol | (new (...args: any[]) => T) | {
|
|
3
|
+
prototype: T;
|
|
20
4
|
name: string;
|
|
21
|
-
callable: (...args: unknown[]) => T$1;
|
|
22
|
-
value?: never;
|
|
23
|
-
factory?: never;
|
|
24
|
-
scope?: never;
|
|
25
|
-
config?: never;
|
|
26
|
-
} | {
|
|
27
|
-
name: string;
|
|
28
|
-
factory: (options: {
|
|
29
|
-
resolver: Resolver;
|
|
30
|
-
config?: C;
|
|
31
|
-
}) => T$1 | Promise<T$1>;
|
|
32
|
-
scope?: Scope;
|
|
33
|
-
config?: C;
|
|
34
|
-
value?: never;
|
|
35
|
-
callable?: never;
|
|
36
5
|
};
|
|
37
|
-
|
|
6
|
+
interface Disposable {
|
|
38
7
|
dispose: () => Promise<void> | void;
|
|
8
|
+
}
|
|
9
|
+
interface Resolver {
|
|
10
|
+
get: (<T>(token: Token<T>) => T) & (<T>(token: Token<T>, options: {
|
|
11
|
+
optional: true;
|
|
12
|
+
}) => T | undefined) & (<T>(token: Token<T>, options: {
|
|
13
|
+
lazy: true;
|
|
14
|
+
}) => () => T) & (<T>(token: Token<T>, options: {
|
|
15
|
+
lazy: true;
|
|
16
|
+
optional: true;
|
|
17
|
+
}) => () => T | undefined) & (<T>(token: Token<T>, options: {
|
|
18
|
+
lazy?: false;
|
|
19
|
+
optional?: boolean;
|
|
20
|
+
}) => T | undefined) & (<T>(token: Token<T>, options?: {
|
|
21
|
+
lazy?: boolean;
|
|
22
|
+
optional?: boolean;
|
|
23
|
+
}) => T | undefined | (() => T | undefined));
|
|
24
|
+
getAsync: (<T>(token: Token<T>) => Promise<T>) & (<T>(token: Token<T>, options: {
|
|
25
|
+
optional: true;
|
|
26
|
+
}) => Promise<T | undefined>) & (<T>(token: Token<T>, options: {
|
|
27
|
+
lazy: true;
|
|
28
|
+
}) => () => Promise<T>) & (<T>(token: Token<T>, options: {
|
|
29
|
+
lazy: true;
|
|
30
|
+
optional: true;
|
|
31
|
+
}) => () => Promise<T | undefined>) & (<T>(token: Token<T>, options: {
|
|
32
|
+
lazy?: false;
|
|
33
|
+
optional?: boolean;
|
|
34
|
+
}) => Promise<T | undefined>) & (<T>(token: Token<T>, options?: {
|
|
35
|
+
lazy?: boolean;
|
|
36
|
+
optional?: boolean;
|
|
37
|
+
}) => Promise<T | undefined> | (() => Promise<T | undefined>));
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/container/index.d.ts
|
|
41
|
+
type Scope = "singleton" | "transient";
|
|
42
|
+
type SyncProvider<T = unknown> = {
|
|
43
|
+
token: Token<T>;
|
|
44
|
+
factory: (resolver: Resolver) => T;
|
|
45
|
+
async?: false;
|
|
46
|
+
scope?: Scope;
|
|
39
47
|
};
|
|
40
|
-
type
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
48
|
+
type AsyncProvider<T = unknown> = {
|
|
49
|
+
token: Token<T>;
|
|
50
|
+
factory: (resolver: Resolver) => Promise<T>;
|
|
51
|
+
async?: true;
|
|
52
|
+
scope?: Scope;
|
|
53
|
+
};
|
|
54
|
+
type Provider<T = unknown> = SyncProvider<T> | AsyncProvider<T>;
|
|
55
|
+
declare class Container implements Resolver, Disposable {
|
|
56
|
+
private readonly _providers;
|
|
57
|
+
private readonly _singletons;
|
|
58
|
+
private readonly _constructing;
|
|
59
|
+
private _checkCircularDependency;
|
|
60
|
+
private _resolveProvide;
|
|
61
|
+
private _resolve;
|
|
62
|
+
private _resolveAsync;
|
|
63
|
+
add(provider: Provider): void;
|
|
64
|
+
get<T>(token: Token<T>): T;
|
|
65
|
+
get<T>(token: Token<T>, options: {
|
|
66
|
+
optional: true;
|
|
67
|
+
}): T | undefined;
|
|
68
|
+
get<T>(token: Token<T>, options: {
|
|
69
|
+
lazy: true;
|
|
70
|
+
}): () => T;
|
|
71
|
+
get<T>(token: Token<T>, options: {
|
|
72
|
+
lazy: true;
|
|
73
|
+
optional: true;
|
|
74
|
+
}): () => T | undefined;
|
|
75
|
+
get<T>(token: Token<T>, options: {
|
|
76
|
+
lazy?: false;
|
|
77
|
+
optional?: boolean;
|
|
78
|
+
}): T | undefined;
|
|
79
|
+
getAsync<T>(token: Token<T>): Promise<T>;
|
|
80
|
+
getAsync<T>(token: Token<T>, options: {
|
|
81
|
+
optional: true;
|
|
82
|
+
}): Promise<T | undefined>;
|
|
83
|
+
getAsync<T>(token: Token<T>, options: {
|
|
84
|
+
lazy: true;
|
|
85
|
+
}): () => Promise<T>;
|
|
86
|
+
getAsync<T>(token: Token<T>, options: {
|
|
87
|
+
lazy: true;
|
|
88
|
+
optional: true;
|
|
89
|
+
}): () => Promise<T | undefined>;
|
|
90
|
+
getAsync<T>(token: Token<T>, options: {
|
|
91
|
+
lazy?: false;
|
|
92
|
+
optional?: boolean;
|
|
93
|
+
}): Promise<T | undefined>;
|
|
94
|
+
dispose(): Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/inject/index.d.ts
|
|
98
|
+
declare function inject<T>(token: Token<T>): T;
|
|
99
|
+
declare function inject<T>(token: Token<T>, options: {
|
|
100
|
+
optional: true;
|
|
101
|
+
}): T | undefined;
|
|
102
|
+
declare function inject<T>(token: Token<T>, options: {
|
|
103
|
+
lazy: true;
|
|
104
|
+
}): () => T;
|
|
105
|
+
declare function inject<T>(token: Token<T>, options: {
|
|
106
|
+
lazy: true;
|
|
107
|
+
optional: true;
|
|
108
|
+
}): () => T | undefined;
|
|
109
|
+
declare function injectAsync<T>(token: Token<T>): Promise<T>;
|
|
110
|
+
declare function injectAsync<T>(token: Token<T>, options: {
|
|
111
|
+
optional: true;
|
|
112
|
+
}): Promise<T | undefined>;
|
|
113
|
+
declare function injectAsync<T>(token: Token<T>, options: {
|
|
114
|
+
lazy: true;
|
|
115
|
+
}): () => Promise<T>;
|
|
116
|
+
declare function injectAsync<T>(token: Token<T>, options: {
|
|
117
|
+
lazy: true;
|
|
118
|
+
optional: true;
|
|
119
|
+
}): () => Promise<T | undefined>;
|
|
44
120
|
//#endregion
|
|
45
|
-
export {
|
|
121
|
+
export { Container, Provider, type Resolver, Scope, type Token, inject, injectAsync };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
var e=class extends Error{constructor(){super(`inject() / injectAsync() must be called within a injection context`)}},t=class t{static contextStack=[];resolver;constructor(e){this.resolver=e}static current(){let t=this.contextStack[this.contextStack.length-1];if(t===void 0)throw new e;return t}run(e){t.contextStack.push(this);try{return e(this.resolver)}finally{t.contextStack.pop()}}async runAsync(e){t.contextStack.push(this);try{return await e(this.resolver)}finally{t.contextStack.pop()}}};function n(e){return typeof e==`symbol`?e.description??String(e):e.name}var r=class{_providers=new Map;_singletons=new Map;_constructing=[];_checkCircularDependency(e){if(this._constructing.includes(e))throw Error(`Circular dependency detected ${[...this._constructing,e].map(n).join(` -> `)}`)}_resolveProvide(e,t){let r=this._providers.get(e);if(r===void 0&&!t)throw Error(`No provider found for ${n(e)}`);return r}_resolve(e,r){this._checkCircularDependency(e);let i=this._resolveProvide(e,r);if(i===void 0)return;if(i.async)throw Error(`Provider for ${n(e)} is async, please use injectAsync()`);let a=i.scope!==`transient`;if(a&&this._singletons.has(e))return this._singletons.get(e);this._constructing.push(e);try{let n=new t(this).run(()=>i.factory(this));return a&&this._singletons.set(e,n),n}finally{this._constructing.pop()}}async _resolveAsync(e,n){this._checkCircularDependency(e);let r=this._resolveProvide(e,n);if(r===void 0)return;let i=r.scope!==`transient`;if(i&&this._singletons.has(e))return this._singletons.get(e);this._constructing.push(e);try{let n=await new t(this).runAsync(async()=>await r.factory(this));return i&&this._singletons.set(e,n),n}finally{this._constructing.pop()}}add(e){this._providers.set(e.token,e)}get(e,t){return t?.lazy??!1?()=>this.get(e,{...t,lazy:!1}):this._resolve(e,t?.optional??!1)}getAsync(e,t){return t?.lazy??!1?()=>this.getAsync(e,{...t,lazy:!1}):this._resolveAsync(e,t?.optional??!1)}async dispose(){let e=0,t=``;for(let[r,i]of this._singletons)if(typeof i.dispose==`function`)try{await i.dispose()}catch(i){e++,t+=`${n(r)}: ${i instanceof Error?i.message:i}; `}if(this._singletons.clear(),e>0)throw Error(`Failed to dispose ${e} provider(s):\n${t.slice(0,-2)}`)}};function i(n,r){try{return t.current().run(e=>e.get(n,r))}catch(t){if(t instanceof e&&r?.optional==1)return;throw t}}function a(n,r){try{return r?.lazy?t.current().run(e=>e.getAsync(n,{...r,lazy:!0})):t.current().runAsync(e=>e.getAsync(n,{...r,lazy:!1}))}catch(t){return t instanceof e&&r?.optional===!0?r?.lazy?()=>Promise.resolve(void 0):Promise.resolve(void 0):Promise.reject(t)}}export{r as Container,i as inject,a as injectAsync};
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@resolid/di",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "TypeScript Dependency Injection Container",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"resolid",
|
|
8
8
|
"container",
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"dist"
|
|
37
37
|
],
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@vitest/coverage-v8": "
|
|
40
|
-
"tsdown": "^0.15.
|
|
39
|
+
"@vitest/coverage-v8": "^4.0.4",
|
|
40
|
+
"tsdown": "^0.15.11",
|
|
41
41
|
"typescript": "^5.9.3",
|
|
42
|
-
"vitest": "
|
|
42
|
+
"vitest": "^4.0.4"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
45
|
"node": "^20.19.0 || ^22.13.0 || >=24"
|