@djodjonx/neo-syringe 1.1.5 → 1.2.2

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.
Files changed (61) hide show
  1. package/.github/workflows/ci.yml +6 -5
  2. package/.github/workflows/docs.yml +59 -0
  3. package/CHANGELOG.md +27 -0
  4. package/README.md +74 -740
  5. package/dist/{GraphValidator-G0F4QiLk.cjs → GraphValidator-CV4VoJl0.cjs} +18 -10
  6. package/dist/{GraphValidator-C8ldJtNp.mjs → GraphValidator-DXqqkNdS.mjs} +18 -10
  7. package/dist/cli/index.cjs +16 -1
  8. package/dist/cli/index.mjs +16 -1
  9. package/dist/index.d.cts +31 -5
  10. package/dist/index.d.mts +31 -5
  11. package/dist/lsp/index.cjs +1 -1
  12. package/dist/lsp/index.mjs +1 -1
  13. package/dist/unplugin/index.cjs +33 -9
  14. package/dist/unplugin/index.d.cts +7 -5
  15. package/dist/unplugin/index.d.mts +7 -5
  16. package/dist/unplugin/index.mjs +33 -9
  17. package/docs/.vitepress/config.ts +109 -0
  18. package/docs/.vitepress/theme/custom.css +150 -0
  19. package/docs/.vitepress/theme/index.ts +17 -0
  20. package/docs/api/configuration.md +274 -0
  21. package/docs/api/functions.md +291 -0
  22. package/docs/api/types.md +158 -0
  23. package/docs/guide/basic-usage.md +267 -0
  24. package/docs/guide/cli.md +174 -0
  25. package/docs/guide/generated-code.md +284 -0
  26. package/docs/guide/getting-started.md +171 -0
  27. package/docs/guide/ide-plugin.md +203 -0
  28. package/docs/guide/injection-types.md +287 -0
  29. package/docs/guide/legacy-migration.md +333 -0
  30. package/docs/guide/lifecycle.md +223 -0
  31. package/docs/guide/parent-container.md +321 -0
  32. package/docs/guide/scoped-injections.md +271 -0
  33. package/docs/guide/what-is-neo-syringe.md +162 -0
  34. package/docs/guide/why-neo-syringe.md +219 -0
  35. package/docs/index.md +138 -0
  36. package/docs/public/logo.png +0 -0
  37. package/package.json +15 -12
  38. package/src/analyzer/Analyzer.ts +20 -10
  39. package/src/analyzer/types.ts +55 -49
  40. package/src/cli/index.ts +15 -0
  41. package/src/generator/Generator.ts +24 -2
  42. package/src/generator/GraphValidator.ts +6 -2
  43. package/src/types.ts +30 -4
  44. package/src/unplugin/index.ts +13 -41
  45. package/tests/analyzer/Analyzer.test.ts +4 -4
  46. package/tests/analyzer/AnalyzerDeclarative.test.ts +1 -1
  47. package/tests/analyzer/Factory.test.ts +2 -2
  48. package/tests/analyzer/Scoped.test.ts +434 -0
  49. package/tests/cli/cli.test.ts +91 -0
  50. package/tests/e2e/container-integration.test.ts +21 -21
  51. package/tests/e2e/generated-code.test.ts +7 -7
  52. package/tests/e2e/scoped.test.ts +370 -0
  53. package/tests/e2e/snapshots.test.ts +2 -2
  54. package/tests/e2e/standalone.test.ts +2 -2
  55. package/tests/generator/ExternalGenerator.test.ts +1 -1
  56. package/tests/generator/FactoryGenerator.test.ts +6 -6
  57. package/tests/generator/Generator.test.ts +2 -2
  58. package/tests/generator/GeneratorDeclarative.test.ts +1 -1
  59. package/tests/generator/GraphValidator.test.ts +1 -1
  60. package/tsconfig.json +2 -1
  61. package/typedoc.json +0 -5
@@ -0,0 +1,291 @@
1
+ # Functions
2
+
3
+ API functions exported by Neo-Syringe.
4
+
5
+ ## defineBuilderConfig
6
+
7
+ ```typescript
8
+ function defineBuilderConfig(config: BuilderConfig): Container
9
+ ```
10
+
11
+ Define a container configuration. At runtime without the build plugin, this throws an error. At build time, it's replaced with the generated container.
12
+
13
+ ### Parameters
14
+
15
+ | Name | Type | Description |
16
+ |------|------|-------------|
17
+ | `config` | `BuilderConfig` | Container configuration |
18
+
19
+ ### Returns
20
+
21
+ `Container` - The generated container (after build)
22
+
23
+ ### Example
24
+
25
+ ```typescript
26
+ import { defineBuilderConfig, useInterface } from '@djodjonx/neo-syringe';
27
+
28
+ export const container = defineBuilderConfig({
29
+ name: 'AppContainer',
30
+ injections: [
31
+ { token: useInterface<ILogger>(), provider: ConsoleLogger },
32
+ { token: UserService }
33
+ ]
34
+ });
35
+ ```
36
+
37
+ ---
38
+
39
+ ## definePartialConfig
40
+
41
+ ```typescript
42
+ function definePartialConfig(config: PartialConfig): PartialConfig
43
+ ```
44
+
45
+ Define a reusable partial configuration that can be extended.
46
+
47
+ ### Parameters
48
+
49
+ | Name | Type | Description |
50
+ |------|------|-------------|
51
+ | `config` | `PartialConfig` | Partial configuration |
52
+
53
+ ### Returns
54
+
55
+ `PartialConfig` - The partial configuration
56
+
57
+ ### Example
58
+
59
+ ```typescript
60
+ import { definePartialConfig, useInterface } from '@djodjonx/neo-syringe';
61
+
62
+ export const loggingPartial = definePartialConfig({
63
+ injections: [
64
+ { token: useInterface<ILogger>(), provider: ConsoleLogger }
65
+ ]
66
+ });
67
+
68
+ // Use in main config
69
+ export const container = defineBuilderConfig({
70
+ extends: [loggingPartial],
71
+ injections: [
72
+ { token: UserService }
73
+ ]
74
+ });
75
+ ```
76
+
77
+ ---
78
+
79
+ ## useInterface
80
+
81
+ ```typescript
82
+ function useInterface<T>(): InterfaceToken<T>
83
+ ```
84
+
85
+ Create a token for an interface. At compile time, this generates a unique string ID.
86
+
87
+ ### Type Parameters
88
+
89
+ | Name | Description |
90
+ |------|-------------|
91
+ | `T` | The interface type |
92
+
93
+ ### Returns
94
+
95
+ `InterfaceToken<T>` - A token representing the interface
96
+
97
+ ### Example
98
+
99
+ ```typescript
100
+ import { useInterface } from '@djodjonx/neo-syringe';
101
+
102
+ interface ILogger {
103
+ log(msg: string): void;
104
+ }
105
+
106
+ interface IDatabase {
107
+ query(sql: string): any[];
108
+ }
109
+
110
+ // In configuration
111
+ {
112
+ injections: [
113
+ { token: useInterface<ILogger>(), provider: ConsoleLogger },
114
+ { token: useInterface<IDatabase>(), provider: PostgresDatabase }
115
+ ]
116
+ }
117
+
118
+ // Resolution
119
+ const logger = container.resolve(useInterface<ILogger>());
120
+ ```
121
+
122
+ ---
123
+
124
+ ## useProperty
125
+
126
+ ```typescript
127
+ function useProperty<T, C = unknown>(
128
+ targetClass: Constructor<C>,
129
+ paramName: string
130
+ ): PropertyToken<T, C>
131
+ ```
132
+
133
+ Create a token for a primitive constructor parameter.
134
+
135
+ ### Type Parameters
136
+
137
+ | Name | Description |
138
+ |------|-------------|
139
+ | `T` | The primitive type (string, number, boolean) |
140
+ | `C` | The class type |
141
+
142
+ ### Parameters
143
+
144
+ | Name | Type | Description |
145
+ |------|------|-------------|
146
+ | `targetClass` | `Constructor<C>` | The class that has this parameter |
147
+ | `paramName` | `string` | The parameter name |
148
+
149
+ ### Returns
150
+
151
+ `PropertyToken<T, C>` - A token for the primitive
152
+
153
+ ### Example
154
+
155
+ ```typescript
156
+ import { useProperty } from '@djodjonx/neo-syringe';
157
+
158
+ class ApiService {
159
+ constructor(
160
+ private apiUrl: string,
161
+ private timeout: number
162
+ ) {}
163
+ }
164
+
165
+ const apiUrl = useProperty<string>(ApiService, 'apiUrl');
166
+ const timeout = useProperty<number>(ApiService, 'timeout');
167
+
168
+ // In configuration
169
+ {
170
+ injections: [
171
+ { token: apiUrl, provider: () => 'https://api.example.com' },
172
+ { token: timeout, provider: () => 5000 },
173
+ { token: ApiService }
174
+ ]
175
+ }
176
+ ```
177
+
178
+ ---
179
+
180
+ ## declareContainerTokens
181
+
182
+ ```typescript
183
+ function declareContainerTokens<T>(container: any): any
184
+ ```
185
+
186
+ Declare tokens provided by a legacy container for type-safety and validation.
187
+
188
+ ### Type Parameters
189
+
190
+ | Name | Description |
191
+ |------|-------------|
192
+ | `T` | Object type mapping token names to types |
193
+
194
+ ### Parameters
195
+
196
+ | Name | Type | Description |
197
+ |------|------|-------------|
198
+ | `container` | `any` | The legacy container instance |
199
+
200
+ ### Returns
201
+
202
+ The container with declared types
203
+
204
+ ### Example
205
+
206
+ ```typescript
207
+ import { declareContainerTokens } from '@djodjonx/neo-syringe';
208
+ import { container as tsyringeContainer } from 'tsyringe';
209
+
210
+ // Declare what tsyringe provides
211
+ const legacy = declareContainerTokens<{
212
+ AuthService: AuthService;
213
+ UserRepository: UserRepository;
214
+ }>(tsyringeContainer);
215
+
216
+ // Use in configuration
217
+ export const container = defineBuilderConfig({
218
+ useContainer: legacy,
219
+ injections: [
220
+ { token: NewService } // Can depend on AuthService, UserRepository
221
+ ]
222
+ });
223
+ ```
224
+
225
+ ---
226
+
227
+ ## Container.resolve
228
+
229
+ ```typescript
230
+ resolve<T>(token: Token<T>): T
231
+ ```
232
+
233
+ Resolve a service from the container.
234
+
235
+ ### Type Parameters
236
+
237
+ | Name | Description |
238
+ |------|-------------|
239
+ | `T` | The service type |
240
+
241
+ ### Parameters
242
+
243
+ | Name | Type | Description |
244
+ |------|------|-------------|
245
+ | `token` | `Token<T>` | Class, interface token, or property token |
246
+
247
+ ### Returns
248
+
249
+ `T` - The resolved instance
250
+
251
+ ### Throws
252
+
253
+ `Error` - If the service is not found
254
+
255
+ ### Example
256
+
257
+ ```typescript
258
+ // By class
259
+ const userService = container.resolve(UserService);
260
+
261
+ // By interface
262
+ const logger = container.resolve(useInterface<ILogger>());
263
+
264
+ // By property (unusual, but possible)
265
+ const apiUrl = container.resolve(useProperty<string>(ApiService, 'apiUrl'));
266
+ ```
267
+
268
+ ---
269
+
270
+ ## Container.createChildContainer
271
+
272
+ ```typescript
273
+ createChildContainer(): Container
274
+ ```
275
+
276
+ Create a child container that inherits from this one.
277
+
278
+ ### Returns
279
+
280
+ `Container` - A new child container
281
+
282
+ ### Example
283
+
284
+ ```typescript
285
+ const parent = container;
286
+ const child = parent.createChildContainer();
287
+
288
+ // Child can resolve parent's services
289
+ const logger = child.resolve(useInterface<ILogger>());
290
+ ```
291
+
@@ -0,0 +1,158 @@
1
+ # Types
2
+
3
+ Type definitions for Neo-Syringe.
4
+
5
+ ## Lifecycle
6
+
7
+ ```typescript
8
+ type Lifecycle = 'singleton' | 'transient';
9
+ ```
10
+
11
+ Defines how instances are managed:
12
+
13
+ | Value | Description |
14
+ |-------|-------------|
15
+ | `singleton` | One instance per container (default) |
16
+ | `transient` | New instance on every `resolve()` |
17
+
18
+ ## Constructor
19
+
20
+ ```typescript
21
+ type Constructor<T = unknown> = new (...args: unknown[]) => T;
22
+ ```
23
+
24
+ Represents any class constructor.
25
+
26
+ ## Token
27
+
28
+ ```typescript
29
+ type Token<T = any> = Constructor<T> | InterfaceToken<T> | PropertyToken<T, any>;
30
+ ```
31
+
32
+ A token that can be resolved by the container:
33
+
34
+ - **Constructor**: A class reference (e.g., `UserService`)
35
+ - **InterfaceToken**: Created by `useInterface<T>()`
36
+ - **PropertyToken**: Created by `useProperty<T>(Class, 'param')`
37
+
38
+ ## InterfaceToken
39
+
40
+ ```typescript
41
+ type InterfaceToken<T> = {
42
+ __brand: 'InterfaceToken';
43
+ __type: T;
44
+ };
45
+ ```
46
+
47
+ A compile-time token for interfaces. Created by `useInterface<T>()`.
48
+
49
+ ::: warning Internal Type
50
+ You don't create this directly. Use `useInterface<T>()` instead.
51
+ :::
52
+
53
+ ## PropertyToken
54
+
55
+ ```typescript
56
+ type PropertyToken<T, C = unknown> = {
57
+ __brand: 'PropertyToken';
58
+ __type: T;
59
+ __class: C;
60
+ __name: string;
61
+ };
62
+ ```
63
+
64
+ A token for primitive values bound to a specific class parameter. Created by `useProperty<T>(Class, 'param')`.
65
+
66
+ ## Provider
67
+
68
+ ```typescript
69
+ type Provider<T> = Constructor<T> | Factory<T>;
70
+ ```
71
+
72
+ What creates instances:
73
+
74
+ - **Constructor**: A class to instantiate
75
+ - **Factory**: A function that creates the instance
76
+
77
+ ## Factory
78
+
79
+ ```typescript
80
+ type Factory<T> = (container: Container) => T;
81
+ ```
82
+
83
+ A function that receives the container and returns an instance.
84
+
85
+ ```typescript
86
+ const myFactory: Factory<IConfig> = (container) => ({
87
+ apiUrl: process.env.API_URL,
88
+ logger: container.resolve(useInterface<ILogger>())
89
+ });
90
+ ```
91
+
92
+ ## Injection
93
+
94
+ ```typescript
95
+ interface Injection<T = any> {
96
+ token: Token<T>;
97
+ provider?: Provider<T>;
98
+ useFactory?: boolean;
99
+ lifecycle?: Lifecycle;
100
+ scoped?: boolean;
101
+ }
102
+ ```
103
+
104
+ A single injection definition:
105
+
106
+ | Property | Type | Description |
107
+ |----------|------|-------------|
108
+ | `token` | `Token<T>` | **Required**. What to register |
109
+ | `provider` | `Provider<T>` | Optional. What provides the instance |
110
+ | `useFactory` | `boolean` | Explicit factory flag |
111
+ | `lifecycle` | `Lifecycle` | `'singleton'` (default) or `'transient'` |
112
+ | `scoped` | `boolean` | If `true`, resolve locally (override parent) |
113
+
114
+ ## PartialConfig
115
+
116
+ ```typescript
117
+ interface PartialConfig {
118
+ injections?: Injection[];
119
+ }
120
+ ```
121
+
122
+ A reusable configuration block.
123
+
124
+ ## BuilderConfig
125
+
126
+ ```typescript
127
+ interface BuilderConfig extends PartialConfig {
128
+ name?: string;
129
+ extends?: PartialConfig[];
130
+ useContainer?: any;
131
+ }
132
+ ```
133
+
134
+ Main configuration for a container:
135
+
136
+ | Property | Type | Description |
137
+ |----------|------|-------------|
138
+ | `name` | `string` | Container name (for debugging) |
139
+ | `injections` | `Injection[]` | List of injections |
140
+ | `extends` | `PartialConfig[]` | Inherit from partials |
141
+ | `useContainer` | `any` | Parent container |
142
+
143
+ ## Container
144
+
145
+ ```typescript
146
+ interface Container {
147
+ resolve<T>(token: Token<T>): T;
148
+ createChildContainer(): Container;
149
+ }
150
+ ```
151
+
152
+ The generated container interface:
153
+
154
+ | Method | Description |
155
+ |--------|-------------|
156
+ | `resolve<T>(token)` | Resolve a service by token |
157
+ | `createChildContainer()` | Create a child container |
158
+
@@ -0,0 +1,267 @@
1
+ # Basic Usage
2
+
3
+ Learn the fundamental concepts and injection patterns in Neo-Syringe.
4
+
5
+ ## Container Configuration
6
+
7
+ All configuration is done through `defineBuilderConfig`:
8
+
9
+ ```typescript
10
+ import { defineBuilderConfig } from '@djodjonx/neo-syringe';
11
+
12
+ export const container = defineBuilderConfig({
13
+ name: 'MyContainer', // Optional: container name for debugging
14
+ injections: [ // Required: list of injections
15
+ // ... your injections
16
+ ],
17
+ extends: [], // Optional: inherit from partials
18
+ useContainer: undefined // Optional: parent container
19
+ });
20
+ ```
21
+
22
+ ## Injection Types
23
+
24
+ ### Class Token (Autowire)
25
+
26
+ The simplest form - register a class and let Neo-Syringe resolve its dependencies:
27
+
28
+ ```typescript
29
+ class UserRepository {
30
+ findAll() { return []; }
31
+ }
32
+
33
+ class UserService {
34
+ constructor(private repo: UserRepository) {}
35
+ }
36
+
37
+ export const container = defineBuilderConfig({
38
+ injections: [
39
+ { token: UserRepository },
40
+ { token: UserService } // Dependencies auto-resolved
41
+ ]
42
+ });
43
+ ```
44
+
45
+ ### Interface Token
46
+
47
+ Use `useInterface<T>()` to bind interfaces to implementations:
48
+
49
+ ```typescript
50
+ import { useInterface } from '@djodjonx/neo-syringe';
51
+
52
+ interface ILogger {
53
+ log(msg: string): void;
54
+ }
55
+
56
+ class ConsoleLogger implements ILogger {
57
+ log(msg: string) { console.log(msg); }
58
+ }
59
+
60
+ class FileLogger implements ILogger {
61
+ log(msg: string) { /* write to file */ }
62
+ }
63
+
64
+ export const container = defineBuilderConfig({
65
+ injections: [
66
+ { token: useInterface<ILogger>(), provider: ConsoleLogger }
67
+ ]
68
+ });
69
+
70
+ // Resolve by interface
71
+ const logger = container.resolve(useInterface<ILogger>());
72
+ ```
73
+
74
+ ::: tip Automatic ID Generation
75
+ `useInterface<ILogger>()` generates a unique string ID at compile-time. You don't need to manage Symbols manually!
76
+ :::
77
+
78
+ ### Explicit Provider
79
+
80
+ Override the default implementation:
81
+
82
+ ```typescript
83
+ class UserService {
84
+ // ...
85
+ }
86
+
87
+ class MockUserService extends UserService {
88
+ // Test implementation
89
+ }
90
+
91
+ export const container = defineBuilderConfig({
92
+ injections: [
93
+ { token: UserService, provider: MockUserService }
94
+ ]
95
+ });
96
+ ```
97
+
98
+ ### Factory Provider
99
+
100
+ Use factory functions for dynamic instantiation:
101
+
102
+ ```typescript
103
+ // Arrow functions are auto-detected as factories
104
+ {
105
+ token: useInterface<IConfig>(),
106
+ provider: (container) => ({
107
+ apiUrl: process.env.API_URL ?? 'http://localhost',
108
+ timeout: 5000
109
+ })
110
+ }
111
+
112
+ // Factory with dependencies
113
+ {
114
+ token: useInterface<IService>(),
115
+ provider: (container) => {
116
+ const logger = container.resolve(useInterface<ILogger>());
117
+ const config = container.resolve(useInterface<IConfig>());
118
+ return new MyService(logger, config);
119
+ }
120
+ }
121
+
122
+ // Explicit factory flag (for non-arrow functions)
123
+ {
124
+ token: useInterface<IDatabase>(),
125
+ provider: createDatabaseConnection,
126
+ useFactory: true
127
+ }
128
+ ```
129
+
130
+ ### Property Token
131
+
132
+ Inject primitive values (string, number, boolean) while keeping classes pure:
133
+
134
+ ```typescript
135
+ import { useProperty } from '@djodjonx/neo-syringe';
136
+
137
+ // Pure class - no DI imports!
138
+ class ApiService {
139
+ constructor(
140
+ private apiUrl: string,
141
+ private timeout: number,
142
+ private debug: boolean
143
+ ) {}
144
+ }
145
+
146
+ // Define property tokens
147
+ const apiUrl = useProperty<string>(ApiService, 'apiUrl');
148
+ const timeout = useProperty<number>(ApiService, 'timeout');
149
+ const debug = useProperty<boolean>(ApiService, 'debug');
150
+
151
+ export const container = defineBuilderConfig({
152
+ injections: [
153
+ { token: apiUrl, provider: () => process.env.API_URL ?? 'http://localhost' },
154
+ { token: timeout, provider: () => 5000 },
155
+ { token: debug, provider: () => process.env.NODE_ENV === 'development' },
156
+ { token: ApiService } // Primitives auto-wired!
157
+ ]
158
+ });
159
+ ```
160
+
161
+ ::: info Type Safety
162
+ `useProperty(ApiService, 'apiUrl')` creates a unique token scoped to that specific class parameter. This means `useProperty(ServiceA, 'url')` ≠ `useProperty(ServiceB, 'url')`.
163
+ :::
164
+
165
+ ## Resolving Services
166
+
167
+ ```typescript
168
+ import { container } from './container';
169
+ import { UserService } from './services/user.service';
170
+ import { useInterface } from '@djodjonx/neo-syringe';
171
+ import type { ILogger } from './services/logger';
172
+
173
+ // Resolve by class
174
+ const userService = container.resolve(UserService);
175
+
176
+ // Resolve by interface
177
+ const logger = container.resolve(useInterface<ILogger>());
178
+ ```
179
+
180
+ ## Partials (Modular Configuration)
181
+
182
+ Split configuration into reusable modules:
183
+
184
+ ```typescript
185
+ // logging.partial.ts
186
+ import { definePartialConfig, useInterface } from '@djodjonx/neo-syringe';
187
+
188
+ export const loggingConfig = definePartialConfig({
189
+ injections: [
190
+ { token: useInterface<ILogger>(), provider: ConsoleLogger }
191
+ ]
192
+ });
193
+
194
+ // database.partial.ts
195
+ export const databaseConfig = definePartialConfig({
196
+ injections: [
197
+ { token: useInterface<IDatabase>(), provider: PostgresDatabase }
198
+ ]
199
+ });
200
+
201
+ // container.ts
202
+ export const container = defineBuilderConfig({
203
+ extends: [loggingConfig, databaseConfig], // Inherit injections
204
+ injections: [
205
+ { token: UserService },
206
+ { token: OrderService }
207
+ ]
208
+ });
209
+ ```
210
+
211
+ ## Complete Example
212
+
213
+ ```typescript
214
+ // interfaces.ts
215
+ export interface ILogger {
216
+ log(msg: string): void;
217
+ }
218
+
219
+ export interface IUserRepository {
220
+ findById(id: string): User | null;
221
+ }
222
+
223
+ // implementations.ts
224
+ export class ConsoleLogger implements ILogger {
225
+ log(msg: string) { console.log(`[LOG] ${msg}`); }
226
+ }
227
+
228
+ export class InMemoryUserRepository implements IUserRepository {
229
+ private users = new Map<string, User>();
230
+
231
+ findById(id: string) {
232
+ return this.users.get(id) ?? null;
233
+ }
234
+ }
235
+
236
+ // services.ts
237
+ export class UserService {
238
+ constructor(
239
+ private logger: ILogger,
240
+ private repo: IUserRepository
241
+ ) {}
242
+
243
+ getUser(id: string) {
244
+ this.logger.log(`Fetching user ${id}`);
245
+ return this.repo.findById(id);
246
+ }
247
+ }
248
+
249
+ // container.ts
250
+ import { defineBuilderConfig, useInterface } from '@djodjonx/neo-syringe';
251
+
252
+ export const container = defineBuilderConfig({
253
+ name: 'AppContainer',
254
+ injections: [
255
+ { token: useInterface<ILogger>(), provider: ConsoleLogger },
256
+ { token: useInterface<IUserRepository>(), provider: InMemoryUserRepository },
257
+ { token: UserService }
258
+ ]
259
+ });
260
+
261
+ // main.ts
262
+ import { container } from './container';
263
+
264
+ const userService = container.resolve(UserService);
265
+ const user = userService.getUser('123');
266
+ ```
267
+