@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.
Files changed (180) hide show
  1. package/README.md +7 -7
  2. package/content/best-practices/api-usage-examples.md +15 -12
  3. package/content/best-practices/architectural-patterns.md +70 -78
  4. package/content/best-practices/architecture-decisions.md +91 -60
  5. package/content/best-practices/code-style-standards/advanced-patterns.md +56 -44
  6. package/content/best-practices/code-style-standards/constants-configuration.md +11 -11
  7. package/content/best-practices/code-style-standards/control-flow.md +5 -2
  8. package/content/best-practices/code-style-standards/documentation.md +13 -13
  9. package/content/best-practices/code-style-standards/function-patterns.md +9 -10
  10. package/content/best-practices/code-style-standards/index.md +1 -1
  11. package/content/best-practices/code-style-standards/naming-conventions.md +10 -8
  12. package/content/best-practices/code-style-standards/route-definitions.md +30 -12
  13. package/content/best-practices/code-style-standards/tooling.md +8 -5
  14. package/content/best-practices/code-style-standards/type-safety.md +13 -12
  15. package/content/best-practices/common-pitfalls.md +56 -37
  16. package/content/best-practices/contribution-workflow.md +13 -14
  17. package/content/best-practices/data-modeling.md +46 -22
  18. package/content/best-practices/deployment-strategies.md +28 -27
  19. package/content/best-practices/error-handling.md +48 -24
  20. package/content/best-practices/index.md +5 -5
  21. package/content/best-practices/performance-optimization.md +40 -31
  22. package/content/best-practices/security-guidelines.md +52 -23
  23. package/content/best-practices/testing-strategies.md +65 -51
  24. package/content/best-practices/troubleshooting-tips.md +24 -24
  25. package/content/extensions/components/{swagger.md → api-reference.md} +40 -31
  26. package/content/extensions/components/authentication/api.md +19 -19
  27. package/content/extensions/components/authentication/errors.md +7 -7
  28. package/content/extensions/components/authentication/index.md +10 -8
  29. package/content/extensions/components/authentication/usage.md +101 -6
  30. package/content/extensions/components/authorization/api.md +45 -25
  31. package/content/extensions/components/authorization/errors.md +6 -6
  32. package/content/extensions/components/authorization/index.md +11 -10
  33. package/content/extensions/components/authorization/usage.md +21 -21
  34. package/content/extensions/components/health-check.md +1 -1
  35. package/content/extensions/components/index.md +5 -5
  36. package/content/extensions/components/mail/errors.md +15 -15
  37. package/content/extensions/components/mail/index.md +1 -2
  38. package/content/extensions/components/mail/usage.md +1 -1
  39. package/content/extensions/components/request-tracker.md +1 -1
  40. package/content/extensions/components/socket-io/api.md +9 -9
  41. package/content/extensions/components/socket-io/errors.md +5 -5
  42. package/content/extensions/components/socket-io/index.md +8 -8
  43. package/content/extensions/components/socket-io/usage.md +1 -1
  44. package/content/extensions/components/static-asset/api.md +17 -4
  45. package/content/extensions/components/static-asset/errors.md +4 -4
  46. package/content/extensions/components/static-asset/index.md +26 -28
  47. package/content/extensions/components/static-asset/usage.md +13 -12
  48. package/content/extensions/components/template/index.md +2 -2
  49. package/content/extensions/components/template/setup-page.md +1 -1
  50. package/content/extensions/components/websocket/api.md +3 -3
  51. package/content/extensions/components/websocket/errors.md +5 -5
  52. package/content/extensions/components/websocket/index.md +5 -5
  53. package/content/extensions/components/websocket/usage.md +3 -3
  54. package/content/extensions/helpers/cron/index.md +2 -2
  55. package/content/extensions/helpers/crypto/index.md +1 -1
  56. package/content/extensions/helpers/env/index.md +27 -12
  57. package/content/extensions/helpers/error/index.md +81 -25
  58. package/content/extensions/helpers/index.md +2 -3
  59. package/content/extensions/helpers/inversion/index.md +15 -7
  60. package/content/extensions/helpers/kafka/compile-binary.md +92 -0
  61. package/content/extensions/helpers/kafka/examples.md +1 -1
  62. package/content/extensions/helpers/kafka/index.md +3 -0
  63. package/content/extensions/helpers/logger/index.md +32 -2
  64. package/content/extensions/helpers/network/index.md +6 -0
  65. package/content/extensions/helpers/queue/index.md +14 -17
  66. package/content/extensions/helpers/redis/index.md +548 -323
  67. package/content/extensions/helpers/socket-io/index.md +14 -10
  68. package/content/extensions/helpers/storage/api.md +44 -8
  69. package/content/extensions/helpers/storage/index.md +43 -7
  70. package/content/extensions/helpers/template/index.md +6 -3
  71. package/content/extensions/helpers/types/index.md +11 -8
  72. package/content/extensions/helpers/websocket/api.md +9 -9
  73. package/content/extensions/helpers/websocket/index.md +7 -7
  74. package/content/extensions/helpers/worker-thread/index.md +2 -2
  75. package/content/extensions/index.md +3 -4
  76. package/content/extensions/src-details/mcp-server.md +18 -24
  77. package/content/guides/core-concepts/application/bootstrapping.md +11 -14
  78. package/content/guides/core-concepts/application/index.md +3 -3
  79. package/content/guides/core-concepts/components.md +19 -10
  80. package/content/guides/core-concepts/dependency-injection.md +6 -3
  81. package/content/guides/core-concepts/grpc-controllers.md +6 -5
  82. package/content/guides/core-concepts/persistent/datasources.md +42 -43
  83. package/content/guides/core-concepts/persistent/index.md +16 -7
  84. package/content/guides/core-concepts/persistent/models.md +24 -20
  85. package/content/guides/core-concepts/persistent/postgres-drivers.md +201 -0
  86. package/content/guides/core-concepts/persistent/repositories.md +40 -23
  87. package/content/guides/core-concepts/persistent/search-meilisearch.md +185 -0
  88. package/content/guides/core-concepts/persistent/search-typesense.md +431 -0
  89. package/content/guides/core-concepts/persistent/transactions.md +61 -25
  90. package/content/guides/core-concepts/rest-controllers.md +12 -9
  91. package/content/guides/core-concepts/services.md +330 -60
  92. package/content/guides/get-started/5-minute-quickstart.md +15 -15
  93. package/content/guides/get-started/philosophy.md +36 -36
  94. package/content/guides/get-started/setup.md +3 -3
  95. package/content/guides/index.md +3 -3
  96. package/content/guides/migrations/redis-helpers-migration.md +177 -0
  97. package/content/guides/migrations/scoped-rbac-migration.md +17 -17
  98. package/content/guides/migrations/unified-connectors-migration.md +113 -0
  99. package/content/guides/reference/glossary.md +19 -12
  100. package/content/guides/reference/mcp-docs-server.md +22 -18
  101. package/content/guides/tutorials/building-a-crud-api.md +37 -44
  102. package/content/guides/tutorials/complete-installation.md +17 -17
  103. package/content/guides/tutorials/ecommerce-api.md +163 -124
  104. package/content/guides/tutorials/realtime-chat.md +181 -135
  105. package/content/guides/tutorials/testing.md +65 -523
  106. package/content/index.md +2 -180
  107. package/content/public/apple-touch-icon.png +0 -0
  108. package/content/public/og-image.png +0 -0
  109. package/content/public/site.webmanifest +11 -0
  110. package/content/references/base/application.md +4 -5
  111. package/content/references/base/bootstrapping.md +18 -5
  112. package/content/references/base/components.md +149 -120
  113. package/content/references/base/connectors.md +178 -0
  114. package/content/references/base/controllers.md +41 -30
  115. package/content/references/base/datasources.md +163 -92
  116. package/content/references/base/dependency-injection.md +34 -22
  117. package/content/references/base/filter-system/application-usage.md +17 -14
  118. package/content/references/base/filter-system/array-operators.md +7 -2
  119. package/content/references/base/filter-system/comparison-operators.md +3 -0
  120. package/content/references/base/filter-system/default-filter.md +89 -71
  121. package/content/references/base/filter-system/fields-order-pagination.md +22 -22
  122. package/content/references/base/filter-system/index.md +6 -3
  123. package/content/references/base/filter-system/json-filtering.md +20 -1
  124. package/content/references/base/filter-system/list-operators.md +1 -1
  125. package/content/references/base/filter-system/logical-operators.md +33 -1
  126. package/content/references/base/filter-system/null-operators.md +30 -1
  127. package/content/references/base/filter-system/quick-reference.md +23 -4
  128. package/content/references/base/filter-system/tips.md +5 -5
  129. package/content/references/base/filter-system/use-cases.md +12 -12
  130. package/content/references/base/grpc-controllers.md +13 -13
  131. package/content/references/base/index.md +24 -12
  132. package/content/references/base/middlewares.md +265 -327
  133. package/content/references/base/models.md +63 -49
  134. package/content/references/base/providers.md +136 -130
  135. package/content/references/base/repositories/advanced.md +59 -58
  136. package/content/references/base/repositories/index.md +115 -91
  137. package/content/references/base/repositories/mixins.md +55 -291
  138. package/content/references/base/repositories/relations.md +54 -64
  139. package/content/references/base/repositories/soft-deletable.md +31 -30
  140. package/content/references/base/services.md +296 -93
  141. package/content/references/configuration/environment-variables.md +49 -31
  142. package/content/references/configuration/index.md +6 -6
  143. package/content/references/index.md +17 -12
  144. package/content/references/quick-reference.md +65 -106
  145. package/content/references/utilities/crypto.md +65 -23
  146. package/content/references/utilities/index.md +3 -3
  147. package/content/references/utilities/jsx.md +6 -4
  148. package/content/references/utilities/module.md +68 -20
  149. package/content/references/utilities/parse.md +4 -14
  150. package/content/references/utilities/promise.md +9 -7
  151. package/content/references/utilities/schema.md +5 -3
  152. package/dist/mcp-server/common/guards.d.ts +8 -0
  153. package/dist/mcp-server/common/guards.d.ts.map +1 -0
  154. package/dist/mcp-server/common/guards.js +14 -0
  155. package/dist/mcp-server/common/guards.js.map +1 -0
  156. package/dist/mcp-server/common/index.d.ts +1 -0
  157. package/dist/mcp-server/common/index.d.ts.map +1 -1
  158. package/dist/mcp-server/common/index.js +1 -0
  159. package/dist/mcp-server/common/index.js.map +1 -1
  160. package/dist/mcp-server/helpers/docs.helper.d.ts.map +1 -1
  161. package/dist/mcp-server/helpers/docs.helper.js +4 -2
  162. package/dist/mcp-server/helpers/docs.helper.js.map +1 -1
  163. package/dist/mcp-server/helpers/github.helper.js +1 -1
  164. package/dist/mcp-server/index.js +7 -2
  165. package/dist/mcp-server/index.js.map +1 -1
  166. package/dist/mcp-server/tools/base.tool.d.ts +6 -2
  167. package/dist/mcp-server/tools/base.tool.d.ts.map +1 -1
  168. package/dist/mcp-server/tools/base.tool.js.map +1 -1
  169. package/dist/mcp-server/tools/docs/search-documents.tool.d.ts +1 -1
  170. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
  171. package/dist/mcp-server/tools/github/search-code.tool.d.ts +1 -1
  172. package/dist/mcp-server/tools/github/search-code.tool.d.ts.map +1 -1
  173. package/dist/mcp-server/tools/github/search-code.tool.js +4 -1
  174. package/dist/mcp-server/tools/github/search-code.tool.js.map +1 -1
  175. package/dist/mcp-server/tools/github/verify-dependencies.tool.d.ts.map +1 -1
  176. package/dist/mcp-server/tools/github/verify-dependencies.tool.js +3 -1
  177. package/dist/mcp-server/tools/github/verify-dependencies.tool.js.map +1 -1
  178. package/package.json +9 -9
  179. package/content/extensions/helpers/testing/index.md +0 -510
  180. 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`—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.
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 runs `binding()` only once |
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
- │ │ └── constants.ts
55
+ │ │ ├── constants.ts
56
+ │ │ └── codecs.ts
56
57
  │ ├── controllers/
57
58
  │ │ ├── index.ts
58
- │ │ └── auth.controller.ts
59
+ │ │ ├── factory.ts
60
+ │ │ └── jwks/
61
+ │ ├── middlewares/
62
+ │ ├── providers/
59
63
  │ ├── services/
60
64
  │ │ ├── index.ts
61
- │ │ └── jwt-token.service.ts
65
+ │ │ ├── basic/
66
+ │ │ └── bearer/
67
+ │ │ ├── jws.service.ts
68
+ │ │ └── jwks/
62
69
  │ └── strategies/
63
70
  │ ├── index.ts
64
- │ ├── jwt.strategy.ts
65
- └── basic.strategy.ts
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
- └── user-token.model.ts
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
- └── sign-up.schema.ts
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()` they are **not** registered via `this.component()`.
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 AUTHENTICATE_OPTIONS = '@app/authenticate/options';
114
- static readonly JWT_OPTIONS = '@app/authenticate/jwt/options';
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]` or `@app/[component]/[sub-feature]/[name]`
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 { Context } from 'hono';
138
- import { AnyObject, ValueOrPromise } from '@venizia/ignis-helpers';
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
- jwtOptions?: IJWTTokenServiceOptions;
143
- basicOptions?: IBasicTokenServiceOptions;
144
- restOptions?: {
145
- useAuthController?: boolean;
146
- controllerOpts?: TDefineAuthControllerOpts;
147
- };
157
+ restOptions?: TAuthenticationRestOptions;
158
+ jwtOptions?: TJWTTokenServiceOptions;
159
+ basicOptions?: TBasicTokenServiceOptions;
148
160
  }
149
161
 
150
- // Service options interface
151
- export interface IJWTTokenServiceOptions {
152
- jwtSecret: string;
153
- applicationSecret: string;
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
- SIRQ = AnyObject,
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: Context, opts: SIRQ): Promise<SIRS>;
163
- signUp(context: Context, opts: SIRQ): Promise<SIRS>;
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: string;
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/swagger/common/constants.ts
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 but only if they are not already bound. Defaults to `{ enable: false }`. |
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 prevents `configure()` from running more than once. |
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 skips if already configured. |
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`. Import it directly from `@venizia/ignis/components/controller/grpc` if needed.
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 { AuthenticateBindingKeys, IAuthenticateOptions, IBasicTokenServiceOptions, IJWTTokenServiceOptions } from './common';
505
- import { BasicTokenService, JWTTokenService } from './services';
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.AUTHENTICATE_OPTIONS]: Binding.bind<IAuthenticateOptions>({
524
- key: AuthenticateBindingKeys.AUTHENTICATE_OPTIONS,
525
- }).toValue(DEFAULT_OPTIONS),
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
- // Validate at least one auth option is provided
531
- private validateOptions(opts: IAuthenticateOptions): void {
532
- if (!opts.jwtOptions && !opts.basicOptions) {
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
- // Configure JWT authentication if jwtOptions is provided
540
- private defineJWTAuth(opts: IAuthenticateOptions): void {
541
- if (!opts.jwtOptions) return;
542
-
543
- this.application
544
- .bind<IJWTTokenServiceOptions>({ key: AuthenticateBindingKeys.JWT_OPTIONS })
545
- .toValue(opts.jwtOptions);
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
- this.application.controller(defineAuthController(opts.restOptions.controllerOpts));
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
- override binding(): ValueOrPromise<void> {
574
- const options = this.application.get<IAuthenticateOptions>({
575
- key: AuthenticateBindingKeys.AUTHENTICATE_OPTIONS,
589
+ const restOptions = this.application.get<TAuthenticationRestOptions>({
590
+ key: AuthenticateBindingKeys.REST_OPTIONS,
591
+ isOptional: true,
576
592
  });
577
593
 
578
- this.validateOptions(options);
579
- this.defineJWTAuth(options);
580
- this.defineBasicAuth(options);
581
- this.defineControllers(options);
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: opt.controller,
602
- storage: opt.storage,
603
- helper: opt.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
- '[binding] Asset storage bound | Key: %s | Type: %s',
635
+ `[binding] Asset storage is bound | Key: %s | Storage type: %s | UseMetaLink: %s`,
609
636
  key,
610
- opt.storage,
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
- Some components skip `initDefault` and assign `this.bindings` directly in the constructor body:
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
- // src/components/swagger/component.ts
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: SwaggerComponent.name });
653
+ super({ scope: CustomComponent.name });
627
654
 
628
655
  this.bindings = {
629
- [SwaggerBindingKeys.SWAGGER_OPTIONS]: Binding.bind<ISwaggerOptions>({
630
- key: SwaggerBindingKeys.SWAGGER_OPTIONS,
631
- }).toValue(DEFAULT_SWAGGER_OPTIONS),
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, configure OpenAPI doc endpoint, UI endpoint, etc.
663
+ // Read options, then wire the component's routes/services.
637
664
  }
638
665
  }
639
666
  ```
640
667
 
641
- In this pattern, `initDefault` defaults to `{ enable: false }`, so the bindings are defined but not auto-registered. The component manages its own option reading and setup in `binding()`.
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
- | **SwaggerComponent** | 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. |
652
- | **AuthenticateComponent** | JWT and/or Basic auth strategies. Optional auth controller (`signIn`/`signUp`). Token services (`JWTTokenService`, `BasicTokenService`). |
653
- | **AuthorizationComponent** | Casbin-based RBAC, permission mapping, `authorize()` middleware. |
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/components/static-asset` | File upload/download CRUD, MinIO/Disk storage. |
661
- | **MailComponent** | `@venizia/ignis/components/mail` | Nodemailer/Mailgun transporters, Direct/BullMQ/InternalQueue executors. |
662
- | **SocketIOComponent** | `@venizia/ignis/components/socket-io` | Socket.IO server with Redis adapter for horizontal scaling. |
663
- | **WebSocketComponent** | `@venizia/ignis/components/websocket` | WebSocket support. |
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<ISwaggerOptions>>({
723
- key: SwaggerBindingKeys.SWAGGER_OPTIONS,
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: ISwaggerOptions = {
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 no need to add your own |
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/swagger) - API documentation
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:**