@venizia/ignis-docs 0.0.7 → 0.0.8-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mcp-server/common/paths.d.ts +4 -2
- package/dist/mcp-server/common/paths.d.ts.map +1 -1
- package/dist/mcp-server/common/paths.js +8 -6
- package/dist/mcp-server/common/paths.js.map +1 -1
- package/dist/mcp-server/tools/docs/get-document-content.tool.d.ts +1 -1
- package/dist/mcp-server/tools/docs/get-document-content.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/docs/get-document-content.tool.js +7 -7
- package/dist/mcp-server/tools/docs/get-document-metadata.tool.js +3 -3
- package/dist/mcp-server/tools/docs/get-package-overview.tool.d.ts +1 -1
- package/dist/mcp-server/tools/docs/get-package-overview.tool.js +1 -1
- package/package.json +1 -1
- package/wiki/best-practices/api-usage-examples.md +9 -9
- package/wiki/best-practices/architectural-patterns.md +19 -3
- package/wiki/best-practices/architecture-decisions.md +6 -6
- package/wiki/best-practices/code-style-standards/advanced-patterns.md +1 -1
- package/wiki/best-practices/code-style-standards/control-flow.md +1 -1
- package/wiki/best-practices/code-style-standards/function-patterns.md +2 -2
- package/wiki/best-practices/code-style-standards/index.md +2 -2
- package/wiki/best-practices/code-style-standards/naming-conventions.md +1 -1
- package/wiki/best-practices/code-style-standards/route-definitions.md +4 -4
- package/wiki/best-practices/data-modeling.md +1 -1
- package/wiki/best-practices/deployment-strategies.md +1 -1
- package/wiki/best-practices/error-handling.md +2 -2
- package/wiki/best-practices/performance-optimization.md +3 -3
- package/wiki/best-practices/security-guidelines.md +2 -2
- package/wiki/best-practices/troubleshooting-tips.md +1 -1
- package/wiki/{references → extensions}/components/authentication/api.md +12 -20
- package/wiki/{references → extensions}/components/authentication/errors.md +1 -1
- package/wiki/{references → extensions}/components/authentication/index.md +5 -8
- package/wiki/{references → extensions}/components/authentication/usage.md +20 -36
- package/wiki/{references → extensions}/components/authorization/api.md +62 -13
- package/wiki/{references → extensions}/components/authorization/errors.md +12 -7
- package/wiki/{references → extensions}/components/authorization/index.md +93 -6
- package/wiki/{references → extensions}/components/authorization/usage.md +42 -4
- package/wiki/{references → extensions}/components/health-check.md +5 -4
- package/wiki/{references → extensions}/components/index.md +2 -0
- package/wiki/{references → extensions}/components/mail/index.md +1 -1
- package/wiki/{references → extensions}/components/request-tracker.md +1 -1
- package/wiki/{references → extensions}/components/socket-io/api.md +2 -2
- package/wiki/{references → extensions}/components/socket-io/errors.md +2 -0
- package/wiki/{references → extensions}/components/socket-io/index.md +24 -20
- package/wiki/{references → extensions}/components/socket-io/usage.md +2 -2
- package/wiki/{references → extensions}/components/static-asset/api.md +14 -15
- package/wiki/{references → extensions}/components/static-asset/errors.md +3 -1
- package/wiki/{references → extensions}/components/static-asset/index.md +158 -89
- package/wiki/{references → extensions}/components/static-asset/usage.md +8 -5
- package/wiki/{references → extensions}/components/swagger.md +3 -3
- package/wiki/{references → extensions}/components/template/index.md +4 -4
- package/wiki/{references → extensions}/components/template/setup-page.md +1 -1
- package/wiki/{references → extensions}/components/template/single-page.md +1 -1
- package/wiki/{references → extensions}/components/websocket/api.md +7 -6
- package/wiki/{references → extensions}/components/websocket/errors.md +17 -3
- package/wiki/{references → extensions}/components/websocket/index.md +17 -11
- package/wiki/{references → extensions}/components/websocket/usage.md +2 -2
- package/wiki/{references → extensions}/helpers/crypto/index.md +1 -1
- package/wiki/{references → extensions}/helpers/env/index.md +9 -5
- package/wiki/{references → extensions}/helpers/error/index.md +2 -7
- package/wiki/{references → extensions}/helpers/index.md +18 -6
- package/wiki/{references → extensions}/helpers/kafka/admin.md +13 -1
- package/wiki/{references → extensions}/helpers/kafka/consumer.md +28 -28
- package/wiki/{references → extensions}/helpers/kafka/examples.md +19 -19
- package/wiki/{references → extensions}/helpers/kafka/index.md +51 -48
- package/wiki/{references → extensions}/helpers/kafka/producer.md +18 -18
- package/wiki/{references → extensions}/helpers/kafka/schema-registry.md +25 -25
- package/wiki/{references → extensions}/helpers/logger/index.md +2 -2
- package/wiki/{references → extensions}/helpers/queue/index.md +400 -4
- package/wiki/{references → extensions}/helpers/storage/api.md +170 -10
- package/wiki/{references → extensions}/helpers/storage/index.md +44 -8
- package/wiki/{references → extensions}/helpers/template/index.md +1 -1
- package/wiki/{references → extensions}/helpers/testing/index.md +4 -4
- package/wiki/{references → extensions}/helpers/types/index.md +63 -16
- package/wiki/{references → extensions}/helpers/websocket/index.md +1 -1
- package/wiki/extensions/index.md +48 -0
- package/wiki/guides/core-concepts/application/bootstrapping.md +55 -37
- package/wiki/guides/core-concepts/application/index.md +95 -35
- package/wiki/guides/core-concepts/components-guide.md +23 -19
- package/wiki/guides/core-concepts/components.md +34 -10
- package/wiki/guides/core-concepts/dependency-injection.md +99 -34
- package/wiki/guides/core-concepts/grpc-controllers.md +295 -0
- package/wiki/guides/core-concepts/persistent/datasources.md +27 -8
- package/wiki/guides/core-concepts/persistent/models.md +43 -1
- package/wiki/guides/core-concepts/persistent/repositories.md +75 -8
- package/wiki/guides/core-concepts/persistent/transactions.md +38 -8
- package/wiki/guides/core-concepts/{controllers.md → rest-controllers.md} +30 -33
- package/wiki/guides/core-concepts/services.md +19 -5
- package/wiki/guides/get-started/5-minute-quickstart.md +6 -7
- package/wiki/guides/get-started/philosophy.md +1 -1
- package/wiki/guides/index.md +2 -2
- package/wiki/guides/reference/glossary.md +7 -7
- package/wiki/guides/reference/mcp-docs-server.md +1 -1
- package/wiki/guides/tutorials/building-a-crud-api.md +2 -2
- package/wiki/guides/tutorials/complete-installation.md +17 -14
- package/wiki/guides/tutorials/ecommerce-api.md +18 -18
- package/wiki/guides/tutorials/realtime-chat.md +8 -8
- package/wiki/guides/tutorials/testing.md +2 -2
- package/wiki/index.md +4 -3
- package/wiki/references/base/application.md +341 -21
- package/wiki/references/base/bootstrapping.md +43 -13
- package/wiki/references/base/components.md +259 -8
- package/wiki/references/base/controllers.md +556 -253
- package/wiki/references/base/datasources.md +159 -79
- package/wiki/references/base/dependency-injection.md +299 -48
- package/wiki/references/base/filter-system/application-usage.md +18 -2
- package/wiki/references/base/filter-system/array-operators.md +14 -6
- package/wiki/references/base/filter-system/comparison-operators.md +9 -3
- package/wiki/references/base/filter-system/default-filter.md +28 -3
- package/wiki/references/base/filter-system/fields-order-pagination.md +17 -13
- package/wiki/references/base/filter-system/index.md +169 -11
- package/wiki/references/base/filter-system/json-filtering.md +51 -18
- package/wiki/references/base/filter-system/list-operators.md +4 -3
- package/wiki/references/base/filter-system/logical-operators.md +7 -2
- package/wiki/references/base/filter-system/null-operators.md +50 -0
- package/wiki/references/base/filter-system/quick-reference.md +82 -243
- package/wiki/references/base/filter-system/range-operators.md +7 -1
- package/wiki/references/base/filter-system/tips.md +34 -7
- package/wiki/references/base/filter-system/use-cases.md +6 -5
- package/wiki/references/base/grpc-controllers.md +984 -0
- package/wiki/references/base/index.md +32 -24
- package/wiki/references/base/middleware.md +347 -0
- package/wiki/references/base/models.md +390 -46
- package/wiki/references/base/providers.md +14 -14
- package/wiki/references/base/repositories/advanced.md +84 -69
- package/wiki/references/base/repositories/index.md +447 -12
- package/wiki/references/base/repositories/mixins.md +103 -98
- package/wiki/references/base/repositories/relations.md +129 -45
- package/wiki/references/base/repositories/soft-deletable.md +104 -23
- package/wiki/references/base/services.md +94 -14
- package/wiki/references/index.md +12 -10
- package/wiki/references/quick-reference.md +98 -65
- package/wiki/references/utilities/crypto.md +21 -4
- package/wiki/references/utilities/date.md +25 -7
- package/wiki/references/utilities/index.md +26 -24
- package/wiki/references/utilities/jsx.md +54 -54
- package/wiki/references/utilities/module.md +8 -6
- package/wiki/references/utilities/parse.md +16 -9
- package/wiki/references/utilities/performance.md +22 -7
- package/wiki/references/utilities/promise.md +19 -16
- package/wiki/references/utilities/request.md +48 -26
- package/wiki/references/utilities/schema.md +69 -6
- package/wiki/references/utilities/statuses.md +131 -140
- /package/wiki/{references → extensions}/components/mail/api.md +0 -0
- /package/wiki/{references → extensions}/components/mail/errors.md +0 -0
- /package/wiki/{references → extensions}/components/mail/usage.md +0 -0
- /package/wiki/{references → extensions}/components/template/api-page.md +0 -0
- /package/wiki/{references → extensions}/components/template/errors-page.md +0 -0
- /package/wiki/{references → extensions}/components/template/usage-page.md +0 -0
- /package/wiki/{references → extensions}/helpers/cron/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/inversion/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/network/api.md +0 -0
- /package/wiki/{references → extensions}/helpers/network/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/redis/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/socket-io/api.md +0 -0
- /package/wiki/{references → extensions}/helpers/socket-io/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/template/single-page.md +0 -0
- /package/wiki/{references → extensions}/helpers/uid/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/websocket/api.md +0 -0
- /package/wiki/{references → extensions}/helpers/worker-thread/index.md +0 -0
- /package/wiki/{references → extensions}/src-details/mcp-server.md +0 -0
|
@@ -7,7 +7,8 @@ Core classes that power every Ignis application - from the Application entry poi
|
|
|
7
7
|
| Class | Purpose | Extends |
|
|
8
8
|
|-------|---------|---------|
|
|
9
9
|
| `BaseApplication` | Application entry point, DI container | `AbstractApplication` |
|
|
10
|
-
| `
|
|
10
|
+
| `BaseRestController` | REST/HTTP route handlers | `AbstractRestController` |
|
|
11
|
+
| `BaseGrpcController` | gRPC route handlers (ConnectRPC) | `AbstractGrpcController` |
|
|
11
12
|
| `BaseService` | Business logic layer | - |
|
|
12
13
|
| `BaseProvider` | Factory pattern for runtime instantiation | `BaseHelper` |
|
|
13
14
|
| `BaseComponent` | Pluggable feature modules | - |
|
|
@@ -19,29 +20,31 @@ Core classes that power every Ignis application - from the Application entry poi
|
|
|
19
20
|
## Architecture
|
|
20
21
|
|
|
21
22
|
```
|
|
22
|
-
|
|
23
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
23
24
|
│ BaseApplication │
|
|
24
25
|
│ (DI Container + Lifecycle + Server Management) │
|
|
25
|
-
|
|
26
|
+
├──────────────────────────────────────────────────────────────┤
|
|
26
27
|
│ │
|
|
27
|
-
│ ┌──────────────┐
|
|
28
|
-
│ │
|
|
29
|
-
│ │
|
|
30
|
-
│ └──────┬───────┘
|
|
31
|
-
│
|
|
32
|
-
│
|
|
33
|
-
│
|
|
34
|
-
│
|
|
35
|
-
│
|
|
36
|
-
│
|
|
37
|
-
│
|
|
38
|
-
│
|
|
39
|
-
│
|
|
40
|
-
│
|
|
41
|
-
│
|
|
42
|
-
│
|
|
43
|
-
│
|
|
44
|
-
│
|
|
28
|
+
│ ┌──────────────────┐ ┌─────────────┐ ┌──────────────┐ │
|
|
29
|
+
│ │BaseRestController │ │ BaseService │ │BaseComponent │ │
|
|
30
|
+
│ │ (REST Layer) │ │(Biz Logic) │ │ (Plugins) │ │
|
|
31
|
+
│ ├──────────────────┤ └──────┬───────┘ └──────────────┘ │
|
|
32
|
+
│ │BaseGrpcController │ │ │
|
|
33
|
+
│ │ (gRPC Layer) │ │ │
|
|
34
|
+
│ └────────┬──────────┘ │ │
|
|
35
|
+
│ └─────────┬─────────┘ │
|
|
36
|
+
│ ▼ │
|
|
37
|
+
│ ┌──────────────────────┐ │
|
|
38
|
+
│ │DefaultCRUDRepository │ │
|
|
39
|
+
│ │ (Data Access) │ │
|
|
40
|
+
│ └──────────┬───────────┘ │
|
|
41
|
+
│ │ │
|
|
42
|
+
│ ┌──────────┴──────────┐ │
|
|
43
|
+
│ ▼ ▼ │
|
|
44
|
+
│ ┌──────────────┐ ┌────────────┐ │
|
|
45
|
+
│ │BaseDataSource │ │ BaseEntity │ │
|
|
46
|
+
│ │(Connection) │ │ (Schema) │ │
|
|
47
|
+
│ └───────────────┘ └────────────┘ │
|
|
45
48
|
│ │
|
|
46
49
|
└──────────────────────────────────────────────────────────────┘
|
|
47
50
|
```
|
|
@@ -52,8 +55,9 @@ Core classes that power every Ignis application - from the Application entry poi
|
|
|
52
55
|
- [Application](./application.md) - `BaseApplication` class, resource registration, lifecycle hooks
|
|
53
56
|
- [Bootstrapping](./bootstrapping.md) - Startup sequence, `initialize()` flow
|
|
54
57
|
|
|
55
|
-
###
|
|
56
|
-
- [Controllers](./controllers.md) -
|
|
58
|
+
### Transport Layer
|
|
59
|
+
- [REST Controllers](./controllers.md) - REST route handlers, decorators, request/response handling
|
|
60
|
+
- [gRPC Controllers](./grpc-controllers.md) - gRPC/ConnectRPC handlers, RPC decorators
|
|
57
61
|
- [Middlewares](./middlewares.md) - Built-in middlewares for error handling, logging, and request processing
|
|
58
62
|
- [Services](./services.md) - Business logic, injectable services
|
|
59
63
|
|
|
@@ -79,7 +83,11 @@ AbstractRepository
|
|
|
79
83
|
│ └── PersistableRepository
|
|
80
84
|
│ └── DefaultCRUDRepository ──────► Your Repository
|
|
81
85
|
│
|
|
82
|
-
|
|
86
|
+
AbstractRestController
|
|
87
|
+
└── BaseRestController ──────► Your REST Controller
|
|
88
|
+
|
|
89
|
+
AbstractGrpcController
|
|
90
|
+
└── BaseGrpcController ──────► Your gRPC Controller
|
|
83
91
|
BaseService ──────► Your Service
|
|
84
92
|
BaseProvider ──────► Your Provider
|
|
85
93
|
BaseComponent ──────► Your Component
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Middleware Reference
|
|
3
|
+
description: Technical reference for built-in middlewares in IGNIS
|
|
4
|
+
difficulty: intermediate
|
|
5
|
+
lastUpdated: 2026-03-15
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Middleware Reference
|
|
9
|
+
|
|
10
|
+
IGNIS provides built-in middleware functions and a provider-based middleware class for handling common HTTP concerns: error handling, request logging, 404 responses, and favicon serving. These are registered automatically by `BaseApplication` during startup.
|
|
11
|
+
|
|
12
|
+
**Files:**
|
|
13
|
+
- `packages/core/src/base/middlewares/app-error.middleware.ts`
|
|
14
|
+
- `packages/core/src/base/middlewares/not-found.middleware.ts`
|
|
15
|
+
- `packages/core/src/base/middlewares/request-spy.middleware.ts`
|
|
16
|
+
- `packages/core/src/base/middlewares/emoji-favicon.middleware.ts`
|
|
17
|
+
|
|
18
|
+
## Prerequisites
|
|
19
|
+
|
|
20
|
+
Before reading this document, you should understand:
|
|
21
|
+
- [Hono middleware](https://hono.dev/docs/guides/middleware) basics
|
|
22
|
+
- [Application lifecycle](./application.md)
|
|
23
|
+
- [Providers](./providers.md) - `RequestSpyMiddleware` implements `IProvider`
|
|
24
|
+
|
|
25
|
+
## Quick Reference
|
|
26
|
+
|
|
27
|
+
| Middleware | Type | Purpose |
|
|
28
|
+
|-----------|------|---------|
|
|
29
|
+
| `appErrorHandler` | `ErrorHandler` | Global error handler (Zod, DB constraints, generic) |
|
|
30
|
+
| `notFoundHandler` | `NotFoundHandler` | JSON 404 response for unknown routes |
|
|
31
|
+
| `RequestSpyMiddleware` | `IProvider<MiddlewareHandler>` | Request/response logging with timing |
|
|
32
|
+
| `emojiFavicon` | `MiddlewareHandler` | Serves an emoji as SVG favicon |
|
|
33
|
+
|
|
34
|
+
## Default Registration Order
|
|
35
|
+
|
|
36
|
+
`BaseApplication.registerDefaultMiddlewares()` registers middleware in this order during `initialize()`:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
protected async registerDefaultMiddlewares() {
|
|
40
|
+
const server = this.getServer();
|
|
41
|
+
|
|
42
|
+
// 1. Global error handler
|
|
43
|
+
server.onError(appErrorHandler({ logger, rootKey }));
|
|
44
|
+
|
|
45
|
+
// 2. Async context storage (if enabled)
|
|
46
|
+
if (this.configs.asyncContext?.enable) {
|
|
47
|
+
server.use(contextStorage());
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 3. Not-found handler
|
|
51
|
+
server.notFound(notFoundHandler({ logger }));
|
|
52
|
+
|
|
53
|
+
// 4. RequestTrackerComponent (requestId + RequestSpyMiddleware)
|
|
54
|
+
this.component(RequestTrackerComponent);
|
|
55
|
+
|
|
56
|
+
// 5. Emoji favicon
|
|
57
|
+
server.use(emojiFavicon({ icon: this.configs.favicon ?? '🔥' }));
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
After `registerDefaultMiddlewares()`, the application calls user-defined `staticConfigure()`, `preConfigure()`, and so on. The user's `setupMiddlewares()` hook runs after `initialize()` but before the server starts.
|
|
62
|
+
|
|
63
|
+
## appErrorHandler
|
|
64
|
+
|
|
65
|
+
Global error handler registered via `server.onError()`. Handles ZodError validation errors, PostgreSQL constraint violations, and generic errors.
|
|
66
|
+
|
|
67
|
+
### Signature
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
function appErrorHandler(opts: {
|
|
71
|
+
logger: Logger;
|
|
72
|
+
rootKey?: string;
|
|
73
|
+
}): ErrorHandler
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
| Parameter | Type | Description |
|
|
77
|
+
|-----------|------|-------------|
|
|
78
|
+
| `logger` | `Logger` | Logger instance for error logging |
|
|
79
|
+
| `rootKey` | `string \| undefined` | Optional root key to wrap the error response object |
|
|
80
|
+
|
|
81
|
+
### Error Handling Logic
|
|
82
|
+
|
|
83
|
+
#### 1. ZodError (Validation Errors)
|
|
84
|
+
|
|
85
|
+
When `error.name === 'ZodError'`, returns HTTP `422 Unprocessable Entity`:
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"message": "ValidationError",
|
|
90
|
+
"statusCode": 422,
|
|
91
|
+
"requestId": "abc-123",
|
|
92
|
+
"details": {
|
|
93
|
+
"url": "http://localhost:3000/users",
|
|
94
|
+
"path": "/users",
|
|
95
|
+
"stack": "...(non-production only)",
|
|
96
|
+
"cause": [
|
|
97
|
+
{
|
|
98
|
+
"path": "email",
|
|
99
|
+
"message": "Invalid email",
|
|
100
|
+
"code": "invalid_string",
|
|
101
|
+
"expected": "string",
|
|
102
|
+
"received": "undefined"
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
#### 2. PostgreSQL Constraint Violations
|
|
110
|
+
|
|
111
|
+
Database errors with recognized SQLSTATE codes return HTTP `400 Bad Request` instead of 500:
|
|
112
|
+
|
|
113
|
+
| SQLSTATE Code | Error Type |
|
|
114
|
+
|--------------|------------|
|
|
115
|
+
| `23505` | Unique constraint violation |
|
|
116
|
+
| `23503` | Foreign key constraint violation |
|
|
117
|
+
| `23502` | Not null constraint violation |
|
|
118
|
+
| `23514` | Check constraint violation |
|
|
119
|
+
| `23P01` | Exclusion constraint violation |
|
|
120
|
+
| `22P02` | Invalid text representation |
|
|
121
|
+
| `22003` | Numeric value out of range |
|
|
122
|
+
| `22001` | String data too long |
|
|
123
|
+
|
|
124
|
+
The error response includes detail, table, and constraint information when available from the database error's `cause` property.
|
|
125
|
+
|
|
126
|
+
#### 3. Generic Errors
|
|
127
|
+
|
|
128
|
+
All other errors use the `statusCode` property from the error if present, otherwise default to HTTP `500 Internal Server Error`.
|
|
129
|
+
|
|
130
|
+
### Response Format
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"message": "Error message",
|
|
135
|
+
"statusCode": 500,
|
|
136
|
+
"requestId": "abc-123",
|
|
137
|
+
"details": {
|
|
138
|
+
"url": "http://localhost:3000/users",
|
|
139
|
+
"path": "/users",
|
|
140
|
+
"stack": "...(non-production only)",
|
|
141
|
+
"cause": "...(non-production only)"
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
When `rootKey` is provided (e.g., `rootKey: 'error'`), the response is wrapped:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"error": {
|
|
151
|
+
"message": "Error message",
|
|
152
|
+
"statusCode": 500,
|
|
153
|
+
"requestId": "abc-123",
|
|
154
|
+
"details": { ... }
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Production behavior:** `stack` and `cause` fields are omitted when `NODE_ENV` is `'production'`.
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
## notFoundHandler
|
|
163
|
+
|
|
164
|
+
Returns a JSON 404 response when no route matches. Registered via `server.notFound()`.
|
|
165
|
+
|
|
166
|
+
### Signature
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
function notFoundHandler(opts: {
|
|
170
|
+
logger?: Logger;
|
|
171
|
+
}): NotFoundHandler
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
| Parameter | Type | Description |
|
|
175
|
+
|-----------|------|-------------|
|
|
176
|
+
| `logger` | `Logger \| undefined` | Logger instance (defaults to `console`) |
|
|
177
|
+
|
|
178
|
+
### Response Format
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{
|
|
182
|
+
"message": "URL NOT FOUND",
|
|
183
|
+
"statusCode": 404,
|
|
184
|
+
"requestId": "abc-123",
|
|
185
|
+
"path": "/unknown",
|
|
186
|
+
"url": "http://localhost:3000/unknown"
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
The handler logs the 404 at error level with the request ID, path, and full URL.
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
## RequestSpyMiddleware
|
|
194
|
+
|
|
195
|
+
A provider-based middleware class that logs incoming request details and outgoing response timing. It extends `BaseHelper` and implements `IProvider<MiddlewareHandler>`.
|
|
196
|
+
|
|
197
|
+
### Class Definition
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
export class RequestSpyMiddleware extends BaseHelper implements IProvider<MiddlewareHandler> {
|
|
201
|
+
static readonly REQUEST_ID_KEY = 'requestId';
|
|
202
|
+
|
|
203
|
+
constructor() {
|
|
204
|
+
super({ scope: 'SpyMW' });
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async parseBody(opts: { req: TContext['req'] }): Promise<unknown>;
|
|
208
|
+
value(): MiddlewareHandler;
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### How It Is Registered
|
|
213
|
+
|
|
214
|
+
`RequestSpyMiddleware` is not registered directly. Instead, `BaseApplication.registerDefaultMiddlewares()` registers a `RequestTrackerComponent`, which:
|
|
215
|
+
|
|
216
|
+
1. Adds the `requestId()` middleware from `hono/request-id` to assign a unique ID to every request
|
|
217
|
+
2. Binds `RequestSpyMiddleware` as a singleton provider in the DI container
|
|
218
|
+
3. Resolves the middleware via `IProvider.value()` and registers it with `server.use()`
|
|
219
|
+
|
|
220
|
+
### Request Logging
|
|
221
|
+
|
|
222
|
+
In **non-production** mode, logs the full request including query and body:
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
[requestId][clientIp][=>] METHOD /path | query: {...} | body: {...}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
In **production** mode, body is excluded:
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
[requestId][clientIp][=>] METHOD /path | query: {...}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Response Logging
|
|
235
|
+
|
|
236
|
+
After the handler completes:
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
[requestId][clientIp][<=] METHOD /path | Took: 12.34 (ms)
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Body Parsing
|
|
243
|
+
|
|
244
|
+
The `parseBody` method parses the request body based on `Content-Type`:
|
|
245
|
+
|
|
246
|
+
| Content-Type | Parse Method |
|
|
247
|
+
|-------------|-------------|
|
|
248
|
+
| `application/json` | `req.json()` |
|
|
249
|
+
| `multipart/form-data` | `req.parseBody()` |
|
|
250
|
+
| `application/x-www-form-urlencoded` | `req.parseBody()` |
|
|
251
|
+
| Other | `req.text()` |
|
|
252
|
+
|
|
253
|
+
Returns `null` if no `Content-Type` header or `Content-Length` is `0`/missing. Throws HTTP 400 `'Malformed Body Payload'` on parse failure.
|
|
254
|
+
|
|
255
|
+
### IP Detection
|
|
256
|
+
|
|
257
|
+
The middleware resolves the client IP from the connection info or falls back to `x-real-ip` / `x-forwarded-for` headers. If neither is available, it throws HTTP 400 `'Malformed Connection Info'`.
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
## emojiFavicon
|
|
261
|
+
|
|
262
|
+
A simple middleware that serves an emoji as an SVG favicon on `/favicon.ico`.
|
|
263
|
+
|
|
264
|
+
### Signature
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
function emojiFavicon(opts: { icon: string }): MiddlewareHandler
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
| Parameter | Type | Description |
|
|
271
|
+
|-----------|------|-------------|
|
|
272
|
+
| `icon` | `string` | Emoji character to use as favicon |
|
|
273
|
+
|
|
274
|
+
### Behavior
|
|
275
|
+
|
|
276
|
+
- Only intercepts requests to `/favicon.ico`
|
|
277
|
+
- Returns an SVG with `content-type: image/svg+xml`
|
|
278
|
+
- All other requests pass through via `next()`
|
|
279
|
+
|
|
280
|
+
**Default icon:** The application uses `this.configs.favicon ?? '🔥'` when registering.
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
## Middleware Configuration via IApplicationConfigs
|
|
284
|
+
|
|
285
|
+
Several middleware behaviors are configured through `IApplicationConfigs`:
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
interface IApplicationConfigs {
|
|
289
|
+
favicon?: string; // Emoji for emojiFavicon (default: '🔥')
|
|
290
|
+
error?: { rootKey: string }; // Root key wrapper for appErrorHandler
|
|
291
|
+
asyncContext?: { enable: boolean }; // Enable Hono contextStorage() middleware
|
|
292
|
+
// ...
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## User-Defined Middlewares
|
|
297
|
+
|
|
298
|
+
The `setupMiddlewares()` abstract method on `AbstractApplication` is called after `initialize()` and before the server starts. Use this hook to register additional Hono middlewares:
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
export class MyApplication extends BaseApplication {
|
|
302
|
+
async setupMiddlewares() {
|
|
303
|
+
const server = this.getServer();
|
|
304
|
+
|
|
305
|
+
// CORS
|
|
306
|
+
server.use(cors({ origin: '*' }));
|
|
307
|
+
|
|
308
|
+
// Body limit
|
|
309
|
+
server.use(bodyLimit({ maxSize: 1024 * 1024 })); // 1MB
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
The `IMiddlewareConfigs` type defines the shape for configurable middleware options:
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
interface IMiddlewareConfigs {
|
|
318
|
+
requestId?: IRequestIdOptions;
|
|
319
|
+
compress?: ICompressOptions;
|
|
320
|
+
cors?: ICORSOptions;
|
|
321
|
+
csrf?: ICSRFOptions;
|
|
322
|
+
bodyLimit?: IBodyLimitOptions;
|
|
323
|
+
ipRestriction?: IBaseMiddlewareOptions & IIPRestrictionRules;
|
|
324
|
+
[extra: string | symbol]: any;
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Each option interface extends `IBaseMiddlewareOptions`:
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
interface IBaseMiddlewareOptions {
|
|
332
|
+
enable: boolean;
|
|
333
|
+
path?: string;
|
|
334
|
+
[extra: string | symbol]: any;
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
## See Also
|
|
340
|
+
|
|
341
|
+
- **Related References:**
|
|
342
|
+
- [Application](./application.md) - Application lifecycle and initialization
|
|
343
|
+
- [Providers](./providers.md) - Provider pattern (`RequestSpyMiddleware` implements `IProvider`)
|
|
344
|
+
- [Components](./components.md) - `RequestTrackerComponent`
|
|
345
|
+
|
|
346
|
+
- **Guides:**
|
|
347
|
+
- [Application Guide](/guides/core-concepts/application/)
|