exisjs 0.7.12 → 0.7.14
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 +195 -39
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +3 -1
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/config/types.d.ts +2 -2
- package/dist/config/types.d.ts.map +1 -1
- package/dist/decorators/params.d.ts +21 -0
- package/dist/decorators/params.d.ts.map +1 -1
- package/dist/decorators/params.js +21 -1
- package/dist/decorators/params.js.map +1 -1
- package/dist/di/container.d.ts +15 -6
- package/dist/di/container.d.ts.map +1 -1
- package/dist/di/container.js +26 -3
- package/dist/di/container.js.map +1 -1
- package/dist/di/index.d.ts +1 -1
- package/dist/di/index.d.ts.map +1 -1
- package/dist/di/index.js.map +1 -1
- package/dist/di/inject.d.ts +2 -1
- package/dist/di/inject.d.ts.map +1 -1
- package/dist/di/inject.js +2 -1
- package/dist/di/inject.js.map +1 -1
- package/dist/docs/ARCHITECTURE.md +130 -78
- package/dist/docs/BENCHMARKS.md +4 -4
- package/dist/docs/content/README.md +43 -44
- package/dist/docs/content/boundaries.mdx +138 -61
- package/dist/docs/content/cli/commands.mdx +151 -128
- package/dist/docs/content/cli/overview.mdx +61 -47
- package/dist/docs/content/cli/usage.mdx +107 -30
- package/dist/docs/content/config.mdx +145 -158
- package/dist/docs/content/controllers.mdx +193 -464
- package/dist/docs/content/cron.mdx +183 -69
- package/dist/docs/content/decorators.mdx +449 -154
- package/dist/docs/content/errors.mdx +202 -305
- package/dist/docs/content/exisjs-mcp.mdx +59 -49
- package/dist/docs/content/installation.mdx +243 -157
- package/dist/docs/content/introduction.mdx +220 -48
- package/dist/docs/content/middleware.mdx +171 -497
- package/dist/docs/content/modules.mdx +141 -83
- package/dist/docs/content/providers.mdx +216 -180
- package/dist/docs/content/requests.mdx +168 -488
- package/dist/docs/content/responses.mdx +200 -533
- package/dist/docs/content/routing.mdx +235 -598
- package/dist/docs/content/security.mdx +233 -57
- package/dist/docs/content/structure.mdx +151 -240
- package/dist/docs/content/swagger.mdx +192 -91
- package/dist/docs/content/testing.mdx +205 -74
- package/dist/docs/content/validation.mdx +479 -341
- package/dist/docs/reference/README.md +34 -2
- package/dist/docs/reference/config.mdx +277 -75
- package/dist/docs/reference/context.mdx +197 -106
- package/dist/docs/reference/cron.mdx +266 -152
- package/dist/docs/reference/database.mdx +135 -53
- package/dist/docs/reference/decorators.mdx +234 -116
- package/dist/docs/reference/di.mdx +146 -112
- package/dist/docs/reference/error.mdx +155 -178
- package/dist/docs/reference/exis.mdx +141 -70
- package/dist/docs/reference/logger.mdx +110 -126
- package/dist/docs/reference/middleware.mdx +235 -158
- package/dist/docs/reference/plugin.mdx +136 -64
- package/dist/docs/reference/router.mdx +275 -293
- package/dist/docs/reference/sanitize.mdx +91 -87
- package/dist/docs/reference/swagger.mdx +280 -100
- package/dist/docs/reference/testing.mdx +223 -89
- package/dist/docs/reference/validator.mdx +194 -206
- package/dist/lib/start-server.js +22 -8
- package/dist/lib/start-server.js.map +1 -1
- package/dist/module/module.d.ts +6 -3
- package/dist/module/module.d.ts.map +1 -1
- package/dist/module/module.js +17 -3
- package/dist/module/module.js.map +1 -1
- package/dist/router/controller-registrar.d.ts.map +1 -1
- package/dist/router/controller-registrar.js +26 -4
- package/dist/router/controller-registrar.js.map +1 -1
- package/dist/router/scanner/fs-scanner.d.ts.map +1 -1
- package/dist/router/scanner/fs-scanner.js +22 -0
- package/dist/router/scanner/fs-scanner.js.map +1 -1
- package/dist/router/types.d.ts +6 -4
- package/dist/router/types.d.ts.map +1 -1
- package/dist/server/app.d.ts +3 -1
- package/dist/server/app.d.ts.map +1 -1
- package/dist/server/app.js +24 -8
- package/dist/server/app.js.map +1 -1
- package/dist/server/bootstrapper.d.ts.map +1 -1
- package/dist/server/bootstrapper.js +19 -0
- package/dist/server/bootstrapper.js.map +1 -1
- package/dist/server/request.d.ts +2 -0
- package/dist/server/request.d.ts.map +1 -1
- package/dist/server/request.js +11 -0
- package/dist/server/request.js.map +1 -1
- package/dist/server/response.d.ts +10 -5
- package/dist/server/response.d.ts.map +1 -1
- package/dist/server/response.js +65 -18
- package/dist/server/response.js.map +1 -1
- package/dist/swagger/generator.d.ts.map +1 -1
- package/dist/swagger/generator.js +130 -10
- package/dist/swagger/generator.js.map +1 -1
- package/dist/telemetry/index.d.ts +12 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +121 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/testing/client.d.ts +1 -0
- package/dist/testing/client.d.ts.map +1 -1
- package/dist/testing/client.js +4 -1
- package/dist/testing/client.js.map +1 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +11 -4
- package/dist/testing/index.js.map +1 -1
- package/dist/validator/builder.d.ts +26 -1
- package/dist/validator/builder.d.ts.map +1 -1
- package/dist/validator/builder.js +31 -0
- package/dist/validator/builder.js.map +1 -1
- package/dist/validator/engine.d.ts +23 -0
- package/dist/validator/engine.d.ts.map +1 -1
- package/dist/validator/engine.js +228 -31
- package/dist/validator/engine.js.map +1 -1
- package/dist/validator/index.d.ts +8 -4
- package/dist/validator/index.d.ts.map +1 -1
- package/dist/validator/index.js +4 -1
- package/dist/validator/index.js.map +1 -1
- package/dist/validator/tex-types.d.ts +19 -4
- package/dist/validator/tex-types.d.ts.map +1 -1
- package/dist/validator/tex-types.js +102 -0
- package/dist/validator/tex-types.js.map +1 -1
- package/dist/validator/tex.d.ts +1 -1
- package/dist/validator/tex.d.ts.map +1 -1
- package/dist/validator/tex.js +3 -1
- package/dist/validator/tex.js.map +1 -1
- package/dist/validator/types.d.ts +1 -0
- package/dist/validator/types.d.ts.map +1 -1
- package/package.json +46 -14
- package/dist/docs/content/dataloader.mdx +0 -170
- package/dist/docs/reference/dataloader.mdx +0 -91
|
@@ -1,180 +1,214 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
3
|
-
description: "API Reference for ExisJS
|
|
2
|
+
title: "exisjs/di"
|
|
3
|
+
description: "API Reference for ExisJS Inversion of Control (IoC) Container, inject() helper, provider definitions, scopes, and forwardRef."
|
|
4
|
+
nextUrl: "/docs/reference/error"
|
|
5
|
+
nextTitle: "Error Reference"
|
|
4
6
|
---
|
|
5
7
|
|
|
6
|
-
#
|
|
8
|
+
# `exisjs/di`
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
It fully supports standard Class-Based constructor injection (similar to NestJS or Angular) but also introduces a highly optimized `inject()` function that allows perfectly typed, deeply nested dependency injection inside purely functional architectures.
|
|
10
|
+
The `exisjs/di` module provides the Inversion of Control (IoC) dependency injection container for ExisJS. It supports functional context-driven injection (`inject()`), class constructor and property decorators (`@Inject()`, `@Optional()`), circular dependency resolution (`forwardRef()`), and multiple lifecycle scopes.
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## Module Exports
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
```typescript
|
|
17
|
+
import {
|
|
18
|
+
Container,
|
|
19
|
+
inject,
|
|
20
|
+
forwardRef,
|
|
21
|
+
isForwardRef,
|
|
22
|
+
Inject,
|
|
23
|
+
Optional,
|
|
24
|
+
INJECT_METADATA,
|
|
25
|
+
PROPERTY_INJECT_METADATA,
|
|
26
|
+
OPTIONAL_METADATA,
|
|
27
|
+
SCOPE_METADATA,
|
|
28
|
+
} from 'exisjs/di'
|
|
29
|
+
|
|
30
|
+
import type {
|
|
31
|
+
ProviderToken,
|
|
32
|
+
ProviderDefinition,
|
|
33
|
+
CustomProvider,
|
|
34
|
+
ValueProvider,
|
|
35
|
+
FactoryProvider,
|
|
36
|
+
ClassProvider,
|
|
37
|
+
ExistingProvider,
|
|
38
|
+
ClassConstructor,
|
|
39
|
+
ForwardReference,
|
|
40
|
+
} from 'exisjs/di'
|
|
41
|
+
```
|
|
17
42
|
|
|
18
|
-
|
|
43
|
+
---
|
|
19
44
|
|
|
20
|
-
|
|
45
|
+
## 1. Provider Definitions & Types
|
|
21
46
|
|
|
22
|
-
|
|
23
|
-
Provide static, pre-instantiated values or configuration objects.
|
|
24
|
-
```typescript
|
|
25
|
-
app.provide('API_KEY', { useValue: 'sk_live_123' })
|
|
26
|
-
```
|
|
47
|
+
Dependencies are registered with the container using tokens (classes, string identifiers, symbols, or forward references):
|
|
27
48
|
|
|
28
|
-
**2. Class Providers**
|
|
29
|
-
Provide a class constructor. ExisJS will automatically instantiate it the first time it is resolved.
|
|
30
49
|
```typescript
|
|
31
|
-
|
|
50
|
+
export type ProviderToken<T = any> =
|
|
51
|
+
| string
|
|
52
|
+
| symbol
|
|
53
|
+
| (new (...args: any[]) => T)
|
|
54
|
+
| ForwardReference<T>
|
|
32
55
|
```
|
|
33
56
|
|
|
34
|
-
|
|
35
|
-
Provide a synchronous or asynchronous function to generate the value dynamically.
|
|
36
|
-
```typescript
|
|
37
|
-
app.provide('Database', {
|
|
38
|
-
useFactory: async () => {
|
|
39
|
-
const db = new DatabaseConnection()
|
|
40
|
-
await db.connect()
|
|
41
|
-
return db
|
|
42
|
-
}
|
|
43
|
-
})
|
|
44
|
-
```
|
|
57
|
+
### Provider Variants
|
|
45
58
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
app.provide(
|
|
50
|
-
|
|
59
|
+
| Provider Type | Interface | Description | Example |
|
|
60
|
+
| :--- | :--- | :--- | :--- |
|
|
61
|
+
| **Value Provider** | `ValueProvider<T>` | Binds a static value, client instance, or configuration object. | `app.provide('CONFIG', { useValue: { env: 'prod' } })` |
|
|
62
|
+
| **Class Provider** | `ClassProvider<T>` | Binds a class constructor instantiated on first resolution. | `app.provide('UserService', { useClass: UserService })` |
|
|
63
|
+
| **Factory Provider** | `FactoryProvider<T>` | Executes a factory function with resolved dependency tokens. | `app.provide({ provide: 'DB', useFactory: (cfg) => connect(cfg), inject: ['CONFIG'] })` |
|
|
64
|
+
| **Existing / Alias Provider** | `ExistingProvider<T>` | Creates an alias pointing to another registered provider token. | `app.provide({ provide: 'DB_ALIAS', useExisting: 'DB' })` |
|
|
65
|
+
| **Direct Class** | `ClassConstructor<T>` | Direct constructor binding without an options wrapper. | `app.provide(AuthService, AuthService)` |
|
|
51
66
|
|
|
52
67
|
---
|
|
53
68
|
|
|
54
|
-
##
|
|
55
|
-
|
|
56
|
-
By default, all providers in ExisJS are **Singletons**. They are instantiated once and cached for the lifetime of the application.
|
|
69
|
+
## 2. Provider Scopes
|
|
57
70
|
|
|
58
|
-
ExisJS supports three provider scopes
|
|
71
|
+
ExisJS supports three provider lifecycle scopes:
|
|
59
72
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
73
|
+
| Scope | Lifetime | Description |
|
|
74
|
+
| :--- | :--- | :--- |
|
|
75
|
+
| `'singleton'` *(Default)* | Application Lifetime | Instantiated once and cached in memory across all requests. |
|
|
76
|
+
| `'request'` | Request Lifetime | Instantiated once per incoming HTTP request; isolated in request-scoped cache. |
|
|
77
|
+
| `'transient'` | Resolution Lifetime | Re-instantiated every single time the dependency is requested. |
|
|
63
78
|
|
|
64
79
|
```typescript
|
|
65
|
-
app.provide('TraceLogger', {
|
|
66
|
-
useClass: RequestScopedLogger,
|
|
67
|
-
scope: 'request'
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
app.provide('OperationContext', {
|
|
71
|
-
useClass: OperationContext,
|
|
72
|
-
scope: 'transient'
|
|
80
|
+
app.provide('TraceLogger', {
|
|
81
|
+
useClass: RequestScopedLogger,
|
|
82
|
+
scope: 'request',
|
|
73
83
|
})
|
|
74
84
|
```
|
|
75
85
|
|
|
76
|
-
> [!WARNING]
|
|
77
|
-
> Request-scoped providers can severely impact application performance because they force the engine to allocate new memory and construct new classes on every single HTTP request. Only use `request` scope when strictly necessary.
|
|
78
|
-
|
|
79
86
|
---
|
|
80
87
|
|
|
81
|
-
##
|
|
88
|
+
## 3. Functional Injection (`inject()`)
|
|
82
89
|
|
|
83
|
-
|
|
90
|
+
Resolves dependencies from within active route handlers, middleware functions, or helper routines using `AsyncLocalStorage`.
|
|
84
91
|
|
|
85
|
-
|
|
92
|
+
```typescript
|
|
93
|
+
function inject<T>(token: ProviderToken<T>): T
|
|
94
|
+
```
|
|
86
95
|
|
|
87
|
-
|
|
96
|
+
### Example
|
|
88
97
|
|
|
89
98
|
```typescript filename="src/http/users/route.ts"
|
|
90
|
-
import {
|
|
99
|
+
import { controller, route } from 'exisjs/router'
|
|
91
100
|
import { inject } from 'exisjs/di'
|
|
92
|
-
import {
|
|
101
|
+
import { DatabaseService } from '../services/database'
|
|
93
102
|
|
|
94
103
|
export default controller({
|
|
95
|
-
|
|
104
|
+
list: route.get('/', {
|
|
96
105
|
async handle() {
|
|
97
|
-
//
|
|
98
|
-
|
|
99
|
-
const db = inject(Database)
|
|
100
|
-
|
|
106
|
+
// Resolved from active request execution context
|
|
107
|
+
const db = inject(DatabaseService)
|
|
101
108
|
const apiKey = inject<string>('API_KEY')
|
|
102
|
-
|
|
109
|
+
|
|
103
110
|
return db.query('SELECT * FROM users')
|
|
104
|
-
}
|
|
105
|
-
})
|
|
111
|
+
},
|
|
112
|
+
}),
|
|
106
113
|
})
|
|
107
114
|
```
|
|
108
115
|
|
|
109
|
-
|
|
110
|
-
> `inject()` relies on the active execution context. If you call `inject()` outside of an active HTTP request or application lifecycle hook (e.g., in a background `setInterval` without context), it will throw an error.
|
|
116
|
+
---
|
|
111
117
|
|
|
112
|
-
|
|
118
|
+
## 4. Class-Based OOP Injection
|
|
113
119
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
- **Property-Level `@Inject()`**: Inject dependencies directly onto class properties (`@Inject(Token) public service!: Service`) with automatic `design:type` reflection fallback.
|
|
117
|
-
- **Token Injection (`@Inject(token)`)**: Use `@Inject('TOKEN')` when injecting custom strings, config objects, or symbols.
|
|
118
|
-
- **Optional Dependencies (`@Optional()`)**: Mark dependencies that can safely resolve to `undefined` if not registered.
|
|
119
|
-
- **Forward References (`forwardRef(() => Service)`)**: Resolve circular dependencies between services using lazy forward references and ES6 Proxy delegates.
|
|
120
|
+
### `@Inject(token)`
|
|
121
|
+
Parameter and property decorator specifying an explicit injection token:
|
|
120
122
|
|
|
121
|
-
```typescript
|
|
122
|
-
import { Controller, Get
|
|
123
|
-
import { Inject
|
|
123
|
+
```typescript
|
|
124
|
+
import { Controller, Get } from 'exisjs/decorators'
|
|
125
|
+
import { Inject } from 'exisjs/di'
|
|
124
126
|
import { UserService } from './service'
|
|
125
|
-
import { ConfigService } from '../config/service'
|
|
126
127
|
|
|
127
128
|
@Controller('/users')
|
|
128
129
|
export default class UserController {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
private config!: ConfigService
|
|
132
|
-
|
|
133
|
-
// 2. Optional property injection
|
|
134
|
-
@Inject('ANALYTICS')
|
|
135
|
-
@Optional()
|
|
136
|
-
private analytics?: any
|
|
130
|
+
@Inject('CONFIG')
|
|
131
|
+
private config!: Record<string, any>
|
|
137
132
|
|
|
138
133
|
constructor(
|
|
139
|
-
// 3. Automatically resolved from INJECTABLE_REGISTRY via type reflection!
|
|
140
134
|
private userService: UserService,
|
|
141
|
-
|
|
142
|
-
@Inject('DATABASE_URL') private dbUrl: string,
|
|
143
|
-
// 5. Circular dependency resolution via forwardRef
|
|
144
|
-
@Inject(forwardRef(() => UserService)) private circularRef: UserService
|
|
135
|
+
@Inject('DATABASE_URL') private dbUrl: string
|
|
145
136
|
) {}
|
|
146
|
-
|
|
147
|
-
@Get('/:id')
|
|
148
|
-
async getUser(@Param('id') id: string) {
|
|
149
|
-
return this.userService.findById(id)
|
|
150
|
-
}
|
|
151
137
|
}
|
|
152
138
|
```
|
|
153
139
|
|
|
140
|
+
### `@Optional()`
|
|
141
|
+
Marks a dependency as optional, resolving to `undefined` without throwing if not present in the container:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import { Inject, Optional } from 'exisjs/di'
|
|
145
|
+
|
|
146
|
+
export class NotificationService {
|
|
147
|
+
constructor(
|
|
148
|
+
@Inject('SLACK_WEBHOOK') @Optional() private slackUrl?: string
|
|
149
|
+
) {}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
154
152
|
|
|
155
153
|
---
|
|
156
154
|
|
|
157
|
-
##
|
|
155
|
+
## 5. Circular Dependency Resolution (`forwardRef`)
|
|
158
156
|
|
|
159
|
-
|
|
157
|
+
Resolves mutually dependent services by deferring token resolution until instantiation time:
|
|
160
158
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
159
|
+
```typescript
|
|
160
|
+
function forwardRef<T>(fn: () => ProviderToken<T>): ForwardReference<T>
|
|
161
|
+
```
|
|
164
162
|
|
|
165
|
-
|
|
166
|
-
|
|
163
|
+
### Example
|
|
164
|
+
|
|
165
|
+
```typescript filename="src/services/orders.ts"
|
|
166
|
+
import { Injectable } from 'exisjs/decorators'
|
|
167
|
+
import { Inject, forwardRef } from 'exisjs/di'
|
|
168
|
+
import { PaymentService } from './payments'
|
|
167
169
|
|
|
168
170
|
@Injectable()
|
|
169
|
-
export class
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
async onDestroy(): Promise<void> {
|
|
175
|
-
await this.pool.end()
|
|
176
|
-
}
|
|
171
|
+
export class OrderService {
|
|
172
|
+
constructor(
|
|
173
|
+
@Inject(forwardRef(() => PaymentService))
|
|
174
|
+
private paymentService: PaymentService
|
|
175
|
+
) {}
|
|
177
176
|
}
|
|
178
177
|
```
|
|
179
178
|
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 6. `Container` Class API
|
|
182
|
+
|
|
183
|
+
The core IoC container coordinating provider registration and resolution.
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
export class Container {
|
|
187
|
+
provide<T>(token: ProviderToken<T>, provider: ProviderDefinition<T>): void
|
|
188
|
+
resolve<T>(token: ProviderToken<T>, requestCache?: Map<any, any>): T
|
|
189
|
+
instantiateClass<T>(TargetClass: ClassConstructor<T>, requestCache?: Map<any, any>): T
|
|
190
|
+
clearCache(): void
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
| Method | Signature | Description |
|
|
195
|
+
| :--- | :--- | :--- |
|
|
196
|
+
| `provide(token, provider)` | `(token, provider) => void` | Registers a provider definition under a token. |
|
|
197
|
+
| `resolve(token, cache?)` | `(token, cache?) => T` | Resolves an instance matching the token. |
|
|
198
|
+
| `instantiateClass(Target, cache?)` | `(Target, cache?) => T` | Instantiates a class, resolving constructor parameters recursively. |
|
|
199
|
+
| `clearCache()` | `() => void` | Clears all cached singleton instances and in-flight locks. |
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## 7. Lifecycle Hooks
|
|
204
|
+
|
|
205
|
+
Providers registered in the container can implement standard lifecycle interfaces:
|
|
206
|
+
|
|
207
|
+
| Hook Interface | Method | Triggered When |
|
|
208
|
+
| :--- | :--- | :--- |
|
|
209
|
+
| `OnInit` | `onInit(): Promise<void> \| void` | Application server starts and container boots. |
|
|
210
|
+
| `OnDestroy` | `onDestroy(): Promise<void> \| void` | Server receives termination signal (`SIGTERM`, `SIGINT`) or `app.close()`. |
|
|
211
|
+
| `OnApplicationBootstrap` | `onApplicationBootstrap(): Promise<void> \| void` | All modules have initialized before listening for connections. |
|
|
212
|
+
|
|
213
|
+
|
|
180
214
|
|