@venizia/ignis-docs 0.2.0 → 0.2.1-1

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 (174) hide show
  1. package/README.md +14 -14
  2. package/content/best-practices/api-usage-examples.md +39 -19
  3. package/content/best-practices/architectural-patterns.md +24 -13
  4. package/content/best-practices/architecture-decisions.md +29 -16
  5. package/content/best-practices/code-style-standards/advanced-patterns.md +43 -31
  6. package/content/best-practices/code-style-standards/constants-configuration.md +19 -4
  7. package/content/best-practices/code-style-standards/control-flow.md +33 -1
  8. package/content/best-practices/code-style-standards/documentation.md +28 -8
  9. package/content/best-practices/code-style-standards/function-patterns.md +15 -4
  10. package/content/best-practices/code-style-standards/index.md +7 -2
  11. package/content/best-practices/code-style-standards/naming-conventions.md +27 -3
  12. package/content/best-practices/code-style-standards/route-definitions.md +9 -5
  13. package/content/best-practices/code-style-standards/tooling.md +14 -1
  14. package/content/best-practices/code-style-standards/type-safety.md +39 -6
  15. package/content/best-practices/common-pitfalls.md +59 -35
  16. package/content/best-practices/contribution-workflow.md +8 -4
  17. package/content/best-practices/data-modeling.md +78 -62
  18. package/content/best-practices/deployment-strategies.md +56 -19
  19. package/content/best-practices/error-handling.md +247 -153
  20. package/content/best-practices/index.md +6 -0
  21. package/content/best-practices/performance-optimization.md +26 -13
  22. package/content/best-practices/security-guidelines.md +35 -9
  23. package/content/best-practices/testing-strategies.md +7 -2
  24. package/content/best-practices/troubleshooting-tips.md +27 -17
  25. package/content/extensions/components/api-reference.md +109 -323
  26. package/content/extensions/components/authentication/api.md +489 -602
  27. package/content/extensions/components/authentication/errors.md +135 -498
  28. package/content/extensions/components/authentication/index.md +89 -801
  29. package/content/extensions/components/authentication/usage.md +231 -955
  30. package/content/extensions/components/authorization/api.md +991 -644
  31. package/content/extensions/components/authorization/errors.md +204 -208
  32. package/content/extensions/components/authorization/getting-started.md +227 -0
  33. package/content/extensions/components/authorization/index.md +88 -795
  34. package/content/extensions/components/authorization/usage.md +219 -528
  35. package/content/extensions/components/health-check.md +77 -243
  36. package/content/extensions/components/index.md +24 -90
  37. package/content/extensions/components/mail/api.md +553 -285
  38. package/content/extensions/components/mail/errors.md +76 -62
  39. package/content/extensions/components/mail/index.md +111 -463
  40. package/content/extensions/components/mail/usage.md +139 -173
  41. package/content/extensions/components/request-tracker.md +70 -173
  42. package/content/extensions/components/socket-io/api.md +462 -785
  43. package/content/extensions/components/socket-io/errors.md +49 -51
  44. package/content/extensions/components/socket-io/index.md +69 -372
  45. package/content/extensions/components/socket-io/usage.md +212 -105
  46. package/content/extensions/components/static-asset/api.md +461 -141
  47. package/content/extensions/components/static-asset/errors.md +121 -53
  48. package/content/extensions/components/static-asset/index.md +84 -606
  49. package/content/extensions/components/static-asset/usage.md +184 -299
  50. package/content/extensions/components/template/index.md +3 -3
  51. package/content/extensions/components/websocket/api.md +311 -404
  52. package/content/extensions/components/websocket/errors.md +47 -56
  53. package/content/extensions/components/websocket/index.md +75 -407
  54. package/content/extensions/components/websocket/usage.md +120 -338
  55. package/content/extensions/helpers/cron/index.md +52 -160
  56. package/content/extensions/helpers/crypto/index.md +67 -480
  57. package/content/extensions/helpers/crypto/reference.md +528 -0
  58. package/content/extensions/helpers/env/index.md +64 -178
  59. package/content/extensions/helpers/error/index.md +286 -196
  60. package/content/extensions/helpers/index.md +61 -47
  61. package/content/extensions/helpers/inversion/index.md +76 -550
  62. package/content/extensions/helpers/inversion/reference.md +530 -0
  63. package/content/extensions/helpers/kafka/admin.md +23 -3
  64. package/content/extensions/helpers/kafka/compile-binary.md +83 -52
  65. package/content/extensions/helpers/kafka/consumer.md +65 -28
  66. package/content/extensions/helpers/kafka/examples.md +46 -253
  67. package/content/extensions/helpers/kafka/index.md +55 -617
  68. package/content/extensions/helpers/kafka/producer.md +156 -22
  69. package/content/extensions/helpers/kafka/schema-registry.md +59 -79
  70. package/content/extensions/helpers/logger/hf-logger.md +220 -0
  71. package/content/extensions/helpers/logger/index.md +78 -552
  72. package/content/extensions/helpers/logger/pino.md +105 -0
  73. package/content/extensions/helpers/logger/reference.md +937 -0
  74. package/content/extensions/helpers/network/api.md +276 -195
  75. package/content/extensions/helpers/network/index.md +87 -524
  76. package/content/extensions/helpers/queue/index.md +80 -897
  77. package/content/extensions/helpers/queue/reference.md +494 -0
  78. package/content/extensions/helpers/redis/index.md +86 -640
  79. package/content/extensions/helpers/redis/reference.md +784 -0
  80. package/content/extensions/helpers/secrets/index.md +136 -0
  81. package/content/extensions/helpers/socket-io/api.md +325 -204
  82. package/content/extensions/helpers/socket-io/index.md +79 -429
  83. package/content/extensions/helpers/storage/api.md +584 -464
  84. package/content/extensions/helpers/storage/index.md +80 -573
  85. package/content/extensions/helpers/types/index.md +75 -495
  86. package/content/extensions/helpers/types/reference.md +689 -0
  87. package/content/extensions/helpers/uid/index.md +176 -189
  88. package/content/extensions/helpers/websocket/api.md +366 -214
  89. package/content/extensions/helpers/websocket/index.md +68 -503
  90. package/content/extensions/helpers/worker-thread/index.md +62 -396
  91. package/content/extensions/helpers/worker-thread/reference.md +428 -0
  92. package/content/extensions/index.md +38 -39
  93. package/content/extensions/src-details/mcp-server.md +96 -548
  94. package/content/guides/core-concepts/persistent/datasources.md +2 -2
  95. package/content/guides/core-concepts/persistent/index.md +5 -1
  96. package/content/guides/core-concepts/persistent/models.md +1 -1
  97. package/content/guides/core-concepts/persistent/pglite.md +218 -0
  98. package/content/guides/core-concepts/persistent/postgres-drivers.md +21 -15
  99. package/content/guides/core-concepts/persistent/search-meilisearch.md +22 -12
  100. package/content/guides/core-concepts/persistent/search-typesense.md +28 -16
  101. package/content/guides/core-concepts/persistent/sqlite.md +296 -0
  102. package/content/guides/core-concepts/persistent/transactions.md +12 -11
  103. package/content/guides/core-concepts/secrets-vault.md +177 -0
  104. package/content/guides/core-concepts/services.md +1 -1
  105. package/content/guides/get-started/5-minute-quickstart.md +59 -206
  106. package/content/guides/get-started/philosophy.md +135 -670
  107. package/content/guides/get-started/setup.md +53 -74
  108. package/content/guides/migrations/redis-helpers-migration.md +5 -4
  109. package/content/guides/migrations/scoped-rbac-migration.md +5 -5
  110. package/content/guides/migrations/unified-connectors-migration.md +8 -7
  111. package/content/guides/tutorials/ecommerce-api.md +3 -8
  112. package/content/guides/tutorials/realtime-chat.md +1 -1
  113. package/content/references/base/application.md +64 -22
  114. package/content/references/base/components.md +3 -3
  115. package/content/references/base/connectors.md +79 -136
  116. package/content/references/base/controllers.md +12 -12
  117. package/content/references/base/datasources-reference.md +600 -0
  118. package/content/references/base/datasources.md +84 -444
  119. package/content/references/base/dependency-injection.md +25 -46
  120. package/content/references/base/filter-system/application-usage.md +95 -123
  121. package/content/references/base/filter-system/array-operators.md +33 -43
  122. package/content/references/base/filter-system/comparison-operators.md +55 -63
  123. package/content/references/base/filter-system/default-filter.md +144 -350
  124. package/content/references/base/filter-system/fields-order-pagination.md +116 -148
  125. package/content/references/base/filter-system/index.md +114 -253
  126. package/content/references/base/filter-system/json-filtering.md +52 -181
  127. package/content/references/base/filter-system/list-operators.md +28 -44
  128. package/content/references/base/filter-system/logical-operators.md +69 -114
  129. package/content/references/base/filter-system/null-operators.md +41 -98
  130. package/content/references/base/filter-system/pattern-matching.md +48 -51
  131. package/content/references/base/filter-system/quick-reference.md +93 -196
  132. package/content/references/base/filter-system/range-operators.md +22 -38
  133. package/content/references/base/filter-system/tips.md +70 -133
  134. package/content/references/base/filter-system/use-cases.md +173 -232
  135. package/content/references/base/grpc-controllers.md +53 -17
  136. package/content/references/base/index.md +5 -3
  137. package/content/references/base/middlewares.md +43 -28
  138. package/content/references/base/models-reference.md +886 -0
  139. package/content/references/base/models.md +81 -1452
  140. package/content/references/base/providers.md +8 -8
  141. package/content/references/base/repositories/advanced.md +281 -419
  142. package/content/references/base/repositories/index.md +84 -644
  143. package/content/references/base/repositories/mixins.md +25 -21
  144. package/content/references/base/repositories/relations.md +194 -375
  145. package/content/references/base/repositories/soft-deletable.md +67 -55
  146. package/content/references/base/secrets.md +267 -0
  147. package/content/references/base/services.md +8 -6
  148. package/content/references/configuration/environment-variables.md +73 -21
  149. package/content/references/configuration/index.md +51 -31
  150. package/content/references/index.md +1 -1
  151. package/content/references/quick-reference.md +3 -16
  152. package/content/references/utilities/crypto.md +35 -76
  153. package/content/references/utilities/date.md +33 -73
  154. package/content/references/utilities/duration.md +85 -0
  155. package/content/references/utilities/index.md +6 -2
  156. package/content/references/utilities/jsx-reference.md +298 -0
  157. package/content/references/utilities/jsx.md +82 -525
  158. package/content/references/utilities/module.md +81 -61
  159. package/content/references/utilities/parse.md +34 -64
  160. package/content/references/utilities/performance.md +33 -58
  161. package/content/references/utilities/promise.md +28 -62
  162. package/content/references/utilities/request.md +58 -218
  163. package/content/references/utilities/retry.md +139 -0
  164. package/content/references/utilities/schema.md +43 -137
  165. package/content/references/utilities/statuses-reference.md +361 -0
  166. package/content/references/utilities/statuses.md +63 -667
  167. package/dist/mcp-server/index.js +0 -0
  168. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
  169. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts.map +1 -1
  170. package/dist/mcp-server/tools/github/list-project-files.tool.js +3 -3
  171. package/dist/mcp-server/tools/github/search-code.tool.js +1 -1
  172. package/dist/mcp-server/tools/github/verify-dependencies.tool.js +1 -1
  173. package/dist/mcp-server/tools/github/view-source-file.tool.js +1 -1
  174. package/package.json +24 -23
@@ -1,6 +1,6 @@
1
1
  # Request Tracker
2
2
 
3
- Automatic request logging middleware with unique request IDs, client IP detection, body parsing, and timing -- auto-registered by the framework.
3
+ Automatic request logging middleware that assigns a UUID request ID to every request. It logs method, path, client IP, and timing on the way in and out.
4
4
 
5
5
  > [!IMPORTANT]
6
6
  > This component is **auto-registered** by `BaseApplication` during `initialize()`. No manual registration is needed.
@@ -12,7 +12,7 @@ Automatic request logging middleware with unique request IDs, client IP detectio
12
12
  | **Package** | `@venizia/ignis` |
13
13
  | **Component** | `RequestTrackerComponent` |
14
14
  | **Middleware** | `RequestSpyMiddleware` |
15
- | **Utility** | `getIncomingIp()` |
15
+ | **Utility** | `NetworkUtility.getIncomingIp()` |
16
16
  | **Runtimes** | Both (Bun and Node.js) |
17
17
 
18
18
  #### Import Paths
@@ -20,225 +20,116 @@ Automatic request logging middleware with unique request IDs, client IP detectio
20
20
  import { RequestTrackerComponent } from '@venizia/ignis';
21
21
  ```
22
22
 
23
- ## Setup
23
+ ## In one example
24
24
 
25
- ### Step 1: Bind Configuration
26
-
27
- No configuration binding is required. The component has no user-facing configuration options.
28
-
29
- ### Step 2: Register Component
30
-
31
- This happens automatically inside `BaseApplication.initialize()`:
32
-
33
- ```typescript
34
- // Internal to BaseApplication -- shown for reference only
35
- this.component(RequestTrackerComponent);
36
- ```
37
-
38
- The component registers two Hono middlewares on the application server during its `binding()` phase:
39
- 1. `requestId()` from `hono/request-id` -- generates a UUID and stores it on the Hono context under the key `'requestId'`
40
- 2. `RequestSpyMiddleware` -- logs request start/end with IP, method, path, query, body, and timing
41
-
42
- ### Step 3: Use
43
-
44
- No injection or manual usage is needed. Once the application starts, every incoming request is automatically logged with a unique request ID.
45
-
46
- A sample log output in **non-production** mode looks like this:
25
+ Nothing to configure - once the application starts, every request is logged automatically.
47
26
 
48
27
  ```
49
28
  [SpyMW] [<request-id>][127.0.0.1][=>] GET /hello | query: {} | body: null
50
29
  [SpyMW] [<request-id>][127.0.0.1][<=] GET /hello | Took: 1.23 (ms)
51
30
  ```
52
31
 
53
- In **production** mode (`NODE_ENV=production`), body is excluded but query is still logged:
32
+ Bodies are logged only in a development environment. Everywhere else - including when `NODE_ENV` is
33
+ unset - the body is omitted and query is still logged:
54
34
 
55
35
  ```
56
36
  [SpyMW] [<request-id>][127.0.0.1][=>] GET /hello | query: {}
57
37
  [SpyMW] [<request-id>][127.0.0.1][<=] GET /hello | Took: 1.23 (ms)
58
38
  ```
59
39
 
60
- The log format follows this structure:
61
-
62
40
  | Direction | Format |
63
41
  |-----------|--------|
64
42
  | Incoming (`=>`) | `[requestId][clientIp][=>] METHOD path \| query: {...} \| body: {...}` |
65
43
  | Outgoing (`<=`) | `[requestId][clientIp][<=] METHOD path \| Took: X.XX (ms)` |
66
44
 
67
- The HTTP method is padded to 8 characters for consistent alignment in log output.
68
-
69
- > [!TIP]
70
- > The request ID is also available in the framework's error handlers (`notFoundHandler`, `appErrorHandler`), making it easy to correlate error logs with the original request.
71
-
72
- ## Configuration
73
-
74
- The Request Tracker component has no user-configurable options. Its behavior is fully automatic.
45
+ The HTTP method is padded to 8 characters for consistent alignment.
75
46
 
76
- | Behavior | Description |
77
- |----------|-------------|
78
- | **Request ID** | Generated automatically via `hono/request-id` middleware (UUID), stored on context as `'requestId'` |
79
- | **IP Detection** | Priority: (1) connection info via `getIncomingIp()`, (2) `x-real-ip` header, (3) `x-forwarded-for` header |
80
- | **Body Logging** | Logs request body in non-production environments only. Query is always logged |
81
- | **Timing** | Measures and logs request duration in milliseconds (2 decimal places) via `performance.now()` |
82
- | **Scope** | Registered as a singleton provider |
47
+ ## How it works
83
48
 
84
- > [!NOTE]
85
- > In **production** (`NODE_ENV=production`), only the request **body** is excluded from log output to prevent sensitive data exposure. Query parameters are still logged in all environments.
49
+ - **One middleware, and an ID it does not install.** `requestId()` comes from `RestApplication.registerDefaultMiddlewares()`, which runs before any component, so it is already in place when `binding()` resolves `RequestSpyMiddleware` from the DI container and registers it. The generator is IGNIS's `RequestIdGenerator`, not hono's `crypto.randomUUID` default - that keeps a server and a browser-Worker BFF stamping the same format.
50
+ - **IP resolution is best-effort, never fatal.** The middleware falls through several sources before giving up - see the resolution order below. An unresolved IP never fails the request; this middleware observes traffic, it does not gate it.
51
+ - **Body logging is environment-gated, and it fails closed.** `RequestSpyMiddleware` reads `NODE_ENV` once in its constructor and logs the body only when the value is one of `local`, `debug`, `development`, `dev`, `sit`. Anything else - `staging`, `uat`, `production`, or `NODE_ENV` unset entirely - logs query only. Query is always logged in every environment.
86
52
 
87
- ## Internals
88
-
89
- ### RequestTrackerComponent
90
-
91
- The component class extends `BaseComponent`. It receives `BaseApplication` via `@inject({ key: CoreBindings.APPLICATION_INSTANCE })` in its constructor.
92
-
93
- During construction, it creates a singleton binding for the middleware:
94
-
95
- ```typescript
96
- Binding.bind({ key: RequestTrackerComponent.REQUEST_TRACKER_MW_BINDING_KEY })
97
- .toProvider(RequestSpyMiddleware)
98
- .setScope(BindingScopes.SINGLETON)
99
- ```
100
-
101
- The binding key is constructed as `BindingNamespaces.MIDDLEWARE + '.' + RequestSpyMiddleware.name`, which resolves to `'middlewares.RequestSpyMiddleware'`.
102
-
103
- #### Component Lifecycle
104
-
105
- 1. **`constructor()`** -- Receives `BaseApplication` via DI. Defines the middleware binding as a singleton provider.
106
- 2. **`binding()`** -- Registers `requestId()` middleware on the server. Resolves the `RequestSpyMiddleware` binding from the DI container. Throws if the middleware cannot be resolved. Registers the resolved middleware on the server.
107
-
108
- ### RequestSpyMiddleware
109
-
110
- The middleware class extends `BaseHelper` with scope `'SpyMW'` and implements `IProvider<MiddlewareHandler>`.
111
-
112
- ```typescript
113
- class RequestSpyMiddleware extends BaseHelper implements IProvider<MiddlewareHandler> {
114
- static readonly REQUEST_ID_KEY = 'requestId';
115
- private isDebugMode: boolean;
116
- // ...
117
- }
118
- ```
119
-
120
- #### IProvider Pattern
121
-
122
- `RequestSpyMiddleware` implements the `IProvider<T>` interface from `@venizia/ignis-inversion`. This interface requires a single method:
123
-
124
- ```typescript
125
- interface IProvider<T> {
126
- value(container: Container): T;
127
- }
128
- ```
53
+ > [!WARNING]
54
+ > This rule used to be "anything that is not `production`", which logged full request bodies in `staging`, `uat` and with `NODE_ENV` unset. If you relied on bodies appearing outside a development environment, set `NODE_ENV` to one of the five values above.
55
+ - **Body parsing follows Content-Type.** See the outcomes table below for what each Content-Type resolves to. A parse failure throws `'Malformed Body Payload'` (HTTP 400).
56
+ - **The middleware is an `IProvider`, not a plain function.** `RequestSpyMiddleware` implements `IProvider<MiddlewareHandler>` from `@venizia/ignis-inversion`. The container instantiates the class, so it can hold `isDebugMode` state as an instance field. It then calls `.value()` to obtain the actual Hono handler.
129
57
 
130
- When the DI container resolves the binding (via `.toProvider(RequestSpyMiddleware)`), it instantiates the class and calls `value()` to obtain the actual `MiddlewareHandler`. This pattern allows the middleware to hold state (like `isDebugMode`) while producing a clean middleware function.
58
+ > [!TIP]
59
+ > The request ID is also available in the framework's error handlers (`notFoundHandler`, `AppErrorMiddleware`) - the same ID correlates error logs with the original request.
131
60
 
132
- #### Debug Mode Detection
61
+ ## Common tasks
133
62
 
134
- The constructor checks `process.env.NODE_ENV`:
63
+ ### Correlate logs with a request
64
+ Read the `requestId` context value inside your own handlers or middleware - the same ID appears in every `[SpyMW]` log line for that request.
135
65
 
136
66
  ```typescript
137
- constructor() {
138
- super({ scope: 'SpyMW' });
139
- const env = process.env.NODE_ENV?.toLowerCase();
140
- this.isDebugMode = env !== Environment.PRODUCTION;
141
- }
67
+ const requestId = context.get('requestId');
142
68
  ```
143
69
 
144
- When `isDebugMode` is `true` (any environment other than `'production'`), the incoming request log includes both `query` and `body`. When `false`, only `query` is logged.
145
-
146
- #### value() -- Middleware Handler
147
-
148
- The `value()` method returns a Hono middleware created via `createMiddleware()` from `hono/factory`. The middleware performs the following steps:
149
-
150
- 1. Starts a performance timer via `performance.now()`
151
- 2. Extracts the request ID from the Hono context (set by `requestId()` middleware)
152
- 3. Resolves the client IP using the priority chain (see IP Detection below)
153
- 4. Throws `'Malformed Connection Info'` (400) if both `incomingIp` and `forwardedIp` are `null`
154
- 5. Extracts method, path, and query from the request
155
- 6. Parses the request body via `parseBody()`
156
- 7. Logs the incoming request with `[=>]` direction marker
157
- 8. Calls `await next()` to proceed to the next middleware/handler
158
- 9. Calculates duration and logs the outgoing response with `[<=]` direction marker
159
-
160
- #### parseBody()
161
-
162
- A public method that parses the request body based on `Content-Type` and `Content-Length` headers.
70
+ ### Reuse `parseBody` for your own middleware
71
+ `parseBody` is a public method - reuse it wherever you need the same Content-Type-aware parsing.
163
72
 
164
73
  ```typescript
165
74
  async parseBody(opts: { req: TContext['req'] }): Promise<unknown>
166
75
  ```
167
76
 
168
- **Return conditions:**
77
+ ### Understand the client IP resolution order
78
+ | Priority | Source | Notes |
79
+ |----------|--------|-------|
80
+ | 1 | `NetworkUtility.getIncomingIp(context)` | Native connection info - `hono/bun` on Bun, `@hono/node-server/conninfo` on Node.js |
81
+ | 2 | `x-real-ip` header | Set by reverse proxies (e.g., Nginx `proxy_set_header X-Real-IP`) |
82
+ | 3 | `x-forwarded-for` header | Standard proxy header |
83
+ | 4 | `'unknown'` | Logged when none of the above resolve - the request still proceeds |
169
84
 
85
+ ### Understand body-parsing outcomes
170
86
  | Condition | Result |
171
87
  |-----------|--------|
172
- | No `Content-Type` header | Returns `null` |
173
- | No `Content-Length` header or value is `'0'` | Returns `null` |
174
- | `Content-Type` includes `application/json` | Calls `req.json()` |
175
- | `Content-Type` includes `multipart/form-data` | Calls `req.parseBody()` |
176
- | `Content-Type` includes `application/x-www-form-urlencoded` | Calls `req.parseBody()` |
177
- | Any other `Content-Type` (text, html, xml, etc.) | Calls `req.text()` |
178
- | Parsing fails for any content type | Throws `'Malformed Body Payload'` (HTTP 400) |
179
-
180
- ### getIncomingIp() Utility
181
-
182
- A utility function that attempts to extract the client IP address from the Hono context using runtime-specific connection info.
183
-
184
- ```typescript
185
- const getIncomingIp = (context: Context): string | null
186
- ```
187
-
188
- **Runtime detection:**
189
- - Uses `RuntimeModules.isBun()` from `@venizia/ignis-helpers` to detect the runtime
190
- - On **Bun**: imports `getConnInfo` from `hono/bun`
191
- - On **Node.js**: imports `getConnInfo` from `@hono/node-server/conninfo`
192
- - Returns `connInfo.remote.address` if available, `null` otherwise
193
- - Returns `null` if `getConnInfo` is unavailable or throws
194
-
195
- #### IP Detection Priority
196
-
197
- The middleware resolves the client IP using a three-step fallback chain:
198
-
199
- | Priority | Source | Description |
200
- |----------|--------|-------------|
201
- | 1 | `getIncomingIp(context)` | Direct connection info from the runtime (Bun or Node.js) |
202
- | 2 | `x-real-ip` header | Set by reverse proxies (e.g., Nginx `proxy_set_header X-Real-IP`) |
203
- | 3 | `x-forwarded-for` header | Standard proxy header with original client IP |
88
+ | No `Content-Type` header | `null` |
89
+ | `Content-Length` is `'0'`, or no body stream present | `null` |
90
+ | `Content-Type` includes `application/json` | `req.json()` |
91
+ | `Content-Type` includes `multipart/form-data` or `application/x-www-form-urlencoded` | `req.parseBody()` |
92
+ | `Content-Type` is `application/octet-stream` | Raw body stream |
93
+ | Any other `Content-Type` (text, html, xml, etc.) | `req.text()` |
94
+ | Parsing throws for any content type | `'Malformed Body Payload'` (HTTP 400) |
204
95
 
205
- The `clientIp` used in log output is resolved as `incomingIp ?? forwardedIp` -- meaning connection info takes precedence when available.
96
+ ## Reference
206
97
 
207
- If **all three** sources return `null`, the middleware throws a `'Malformed Connection Info'` error with HTTP 400 status.
208
-
209
- ## Binding Keys
98
+ ### Configuration
99
+ No user-configurable options - behavior is fully automatic.
210
100
 
101
+ ### Binding keys
211
102
  | Key | Constant | Type | Required | Default |
212
103
  |-----|----------|------|----------|---------|
213
- | `middlewares.RequestSpyMiddleware` | `RequestTrackerComponent.REQUEST_TRACKER_MW_BINDING_KEY` | `MiddlewareHandler` | Auto | Provided by component |
214
-
215
- The key is constructed from `BindingNamespaces.MIDDLEWARE` (`'middlewares'`) + `RequestSpyMiddleware.name` (`'RequestSpyMiddleware'`). The component binds `RequestSpyMiddleware` as a singleton provider at this key during construction.
216
-
217
- ## Troubleshooting
218
-
219
- ### "Invalid middleware to init request tracker | Please check again binding value"
104
+ | `middlewares.RequestSpyMiddleware` | `RequestTrackerComponent.REQUEST_TRACKER_MW_BINDING_KEY` | `MiddlewareHandler` | Auto | Singleton provider, registered by the constructor |
220
105
 
221
- **Cause:** The `RequestSpyMiddleware` binding could not be resolved from the DI container during the component's `binding()` phase. This typically means the binding was removed or overwritten before `binding()` executed.
106
+ The key is built as `BindingNamespaces.MIDDLEWARE` (`'middlewares'`) + `.` + `RequestSpyMiddleware.name`.
222
107
 
223
- **Fix:** Ensure no custom code unbinds or replaces the `middlewares.RequestSpyMiddleware` key. If you need to customize request logging, extend the component rather than removing the binding.
224
-
225
- ### "Malformed Body Payload"
226
-
227
- **Cause:** The `RequestSpyMiddleware` attempted to parse the request body based on the `Content-Type` header, but the body content was malformed (e.g., invalid JSON with `application/json` content type, or corrupt form data).
228
-
229
- **Fix:** Ensure clients send valid body content that matches the declared `Content-Type` header. This error returns HTTP 400 Bad Request.
108
+ ### RequestSpyMiddleware
109
+ ```typescript
110
+ class RequestSpyMiddleware extends BaseHelper implements IProvider<MiddlewareHandler> {
111
+ static readonly REQUEST_ID_KEY = 'requestId';
112
+ private isDebugMode: boolean;
113
+ // ...
114
+ }
115
+ ```
230
116
 
231
- ### "Malformed Connection Info"
117
+ - Extends `BaseHelper` with scope `'SpyMW'`
118
+ - Constructor sets `isDebugMode = process.env.NODE_ENV?.toLowerCase() !== Environment.PRODUCTION`
119
+ - `value()` returns a Hono middleware built via `createMiddleware()` from `hono/factory`
232
120
 
233
- **Cause:** The middleware could not determine the client IP address from any source. All three must have failed: (1) `getIncomingIp()` returned `null` (runtime connection info unavailable), (2) `x-real-ip` header was absent, and (3) `x-forwarded-for` header was absent. This error returns HTTP 400 Bad Request.
121
+ ### Component lifecycle
122
+ 1. **`constructor()`** - Receives `BaseApplication` via DI. Defines the middleware binding as a singleton provider.
123
+ 2. **`binding()`** - Resolves the `RequestSpyMiddleware` binding, throwing if it cannot be resolved. Registers the resolved middleware on the server. The request ID is already installed by the application's default stack.
234
124
 
235
- **Fix:** Ensure your reverse proxy (e.g., Nginx, Caddy) forwards at least one of these headers:
236
- - `x-real-ip`
237
- - `x-forwarded-for`
125
+ ## Troubleshooting
238
126
 
239
- If running without a proxy, ensure the runtime provides connection info (Bun does this natively; Node.js requires `@hono/node-server`).
127
+ | Symptom | Cause | Fix |
128
+ |---------|-------|-----|
129
+ | `Invalid middleware to init request tracker \| Please check again binding value` | `RequestSpyMiddleware` binding was unbound or overwritten before `binding()` ran | Don't unbind or replace `middlewares.RequestSpyMiddleware`; extend the component instead of removing its binding |
130
+ | `Malformed Body Payload` (400) | Body content didn't match its declared `Content-Type` (e.g., invalid JSON with `application/json`) | Ensure clients send body content that matches the `Content-Type` header |
240
131
 
241
- ## See Also
132
+ ## See also
242
133
 
243
134
  - **Guides:**
244
135
  - [Components Overview](/guides/core-concepts/components) - Component system basics
@@ -253,3 +144,9 @@ If running without a proxy, ensure the runtime provides connection info (Bun doe
253
144
  - **Best Practices:**
254
145
  - [Troubleshooting Tips](/best-practices/troubleshooting-tips) - Debugging with request IDs
255
146
  - [Deployment Strategies](/best-practices/deployment-strategies) - Production logging
147
+
148
+ **Files:**
149
+
150
+ - [`packages/core-server/src/components/request-tracker/component.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/components/request-tracker/component.ts) - `RequestTrackerComponent`
151
+ - [`packages/core-server/src/base/middlewares/request-spy/request-spy.middleware.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/base/middlewares/request-spy/request-spy.middleware.ts) - `RequestSpyMiddleware`
152
+ - [`packages/core-server/src/utilities/network.utility.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/utilities/network.utility.ts) - `NetworkUtility.getIncomingIp()`