@venizia/ignis-docs 0.2.0 → 0.2.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 (142) 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 +22 -11
  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 +26 -2
  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 +6 -2
  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 +182 -93
  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 +107 -322
  26. package/content/extensions/components/authentication/api.md +454 -603
  27. package/content/extensions/components/authentication/errors.md +121 -498
  28. package/content/extensions/components/authentication/index.md +88 -801
  29. package/content/extensions/components/authentication/usage.md +207 -956
  30. package/content/extensions/components/authorization/api.md +736 -656
  31. package/content/extensions/components/authorization/errors.md +168 -206
  32. package/content/extensions/components/authorization/index.md +82 -797
  33. package/content/extensions/components/authorization/usage.md +194 -527
  34. package/content/extensions/components/health-check.md +71 -243
  35. package/content/extensions/components/mail/api.md +504 -287
  36. package/content/extensions/components/mail/errors.md +73 -61
  37. package/content/extensions/components/mail/index.md +96 -467
  38. package/content/extensions/components/mail/usage.md +130 -172
  39. package/content/extensions/components/request-tracker.md +66 -173
  40. package/content/extensions/components/socket-io/api.md +195 -13
  41. package/content/extensions/components/socket-io/errors.md +3 -3
  42. package/content/extensions/components/socket-io/index.md +50 -337
  43. package/content/extensions/components/socket-io/usage.md +143 -26
  44. package/content/extensions/components/static-asset/api.md +410 -142
  45. package/content/extensions/components/static-asset/errors.md +110 -53
  46. package/content/extensions/components/static-asset/index.md +79 -608
  47. package/content/extensions/components/static-asset/usage.md +180 -300
  48. package/content/extensions/components/websocket/api.md +275 -399
  49. package/content/extensions/components/websocket/errors.md +47 -56
  50. package/content/extensions/components/websocket/index.md +74 -407
  51. package/content/extensions/components/websocket/usage.md +110 -341
  52. package/content/extensions/helpers/cron/index.md +51 -160
  53. package/content/extensions/helpers/crypto/index.md +62 -483
  54. package/content/extensions/helpers/crypto/reference.md +456 -0
  55. package/content/extensions/helpers/env/index.md +60 -178
  56. package/content/extensions/helpers/error/index.md +221 -207
  57. package/content/extensions/helpers/inversion/index.md +65 -556
  58. package/content/extensions/helpers/inversion/reference.md +522 -0
  59. package/content/extensions/helpers/kafka/admin.md +20 -1
  60. package/content/extensions/helpers/kafka/compile-binary.md +41 -35
  61. package/content/extensions/helpers/kafka/consumer.md +54 -20
  62. package/content/extensions/helpers/kafka/examples.md +21 -16
  63. package/content/extensions/helpers/kafka/index.md +80 -610
  64. package/content/extensions/helpers/kafka/producer.md +134 -5
  65. package/content/extensions/helpers/kafka/schema-registry.md +45 -70
  66. package/content/extensions/helpers/logger/hf-logger.md +193 -0
  67. package/content/extensions/helpers/logger/index.md +64 -563
  68. package/content/extensions/helpers/logger/pino.md +85 -0
  69. package/content/extensions/helpers/logger/reference.md +746 -0
  70. package/content/extensions/helpers/network/api.md +241 -195
  71. package/content/extensions/helpers/network/index.md +72 -530
  72. package/content/extensions/helpers/queue/index.md +72 -900
  73. package/content/extensions/helpers/queue/reference.md +467 -0
  74. package/content/extensions/helpers/redis/index.md +73 -645
  75. package/content/extensions/helpers/redis/reference.md +727 -0
  76. package/content/extensions/helpers/secrets/index.md +66 -0
  77. package/content/extensions/helpers/socket-io/api.md +305 -203
  78. package/content/extensions/helpers/socket-io/index.md +66 -432
  79. package/content/extensions/helpers/storage/api.md +564 -462
  80. package/content/extensions/helpers/storage/index.md +77 -573
  81. package/content/extensions/helpers/types/index.md +66 -499
  82. package/content/extensions/helpers/types/reference.md +650 -0
  83. package/content/extensions/helpers/uid/index.md +58 -227
  84. package/content/extensions/helpers/websocket/api.md +329 -216
  85. package/content/extensions/helpers/websocket/index.md +65 -503
  86. package/content/extensions/helpers/worker-thread/index.md +58 -396
  87. package/content/extensions/helpers/worker-thread/reference.md +428 -0
  88. package/content/guides/core-concepts/persistent/models.md +1 -1
  89. package/content/guides/core-concepts/persistent/search-typesense.md +3 -3
  90. package/content/guides/core-concepts/persistent/transactions.md +1 -1
  91. package/content/guides/core-concepts/secrets-vault.md +177 -0
  92. package/content/guides/core-concepts/services.md +1 -1
  93. package/content/guides/migrations/redis-helpers-migration.md +1 -1
  94. package/content/guides/migrations/unified-connectors-migration.md +2 -2
  95. package/content/guides/tutorials/ecommerce-api.md +3 -8
  96. package/content/references/base/application.md +1 -1
  97. package/content/references/base/connectors.md +79 -136
  98. package/content/references/base/datasources-reference.md +599 -0
  99. package/content/references/base/datasources.md +84 -444
  100. package/content/references/base/dependency-injection.md +17 -39
  101. package/content/references/base/filter-system/application-usage.md +69 -121
  102. package/content/references/base/filter-system/array-operators.md +12 -0
  103. package/content/references/base/filter-system/comparison-operators.md +12 -0
  104. package/content/references/base/filter-system/default-filter.md +136 -348
  105. package/content/references/base/filter-system/fields-order-pagination.md +38 -16
  106. package/content/references/base/filter-system/index.md +106 -257
  107. package/content/references/base/filter-system/json-filtering.md +12 -2
  108. package/content/references/base/filter-system/list-operators.md +16 -2
  109. package/content/references/base/filter-system/logical-operators.md +13 -0
  110. package/content/references/base/filter-system/null-operators.md +13 -0
  111. package/content/references/base/filter-system/pattern-matching.md +12 -0
  112. package/content/references/base/filter-system/quick-reference.md +11 -2
  113. package/content/references/base/filter-system/range-operators.md +12 -0
  114. package/content/references/base/filter-system/tips.md +70 -133
  115. package/content/references/base/filter-system/use-cases.md +156 -233
  116. package/content/references/base/middlewares.md +35 -21
  117. package/content/references/base/models-reference.md +886 -0
  118. package/content/references/base/models.md +80 -1452
  119. package/content/references/base/repositories/advanced.md +156 -192
  120. package/content/references/base/repositories/index.md +77 -650
  121. package/content/references/base/repositories/mixins.md +22 -18
  122. package/content/references/base/repositories/relations.md +123 -171
  123. package/content/references/base/repositories/soft-deletable.md +58 -56
  124. package/content/references/base/secrets.md +263 -0
  125. package/content/references/base/services.md +2 -2
  126. package/content/references/configuration/environment-variables.md +48 -4
  127. package/content/references/configuration/index.md +49 -31
  128. package/content/references/quick-reference.md +3 -16
  129. package/content/references/utilities/crypto.md +35 -76
  130. package/content/references/utilities/date.md +33 -73
  131. package/content/references/utilities/index.md +1 -1
  132. package/content/references/utilities/jsx-reference.md +298 -0
  133. package/content/references/utilities/jsx.md +82 -525
  134. package/content/references/utilities/module.md +29 -62
  135. package/content/references/utilities/parse.md +34 -64
  136. package/content/references/utilities/performance.md +33 -58
  137. package/content/references/utilities/promise.md +28 -62
  138. package/content/references/utilities/request.md +57 -218
  139. package/content/references/utilities/schema.md +43 -137
  140. package/content/references/utilities/statuses-reference.md +361 -0
  141. package/content/references/utilities/statuses.md +63 -667
  142. package/package.json +8 -8
@@ -1,245 +1,84 @@
1
- # Request Utility
2
-
3
- The Request utility provides functions for handling HTTP request data, such as parsing multipart form data, and utilities for creating secure Content-Disposition headers.
4
-
5
- ## `parseMultipartBody`
6
-
7
- The `parseMultipartBody` function is an asynchronous utility for parsing `multipart/form-data` request bodies, which is essential for handling file uploads. It can store the uploaded files in memory or on disk.
8
-
9
- ### `parseMultipartBody(opts)`
10
-
11
- - `opts` (object):
12
- - `context` (object with `req` property): The Hono context object for the current request. Uses `context.req.formData()` internally.
13
- - `storage` (`'memory'` | `'disk'`, optional): The storage strategy for uploaded files. Defaults to `'memory'`.
14
- - `uploadDir` (string, optional): The directory to save files to when using the `'disk'` storage strategy. Defaults to `'./uploads'`. The directory is created recursively if it does not exist.
15
-
16
- The function returns a `Promise` that resolves to an array of `IParsedFile` objects. String form fields are skipped (only `File` entries are processed).
17
-
18
- ### `IParsedFile` Interface
1
+ ---
2
+ title: Request Utility
3
+ description: Multipart form parsing and secure Content-Disposition header helpers for file uploads and downloads
4
+ difficulty: beginner
5
+ lastUpdated: 2026-07-16
6
+ ---
19
7
 
20
- - `fieldname`: The name of the form field.
21
- - `originalname`: The original name of the uploaded file.
22
- - `encoding`: The file's encoding (always `'utf8'`).
23
- - `mimetype`: The MIME type of the file.
24
- - `size`: The size of the file in bytes.
25
- - `buffer` (Buffer, optional): The file's content as a Buffer (if `storage` is `'memory'`).
26
- - `filename` (string, optional): The generated name of the file on disk (if `storage` is `'disk'`). Format: `{timestamp}-{randomString}-{sanitizedOriginalName}`.
27
- - `path` (string, optional): The full path to the file on disk (if `storage` is `'disk'`).
8
+ # Request Utility
28
9
 
29
- ### Example
10
+ Functions for handling HTTP request data: parsing `multipart/form-data` bodies for file uploads, and building safe, RFC-compliant `Content-Disposition` headers for downloads.
30
11
 
31
- Here is an example of how to use `parseMultipartBody` in a controller to handle a file upload.
12
+ ## In one example
32
13
 
33
14
  ```typescript
34
15
  import { BaseRestController, controller } from '@venizia/ignis';
35
- import { parseMultipartBody, HTTP } from '@venizia/ignis-helpers';
16
+ import { parseMultipartBody, createContentDispositionHeader, HTTP } from '@venizia/ignis-helpers';
36
17
 
37
18
  @controller({ path: '/files' })
38
19
  export class FileController extends BaseRestController {
39
- // ...
40
20
  override binding() {
41
- this.defineRoute({
42
- configs: {
43
- path: '/upload',
44
- method: 'post',
45
- // Note: You would typically define a request body schema
46
- // for multipart/form-data in your OpenAPI spec.
21
+ this.bindRoute({ configs: { path: '/upload', method: 'post' } }).to({
22
+ handler: async (ctx) => {
23
+ const files = await parseMultipartBody({ context: ctx, storage: 'disk', uploadDir: './uploads' });
24
+ return ctx.json(
25
+ { message: 'Uploaded', files: files.map(f => ({ name: f.originalname, size: f.size })) },
26
+ HTTP.ResultCodes.RS_2.Ok,
27
+ );
47
28
  },
48
- handler: async (c) => {
49
- try {
50
- const files = await parseMultipartBody({
51
- context: c,
52
- storage: 'disk', // or 'memory'
53
- uploadDir: './my-uploads',
54
- });
55
-
56
- console.log('Uploaded files:', files);
57
-
58
- return c.json(
59
- { message: `${files.length} file(s) uploaded successfully.` },
60
- HTTP.ResultCodes.RS_2.Ok,
61
- );
62
- } catch (error) {
63
- return c.json(
64
- { message: 'Failed to upload files', error: error.message },
65
- HTTP.ResultCodes.RS_5.InternalServerError,
66
- );
67
- }
29
+ });
30
+
31
+ this.bindRoute({ configs: { path: '/:filename', method: 'get' } }).to({
32
+ handler: (ctx) => {
33
+ const { filename } = ctx.req.valid('param');
34
+ ctx.header(
35
+ 'content-disposition',
36
+ createContentDispositionHeader({ filename, type: 'attachment' }),
37
+ );
38
+ // ... stream the file
68
39
  },
69
40
  });
70
41
  }
71
42
  }
72
43
  ```
73
44
 
74
- ---
75
-
76
- ## Content-Disposition Utilities
77
-
78
- These utilities help create secure, RFC-compliant `Content-Disposition` headers for file downloads.
79
-
80
- ### `createContentDispositionHeader`
81
-
82
- Creates a safe Content-Disposition header with proper filename encoding for file downloads.
83
-
84
- #### `createContentDispositionHeader(opts)`
85
-
86
- - `opts` (object):
87
- - `filename` (string): The filename to use in the Content-Disposition header.
88
- - `type` (`'attachment'` | `'inline'`): The disposition type.
89
-
90
- The function returns a properly formatted `Content-Disposition` header string with both ASCII and UTF-8 encoded filenames for maximum browser compatibility.
91
-
92
- **Features:**
93
- - Automatic filename sanitization via `sanitizeFilename()`
94
- - UTF-8 encoding support via `encodeRFC5987()`
95
- - RFC 5987 compliant
96
- - Dual `filename` / `filename*` for browser compatibility
97
-
98
- **Example:**
99
-
100
- ```typescript
101
- import { createContentDispositionHeader } from '@venizia/ignis-helpers';
102
-
103
- // Attachment (file download)
104
- ctx.header('content-disposition', createContentDispositionHeader({
105
- filename: 'my-document.pdf',
106
- type: 'attachment',
107
- }));
108
- // Output: attachment; filename="my-document.pdf"; filename*=UTF-8''my-document.pdf
109
-
110
- // Inline (display in browser)
111
- ctx.header('content-disposition', createContentDispositionHeader({
112
- filename: 'report.pdf',
113
- type: 'inline',
114
- }));
115
- // Output: inline; filename="report.pdf"; filename*=UTF-8''report.pdf
116
- ```
117
-
118
- ---
119
-
120
- ### `sanitizeFilename`
121
-
122
- Sanitizes a filename for safe use, removing path components and dangerous characters. Useful for HTTP headers (e.g., Content-Disposition) and general file handling.
123
-
124
- #### `sanitizeFilename(filename: string): string`
125
-
126
- - `filename` (string): The filename to sanitize.
127
-
128
- Returns a safe filename suitable for use in headers or filesystem operations.
129
-
130
- **Features:**
131
- - Removes path components via `path.basename()` (prevents directory traversal attacks)
132
- - Allows only word characters (`\w`), spaces, hyphens, underscores, and dots
133
- - Replaces dangerous characters with underscores
134
- - Removes leading dots (prevents hidden files)
135
- - Replaces consecutive dots with a single dot
136
- - Removes ".." patterns (additional path traversal protection)
137
- - Returns `'download'` for empty, suspicious, or invalid filenames
138
-
139
- **Example:**
140
-
141
- ```typescript
142
- import { sanitizeFilename } from '@venizia/ignis-helpers';
143
-
144
- sanitizeFilename('../../etc/passwd'); // Returns: 'passwd'
145
- sanitizeFilename('my<file>name.txt'); // Returns: 'my_file_name.txt'
146
- sanitizeFilename('.hidden'); // Returns: 'hidden'
147
- sanitizeFilename('file...txt'); // Returns: 'file.txt'
148
- sanitizeFilename(''); // Returns: 'download'
149
- sanitizeFilename('..'); // Returns: 'download'
150
- ```
151
-
152
-
153
- ### `encodeRFC5987`
154
-
155
- Encodes a filename according to RFC 5987 for use in HTTP headers. Encodes using `encodeURIComponent` and additionally escapes single quotes, parentheses, and asterisks.
156
-
157
- #### `encodeRFC5987(filename: string): string`
158
-
159
- - `filename` (string): The filename to encode.
160
-
161
- Returns an RFC 5987 encoded string suitable for the `filename*` parameter in Content-Disposition headers.
162
-
163
- **Example:**
164
-
165
- ```typescript
166
- import { encodeRFC5987 } from '@venizia/ignis-helpers';
167
-
168
- encodeRFC5987('my document.pdf'); // Returns: 'my%20document.pdf'
169
- ```
170
-
45
+ ## Functions
171
46
 
172
- ## `IRequestedRemark` Interface
47
+ | Function | Signature | What it does |
48
+ |----------|-----------|---------------|
49
+ | `parseMultipartBody` | `parseMultipartBody(opts: { context: { req: any }; storage?: 'memory' \| 'disk'; uploadDir?: string }): Promise<IParsedFile[]>` | Parses a `multipart/form-data` body via `context.req.formData()`. String fields are skipped - only `File` entries are returned. |
50
+ | `sanitizeFilename` | `sanitizeFilename(filename: string): string` | Strips path components and dangerous characters from `filename`. Returns `'download'` for empty or suspicious input. |
51
+ | `encodeRFC5987` | `encodeRFC5987(filename: string): string` | RFC 5987 encodes `filename` for the `filename*` header parameter (`encodeURIComponent` plus escaped `'`, `(`, `)`, `*`). |
52
+ | `createContentDispositionHeader` | `createContentDispositionHeader(opts: { filename: string; type: 'attachment' \| 'inline' }): string` | Builds a full `Content-Disposition` value: sanitizes the filename, then emits both the ASCII `filename=` and UTF-8 `filename*=` forms. |
173
53
 
174
- The Request utility also exports the `IRequestedRemark` interface, which describes a request remark object:
54
+ ## Parsed file shape
175
55
 
176
- - `id` (string): The request identifier.
177
- - `url` (string): The request URL.
178
- - `method` (string): The HTTP method.
179
- - `[extra: string | symbol]`: Additional arbitrary properties.
56
+ `parseMultipartBody` resolves to an array of objects (the `IParsedFile` shape, internal to the module - not separately exported):
180
57
 
58
+ | Field | Type | Present when |
59
+ |-------|------|---------------|
60
+ | `fieldname` | `string` | always |
61
+ | `originalname` | `string` | always |
62
+ | `encoding` | `string` | always - hardcoded `'utf8'` |
63
+ | `mimetype` | `string` | always |
64
+ | `size` | `number` | always |
65
+ | `buffer` | `Buffer` | `storage: 'memory'` (default) |
66
+ | `filename` | `string` | `storage: 'disk'` - format `{timestamp}-{randomString}-{sanitizedOriginalName}` |
67
+ | `path` | `string` | `storage: 'disk'` |
181
68
 
182
- ## Complete File Download Example
69
+ ## Notes
183
70
 
184
- Here's a complete example combining multipart upload parsing with secure file downloads:
71
+ - **`storage` defaults to `'memory'`**; `uploadDir` defaults to `'./uploads'` and is created recursively if it does not exist.
72
+ - **`sanitizeFilename` is applied automatically** inside `createContentDispositionHeader` - callers do not need to sanitize twice. It also removes leading dots, collapses repeated dots, and strips `..` sequences to block directory traversal and hidden-file tricks.
73
+ - **`createContentDispositionHeader` always emits both forms** (`filename="..."; filename*=UTF-8''...`) for maximum browser compatibility - older browsers read the ASCII fallback, modern ones read the UTF-8 form.
74
+ - **`IRequestedRemark`** is a separately exported interface for describing a request: `{ id: string; url: string; method: string; [extra: string | symbol]: any }`. It is not consumed internally by `parseMultipartBody` or any other function on this page - it is a general-purpose shape for application code that needs to tag a request with an id, URL, method, and arbitrary extra fields.
185
75
 
186
- ```typescript
187
- import { BaseRestController, controller } from '@venizia/ignis';
188
- import { parseMultipartBody, createContentDispositionHeader, HTTP } from '@venizia/ignis-helpers';
189
- import fs from 'node:fs';
190
- import path from 'node:path';
76
+ ## See also
191
77
 
192
- @controller({ path: '/files' })
193
- export class FileController extends BaseRestController {
194
- override binding() {
195
- // Upload endpoint
196
- this.bindRoute({
197
- configs: { path: '/upload', method: 'post' },
198
- }).to({
199
- handler: async (ctx) => {
200
- const files = await parseMultipartBody({
201
- context: ctx,
202
- storage: 'disk',
203
- uploadDir: './uploads',
204
- });
78
+ - [Utilities Overview](/references/utilities/) - all utility functions
79
+ - [Static Asset Component](/extensions/components/static-asset/) - built-in upload/download CRUD built on this utility
80
+ - [Request Tracker Component](/extensions/components/request-tracker) - `x-request-id` header and request body parsing
205
81
 
206
- return ctx.json(
207
- {
208
- message: 'Files uploaded successfully',
209
- files: files.map(f => ({ name: f.originalname, size: f.size })),
210
- },
211
- HTTP.ResultCodes.RS_2.Ok,
212
- );
213
- },
214
- });
82
+ **Files:**
215
83
 
216
- // Download endpoint
217
- this.bindRoute({
218
- configs: { path: '/:filename', method: 'get' },
219
- }).to({
220
- handler: async (ctx) => {
221
- const { filename } = ctx.req.valid('param');
222
- const filePath = path.join('./uploads', filename);
223
-
224
- // Read file
225
- const fileStat = fs.statSync(filePath);
226
- const fileStream = fs.createReadStream(filePath);
227
-
228
- // Set secure headers
229
- ctx.header('content-type', 'application/octet-stream');
230
- ctx.header('content-length', fileStat.size.toString());
231
- ctx.header('content-disposition', createContentDispositionHeader({
232
- filename,
233
- type: 'attachment',
234
- }));
235
- ctx.header('x-content-type-options', 'nosniff');
236
-
237
- return new Response(fileStream, {
238
- headers: ctx.res.headers,
239
- status: HTTP.ResultCodes.RS_2.Ok,
240
- });
241
- },
242
- });
243
- }
244
- }
245
- ```
84
+ - [`packages/helpers/src/utilities/request.utility.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/utilities/request.utility.ts)
@@ -1,162 +1,68 @@
1
- # Schema Utility
2
-
3
- The Schema utility provides a set of helper functions and predefined schemas for working with `zod` and `@hono/zod-openapi`. These utilities simplify the process of defining API request/response schemas and improve consistency in your API documentation.
4
-
5
- ## `jsonContent`
6
-
7
- The `jsonContent` function creates a standard OpenAPI content object for `application/json` payloads.
1
+ ---
2
+ title: Schema Utility
3
+ description: Zod and OpenAPI helpers for JSON response schemas, path params, string constraints, and case conversion
4
+ difficulty: beginner
5
+ lastUpdated: 2026-07-16
6
+ ---
8
7
 
9
- ### `jsonContent(opts)`
10
-
11
- - `opts` (object):
12
- - `schema` (ZodType): The Zod schema describing the JSON payload.
13
- - `description` (string): A description of the content.
14
- - `required` (boolean, optional): Whether the content is required.
15
-
16
- ```typescript
17
- import { jsonContent } from '@venizia/ignis';
18
- import { z } from '@hono/zod-openapi';
19
-
20
- const UserSchema = z.object({
21
- id: z.number(),
22
- name: z.string(),
23
- });
24
-
25
- const userResponse = {
26
- description: 'A single user object',
27
- ...jsonContent({ schema: UserSchema, description: 'User data' }),
28
- };
29
- ```
30
-
31
- ## `jsonResponse`
32
-
33
- The `jsonResponse` function generates a standard OpenAPI response object that includes a success (200 OK) response and a default error response for `4xx | 5xx` status codes. The error response uses the `ErrorSchema`.
8
+ # Schema Utility
34
9
 
35
- ### `jsonResponse(opts)`
10
+ Helper functions and predefined schemas for working with `zod` and `@hono/zod-openapi` - building JSON request/response schemas, path-param schemas, and case-converting schemas for API routes.
36
11
 
37
- - `opts` (object):
38
- - `schema` (ZodType): The Zod schema for the success response body.
39
- - `description` (string, optional): A description for the success response. Defaults to `'Success Response'`.
40
- - `required` (boolean, optional): Whether the content is required.
41
- - `headers` (Record&lt;string, THeaderObject&gt;, optional): Custom response headers to include in the success response.
12
+ ## In one example
42
13
 
43
14
  ```typescript
44
- import { jsonResponse } from '@venizia/ignis';
15
+ import { jsonResponse, requiredString, idParamsSchema } from '@venizia/ignis';
45
16
  import { z } from '@hono/zod-openapi';
46
17
 
47
- const UserSchema = z.object({
48
- id: z.number(),
49
- name: z.string(),
50
- });
18
+ const UserSchema = z.object({ id: z.number(), name: requiredString({ min: 1, max: 50 }) });
51
19
 
52
20
  this.defineRoute({
53
21
  configs: {
54
- path: '/',
22
+ path: '/{id}',
55
23
  method: 'get',
56
- responses: jsonResponse({
57
- description: 'A single user object',
58
- schema: UserSchema,
59
- }),
24
+ request: { params: idParamsSchema({ idType: 'number' }) },
25
+ responses: jsonResponse({ schema: UserSchema, description: 'A single user object' }),
60
26
  },
61
- // ...
62
- });
63
-
64
- // With custom headers
65
- this.defineRoute({
66
- configs: {
67
- path: '/list',
68
- method: 'get',
69
- responses: jsonResponse({
70
- schema: z.array(UserSchema),
71
- description: 'User list',
72
- headers: {
73
- 'x-total-count': {
74
- description: 'Total number of records',
75
- schema: { type: 'string', examples: ['100'] },
76
- },
77
- },
78
- }),
27
+ handler: (c) => {
28
+ const { id } = c.req.valid('param');
29
+ // ...
79
30
  },
80
- // ...
81
31
  });
82
32
  ```
83
33
 
84
- ## `requiredString`
34
+ ## Functions
85
35
 
86
- This function creates a `zod` string schema that is non-empty (`nonempty()`) and can be further constrained by length.
36
+ | Function | Signature | What it does |
37
+ |----------|-----------|---------------|
38
+ | `jsonContent` | `jsonContent(opts: { schema: ZodType; description: string; required?: boolean }): { description; content; required }` | Builds a standard OpenAPI content object for an `application/json` payload. |
39
+ | `jsonResponse` | `jsonResponse(opts: { schema: ZodType; description?: string; required?: boolean; headers?: Record<string, THeaderObject> }): Record<number \| string, ...>` | Builds a full response map: `200` success (via `jsonContent`, description defaults to `'Success Response'`) plus a `'4xx \| 5xx'` error entry using `ErrorSchema`. |
40
+ | `requiredString` | `requiredString(opts?: { min?: number; max?: number; fixed?: number }): ZodString` | A non-empty (`.nonempty()`) Zod string, optionally constrained by `min`, `max`, or an exact `fixed` length. |
41
+ | `idParamsSchema` | `idParamsSchema(opts?: { idType?: 'number' \| 'string' }): ZodObject` | Builds a path-param schema for `{ id }`, typed and OpenAPI-documented as `number` (default) or `string`. Throws on any other `idType`. |
42
+ | `snakeToCamel` | `snakeToCamel<T extends ZodRawShape>(shape: T): ZodEffects` | Wraps a Zod object `shape` so it accepts `snake_case` input keys and produces a `camelCase`-keyed output, via `.transform()` piped into a camelCase-shaped schema. |
87
43
 
88
- ### `requiredString(opts?)`
44
+ ## Predefined schemas and types
89
45
 
90
- - `opts` (object, optional):
91
- - `min` (number, optional): Minimum string length.
92
- - `max` (number, optional): Maximum string length.
93
- - `fixed` (number, optional): Exact string length (uses `.length()`).
46
+ | Export | What it is |
47
+ |--------|------------|
48
+ | `AnyObjectSchema` | `z.object().catchall(z.any())`, OpenAPI-described as `'Unknown schema'` - a permissive object schema. |
49
+ | `TAnyObjectSchema` | Type alias for `z.ZodObject<z.ZodRawShape>`. |
50
+ | `TInferSchema<T>` | Type alias for `z.infer<T>` - the TypeScript type inferred from a Zod schema `T`. |
94
51
 
95
- ```typescript
96
- import { requiredString } from '@venizia/ignis';
52
+ ## Notes
97
53
 
98
- const schema = z.object({
99
- username: requiredString({ min: 3, max: 20 }),
100
- password: requiredString({ min: 8 }),
101
- countryCode: requiredString({ fixed: 2 }),
102
- });
103
- ```
104
-
105
- ## Predefined Schemas
54
+ - **Two source files, one page.** `requiredString`, `AnyObjectSchema`, `TAnyObjectSchema`, and `TInferSchema` live in `schema.utility.ts`; `jsonContent`, `jsonResponse`, `idParamsSchema`, and `snakeToCamel` live in `base/models/common/types.ts`. Both are re-exported from the `@venizia/ignis` root barrel, so the import path is the same either way.
55
+ - **`jsonResponse`'s error branch is fixed** - it always uses `ErrorSchema` under the `'4xx | 5xx'` key; only the success schema, description, and headers are customizable per call.
56
+ - **HTML responses are a separate utility.** For `text/html` routes, use `htmlContent`/`htmlResponse` from the [JSX Utility](/references/utilities/jsx) instead of `jsonContent`/`jsonResponse`.
106
57
 
107
- - **`AnyObjectSchema`**: A flexible schema for any object (`z.object().catchall(z.any())`), with an OpenAPI description of `'Unknown schema'`.
58
+ ## See also
108
59
 
109
- ### Type Utilities
60
+ - [Utilities Overview](/references/utilities/) - all utility functions
61
+ - [JSX Utility](/references/utilities/jsx) - `htmlContent()` / `htmlResponse()` for HTML routes
62
+ - [Parse Utility](/references/utilities/parse) - `toCamel()` / `keysToCamel()`, the transforms `snakeToCamel` builds on
63
+ - [REST Controllers Guide](/guides/core-concepts/rest-controllers) - defining routes with `request`/`responses`
110
64
 
111
- ```typescript
112
- import { TAnyObjectSchema, TInferSchema } from '@venizia/ignis';
65
+ **Files:**
113
66
 
114
- // TAnyObjectSchema = z.ZodObject<z.ZodRawShape>
115
- // TInferSchema<T> = z.infer<T> - infer TypeScript type from a Zod schema
116
-
117
- type UserType = TInferSchema<typeof UserSchema>;
118
- ```
119
-
120
- ## `snakeToCamel`
121
-
122
- Transforms a Zod object shape from snake_case keys to camelCase. Uses `.transform()` and `.pipe()` to create a schema that accepts snake_case input but produces camelCase output.
123
-
124
- ```typescript
125
- import { snakeToCamel } from '@venizia/ignis';
126
-
127
- const schema = snakeToCamel({
128
- first_name: z.string(),
129
- last_name: z.string(),
130
- });
131
-
132
- // Input: { first_name: 'John', last_name: 'Doe' }
133
- // Output: { firstName: 'John', lastName: 'Doe' }
134
- ```
135
-
136
- ## Custom ID Params
137
-
138
- Use the `idParamsSchema()` helper to generate path parameter schemas for resource IDs:
139
-
140
- ### `idParamsSchema(opts?)`
141
-
142
- - `opts` (object, optional):
143
- - `idType` (string): `'number'` (default) or `'string'`.
144
-
145
- ```typescript
146
- import { idParamsSchema } from '@venizia/ignis';
147
-
148
- this.defineRoute({
149
- configs: {
150
- path: '/{id}',
151
- method: 'get',
152
- request: {
153
- params: idParamsSchema({ idType: 'number' }),
154
- },
155
- // ...
156
- },
157
- handler: (c) => {
158
- const { id } = c.req.valid('param');
159
- // ...
160
- },
161
- });
162
- ```
67
+ - [`packages/core/src/utilities/schema.utility.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/utilities/schema.utility.ts)
68
+ - [`packages/core/src/base/models/common/types.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/base/models/common/types.ts)