@venizia/ignis-docs 0.0.4 → 0.0.5
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/package.json +2 -2
- package/wiki/best-practices/code-style-standards/function-patterns.md +31 -5
- package/wiki/best-practices/performance-optimization.md +39 -0
- package/wiki/best-practices/troubleshooting-tips.md +24 -3
- package/wiki/guides/tutorials/realtime-chat.md +724 -460
- package/wiki/references/base/filter-system/json-filtering.md +4 -2
- package/wiki/references/base/middlewares.md +24 -72
- package/wiki/references/base/repositories/advanced.md +83 -0
- package/wiki/references/base/repositories/index.md +1 -1
- package/wiki/references/components/socket-io.md +495 -78
- package/wiki/references/helpers/logger.md +222 -43
- package/wiki/references/helpers/network.md +273 -31
- package/wiki/references/helpers/socket-io.md +881 -71
- package/wiki/references/quick-reference.md +3 -5
- package/wiki/references/src-details/core.md +1 -2
- package/wiki/references/utilities/statuses.md +4 -2
|
@@ -193,5 +193,7 @@ CREATE INDEX idx_metadata_gin ON "Product" USING GIN ("metadata");
|
|
|
193
193
|
// This is safe - no errors, just no matches
|
|
194
194
|
{ where: { 'metadata.nonexistent.field': 'value' } }
|
|
195
195
|
// SQL: "metadata" #>> '{nonexistent,field}' = 'value'
|
|
196
|
-
|
|
197
|
-
|
|
196
|
+
## See Also
|
|
197
|
+
|
|
198
|
+
- [Nested JSON Updates](../repositories/advanced.md#nested-json-updates) - Updating JSON fields
|
|
199
|
+
|
|
@@ -7,7 +7,7 @@ lastUpdated: 2026-01-03
|
|
|
7
7
|
|
|
8
8
|
# Middlewares Reference
|
|
9
9
|
|
|
10
|
-
IGNIS provides a collection of built-in middlewares for common application needs including error handling, request logging,
|
|
10
|
+
IGNIS provides a collection of built-in middlewares for common application needs including error handling, request logging, and favicon serving.
|
|
11
11
|
|
|
12
12
|
**Files:**
|
|
13
13
|
- `packages/core/src/base/middlewares/*.ts`
|
|
@@ -24,16 +24,14 @@ IGNIS provides a collection of built-in middlewares for common application needs
|
|
|
24
24
|
|------------|---------|-------------|
|
|
25
25
|
| `appErrorHandler` | Catches and formats application errors | `logger` |
|
|
26
26
|
| `notFoundHandler` | Handles 404 Not Found responses | `logger` |
|
|
27
|
-
| `
|
|
28
|
-
| `RequestSpyMiddleware` | Logs request lifecycle and timing | None |
|
|
27
|
+
| `RequestSpyMiddleware` | Logs request lifecycle, timing, and parses request body | None |
|
|
29
28
|
| `emojiFavicon` | Serves an emoji as favicon | `icon` |
|
|
30
29
|
|
|
31
30
|
## Table of Contents
|
|
32
31
|
|
|
33
32
|
- [Error Handler (`appErrorHandler`)](#error-handler-apporerrorhandler)
|
|
34
33
|
- [Not Found Handler (`notFoundHandler`)](#not-found-handler-notfoundhandler)
|
|
35
|
-
- [Request
|
|
36
|
-
- [Request Spy (Debug)](#request-spy-debug)
|
|
34
|
+
- [Request Spy (`RequestSpyMiddleware`)](#request-spy-requestspymiddleware)
|
|
37
35
|
- [Emoji Favicon](#emoji-favicon)
|
|
38
36
|
- [Creating Custom Middleware](#creating-custom-middleware)
|
|
39
37
|
- [Middleware Order & Priority](#middleware-order--priority)
|
|
@@ -237,65 +235,23 @@ app.notFound(notFoundHandler({
|
|
|
237
235
|
|
|
238
236
|
---
|
|
239
237
|
|
|
240
|
-
### Request
|
|
238
|
+
### Request Spy (`RequestSpyMiddleware`)
|
|
241
239
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
**File:** `packages/core/src/base/middlewares/request-normalize.middleware.ts`
|
|
245
|
-
|
|
246
|
-
#### How It Works
|
|
247
|
-
|
|
248
|
-
1. **Skip for GET/OPTIONS**: No normalization for read-only requests
|
|
249
|
-
2. **Check Content-Length**: Skip if no body is present (`Content-Length: 0`)
|
|
250
|
-
3. **Check Content-Type**: Only process `application/json` requests
|
|
251
|
-
4. **Pre-parse JSON**: Calls `context.req.json()` to cache the parsed body
|
|
252
|
-
|
|
253
|
-
#### Benefits
|
|
254
|
-
|
|
255
|
-
- Prevents multiple body parsing attempts
|
|
256
|
-
- Ensures body is available for all subsequent middleware/handlers
|
|
257
|
-
- Catches JSON parsing errors early in the request lifecycle
|
|
258
|
-
|
|
259
|
-
#### Usage
|
|
260
|
-
|
|
261
|
-
```typescript
|
|
262
|
-
import { requestNormalize } from '@venizia/ignis';
|
|
263
|
-
|
|
264
|
-
const app = new IgnisApplication({
|
|
265
|
-
// ...
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
// Register as early middleware
|
|
269
|
-
app.use(requestNormalize());
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
:::tip Why Pre-parse?
|
|
273
|
-
Hono's request body can only be read once. This middleware ensures the body is parsed and cached early, making it available to all downstream handlers.
|
|
274
|
-
:::
|
|
275
|
-
|
|
276
|
-
#### API Reference
|
|
277
|
-
|
|
278
|
-
##### `requestNormalize()`
|
|
279
|
-
|
|
280
|
-
**Parameters:** None
|
|
281
|
-
|
|
282
|
-
**Returns:** `MiddlewareHandler` - Hono middleware function
|
|
283
|
-
|
|
284
|
-
---
|
|
285
|
-
|
|
286
|
-
### Request Spy (Debug)
|
|
287
|
-
|
|
288
|
-
Logs detailed information about each request including timing, IP address, method, path, and query parameters.
|
|
240
|
+
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.
|
|
289
241
|
|
|
290
242
|
**File:** `packages/core/src/base/middlewares/request-spy.middleware.ts`
|
|
291
243
|
|
|
292
244
|
#### Features
|
|
293
245
|
|
|
294
|
-
- Request lifecycle logging (
|
|
246
|
+
- Request lifecycle logging (incoming/outgoing)
|
|
295
247
|
- Performance timing tracking
|
|
296
248
|
- IP address extraction (supports `x-real-ip` and `x-forwarded-for` headers)
|
|
297
249
|
- Request ID tracking
|
|
298
|
-
- Query and body parameter logging
|
|
250
|
+
- Query and body parameter logging (body only logged in non-production)
|
|
251
|
+
- **Request body parsing**: Automatically parses and caches request bodies:
|
|
252
|
+
- `application/json` → `req.json()`
|
|
253
|
+
- `multipart/form-data`, `application/x-www-form-urlencoded` → `req.parseBody()`
|
|
254
|
+
- Other content types (text, html, xml) → `req.text()`
|
|
299
255
|
|
|
300
256
|
#### Usage
|
|
301
257
|
|
|
@@ -511,43 +467,39 @@ app.use(cors());
|
|
|
511
467
|
// 2. Request ID generation
|
|
512
468
|
app.use(requestId());
|
|
513
469
|
|
|
514
|
-
// 3. Request spy/logging
|
|
470
|
+
// 3. Request spy/logging (also handles body parsing)
|
|
515
471
|
const requestSpy = new RequestSpyMiddleware();
|
|
516
472
|
app.use(requestSpy.value());
|
|
517
473
|
|
|
518
|
-
// 4.
|
|
519
|
-
app.use(requestNormalize());
|
|
520
|
-
|
|
521
|
-
// 5. Security middleware (helmet, etc.)
|
|
474
|
+
// 4. Security middleware (helmet, etc.)
|
|
522
475
|
app.use(helmet());
|
|
523
476
|
|
|
524
|
-
//
|
|
477
|
+
// 5. Rate limiting
|
|
525
478
|
app.use(rateLimit());
|
|
526
479
|
|
|
527
|
-
//
|
|
480
|
+
// 6. Authentication
|
|
528
481
|
app.use('/api/*', authenticate());
|
|
529
482
|
|
|
530
|
-
//
|
|
483
|
+
// 7. Favicon (can be early or late)
|
|
531
484
|
app.use(emojiFavicon({ icon: '🚀' }));
|
|
532
485
|
|
|
533
|
-
//
|
|
486
|
+
// 8. Application routes
|
|
534
487
|
app.mountControllers();
|
|
535
488
|
|
|
536
|
-
//
|
|
489
|
+
// 9. Error handler (LAST in chain)
|
|
537
490
|
app.onError(appErrorHandler({ logger: app.logger }));
|
|
538
491
|
|
|
539
|
-
//
|
|
492
|
+
// 10. Not found handler (AFTER error handler)
|
|
540
493
|
app.notFound(notFoundHandler({ logger: app.logger }));
|
|
541
494
|
```
|
|
542
495
|
|
|
543
496
|
### Key Principles
|
|
544
497
|
|
|
545
498
|
1. **Request ID First**: Generate request ID before logging
|
|
546
|
-
2. **
|
|
547
|
-
3. **
|
|
548
|
-
4. **
|
|
549
|
-
5. **Error Handler
|
|
550
|
-
6. **404 Handler After Error Handler**: Ensure unhandled routes return 404
|
|
499
|
+
2. **Request Spy Early**: Log and parse request bodies before business logic
|
|
500
|
+
3. **Security Middleware Before Routes**: Protect routes with security checks
|
|
501
|
+
4. **Error Handler Last**: Catch all errors from previous middleware
|
|
502
|
+
5. **404 Handler After Error Handler**: Ensure unhandled routes return 404
|
|
551
503
|
|
|
552
504
|
:::warning Order Matters
|
|
553
505
|
Placing error handler before routes will prevent it from catching route errors. Always register error handlers last.
|
|
@@ -584,7 +536,7 @@ app.use('/api/public/*', rateLimitMiddleware());
|
|
|
584
536
|
const apiMiddleware = (): MiddlewareHandler => {
|
|
585
537
|
return createMiddleware(async (context, next) => {
|
|
586
538
|
// Run multiple middleware in sequence
|
|
587
|
-
await
|
|
539
|
+
await rateLimit()(context, async () => {
|
|
588
540
|
await authenticate()(context, next);
|
|
589
541
|
});
|
|
590
542
|
});
|
|
@@ -513,6 +513,89 @@ await tx.commit();
|
|
|
513
513
|
> See [Default Filter](../filter-system/default-filter.md) for full documentation on configuring model default filters.
|
|
514
514
|
|
|
515
515
|
|
|
516
|
+
## Nested JSON Updates
|
|
517
|
+
|
|
518
|
+
Repositories support updating specific fields within `json` or `jsonb` columns without overwriting the entire object. This is achieved using **JSON Path Notation** in the update data.
|
|
519
|
+
|
|
520
|
+
### Basic Usage
|
|
521
|
+
|
|
522
|
+
Use dot notation keys to target nested properties:
|
|
523
|
+
|
|
524
|
+
```typescript
|
|
525
|
+
// Assume 'metadata' is a JSONB column
|
|
526
|
+
// Current value: { theme: 'light', notifications: { email: true } }
|
|
527
|
+
|
|
528
|
+
await repo.updateById({
|
|
529
|
+
id: '123',
|
|
530
|
+
data: {
|
|
531
|
+
// Update only the theme, preserving other fields
|
|
532
|
+
'metadata.theme': 'dark'
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
// New value: { theme: 'dark', notifications: { email: true } }
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
### Supported Features
|
|
540
|
+
|
|
541
|
+
- **Deep Nesting:** Update properties at any depth (e.g., `settings.display.font.size`).
|
|
542
|
+
- **Array Access:** Update array elements by index (e.g., `tags[0]`).
|
|
543
|
+
- **Auto-Creation:** Creates missing intermediate keys automatically.
|
|
544
|
+
- **Type Safety:** Validates that the target column is a JSON type.
|
|
545
|
+
- **Multiple Updates:** Chain multiple updates to the same or different columns.
|
|
546
|
+
|
|
547
|
+
### Examples
|
|
548
|
+
|
|
549
|
+
#### Deeply Nested Updates
|
|
550
|
+
|
|
551
|
+
```typescript
|
|
552
|
+
await repo.updateById({
|
|
553
|
+
id: '123',
|
|
554
|
+
data: {
|
|
555
|
+
'metadata.settings.display.fontSize': 16,
|
|
556
|
+
'metadata.settings.display.showSidebar': true
|
|
557
|
+
}
|
|
558
|
+
});
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
#### Array Element Updates
|
|
562
|
+
|
|
563
|
+
```typescript
|
|
564
|
+
await repo.updateById({
|
|
565
|
+
id: '123',
|
|
566
|
+
data: {
|
|
567
|
+
// Set the first address as primary
|
|
568
|
+
'metadata.addresses[0].primary': true
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
#### Mixed Updates (Regular + JSON)
|
|
574
|
+
|
|
575
|
+
You can mix regular column updates with JSON path updates:
|
|
576
|
+
|
|
577
|
+
```typescript
|
|
578
|
+
await repo.updateById({
|
|
579
|
+
id: '123',
|
|
580
|
+
data: {
|
|
581
|
+
status: 'active', // Regular column
|
|
582
|
+
'metadata.lastLogin': now, // JSON path
|
|
583
|
+
'preferences.lang': 'en' // Another JSON path
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
### Security & Validation
|
|
589
|
+
|
|
590
|
+
The framework validates JSON paths to prevent SQL injection:
|
|
591
|
+
- **Allowed Characters:** Alphanumeric, underscores `_`, hyphens `-`, and brackets `[]`.
|
|
592
|
+
- **Validation:** Invalid paths (e.g., containing SQL commands or special characters) throw an error before reaching the database.
|
|
593
|
+
- **Values:** Values are safely serialized and parameterized.
|
|
594
|
+
|
|
595
|
+
> [!NOTE]
|
|
596
|
+
> This feature uses PostgreSQL's `jsonb_set` function. It is only available for columns defined as `json` or `jsonb`.
|
|
597
|
+
|
|
598
|
+
|
|
516
599
|
## Quick Reference
|
|
517
600
|
|
|
518
601
|
| Feature | Code |
|
|
@@ -214,7 +214,7 @@ await repo.deleteAll({ where: {}, options: { force: true } });
|
|
|
214
214
|
|
|
215
215
|
- **Repository Topics:**
|
|
216
216
|
- [Relations & Includes](./relations) - Loading related data
|
|
217
|
-
- [Advanced Features](./advanced) - JSON
|
|
217
|
+
- [Advanced Features](./advanced) - JSON updates, transactions, performance tuning
|
|
218
218
|
- [Repository Mixins](./mixins) - Soft delete and auditing
|
|
219
219
|
|
|
220
220
|
- **Filtering:**
|