@venizia/ignis-docs 0.0.7-2 → 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 +33 -16
- package/wiki/extensions/helpers/kafka/consumer.md +384 -0
- package/wiki/extensions/helpers/kafka/examples.md +361 -0
- package/wiki/extensions/helpers/kafka/index.md +639 -0
- package/wiki/{references → extensions}/helpers/kafka/producer.md +100 -96
- package/wiki/extensions/helpers/kafka/schema-registry.md +214 -0
- 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/helpers/kafka/consumer.md +0 -473
- package/wiki/references/helpers/kafka/examples.md +0 -234
- package/wiki/references/helpers/kafka/index.md +0 -482
- /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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Static Asset
|
|
2
2
|
|
|
3
|
-
> Flexible file management system with support for multiple storage backends (local disk, MinIO/S3-compatible) through a unified interface, featuring factory-based controller generation and optional database file tracking via MetaLink.
|
|
3
|
+
> Flexible file management system with support for multiple storage backends (local disk, MinIO/S3-compatible, Bun S3) through a unified interface, featuring factory-based controller generation and optional database file tracking via MetaLink.
|
|
4
4
|
|
|
5
5
|
## Quick Reference
|
|
6
6
|
|
|
@@ -8,23 +8,35 @@
|
|
|
8
8
|
|------|-------|
|
|
9
9
|
| **Package** | `@venizia/ignis` |
|
|
10
10
|
| **Class** | `StaticAssetComponent` |
|
|
11
|
-
| **Helper** | [`DiskHelper`](/
|
|
11
|
+
| **Helper** | [`DiskHelper`](/extensions/helpers/storage/), [`MinioHelper`](/extensions/helpers/storage/), [`BunS3Helper`](/extensions/helpers/storage/) |
|
|
12
12
|
| **Runtimes** | Both |
|
|
13
13
|
|
|
14
14
|
#### Import Paths
|
|
15
|
+
|
|
16
|
+
> [!IMPORTANT]
|
|
17
|
+
> `StaticAssetComponent` and its related exports are **not** exported from the `@venizia/ignis` barrel. You must import from the `@venizia/ignis/static-asset` subpath.
|
|
18
|
+
|
|
15
19
|
```typescript
|
|
20
|
+
// From core -- subpath import (NOT from '@venizia/ignis')
|
|
16
21
|
import {
|
|
17
22
|
StaticAssetComponent,
|
|
18
23
|
StaticAssetComponentBindingKeys,
|
|
19
24
|
StaticAssetStorageTypes,
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
AssetControllerFactory,
|
|
26
|
+
BaseMetaLinkModel,
|
|
27
|
+
BaseMetaLinkRepository,
|
|
28
|
+
} from '@venizia/ignis/static-asset';
|
|
29
|
+
|
|
30
|
+
import { DiskHelper } from '@venizia/ignis-helpers';
|
|
31
|
+
import { MinioHelper } from '@venizia/ignis-helpers/minio';
|
|
32
|
+
import { BunS3Helper } from '@venizia/ignis-helpers/bun-s3';
|
|
33
|
+
|
|
22
34
|
import type {
|
|
23
35
|
TStaticAssetsComponentOptions,
|
|
24
36
|
TMetaLinkConfig,
|
|
25
37
|
TStaticAssetExtraOptions,
|
|
26
38
|
TStaticAssetStorageType,
|
|
27
|
-
} from '@venizia/ignis';
|
|
39
|
+
} from '@venizia/ignis/static-asset';
|
|
28
40
|
```
|
|
29
41
|
|
|
30
42
|
### Key Features
|
|
@@ -35,7 +47,8 @@ import type {
|
|
|
35
47
|
| **Multiple Storage Instances** | Configure multiple storage backends simultaneously |
|
|
36
48
|
| **Factory Pattern** | Dynamic controller generation per storage backend |
|
|
37
49
|
| **Built-in Security** | Comprehensive name validation, path traversal protection, header sanitization |
|
|
38
|
-
| **Database Tracking (MetaLink)** | Optional database-backed file tracking with metadata, principal association, and sync status |
|
|
50
|
+
| **Database Tracking (MetaLink)** | Optional database-backed file tracking with metadata, principal association, variant support, and sync status |
|
|
51
|
+
| **Per-Route Configuration** | Override authentication, middleware, and path for individual routes |
|
|
39
52
|
| **Flexible Configuration** | Environment-based, production-ready setup |
|
|
40
53
|
|
|
41
54
|
## Setup
|
|
@@ -43,13 +56,14 @@ import type {
|
|
|
43
56
|
### Step 1: Bind Configuration
|
|
44
57
|
|
|
45
58
|
```typescript
|
|
59
|
+
import { BaseApplication } from '@venizia/ignis';
|
|
46
60
|
import {
|
|
47
|
-
BaseApplication,
|
|
48
61
|
StaticAssetComponentBindingKeys,
|
|
49
62
|
StaticAssetStorageTypes,
|
|
50
|
-
} from '@venizia/ignis';
|
|
51
|
-
import { DiskHelper
|
|
52
|
-
import
|
|
63
|
+
} from '@venizia/ignis/static-asset';
|
|
64
|
+
import { DiskHelper } from '@venizia/ignis-helpers';
|
|
65
|
+
import { MinioHelper } from '@venizia/ignis-helpers/minio';
|
|
66
|
+
import type { TStaticAssetsComponentOptions } from '@venizia/ignis/static-asset';
|
|
53
67
|
|
|
54
68
|
export class Application extends BaseApplication {
|
|
55
69
|
preConfigure() {
|
|
@@ -100,7 +114,7 @@ Each storage backend gets a unique key (`staticAsset`, `staticResource`), its ow
|
|
|
100
114
|
### Step 2: Register Component
|
|
101
115
|
|
|
102
116
|
```typescript
|
|
103
|
-
import { StaticAssetComponent } from '@venizia/ignis';
|
|
117
|
+
import { StaticAssetComponent } from '@venizia/ignis/static-asset';
|
|
104
118
|
|
|
105
119
|
export class Application extends BaseApplication {
|
|
106
120
|
preConfigure() {
|
|
@@ -186,13 +200,15 @@ Start with `docker-compose up -d` and access the console at `http://localhost:90
|
|
|
186
200
|
|------|----------|--------|-------------|
|
|
187
201
|
| `'disk'` | `StaticAssetStorageTypes.DISK` | `DiskHelper` | Local filesystem with bucket-based directory structure |
|
|
188
202
|
| `'minio'` | `StaticAssetStorageTypes.MINIO` | `MinioHelper` | S3-compatible object storage (MinIO, AWS S3, etc.) |
|
|
203
|
+
| `'bun-s3'` | `StaticAssetStorageTypes.BUN_S3` | `BunS3Helper` | Bun-native S3 client (requires Bun runtime) |
|
|
189
204
|
|
|
190
205
|
The `StaticAssetStorageTypes` class provides a `SCHEME_SET` (a `Set` of all valid storage type strings) and an `isValid(orgType)` method for runtime validation:
|
|
191
206
|
|
|
192
207
|
```typescript
|
|
193
|
-
StaticAssetStorageTypes.isValid('minio');
|
|
194
|
-
StaticAssetStorageTypes.isValid('s3');
|
|
195
|
-
StaticAssetStorageTypes.
|
|
208
|
+
StaticAssetStorageTypes.isValid('minio'); // true
|
|
209
|
+
StaticAssetStorageTypes.isValid('bun-s3'); // true
|
|
210
|
+
StaticAssetStorageTypes.isValid('s3'); // false
|
|
211
|
+
StaticAssetStorageTypes.SCHEME_SET; // Set { 'disk', 'minio', 'bun-s3' }
|
|
196
212
|
```
|
|
197
213
|
|
|
198
214
|
### `TStaticAssetsComponentOptions`
|
|
@@ -204,12 +220,37 @@ Each key in the options object defines a separate storage backend with its own c
|
|
|
204
220
|
| `controller.name` | `string` | -- | Controller class name |
|
|
205
221
|
| `controller.basePath` | `string` | -- | Base URL path (e.g., `'/assets'`) |
|
|
206
222
|
| `controller.isStrict` | `boolean` | `true` | Strict routing mode |
|
|
207
|
-
| `
|
|
208
|
-
| `
|
|
223
|
+
| `controller.routes` | `object` | `undefined` | Per-route overrides (authenticate, middleware, path) |
|
|
224
|
+
| `storage` | `'disk' \| 'minio' \| 'bun-s3'` | -- | Storage type |
|
|
225
|
+
| `helper` | `DiskHelper \| MinioHelper \| BunS3Helper` | -- | Storage helper instance |
|
|
209
226
|
| `extra` | `TStaticAssetExtraOptions` | `undefined` | Extra options (multipart parsing, name normalization) |
|
|
210
227
|
| `useMetaLink` | `boolean` | `false` | Enable database file tracking |
|
|
211
228
|
| `metaLink` | `TMetaLinkConfig` | -- | MetaLink configuration (required when `useMetaLink: true`) |
|
|
212
229
|
|
|
230
|
+
#### Per-Route Configuration
|
|
231
|
+
|
|
232
|
+
Each route can be individually configured with authentication, middleware, and path overrides:
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
{
|
|
236
|
+
controller: {
|
|
237
|
+
name: 'AssetController',
|
|
238
|
+
basePath: '/assets',
|
|
239
|
+
routes: {
|
|
240
|
+
getBuckets: { authenticate: { strategies: ['jwt'], mode: 'required' } },
|
|
241
|
+
upload: { authenticate: { strategies: ['jwt'], mode: 'required' }, middleware: [rateLimitMw] },
|
|
242
|
+
getObjectByName: { /* public -- no authenticate */ },
|
|
243
|
+
downloadObjectByName: { /* public */ },
|
|
244
|
+
deleteObject: { authenticate: { strategies: ['jwt'], mode: 'required' } },
|
|
245
|
+
deleteBucket: { authenticate: { strategies: ['jwt'], mode: 'required' } },
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
// ...
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Available route keys: `getBuckets`, `getBucketByName`, `createBucket`, `deleteBucket`, `upload`, `listObjects`, `deleteObject`, `getObjectByName`, `downloadObjectByName`, `recreateMetaLink`.
|
|
253
|
+
|
|
213
254
|
#### TStaticAssetsComponentOptions -- Full Reference
|
|
214
255
|
```typescript
|
|
215
256
|
type TStaticAssetsComponentOptions = {
|
|
@@ -218,9 +259,22 @@ type TStaticAssetsComponentOptions = {
|
|
|
218
259
|
name: string;
|
|
219
260
|
basePath: string;
|
|
220
261
|
isStrict?: boolean;
|
|
262
|
+
routes?: {
|
|
263
|
+
getBuckets?: Partial<Omit<IAuthRouteConfig, 'method' | 'request' | 'responses'>>;
|
|
264
|
+
getBucketByName?: Partial<Omit<IAuthRouteConfig, 'method' | 'request' | 'responses'>>;
|
|
265
|
+
createBucket?: Partial<Omit<IAuthRouteConfig, 'method' | 'request' | 'responses'>>;
|
|
266
|
+
deleteBucket?: Partial<Omit<IAuthRouteConfig, 'method' | 'request' | 'responses'>>;
|
|
267
|
+
upload?: Partial<Omit<IAuthRouteConfig, 'method' | 'request' | 'responses'>>;
|
|
268
|
+
listObjects?: Partial<Omit<IAuthRouteConfig, 'method' | 'request' | 'responses'>>;
|
|
269
|
+
deleteObject?: Partial<Omit<IAuthRouteConfig, 'method' | 'request' | 'responses'>>;
|
|
270
|
+
getObjectByName?: Partial<Omit<IAuthRouteConfig, 'method' | 'request' | 'responses'>>;
|
|
271
|
+
downloadObjectByName?: Partial<Omit<IAuthRouteConfig, 'method' | 'request' | 'responses'>>;
|
|
272
|
+
recreateMetaLink?: Partial<Omit<IAuthRouteConfig, 'method' | 'request' | 'responses'>>;
|
|
273
|
+
};
|
|
221
274
|
};
|
|
222
275
|
extra?: TStaticAssetExtraOptions;
|
|
223
276
|
} & (
|
|
277
|
+
| { storage: typeof StaticAssetStorageTypes.BUN_S3; helper: BunS3Helper }
|
|
224
278
|
| { storage: typeof StaticAssetStorageTypes.DISK; helper: DiskHelper }
|
|
225
279
|
| { storage: typeof StaticAssetStorageTypes.MINIO; helper: MinioHelper }
|
|
226
280
|
) &
|
|
@@ -232,7 +286,7 @@ type TStaticAssetExtraOptions = {
|
|
|
232
286
|
storage?: 'memory' | 'disk';
|
|
233
287
|
uploadDir?: string;
|
|
234
288
|
};
|
|
235
|
-
normalizeNameFn?: (opts: { originalName: string
|
|
289
|
+
normalizeNameFn?: (opts: { originalName: string }) => string;
|
|
236
290
|
normalizeLinkFn?: (opts: { bucketName: string; normalizeName: string }) => string;
|
|
237
291
|
[key: string]: any;
|
|
238
292
|
};
|
|
@@ -240,9 +294,20 @@ type TStaticAssetExtraOptions = {
|
|
|
240
294
|
type TMetaLinkConfig<Schema extends TMetaLinkSchema = TMetaLinkSchema> = {
|
|
241
295
|
model: typeof BaseEntity<Schema>;
|
|
242
296
|
repository: DefaultCRUDRepository<Schema>;
|
|
297
|
+
createMetaLink?: (opts: {
|
|
298
|
+
uploadResult: IUploadResult;
|
|
299
|
+
fileStat: IFileStat;
|
|
300
|
+
query: TUploadQuery;
|
|
301
|
+
}) => ValueOrPromise<{ count: number; data: Schema }>;
|
|
243
302
|
};
|
|
244
303
|
```
|
|
245
304
|
|
|
305
|
+
> [!NOTE]
|
|
306
|
+
> The `normalizeNameFn` receives only `{ originalName }` -- there is no `folderPath` parameter.
|
|
307
|
+
|
|
308
|
+
> [!TIP]
|
|
309
|
+
> The `createMetaLink` callback on `TMetaLinkConfig` is optional. When provided, it replaces the default MetaLink creation logic during upload, giving you full control over how file metadata is stored.
|
|
310
|
+
|
|
246
311
|
### DiskHelper
|
|
247
312
|
|
|
248
313
|
Stores files on the local filesystem using a bucket-based directory structure.
|
|
@@ -301,16 +366,26 @@ const minioHelper = new MinioHelper({
|
|
|
301
366
|
});
|
|
302
367
|
```
|
|
303
368
|
|
|
369
|
+
### BunS3Helper
|
|
370
|
+
|
|
371
|
+
Bun-native S3 client for direct S3/S3-compatible access using Bun's built-in S3 support. Requires Bun runtime.
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
import { BunS3Helper } from '@venizia/ignis-helpers/bun-s3';
|
|
375
|
+
```
|
|
376
|
+
|
|
304
377
|
### MetaLink Configuration
|
|
305
378
|
|
|
306
|
-
MetaLink is an optional feature that tracks uploaded files in a database, storing file location, metadata (mimetype, size, etag), storage type, principal association (`principalType`, `principalId`), timestamps, and custom metadata (JSONB).
|
|
379
|
+
MetaLink is an optional feature that tracks uploaded files in a database, storing file location, metadata (mimetype, size, etag), storage type, principal association (`principalType`, `principalId`), variant, timestamps, and custom metadata (JSONB).
|
|
307
380
|
|
|
308
381
|
#### Benefits
|
|
309
382
|
|
|
310
|
-
- Query uploaded files by bucket, name, mimetype, etc.
|
|
383
|
+
- Query uploaded files by bucket, name, mimetype, variant, etc.
|
|
311
384
|
- Track file history and audit trails
|
|
312
385
|
- Store custom metadata about files
|
|
313
386
|
- Associate files with principals via `principalType` and `principalId` (passed as query parameters on the upload endpoint)
|
|
387
|
+
- Tag uploads with a `variant` query parameter (e.g., `"thumbnail"`, `"original"`)
|
|
388
|
+
- Custom `createMetaLink` callback for full control over MetaLink creation
|
|
314
389
|
- Graceful errors -- upload succeeds even if MetaLink creation fails
|
|
315
390
|
|
|
316
391
|
#### Setup
|
|
@@ -318,7 +393,7 @@ MetaLink is an optional feature that tracks uploaded files in a database, storin
|
|
|
318
393
|
**1. Create Model:**
|
|
319
394
|
|
|
320
395
|
```typescript
|
|
321
|
-
import { BaseMetaLinkModel, model } from '@venizia/ignis';
|
|
396
|
+
import { BaseMetaLinkModel, model } from '@venizia/ignis/static-asset';
|
|
322
397
|
|
|
323
398
|
@model({ type: 'entity' })
|
|
324
399
|
export class FileMetaLinkModel extends BaseMetaLinkModel {
|
|
@@ -329,7 +404,9 @@ export class FileMetaLinkModel extends BaseMetaLinkModel {
|
|
|
329
404
|
**2. Create Repository:**
|
|
330
405
|
|
|
331
406
|
```typescript
|
|
332
|
-
import { BaseMetaLinkRepository
|
|
407
|
+
import { BaseMetaLinkRepository } from '@venizia/ignis/static-asset';
|
|
408
|
+
import { repository, inject } from '@venizia/ignis';
|
|
409
|
+
import type { IDataSource } from '@venizia/ignis';
|
|
333
410
|
|
|
334
411
|
@repository({})
|
|
335
412
|
export class FileMetaLinkRepository extends BaseMetaLinkRepository {
|
|
@@ -361,6 +438,7 @@ CREATE TABLE "MetaLink" (
|
|
|
361
438
|
metadata JSONB,
|
|
362
439
|
storage_type TEXT NOT NULL,
|
|
363
440
|
is_synced BOOLEAN NOT NULL DEFAULT false,
|
|
441
|
+
variant TEXT,
|
|
364
442
|
principal_type TEXT,
|
|
365
443
|
principal_id TEXT
|
|
366
444
|
);
|
|
@@ -375,6 +453,12 @@ CREATE INDEX "IDX_MetaLink_isSynced" ON "MetaLink"(is_synced);
|
|
|
375
453
|
|
|
376
454
|
```typescript
|
|
377
455
|
import { FileMetaLinkModel, FileMetaLinkRepository } from './your-models';
|
|
456
|
+
import {
|
|
457
|
+
StaticAssetComponent,
|
|
458
|
+
StaticAssetComponentBindingKeys,
|
|
459
|
+
StaticAssetStorageTypes,
|
|
460
|
+
} from '@venizia/ignis/static-asset';
|
|
461
|
+
import type { TStaticAssetsComponentOptions } from '@venizia/ignis/static-asset';
|
|
378
462
|
|
|
379
463
|
export class Application extends BaseApplication {
|
|
380
464
|
configureComponents(): void {
|
|
@@ -407,23 +491,56 @@ export class Application extends BaseApplication {
|
|
|
407
491
|
}
|
|
408
492
|
```
|
|
409
493
|
|
|
410
|
-
**5. Upload with Principal Association:**
|
|
494
|
+
**5. Upload with Principal Association and Variant:**
|
|
411
495
|
|
|
412
|
-
When MetaLink is enabled, you can associate uploaded files with a principal
|
|
496
|
+
When MetaLink is enabled, you can associate uploaded files with a principal and variant by passing query parameters on the upload endpoint:
|
|
413
497
|
|
|
414
498
|
```typescript
|
|
415
499
|
const formData = new FormData();
|
|
416
500
|
formData.append('file', fileBlob, 'document.pdf');
|
|
417
501
|
|
|
418
|
-
// Associate the upload with a user
|
|
502
|
+
// Associate the upload with a user and tag as 'original' variant
|
|
419
503
|
const response = await fetch(
|
|
420
|
-
'/uploads/buckets/user-files/upload?principalType=user&principalId=42',
|
|
504
|
+
'/uploads/buckets/user-files/upload?principalType=user&principalId=42&variant=original',
|
|
421
505
|
{ method: 'POST', body: formData },
|
|
422
506
|
);
|
|
423
507
|
```
|
|
424
508
|
|
|
425
509
|
The `principalId` value is always stored as a string regardless of input type (coerced via `String()`).
|
|
426
510
|
|
|
511
|
+
#### Custom MetaLink Creation
|
|
512
|
+
|
|
513
|
+
You can provide a custom `createMetaLink` callback to fully control how MetaLink records are created:
|
|
514
|
+
|
|
515
|
+
```typescript
|
|
516
|
+
metaLink: {
|
|
517
|
+
model: FileMetaLinkModel,
|
|
518
|
+
repository: this.getSync(FileMetaLinkRepository),
|
|
519
|
+
createMetaLink: async ({ uploadResult, fileStat, query }) => {
|
|
520
|
+
// Custom logic -- e.g., add extra fields, validate, transform
|
|
521
|
+
return metaLinkRepo.create({
|
|
522
|
+
data: {
|
|
523
|
+
bucketName: uploadResult.bucketName,
|
|
524
|
+
objectName: uploadResult.objectName,
|
|
525
|
+
link: uploadResult.link,
|
|
526
|
+
mimetype: fileStat.metadata?.['mimetype'],
|
|
527
|
+
size: fileStat.size,
|
|
528
|
+
etag: fileStat.etag,
|
|
529
|
+
metadata: fileStat.metadata,
|
|
530
|
+
storageType: 'minio',
|
|
531
|
+
isSynced: true,
|
|
532
|
+
principalId: query.principalId ? String(query.principalId) : undefined,
|
|
533
|
+
principalType: query.principalType,
|
|
534
|
+
variant: query.variant,
|
|
535
|
+
// ... additional custom fields
|
|
536
|
+
},
|
|
537
|
+
});
|
|
538
|
+
},
|
|
539
|
+
},
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
When `createMetaLink` is not provided, the component uses a default implementation that stores all standard fields.
|
|
543
|
+
|
|
427
544
|
#### Querying MetaLinks
|
|
428
545
|
|
|
429
546
|
```typescript
|
|
@@ -447,32 +564,27 @@ const userFiles = await fileMetaLinkRepository.find({
|
|
|
447
564
|
where: { principalType: 'user', principalId: '42' },
|
|
448
565
|
});
|
|
449
566
|
|
|
450
|
-
// Get
|
|
451
|
-
const
|
|
452
|
-
where: {
|
|
567
|
+
// Get files by variant
|
|
568
|
+
const thumbnails = await fileMetaLinkRepository.find({
|
|
569
|
+
where: { variant: 'thumbnail' },
|
|
453
570
|
});
|
|
454
571
|
|
|
455
|
-
// Get
|
|
456
|
-
const
|
|
457
|
-
where: { isSynced: false },
|
|
458
|
-
});
|
|
459
|
-
|
|
460
|
-
// Count synced files
|
|
461
|
-
const syncedCount = await fileMetaLinkRepository.count({
|
|
572
|
+
// Get synced files only
|
|
573
|
+
const syncedFiles = await fileMetaLinkRepository.find({
|
|
462
574
|
where: { isSynced: true },
|
|
463
575
|
});
|
|
464
|
-
|
|
465
|
-
// Get recent uploads
|
|
466
|
-
const recent = await fileMetaLinkRepository.find({
|
|
467
|
-
orderBy: { createdAt: 'desc' },
|
|
468
|
-
limit: 10,
|
|
469
|
-
});
|
|
470
576
|
```
|
|
471
577
|
|
|
472
578
|
### Quick Start Options
|
|
473
579
|
|
|
474
580
|
**Option 1: MinIO Only**
|
|
475
581
|
```typescript
|
|
582
|
+
import {
|
|
583
|
+
StaticAssetComponent,
|
|
584
|
+
StaticAssetComponentBindingKeys,
|
|
585
|
+
StaticAssetStorageTypes,
|
|
586
|
+
} from '@venizia/ignis/static-asset';
|
|
587
|
+
|
|
476
588
|
this.bind({
|
|
477
589
|
key: StaticAssetComponentBindingKeys.STATIC_ASSET_COMPONENT_OPTIONS,
|
|
478
590
|
}).toValue({
|
|
@@ -538,9 +650,8 @@ this.component(StaticAssetComponent);
|
|
|
538
650
|
helper: new MinioHelper({ /* ... */ }),
|
|
539
651
|
extra: {
|
|
540
652
|
parseMultipartBody: { storage: 'memory' },
|
|
541
|
-
normalizeNameFn: ({ originalName
|
|
542
|
-
|
|
543
|
-
return `${prefix}${Date.now()}_${originalName.toLowerCase().replace(/\s/g, '_')}`;
|
|
653
|
+
normalizeNameFn: ({ originalName }) => {
|
|
654
|
+
return `${Date.now()}_${originalName.toLowerCase().replace(/\s/g, '_')}`;
|
|
544
655
|
},
|
|
545
656
|
normalizeLinkFn: ({ bucketName, normalizeName }) => {
|
|
546
657
|
return `/api/files/${bucketName}/${encodeURIComponent(normalizeName)}`;
|
|
@@ -550,49 +661,7 @@ this.component(StaticAssetComponent);
|
|
|
550
661
|
}
|
|
551
662
|
```
|
|
552
663
|
|
|
553
|
-
The `normalizeNameFn` receives
|
|
554
|
-
|
|
555
|
-
### Custom Storage Implementation
|
|
556
|
-
|
|
557
|
-
You can implement your own storage backend by extending `BaseStorageHelper`:
|
|
558
|
-
|
|
559
|
-
```typescript
|
|
560
|
-
import { BaseStorageHelper, IUploadFile, IUploadResult } from '@venizia/ignis-helpers';
|
|
561
|
-
|
|
562
|
-
class S3Helper extends BaseStorageHelper {
|
|
563
|
-
constructor(config: S3Config) {
|
|
564
|
-
super({ scope: 'S3Helper', identifier: 'S3Helper' });
|
|
565
|
-
// Initialize S3 client
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
async isBucketExists(opts: { name: string }): Promise<boolean> {
|
|
569
|
-
// Implementation
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
async upload(opts: {
|
|
573
|
-
bucket: string;
|
|
574
|
-
files: IUploadFile[];
|
|
575
|
-
normalizeNameFn?: (opts: { originalName: string; folderPath?: string }) => string;
|
|
576
|
-
normalizeLinkFn?: (opts: { bucketName: string; normalizeName: string }) => string;
|
|
577
|
-
}): Promise<IUploadResult[]> {
|
|
578
|
-
// Implementation
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
// Implement other IStorageHelper methods...
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
// Usage
|
|
585
|
-
this.bind<TStaticAssetsComponentOptions>({
|
|
586
|
-
key: StaticAssetComponentBindingKeys.STATIC_ASSET_COMPONENT_OPTIONS,
|
|
587
|
-
}).toValue({
|
|
588
|
-
s3Storage: {
|
|
589
|
-
controller: { name: 'S3Controller', basePath: '/s3-assets' },
|
|
590
|
-
storage: 'custom-s3',
|
|
591
|
-
helper: new S3Helper({ /* ... */ }),
|
|
592
|
-
extra: {},
|
|
593
|
-
},
|
|
594
|
-
});
|
|
595
|
-
```
|
|
664
|
+
The `normalizeNameFn` receives only the `originalName` of the uploaded file.
|
|
596
665
|
|
|
597
666
|
## Binding Keys
|
|
598
667
|
|
|
@@ -608,8 +677,8 @@ this.bind<TStaticAssetsComponentOptions>({
|
|
|
608
677
|
- [Usage & Examples](./usage) - API Endpoints and Frontend Integration
|
|
609
678
|
- [API Reference](./api) - Controller Factory, Storage Interface, MetaLink Schema
|
|
610
679
|
- [Error Reference](./errors) - Name Validation and Troubleshooting
|
|
611
|
-
- [Storage Helpers](/
|
|
680
|
+
- [Storage Helpers](/extensions/helpers/storage/) - DiskHelper, MinioHelper, BaseStorageHelper
|
|
612
681
|
- [Request Utilities](/references/utilities/request) - File upload utilities
|
|
613
682
|
- [Security Guidelines](/best-practices/security-guidelines) - File upload security
|
|
614
683
|
- [Components Overview](/guides/core-concepts/components) - Component system basics
|
|
615
|
-
- [Controllers](/guides/core-concepts/controllers) - File upload endpoints
|
|
684
|
+
- [Controllers](/guides/core-concepts/rest-controllers) - File upload endpoints
|
|
@@ -73,6 +73,7 @@ The `isDeleted` field is a boolean indicating whether the bucket was successfull
|
|
|
73
73
|
**Query Parameters:**
|
|
74
74
|
- `principalType` (optional, string): Type of the principal to associate with the uploaded files (e.g., `"user"`, `"service"`)
|
|
75
75
|
- `principalId` (optional, string or number): ID of the principal. Always coerced to a string via `String()` before storage regardless of input type
|
|
76
|
+
- `variant` (optional, string): Variant tag for the upload (e.g., `"thumbnail"`, `"original"`)
|
|
76
77
|
|
|
77
78
|
**Validation:** Bucket name validated with `isValidName()`. Returns 400 `"Invalid bucket name"` if invalid.
|
|
78
79
|
|
|
@@ -84,7 +85,7 @@ const MultipartBodySchema = z.object({
|
|
|
84
85
|
});
|
|
85
86
|
```
|
|
86
87
|
|
|
87
|
-
This accepts either a single `File` or an array of `File` objects.
|
|
88
|
+
This accepts either a single `File` or an array of `File` objects.
|
|
88
89
|
|
|
89
90
|
**Response `200` (without MetaLink):**
|
|
90
91
|
```json
|
|
@@ -115,6 +116,7 @@ This accepts either a single `File` or an array of `File` objects. Each file can
|
|
|
115
116
|
"metadata": {},
|
|
116
117
|
"storageType": "minio",
|
|
117
118
|
"isSynced": true,
|
|
119
|
+
"variant": "original",
|
|
118
120
|
"principalType": "user",
|
|
119
121
|
"principalId": "42",
|
|
120
122
|
"createdAt": "2025-12-15T03:00:00.000Z",
|
|
@@ -144,9 +146,9 @@ When MetaLink creation fails, the upload itself still succeeds. The response inc
|
|
|
144
146
|
const formData = new FormData();
|
|
145
147
|
formData.append('file', fileBlob, 'document.pdf');
|
|
146
148
|
|
|
147
|
-
// Upload with principal association
|
|
149
|
+
// Upload with principal association and variant
|
|
148
150
|
const response = await fetch(
|
|
149
|
-
'/assets/buckets/uploads/upload?principalType=user&principalId=123',
|
|
151
|
+
'/assets/buckets/uploads/upload?principalType=user&principalId=123&variant=original',
|
|
150
152
|
{ method: 'POST', body: formData },
|
|
151
153
|
);
|
|
152
154
|
|
|
@@ -322,14 +324,15 @@ for (const obj of objects) {
|
|
|
322
324
|
## Frontend Integration
|
|
323
325
|
|
|
324
326
|
```typescript
|
|
325
|
-
// Upload file with principal association
|
|
326
|
-
async function uploadFile(file: File, principalType?: string, principalId?: string) {
|
|
327
|
+
// Upload file with principal association and variant
|
|
328
|
+
async function uploadFile(file: File, principalType?: string, principalId?: string, variant?: string) {
|
|
327
329
|
const formData = new FormData();
|
|
328
330
|
formData.append('file', file);
|
|
329
331
|
|
|
330
332
|
const url = new URL('/assets/buckets/user-uploads/upload', window.location.origin);
|
|
331
333
|
if (principalType) url.searchParams.append('principalType', principalType);
|
|
332
334
|
if (principalId) url.searchParams.append('principalId', principalId);
|
|
335
|
+
if (variant) url.searchParams.append('variant', variant);
|
|
333
336
|
|
|
334
337
|
const response = await fetch(url, {
|
|
335
338
|
method: 'POST',
|
|
@@ -67,11 +67,11 @@ To get the most out of the documentation, define your routes with `zod` schemas:
|
|
|
67
67
|
```typescript
|
|
68
68
|
// src/controllers/hello.controller.ts
|
|
69
69
|
import { z } from '@hono/zod-openapi';
|
|
70
|
-
import {
|
|
70
|
+
import { BaseRestController, controller, jsonContent, ValueOrPromise } from '@venizia/ignis';
|
|
71
71
|
import { HTTP } from '@venizia/ignis-helpers';
|
|
72
72
|
|
|
73
73
|
@controller({ path: '/hello' })
|
|
74
|
-
export class HelloController extends
|
|
74
|
+
export class HelloController extends BaseRestController {
|
|
75
75
|
constructor() {
|
|
76
76
|
super({ scope: HelloController.name, path: '/hello' });
|
|
77
77
|
}
|
|
@@ -457,7 +457,7 @@ this.defineRoute({
|
|
|
457
457
|
|
|
458
458
|
- **Guides:**
|
|
459
459
|
- [Components Overview](/guides/core-concepts/components) - Component system basics
|
|
460
|
-
- [Controllers](/guides/core-concepts/controllers) - Defining OpenAPI routes
|
|
460
|
+
- [Controllers](/guides/core-concepts/rest-controllers) - Defining OpenAPI routes
|
|
461
461
|
|
|
462
462
|
- **Components:**
|
|
463
463
|
- [All Components](./index) - Built-in components list
|
|
@@ -40,10 +40,10 @@ A directory with 4 files:
|
|
|
40
40
|
text: 'ComponentName',
|
|
41
41
|
collapsed: true,
|
|
42
42
|
items: [
|
|
43
|
-
{ text: 'Setup & Configuration', link: '/
|
|
44
|
-
{ text: 'Usage & Examples', link: '/
|
|
45
|
-
{ text: 'API Reference', link: '/
|
|
46
|
-
{ text: 'Error Reference', link: '/
|
|
43
|
+
{ text: 'Setup & Configuration', link: '/extensions/components/slug/' },
|
|
44
|
+
{ text: 'Usage & Examples', link: '/extensions/components/slug/usage' },
|
|
45
|
+
{ text: 'API Reference', link: '/extensions/components/slug/api' },
|
|
46
|
+
{ text: 'Error Reference', link: '/extensions/components/slug/errors' },
|
|
47
47
|
],
|
|
48
48
|
},
|
|
49
49
|
```
|
|
@@ -26,7 +26,7 @@ Paired with [Usage](./usage-page), [API Reference](./api-page), and [Error Refer
|
|
|
26
26
|
|------|-------|
|
|
27
27
|
| **Package** | `@venizia/ignis` |
|
|
28
28
|
| **Class** | `{ComponentClass}` |
|
|
29
|
-
| **Helper** | [`{HelperClass}`](/
|
|
29
|
+
| **Helper** | [`{HelperClass}`](/extensions/helpers/{slug}) |
|
|
30
30
|
| **Runtimes** | Both / Bun only |
|
|
31
31
|
|
|
32
32
|
| Sub-component | Purpose |
|
|
@@ -24,7 +24,7 @@ For simple components with few configuration options and straightforward behavio
|
|
|
24
24
|
|------|-------|
|
|
25
25
|
| **Package** | `@venizia/ignis` |
|
|
26
26
|
| **Class** | `{ComponentClass}` |
|
|
27
|
-
| **Helper** | [`{HelperClass}`](/
|
|
27
|
+
| **Helper** | [`{HelperClass}`](/extensions/helpers/{slug}) |
|
|
28
28
|
| **Runtimes** | Both / Bun only |
|
|
29
29
|
|
|
30
30
|
#### Import Paths
|
|
@@ -232,11 +232,12 @@ Registers a post-start hook that executes the following steps:
|
|
|
232
232
|
|
|
233
233
|
1. **Get Bun server instance** via `getServerInstance<TBunServerInstance>()`
|
|
234
234
|
2. **Get Hono server** via `getServer()`
|
|
235
|
-
3. **
|
|
236
|
-
4. **
|
|
237
|
-
5. **
|
|
238
|
-
6. **
|
|
239
|
-
7. **
|
|
235
|
+
3. **Validate server instance** -- throws `"[WebSocketComponent] Bun server instance not available!"` if not found
|
|
236
|
+
4. **Create WebSocketServerHelper** with all resolved bindings and server options
|
|
237
|
+
5. **Await `wsHelper.configure()`** which connects Redis clients and sets up subscriptions
|
|
238
|
+
6. **Bind the helper** to `WEBSOCKET_INSTANCE` in the DI container
|
|
239
|
+
7. **Create custom `fetch` handler** via `createBunFetchHandler({ wsPath, honoServer })`
|
|
240
|
+
8. **Wire WebSocket into running server** via `serverInstance.reload({ fetch, websocket })`
|
|
240
241
|
|
|
241
242
|
#### Post-Start Hook Code Flow
|
|
242
243
|
```typescript
|
|
@@ -503,6 +504,6 @@ The emitter shutdown is simpler since it only has one Redis client and no local
|
|
|
503
504
|
- [Setup & Configuration](./) - Quick reference, imports, setup steps, configuration, and binding keys
|
|
504
505
|
- [Usage & Examples](./usage) - Server-side usage, emitter, wire protocol, client tracking, and delivery strategy
|
|
505
506
|
- [Error Reference](./errors) - Error conditions table and troubleshooting
|
|
506
|
-
- [WebSocketServerHelper](/
|
|
507
|
+
- [WebSocketServerHelper](/extensions/helpers/websocket/) - Helper API documentation
|
|
507
508
|
- [Socket.IO Component](../socket-io/) - Node.js-compatible alternative with Socket.IO
|
|
508
509
|
- [Bun WebSocket Documentation](https://bun.sh/docs/api/websockets) - Official Bun WebSocket API reference
|
|
@@ -22,6 +22,16 @@ The server can send `error` events or close the connection under the following c
|
|
|
22
22
|
| `"Invalid redis connection!"` | Constructor: `redisConnection` is falsy | thrown `Error` (startup) |
|
|
23
23
|
| `"WebSocket upgrade failed"` | `server.upgrade()` returned `false` | HTTP `500` response |
|
|
24
24
|
|
|
25
|
+
### Component Errors
|
|
26
|
+
|
|
27
|
+
| Method | Condition | Error Message |
|
|
28
|
+
|--------|-----------|---------------|
|
|
29
|
+
| `binding()` | `application` is falsy | `"[binding] Invalid application to bind WebSocketComponent"` |
|
|
30
|
+
| `binding()` | Node.js runtime detected | `"[WebSocketComponent] Node.js runtime is not supported yet. Please use Bun runtime."` |
|
|
31
|
+
| `resolveBindings()` | `REDIS_CONNECTION` not instanceof `DefaultRedisHelper` | `"[WebSocketComponent][resolveBindings] Invalid instance of redisConnection | Please init connection with RedisHelper for single redis connection or RedisClusterHelper for redis cluster mode!"` |
|
|
32
|
+
| `resolveBindings()` | `AUTHENTICATE_HANDLER` is falsy | `"[WebSocketComponent] Invalid authenticateFn to setup WebSocket server!"` |
|
|
33
|
+
| `registerBunHook()` | Bun server instance not available | `"[WebSocketComponent] Bun server instance not available!"` |
|
|
34
|
+
|
|
25
35
|
## Troubleshooting
|
|
26
36
|
|
|
27
37
|
### "WebSocket not initialized"
|
|
@@ -32,11 +42,13 @@ The server can send `error` events or close the connection under the following c
|
|
|
32
42
|
|
|
33
43
|
### "Invalid instance of redisConnection"
|
|
34
44
|
|
|
35
|
-
**Cause**: The value bound to `REDIS_CONNECTION` is not an instance of `DefaultRedisHelper` (or its
|
|
45
|
+
**Cause**: The value bound to `REDIS_CONNECTION` is not an instance of `DefaultRedisHelper` (or its subclasses `RedisHelper` / `RedisClusterHelper`).
|
|
36
46
|
|
|
37
|
-
**Fix**: Use `RedisHelper` (
|
|
47
|
+
**Fix**: Use `RedisHelper` (single instance) or `RedisClusterHelper` (cluster mode):
|
|
38
48
|
|
|
39
49
|
```typescript
|
|
50
|
+
import { WebSocketBindingKeys } from '@venizia/ignis/websocket';
|
|
51
|
+
|
|
40
52
|
// Correct
|
|
41
53
|
this.bind({ key: WebSocketBindingKeys.REDIS_CONNECTION })
|
|
42
54
|
.toValue(new RedisHelper({ name: 'websocket', host, port, password }));
|
|
@@ -53,6 +65,8 @@ this.bind({ key: WebSocketBindingKeys.REDIS_CONNECTION })
|
|
|
53
65
|
**Fix**: Bind a valid authentication function before registering the component:
|
|
54
66
|
|
|
55
67
|
```typescript
|
|
68
|
+
import { WebSocketBindingKeys } from '@venizia/ignis/websocket';
|
|
69
|
+
|
|
56
70
|
this.bind<TWebSocketAuthenticateFn>({
|
|
57
71
|
key: WebSocketBindingKeys.AUTHENTICATE_HANDLER,
|
|
58
72
|
}).toValue(async (data) => {
|
|
@@ -118,6 +132,6 @@ setInterval(() => {
|
|
|
118
132
|
- [Setup & Configuration](./) - Quick reference, imports, setup steps, configuration, and binding keys
|
|
119
133
|
- [Usage & Examples](./usage) - Server-side usage, emitter, wire protocol, client tracking, and delivery strategy
|
|
120
134
|
- [API Reference](./api) - Architecture, WebSocketEmitter API, and internals
|
|
121
|
-
- [WebSocketServerHelper](/
|
|
135
|
+
- [WebSocketServerHelper](/extensions/helpers/websocket/) - Helper API documentation
|
|
122
136
|
- [Socket.IO Component](../socket-io/) - Node.js-compatible alternative with Socket.IO
|
|
123
137
|
- [Bun WebSocket Documentation](https://bun.sh/docs/api/websockets) - Official Bun WebSocket API reference
|