@venizia/ignis-docs 0.0.5 → 0.0.6-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 (98) hide show
  1. package/package.json +1 -1
  2. package/wiki/best-practices/architecture-decisions.md +0 -8
  3. package/wiki/best-practices/code-style-standards/control-flow.md +1 -1
  4. package/wiki/best-practices/performance-optimization.md +3 -3
  5. package/wiki/best-practices/security-guidelines.md +2 -2
  6. package/wiki/best-practices/troubleshooting-tips.md +1 -1
  7. package/wiki/guides/core-concepts/components-guide.md +1 -1
  8. package/wiki/guides/core-concepts/components.md +2 -2
  9. package/wiki/guides/core-concepts/dependency-injection.md +1 -1
  10. package/wiki/guides/core-concepts/services.md +1 -1
  11. package/wiki/guides/tutorials/building-a-crud-api.md +1 -1
  12. package/wiki/guides/tutorials/ecommerce-api.md +2 -2
  13. package/wiki/guides/tutorials/realtime-chat.md +6 -6
  14. package/wiki/guides/tutorials/testing.md +1 -1
  15. package/wiki/references/base/bootstrapping.md +0 -2
  16. package/wiki/references/base/components.md +2 -2
  17. package/wiki/references/base/controllers.md +0 -1
  18. package/wiki/references/base/datasources.md +1 -1
  19. package/wiki/references/base/dependency-injection.md +1 -1
  20. package/wiki/references/base/filter-system/quick-reference.md +0 -14
  21. package/wiki/references/base/middlewares.md +0 -8
  22. package/wiki/references/base/providers.md +0 -9
  23. package/wiki/references/base/services.md +0 -1
  24. package/wiki/references/components/authentication/api.md +444 -0
  25. package/wiki/references/components/authentication/errors.md +177 -0
  26. package/wiki/references/components/authentication/index.md +571 -0
  27. package/wiki/references/components/authentication/usage.md +781 -0
  28. package/wiki/references/components/health-check.md +292 -103
  29. package/wiki/references/components/index.md +14 -12
  30. package/wiki/references/components/mail/api.md +505 -0
  31. package/wiki/references/components/mail/errors.md +176 -0
  32. package/wiki/references/components/mail/index.md +535 -0
  33. package/wiki/references/components/mail/usage.md +404 -0
  34. package/wiki/references/components/request-tracker.md +229 -25
  35. package/wiki/references/components/socket-io/api.md +1051 -0
  36. package/wiki/references/components/socket-io/errors.md +119 -0
  37. package/wiki/references/components/socket-io/index.md +410 -0
  38. package/wiki/references/components/socket-io/usage.md +322 -0
  39. package/wiki/references/components/static-asset/api.md +261 -0
  40. package/wiki/references/components/static-asset/errors.md +89 -0
  41. package/wiki/references/components/static-asset/index.md +617 -0
  42. package/wiki/references/components/static-asset/usage.md +364 -0
  43. package/wiki/references/components/swagger.md +390 -110
  44. package/wiki/references/components/template/api-page.md +125 -0
  45. package/wiki/references/components/template/errors-page.md +100 -0
  46. package/wiki/references/components/template/index.md +104 -0
  47. package/wiki/references/components/template/setup-page.md +134 -0
  48. package/wiki/references/components/template/single-page.md +132 -0
  49. package/wiki/references/components/template/usage-page.md +127 -0
  50. package/wiki/references/components/websocket/api.md +508 -0
  51. package/wiki/references/components/websocket/errors.md +123 -0
  52. package/wiki/references/components/websocket/index.md +453 -0
  53. package/wiki/references/components/websocket/usage.md +475 -0
  54. package/wiki/references/helpers/cron/index.md +224 -0
  55. package/wiki/references/helpers/crypto/index.md +537 -0
  56. package/wiki/references/helpers/env/index.md +214 -0
  57. package/wiki/references/helpers/error/index.md +232 -0
  58. package/wiki/references/helpers/index.md +16 -15
  59. package/wiki/references/helpers/inversion/index.md +608 -0
  60. package/wiki/references/helpers/logger/index.md +600 -0
  61. package/wiki/references/helpers/network/api.md +986 -0
  62. package/wiki/references/helpers/network/index.md +620 -0
  63. package/wiki/references/helpers/queue/index.md +589 -0
  64. package/wiki/references/helpers/redis/index.md +495 -0
  65. package/wiki/references/helpers/socket-io/api.md +497 -0
  66. package/wiki/references/helpers/socket-io/index.md +513 -0
  67. package/wiki/references/helpers/storage/api.md +705 -0
  68. package/wiki/references/helpers/storage/index.md +583 -0
  69. package/wiki/references/helpers/template/index.md +66 -0
  70. package/wiki/references/helpers/template/single-page.md +126 -0
  71. package/wiki/references/helpers/testing/index.md +510 -0
  72. package/wiki/references/helpers/types/index.md +512 -0
  73. package/wiki/references/helpers/uid/index.md +272 -0
  74. package/wiki/references/helpers/websocket/api.md +736 -0
  75. package/wiki/references/helpers/websocket/index.md +574 -0
  76. package/wiki/references/helpers/worker-thread/index.md +470 -0
  77. package/wiki/references/quick-reference.md +3 -18
  78. package/wiki/references/utilities/jsx.md +1 -8
  79. package/wiki/references/utilities/statuses.md +0 -7
  80. package/wiki/references/components/authentication.md +0 -476
  81. package/wiki/references/components/mail.md +0 -687
  82. package/wiki/references/components/socket-io.md +0 -562
  83. package/wiki/references/components/static-asset.md +0 -1277
  84. package/wiki/references/helpers/cron.md +0 -108
  85. package/wiki/references/helpers/crypto.md +0 -132
  86. package/wiki/references/helpers/env.md +0 -83
  87. package/wiki/references/helpers/error.md +0 -97
  88. package/wiki/references/helpers/inversion.md +0 -176
  89. package/wiki/references/helpers/logger.md +0 -296
  90. package/wiki/references/helpers/network.md +0 -396
  91. package/wiki/references/helpers/queue.md +0 -150
  92. package/wiki/references/helpers/redis.md +0 -142
  93. package/wiki/references/helpers/socket-io.md +0 -932
  94. package/wiki/references/helpers/storage.md +0 -665
  95. package/wiki/references/helpers/testing.md +0 -133
  96. package/wiki/references/helpers/types.md +0 -167
  97. package/wiki/references/helpers/uid.md +0 -167
  98. package/wiki/references/helpers/worker-thread.md +0 -178
@@ -0,0 +1,364 @@
1
+ # Static Asset -- Usage & Examples
2
+
3
+ > API endpoint specifications, request/response details, and frontend integration examples.
4
+
5
+ ## API Endpoints
6
+
7
+ The component dynamically generates REST endpoints for each configured storage backend. All backends expose the same API structure under their configured `basePath`.
8
+
9
+ | Method | Path | Description |
10
+ |--------|------|-------------|
11
+ | `GET` | <code v-pre>/{basePath}/buckets</code> | List all buckets |
12
+ | `GET` | <code v-pre>/{basePath}/buckets/:bucketName</code> | Get bucket by name |
13
+ | `POST` | <code v-pre>/{basePath}/buckets/:bucketName</code> | Create a bucket |
14
+ | `DELETE` | <code v-pre>/{basePath}/buckets/:bucketName</code> | Delete a bucket |
15
+ | `POST` | <code v-pre>/{basePath}/buckets/:bucketName/upload</code> | Upload files |
16
+ | `GET` | <code v-pre>/{basePath}/buckets/:bucketName/objects</code> | List objects |
17
+ | `GET` | <code v-pre>/{basePath}/buckets/:bucketName/objects/:objectName</code> | Stream file |
18
+ | `GET` | <code v-pre>/{basePath}/buckets/:bucketName/objects/:objectName/download</code> | Download file |
19
+ | `DELETE` | <code v-pre>/{basePath}/buckets/:bucketName/objects/:objectName</code> | Delete object |
20
+ | `PUT` | <code v-pre>/{basePath}/buckets/:bucketName/objects/:objectName/meta-links</code> | Sync MetaLink (MetaLink only) |
21
+
22
+ #### GET <code v-pre>/{basePath}/buckets</code>
23
+ **Response `200`:**
24
+ ```json
25
+ [
26
+ { "name": "my-bucket", "creationDate": "2025-01-01T00:00:00.000Z" }
27
+ ]
28
+ ```
29
+
30
+ #### GET <code v-pre>/{basePath}/buckets/:bucketName</code>
31
+ **Parameters:**
32
+ - `bucketName` (path): Bucket name
33
+
34
+ **Validation:** Bucket name validated with `isValidName()`. Returns 400 `"Invalid bucket name"` if invalid.
35
+
36
+ **Response `200`:**
37
+ ```json
38
+ { "name": "my-bucket", "creationDate": "2025-01-01T00:00:00.000Z" }
39
+ ```
40
+
41
+ Returns `null` when the bucket does not exist. The response schema is nullable.
42
+
43
+ #### POST <code v-pre>/{basePath}/buckets/:bucketName</code>
44
+ **Parameters:**
45
+ - `bucketName` (path): Name of the new bucket
46
+
47
+ **Validation:** Bucket name validated with `isValidName()`. Returns 400 `"Invalid bucket name"` if invalid.
48
+
49
+ **Response `200`:**
50
+ ```json
51
+ { "name": "my-bucket", "creationDate": "2025-12-13T00:00:00.000Z" }
52
+ ```
53
+
54
+ Returns `null` if bucket creation fails (e.g., already exists). The response schema is nullable.
55
+
56
+ #### DELETE <code v-pre>/{basePath}/buckets/:bucketName</code>
57
+ **Parameters:**
58
+ - `bucketName` (path): Bucket to delete
59
+
60
+ **Validation:** Bucket name validated with `isValidName()`. Returns 400 `"Invalid bucket name"` if invalid.
61
+
62
+ **Response `200`:**
63
+ ```json
64
+ { "isDeleted": true }
65
+ ```
66
+
67
+ The `isDeleted` field is a boolean indicating whether the bucket was successfully removed from storage.
68
+
69
+ #### POST <code v-pre>/{basePath}/buckets/:bucketName/upload</code>
70
+ **Parameters:**
71
+ - `bucketName` (path): Target bucket name
72
+
73
+ **Query Parameters:**
74
+ - `principalType` (optional, string): Type of the principal to associate with the uploaded files (e.g., `"user"`, `"service"`)
75
+ - `principalId` (optional, string or number): ID of the principal. Always coerced to a string via `String()` before storage regardless of input type
76
+
77
+ **Validation:** Bucket name validated with `isValidName()`. Returns 400 `"Invalid bucket name"` if invalid.
78
+
79
+ **Request Body:** `multipart/form-data` with file fields. The request body is parsed using the `MultipartBodySchema` Zod schema:
80
+
81
+ ```typescript
82
+ const MultipartBodySchema = z.object({
83
+ files: z.union([z.instanceof(File), z.array(z.instanceof(File))]),
84
+ });
85
+ ```
86
+
87
+ This accepts either a single `File` or an array of `File` objects. Each file can optionally include `folderPath` for organization.
88
+
89
+ **Response `200` (without MetaLink):**
90
+ ```json
91
+ [
92
+ {
93
+ "bucketName": "my-bucket",
94
+ "objectName": "file.pdf",
95
+ "link": "/assets/buckets/my-bucket/objects/file.pdf"
96
+ }
97
+ ]
98
+ ```
99
+
100
+ **Response `200` (with MetaLink enabled):**
101
+ ```json
102
+ [
103
+ {
104
+ "bucketName": "my-bucket",
105
+ "objectName": "file.pdf",
106
+ "link": "/assets/buckets/my-bucket/objects/file.pdf",
107
+ "metaLink": {
108
+ "id": "uuid",
109
+ "bucketName": "my-bucket",
110
+ "objectName": "file.pdf",
111
+ "link": "/assets/buckets/my-bucket/objects/file.pdf",
112
+ "mimetype": "application/pdf",
113
+ "size": 1024,
114
+ "etag": "abc123",
115
+ "metadata": {},
116
+ "storageType": "minio",
117
+ "isSynced": true,
118
+ "principalType": "user",
119
+ "principalId": "42",
120
+ "createdAt": "2025-12-15T03:00:00.000Z",
121
+ "modifiedAt": "2025-12-15T03:00:00.000Z"
122
+ }
123
+ }
124
+ ]
125
+ ```
126
+
127
+ **Response `200` (with MetaLink enabled, MetaLink creation failed):**
128
+ ```json
129
+ [
130
+ {
131
+ "bucketName": "my-bucket",
132
+ "objectName": "file.pdf",
133
+ "link": "/assets/buckets/my-bucket/objects/file.pdf",
134
+ "metaLink": null,
135
+ "metaLinkError": "Database connection failed"
136
+ }
137
+ ]
138
+ ```
139
+
140
+ When MetaLink creation fails, the upload itself still succeeds. The response includes `metaLink: null` and a `metaLinkError` string describing the failure. The error is also logged via the controller's scoped logger.
141
+
142
+ **Example:**
143
+ ```typescript
144
+ const formData = new FormData();
145
+ formData.append('file', fileBlob, 'document.pdf');
146
+
147
+ // Upload with principal association
148
+ const response = await fetch(
149
+ '/assets/buckets/uploads/upload?principalType=user&principalId=123',
150
+ { method: 'POST', body: formData },
151
+ );
152
+
153
+ const result = await response.json();
154
+ console.log(result[0].metaLink); // Database record (if MetaLink enabled)
155
+ ```
156
+
157
+ #### GET <code v-pre>/{basePath}/buckets/:bucketName/objects</code>
158
+ **Parameters:**
159
+ - `bucketName` (path): Bucket name
160
+
161
+ **Validation:** Bucket name validated with `isValidName()`. Returns 400 `"Invalid bucket name"` if invalid.
162
+
163
+ **Query Parameters:**
164
+ - `prefix` (optional, string): Filter objects by prefix (e.g., `"folder/"`)
165
+ - `recursive` (optional, string): Recursive listing. Parsed via strict string comparison `=== 'true'` -- only the exact string `"true"` enables recursion; any other truthy value (e.g., `"1"`, `"yes"`) does not
166
+ - `maxKeys` (optional, string): Maximum number of objects to return. Parsed as integer via `parseInt(value, 10)`
167
+
168
+ **Response `200`:**
169
+ ```json
170
+ [
171
+ {
172
+ "name": "file1.pdf",
173
+ "size": 1024,
174
+ "lastModified": "2025-12-13T00:00:00.000Z",
175
+ "etag": "abc123",
176
+ "prefix": "folder/"
177
+ }
178
+ ]
179
+ ```
180
+
181
+ All fields in the `IObjectInfo` response are optional. The `prefix` field is present when listing non-recursively and the object is a directory prefix. When listing individual files, `name`, `size`, `lastModified`, and `etag` are typically populated.
182
+
183
+ #### GET <code v-pre>/{basePath}/buckets/:bucketName/objects/:objectName</code>
184
+ **Parameters:**
185
+ - `bucketName` (path): Bucket name
186
+ - `objectName` (path): Object name (URL-encoded)
187
+
188
+ **Validation:** Both bucket and object names validated with `isValidName()`. Returns 400 `"Invalid bucket name"` or `"Invalid object name"` respectively if either is invalid.
189
+
190
+ **Response:**
191
+ - Streams file content with appropriate headers
192
+ - `Content-Type`: From storage metadata or `application/octet-stream` as fallback
193
+ - `Content-Length`: File size in bytes
194
+ - `X-Content-Type-Options`: `nosniff`
195
+ - Additional whitelisted headers forwarded from storage metadata (see [Header Sanitization](./api#header-sanitization))
196
+
197
+ #### GET <code v-pre>/{basePath}/buckets/:bucketName/objects/:objectName/download</code>
198
+ **Parameters:**
199
+ - `bucketName` (path): Bucket name
200
+ - `objectName` (path): Object name (URL-encoded)
201
+
202
+ **Validation:** Both bucket and object names validated with `isValidName()`. Returns 400 `"Invalid bucket name"` or `"Invalid object name"` respectively if either is invalid.
203
+
204
+ **Response:**
205
+ - Streams file with download headers
206
+ - `Content-Disposition`: `attachment; filename="..."` (generated via `createContentDispositionHeader()`)
207
+ - `Content-Type`: From storage metadata or `application/octet-stream` as fallback
208
+ - `Content-Length`: File size in bytes
209
+ - `X-Content-Type-Options`: `nosniff`
210
+ - Additional whitelisted headers forwarded from storage metadata (see [Header Sanitization](./api#header-sanitization))
211
+ - Triggers browser download dialog
212
+
213
+ **Example:**
214
+ ```typescript
215
+ const downloadUrl = `/assets/buckets/uploads/objects/${encodeURIComponent('document.pdf')}/download`;
216
+ window.open(downloadUrl, '_blank');
217
+ ```
218
+
219
+ #### DELETE <code v-pre>/{basePath}/buckets/:bucketName/objects/:objectName</code>
220
+ **Parameters:**
221
+ - `bucketName` (path): Bucket name
222
+ - `objectName` (path): Object to delete (URL-encoded)
223
+
224
+ **Validation:** Both bucket and object names validated with `isValidName()`. Returns 400 `"Invalid bucket name"` or `"Invalid object name"` respectively if either is invalid.
225
+
226
+ **Behavior:**
227
+ - Deletes file from storage
228
+ - If MetaLink enabled, the MetaLink database record deletion is **fire-and-forget** -- the HTTP response returns immediately after the storage delete completes, without awaiting the database deletion
229
+ - MetaLink deletion errors are logged but do not fail the request
230
+ - MetaLink deletion uses `deleteAll({ where: { bucketName, objectName } })` to remove all matching records
231
+
232
+ **Response `200`:**
233
+ ```json
234
+ { "success": true }
235
+ ```
236
+
237
+ **Example:**
238
+ ```typescript
239
+ const bucketName = 'user-uploads';
240
+ const objectName = 'document.pdf';
241
+
242
+ await fetch(`/assets/buckets/${bucketName}/objects/${encodeURIComponent(objectName)}`, {
243
+ method: 'DELETE',
244
+ });
245
+ // File deleted from storage
246
+ // MetaLink record deletion initiated (if enabled) but may complete after response
247
+ ```
248
+
249
+ #### PUT <code v-pre>/{basePath}/buckets/:bucketName/objects/:objectName/meta-links</code>
250
+ **Availability:** Only registered when `useMetaLink: true`.
251
+
252
+ **Parameters:**
253
+ - `bucketName` (path): Bucket name
254
+ - `objectName` (path): Object name (URL-encoded)
255
+
256
+ **Validation:** Both bucket and object names validated with `isValidName()`. Returns 400 `"Invalid bucket name"` or `"Invalid object name"` respectively if either is invalid.
257
+
258
+ **Behavior:**
259
+ - Fetches current file metadata from storage via `helper.getStat()`
260
+ - Generates the file link using `normalizeLinkFn` (or the default link format <code v-pre>{basePath}/buckets/{bucket}/objects/{encodedName}</code>)
261
+ - If MetaLink exists (matched by `bucketName` + `objectName`): Updates with latest metadata via `updateById()`, then refetches via `findById()`
262
+ - If MetaLink doesn't exist: Creates new MetaLink record via `create()`
263
+ - Always sets `isSynced: true` to mark as synchronized
264
+
265
+ **Use Cases:**
266
+ - Manually sync files that exist in storage but not in database
267
+ - Update MetaLink metadata after file changes
268
+ - Rebuild MetaLink records after database restore
269
+ - Bulk synchronization operations
270
+
271
+ **Response `200` (MetaLink created or updated):**
272
+ ```json
273
+ {
274
+ "success": true,
275
+ "metaLink": {
276
+ "id": "uuid",
277
+ "bucketName": "user-uploads",
278
+ "objectName": "document.pdf",
279
+ "link": "/assets/buckets/user-uploads/objects/document.pdf",
280
+ "mimetype": "application/pdf",
281
+ "size": 1048576,
282
+ "etag": "abc123",
283
+ "metadata": {},
284
+ "storageType": "minio",
285
+ "isSynced": true,
286
+ "principalType": null,
287
+ "principalId": null,
288
+ "createdAt": "2025-12-15T03:00:00.000Z",
289
+ "modifiedAt": "2025-12-15T03:00:00.000Z"
290
+ }
291
+ }
292
+ ```
293
+
294
+ The response always wraps the MetaLink in a `{ success: boolean, metaLink: ... }` envelope. Both create and update flows return the same shape.
295
+
296
+ **Example:**
297
+ ```typescript
298
+ // Sync a single file
299
+ const bucketName = 'user-uploads';
300
+ const objectName = 'document.pdf';
301
+
302
+ const response = await fetch(
303
+ `/assets/buckets/${bucketName}/objects/${encodeURIComponent(objectName)}/meta-links`,
304
+ { method: 'PUT' }
305
+ );
306
+
307
+ const result = await response.json();
308
+ console.log('Success:', result.success); // true
309
+ console.log('Synced:', result.metaLink.isSynced); // true
310
+
311
+ // Bulk sync example: sync all files in storage
312
+ const objects = await fetch(`/assets/buckets/${bucketName}/objects`).then(r => r.json());
313
+
314
+ for (const obj of objects) {
315
+ await fetch(
316
+ `/assets/buckets/${bucketName}/objects/${encodeURIComponent(obj.name)}/meta-links`,
317
+ { method: 'PUT' }
318
+ );
319
+ }
320
+ ```
321
+
322
+ ## Frontend Integration
323
+
324
+ ```typescript
325
+ // Upload file with principal association
326
+ async function uploadFile(file: File, principalType?: string, principalId?: string) {
327
+ const formData = new FormData();
328
+ formData.append('file', file);
329
+
330
+ const url = new URL('/assets/buckets/user-uploads/upload', window.location.origin);
331
+ if (principalType) url.searchParams.append('principalType', principalType);
332
+ if (principalId) url.searchParams.append('principalId', principalId);
333
+
334
+ const response = await fetch(url, {
335
+ method: 'POST',
336
+ body: formData,
337
+ });
338
+
339
+ const result = await response.json();
340
+ return result[0].link;
341
+ }
342
+
343
+ // Download file
344
+ function downloadFile(bucketName: string, objectName: string) {
345
+ const url = `/assets/buckets/${bucketName}/objects/${encodeURIComponent(objectName)}/download`;
346
+ window.open(url, '_blank');
347
+ }
348
+
349
+ // List files in bucket
350
+ async function listFiles(bucketName: string, prefix?: string, recursive?: boolean) {
351
+ const url = new URL(`/assets/buckets/${bucketName}/objects`, window.location.origin);
352
+ if (prefix) url.searchParams.append('prefix', prefix);
353
+ if (recursive) url.searchParams.append('recursive', 'true');
354
+
355
+ const response = await fetch(url);
356
+ return await response.json();
357
+ }
358
+ ```
359
+
360
+ ## See Also
361
+
362
+ - [Setup & Configuration](./) - Quick Reference, Setup Steps, Configuration Options
363
+ - [API Reference](./api) - Controller Factory, Storage Interface, MetaLink Schema
364
+ - [Error Reference](./errors) - Name Validation and Troubleshooting