@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
@@ -1,6 +1,6 @@
1
1
  # Troubleshooting Tips
2
2
 
3
- Common issues and their solutions when building Ignis applications.
3
+ Common issues and their solutions when building IGNIS applications.
4
4
 
5
5
  ## 1. Application Fails to Start
6
6
 
@@ -31,8 +31,9 @@ lsof -ti:3000 | xargs kill -9
31
31
  ```typescript
32
32
  // In application.ts config
33
33
  export const appConfigs: IApplicationConfigs = {
34
+ path: { base: '/api', isStrict: true },
34
35
  debug: {
35
- showRoutes: process.env.NODE_ENV !== 'production',
36
+ shouldShowRoutes: process.env.NODE_ENV !== 'production',
36
37
  },
37
38
  };
38
39
  ```
@@ -90,8 +91,8 @@ class UserService {
90
91
  // Output: [UserService-createUser] Creating user: {...}
91
92
 
92
93
  try {
93
- const user = await this.userRepo.create({ data });
94
- this.logger.for('createUser').info('User created: %s', user.id);
94
+ const user = await this.userRepository.create({ data });
95
+ this.logger.for('createUser').info('User created: %s', user.data.id);
95
96
  return user;
96
97
  } catch (error) {
97
98
  this.logger.for('createUser').error('Failed: %s', error);
@@ -122,21 +123,19 @@ cat .env | grep APP_ENV
122
123
 
123
124
  ## 6. Request ID Tracking
124
125
 
125
- Every request in Ignis is automatically assigned a unique `requestId` for log correlation. The `RequestSpyMiddleware` logs this ID at the start and end of each request.
126
+ Every request in IGNIS is automatically assigned a unique `requestId` for log correlation (via `RequestTrackerComponent`, which registers Hono's `requestId()` middleware plus a request-spy middleware). The spy middleware logs this ID when a request starts (`[=>]`) and finishes (`[<=]`).
126
127
 
127
128
  **Log output format:**
128
129
  ```
129
- [spy][abc123] START | Handling Request | forwardedIp: 192.168.1.1 | path: /api/users | method: GET
130
- [spy][abc123] DONE | Handling Request | forwardedIp: 192.168.1.1 | path: /api/users | method: GET | Took: 45.2 (ms)
130
+ [SpyMW] [abc123][192.168.1.1][=>] GET /api/users | query: {}
131
+ [SpyMW] [abc123][192.168.1.1][<=] GET /api/users | Took: 45.20 (ms)
131
132
  ```
132
133
 
133
134
  **Access request ID in handlers:**
134
135
  ```typescript
135
- import { RequestSpyMiddleware } from '@venizia/ignis';
136
-
137
- // Inside a controller method
136
+ // Inside a controller method - 'requestId' is the Hono request-id context variable
138
137
  async getUser(c: Context) {
139
- const requestId = c.get(RequestSpyMiddleware.REQUEST_ID_KEY);
138
+ const requestId = c.get('requestId');
140
139
  this.logger.info('[%s] Processing user request', requestId);
141
140
  // ...
142
141
  }
@@ -148,53 +147,54 @@ async getUser(c: Context) {
148
147
  grep "abc123" logs/app.log
149
148
 
150
149
  # Extract request timing
151
- grep "\[spy\]\[abc123\]" logs/app.log
150
+ grep "\[abc123\]" logs/app.log | grep "Took:"
152
151
  ```
153
152
 
154
153
  **Why this matters:**
155
154
  - Correlate logs across services in distributed systems
156
155
  - Debug specific user issues by their request ID
157
- - Measure request duration from START to DONE timestamps
156
+ - Measure request duration from the `[=>]` / `[<=]` log pair
158
157
 
159
158
  ## 7. Validation Error Debugging
160
159
 
161
- When Zod validation fails, Ignis returns a structured error response. Understanding this format helps debug client-side issues.
160
+ When Zod validation fails, IGNIS returns a structured error response. Understanding this format helps debug client-side issues.
162
161
 
163
- **Error response structure:**
162
+ **Error response structure** (top-level `message`/`messageCode` come from the first issue; the fallback message is `ValidationError`):
164
163
  ```json
165
164
  {
166
165
  "statusCode": 422,
167
- "message": "ValidationError",
166
+ "message": "Invalid email address",
167
+ "messageCode": "invalid_format",
168
168
  "requestId": "abc123",
169
169
  "details": {
170
+ "url": "http://localhost:3000/api/users",
171
+ "path": "/api/users",
170
172
  "cause": [
171
173
  {
172
174
  "path": "email",
173
- "message": "Invalid email",
174
- "code": "invalid_string",
175
- "expected": "email",
176
- "received": "string"
175
+ "message": "Invalid email address",
176
+ "code": "invalid_format"
177
177
  }
178
178
  ]
179
179
  }
180
180
  }
181
181
  ```
182
182
 
183
- **Common validation error codes:**
183
+ **Common validation error codes (Zod v4):**
184
184
 
185
185
  | Code | Meaning | Example |
186
186
  |------|---------|---------|
187
187
  | `invalid_type` | Wrong data type | Expected `number`, got `string` |
188
- | `invalid_string` | String format invalid | Invalid email or UUID format |
188
+ | `invalid_format` | String format invalid | Invalid email or UUID format |
189
189
  | `too_small` | Value below minimum | String shorter than min length |
190
190
  | `too_big` | Value above maximum | Number exceeds max value |
191
- | `invalid_enum_value` | Value not in enum | Status must be 'ACTIVE' or 'INACTIVE' |
191
+ | `invalid_value` | Value not in enum/literal | Status must be 'ACTIVE' or 'INACTIVE' |
192
192
  | `unrecognized_keys` | Extra fields in request | Strict schema rejects unknown fields |
193
193
 
194
194
  **Debugging tips:**
195
195
 
196
196
  1. **Check the `path` field** - Shows which field failed validation
197
- 2. **Compare `expected` vs `received`** - Identifies type mismatches
197
+ 2. **Compare `expected` vs `received`** - Present on `invalid_type` issues, identifies type mismatches
198
198
  3. **Review schema definition** - Ensure client sends correct format
199
199
 
200
200
  **Example: Debugging nested validation errors:**
@@ -1,13 +1,16 @@
1
- # Swagger/OpenAPI
1
+ # API Reference
2
2
 
3
3
  Automatic interactive API documentation generation using OpenAPI specifications, powered by Scalar or Swagger UI.
4
4
 
5
+ > [!NOTE] Renamed from SwaggerComponent
6
+ > Swagger UI is just one of the pluggable UI providers, so the component carries a vendor-neutral name. `SwaggerComponent`, `ISwaggerOptions`, and `SwaggerBindingKeys` remain available as deprecated aliases - existing applications keep working unchanged.
7
+
5
8
  ## Quick Reference
6
9
 
7
10
  | Item | Value |
8
11
  |------|-------|
9
12
  | **Package** | `@venizia/ignis` |
10
- | **Class** | `SwaggerComponent` |
13
+ | **Class** | `ApiReferenceComponent` |
11
14
  | **UI Factory** | `UIProviderFactory` |
12
15
  | **Runtimes** | Both |
13
16
 
@@ -18,8 +21,8 @@ Automatic interactive API documentation generation using OpenAPI specifications,
18
21
 
19
22
  #### Import Paths
20
23
  ```typescript
21
- import { SwaggerComponent, SwaggerBindingKeys, UIProviderFactory } from '@venizia/ignis';
22
- import type { ISwaggerOptions, IUIProvider, IUIConfig, IGetProviderParams } from '@venizia/ignis';
24
+ import { ApiReferenceComponent, ApiReferenceBindingKeys, UIProviderFactory } from '@venizia/ignis';
25
+ import type { IApiReferenceOptions, IUIProvider, IUIConfig, IGetProviderParams } from '@venizia/ignis';
23
26
  ```
24
27
 
25
28
  ## Setup
@@ -30,10 +33,10 @@ Skip this step to use the defaults (Scalar UI at `/doc/explorer`). To customize:
30
33
 
31
34
  ```typescript
32
35
  // In your Application class's preConfigure method (src/application.ts)
33
- import { SwaggerBindingKeys, ISwaggerOptions } from '@venizia/ignis';
36
+ import { ApiReferenceBindingKeys, IApiReferenceOptions } from '@venizia/ignis';
34
37
 
35
- this.bind<ISwaggerOptions>({
36
- key: SwaggerBindingKeys.SWAGGER_OPTIONS,
38
+ this.bind<IApiReferenceOptions>({
39
+ key: ApiReferenceBindingKeys.API_REFERENCE_OPTIONS,
37
40
  }).toValue({
38
41
  restOptions: {
39
42
  base: { path: '/doc' },
@@ -50,12 +53,12 @@ this.bind<ISwaggerOptions>({
50
53
 
51
54
  ```typescript
52
55
  // src/application.ts
53
- import { SwaggerComponent, BaseApplication, ValueOrPromise } from '@venizia/ignis';
56
+ import { ApiReferenceComponent, BaseApplication, ValueOrPromise } from '@venizia/ignis';
54
57
 
55
58
  export class Application extends BaseApplication {
56
59
  preConfigure(): ValueOrPromise<void> {
57
60
  // ...
58
- this.component(SwaggerComponent);
61
+ this.component(ApiReferenceComponent);
59
62
  }
60
63
  }
61
64
  ```
@@ -89,7 +92,7 @@ export class HelloController extends BaseRestController {
89
92
  },
90
93
  },
91
94
  handler: (c) => {
92
- return c.json({ message: 'Hello, `Ignis`!' }, HTTP.ResultCodes.RS_2.Ok);
95
+ return c.json({ message: 'Hello, `IGNIS`!' }, HTTP.ResultCodes.RS_2.Ok);
93
96
  },
94
97
  });
95
98
  }
@@ -116,9 +119,9 @@ export class HelloController extends BaseRestController {
116
119
  > [!NOTE]
117
120
  > The `explorer.servers` field is auto-populated only when empty. If you provide `explorer.servers` with at least one entry, the component preserves your values. When no servers are configured, it creates a default entry from `application.getServerAddress()` plus the application base path.
118
121
 
119
- #### ISwaggerOptions -- Full Reference
122
+ #### IApiReferenceOptions -- Full Reference
120
123
  ```typescript
121
- export interface ISwaggerOptions {
124
+ export interface IApiReferenceOptions {
122
125
  restOptions: {
123
126
  base: { path: string };
124
127
  doc: { path: string };
@@ -183,9 +186,9 @@ This interface is exported for use when building custom tooling around the `UIPr
183
186
 
184
187
  ### Component Lifecycle
185
188
 
186
- The `SwaggerComponent` executes the following during `binding()`:
189
+ The `ApiReferenceComponent` executes the following during `binding()`:
187
190
 
188
- 1. **Resolve options** -- reads `SwaggerBindingKeys.SWAGGER_OPTIONS` from DI using `application.get()` with `isOptional: true`, falls back to `DEFAULT_SWAGGER_OPTIONS` via the `??` operator if no binding exists
191
+ 1. **Resolve options** -- reads `ApiReferenceBindingKeys.API_REFERENCE_OPTIONS` from DI using `application.get()` with `isOptional: true`, then deep-merges what it finds over `DEFAULT_API_REFERENCE_OPTIONS` group by group, so an application that overrides one path keeps the defaults for the rest
189
192
  2. **Overwrite info** -- unconditionally reads `package.json` via `application.getAppInfo()` and overwrites `explorer.info` with `{ title: appInfo.name, version: appInfo.version, description: appInfo.description, contact: appInfo.author }`
190
193
  3. **Auto-detect servers** -- if `explorer.servers` is empty or unset, creates one entry from `http://` + `application.getServerAddress()` + `configs.path.base`
191
194
  4. **Normalize paths** -- all path segments (`base.path`, `doc.path`, `ui.path`) are normalized to ensure a leading `/` is present, handling both `/path` and `path` inputs
@@ -201,7 +204,7 @@ The `SwaggerComponent` executes the following during `binding()`:
201
204
 
202
205
  | Component | Class | Role |
203
206
  |-----------|-------|------|
204
- | **SwaggerComponent** | `extends BaseComponent` | Orchestrates binding, overwrites OpenAPI metadata from `package.json` |
207
+ | **ApiReferenceComponent** | `extends BaseComponent` | Orchestrates binding, overwrites OpenAPI metadata from `package.json` |
205
208
  | **UIProviderFactory** | `extends MemoryStorageHelper` (singleton) | Registry for UI providers, validates and instantiates |
206
209
  | **SwaggerUIProvider** | `implements IUIProvider` | Renders Swagger UI via `@hono/swagger-ui` |
207
210
  | **ScalarUIProvider** | `implements IUIProvider` | Renders Scalar UI via `@scalar/hono-api-reference` |
@@ -314,24 +317,30 @@ This ensures routes using `authStrategies: ['jwt']` or `authStrategies: ['basic'
314
317
 
315
318
  | Key | Constant | Type | Required | Default |
316
319
  |-----|----------|------|----------|---------|
317
- | `@app/swagger/options` | `SwaggerBindingKeys.SWAGGER_OPTIONS` | `ISwaggerOptions` | No | See below |
320
+ | `@app/api-reference/options` | `ApiReferenceBindingKeys.API_REFERENCE_OPTIONS` | `IApiReferenceOptions` | No | See below |
321
+
322
+ The deprecated `SwaggerBindingKeys.SWAGGER_OPTIONS` still resolves - it is an alias whose **value** is that same `'@app/api-reference/options'` string. There is no binding under the literal `'@app/swagger/options'`; binding that raw string does nothing.
318
323
 
319
- The `SwaggerComponent` constructor creates a default binding using the `Binding` fluent API:
324
+ The constructor registers the default through `super()`, so the binding is in the container from the start:
320
325
 
321
326
  ```typescript
322
- this.bindings = {
323
- [SwaggerBindingKeys.SWAGGER_OPTIONS]: Binding.bind<ISwaggerOptions>({
324
- key: SwaggerBindingKeys.SWAGGER_OPTIONS,
325
- }).toValue(DEFAULT_SWAGGER_OPTIONS),
326
- };
327
+ super({
328
+ scope: ApiReferenceComponent.name,
329
+ initDefault: { enable: true, container: application },
330
+ bindings: {
331
+ [ApiReferenceBindingKeys.API_REFERENCE_OPTIONS]: Binding.bind<IApiReferenceOptions>({
332
+ key: ApiReferenceBindingKeys.API_REFERENCE_OPTIONS,
333
+ }).toValue(DEFAULT_API_REFERENCE_OPTIONS),
334
+ },
335
+ });
327
336
  ```
328
337
 
329
- Note that unlike `HealthCheckComponent`, `SwaggerComponent` does not pass `initDefault: { enable: true, container: application }` to `BaseComponent`. The default bindings stored in `this.bindings` are not automatically registered into the DI container. Instead, the `binding()` method reads from the container with `isOptional: true` and falls back to `DEFAULT_SWAGGER_OPTIONS` via the `??` operator.
338
+ `binding()` then reads the key back with `isOptional: true` and **deep-merges** whatever the application bound over the defaults, group by group (`base`, `doc`, `ui`, `explorer`) - so overriding one path does not wipe the others. The merge builds a fresh `explorer` object per application; mutating the bound one would leak this application's info into every later application in the same process.
330
339
 
331
340
  **Default value:**
332
341
 
333
342
  ```typescript
334
- const DEFAULT_SWAGGER_OPTIONS: ISwaggerOptions = {
343
+ const DEFAULT_API_REFERENCE_OPTIONS: IApiReferenceOptions = {
335
344
  restOptions: {
336
345
  base: { path: '/doc' },
337
346
  doc: { path: '/openapi.json' },
@@ -349,7 +358,7 @@ const DEFAULT_SWAGGER_OPTIONS: ISwaggerOptions = {
349
358
  ```
350
359
 
351
360
  > [!NOTE]
352
- > The `explorer.info` values in `DEFAULT_SWAGGER_OPTIONS` are never used at runtime because `binding()` unconditionally overwrites `explorer.info` with data from `package.json`. They exist only as structural defaults.
361
+ > The `explorer.info` values in `DEFAULT_API_REFERENCE_OPTIONS` are never used at runtime because `binding()` unconditionally overwrites `explorer.info` with data from `package.json`. They exist only as structural defaults.
353
362
 
354
363
  ### Type Definitions
355
364
 
@@ -401,8 +410,8 @@ Returns the raw OpenAPI JSON specification generated from all registered control
401
410
  **Fix:** Use a valid UI type:
402
411
 
403
412
  ```typescript
404
- this.bind<ISwaggerOptions>({
405
- key: SwaggerBindingKeys.SWAGGER_OPTIONS,
413
+ this.bind<IApiReferenceOptions>({
414
+ key: ApiReferenceBindingKeys.API_REFERENCE_OPTIONS,
406
415
  }).toValue({
407
416
  restOptions: {
408
417
  base: { path: '/doc' },
@@ -439,17 +448,17 @@ this.defineRoute({
439
448
 
440
449
  **Cause:** The `UIProviderFactory.getProvider()` was called with a type that has not been registered. This typically happens if the component binding phase failed silently.
441
450
 
442
- **Fix:** Ensure the `SwaggerComponent` is registered in `preConfigure()` and that no errors occur during its `binding()` phase. Check the application logs for warnings from `UIProviderFactory`.
451
+ **Fix:** Ensure the `ApiReferenceComponent` is registered in `preConfigure()` and that no errors occur during its `binding()` phase. Check the application logs for warnings from `UIProviderFactory`.
443
452
 
444
453
  ### OpenAPI spec missing authentication schemes
445
454
 
446
- **Cause:** The `SwaggerComponent` auto-registers JWT and Basic security schemes. If the `AuthenticationComponent` is not registered, authenticated routes will not show auth UI in the documentation.
455
+ **Cause:** The `ApiReferenceComponent` auto-registers JWT and Basic security schemes. If the `AuthenticationComponent` is not registered, authenticated routes will not show auth UI in the documentation.
447
456
 
448
- **Fix:** Register `AuthenticationComponent` before `SwaggerComponent` in `preConfigure()` to ensure auth strategies are available when the Swagger component configures security schemes.
457
+ **Fix:** Register `AuthenticationComponent` before `ApiReferenceComponent` in `preConfigure()` to ensure auth strategies are available when the Swagger component configures security schemes.
449
458
 
450
459
  ### explorer.info values not matching custom configuration
451
460
 
452
- **Cause:** The `SwaggerComponent` unconditionally overwrites `explorer.info` with values from `package.json` during its `binding()` phase. Any values you set in `explorer.info` via the DI binding are discarded.
461
+ **Cause:** The `ApiReferenceComponent` unconditionally overwrites `explorer.info` with values from `package.json` during its `binding()` phase. Any values you set in `explorer.info` via the DI binding are discarded.
453
462
 
454
463
  **Fix:** Update your project's `package.json` fields (`name`, `version`, `description`, `author`) to control what appears in the API documentation info section. The component reads these via `application.getAppInfo()`.
455
464
 
@@ -91,7 +91,7 @@ The `AuthenticateComponent` uses five methods during its `binding()` lifecycle (
91
91
  | Method | Purpose |
92
92
  |--------|---------|
93
93
  | `defineJWSAuth(opts)` | Validates JWS secrets (rejects falsy values and `'unknown_secret'`), validates `getTokenExpiresFn`, binds `IJWSTokenServiceOptions` to `JWT_OPTIONS`, registers `JWSTokenService`. |
94
- | `defineJWKSAuth(opts)` | Switches on `mode`: **Issuer** validates keys, format, kid, getTokenExpiresFn; binds to `JWKS_OPTIONS`; registers `JWKSIssuerTokenService` + `JWKSController`. **Verifier** validates jwksUrl; binds to `JWKS_OPTIONS`; registers `JWKSVerifierTokenService`. |
94
+ | `defineJWKSAuth(opts)` | Switches on `mode`: **Issuer** - validates keys, format, kid, getTokenExpiresFn; binds to `JWKS_OPTIONS`; registers `JWKSIssuerTokenService` + `JWKSController`. **Verifier** - validates jwksUrl; binds to `JWKS_OPTIONS`; registers `JWKSVerifierTokenService`. |
95
95
  | `defineBasicAuth(opts)` | Validates `verifyCredentials` callback presence, binds `BasicTokenService` as a service. Logs debug if skipped. |
96
96
  | `defineControllers(opts)` | Requires `jwtOptions` when `useAuthController: true`. Calls `defineAuthController()` factory and registers the generated controller. |
97
97
  | `defineOAuth2()` | **Public** stub method -- not yet implemented. Called during `binding()` but performs no action. |
@@ -133,8 +133,8 @@ AuthenticationStrategyRegistry.getInstance().register({
133
133
  **Middleware creation:**
134
134
 
135
135
  The `authenticate()` function returns a Hono middleware that:
136
- 1. Checks if `Authentication.SKIP_AUTHENTICATION` is set on context if true, skips entirely (logs debug)
137
- 2. Checks if `Authentication.CURRENT_USER` is already set on context if true, skips (already authenticated)
136
+ 1. Checks if `Authentication.SKIP_AUTHENTICATION` is set on context - if true, skips entirely (logs debug)
137
+ 2. Checks if `Authentication.CURRENT_USER` is already set on context - if true, skips (already authenticated)
138
138
  3. Reads `strategies` and `mode` from the provided options
139
139
  4. Executes strategies based on mode (`any` or `all`)
140
140
  5. On success, sets `Authentication.CURRENT_USER` and `Authentication.AUDIT_USER_ID` on context
@@ -179,7 +179,7 @@ export const authenticate = (opts: { strategies: string[]; mode?: TAuthMode }) =
179
179
  This is the primary export for creating auth middleware. It creates an `AuthenticationProvider` instance and calls `.value()` to get the middleware factory. The provider uses `AuthenticationStrategyRegistry.getInstance()` internally to resolve strategies.
180
180
 
181
181
  > [!NOTE]
182
- > In `all` mode, the **first** strategy's user payload is used as the identity source all strategies must succeed but the first one wins for identity. If every strategy passes but the first user payload has no `userId`, the middleware throws a `401` with message `"Failed to identify authenticated user!"`. The `any` mode **discards errors** from each failing strategy (logs at debug level) and only throws after all strategies are exhausted.
182
+ > In `all` mode, the **first** strategy's user payload is used as the identity source - all strategies must succeed but the first one wins for identity. If every strategy passes but the first user payload has no `userId`, the middleware throws a `401` with message `"Failed to identify authenticated user!"`. The `any` mode **discards errors** from each failing strategy (logs at debug level) and only throws after all strategies are exhausted.
183
183
 
184
184
  ## Service Class Hierarchy
185
185
 
@@ -259,8 +259,8 @@ Base class for all Bearer token services. Extends `BaseService`. Generic on <cod
259
259
  |--------|-----------|-------------|
260
260
  | `configurePayloadEncryption` | <code v-pre>(opts: { aesAlgorithm?: AESAlgorithmType; applicationSecret?: string; fieldCodecs?: IPayloadFieldCodec[] }) =&gt; void</code> | Configures optional AES encryption and field codecs. Codecs are converted to a Map keyed by `codec.key` for O(1) lookup. |
261
261
  | `extractCredentials` | <code v-pre>(context: TContext&lt;E, string&gt;) =&gt; { type: string; token: string }</code> | Extracts Bearer token from Authorization header |
262
- | `verify` | <code v-pre>(opts: { type: string; token: string }) =&gt; Promise&lt;IJWTTokenPayload&gt;</code> | Template method calls `doVerify()` |
263
- | `generate` | <code v-pre>(opts: { payload: IJWTTokenPayload; getTokenExpiresFn?: TGetTokenExpiresFn }) =&gt; Promise&lt;string&gt;</code> | Template method calls `getSigner()` + `getSigningKey()` |
262
+ | `verify` | <code v-pre>(opts: { type: string; token: string }) =&gt; Promise&lt;IJWTTokenPayload&gt;</code> | Template method - calls `doVerify()` |
263
+ | `generate` | <code v-pre>(opts: { payload: IJWTTokenPayload; getTokenExpiresFn?: TGetTokenExpiresFn }) =&gt; Promise&lt;string&gt;</code> | Template method - calls `getSigner()` + `getSigningKey()` |
264
264
  | `serializeField` | <code v-pre>(opts: { key: string; value: any }) =&gt; string</code> | Serializes a single field: codec → `JSON.stringify` fallback |
265
265
  | `deserializeField` | <code v-pre>(opts: { key: string; value: string }) =&gt; any</code> | Deserializes a single field: codec → `JSON.parse` fallback |
266
266
  | `encryptPayload` | <code v-pre>(payload: IJWTTokenPayload) =&gt; Record&lt;string, any&gt;</code> | AES-encrypts non-standard JWT fields using `serializeField`. Returns payload unchanged if AES not configured. |
@@ -421,17 +421,17 @@ constructor(
421
421
  protected options: IJWKSIssuerOptions,
422
422
  ) {
423
423
  // Calls configurePayloadEncryption({ aesAlgorithm, applicationSecret })
424
- // Keys are NOT loaded here loaded lazily via ensureInitialized()
424
+ // Keys are NOT loaded here - loaded lazily via ensureInitialized()
425
425
  }
426
426
  ```
427
427
 
428
428
  ### Initialization Flow
429
429
 
430
430
  The `initialize()` method:
431
- 1. **Resolves key content** reads from file (`readFile` from `node:fs/promises`) or uses inline text, based on `keys.driver`
432
- 2. **Parses key material** imports keys using `importPKCS8`/`importSPKI` (PEM format) or `importJWK` (JWK format), based on `keys.format`
433
- 3. **Exports public JWK** calls `exportJWK()` and adds `kid`, `alg`, `use: 'sig'` metadata
434
- 4. **Caches JWKS** stores `{ keys: [publicJWK] }` for the `/certs` endpoint
431
+ 1. **Resolves key content** - reads from file (`readFile` from `node:fs/promises`) or uses inline text, based on `keys.driver`
432
+ 2. **Parses key material** - imports keys using `importPKCS8`/`importSPKI` (PEM format) or `importJWK` (JWK format), based on `keys.format`
433
+ 3. **Exports public JWK** - calls `exportJWK()` and adds `kid`, `alg`, `use: 'sig'` metadata
434
+ 4. **Caches JWKS** - stores `{ keys: [publicJWK] }` for the `/certs` endpoint
435
435
  5. **Sets `initialized = true`**
436
436
 
437
437
  ### Overridden Methods
@@ -447,8 +447,8 @@ The `initialize()` method:
447
447
 
448
448
  | Method | Signature | Description |
449
449
  |--------|-----------|-------------|
450
- | `getJWKS` | `() => { keys: JWK[] }` | Synchronous returns cached JWKS. Throws if not yet initialized. |
451
- | `getJWKSAsync` | `() => Promise<{ keys: JWK[] }>` | Async calls `ensureInitialized()` first, then returns JWKS. |
450
+ | `getJWKS` | `() => { keys: JWK[] }` | Synchronous - returns cached JWKS. Throws if not yet initialized. |
451
+ | `getJWKSAsync` | `() => Promise<{ keys: JWK[] }>` | Async - calls `ensureInitialized()` first, then returns JWKS. |
452
452
 
453
453
  ### Internal Methods
454
454
 
@@ -504,7 +504,7 @@ constructor(
504
504
  protected options: IJWKSVerifierOptions,
505
505
  ) {
506
506
  // Calls configurePayloadEncryption({ aesAlgorithm, applicationSecret })
507
- // Remote JWKS is NOT fetched here fetched lazily via ensureInitialized()
507
+ // Remote JWKS is NOT fetched here - fetched lazily via ensureInitialized()
508
508
  }
509
509
  ```
510
510
 
@@ -520,13 +520,13 @@ The `initialize()` method:
520
520
  | Method | Behavior |
521
521
  |--------|----------|
522
522
  | `doVerify(token)` | Calls `ensureInitialized()`, then `jwtVerify(token, this.jwksVerifier!)`, then `this.decryptPayload()` |
523
- | `getSigner(opts)` | Throws verifier mode cannot sign tokens |
524
- | `getSigningKey()` | Throws verifier mode cannot sign tokens |
525
- | `getDefaultTokenExpiresFn()` | Throws verifier mode has no token expiry |
523
+ | `getSigner(opts)` | Throws - verifier mode cannot sign tokens |
524
+ | `getSigningKey()` | Throws - verifier mode cannot sign tokens |
525
+ | `getDefaultTokenExpiresFn()` | Throws - verifier mode has no token expiry |
526
526
 
527
527
  ## JWKSController
528
528
 
529
- Serves the JWKS endpoint (default path `/certs`). This endpoint is **intentionally unauthenticated** it serves the public keys needed by external verifiers.
529
+ Serves the JWKS endpoint (default path `/certs`). This endpoint is **intentionally unauthenticated** - it serves the public keys needed by external verifiers.
530
530
 
531
531
  **File:** `packages/core/src/components/auth/authenticate/controllers/jwks/controller.ts`
532
532
 
@@ -689,7 +689,7 @@ function defineAuthController(opts: TDefineAuthControllerOpts): typeof AuthContr
689
689
  ```
690
690
 
691
691
  > [!NOTE]
692
- > The factory also exports `JWTTokenPayloadSchema`, a Zod schema used for the `/who-am-i` response validation.
692
+ > The factory also exports `JWTTokenPayloadSchema`, a Zod schema used for the `/who-am-i` response validation. For `/who-am-i`, it is extended with an optional `userInformation` field that is populated when the request sets `?withUserInformation=true`. The same `getUserInformation` service method backs the dedicated `GET /me` route.
693
693
 
694
694
  **Service resolution:**
695
695
 
@@ -49,7 +49,7 @@ Thrown during `binding()` when validating options and configuring services.
49
49
  | `[defineJWSAuth] getTokenExpiresFn is required` | 400 | `defineJWSAuth` | `getTokenExpiresFn` not provided in JWS options |
50
50
 
51
51
  ::: info applicationSecret is no longer validated
52
- `applicationSecret` was previously required and validated by the component. It is now **optional** omitting it simply disables AES payload encryption.
52
+ `applicationSecret` was previously required and validated by the component. It is now **optional** - omitting it simply disables AES payload encryption.
53
53
  :::
54
54
 
55
55
  #### `defineJWKSAuth` Errors (Issuer Mode)
@@ -104,10 +104,10 @@ Base class errors shared by `JWSTokenService`, `JWKSIssuerTokenService`, and `JW
104
104
  | Error Message | Status | Method | When |
105
105
  |---------------|--------|--------|------|
106
106
  | `[verify] Invalid request token!` | 401 | `verify` | Token value is empty/falsy |
107
- | `[verify] Invalid or expired token` | 401 | `verify` | `doVerify()` threw token is expired, malformed, or signature invalid |
107
+ | `[verify] Invalid or expired token` | 401 | `verify` | `doVerify()` threw - token is expired, malformed, or signature invalid |
108
108
 
109
109
  ::: tip Sanitized error messages
110
- The `verify()` and `generate()` methods use **sanitized error messages** they do NOT include the original `error.message` in the thrown error. The full error is logged at `error` level for debugging but not exposed to clients.
110
+ The `verify()` and `generate()` methods use **sanitized error messages** - they do NOT include the original `error.message` in the thrown error. The full error is logged at `error` level for debugging but not exposed to clients.
111
111
  :::
112
112
 
113
113
  #### `generate` Errors
@@ -150,7 +150,7 @@ Errors thrown during lazy initialization (`ensureInitialized()`) and key operati
150
150
  | <code v-pre>[JWKSIssuerTokenService] Unknown key format: {{format}}</code> | 500 | `parseKeyMaterial` | `keys.format` is not `'pem'` or `'jwk'` |
151
151
 
152
152
  ::: warning File read errors
153
- When using `JWKSKeyDrivers.FILE`, file read errors from `readFile()` propagate as Node.js filesystem errors (e.g., `ENOENT`, `EACCES`). These are **not** wrapped the raw error surfaces during initialization.
153
+ When using `JWKSKeyDrivers.FILE`, file read errors from `readFile()` propagate as Node.js filesystem errors (e.g., `ENOENT`, `EACCES`). These are **not** wrapped - the raw error surfaces during initialization.
154
154
  :::
155
155
 
156
156
  #### Runtime Errors
@@ -208,7 +208,7 @@ The middleware that executes strategies in the configured mode.
208
208
 
209
209
  | Error Message | Status | Method | When |
210
210
  |---------------|--------|--------|------|
211
- | <code v-pre>Authentication failed. Tried strategies: {{strategies}}</code> | 401 | `executeAnyMode` | All strategies failed in `'any'` mode each strategy threw during `authenticate()` |
211
+ | <code v-pre>Authentication failed. Tried strategies: {{strategies}}</code> | 401 | `executeAnyMode` | All strategies failed in `'any'` mode - each strategy threw during `authenticate()` |
212
212
  | `Failed to identify authenticated user!` | 401 | `executeAllMode` | All strategies succeeded in `'all'` mode but the first strategy's `authUser.userId` is falsy |
213
213
  | <code v-pre>Invalid authentication mode &#124; mode: {{mode}}</code> | 500 | `createAuthenticateMiddleware` | `mode` is not `'any'` or `'all'` |
214
214
 
@@ -391,7 +391,7 @@ The built-in `JWKSController` already uses `getJWKSAsync()`, so this error only
391
391
 
392
392
  **Cause:** `generate()` was called on a `JWKSVerifierTokenService`. The verifier mode only has access to public keys (via the remote JWKS URL) and cannot sign tokens.
393
393
 
394
- **Fix:** Token generation should only happen on the **issuer** service. If you need both signing and verification in the same application, use `JWKSModes.ISSUER` the issuer can both sign and verify.
394
+ **Fix:** Token generation should only happen on the **issuer** service. If you need both signing and verification in the same application, use `JWKSModes.ISSUER` - the issuer can both sign and verify.
395
395
 
396
396
  ### "Authentication failed. Tried strategies: jwt, jwks"
397
397
 
@@ -471,7 +471,7 @@ this.bind<TBasicTokenServiceOptions>({ key: AuthenticateBindingKeys.BASIC_OPTION
471
471
 
472
472
  ### "[verify] Invalid or expired token"
473
473
 
474
- **Cause:** Token verification failed. This is a sanitized error the original error (expired, wrong signature, malformed) is logged internally but not exposed to clients.
474
+ **Cause:** Token verification failed. This is a sanitized error - the original error (expired, wrong signature, malformed) is logged internally but not exposed to clients.
475
475
 
476
476
  **Fix:** Check the application logs for the full error. Common causes:
477
477
  - Token has expired (check `exp` claim)
@@ -21,9 +21,9 @@
21
21
  | **JWKSVerifierAuthenticationStrategy** | JWT verification via remote JWKS URL |
22
22
  | **BasicAuthenticationStrategy** | Basic HTTP authentication using `BasicTokenService` |
23
23
  | **AbstractBearerTokenService** | Base class for all Bearer token services (JWS, JWKS Issuer, JWKS Verifier) |
24
- | **JWSTokenService** | Symmetric JWT sign, verify, optional AES encrypt/decrypt |
25
- | **JWKSIssuerTokenService** | Asymmetric JWT sign with private key, verify with public key, serve JWKS endpoint |
26
- | **JWKSVerifierTokenService** | Asymmetric JWT verify-only via remote JWKS URL |
24
+ | **JWSTokenService** | Symmetric JWT - sign, verify, optional AES encrypt/decrypt |
25
+ | **JWKSIssuerTokenService** | Asymmetric JWT - sign with private key, verify with public key, serve JWKS endpoint |
26
+ | **JWKSVerifierTokenService** | Asymmetric JWT - verify-only via remote JWKS URL |
27
27
  | **BasicTokenService** | Extract and verify Basic auth credentials |
28
28
  | **JWKSController** | Serves `/.well-known/jwks.json`-style endpoint at `/certs` |
29
29
  | **IAuthService** | Interface for custom auth implementation (sign-in, sign-up) |
@@ -97,8 +97,8 @@ The authentication module supports two JOSE (JSON Object Signing and Encryption)
97
97
  | `JWKSKeyFormats` | `JWK` | `'jwk'` | JSON Web Key format |
98
98
 
99
99
  Each constants class also provides:
100
- - `SCHEME_SET: Set<string>` set of all valid values
101
- - `isValid(input: string): boolean` check if a value is recognized
100
+ - `SCHEME_SET: Set<string>` - set of all valid values
101
+ - `isValid(input: string): boolean` - check if a value is recognized
102
102
 
103
103
  #### Import Paths
104
104
 
@@ -244,7 +244,7 @@ this.bind<TJWTTokenServiceOptions>({ key: AuthenticateBindingKeys.JWT_OPTIONS })
244
244
  standard: JOSEStandards.JWS,
245
245
  options: {
246
246
  jwtSecret: process.env.APP_ENV_JWT_SECRET,
247
- applicationSecret: process.env.APP_ENV_APPLICATION_SECRET, // Optional enables AES payload encryption
247
+ applicationSecret: process.env.APP_ENV_APPLICATION_SECRET, // Optional - enables AES payload encryption
248
248
  getTokenExpiresFn: () => Number(process.env.APP_ENV_JWT_EXPIRES_IN || 86400),
249
249
  },
250
250
  });
@@ -495,7 +495,7 @@ type TJWTTokenServiceOptions =
495
495
  | { standard: typeof JOSEStandards.JWKS; options: TJWKSTokenServiceOptions };
496
496
  ```
497
497
 
498
- This enables clean TypeScript narrowing once you set `standard: JOSEStandards.JWS`, the `options` field is typed as `IJWSTokenServiceOptions`; with `standard: JOSEStandards.JWKS`, it becomes `TJWKSTokenServiceOptions`.
498
+ This enables clean TypeScript narrowing - once you set `standard: JOSEStandards.JWS`, the `options` field is typed as `IJWSTokenServiceOptions`; with `standard: JOSEStandards.JWKS`, it becomes `TJWKSTokenServiceOptions`.
499
499
 
500
500
  ### JWS Options (IJWSTokenServiceOptions)
501
501
 
@@ -759,16 +759,18 @@ interface IAuthService<
759
759
  CPRS = AnyObject,
760
760
  UIRQ = AnyObject,
761
761
  UIRS = AnyObject,
762
+ RTRS = AnyObject,
762
763
  > {
763
764
  signIn(context: TContext<E>, opts: SIRQ): Promise<SIRS>;
764
765
  signUp(context: TContext<E>, opts: SURQ): Promise<SURS>;
765
766
  changePassword(context: TContext<E>, opts: CPRQ): Promise<CPRS>;
766
767
  getUserInformation?(context: TContext<E>, opts: UIRQ): Promise<UIRS>;
768
+ refreshToken?(context: TContext<E>): Promise<RTRS>;
767
769
  }
768
770
  ```
769
771
 
770
772
  > [!NOTE]
771
- > `IAuthService` is generic on the Hono `Env` type as well as all request/response types. The `getUserInformation` method is optional.
773
+ > `IAuthService` is generic on the Hono `Env` type as well as all request/response types. The `getUserInformation` and `refreshToken` methods are both optional -- the auth controller factory returns a 501 (`core.not_supported`) when an endpoint that depends on one is called but the method is not implemented.
772
774
 
773
775
  #### IJWTTokenPayload -- Full Interface
774
776
  ```typescript