@venizia/ignis-docs 0.0.7 → 0.0.8-1
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/helpers/docs.helper.d.ts.map +1 -1
- package/dist/mcp-server/helpers/docs.helper.js +1 -1
- package/dist/mcp-server/helpers/docs.helper.js.map +1 -1
- package/dist/mcp-server/tools/base.tool.d.ts +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/dist/mcp-server/tools/docs/search-documents.tool.d.ts +1 -1
- package/dist/mcp-server/tools/docs/search-documents.tool.js +1 -1
- package/dist/mcp-server/tools/docs/search-documents.tool.js.map +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.js +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.js.map +1 -1
- package/dist/mcp-server/tools/github/search-code.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/search-code.tool.js +1 -1
- package/dist/mcp-server/tools/github/search-code.tool.js.map +1 -1
- package/package.json +9 -9
- package/wiki/best-practices/api-usage-examples.md +9 -9
- package/wiki/best-practices/architectural-patterns.md +19 -3
- package/wiki/best-practices/architecture-decisions.md +6 -6
- package/wiki/best-practices/code-style-standards/advanced-patterns.md +1 -1
- package/wiki/best-practices/code-style-standards/control-flow.md +1 -1
- package/wiki/best-practices/code-style-standards/function-patterns.md +2 -2
- package/wiki/best-practices/code-style-standards/index.md +2 -2
- package/wiki/best-practices/code-style-standards/naming-conventions.md +1 -1
- package/wiki/best-practices/code-style-standards/route-definitions.md +4 -4
- package/wiki/best-practices/data-modeling.md +1 -1
- package/wiki/best-practices/deployment-strategies.md +1 -1
- package/wiki/best-practices/error-handling.md +2 -2
- package/wiki/best-practices/performance-optimization.md +3 -3
- package/wiki/best-practices/security-guidelines.md +2 -2
- package/wiki/best-practices/troubleshooting-tips.md +1 -1
- package/wiki/{references → extensions}/components/authentication/api.md +12 -20
- package/wiki/{references → extensions}/components/authentication/errors.md +1 -1
- package/wiki/{references → extensions}/components/authentication/index.md +5 -8
- package/wiki/{references → extensions}/components/authentication/usage.md +20 -36
- package/wiki/{references → extensions}/components/authorization/api.md +62 -13
- package/wiki/{references → extensions}/components/authorization/errors.md +12 -7
- package/wiki/{references → extensions}/components/authorization/index.md +93 -6
- package/wiki/{references → extensions}/components/authorization/usage.md +42 -4
- package/wiki/{references → extensions}/components/health-check.md +5 -4
- package/wiki/{references → extensions}/components/index.md +2 -0
- package/wiki/{references → extensions}/components/mail/index.md +1 -1
- package/wiki/{references → extensions}/components/request-tracker.md +1 -1
- package/wiki/{references → extensions}/components/socket-io/api.md +2 -2
- package/wiki/{references → extensions}/components/socket-io/errors.md +2 -0
- package/wiki/{references → extensions}/components/socket-io/index.md +24 -20
- package/wiki/{references → extensions}/components/socket-io/usage.md +2 -2
- package/wiki/{references → extensions}/components/static-asset/api.md +14 -15
- package/wiki/{references → extensions}/components/static-asset/errors.md +3 -1
- package/wiki/{references → extensions}/components/static-asset/index.md +158 -89
- package/wiki/{references → extensions}/components/static-asset/usage.md +8 -5
- package/wiki/{references → extensions}/components/swagger.md +3 -3
- package/wiki/{references → extensions}/components/template/index.md +4 -4
- package/wiki/{references → extensions}/components/template/setup-page.md +1 -1
- package/wiki/{references → extensions}/components/template/single-page.md +1 -1
- package/wiki/{references → extensions}/components/websocket/api.md +7 -6
- package/wiki/{references → extensions}/components/websocket/errors.md +17 -3
- package/wiki/{references → extensions}/components/websocket/index.md +17 -11
- package/wiki/{references → extensions}/components/websocket/usage.md +2 -2
- package/wiki/{references → extensions}/helpers/crypto/index.md +1 -1
- package/wiki/{references → extensions}/helpers/env/index.md +9 -5
- package/wiki/{references → extensions}/helpers/error/index.md +2 -7
- package/wiki/{references → extensions}/helpers/index.md +18 -6
- package/wiki/{references → extensions}/helpers/kafka/admin.md +13 -1
- package/wiki/{references → extensions}/helpers/kafka/consumer.md +32 -31
- package/wiki/{references → extensions}/helpers/kafka/examples.md +20 -20
- package/wiki/{references → extensions}/helpers/kafka/index.md +61 -54
- package/wiki/{references → extensions}/helpers/kafka/producer.md +21 -20
- package/wiki/{references → extensions}/helpers/kafka/schema-registry.md +25 -25
- package/wiki/{references → extensions}/helpers/logger/index.md +2 -2
- package/wiki/{references → extensions}/helpers/queue/index.md +400 -4
- package/wiki/{references → extensions}/helpers/storage/api.md +170 -10
- package/wiki/{references → extensions}/helpers/storage/index.md +44 -8
- package/wiki/{references → extensions}/helpers/template/index.md +1 -1
- package/wiki/{references → extensions}/helpers/testing/index.md +4 -4
- package/wiki/{references → extensions}/helpers/types/index.md +63 -16
- package/wiki/{references → extensions}/helpers/websocket/index.md +1 -1
- package/wiki/extensions/index.md +48 -0
- package/wiki/guides/core-concepts/application/bootstrapping.md +55 -37
- package/wiki/guides/core-concepts/application/index.md +95 -35
- package/wiki/guides/core-concepts/components-guide.md +23 -19
- package/wiki/guides/core-concepts/components.md +34 -10
- package/wiki/guides/core-concepts/dependency-injection.md +99 -34
- package/wiki/guides/core-concepts/grpc-controllers.md +295 -0
- package/wiki/guides/core-concepts/persistent/datasources.md +37 -19
- package/wiki/guides/core-concepts/persistent/index.md +6 -6
- package/wiki/guides/core-concepts/persistent/models.md +50 -6
- package/wiki/guides/core-concepts/persistent/repositories.md +83 -8
- package/wiki/guides/core-concepts/persistent/transactions.md +39 -8
- package/wiki/guides/core-concepts/{controllers.md → rest-controllers.md} +32 -35
- package/wiki/guides/core-concepts/services.md +19 -6
- package/wiki/guides/get-started/5-minute-quickstart.md +17 -17
- 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 +45 -39
- package/wiki/guides/tutorials/complete-installation.md +74 -51
- package/wiki/guides/tutorials/ecommerce-api.md +39 -30
- package/wiki/guides/tutorials/realtime-chat.md +12 -13
- 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 +195 -69
- package/wiki/references/base/repositories/index.md +447 -12
- package/wiki/references/base/repositories/mixins.md +103 -98
- package/wiki/references/base/repositories/relations.md +129 -45
- package/wiki/references/base/repositories/soft-deletable.md +104 -23
- package/wiki/references/base/services.md +94 -14
- package/wiki/references/index.md +12 -10
- package/wiki/references/quick-reference.md +98 -65
- package/wiki/references/utilities/crypto.md +21 -4
- package/wiki/references/utilities/date.md +25 -7
- package/wiki/references/utilities/index.md +26 -24
- package/wiki/references/utilities/jsx.md +54 -54
- package/wiki/references/utilities/module.md +8 -6
- package/wiki/references/utilities/parse.md +16 -9
- package/wiki/references/utilities/performance.md +22 -7
- package/wiki/references/utilities/promise.md +19 -16
- package/wiki/references/utilities/request.md +48 -26
- package/wiki/references/utilities/schema.md +69 -6
- package/wiki/references/utilities/statuses.md +131 -140
- /package/wiki/{references → extensions}/components/mail/api.md +0 -0
- /package/wiki/{references → extensions}/components/mail/errors.md +0 -0
- /package/wiki/{references → extensions}/components/mail/usage.md +0 -0
- /package/wiki/{references → extensions}/components/template/api-page.md +0 -0
- /package/wiki/{references → extensions}/components/template/errors-page.md +0 -0
- /package/wiki/{references → extensions}/components/template/usage-page.md +0 -0
- /package/wiki/{references → extensions}/helpers/cron/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/inversion/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/network/api.md +0 -0
- /package/wiki/{references → extensions}/helpers/network/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/redis/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/socket-io/api.md +0 -0
- /package/wiki/{references → extensions}/helpers/socket-io/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/template/single-page.md +0 -0
- /package/wiki/{references → extensions}/helpers/uid/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/websocket/api.md +0 -0
- /package/wiki/{references → extensions}/helpers/worker-thread/index.md +0 -0
- /package/wiki/{references → extensions}/src-details/mcp-server.md +0 -0
|
@@ -10,12 +10,12 @@ Use the `authorize` field in route configs to declare authorization requirements
|
|
|
10
10
|
|
|
11
11
|
```typescript
|
|
12
12
|
import {
|
|
13
|
-
|
|
13
|
+
BaseRestController,
|
|
14
14
|
Authentication,
|
|
15
15
|
AuthorizationActions,
|
|
16
16
|
} from '@venizia/ignis';
|
|
17
17
|
|
|
18
|
-
class ArticleController extends
|
|
18
|
+
class ArticleController extends BaseRestController {
|
|
19
19
|
binding() {
|
|
20
20
|
// Read requires 'read' action on 'Article' resource
|
|
21
21
|
this.defineRoute({
|
|
@@ -102,7 +102,7 @@ Use the `authorize` field alongside `authenticate` in decorator configs:
|
|
|
102
102
|
import { controller, get, post, AuthorizationActions, AuthorizationRoles } from '@venizia/ignis';
|
|
103
103
|
|
|
104
104
|
@controller({ path: '/articles' })
|
|
105
|
-
class ArticleController extends
|
|
105
|
+
class ArticleController extends BaseRestController {
|
|
106
106
|
@get({
|
|
107
107
|
configs: {
|
|
108
108
|
path: '/',
|
|
@@ -134,6 +134,34 @@ class ArticleController extends BaseController {
|
|
|
134
134
|
}
|
|
135
135
|
```
|
|
136
136
|
|
|
137
|
+
### gRPC Route Authorization
|
|
138
|
+
|
|
139
|
+
Authorization works the same way in gRPC controllers. Use the `authorize` field in RPC metadata:
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import { AuthorizationActions, Authentication } from '@venizia/ignis';
|
|
143
|
+
|
|
144
|
+
class GreeterController extends BaseGrpcController {
|
|
145
|
+
binding() {
|
|
146
|
+
this.defineRoute({
|
|
147
|
+
configs: {
|
|
148
|
+
method: sayHello,
|
|
149
|
+
authenticate: { strategies: [Authentication.STRATEGY_JWT] },
|
|
150
|
+
authorize: {
|
|
151
|
+
action: AuthorizationActions.EXECUTE,
|
|
152
|
+
resource: 'Greeter',
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
handler: async (context) => {
|
|
156
|
+
// Handler runs only if authorized
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The `AbstractGrpcController.buildRpcMiddlewares()` method injects authorization middleware in the same order as REST controllers: authenticate first, then authorize.
|
|
164
|
+
|
|
137
165
|
## Using the `authorize()` Standalone Function
|
|
138
166
|
|
|
139
167
|
The `authorize()` function is a convenience wrapper around `AuthorizationProvider`. It returns a Hono `MiddlewareHandler`:
|
|
@@ -383,7 +411,7 @@ ControllerFactory.defineCrudController({
|
|
|
383
411
|
|
|
384
412
|
### Priority Resolution (Factory Routes)
|
|
385
413
|
|
|
386
|
-
The `
|
|
414
|
+
The `resolveRouteAuthorize` function in `defineControllerRouteConfigs` resolves authorization with this priority:
|
|
387
415
|
|
|
388
416
|
```mermaid
|
|
389
417
|
flowchart TD
|
|
@@ -403,6 +431,16 @@ flowchart TD
|
|
|
403
431
|
3. **Per-route `authorize` spec** -- overrides controller-level
|
|
404
432
|
4. **Controller-level `authorize`** -- default for all routes
|
|
405
433
|
|
|
434
|
+
### Per-Route Auth Type
|
|
435
|
+
|
|
436
|
+
The per-route authorize config is typed as a discriminated union:
|
|
437
|
+
|
|
438
|
+
```typescript
|
|
439
|
+
type TRouteAuthorizeConfig = { skip: true } | IAuthorizationSpec | IAuthorizationSpec[];
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
This means each route can either skip authorization entirely, provide a single spec, or provide an array of specs that all must pass.
|
|
443
|
+
|
|
406
444
|
## Dynamic Skip Authorization
|
|
407
445
|
|
|
408
446
|
Use `Authorization.SKIP_AUTHORIZATION` to dynamically bypass authorization in middleware (step 1 in the pipeline):
|
|
@@ -213,10 +213,11 @@ The controller uses `this.definitions = RouteConfigs` to store route configurati
|
|
|
213
213
|
#### Controller Source
|
|
214
214
|
```typescript
|
|
215
215
|
import {
|
|
216
|
-
|
|
217
|
-
api, jsonContent, jsonResponse, z,
|
|
216
|
+
BaseRestController, IControllerOptions, TRouteContext,
|
|
218
217
|
} from '@venizia/ignis';
|
|
219
|
-
import {
|
|
218
|
+
import { api, jsonContent, jsonResponse } from '@venizia/ignis';
|
|
219
|
+
import { z } from '@hono/zod-openapi';
|
|
220
|
+
import { HTTP, ValueOrPromise } from '@venizia/ignis-helpers';
|
|
220
221
|
|
|
221
222
|
const RouteConfigs = {
|
|
222
223
|
ROOT: {
|
|
@@ -258,7 +259,7 @@ const RouteConfigs = {
|
|
|
258
259
|
},
|
|
259
260
|
} as const;
|
|
260
261
|
|
|
261
|
-
export class HealthCheckController extends
|
|
262
|
+
export class HealthCheckController extends BaseRestController {
|
|
262
263
|
constructor(opts: IControllerOptions) {
|
|
263
264
|
super({ ...opts, scope: HealthCheckController.name });
|
|
264
265
|
this.definitions = RouteConfigs;
|
|
@@ -15,6 +15,7 @@ Reusable, pluggable modules that group together related features. A component ca
|
|
|
15
15
|
| [WebSocket](./websocket/) | Real-time communication | Bun native WebSocket, Redis Pub/Sub, heartbeat |
|
|
16
16
|
| [Static Asset](./static-asset/) | File management | Upload/download files, MinIO & local filesystem support |
|
|
17
17
|
| [Swagger](./swagger) | API documentation | OpenAPI generation, Swagger UI, Scalar UI |
|
|
18
|
+
| [gRPC](/references/base/grpc-controllers) | gRPC transport | ConnectRPC integration, unary RPC, decorator-based |
|
|
18
19
|
|
|
19
20
|
## Creating a Component
|
|
20
21
|
|
|
@@ -81,6 +82,7 @@ Using components is a great way to organize your application's features into mod
|
|
|
81
82
|
- [WebSocket](./websocket/) - Bun native WebSocket
|
|
82
83
|
- [Static Asset](./static-asset/) - Static file serving
|
|
83
84
|
- [Swagger](./swagger) - API documentation
|
|
85
|
+
- [gRPC](/references/base/grpc-controllers) - gRPC transport (ConnectRPC)
|
|
84
86
|
|
|
85
87
|
- **References:**
|
|
86
88
|
- [BaseComponent API](/references/base/components) - Component base class
|
|
@@ -211,7 +211,7 @@ The `TMailOptions` configuration determines which email transport provider is us
|
|
|
211
211
|
|
|
212
212
|
```typescript
|
|
213
213
|
// Simple SMTP Authentication (e.g., Gmail with app password)
|
|
214
|
-
this.bind<TMailOptions>({ key:
|
|
214
|
+
this.bind<TMailOptions>({ key: MailKeys.MAIL_OPTIONS }).toValue({
|
|
215
215
|
provider: 'nodemailer',
|
|
216
216
|
from: 'noreply@example.com',
|
|
217
217
|
fromName: 'My App',
|
|
@@ -248,7 +248,7 @@ If running without a proxy, ensure the runtime provides connection info (Bun doe
|
|
|
248
248
|
- [All Components](./index) - Built-in components list
|
|
249
249
|
|
|
250
250
|
- **Helpers:**
|
|
251
|
-
- [Logger Helper](/
|
|
251
|
+
- [Logger Helper](/extensions/helpers/logger/) - Logging utilities
|
|
252
252
|
|
|
253
253
|
- **Best Practices:**
|
|
254
254
|
- [Troubleshooting Tips](/best-practices/troubleshooting-tips) - Debugging with request IDs
|
|
@@ -630,7 +630,7 @@ Reads all binding keys from the DI container and validates required ones:
|
|
|
630
630
|
|---------|-----------|------------------|
|
|
631
631
|
| `SERVER_OPTIONS` | Optional, merged with defaults via `Object.assign()` | -- |
|
|
632
632
|
| `REDIS_CONNECTION` | Must be `instanceof DefaultRedisHelper` | `"Invalid instance of redisConnection | Please init connection with RedisHelper for single redis connection or RedisClusterHelper for redis cluster mode!"` |
|
|
633
|
-
| `AUTHENTICATE_HANDLER` | Must be a function (non-null) | `"Invalid authenticateFn to setup io socket server!"` |
|
|
633
|
+
| `AUTHENTICATE_HANDLER` | Must be a function (non-null) | `"[DANGER][SocketIOComponent] Invalid authenticateFn to setup io socket server!"` |
|
|
634
634
|
| `VALIDATE_ROOM_HANDLER` | Optional, resolved from container, `null` coerced to `undefined` | -- |
|
|
635
635
|
| `CLIENT_CONNECTED_HANDLER` | Optional, resolved from container, `null` coerced to `undefined` | -- |
|
|
636
636
|
|
|
@@ -673,7 +673,7 @@ Returns a fetch handler function that routes requests:
|
|
|
673
673
|
Registers a post-start hook that:
|
|
674
674
|
|
|
675
675
|
1. Gets the HTTP server instance via `getServerInstance()`
|
|
676
|
-
2. Validates the server instance exists (throws `"HTTP server not available for Node.js runtime!"` if not)
|
|
676
|
+
2. Validates the server instance exists (throws `"[SocketIOComponent] HTTP server not available for Node.js runtime!"` if not)
|
|
677
677
|
3. Calls `createNodeSocketIOHelper()` which creates `SocketIOServerHelper` with `runtime: RuntimeModules.NODE` and the HTTP server, then awaits `configure()`
|
|
678
678
|
4. Binds the helper to `SOCKET_IO_INSTANCE`
|
|
679
679
|
|
|
@@ -59,6 +59,8 @@
|
|
|
59
59
|
**Fix**: Use `RedisHelper` (single instance) or `RedisClusterHelper` (cluster mode):
|
|
60
60
|
|
|
61
61
|
```typescript
|
|
62
|
+
import { SocketIOBindingKeys } from '@venizia/ignis/socket-io';
|
|
63
|
+
|
|
62
64
|
// Correct -- single instance
|
|
63
65
|
this.bind({ key: SocketIOBindingKeys.REDIS_CONNECTION })
|
|
64
66
|
.toValue(new RedisHelper({ name: 'socket-io', host, port, password }));
|
|
@@ -8,31 +8,33 @@
|
|
|
8
8
|
|------|-------|
|
|
9
9
|
| **Package** | `@venizia/ignis` (core) |
|
|
10
10
|
| **Class** | `SocketIOComponent` |
|
|
11
|
-
| **Server Helper** | [`SocketIOServerHelper`](/
|
|
12
|
-
| **Client Helper** | [`SocketIOClientHelper`](/
|
|
11
|
+
| **Server Helper** | [`SocketIOServerHelper`](/extensions/helpers/socket-io/) |
|
|
12
|
+
| **Client Helper** | [`SocketIOClientHelper`](/extensions/helpers/socket-io/) |
|
|
13
13
|
| **Runtimes** | Node.js (`@hono/node-server`) and Bun (native) |
|
|
14
14
|
| **Scaling** | `@socket.io/redis-adapter` + `@socket.io/redis-emitter` |
|
|
15
15
|
|
|
16
16
|
#### Import Paths
|
|
17
|
+
|
|
18
|
+
> [!IMPORTANT]
|
|
19
|
+
> `SocketIOComponent` and `SocketIOBindingKeys` are **not** exported from the `@venizia/ignis` barrel. You must import from the `@venizia/ignis/socket-io` subpath.
|
|
20
|
+
|
|
17
21
|
```typescript
|
|
22
|
+
// From core -- subpath import (NOT from '@venizia/ignis')
|
|
18
23
|
import {
|
|
19
24
|
SocketIOComponent,
|
|
20
25
|
SocketIOBindingKeys,
|
|
21
|
-
} from '@venizia/ignis';
|
|
26
|
+
} from '@venizia/ignis/socket-io';
|
|
22
27
|
|
|
28
|
+
// From helpers -- subpath import
|
|
23
29
|
import {
|
|
24
30
|
SocketIOServerHelper,
|
|
25
|
-
RedisHelper,
|
|
26
|
-
} from '@venizia/ignis-helpers';
|
|
27
|
-
|
|
28
|
-
import {
|
|
29
31
|
SocketIOClientHelper,
|
|
30
32
|
SocketIOConstants,
|
|
31
33
|
SocketIOClientStates,
|
|
32
34
|
} from '@venizia/ignis-helpers/socket-io';
|
|
33
35
|
|
|
36
|
+
// Types from helpers subpath
|
|
34
37
|
import type {
|
|
35
|
-
IServerOptions,
|
|
36
38
|
TSocketIOAuthenticateFn,
|
|
37
39
|
TSocketIOValidateRoomFn,
|
|
38
40
|
TSocketIOClientConnectedFn,
|
|
@@ -40,7 +42,7 @@ import type {
|
|
|
40
42
|
IOptions,
|
|
41
43
|
TSocketIOEventHandler,
|
|
42
44
|
TSocketIOClientState,
|
|
43
|
-
} from '@venizia/ignis';
|
|
45
|
+
} from '@venizia/ignis-helpers/socket-io';
|
|
44
46
|
```
|
|
45
47
|
|
|
46
48
|
### Use Cases
|
|
@@ -69,18 +71,17 @@ bun add @socket.io/bun-engine
|
|
|
69
71
|
In your application's `preConfigure()` method, bind the required services and register the component:
|
|
70
72
|
|
|
71
73
|
```typescript
|
|
74
|
+
import { BaseApplication } from '@venizia/ignis';
|
|
72
75
|
import {
|
|
73
|
-
BaseApplication,
|
|
74
76
|
SocketIOComponent,
|
|
75
77
|
SocketIOBindingKeys,
|
|
76
|
-
|
|
77
|
-
} from '@venizia/ignis';
|
|
78
|
-
import { RedisHelper } from '@venizia/ignis-helpers';
|
|
78
|
+
} from '@venizia/ignis/socket-io';
|
|
79
|
+
import { RedisHelper, ValueOrPromise } from '@venizia/ignis-helpers';
|
|
79
80
|
import type {
|
|
80
81
|
TSocketIOAuthenticateFn,
|
|
81
82
|
TSocketIOValidateRoomFn,
|
|
82
83
|
TSocketIOClientConnectedFn,
|
|
83
|
-
} from '@venizia/ignis';
|
|
84
|
+
} from '@venizia/ignis-helpers/socket-io';
|
|
84
85
|
|
|
85
86
|
export class Application extends BaseApplication {
|
|
86
87
|
private redisHelper: RedisHelper;
|
|
@@ -225,10 +226,10 @@ const DEFAULT_SERVER_OPTIONS: Partial<IServerOptions> = {
|
|
|
225
226
|
Bind custom server options before registering the component:
|
|
226
227
|
|
|
227
228
|
```typescript
|
|
228
|
-
import { SocketIOBindingKeys
|
|
229
|
+
import { SocketIOBindingKeys } from '@venizia/ignis/socket-io';
|
|
230
|
+
import type { ServerOptions } from 'socket.io';
|
|
229
231
|
|
|
230
|
-
const customOptions: Partial<
|
|
231
|
-
identifier: 'my-app-socket',
|
|
232
|
+
const customOptions: Partial<ServerOptions> = {
|
|
232
233
|
path: '/socket.io',
|
|
233
234
|
cors: {
|
|
234
235
|
origin: ['https://myapp.com', 'https://admin.myapp.com'],
|
|
@@ -240,20 +241,23 @@ const customOptions: Partial<IServerOptions> = {
|
|
|
240
241
|
maxHttpBufferSize: 1e6, // 1MB
|
|
241
242
|
};
|
|
242
243
|
|
|
243
|
-
this.bind<Partial<
|
|
244
|
+
this.bind<Partial<ServerOptions>>({
|
|
244
245
|
key: SocketIOBindingKeys.SERVER_OPTIONS,
|
|
245
246
|
}).toValue(customOptions);
|
|
246
247
|
|
|
247
248
|
this.component(SocketIOComponent);
|
|
248
249
|
```
|
|
249
250
|
|
|
251
|
+
> [!NOTE]
|
|
252
|
+
> The `identifier` field is part of the component's `IServerOptions` interface (which extends `ServerOptions`), not Socket.IO's native options. To set the identifier, include it in the bound options object.
|
|
253
|
+
|
|
250
254
|
## Binding Keys
|
|
251
255
|
|
|
252
256
|
All binding keys are available in `SocketIOBindingKeys`:
|
|
253
257
|
|
|
254
258
|
| Binding Key | Constant | Type | Required | Default |
|
|
255
259
|
|------------|----------|------|----------|---------|
|
|
256
|
-
| `@app/socket-io/server-options` | `SERVER_OPTIONS` | `Partial<
|
|
260
|
+
| `@app/socket-io/server-options` | `SERVER_OPTIONS` | `Partial<ServerOptions>` | No | See defaults above |
|
|
257
261
|
| `@app/socket-io/redis-connection` | `REDIS_CONNECTION` | `RedisHelper` / `RedisClusterHelper` / `DefaultRedisHelper` | **Yes** | `null` |
|
|
258
262
|
| `@app/socket-io/authenticate-handler` | `AUTHENTICATE_HANDLER` | `TSocketIOAuthenticateFn` | **Yes** | `null` |
|
|
259
263
|
| `@app/socket-io/validate-room-handler` | `VALIDATE_ROOM_HANDLER` | `TSocketIOValidateRoomFn` | No | `null` |
|
|
@@ -404,7 +408,7 @@ interface IHandshake {
|
|
|
404
408
|
- **Components:**
|
|
405
409
|
- [Components Index](../index) -- All built-in components
|
|
406
410
|
- **Helpers:**
|
|
407
|
-
- [Socket.IO Helper](/
|
|
411
|
+
- [Socket.IO Helper](/extensions/helpers/socket-io/) -- Full `SocketIOServerHelper` + `SocketIOClientHelper` API reference
|
|
408
412
|
- **External Resources:**
|
|
409
413
|
- [Socket.IO Documentation](https://socket.io/docs/) -- Official docs
|
|
410
414
|
- [Socket.IO Redis Adapter](https://socket.io/docs/v4/redis-adapter/) -- Horizontal scaling guide
|
|
@@ -12,11 +12,11 @@ Inject `SocketIOServerHelper` to interact with Socket.IO:
|
|
|
12
12
|
import {
|
|
13
13
|
BaseService,
|
|
14
14
|
inject,
|
|
15
|
-
SocketIOBindingKeys,
|
|
16
15
|
CoreBindings,
|
|
17
16
|
BaseApplication,
|
|
18
17
|
} from '@venizia/ignis';
|
|
19
|
-
import {
|
|
18
|
+
import { SocketIOBindingKeys } from '@venizia/ignis/socket-io';
|
|
19
|
+
import { SocketIOServerHelper } from '@venizia/ignis-helpers/socket-io';
|
|
20
20
|
|
|
21
21
|
export class NotificationService extends BaseService {
|
|
22
22
|
// Lazy getter pattern -- helper is bound AFTER server starts
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
The `AssetControllerFactory.defineAssetController()` method dynamically creates controller classes at runtime. For each storage backend in the options:
|
|
8
8
|
|
|
9
|
-
1. A new class extending `
|
|
9
|
+
1. A new class extending `BaseRestController` is created with `@controller({ path: basePath })`
|
|
10
10
|
2. The class name is set dynamically via `Object.defineProperty(_controller, 'name', { value: name })`
|
|
11
11
|
3. Routes are bound in the controller's `binding()` method using `this.bindRoute().to()`
|
|
12
|
-
4.
|
|
12
|
+
4. Route configs are spread-merged with per-route overrides from `controller.routes` (e.g., `{ ...StaticAssetDefinitions.UPLOAD, ...routes?.upload }`)
|
|
13
|
+
5. The controller is registered via `this.application.controller()`
|
|
13
14
|
|
|
14
15
|
```
|
|
15
16
|
StaticAssetComponent.binding()
|
|
@@ -17,7 +18,7 @@ StaticAssetComponent.binding()
|
|
|
17
18
|
AssetControllerFactory.defineAssetController({ controller, storage, helper, ... })
|
|
18
19
|
| creates
|
|
19
20
|
@controller({ path: basePath })
|
|
20
|
-
class _controller extends
|
|
21
|
+
class _controller extends BaseRestController { ... }
|
|
21
22
|
| registered via
|
|
22
23
|
this.application.controller(_controller)
|
|
23
24
|
```
|
|
@@ -28,11 +29,7 @@ The factory method accepts the following options:
|
|
|
28
29
|
|
|
29
30
|
```typescript
|
|
30
31
|
interface IAssetControllerOptions {
|
|
31
|
-
controller:
|
|
32
|
-
name: string;
|
|
33
|
-
basePath: string;
|
|
34
|
-
isStrict?: boolean; // Default: true
|
|
35
|
-
};
|
|
32
|
+
controller: TStaticAssetsComponentOptions[string]['controller'];
|
|
36
33
|
storage: TStaticAssetStorageType;
|
|
37
34
|
helper: IStorageHelper;
|
|
38
35
|
useMetaLink?: boolean;
|
|
@@ -49,8 +46,9 @@ A constants class following the Ignis pattern with `static readonly` fields, a `
|
|
|
49
46
|
class StaticAssetStorageTypes {
|
|
50
47
|
static readonly DISK = 'disk';
|
|
51
48
|
static readonly MINIO = 'minio';
|
|
49
|
+
static readonly BUN_S3 = 'bun-s3';
|
|
52
50
|
|
|
53
|
-
static readonly SCHEME_SET = new Set([this.DISK, this.MINIO]);
|
|
51
|
+
static readonly SCHEME_SET = new Set([this.DISK, this.MINIO, this.BUN_S3]);
|
|
54
52
|
|
|
55
53
|
static isValid(orgType: string): boolean {
|
|
56
54
|
return this.SCHEME_SET.has(orgType);
|
|
@@ -58,7 +56,7 @@ class StaticAssetStorageTypes {
|
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
type TStaticAssetStorageType = TConstValue<typeof StaticAssetStorageTypes>;
|
|
61
|
-
// Resolves to: 'disk' | 'minio'
|
|
59
|
+
// Resolves to: 'disk' | 'minio' | 'bun-s3'
|
|
62
60
|
```
|
|
63
61
|
|
|
64
62
|
## MultipartBodySchema
|
|
@@ -133,7 +131,7 @@ interface IStorageHelper {
|
|
|
133
131
|
upload(opts: {
|
|
134
132
|
bucket: string;
|
|
135
133
|
files: IUploadFile[];
|
|
136
|
-
normalizeNameFn?: (opts: { originalName: string
|
|
134
|
+
normalizeNameFn?: (opts: { originalName: string }) => string;
|
|
137
135
|
normalizeLinkFn?: (opts: { bucketName: string; normalizeName: string }) => string;
|
|
138
136
|
}): Promise<IUploadResult[]>;
|
|
139
137
|
|
|
@@ -157,7 +155,6 @@ interface IUploadFile {
|
|
|
157
155
|
buffer: Buffer;
|
|
158
156
|
size: number;
|
|
159
157
|
encoding?: string;
|
|
160
|
-
folderPath?: string;
|
|
161
158
|
[key: string | symbol]: any;
|
|
162
159
|
}
|
|
163
160
|
|
|
@@ -207,6 +204,7 @@ BaseStorageHelper (abstract class)
|
|
|
207
204
|
|
|
|
208
205
|
+-- DiskHelper (local filesystem)
|
|
209
206
|
+-- MinioHelper (S3-compatible)
|
|
207
|
+
+-- BunS3Helper (Bun-native S3)
|
|
210
208
|
```
|
|
211
209
|
|
|
212
210
|
## MetaLink SQL Schema
|
|
@@ -225,21 +223,22 @@ BaseStorageHelper (abstract class)
|
|
|
225
223
|
| `size` | INTEGER | No | -- | File size in bytes |
|
|
226
224
|
| `etag` | TEXT | Yes | -- | Entity tag for versioning |
|
|
227
225
|
| `metadata` | JSONB | Yes | -- | Additional file metadata |
|
|
228
|
-
| `storage_type` | TEXT | No | -- | Storage type (`'disk'` or `'
|
|
226
|
+
| `storage_type` | TEXT | No | -- | Storage type (`'disk'`, `'minio'`, or `'bun-s3'`) |
|
|
229
227
|
| `is_synced` | BOOLEAN | No | `false` | Whether MetaLink is synchronized with storage |
|
|
228
|
+
| `variant` | TEXT | Yes | -- | Upload variant tag (e.g., `'thumbnail'`, `'original'`) |
|
|
230
229
|
| `principal_type` | TEXT | Yes | -- | Type of the associated principal (e.g., `'user'`, `'service'`) |
|
|
231
230
|
| `principal_id` | TEXT | Yes | -- | ID of the associated principal (always stored as string) |
|
|
232
231
|
|
|
233
232
|
**Indexes:** `bucket_name`, `object_name`, `storage_type`, `is_synced`.
|
|
234
233
|
|
|
235
234
|
> [!NOTE]
|
|
236
|
-
> The `isSynced` field is automatically set to `true` when files are uploaded or synced via the meta-links endpoint. When a file is deleted, the MetaLink record is removed entirely. The `principalType` and `
|
|
235
|
+
> The `isSynced` field is automatically set to `true` when files are uploaded or synced via the meta-links endpoint. When a file is deleted, the MetaLink record is removed entirely. The `principalType`, `principalId`, and `variant` fields are only populated during upload when the corresponding query parameters are provided.
|
|
237
236
|
|
|
238
237
|
### MetaLink Tracking
|
|
239
238
|
|
|
240
239
|
When `useMetaLink: true`, the component:
|
|
241
240
|
|
|
242
|
-
- **On upload:** Creates a MetaLink database record for each uploaded file after fetching file stats from storage. Stores `principalType` and `
|
|
241
|
+
- **On upload:** Creates a MetaLink database record for each uploaded file after fetching file stats from storage. If a `createMetaLink` callback is provided on `TMetaLinkConfig`, it is used instead of the default creation logic. Stores `principalType`, `principalId`, and `variant` from query parameters (if provided). The `principalId` is always coerced to a string via `String()`. If MetaLink creation fails, the upload still succeeds and the response includes `metaLink: null` with a `metaLinkError` message.
|
|
243
242
|
- **On delete:** Initiates MetaLink record deletion as fire-and-forget (the `.then()/.catch()` promise chain is not awaited). The HTTP response with `{ "success": true }` returns before the database deletion completes. Deletion errors are logged but do not fail the request.
|
|
244
243
|
- **On sync (PUT meta-links):** Checks if a MetaLink exists for the object (matched by `bucketName` + `objectName`). Updates it if found, creates a new one if not. Always sets `isSynced: true`. Returns `{ success: true, metaLink: ... }`.
|
|
245
244
|
|
|
@@ -41,10 +41,12 @@ Every endpoint that accepts `bucketName` validates it and returns HTTP 400 `"Inv
|
|
|
41
41
|
**Fix:** Ensure each storage configuration has all required fields:
|
|
42
42
|
|
|
43
43
|
```typescript
|
|
44
|
+
import { StaticAssetStorageTypes } from '@venizia/ignis/static-asset';
|
|
45
|
+
|
|
44
46
|
{
|
|
45
47
|
[uniqueKey]: {
|
|
46
48
|
controller: { name, basePath, isStrict },
|
|
47
|
-
storage:
|
|
49
|
+
storage: StaticAssetStorageTypes.DISK | StaticAssetStorageTypes.MINIO | StaticAssetStorageTypes.BUN_S3,
|
|
48
50
|
helper: IStorageHelper,
|
|
49
51
|
extra: {}
|
|
50
52
|
}
|