@djodjonx/neo-syringe 1.2.0 → 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.
- package/.github/workflows/docs.yml +59 -0
- package/CHANGELOG.md +14 -0
- package/README.md +72 -779
- package/dist/cli/index.cjs +15 -0
- package/dist/cli/index.mjs +15 -0
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/unplugin/index.cjs +31 -7
- package/dist/unplugin/index.d.cts +7 -5
- package/dist/unplugin/index.d.mts +7 -5
- package/dist/unplugin/index.mjs +31 -7
- package/docs/.vitepress/config.ts +109 -0
- package/docs/.vitepress/theme/custom.css +150 -0
- package/docs/.vitepress/theme/index.ts +17 -0
- package/docs/api/configuration.md +274 -0
- package/docs/api/functions.md +291 -0
- package/docs/api/types.md +158 -0
- package/docs/guide/basic-usage.md +267 -0
- package/docs/guide/cli.md +174 -0
- package/docs/guide/generated-code.md +284 -0
- package/docs/guide/getting-started.md +171 -0
- package/docs/guide/ide-plugin.md +203 -0
- package/docs/guide/injection-types.md +287 -0
- package/docs/guide/legacy-migration.md +333 -0
- package/docs/guide/lifecycle.md +223 -0
- package/docs/guide/parent-container.md +321 -0
- package/docs/guide/scoped-injections.md +271 -0
- package/docs/guide/what-is-neo-syringe.md +162 -0
- package/docs/guide/why-neo-syringe.md +219 -0
- package/docs/index.md +138 -0
- package/docs/public/logo.png +0 -0
- package/package.json +5 -3
- package/src/analyzer/types.ts +52 -52
- package/src/cli/index.ts +15 -0
- package/src/generator/Generator.ts +23 -1
- package/src/types.ts +1 -1
- package/src/unplugin/index.ts +13 -41
- package/tests/analyzer/AnalyzerDeclarative.test.ts +1 -1
- package/tests/e2e/container-integration.test.ts +19 -19
- package/tests/e2e/generated-code.test.ts +2 -2
- package/tsconfig.json +2 -1
- package/typedoc.json +0 -5
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
Configure Neo-Syringe in your project.
|
|
4
|
+
|
|
5
|
+
## Build Plugin
|
|
6
|
+
|
|
7
|
+
### Vite
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
// vite.config.ts
|
|
11
|
+
import { defineConfig } from 'vite';
|
|
12
|
+
import { neoSyringePlugin } from '@djodjonx/neo-syringe/plugin';
|
|
13
|
+
|
|
14
|
+
export default defineConfig({
|
|
15
|
+
plugins: [neoSyringePlugin.vite()]
|
|
16
|
+
});
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Rollup
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// rollup.config.js
|
|
23
|
+
import { neoSyringePlugin } from '@djodjonx/neo-syringe/plugin';
|
|
24
|
+
|
|
25
|
+
export default {
|
|
26
|
+
input: 'src/main.ts',
|
|
27
|
+
output: {
|
|
28
|
+
file: 'dist/bundle.js',
|
|
29
|
+
format: 'esm'
|
|
30
|
+
},
|
|
31
|
+
plugins: [neoSyringePlugin.rollup()]
|
|
32
|
+
};
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Webpack
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
// webpack.config.js
|
|
39
|
+
const { webpack } = require('@djodjonx/neo-syringe/plugin');
|
|
40
|
+
|
|
41
|
+
module.exports = {
|
|
42
|
+
plugins: [webpack()]
|
|
43
|
+
};
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### esbuild
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
// esbuild.config.js
|
|
50
|
+
import { neoSyringePlugin } from '@djodjonx/neo-syringe/plugin';
|
|
51
|
+
import esbuild from 'esbuild';
|
|
52
|
+
|
|
53
|
+
await esbuild.build({
|
|
54
|
+
entryPoints: ['src/main.ts'],
|
|
55
|
+
bundle: true,
|
|
56
|
+
outfile: 'dist/bundle.js',
|
|
57
|
+
plugins: [neoSyringePlugin.esbuild()]
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Rspack
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
// rspack.config.js
|
|
65
|
+
const { rspack } = require('@djodjonx/neo-syringe/plugin');
|
|
66
|
+
|
|
67
|
+
module.exports = {
|
|
68
|
+
plugins: [rspack()]
|
|
69
|
+
};
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## TypeScript LSP Plugin
|
|
73
|
+
|
|
74
|
+
Add to `tsconfig.json` for IDE error detection:
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"compilerOptions": {
|
|
79
|
+
"plugins": [
|
|
80
|
+
{ "name": "@djodjonx/neo-syringe/lsp" }
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
::: tip VS Code
|
|
87
|
+
Remember to select "Use Workspace Version" for TypeScript.
|
|
88
|
+
:::
|
|
89
|
+
|
|
90
|
+
## BuilderConfig Options
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
defineBuilderConfig({
|
|
94
|
+
// Container name (for debugging)
|
|
95
|
+
name: 'AppContainer',
|
|
96
|
+
|
|
97
|
+
// List of injections
|
|
98
|
+
injections: [
|
|
99
|
+
{ token: UserService },
|
|
100
|
+
{ token: useInterface<ILogger>(), provider: ConsoleLogger }
|
|
101
|
+
],
|
|
102
|
+
|
|
103
|
+
// Inherit from partial configs
|
|
104
|
+
extends: [loggingPartial, databasePartial],
|
|
105
|
+
|
|
106
|
+
// Parent container (Neo-Syringe or legacy)
|
|
107
|
+
useContainer: parentContainer
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### name
|
|
112
|
+
|
|
113
|
+
Type: `string`
|
|
114
|
+
|
|
115
|
+
Optional. The container name appears in error messages.
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
defineBuilderConfig({
|
|
119
|
+
name: 'UserModule'
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Error: [UserModule] Service not found: XYZ
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### injections
|
|
126
|
+
|
|
127
|
+
Type: `Injection[]`
|
|
128
|
+
|
|
129
|
+
Required. List of services to register.
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
defineBuilderConfig({
|
|
133
|
+
injections: [
|
|
134
|
+
// Class autowiring
|
|
135
|
+
{ token: UserService },
|
|
136
|
+
|
|
137
|
+
// Interface binding
|
|
138
|
+
{ token: useInterface<ILogger>(), provider: ConsoleLogger },
|
|
139
|
+
|
|
140
|
+
// Explicit provider
|
|
141
|
+
{ token: BaseService, provider: ConcreteService },
|
|
142
|
+
|
|
143
|
+
// Factory
|
|
144
|
+
{ token: useInterface<IConfig>(), provider: () => loadConfig() },
|
|
145
|
+
|
|
146
|
+
// Property token
|
|
147
|
+
{ token: useProperty<string>(ApiService, 'apiUrl'), provider: () => 'http://...' },
|
|
148
|
+
|
|
149
|
+
// With lifecycle
|
|
150
|
+
{ token: RequestContext, lifecycle: 'transient' },
|
|
151
|
+
|
|
152
|
+
// Scoped override
|
|
153
|
+
{ token: useInterface<ILogger>(), provider: MockLogger, scoped: true }
|
|
154
|
+
]
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### extends
|
|
159
|
+
|
|
160
|
+
Type: `PartialConfig[]`
|
|
161
|
+
|
|
162
|
+
Optional. Inherit injections from partial configs.
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const loggingPartial = definePartialConfig({
|
|
166
|
+
injections: [
|
|
167
|
+
{ token: useInterface<ILogger>(), provider: ConsoleLogger }
|
|
168
|
+
]
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
defineBuilderConfig({
|
|
172
|
+
extends: [loggingPartial],
|
|
173
|
+
injections: [
|
|
174
|
+
{ token: UserService } // Can use ILogger
|
|
175
|
+
]
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### useContainer
|
|
180
|
+
|
|
181
|
+
Type: `Container | any`
|
|
182
|
+
|
|
183
|
+
Optional. Parent container for delegation.
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
// Neo-Syringe parent
|
|
187
|
+
defineBuilderConfig({
|
|
188
|
+
useContainer: sharedKernel,
|
|
189
|
+
injections: [...]
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// Legacy container (tsyringe, etc.)
|
|
193
|
+
const legacy = declareContainerTokens<{...}>(tsyringeContainer);
|
|
194
|
+
defineBuilderConfig({
|
|
195
|
+
useContainer: legacy,
|
|
196
|
+
injections: [...]
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Injection Options
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
interface Injection<T> {
|
|
204
|
+
token: Token<T>;
|
|
205
|
+
provider?: Provider<T>;
|
|
206
|
+
useFactory?: boolean;
|
|
207
|
+
lifecycle?: 'singleton' | 'transient';
|
|
208
|
+
scoped?: boolean;
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### token
|
|
213
|
+
|
|
214
|
+
Type: `Token<T>` (required)
|
|
215
|
+
|
|
216
|
+
What to register. Can be:
|
|
217
|
+
|
|
218
|
+
- Class constructor: `UserService`
|
|
219
|
+
- Interface token: `useInterface<ILogger>()`
|
|
220
|
+
- Property token: `useProperty<string>(ApiService, 'apiUrl')`
|
|
221
|
+
|
|
222
|
+
### provider
|
|
223
|
+
|
|
224
|
+
Type: `Provider<T>`
|
|
225
|
+
|
|
226
|
+
What provides the instance. Can be:
|
|
227
|
+
|
|
228
|
+
- Class constructor: `ConsoleLogger`
|
|
229
|
+
- Factory function: `(container) => new Service()`
|
|
230
|
+
|
|
231
|
+
If omitted, the token itself is used (autowiring).
|
|
232
|
+
|
|
233
|
+
### useFactory
|
|
234
|
+
|
|
235
|
+
Type: `boolean`
|
|
236
|
+
|
|
237
|
+
Force treating the provider as a factory function.
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
// Auto-detected (arrow function)
|
|
241
|
+
{ provider: () => createService() }
|
|
242
|
+
|
|
243
|
+
// Explicit (regular function)
|
|
244
|
+
{ provider: createService, useFactory: true }
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### lifecycle
|
|
248
|
+
|
|
249
|
+
Type: `'singleton' | 'transient'`
|
|
250
|
+
|
|
251
|
+
Default: `'singleton'`
|
|
252
|
+
|
|
253
|
+
How instances are managed.
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
{ token: UserService, lifecycle: 'singleton' } // One instance
|
|
257
|
+
{ token: RequestContext, lifecycle: 'transient' } // New each time
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### scoped
|
|
261
|
+
|
|
262
|
+
Type: `boolean`
|
|
263
|
+
|
|
264
|
+
Default: `false`
|
|
265
|
+
|
|
266
|
+
If `true`, resolve locally instead of delegating to parent.
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
// Override parent's ILogger with local MockLogger
|
|
270
|
+
{ token: useInterface<ILogger>(), provider: MockLogger, scoped: true }
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
See [Scoped Injections](/guide/scoped-injections) for details.
|
|
274
|
+
|
|
@@ -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
|
+
|