@venizia/ignis-docs 0.0.8 → 0.2.0
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 +7 -7
- package/content/best-practices/api-usage-examples.md +15 -12
- package/content/best-practices/architectural-patterns.md +70 -78
- package/content/best-practices/architecture-decisions.md +91 -60
- package/content/best-practices/code-style-standards/advanced-patterns.md +56 -44
- package/content/best-practices/code-style-standards/constants-configuration.md +11 -11
- package/content/best-practices/code-style-standards/control-flow.md +5 -2
- package/content/best-practices/code-style-standards/documentation.md +13 -13
- package/content/best-practices/code-style-standards/function-patterns.md +9 -10
- package/content/best-practices/code-style-standards/index.md +1 -1
- package/content/best-practices/code-style-standards/naming-conventions.md +10 -8
- package/content/best-practices/code-style-standards/route-definitions.md +30 -12
- package/content/best-practices/code-style-standards/tooling.md +8 -5
- package/content/best-practices/code-style-standards/type-safety.md +13 -12
- package/content/best-practices/common-pitfalls.md +56 -37
- package/content/best-practices/contribution-workflow.md +13 -14
- package/content/best-practices/data-modeling.md +46 -22
- package/content/best-practices/deployment-strategies.md +28 -27
- package/content/best-practices/error-handling.md +48 -24
- package/content/best-practices/index.md +5 -5
- package/content/best-practices/performance-optimization.md +40 -31
- package/content/best-practices/security-guidelines.md +52 -23
- package/content/best-practices/testing-strategies.md +65 -51
- package/content/best-practices/troubleshooting-tips.md +24 -24
- package/content/extensions/components/{swagger.md → api-reference.md} +40 -31
- package/content/extensions/components/authentication/api.md +19 -19
- package/content/extensions/components/authentication/errors.md +7 -7
- package/content/extensions/components/authentication/index.md +10 -8
- package/content/extensions/components/authentication/usage.md +101 -6
- package/content/extensions/components/authorization/api.md +45 -25
- package/content/extensions/components/authorization/errors.md +6 -6
- package/content/extensions/components/authorization/index.md +11 -10
- package/content/extensions/components/authorization/usage.md +21 -21
- package/content/extensions/components/health-check.md +1 -1
- package/content/extensions/components/index.md +5 -5
- package/content/extensions/components/mail/errors.md +15 -15
- package/content/extensions/components/mail/index.md +1 -2
- package/content/extensions/components/mail/usage.md +1 -1
- package/content/extensions/components/request-tracker.md +1 -1
- package/content/extensions/components/socket-io/api.md +9 -9
- package/content/extensions/components/socket-io/errors.md +5 -5
- package/content/extensions/components/socket-io/index.md +8 -8
- package/content/extensions/components/socket-io/usage.md +1 -1
- package/content/extensions/components/static-asset/api.md +17 -4
- package/content/extensions/components/static-asset/errors.md +4 -4
- package/content/extensions/components/static-asset/index.md +26 -28
- package/content/extensions/components/static-asset/usage.md +13 -12
- package/content/extensions/components/template/index.md +2 -2
- package/content/extensions/components/template/setup-page.md +1 -1
- package/content/extensions/components/websocket/api.md +3 -3
- package/content/extensions/components/websocket/errors.md +5 -5
- package/content/extensions/components/websocket/index.md +5 -5
- package/content/extensions/components/websocket/usage.md +3 -3
- package/content/extensions/helpers/cron/index.md +2 -2
- package/content/extensions/helpers/crypto/index.md +1 -1
- package/content/extensions/helpers/env/index.md +27 -12
- package/content/extensions/helpers/error/index.md +81 -25
- package/content/extensions/helpers/index.md +2 -3
- package/content/extensions/helpers/inversion/index.md +15 -7
- package/content/extensions/helpers/kafka/compile-binary.md +92 -0
- package/content/extensions/helpers/kafka/examples.md +1 -1
- package/content/extensions/helpers/kafka/index.md +3 -0
- package/content/extensions/helpers/logger/index.md +32 -2
- package/content/extensions/helpers/network/index.md +6 -0
- package/content/extensions/helpers/queue/index.md +14 -17
- package/content/extensions/helpers/redis/index.md +548 -323
- package/content/extensions/helpers/socket-io/index.md +14 -10
- package/content/extensions/helpers/storage/api.md +44 -8
- package/content/extensions/helpers/storage/index.md +43 -7
- package/content/extensions/helpers/template/index.md +6 -3
- package/content/extensions/helpers/types/index.md +11 -8
- package/content/extensions/helpers/websocket/api.md +9 -9
- package/content/extensions/helpers/websocket/index.md +7 -7
- package/content/extensions/helpers/worker-thread/index.md +2 -2
- package/content/extensions/index.md +3 -4
- package/content/extensions/src-details/mcp-server.md +18 -24
- package/content/guides/core-concepts/application/bootstrapping.md +11 -14
- package/content/guides/core-concepts/application/index.md +3 -3
- package/content/guides/core-concepts/components.md +19 -10
- package/content/guides/core-concepts/dependency-injection.md +6 -3
- package/content/guides/core-concepts/grpc-controllers.md +6 -5
- package/content/guides/core-concepts/persistent/datasources.md +42 -43
- package/content/guides/core-concepts/persistent/index.md +16 -7
- package/content/guides/core-concepts/persistent/models.md +24 -20
- package/content/guides/core-concepts/persistent/postgres-drivers.md +201 -0
- package/content/guides/core-concepts/persistent/repositories.md +40 -23
- package/content/guides/core-concepts/persistent/search-meilisearch.md +185 -0
- package/content/guides/core-concepts/persistent/search-typesense.md +431 -0
- package/content/guides/core-concepts/persistent/transactions.md +61 -25
- package/content/guides/core-concepts/rest-controllers.md +12 -9
- package/content/guides/core-concepts/services.md +330 -60
- package/content/guides/get-started/5-minute-quickstart.md +15 -15
- package/content/guides/get-started/philosophy.md +36 -36
- package/content/guides/get-started/setup.md +3 -3
- package/content/guides/index.md +3 -3
- package/content/guides/migrations/redis-helpers-migration.md +177 -0
- package/content/guides/migrations/scoped-rbac-migration.md +17 -17
- package/content/guides/migrations/unified-connectors-migration.md +113 -0
- package/content/guides/reference/glossary.md +19 -12
- package/content/guides/reference/mcp-docs-server.md +22 -18
- package/content/guides/tutorials/building-a-crud-api.md +37 -44
- package/content/guides/tutorials/complete-installation.md +17 -17
- package/content/guides/tutorials/ecommerce-api.md +163 -124
- package/content/guides/tutorials/realtime-chat.md +181 -135
- package/content/guides/tutorials/testing.md +65 -523
- package/content/index.md +2 -180
- package/content/public/apple-touch-icon.png +0 -0
- package/content/public/og-image.png +0 -0
- package/content/public/site.webmanifest +11 -0
- package/content/references/base/application.md +4 -5
- package/content/references/base/bootstrapping.md +18 -5
- package/content/references/base/components.md +149 -120
- package/content/references/base/connectors.md +178 -0
- package/content/references/base/controllers.md +41 -30
- package/content/references/base/datasources.md +163 -92
- package/content/references/base/dependency-injection.md +34 -22
- package/content/references/base/filter-system/application-usage.md +17 -14
- package/content/references/base/filter-system/array-operators.md +7 -2
- package/content/references/base/filter-system/comparison-operators.md +3 -0
- package/content/references/base/filter-system/default-filter.md +89 -71
- package/content/references/base/filter-system/fields-order-pagination.md +22 -22
- package/content/references/base/filter-system/index.md +6 -3
- package/content/references/base/filter-system/json-filtering.md +20 -1
- package/content/references/base/filter-system/list-operators.md +1 -1
- package/content/references/base/filter-system/logical-operators.md +33 -1
- package/content/references/base/filter-system/null-operators.md +30 -1
- package/content/references/base/filter-system/quick-reference.md +23 -4
- package/content/references/base/filter-system/tips.md +5 -5
- package/content/references/base/filter-system/use-cases.md +12 -12
- package/content/references/base/grpc-controllers.md +13 -13
- package/content/references/base/index.md +24 -12
- package/content/references/base/middlewares.md +265 -327
- package/content/references/base/models.md +63 -49
- package/content/references/base/providers.md +136 -130
- package/content/references/base/repositories/advanced.md +59 -58
- package/content/references/base/repositories/index.md +115 -91
- package/content/references/base/repositories/mixins.md +55 -291
- package/content/references/base/repositories/relations.md +54 -64
- package/content/references/base/repositories/soft-deletable.md +31 -30
- package/content/references/base/services.md +296 -93
- package/content/references/configuration/environment-variables.md +49 -31
- package/content/references/configuration/index.md +6 -6
- package/content/references/index.md +17 -12
- package/content/references/quick-reference.md +65 -106
- package/content/references/utilities/crypto.md +65 -23
- package/content/references/utilities/index.md +3 -3
- package/content/references/utilities/jsx.md +6 -4
- package/content/references/utilities/module.md +68 -20
- package/content/references/utilities/parse.md +4 -14
- package/content/references/utilities/promise.md +9 -7
- package/content/references/utilities/schema.md +5 -3
- package/dist/mcp-server/common/guards.d.ts +8 -0
- package/dist/mcp-server/common/guards.d.ts.map +1 -0
- package/dist/mcp-server/common/guards.js +14 -0
- package/dist/mcp-server/common/guards.js.map +1 -0
- package/dist/mcp-server/common/index.d.ts +1 -0
- package/dist/mcp-server/common/index.d.ts.map +1 -1
- package/dist/mcp-server/common/index.js +1 -0
- package/dist/mcp-server/common/index.js.map +1 -1
- package/dist/mcp-server/helpers/docs.helper.d.ts.map +1 -1
- package/dist/mcp-server/helpers/docs.helper.js +4 -2
- package/dist/mcp-server/helpers/docs.helper.js.map +1 -1
- package/dist/mcp-server/helpers/github.helper.js +1 -1
- package/dist/mcp-server/index.js +7 -2
- package/dist/mcp-server/index.js.map +1 -1
- package/dist/mcp-server/tools/base.tool.d.ts +6 -2
- package/dist/mcp-server/tools/base.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/base.tool.js.map +1 -1
- package/dist/mcp-server/tools/docs/search-documents.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/search-code.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/search-code.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/github/search-code.tool.js +4 -1
- package/dist/mcp-server/tools/github/search-code.tool.js.map +1 -1
- package/dist/mcp-server/tools/github/verify-dependencies.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/github/verify-dependencies.tool.js +3 -1
- package/dist/mcp-server/tools/github/verify-dependencies.tool.js.map +1 -1
- package/package.json +9 -9
- package/content/extensions/helpers/testing/index.md +0 -510
- package/content/references/base/middleware.md +0 -347
|
@@ -6,7 +6,7 @@ difficulty: advanced
|
|
|
6
6
|
|
|
7
7
|
# Deep Dive: Components
|
|
8
8
|
|
|
9
|
-
Technical reference for `BaseComponent
|
|
9
|
+
Technical reference for `BaseComponent`-the foundation for creating reusable, pluggable features in IGNIS. Components are powerful containers that can group together multiple providers, services, controllers, repositories, and even entire mini-applications into a single, redistributable module.
|
|
10
10
|
|
|
11
11
|
**File:** `packages/core/src/base/components/base.ts`
|
|
12
12
|
|
|
@@ -17,7 +17,7 @@ Technical reference for `BaseComponent`—the foundation for creating reusable,
|
|
|
17
17
|
| **Encapsulation** | Bundle feature bindings (services, controllers) into single class |
|
|
18
18
|
| **Lifecycle Management** | Auto-called `binding()` method during startup |
|
|
19
19
|
| **Default Bindings** | Self-contained with automatic DI registration |
|
|
20
|
-
| **Idempotent Configure** | `configure()` is safe to call multiple times
|
|
20
|
+
| **Idempotent Configure** | `configure()` is safe to call multiple times - runs `binding()` only once |
|
|
21
21
|
| **Controller Transports** | `RestComponent` and `GrpcComponent` handle controller discovery per transport |
|
|
22
22
|
|
|
23
23
|
|
|
@@ -52,29 +52,42 @@ src/components/auth/
|
|
|
52
52
|
│ │ ├── index.ts
|
|
53
53
|
│ │ ├── keys.ts
|
|
54
54
|
│ │ ├── types.ts
|
|
55
|
-
│ │
|
|
55
|
+
│ │ ├── constants.ts
|
|
56
|
+
│ │ └── codecs.ts
|
|
56
57
|
│ ├── controllers/
|
|
57
58
|
│ │ ├── index.ts
|
|
58
|
-
│ │
|
|
59
|
+
│ │ ├── factory.ts
|
|
60
|
+
│ │ └── jwks/
|
|
61
|
+
│ ├── middlewares/
|
|
62
|
+
│ ├── providers/
|
|
59
63
|
│ ├── services/
|
|
60
64
|
│ │ ├── index.ts
|
|
61
|
-
│ │
|
|
65
|
+
│ │ ├── basic/
|
|
66
|
+
│ │ └── bearer/
|
|
67
|
+
│ │ ├── jws.service.ts
|
|
68
|
+
│ │ └── jwks/
|
|
62
69
|
│ └── strategies/
|
|
63
70
|
│ ├── index.ts
|
|
64
|
-
│ ├──
|
|
65
|
-
│
|
|
71
|
+
│ ├── jws.strategy.ts
|
|
72
|
+
│ ├── jwks.strategy.ts
|
|
73
|
+
│ ├── basic.strategy.ts
|
|
74
|
+
│ └── strategy-registry.ts
|
|
66
75
|
└── models/
|
|
67
76
|
├── index.ts
|
|
68
77
|
├── entities/
|
|
69
|
-
│
|
|
78
|
+
│ ├── user.model.ts
|
|
79
|
+
│ ├── role.model.ts
|
|
80
|
+
│ ├── permission.model.ts
|
|
81
|
+
│ └── policy-definition.model.ts
|
|
70
82
|
└── requests/
|
|
71
83
|
├── sign-in.schema.ts
|
|
72
|
-
|
|
84
|
+
├── sign-up.schema.ts
|
|
85
|
+
└── change-password.schema.ts
|
|
73
86
|
```
|
|
74
87
|
|
|
75
88
|
### Controller Transport Component
|
|
76
89
|
|
|
77
|
-
Transport components live under `src/components/controller/` and are instantiated directly by the application during `registerControllers()`
|
|
90
|
+
Transport components live under `src/components/controller/` and are instantiated directly by the application during `registerControllers()` - they are **not** registered via `this.component()`.
|
|
78
91
|
|
|
79
92
|
```
|
|
80
93
|
src/components/controller/
|
|
@@ -110,14 +123,16 @@ export class HealthCheckBindingKeys {
|
|
|
110
123
|
```typescript
|
|
111
124
|
// src/components/auth/authenticate/common/keys.ts
|
|
112
125
|
export class AuthenticateBindingKeys {
|
|
113
|
-
static readonly
|
|
114
|
-
static readonly JWT_OPTIONS = '@app/authenticate/jwt
|
|
126
|
+
static readonly REST_OPTIONS = '@app/authenticate/rest-options';
|
|
127
|
+
static readonly JWT_OPTIONS = '@app/authenticate/jwt-options';
|
|
128
|
+
static readonly JWKS_OPTIONS = '@app/authenticate/jwks-options';
|
|
129
|
+
static readonly BASIC_OPTIONS = '@app/authenticate/basic-options';
|
|
115
130
|
}
|
|
116
131
|
```
|
|
117
132
|
|
|
118
133
|
**Naming Convention:**
|
|
119
134
|
- Class name: `[Feature]BindingKeys`
|
|
120
|
-
- Key format: `@app/[component]/[feature]`
|
|
135
|
+
- Key format: `@app/[component]/[feature]`
|
|
121
136
|
|
|
122
137
|
### 2. Types (`types.ts`)
|
|
123
138
|
|
|
@@ -134,38 +149,49 @@ export interface IHealthCheckOptions {
|
|
|
134
149
|
|
|
135
150
|
```typescript
|
|
136
151
|
// src/components/auth/authenticate/common/types.ts
|
|
137
|
-
import {
|
|
138
|
-
import {
|
|
152
|
+
import { AnyObject } from '@venizia/ignis-helpers';
|
|
153
|
+
import { Env } from 'hono';
|
|
139
154
|
|
|
140
155
|
// Options interface for the component
|
|
141
156
|
export interface IAuthenticateOptions {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
useAuthController?: boolean;
|
|
146
|
-
controllerOpts?: TDefineAuthControllerOpts;
|
|
147
|
-
};
|
|
157
|
+
restOptions?: TAuthenticationRestOptions;
|
|
158
|
+
jwtOptions?: TJWTTokenServiceOptions;
|
|
159
|
+
basicOptions?: TBasicTokenServiceOptions;
|
|
148
160
|
}
|
|
149
161
|
|
|
150
|
-
// Service options
|
|
151
|
-
export
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
getTokenExpiresFn: () => ValueOrPromise<number>;
|
|
155
|
-
}
|
|
162
|
+
// Service options type (JWS or JWKS)
|
|
163
|
+
export type TJWTTokenServiceOptions =
|
|
164
|
+
| { standard: typeof JOSEStandards.JWS; options: IJWSTokenServiceOptions }
|
|
165
|
+
| { standard: typeof JOSEStandards.JWKS; options: TJWKSTokenServiceOptions };
|
|
156
166
|
|
|
157
167
|
// Service contract interface
|
|
158
168
|
export interface IAuthService<
|
|
159
|
-
|
|
169
|
+
E extends Env = Env,
|
|
170
|
+
// SignIn types
|
|
171
|
+
SIRQ extends TSignInRequest = TSignInRequest,
|
|
160
172
|
SIRS = AnyObject,
|
|
173
|
+
// SignUp types
|
|
174
|
+
SURQ extends TSignUpRequest = TSignUpRequest,
|
|
175
|
+
SURS = AnyObject,
|
|
176
|
+
// ChangePassword types
|
|
177
|
+
CPRQ extends TChangePasswordRequest = TChangePasswordRequest,
|
|
178
|
+
CPRS = AnyObject,
|
|
179
|
+
// UserInformation types
|
|
180
|
+
UIRQ = AnyObject,
|
|
181
|
+
UIRS = AnyObject,
|
|
182
|
+
// RefreshToken types
|
|
183
|
+
RTRS = AnyObject,
|
|
161
184
|
> {
|
|
162
|
-
signIn(context:
|
|
163
|
-
signUp(context:
|
|
185
|
+
signIn(context: TContext<E>, opts: SIRQ): Promise<SIRS>;
|
|
186
|
+
signUp(context: TContext<E>, opts: SURQ): Promise<SURS>;
|
|
187
|
+
changePassword(context: TContext<E>, opts: CPRQ): Promise<CPRS>;
|
|
188
|
+
getUserInformation?(context: TContext<E>, opts: UIRQ): Promise<UIRS>;
|
|
189
|
+
refreshToken?(context: TContext<E>): Promise<RTRS>;
|
|
164
190
|
}
|
|
165
191
|
|
|
166
192
|
// Auth user type
|
|
167
193
|
export interface IAuthUser {
|
|
168
|
-
userId:
|
|
194
|
+
userId: IdType;
|
|
169
195
|
[extra: string | symbol]: any;
|
|
170
196
|
}
|
|
171
197
|
```
|
|
@@ -198,9 +224,7 @@ export class Authentication {
|
|
|
198
224
|
**With validation (for user-configurable values):**
|
|
199
225
|
|
|
200
226
|
```typescript
|
|
201
|
-
// src/components/
|
|
202
|
-
import { TConstValue } from '@venizia/ignis-helpers';
|
|
203
|
-
|
|
227
|
+
// src/components/api-reference/common/constants.ts
|
|
204
228
|
export class DocumentUITypes {
|
|
205
229
|
static readonly SWAGGER = 'swagger';
|
|
206
230
|
static readonly SCALAR = 'scalar';
|
|
@@ -214,6 +238,9 @@ export class DocumentUITypes {
|
|
|
214
238
|
}
|
|
215
239
|
}
|
|
216
240
|
|
|
241
|
+
// src/components/api-reference/common/types.ts
|
|
242
|
+
import { TConstValue } from '@venizia/ignis-helpers';
|
|
243
|
+
|
|
217
244
|
// Extract union type: 'swagger' | 'scalar'
|
|
218
245
|
export type TDocumentUIType = TConstValue<typeof DocumentUITypes>;
|
|
219
246
|
```
|
|
@@ -227,7 +254,6 @@ Define route path constants for controllers.
|
|
|
227
254
|
export class HealthCheckRestPaths {
|
|
228
255
|
static readonly ROOT = '/';
|
|
229
256
|
static readonly PING = '/ping';
|
|
230
|
-
static readonly METRICS = '/metrics';
|
|
231
257
|
}
|
|
232
258
|
```
|
|
233
259
|
|
|
@@ -269,7 +295,7 @@ The `super()` constructor in your component can take the following options:
|
|
|
269
295
|
| Option | Type | Description |
|
|
270
296
|
| :--- | :--- | :--- |
|
|
271
297
|
| `scope` | `string` | **Required.** A unique name for the component, typically `MyComponent.name`. Used for logging. |
|
|
272
|
-
| `initDefault` | `{ enable: false } \| { enable: true; container: Container }` | If `enable` is `true`, the `bindings` defined below will be automatically registered with the provided `container` (usually the application instance) when `configure()` is called
|
|
298
|
+
| `initDefault` | `{ enable: false } \| { enable: true; container: Container }` | If `enable` is `true`, the `bindings` defined below will be automatically registered with the provided `container` (usually the application instance) when `configure()` is called - but only if they are not already bound. Defaults to `{ enable: false }`. |
|
|
273
299
|
| `bindings` | `Record<string \| symbol, Binding>` | An object where keys are binding keys and values are `Binding` instances. These are the default services, values, or providers that your component offers. Defaults to `{}`. |
|
|
274
300
|
|
|
275
301
|
### Properties
|
|
@@ -278,14 +304,14 @@ The `super()` constructor in your component can take the following options:
|
|
|
278
304
|
| :--- | :--- | :--- | :--- |
|
|
279
305
|
| `bindings` | `Record<string \| symbol, Binding>` | `protected` | Default bindings the component provides. Can be set in constructor or assigned directly in the constructor body. |
|
|
280
306
|
| `initDefault` | `TInitDefault` | `protected` | Controls whether default bindings are auto-registered to a container. |
|
|
281
|
-
| `isConfigured` | `boolean` | `protected` | Guard flag
|
|
307
|
+
| `isConfigured` | `boolean` | `protected` | Guard flag - prevents `configure()` from running more than once. |
|
|
282
308
|
|
|
283
309
|
### Methods
|
|
284
310
|
|
|
285
311
|
| Method | Signature | Description |
|
|
286
312
|
| :--- | :--- | :--- |
|
|
287
313
|
| `binding()` | `abstract binding(): ValueOrPromise<void>` | **Abstract.** Override this to register services, controllers, and other resources. Called by `configure()`. |
|
|
288
|
-
| `configure(opts?)` | `async configure(opts?: ConfigurableOptions): Promise<void>` | Entry point. Calls `initDefaultBindings()` (if enabled), then `binding()`. Idempotent
|
|
314
|
+
| `configure(opts?)` | `async configure(opts?: ConfigurableOptions): Promise<void>` | Entry point. Calls `initDefaultBindings()` (if enabled), then `binding()`. Idempotent - skips if already configured. |
|
|
289
315
|
| `initDefaultBindings(opts)` | `protected initDefaultBindings(opts: { container: Container }): void` | Iterates `this.bindings` and registers each into the container if not already bound. |
|
|
290
316
|
|
|
291
317
|
### Lifecycle Flow
|
|
@@ -440,7 +466,7 @@ export class GrpcBindingKeys {
|
|
|
440
466
|
}
|
|
441
467
|
```
|
|
442
468
|
|
|
443
|
-
> **Note:** `GrpcComponent` is excluded from the barrel export at `src/components/controller/index.ts`.
|
|
469
|
+
> **Note:** `GrpcComponent` is excluded from the barrel export at `src/components/controller/index.ts`. You never import it in application code - `BaseApplication.registerControllers()` instantiates it automatically when `transports` includes `'grpc'`.
|
|
444
470
|
|
|
445
471
|
|
|
446
472
|
## Component Implementation Patterns
|
|
@@ -449,7 +475,7 @@ export class GrpcBindingKeys {
|
|
|
449
475
|
|
|
450
476
|
```typescript
|
|
451
477
|
// src/components/health-check/component.ts
|
|
452
|
-
import { BaseApplication, BaseComponent, inject, CoreBindings, Binding, ValueOrPromise } from '@venizia/ignis';
|
|
478
|
+
import { BaseApplication, BaseComponent, controller, inject, CoreBindings, Binding, ValueOrPromise } from '@venizia/ignis';
|
|
453
479
|
import { HealthCheckBindingKeys, IHealthCheckOptions } from './common';
|
|
454
480
|
import { HealthCheckController } from './controller';
|
|
455
481
|
|
|
@@ -501,16 +527,15 @@ export class HealthCheckComponent extends BaseComponent {
|
|
|
501
527
|
// src/components/auth/authenticate/component.ts
|
|
502
528
|
import { BaseApplication, BaseComponent, inject, CoreBindings, Binding, ValueOrPromise } from '@venizia/ignis';
|
|
503
529
|
import { getError } from '@venizia/ignis-helpers';
|
|
504
|
-
import {
|
|
505
|
-
|
|
530
|
+
import {
|
|
531
|
+
AuthenticateBindingKeys,
|
|
532
|
+
TAuthenticationRestOptions,
|
|
533
|
+
TBasicTokenServiceOptions,
|
|
534
|
+
TJWTTokenServiceOptions,
|
|
535
|
+
} from './common';
|
|
536
|
+
import { BasicTokenService, JWSTokenService } from './services';
|
|
506
537
|
import { defineAuthController } from './controllers';
|
|
507
538
|
|
|
508
|
-
const DEFAULT_OPTIONS: IAuthenticateOptions = {
|
|
509
|
-
restOptions: {
|
|
510
|
-
useAuthController: false,
|
|
511
|
-
},
|
|
512
|
-
};
|
|
513
|
-
|
|
514
539
|
export class AuthenticateComponent extends BaseComponent {
|
|
515
540
|
constructor(
|
|
516
541
|
@inject({ key: CoreBindings.APPLICATION_INSTANCE })
|
|
@@ -519,66 +544,63 @@ export class AuthenticateComponent extends BaseComponent {
|
|
|
519
544
|
super({
|
|
520
545
|
scope: AuthenticateComponent.name,
|
|
521
546
|
initDefault: { enable: true, container: application },
|
|
547
|
+
// Only restOptions gets a default here - jwtOptions/basicOptions are
|
|
548
|
+
// bound separately (by the app, before registration) since at least one is required.
|
|
522
549
|
bindings: {
|
|
523
|
-
[AuthenticateBindingKeys.
|
|
524
|
-
key: AuthenticateBindingKeys.
|
|
525
|
-
}).toValue(
|
|
550
|
+
[AuthenticateBindingKeys.REST_OPTIONS]: Binding.bind<TAuthenticationRestOptions>({
|
|
551
|
+
key: AuthenticateBindingKeys.REST_OPTIONS,
|
|
552
|
+
}).toValue({ useAuthController: false }),
|
|
526
553
|
},
|
|
527
554
|
});
|
|
528
555
|
}
|
|
529
556
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
557
|
+
override binding(): ValueOrPromise<void> {
|
|
558
|
+
const jwtOptions = this.application.get<TJWTTokenServiceOptions>({
|
|
559
|
+
key: AuthenticateBindingKeys.JWT_OPTIONS,
|
|
560
|
+
isOptional: true,
|
|
561
|
+
});
|
|
562
|
+
const basicOptions = this.application.get<TBasicTokenServiceOptions>({
|
|
563
|
+
key: AuthenticateBindingKeys.BASIC_OPTIONS,
|
|
564
|
+
isOptional: true,
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
if (!jwtOptions && !basicOptions) {
|
|
533
568
|
throw getError({
|
|
534
569
|
message: '[AuthenticateComponent] At least one of jwtOptions or basicOptions must be provided',
|
|
535
570
|
});
|
|
536
571
|
}
|
|
537
|
-
}
|
|
538
572
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
if (
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
.
|
|
546
|
-
this.application.service(JWTTokenService);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
// Configure Basic authentication if basicOptions is provided
|
|
550
|
-
private defineBasicAuth(opts: IAuthenticateOptions): void {
|
|
551
|
-
if (!opts.basicOptions) return;
|
|
552
|
-
|
|
553
|
-
this.application
|
|
554
|
-
.bind<IBasicTokenServiceOptions>({ key: AuthenticateBindingKeys.BASIC_OPTIONS })
|
|
555
|
-
.toValue(opts.basicOptions);
|
|
556
|
-
this.application.service(BasicTokenService);
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
// Configure auth controllers if enabled
|
|
560
|
-
private defineControllers(opts: IAuthenticateOptions): void {
|
|
561
|
-
if (!opts.restOptions?.useAuthController) return;
|
|
562
|
-
|
|
563
|
-
// Auth controller requires JWT for token generation
|
|
564
|
-
if (!opts.jwtOptions) {
|
|
565
|
-
throw getError({
|
|
566
|
-
message: '[defineControllers] Auth controller requires jwtOptions to be configured',
|
|
567
|
-
});
|
|
573
|
+
// JWT auth supports both JWS (shared-secret) and JWKS (issuer/verifier) standards -
|
|
574
|
+
// see the real component for the full switch over `jwtOptions.standard`.
|
|
575
|
+
if (jwtOptions) {
|
|
576
|
+
this.application
|
|
577
|
+
.bind<TJWTTokenServiceOptions>({ key: AuthenticateBindingKeys.JWT_OPTIONS })
|
|
578
|
+
.toValue(jwtOptions);
|
|
579
|
+
this.application.service(JWSTokenService);
|
|
568
580
|
}
|
|
569
581
|
|
|
570
|
-
|
|
571
|
-
|
|
582
|
+
if (basicOptions) {
|
|
583
|
+
this.application
|
|
584
|
+
.bind<TBasicTokenServiceOptions>({ key: AuthenticateBindingKeys.BASIC_OPTIONS })
|
|
585
|
+
.toValue(basicOptions);
|
|
586
|
+
this.application.service(BasicTokenService);
|
|
587
|
+
}
|
|
572
588
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
589
|
+
const restOptions = this.application.get<TAuthenticationRestOptions>({
|
|
590
|
+
key: AuthenticateBindingKeys.REST_OPTIONS,
|
|
591
|
+
isOptional: true,
|
|
576
592
|
});
|
|
577
593
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
594
|
+
if (restOptions?.useAuthController) {
|
|
595
|
+
// Auth controller requires JWT for token generation
|
|
596
|
+
if (!jwtOptions) {
|
|
597
|
+
throw getError({
|
|
598
|
+
message: '[AuthenticateComponent] Auth controller requires jwtOptions to be configured',
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
this.application.controller(defineAuthController(restOptions.controllerOpts));
|
|
603
|
+
}
|
|
582
604
|
}
|
|
583
605
|
}
|
|
584
606
|
```
|
|
@@ -588,7 +610,7 @@ export class AuthenticateComponent extends BaseComponent {
|
|
|
588
610
|
When controllers need to be dynamically configured:
|
|
589
611
|
|
|
590
612
|
```typescript
|
|
591
|
-
// src/components/static-asset/component.ts
|
|
613
|
+
// src/components/static-asset/component.ts (condensed)
|
|
592
614
|
override binding(): ValueOrPromise<void> {
|
|
593
615
|
const componentOptions = this.application.get<TStaticAssetsComponentOptions>({
|
|
594
616
|
key: StaticAssetComponentBindingKeys.STATIC_ASSET_COMPONENT_OPTIONS,
|
|
@@ -596,18 +618,24 @@ override binding(): ValueOrPromise<void> {
|
|
|
596
618
|
|
|
597
619
|
// Create multiple controllers from configuration
|
|
598
620
|
for (const [key, opt] of Object.entries(componentOptions)) {
|
|
621
|
+
const { storage, controller, helper, extra } = opt;
|
|
622
|
+
|
|
599
623
|
this.application.controller(
|
|
600
624
|
AssetControllerFactory.defineAssetController({
|
|
601
|
-
controller
|
|
602
|
-
storage
|
|
603
|
-
helper
|
|
625
|
+
controller,
|
|
626
|
+
storage,
|
|
627
|
+
helper,
|
|
628
|
+
useMetaLink: opt.useMetaLink,
|
|
629
|
+
metaLink: opt.useMetaLink ? opt.metaLink : undefined,
|
|
630
|
+
options: { ...extra /* , normalizeLinkFn fallback */ },
|
|
604
631
|
}),
|
|
605
632
|
);
|
|
606
633
|
|
|
607
634
|
this.application.logger.info(
|
|
608
|
-
|
|
635
|
+
`[binding] Asset storage is bound | Key: %s | Storage type: %s | UseMetaLink: %s`,
|
|
609
636
|
key,
|
|
610
|
-
|
|
637
|
+
storage,
|
|
638
|
+
Boolean(opt.useMetaLink),
|
|
611
639
|
);
|
|
612
640
|
}
|
|
613
641
|
}
|
|
@@ -615,30 +643,31 @@ override binding(): ValueOrPromise<void> {
|
|
|
615
643
|
|
|
616
644
|
### Component without `initDefault` (Manual Binding Assignment)
|
|
617
645
|
|
|
618
|
-
|
|
646
|
+
A component may instead declare its defaults but NOT register them, by omitting `initDefault` and assigning `this.bindings` in the constructor body:
|
|
619
647
|
|
|
620
648
|
```typescript
|
|
621
|
-
|
|
622
|
-
export class SwaggerComponent extends BaseComponent {
|
|
649
|
+
export class CustomComponent extends BaseComponent {
|
|
623
650
|
constructor(
|
|
624
651
|
@inject({ key: CoreBindings.APPLICATION_INSTANCE }) private application: BaseApplication,
|
|
625
652
|
) {
|
|
626
|
-
super({ scope:
|
|
653
|
+
super({ scope: CustomComponent.name });
|
|
627
654
|
|
|
628
655
|
this.bindings = {
|
|
629
|
-
[
|
|
630
|
-
key:
|
|
631
|
-
}).toValue(
|
|
656
|
+
[CustomBindingKeys.OPTIONS]: Binding.bind<ICustomOptions>({
|
|
657
|
+
key: CustomBindingKeys.OPTIONS,
|
|
658
|
+
}).toValue(DEFAULT_CUSTOM_OPTIONS),
|
|
632
659
|
};
|
|
633
660
|
}
|
|
634
661
|
|
|
635
662
|
override async binding() {
|
|
636
|
-
// Read options,
|
|
663
|
+
// Read options, then wire the component's routes/services.
|
|
637
664
|
}
|
|
638
665
|
}
|
|
639
666
|
```
|
|
640
667
|
|
|
641
|
-
|
|
668
|
+
With `initDefault` omitted it defaults to `{ enable: false }`, so the bindings are defined but not auto-registered - the component takes over its own option reading and setup in `binding()`.
|
|
669
|
+
|
|
670
|
+
The shipped `ApiReferenceComponent` does **not** use this pattern: it passes `initDefault: { enable: true, container: application }` and its `bindings` through `super()`, so its default `IApiReferenceOptions` binding lands in the container immediately (see [API Reference](/extensions/components/api-reference)).
|
|
642
671
|
|
|
643
672
|
|
|
644
673
|
## Built-in Components
|
|
@@ -648,19 +677,19 @@ In this pattern, `initDefault` defaults to `{ enable: false }`, so the bindings
|
|
|
648
677
|
| Component | Key Features |
|
|
649
678
|
|-----------|-------------|
|
|
650
679
|
| **HealthCheckComponent** | `GET /health` (default path, configurable). Registers `HealthCheckController` with `GET /` and `POST /ping` endpoints. |
|
|
651
|
-
| **
|
|
652
|
-
| **AuthenticateComponent** | JWT and/or Basic auth strategies. Optional auth controller (`signIn`/`signUp`). Token services (`
|
|
653
|
-
| **
|
|
680
|
+
| **ApiReferenceComponent** | OpenAPI doc at `/doc/openapi.json`, UI at `/doc/explorer` (Scalar by default, Swagger UI also supported). Auto-populates app info and server URL. Registers JWT and Basic security schemes. |
|
|
681
|
+
| **AuthenticateComponent** | JWT and/or Basic auth strategies. Optional auth controller (`signIn`/`signUp`). Token services (`JWSTokenService`, `BasicTokenService`). |
|
|
682
|
+
| **AuthorizeComponent** | Casbin-based RBAC, permission mapping, `authorize()` middleware. |
|
|
654
683
|
| **RequestTrackerComponent** | Registers Hono `requestId()` middleware and a `RequestSpyMiddleware` for `x-request-id` header tracking and request body parsing. |
|
|
655
684
|
|
|
656
685
|
### Excluded from Barrel (Import Directly)
|
|
657
686
|
|
|
658
687
|
| Component | Import Path | Key Features |
|
|
659
688
|
|-----------|-------------|-------------|
|
|
660
|
-
| **StaticAssetComponent** | `@venizia/ignis/
|
|
661
|
-
| **MailComponent** | `@venizia/ignis/
|
|
662
|
-
| **SocketIOComponent** | `@venizia/ignis/
|
|
663
|
-
| **WebSocketComponent** | `@venizia/ignis/
|
|
689
|
+
| **StaticAssetComponent** | `@venizia/ignis/static-asset` | File upload/download CRUD, MinIO/Disk storage. |
|
|
690
|
+
| **MailComponent** | `@venizia/ignis/mail` | Nodemailer/Mailgun transporters, Direct/BullMQ/InternalQueue executors. |
|
|
691
|
+
| **SocketIOComponent** | `@venizia/ignis/socket-io` | Socket.IO server with Redis adapter for horizontal scaling. |
|
|
692
|
+
| **WebSocketComponent** | `@venizia/ignis/websocket` | WebSocket support. |
|
|
664
693
|
|
|
665
694
|
### Controller Transport Components (Not Registered via `this.component()`)
|
|
666
695
|
|
|
@@ -719,13 +748,13 @@ For complex nested configurations:
|
|
|
719
748
|
|
|
720
749
|
```typescript
|
|
721
750
|
override binding(): ValueOrPromise<void> {
|
|
722
|
-
const extraOptions = this.application.get<Partial<
|
|
723
|
-
key:
|
|
751
|
+
const extraOptions = this.application.get<Partial<IApiReferenceOptions>>({
|
|
752
|
+
key: ApiReferenceBindingKeys.API_REFERENCE_OPTIONS,
|
|
724
753
|
isOptional: true,
|
|
725
754
|
}) ?? {};
|
|
726
755
|
|
|
727
756
|
// Deep merge nested objects
|
|
728
|
-
const options:
|
|
757
|
+
const options: IApiReferenceOptions = {
|
|
729
758
|
...DEFAULT_OPTIONS,
|
|
730
759
|
...extraOptions,
|
|
731
760
|
restOptions: {
|
|
@@ -754,7 +783,7 @@ override binding(): ValueOrPromise<void> {
|
|
|
754
783
|
| **Validation** | Validate required options in `binding()` |
|
|
755
784
|
| **Logging** | Log binding activity with structured messages |
|
|
756
785
|
| **Scope** | Always set `scope: ComponentName.name` |
|
|
757
|
-
| **Idempotency** | `configure()` is already idempotent via `isConfigured` guard
|
|
786
|
+
| **Idempotency** | `configure()` is already idempotent via `isConfigured` guard - no need to add your own |
|
|
758
787
|
|
|
759
788
|
|
|
760
789
|
## Quick Reference Template
|
|
@@ -843,7 +872,7 @@ export * from './controller';
|
|
|
843
872
|
- **Built-in Components:**
|
|
844
873
|
- [Authentication Component](/extensions/components/authentication/) - JWT authentication
|
|
845
874
|
- [Health Check Component](/extensions/components/health-check) - Health endpoints
|
|
846
|
-
- [Swagger Component](/extensions/components/
|
|
875
|
+
- [Swagger Component](/extensions/components/api-reference) - API documentation
|
|
847
876
|
- [Socket.IO Component](/extensions/components/socket-io/) - WebSocket support
|
|
848
877
|
|
|
849
878
|
- **Best Practices:**
|