@venizia/ignis-docs 0.0.8-3 → 0.1.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 (213) hide show
  1. package/README.md +7 -7
  2. package/{wiki → content}/best-practices/api-usage-examples.md +15 -12
  3. package/{wiki → content}/best-practices/architectural-patterns.md +70 -78
  4. package/{wiki → content}/best-practices/architecture-decisions.md +91 -60
  5. package/{wiki → content}/best-practices/code-style-standards/advanced-patterns.md +56 -44
  6. package/{wiki → content}/best-practices/code-style-standards/constants-configuration.md +11 -11
  7. package/{wiki → content}/best-practices/code-style-standards/control-flow.md +5 -2
  8. package/{wiki → content}/best-practices/code-style-standards/documentation.md +13 -13
  9. package/{wiki → content}/best-practices/code-style-standards/function-patterns.md +9 -10
  10. package/{wiki → content}/best-practices/code-style-standards/index.md +1 -1
  11. package/{wiki → content}/best-practices/code-style-standards/naming-conventions.md +10 -8
  12. package/{wiki → content}/best-practices/code-style-standards/route-definitions.md +30 -12
  13. package/{wiki → content}/best-practices/code-style-standards/tooling.md +8 -5
  14. package/{wiki → content}/best-practices/code-style-standards/type-safety.md +13 -12
  15. package/{wiki → content}/best-practices/common-pitfalls.md +56 -37
  16. package/{wiki → content}/best-practices/contribution-workflow.md +13 -14
  17. package/{wiki → content}/best-practices/data-modeling.md +44 -20
  18. package/{wiki → content}/best-practices/deployment-strategies.md +28 -27
  19. package/{wiki → content}/best-practices/error-handling.md +48 -24
  20. package/{wiki → content}/best-practices/index.md +5 -5
  21. package/{wiki → content}/best-practices/performance-optimization.md +36 -28
  22. package/{wiki → content}/best-practices/security-guidelines.md +52 -23
  23. package/{wiki → content}/best-practices/testing-strategies.md +65 -51
  24. package/{wiki → content}/best-practices/troubleshooting-tips.md +24 -24
  25. package/{wiki/extensions/components/swagger.md → content/extensions/components/api-reference.md} +40 -31
  26. package/{wiki → content}/extensions/components/authentication/api.md +19 -19
  27. package/{wiki → content}/extensions/components/authentication/errors.md +7 -7
  28. package/{wiki → content}/extensions/components/authentication/index.md +10 -8
  29. package/{wiki → content}/extensions/components/authentication/usage.md +101 -6
  30. package/{wiki → content}/extensions/components/authorization/api.md +45 -25
  31. package/{wiki → content}/extensions/components/authorization/errors.md +6 -6
  32. package/{wiki → content}/extensions/components/authorization/index.md +11 -10
  33. package/{wiki → content}/extensions/components/authorization/usage.md +21 -21
  34. package/{wiki → content}/extensions/components/health-check.md +1 -1
  35. package/{wiki → content}/extensions/components/index.md +5 -5
  36. package/{wiki → content}/extensions/components/mail/errors.md +15 -15
  37. package/{wiki → content}/extensions/components/mail/index.md +1 -2
  38. package/{wiki → content}/extensions/components/mail/usage.md +1 -1
  39. package/{wiki → content}/extensions/components/request-tracker.md +1 -1
  40. package/{wiki → content}/extensions/components/socket-io/api.md +9 -9
  41. package/{wiki → content}/extensions/components/socket-io/errors.md +5 -5
  42. package/{wiki → content}/extensions/components/socket-io/index.md +8 -8
  43. package/{wiki → content}/extensions/components/socket-io/usage.md +1 -1
  44. package/{wiki → content}/extensions/components/static-asset/api.md +17 -4
  45. package/{wiki → content}/extensions/components/static-asset/errors.md +4 -4
  46. package/{wiki → content}/extensions/components/static-asset/index.md +26 -28
  47. package/{wiki → content}/extensions/components/static-asset/usage.md +13 -12
  48. package/{wiki → content}/extensions/components/template/index.md +2 -2
  49. package/{wiki → content}/extensions/components/template/setup-page.md +1 -1
  50. package/{wiki → content}/extensions/components/websocket/api.md +3 -3
  51. package/{wiki → content}/extensions/components/websocket/errors.md +5 -5
  52. package/{wiki → content}/extensions/components/websocket/index.md +5 -5
  53. package/{wiki → content}/extensions/components/websocket/usage.md +3 -3
  54. package/{wiki → content}/extensions/helpers/cron/index.md +2 -2
  55. package/{wiki → content}/extensions/helpers/crypto/index.md +1 -1
  56. package/{wiki → content}/extensions/helpers/env/index.md +27 -12
  57. package/content/extensions/helpers/error/index.md +283 -0
  58. package/{wiki → content}/extensions/helpers/index.md +2 -3
  59. package/{wiki → content}/extensions/helpers/inversion/index.md +15 -7
  60. package/{wiki → content}/extensions/helpers/kafka/examples.md +1 -1
  61. package/{wiki → content}/extensions/helpers/logger/index.md +32 -2
  62. package/{wiki → content}/extensions/helpers/network/index.md +6 -0
  63. package/{wiki → content}/extensions/helpers/queue/index.md +14 -17
  64. package/content/extensions/helpers/redis/index.md +713 -0
  65. package/{wiki → content}/extensions/helpers/socket-io/index.md +14 -10
  66. package/{wiki → content}/extensions/helpers/storage/api.md +44 -8
  67. package/{wiki → content}/extensions/helpers/storage/index.md +43 -7
  68. package/{wiki → content}/extensions/helpers/template/index.md +6 -3
  69. package/{wiki → content}/extensions/helpers/types/index.md +11 -8
  70. package/{wiki → content}/extensions/helpers/websocket/api.md +9 -9
  71. package/{wiki → content}/extensions/helpers/websocket/index.md +7 -7
  72. package/{wiki → content}/extensions/helpers/worker-thread/index.md +2 -2
  73. package/{wiki → content}/extensions/index.md +3 -4
  74. package/{wiki → content}/extensions/src-details/mcp-server.md +18 -24
  75. package/{wiki → content}/guides/core-concepts/application/bootstrapping.md +11 -14
  76. package/{wiki → content}/guides/core-concepts/application/index.md +3 -3
  77. package/{wiki → content}/guides/core-concepts/components.md +19 -10
  78. package/{wiki → content}/guides/core-concepts/dependency-injection.md +6 -3
  79. package/{wiki → content}/guides/core-concepts/grpc-controllers.md +6 -5
  80. package/{wiki → content}/guides/core-concepts/persistent/datasources.md +33 -27
  81. package/{wiki → content}/guides/core-concepts/persistent/index.md +16 -5
  82. package/{wiki → content}/guides/core-concepts/persistent/models.md +24 -20
  83. package/content/guides/core-concepts/persistent/postgres-drivers.md +167 -0
  84. package/{wiki → content}/guides/core-concepts/persistent/repositories.md +40 -23
  85. package/content/guides/core-concepts/persistent/search-meilisearch.md +183 -0
  86. package/content/guides/core-concepts/persistent/search-typesense.md +429 -0
  87. package/{wiki → content}/guides/core-concepts/persistent/transactions.md +61 -25
  88. package/{wiki → content}/guides/core-concepts/rest-controllers.md +12 -9
  89. package/content/guides/core-concepts/services.md +389 -0
  90. package/{wiki → content}/guides/get-started/5-minute-quickstart.md +19 -19
  91. package/{wiki → content}/guides/get-started/philosophy.md +36 -36
  92. package/{wiki → content}/guides/get-started/setup.md +3 -3
  93. package/{wiki → content}/guides/index.md +3 -3
  94. package/content/guides/migrations/redis-helpers-migration.md +177 -0
  95. package/{wiki → content}/guides/migrations/scoped-rbac-migration.md +17 -17
  96. package/content/guides/migrations/unified-connectors-migration.md +113 -0
  97. package/{wiki → content}/guides/reference/glossary.md +19 -12
  98. package/{wiki → content}/guides/reference/mcp-docs-server.md +22 -18
  99. package/{wiki → content}/guides/tutorials/building-a-crud-api.md +30 -33
  100. package/{wiki → content}/guides/tutorials/complete-installation.md +17 -17
  101. package/{wiki → content}/guides/tutorials/ecommerce-api.md +158 -119
  102. package/{wiki → content}/guides/tutorials/realtime-chat.md +176 -130
  103. package/content/guides/tutorials/testing.md +264 -0
  104. package/content/index.md +5 -0
  105. package/content/public/apple-touch-icon.png +0 -0
  106. package/content/public/og-image.png +0 -0
  107. package/content/public/site.webmanifest +11 -0
  108. package/{wiki → content}/references/base/application.md +4 -5
  109. package/{wiki → content}/references/base/bootstrapping.md +18 -5
  110. package/{wiki → content}/references/base/components.md +149 -120
  111. package/content/references/base/connectors.md +178 -0
  112. package/{wiki → content}/references/base/controllers.md +41 -30
  113. package/content/references/base/datasources.md +527 -0
  114. package/{wiki → content}/references/base/dependency-injection.md +34 -22
  115. package/{wiki → content}/references/base/filter-system/application-usage.md +17 -14
  116. package/{wiki → content}/references/base/filter-system/array-operators.md +7 -2
  117. package/{wiki → content}/references/base/filter-system/comparison-operators.md +3 -0
  118. package/{wiki → content}/references/base/filter-system/default-filter.md +89 -71
  119. package/{wiki → content}/references/base/filter-system/fields-order-pagination.md +22 -22
  120. package/{wiki → content}/references/base/filter-system/index.md +6 -3
  121. package/{wiki → content}/references/base/filter-system/json-filtering.md +20 -1
  122. package/{wiki → content}/references/base/filter-system/list-operators.md +1 -1
  123. package/{wiki → content}/references/base/filter-system/logical-operators.md +33 -1
  124. package/{wiki → content}/references/base/filter-system/null-operators.md +30 -1
  125. package/{wiki → content}/references/base/filter-system/quick-reference.md +23 -4
  126. package/{wiki → content}/references/base/filter-system/tips.md +5 -5
  127. package/{wiki → content}/references/base/filter-system/use-cases.md +12 -12
  128. package/{wiki → content}/references/base/grpc-controllers.md +13 -13
  129. package/{wiki → content}/references/base/index.md +24 -12
  130. package/{wiki/references/base/middleware.md → content/references/base/middlewares.md} +205 -24
  131. package/{wiki → content}/references/base/models.md +63 -49
  132. package/{wiki → content}/references/base/providers.md +136 -130
  133. package/{wiki → content}/references/base/repositories/advanced.md +59 -58
  134. package/{wiki → content}/references/base/repositories/index.md +115 -91
  135. package/content/references/base/repositories/mixins.md +99 -0
  136. package/{wiki → content}/references/base/repositories/relations.md +54 -64
  137. package/{wiki → content}/references/base/repositories/soft-deletable.md +31 -30
  138. package/content/references/base/services.md +404 -0
  139. package/{wiki → content}/references/configuration/environment-variables.md +46 -30
  140. package/{wiki → content}/references/configuration/index.md +6 -6
  141. package/{wiki → content}/references/index.md +17 -12
  142. package/{wiki → content}/references/quick-reference.md +65 -106
  143. package/content/references/utilities/crypto.md +98 -0
  144. package/{wiki → content}/references/utilities/index.md +3 -3
  145. package/{wiki → content}/references/utilities/jsx.md +6 -4
  146. package/content/references/utilities/module.md +90 -0
  147. package/{wiki → content}/references/utilities/parse.md +4 -14
  148. package/{wiki → content}/references/utilities/promise.md +9 -7
  149. package/{wiki → content}/references/utilities/schema.md +5 -3
  150. package/dist/mcp-server/common/guards.d.ts +8 -0
  151. package/dist/mcp-server/common/guards.d.ts.map +1 -0
  152. package/dist/mcp-server/common/guards.js +14 -0
  153. package/dist/mcp-server/common/guards.js.map +1 -0
  154. package/dist/mcp-server/common/index.d.ts +1 -0
  155. package/dist/mcp-server/common/index.d.ts.map +1 -1
  156. package/dist/mcp-server/common/index.js +1 -0
  157. package/dist/mcp-server/common/index.js.map +1 -1
  158. package/dist/mcp-server/common/paths.d.ts.map +1 -1
  159. package/dist/mcp-server/common/paths.js +2 -2
  160. package/dist/mcp-server/common/paths.js.map +1 -1
  161. package/dist/mcp-server/helpers/docs.helper.d.ts.map +1 -1
  162. package/dist/mcp-server/helpers/docs.helper.js +4 -2
  163. package/dist/mcp-server/helpers/docs.helper.js.map +1 -1
  164. package/dist/mcp-server/helpers/github.helper.js +1 -1
  165. package/dist/mcp-server/index.js +7 -2
  166. package/dist/mcp-server/index.js.map +1 -1
  167. package/dist/mcp-server/tools/base.tool.d.ts +6 -2
  168. package/dist/mcp-server/tools/base.tool.d.ts.map +1 -1
  169. package/dist/mcp-server/tools/base.tool.js.map +1 -1
  170. package/dist/mcp-server/tools/docs/search-documents.tool.d.ts +1 -1
  171. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
  172. package/dist/mcp-server/tools/github/search-code.tool.d.ts +1 -1
  173. package/dist/mcp-server/tools/github/search-code.tool.d.ts.map +1 -1
  174. package/dist/mcp-server/tools/github/search-code.tool.js +4 -1
  175. package/dist/mcp-server/tools/github/search-code.tool.js.map +1 -1
  176. package/dist/mcp-server/tools/github/verify-dependencies.tool.d.ts.map +1 -1
  177. package/dist/mcp-server/tools/github/verify-dependencies.tool.js +3 -1
  178. package/dist/mcp-server/tools/github/verify-dependencies.tool.js.map +1 -1
  179. package/package.json +12 -12
  180. package/wiki/extensions/helpers/error/index.md +0 -227
  181. package/wiki/extensions/helpers/redis/index.md +0 -488
  182. package/wiki/extensions/helpers/testing/index.md +0 -510
  183. package/wiki/guides/core-concepts/services.md +0 -119
  184. package/wiki/guides/tutorials/testing.md +0 -722
  185. package/wiki/index.md +0 -183
  186. package/wiki/references/base/datasources.md +0 -454
  187. package/wiki/references/base/middlewares.md +0 -590
  188. package/wiki/references/base/repositories/mixins.md +0 -335
  189. package/wiki/references/base/services.md +0 -201
  190. package/wiki/references/utilities/crypto.md +0 -56
  191. package/wiki/references/utilities/module.md +0 -42
  192. /package/{wiki → content}/extensions/components/mail/api.md +0 -0
  193. /package/{wiki → content}/extensions/components/template/api-page.md +0 -0
  194. /package/{wiki → content}/extensions/components/template/errors-page.md +0 -0
  195. /package/{wiki → content}/extensions/components/template/single-page.md +0 -0
  196. /package/{wiki → content}/extensions/components/template/usage-page.md +0 -0
  197. /package/{wiki → content}/extensions/helpers/kafka/admin.md +0 -0
  198. /package/{wiki → content}/extensions/helpers/kafka/consumer.md +0 -0
  199. /package/{wiki → content}/extensions/helpers/kafka/index.md +0 -0
  200. /package/{wiki → content}/extensions/helpers/kafka/producer.md +0 -0
  201. /package/{wiki → content}/extensions/helpers/kafka/schema-registry.md +0 -0
  202. /package/{wiki → content}/extensions/helpers/network/api.md +0 -0
  203. /package/{wiki → content}/extensions/helpers/socket-io/api.md +0 -0
  204. /package/{wiki → content}/extensions/helpers/template/single-page.md +0 -0
  205. /package/{wiki → content}/extensions/helpers/uid/index.md +0 -0
  206. /package/{wiki → content}/guides/core-concepts/components-guide.md +0 -0
  207. /package/{wiki → content}/public/logo.svg +0 -0
  208. /package/{wiki → content}/references/base/filter-system/pattern-matching.md +0 -0
  209. /package/{wiki → content}/references/base/filter-system/range-operators.md +0 -0
  210. /package/{wiki → content}/references/utilities/date.md +0 -0
  211. /package/{wiki → content}/references/utilities/performance.md +0 -0
  212. /package/{wiki → content}/references/utilities/request.md +0 -0
  213. /package/{wiki → content}/references/utilities/statuses.md +0 -0
@@ -1,590 +0,0 @@
1
- ---
2
- title: Middlewares Reference
3
- description: Technical reference for IGNIS built-in middlewares
4
- difficulty: intermediate
5
- lastUpdated: 2026-01-03
6
- ---
7
-
8
- # Middlewares Reference
9
-
10
- IGNIS provides a collection of built-in middlewares for common application needs including error handling, request logging, and favicon serving.
11
-
12
- **Files:**
13
- - `packages/core/src/base/middlewares/*.ts`
14
-
15
- ## Prerequisites
16
-
17
- - [Hono Middleware basics](https://hono.dev/docs/guides/middleware)
18
- - [IGNIS Application basics](./application.md)
19
- - Basic understanding of HTTP request/response lifecycle
20
-
21
- ## Quick Reference
22
-
23
- | Middleware | Purpose | Key Options |
24
- |------------|---------|-------------|
25
- | `appErrorHandler` | Catches and formats application errors | `logger` |
26
- | `notFoundHandler` | Handles 404 Not Found responses | `logger` |
27
- | `RequestSpyMiddleware` | Logs request lifecycle, timing, and parses request body | None |
28
- | `emojiFavicon` | Serves an emoji as favicon | `icon` |
29
-
30
- ## Table of Contents
31
-
32
- - [Error Handler (`appErrorHandler`)](#error-handler-apporerrorhandler)
33
- - [Not Found Handler (`notFoundHandler`)](#not-found-handler-notfoundhandler)
34
- - [Request Spy (`RequestSpyMiddleware`)](#request-spy-requestspymiddleware)
35
- - [Emoji Favicon](#emoji-favicon)
36
- - [Creating Custom Middleware](#creating-custom-middleware)
37
- - [Middleware Order & Priority](#middleware-order--priority)
38
- - [See Also](#see-also)
39
-
40
- ## Built-in Middlewares
41
-
42
- ### Error Handler (`appErrorHandler`)
43
-
44
- The error handler middleware catches all unhandled errors in your application and formats them into consistent JSON responses.
45
-
46
- **File:** `packages/core/src/base/middlewares/app-error/app-error.middleware.ts`
47
-
48
- #### Features
49
-
50
- - **Automatic Error Formatting**: Converts all errors to structured JSON responses
51
- - **ZodError Support**: Validation errors surface a schema-driven `messageCode` and `message` (from `params.code`, else the raw Zod code), with the full per-field list under `details.cause`
52
- - **Database Error Handling**: Returns 400 for SQLSTATE class `22` (data exception) and `23` (integrity) errors, with a fallback message; other classes (e.g. `42` programming errors) stay 500
53
- - **Production-Safe**: Hides stack traces, error causes, DB driver internals (`detail`/`table`/`constraint`), and raw system messages in production
54
- - **Request Tracking**: Includes `requestId` for debugging and tracing
55
- - **Status Code Detection**: Automatically extracts `statusCode` from errors
56
-
57
- #### Usage
58
-
59
- ```typescript
60
- import { appErrorHandler } from '@venizia/ignis';
61
-
62
- const app = new IgnisApplication({
63
- // ...
64
- });
65
-
66
- // Register error handler
67
- app.onError(appErrorHandler({
68
- logger: app.logger
69
- }));
70
- ```
71
-
72
- #### Error Response Format
73
-
74
- **Standard Error:**
75
- ```json
76
- {
77
- "message": "Something went wrong",
78
- "statusCode": 500,
79
- "requestId": "abc123",
80
- "details": {
81
- "url": "http://localhost:3000/api/users",
82
- "path": "/api/users",
83
- "stack": "Error: Something went wrong\n at ...", // development only
84
- "cause": { ... } // development only
85
- }
86
- }
87
- ```
88
-
89
- **Validation Error (ZodError):**
90
-
91
- Top-level `message`/`messageCode` come from the first failing issue — its `params.code` if the schema set one (see below), otherwise its raw Zod code. The full per-field list stays under `details.cause`. If `error.rootKey` is configured, the whole body is wrapped under that key.
92
-
93
- ```json
94
- {
95
- "message": "Invalid email address",
96
- "messageCode": "invalid_type",
97
- "statusCode": 422,
98
- "requestId": "abc123",
99
- "details": {
100
- "url": "http://localhost:3000/api/users",
101
- "path": "/api/users",
102
- "stack": "...", // development only
103
- "cause": [
104
- {
105
- "path": "email",
106
- "message": "Invalid email address",
107
- "code": "invalid_type",
108
- "expected": "string"
109
- }
110
- ]
111
- }
112
- }
113
- ```
114
-
115
- To emit a stable, domain-specific `messageCode`, attach `params.code` to a custom check:
116
-
117
- ```typescript
118
- z.string().refine(isEmail, { message: 'Invalid email address', params: { code: 'user.email.invalid' } });
119
- // → "messageCode": "user.email.invalid"
120
- ```
121
-
122
- **Database Constraint Error:**
123
-
124
- Database errors in SQLSTATE class `22` (data exception) and `23` (integrity constraint) are detected by **class** and returned as 400 Bad Request. A known code uses its specific message; any other in-class code uses `DATABASE_CLIENT_ERROR_FALLBACK_MESSAGE` (`"Invalid database request"`).
125
-
126
- ```json
127
- // non-production — full driver context for debugging
128
- {
129
- "message": "Unique constraint violation\nDetail: Key (email)=(test@example.com) already exists.\nTable: User\nConstraint: UQ_User_email",
130
- "statusCode": 400,
131
- "requestId": "abc123",
132
- "details": { "url": "...", "path": "/api/users", "stack": "...", "cause": { } }
133
- }
134
- ```
135
-
136
- :::warning Production sanitizes database internals
137
- In **production** the message is the base message only — `Detail:`/`Table:`/`Constraint:` are stripped (they echo row values and schema names), and `details.stack`/`details.cause` are omitted. Codes outside class 22/23 (e.g. `42703` undefined column) and connection failures return a generic `"Internal Server Error"`, so SQL, schema names, and connection host/port never leak.
138
- :::
139
-
140
- **Database client error classes** — codes in SQLSTATE class `22` (data exception), `23` (integrity constraint), and `44` (WITH CHECK OPTION) map to HTTP 400. Common codes get a specific message; any other in-class code uses the fallback (`"Invalid database request"`).
141
-
142
- | Class | Codes with a specific message |
143
- |-------|-------------------------------|
144
- | `23` Integrity | `23505` unique · `23503` foreign key · `23502` not null · `23514` check · `23P01` exclusion · `23000` integrity · `23001` restrict |
145
- | `22` Data exception | `22001` string too long · `22003` numeric range · `22004` null not allowed · `22007` datetime format · `22008` datetime overflow · `22009` tz displacement · `22011` substring · `22012` division by zero · `22023` invalid parameter · `22025` invalid escape · `22026` length mismatch · `22030` duplicate JSON key · `22032` invalid JSON · `22P01` floating-point · `22P02` invalid text · `22P03` invalid binary · `22P05` untranslatable char |
146
- | `44` View check | `44000` WITH CHECK OPTION violation |
147
-
148
- :::tip Transient conflicts return 409, not 400/500
149
- Class `40` (`40001` serialization failure, `40P01` deadlock) is **transient/retryable** and returns **409 Conflict** with `messageCode: "database.conflict"` and a safe "please retry" message — the client can safely retry the same request. Programming/infra classes (`42` syntax, `53` resources, `0A`, `25`, `28`) remain 500.
150
- :::
151
-
152
- #### API Reference
153
-
154
- ##### `appErrorHandler(options)`
155
-
156
- **Parameters:**
157
- | Option | Type | Required | Description |
158
- |--------|------|----------|-------------|
159
- | `logger` | `ApplicationLogger` | Yes | Logger instance for error logging |
160
-
161
- **Returns:** `ErrorHandler` - Hono error handler function
162
-
163
- #### Common Patterns
164
-
165
- ```typescript
166
- // Custom error with status code
167
- class NotFoundError extends Error {
168
- statusCode = 404;
169
-
170
- constructor(message: string) {
171
- super(message);
172
- this.name = 'NotFoundError';
173
- }
174
- }
175
-
176
- // Throw in controller
177
- const GetUserConfig = {
178
- method: HTTP.Methods.GET,
179
- path: '/users/:id',
180
- request: {
181
- params: z.object({ id: z.string() }),
182
- },
183
- responses: jsonResponse({
184
- schema: z.object({ id: z.string(), name: z.string() }),
185
- }),
186
- } as const;
187
-
188
- @get({ configs: GetUserConfig })
189
- async getUser(c: TRouteContext) {
190
- const { id } = c.req.valid<{ id: string }>('param');
191
- const user = await this.userRepository.findById(id);
192
- if (!user) {
193
- throw new NotFoundError(`User ${id} not found`);
194
- }
195
- return c.json(user, HTTP.ResultCodes.RS_2.Ok);
196
- }
197
- ```
198
-
199
-
200
- ### Not Found Handler (`notFoundHandler`)
201
-
202
- Handles requests to routes that don't exist, returning a standardized 404 response.
203
-
204
- **File:** `packages/core/src/base/middlewares/not-found.middleware.ts`
205
-
206
- #### Usage
207
-
208
- ```typescript
209
- import { notFoundHandler } from '@venizia/ignis';
210
-
211
- const app = new IgnisApplication({
212
- // ...
213
- });
214
-
215
- // Register 404 handler
216
- app.notFound(notFoundHandler({
217
- logger: app.logger
218
- }));
219
- ```
220
-
221
- #### Response Format
222
-
223
- ```json
224
- {
225
- "message": "URL NOT FOUND",
226
- "path": "/api/nonexistent",
227
- "url": "http://localhost:3000/api/nonexistent"
228
- }
229
- ```
230
-
231
- **Status Code:** `404 Not Found`
232
-
233
- #### API Reference
234
-
235
- ##### `notFoundHandler(options)`
236
-
237
- **Parameters:**
238
- | Option | Type | Required | Default | Description |
239
- |--------|------|----------|---------|-------------|
240
- | `logger` | `ApplicationLogger` | No | `console` | Logger instance for logging 404s |
241
-
242
- **Returns:** `NotFoundHandler` - Hono not found handler function
243
-
244
-
245
- ### Request Spy (`RequestSpyMiddleware`)
246
-
247
- Logs detailed information about each request including timing, IP address, method, path, query parameters, and request body. Also handles request body parsing for JSON, form data, and text content types.
248
-
249
- **File:** `packages/core/src/base/middlewares/request-spy.middleware.ts`
250
-
251
- #### Features
252
-
253
- - Request lifecycle logging (incoming/outgoing)
254
- - Performance timing tracking
255
- - IP address extraction (supports `x-real-ip` and `x-forwarded-for` headers)
256
- - Request ID tracking
257
- - Query and body parameter logging (body only logged in non-production)
258
- - **Request body parsing**: Automatically parses and caches request bodies:
259
- - `application/json` → `req.json()`
260
- - `multipart/form-data`, `application/x-www-form-urlencoded` → `req.parseBody()`
261
- - Other content types (text, html, xml) → `req.text()`
262
-
263
- #### Usage
264
-
265
- ```typescript
266
- import { RequestSpyMiddleware } from '@venizia/ignis';
267
-
268
- const app = new IgnisApplication({
269
- // ...
270
- });
271
-
272
- // Create and register spy middleware
273
- const requestSpy = new RequestSpyMiddleware();
274
- app.use(requestSpy.value());
275
- ```
276
-
277
- #### Log Output
278
-
279
- **Request Start:**
280
- ```
281
- [spy][abc123] START | Handling Request | forwardedIp: 192.168.1.1 | path: /api/users | method: GET
282
- ```
283
-
284
- **Request Complete:**
285
- ```
286
- [spy][abc123] DONE | Handling Request | forwardedIp: 192.168.1.1 | path: /api/users | method: GET | Took: 45.23 (ms)
287
- ```
288
-
289
- #### API Reference
290
-
291
- ##### `RequestSpyMiddleware`
292
-
293
- **Class Methods:**
294
- | Method | Returns | Description |
295
- |--------|---------|-------------|
296
- | `value()` | `MiddlewareHandler` | Returns the middleware handler |
297
-
298
- **Static Properties:**
299
- | Property | Type | Value | Description |
300
- |----------|------|-------|-------------|
301
- | `REQUEST_ID_KEY` | `string` | `'requestId'` | Context key for request ID |
302
-
303
- #### Accessing Request ID
304
-
305
- ```typescript
306
- import { RequestSpyMiddleware, get, jsonResponse, TRouteContext, z } from '@venizia/ignis';
307
- import { HTTP } from '@venizia/ignis-helpers';
308
-
309
- const ExampleConfig = {
310
- method: HTTP.Methods.GET,
311
- path: '/example',
312
- responses: jsonResponse({
313
- schema: z.object({ requestId: z.string() }),
314
- }),
315
- } as const;
316
-
317
- // In a controller
318
- @get({ configs: ExampleConfig })
319
- async example(c: TRouteContext) {
320
- const requestId = c.get(RequestSpyMiddleware.REQUEST_ID_KEY);
321
- console.log('Request ID:', requestId);
322
- return c.json({ requestId }, HTTP.ResultCodes.RS_2.Ok);
323
- }
324
- ```
325
-
326
- :::warning Performance Impact
327
- Request spy logs every request detail. Consider disabling or reducing verbosity in production environments with high traffic.
328
- :::
329
-
330
-
331
- ### Emoji Favicon
332
-
333
- Serves an SVG emoji as the application's favicon, providing a lightweight alternative to traditional favicon files.
334
-
335
- **File:** `packages/core/src/base/middlewares/emoji-favicon.middleware.ts`
336
-
337
- #### Usage
338
-
339
- ```typescript
340
- import { emojiFavicon } from '@venizia/ignis';
341
-
342
- const app = new IgnisApplication({
343
- // ...
344
- });
345
-
346
- // Serve a rocket emoji as favicon
347
- app.use(emojiFavicon({ icon: '🚀' }));
348
- ```
349
-
350
- #### How It Works
351
-
352
- 1. Intercepts requests to `/favicon.ico`
353
- 2. Returns an inline SVG with the specified emoji
354
- 3. Sets `Content-Type: image/svg+xml`
355
- 4. All other requests pass through unchanged
356
-
357
- #### API Reference
358
-
359
- ##### `emojiFavicon(options)`
360
-
361
- **Parameters:**
362
- | Option | Type | Required | Description |
363
- |--------|------|----------|-------------|
364
- | `icon` | `string` | Yes | Emoji character to use as favicon |
365
-
366
- **Returns:** `MiddlewareHandler` - Hono middleware function
367
-
368
- #### Examples
369
-
370
- ```typescript
371
- // Different emoji icons
372
- app.use(emojiFavicon({ icon: '🔥' })); // Fire
373
- app.use(emojiFavicon({ icon: '⚡' })); // Lightning
374
- app.use(emojiFavicon({ icon: '🎯' })); // Target
375
- app.use(emojiFavicon({ icon: '🌟' })); // Star
376
- ```
377
-
378
- :::tip Browser Support
379
- SVG favicons are supported in all modern browsers. Fallback to a traditional `.ico` file if you need to support legacy browsers.
380
- :::
381
-
382
-
383
- ## Creating Custom Middleware
384
-
385
- IGNIS uses Hono's middleware system. Create custom middleware using the `createMiddleware` factory:
386
-
387
- ### Basic Middleware
388
-
389
- ```typescript
390
- import { createMiddleware } from 'hono/factory';
391
- import type { MiddlewareHandler } from 'hono';
392
-
393
- export const myMiddleware = (): MiddlewareHandler => {
394
- return createMiddleware(async (context, next) => {
395
- // Before request handling
396
- console.log('Before:', context.req.path);
397
-
398
- await next();
399
-
400
- // After request handling
401
- console.log('After:', context.req.path);
402
- });
403
- };
404
- ```
405
-
406
- ### Middleware with Options
407
-
408
- ```typescript
409
- interface MyMiddlewareOptions {
410
- enabled: boolean;
411
- prefix?: string;
412
- }
413
-
414
- export const myMiddleware = (opts: MyMiddlewareOptions): MiddlewareHandler => {
415
- const { enabled, prefix = 'LOG' } = opts;
416
-
417
- return createMiddleware(async (context, next) => {
418
- if (enabled) {
419
- console.log(`[${prefix}]`, context.req.path);
420
- }
421
- await next();
422
- });
423
- };
424
-
425
- // Usage
426
- app.use(myMiddleware({ enabled: true, prefix: 'API' }));
427
- ```
428
-
429
- ### Provider-Based Middleware
430
-
431
- For middleware requiring dependency injection:
432
-
433
- ```typescript
434
- import { BaseHelper } from '@venizia/ignis-helpers';
435
- import { IProvider } from '@venizia/ignis-inversion';
436
- import { injectable } from '@venizia/ignis-inversion';
437
- import { createMiddleware } from 'hono/factory';
438
- import type { MiddlewareHandler } from 'hono';
439
-
440
- @injectable()
441
- export class MyMiddleware extends BaseHelper implements IProvider<MiddlewareHandler> {
442
- constructor() {
443
- super({ scope: MyMiddleware.name });
444
- }
445
-
446
- value(): MiddlewareHandler {
447
- return createMiddleware(async (context, next) => {
448
- this.logger.info('Processing request:', context.req.path);
449
- await next();
450
- });
451
- }
452
- }
453
-
454
- // Usage
455
- const myMiddleware = app.get(MyMiddleware);
456
- app.use(myMiddleware.value());
457
- ```
458
-
459
-
460
- ## Middleware Order & Priority
461
-
462
- Middleware execution order matters. Follow these guidelines:
463
-
464
- ### Recommended Order
465
-
466
- ```typescript
467
- const app = new IgnisApplication({ /* ... */ });
468
-
469
- // 1. CORS (if needed)
470
- app.use(cors());
471
-
472
- // 2. Request ID generation
473
- app.use(requestId());
474
-
475
- // 3. Request spy/logging (also handles body parsing)
476
- const requestSpy = new RequestSpyMiddleware();
477
- app.use(requestSpy.value());
478
-
479
- // 4. Security middleware (helmet, etc.)
480
- app.use(helmet());
481
-
482
- // 5. Rate limiting
483
- app.use(rateLimit());
484
-
485
- // 6. Authentication
486
- app.use('/api/*', authenticate());
487
-
488
- // 7. Favicon (can be early or late)
489
- app.use(emojiFavicon({ icon: '🚀' }));
490
-
491
- // 8. Application routes
492
- app.mountControllers();
493
-
494
- // 9. Error handler (LAST in chain)
495
- app.onError(appErrorHandler({ logger: app.logger }));
496
-
497
- // 10. Not found handler (AFTER error handler)
498
- app.notFound(notFoundHandler({ logger: app.logger }));
499
- ```
500
-
501
- ### Key Principles
502
-
503
- 1. **Request ID First**: Generate request ID before logging
504
- 2. **Request Spy Early**: Log and parse request bodies before business logic
505
- 3. **Security Middleware Before Routes**: Protect routes with security checks
506
- 4. **Error Handler Last**: Catch all errors from previous middleware
507
- 5. **404 Handler After Error Handler**: Ensure unhandled routes return 404
508
-
509
- :::warning Order Matters
510
- Placing error handler before routes will prevent it from catching route errors. Always register error handlers last.
511
- :::
512
-
513
-
514
- ## Common Patterns
515
-
516
- ### Conditional Middleware
517
-
518
- ```typescript
519
- const app = new IgnisApplication({ /* ... */ });
520
-
521
- // Enable request spy only in development
522
- if (process.env.NODE_ENV === 'development') {
523
- const requestSpy = new RequestSpyMiddleware();
524
- app.use(requestSpy.value());
525
- }
526
- ```
527
-
528
- ### Route-Specific Middleware
529
-
530
- ```typescript
531
- // Apply middleware to specific routes
532
- app.use('/api/admin/*', adminAuthMiddleware());
533
- app.use('/api/public/*', rateLimitMiddleware());
534
- ```
535
-
536
- ### Middleware Composition
537
-
538
- ```typescript
539
- // Combine multiple middleware
540
- const apiMiddleware = (): MiddlewareHandler => {
541
- return createMiddleware(async (context, next) => {
542
- // Run multiple middleware in sequence
543
- await rateLimit()(context, async () => {
544
- await authenticate()(context, next);
545
- });
546
- });
547
- };
548
- ```
549
-
550
-
551
- ## Performance Considerations
552
-
553
- ### Request Spy in Production
554
-
555
- Request spy logs detailed information for every request. In high-traffic production environments:
556
-
557
- ```typescript
558
- // Conditional request spy
559
- const isDevelopment = process.env.NODE_ENV === 'development';
560
-
561
- if (isDevelopment) {
562
- const requestSpy = new RequestSpyMiddleware();
563
- app.use(requestSpy.value());
564
- }
565
- ```
566
-
567
- ### Error Logging Volume
568
-
569
- Error handlers log every error. For high error rates, consider:
570
- - Sampling (log 1 in N errors)
571
- - Error aggregation services (Sentry, Rollbar)
572
- - Rate-limited logging
573
-
574
-
575
- ## See Also
576
-
577
- - **Related References:**
578
- - [Application](./application.md) - Application setup and configuration
579
- - [Controllers](./controllers.md) - HTTP routing and request handling
580
- - [Dependency Injection](./dependency-injection.md) - DI container and providers
581
-
582
- - **Guides:**
583
- - [Building a CRUD API](/guides/tutorials/building-a-crud-api)
584
-
585
- - **Best Practices:**
586
- - [Troubleshooting Tips](/best-practices/troubleshooting-tips)
587
-
588
- - **External Resources:**
589
- - [Hono Middleware Documentation](https://hono.dev/docs/guides/middleware)
590
- - [HTTP Status Codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)