@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.
Files changed (172) hide show
  1. package/dist/mcp-server/common/paths.d.ts +4 -2
  2. package/dist/mcp-server/common/paths.d.ts.map +1 -1
  3. package/dist/mcp-server/common/paths.js +8 -6
  4. package/dist/mcp-server/common/paths.js.map +1 -1
  5. package/dist/mcp-server/helpers/docs.helper.d.ts.map +1 -1
  6. package/dist/mcp-server/helpers/docs.helper.js +1 -1
  7. package/dist/mcp-server/helpers/docs.helper.js.map +1 -1
  8. package/dist/mcp-server/tools/base.tool.d.ts +1 -1
  9. package/dist/mcp-server/tools/docs/get-document-content.tool.d.ts +1 -1
  10. package/dist/mcp-server/tools/docs/get-document-content.tool.d.ts.map +1 -1
  11. package/dist/mcp-server/tools/docs/get-document-content.tool.js +7 -7
  12. package/dist/mcp-server/tools/docs/get-document-metadata.tool.js +3 -3
  13. package/dist/mcp-server/tools/docs/get-package-overview.tool.d.ts +1 -1
  14. package/dist/mcp-server/tools/docs/get-package-overview.tool.js +1 -1
  15. package/dist/mcp-server/tools/docs/search-documents.tool.d.ts +1 -1
  16. package/dist/mcp-server/tools/docs/search-documents.tool.js +1 -1
  17. package/dist/mcp-server/tools/docs/search-documents.tool.js.map +1 -1
  18. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
  19. package/dist/mcp-server/tools/github/list-project-files.tool.js +1 -1
  20. package/dist/mcp-server/tools/github/list-project-files.tool.js.map +1 -1
  21. package/dist/mcp-server/tools/github/search-code.tool.d.ts +1 -1
  22. package/dist/mcp-server/tools/github/search-code.tool.js +1 -1
  23. package/dist/mcp-server/tools/github/search-code.tool.js.map +1 -1
  24. package/package.json +9 -9
  25. package/wiki/best-practices/api-usage-examples.md +9 -9
  26. package/wiki/best-practices/architectural-patterns.md +19 -3
  27. package/wiki/best-practices/architecture-decisions.md +6 -6
  28. package/wiki/best-practices/code-style-standards/advanced-patterns.md +1 -1
  29. package/wiki/best-practices/code-style-standards/control-flow.md +1 -1
  30. package/wiki/best-practices/code-style-standards/function-patterns.md +2 -2
  31. package/wiki/best-practices/code-style-standards/index.md +2 -2
  32. package/wiki/best-practices/code-style-standards/naming-conventions.md +1 -1
  33. package/wiki/best-practices/code-style-standards/route-definitions.md +4 -4
  34. package/wiki/best-practices/data-modeling.md +1 -1
  35. package/wiki/best-practices/deployment-strategies.md +1 -1
  36. package/wiki/best-practices/error-handling.md +2 -2
  37. package/wiki/best-practices/performance-optimization.md +3 -3
  38. package/wiki/best-practices/security-guidelines.md +2 -2
  39. package/wiki/best-practices/troubleshooting-tips.md +1 -1
  40. package/wiki/{references → extensions}/components/authentication/api.md +12 -20
  41. package/wiki/{references → extensions}/components/authentication/errors.md +1 -1
  42. package/wiki/{references → extensions}/components/authentication/index.md +5 -8
  43. package/wiki/{references → extensions}/components/authentication/usage.md +20 -36
  44. package/wiki/{references → extensions}/components/authorization/api.md +62 -13
  45. package/wiki/{references → extensions}/components/authorization/errors.md +12 -7
  46. package/wiki/{references → extensions}/components/authorization/index.md +93 -6
  47. package/wiki/{references → extensions}/components/authorization/usage.md +42 -4
  48. package/wiki/{references → extensions}/components/health-check.md +5 -4
  49. package/wiki/{references → extensions}/components/index.md +2 -0
  50. package/wiki/{references → extensions}/components/mail/index.md +1 -1
  51. package/wiki/{references → extensions}/components/request-tracker.md +1 -1
  52. package/wiki/{references → extensions}/components/socket-io/api.md +2 -2
  53. package/wiki/{references → extensions}/components/socket-io/errors.md +2 -0
  54. package/wiki/{references → extensions}/components/socket-io/index.md +24 -20
  55. package/wiki/{references → extensions}/components/socket-io/usage.md +2 -2
  56. package/wiki/{references → extensions}/components/static-asset/api.md +14 -15
  57. package/wiki/{references → extensions}/components/static-asset/errors.md +3 -1
  58. package/wiki/{references → extensions}/components/static-asset/index.md +158 -89
  59. package/wiki/{references → extensions}/components/static-asset/usage.md +8 -5
  60. package/wiki/{references → extensions}/components/swagger.md +3 -3
  61. package/wiki/{references → extensions}/components/template/index.md +4 -4
  62. package/wiki/{references → extensions}/components/template/setup-page.md +1 -1
  63. package/wiki/{references → extensions}/components/template/single-page.md +1 -1
  64. package/wiki/{references → extensions}/components/websocket/api.md +7 -6
  65. package/wiki/{references → extensions}/components/websocket/errors.md +17 -3
  66. package/wiki/{references → extensions}/components/websocket/index.md +17 -11
  67. package/wiki/{references → extensions}/components/websocket/usage.md +2 -2
  68. package/wiki/{references → extensions}/helpers/crypto/index.md +1 -1
  69. package/wiki/{references → extensions}/helpers/env/index.md +9 -5
  70. package/wiki/{references → extensions}/helpers/error/index.md +2 -7
  71. package/wiki/{references → extensions}/helpers/index.md +18 -6
  72. package/wiki/{references → extensions}/helpers/kafka/admin.md +13 -1
  73. package/wiki/{references → extensions}/helpers/kafka/consumer.md +32 -31
  74. package/wiki/{references → extensions}/helpers/kafka/examples.md +20 -20
  75. package/wiki/{references → extensions}/helpers/kafka/index.md +61 -54
  76. package/wiki/{references → extensions}/helpers/kafka/producer.md +21 -20
  77. package/wiki/{references → extensions}/helpers/kafka/schema-registry.md +25 -25
  78. package/wiki/{references → extensions}/helpers/logger/index.md +2 -2
  79. package/wiki/{references → extensions}/helpers/queue/index.md +400 -4
  80. package/wiki/{references → extensions}/helpers/storage/api.md +170 -10
  81. package/wiki/{references → extensions}/helpers/storage/index.md +44 -8
  82. package/wiki/{references → extensions}/helpers/template/index.md +1 -1
  83. package/wiki/{references → extensions}/helpers/testing/index.md +4 -4
  84. package/wiki/{references → extensions}/helpers/types/index.md +63 -16
  85. package/wiki/{references → extensions}/helpers/websocket/index.md +1 -1
  86. package/wiki/extensions/index.md +48 -0
  87. package/wiki/guides/core-concepts/application/bootstrapping.md +55 -37
  88. package/wiki/guides/core-concepts/application/index.md +95 -35
  89. package/wiki/guides/core-concepts/components-guide.md +23 -19
  90. package/wiki/guides/core-concepts/components.md +34 -10
  91. package/wiki/guides/core-concepts/dependency-injection.md +99 -34
  92. package/wiki/guides/core-concepts/grpc-controllers.md +295 -0
  93. package/wiki/guides/core-concepts/persistent/datasources.md +37 -19
  94. package/wiki/guides/core-concepts/persistent/index.md +6 -6
  95. package/wiki/guides/core-concepts/persistent/models.md +50 -6
  96. package/wiki/guides/core-concepts/persistent/repositories.md +83 -8
  97. package/wiki/guides/core-concepts/persistent/transactions.md +39 -8
  98. package/wiki/guides/core-concepts/{controllers.md → rest-controllers.md} +32 -35
  99. package/wiki/guides/core-concepts/services.md +19 -6
  100. package/wiki/guides/get-started/5-minute-quickstart.md +17 -17
  101. package/wiki/guides/get-started/philosophy.md +1 -1
  102. package/wiki/guides/index.md +2 -2
  103. package/wiki/guides/reference/glossary.md +7 -7
  104. package/wiki/guides/reference/mcp-docs-server.md +1 -1
  105. package/wiki/guides/tutorials/building-a-crud-api.md +45 -39
  106. package/wiki/guides/tutorials/complete-installation.md +74 -51
  107. package/wiki/guides/tutorials/ecommerce-api.md +39 -30
  108. package/wiki/guides/tutorials/realtime-chat.md +12 -13
  109. package/wiki/guides/tutorials/testing.md +2 -2
  110. package/wiki/index.md +4 -3
  111. package/wiki/references/base/application.md +341 -21
  112. package/wiki/references/base/bootstrapping.md +43 -13
  113. package/wiki/references/base/components.md +259 -8
  114. package/wiki/references/base/controllers.md +556 -253
  115. package/wiki/references/base/datasources.md +159 -79
  116. package/wiki/references/base/dependency-injection.md +299 -48
  117. package/wiki/references/base/filter-system/application-usage.md +18 -2
  118. package/wiki/references/base/filter-system/array-operators.md +14 -6
  119. package/wiki/references/base/filter-system/comparison-operators.md +9 -3
  120. package/wiki/references/base/filter-system/default-filter.md +28 -3
  121. package/wiki/references/base/filter-system/fields-order-pagination.md +17 -13
  122. package/wiki/references/base/filter-system/index.md +169 -11
  123. package/wiki/references/base/filter-system/json-filtering.md +51 -18
  124. package/wiki/references/base/filter-system/list-operators.md +4 -3
  125. package/wiki/references/base/filter-system/logical-operators.md +7 -2
  126. package/wiki/references/base/filter-system/null-operators.md +50 -0
  127. package/wiki/references/base/filter-system/quick-reference.md +82 -243
  128. package/wiki/references/base/filter-system/range-operators.md +7 -1
  129. package/wiki/references/base/filter-system/tips.md +34 -7
  130. package/wiki/references/base/filter-system/use-cases.md +6 -5
  131. package/wiki/references/base/grpc-controllers.md +984 -0
  132. package/wiki/references/base/index.md +32 -24
  133. package/wiki/references/base/middleware.md +347 -0
  134. package/wiki/references/base/models.md +390 -46
  135. package/wiki/references/base/providers.md +14 -14
  136. package/wiki/references/base/repositories/advanced.md +195 -69
  137. package/wiki/references/base/repositories/index.md +447 -12
  138. package/wiki/references/base/repositories/mixins.md +103 -98
  139. package/wiki/references/base/repositories/relations.md +129 -45
  140. package/wiki/references/base/repositories/soft-deletable.md +104 -23
  141. package/wiki/references/base/services.md +94 -14
  142. package/wiki/references/index.md +12 -10
  143. package/wiki/references/quick-reference.md +98 -65
  144. package/wiki/references/utilities/crypto.md +21 -4
  145. package/wiki/references/utilities/date.md +25 -7
  146. package/wiki/references/utilities/index.md +26 -24
  147. package/wiki/references/utilities/jsx.md +54 -54
  148. package/wiki/references/utilities/module.md +8 -6
  149. package/wiki/references/utilities/parse.md +16 -9
  150. package/wiki/references/utilities/performance.md +22 -7
  151. package/wiki/references/utilities/promise.md +19 -16
  152. package/wiki/references/utilities/request.md +48 -26
  153. package/wiki/references/utilities/schema.md +69 -6
  154. package/wiki/references/utilities/statuses.md +131 -140
  155. /package/wiki/{references → extensions}/components/mail/api.md +0 -0
  156. /package/wiki/{references → extensions}/components/mail/errors.md +0 -0
  157. /package/wiki/{references → extensions}/components/mail/usage.md +0 -0
  158. /package/wiki/{references → extensions}/components/template/api-page.md +0 -0
  159. /package/wiki/{references → extensions}/components/template/errors-page.md +0 -0
  160. /package/wiki/{references → extensions}/components/template/usage-page.md +0 -0
  161. /package/wiki/{references → extensions}/helpers/cron/index.md +0 -0
  162. /package/wiki/{references → extensions}/helpers/inversion/index.md +0 -0
  163. /package/wiki/{references → extensions}/helpers/network/api.md +0 -0
  164. /package/wiki/{references → extensions}/helpers/network/index.md +0 -0
  165. /package/wiki/{references → extensions}/helpers/redis/index.md +0 -0
  166. /package/wiki/{references → extensions}/helpers/socket-io/api.md +0 -0
  167. /package/wiki/{references → extensions}/helpers/socket-io/index.md +0 -0
  168. /package/wiki/{references → extensions}/helpers/template/single-page.md +0 -0
  169. /package/wiki/{references → extensions}/helpers/uid/index.md +0 -0
  170. /package/wiki/{references → extensions}/helpers/websocket/api.md +0 -0
  171. /package/wiki/{references → extensions}/helpers/worker-thread/index.md +0 -0
  172. /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
- BaseController,
13
+ BaseRestController,
14
14
  Authentication,
15
15
  AuthorizationActions,
16
16
  } from '@venizia/ignis';
17
17
 
18
- class ArticleController extends BaseController {
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 BaseController {
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 `defineControllerRouteConfigs` function resolves authorization with this priority:
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
- BaseController, IControllerOptions, TRouteContext,
217
- api, jsonContent, jsonResponse, z,
216
+ BaseRestController, IControllerOptions, TRouteContext,
218
217
  } from '@venizia/ignis';
219
- import { HTTP } from '@venizia/ignis-helpers';
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 BaseController {
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: MailBindingKeys.MAIL_OPTIONS }).toValue({
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](/references/helpers/logger/) - Logging utilities
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`](/references/helpers/socket-io/) |
12
- | **Client Helper** | [`SocketIOClientHelper`](/references/helpers/socket-io/) |
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
- ValueOrPromise,
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, IServerOptions } from '@venizia/ignis';
229
+ import { SocketIOBindingKeys } from '@venizia/ignis/socket-io';
230
+ import type { ServerOptions } from 'socket.io';
229
231
 
230
- const customOptions: Partial<IServerOptions> = {
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<IServerOptions>>({
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<IServerOptions>` | No | See defaults above |
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](/references/helpers/socket-io/) -- Full `SocketIOServerHelper` + `SocketIOClientHelper` API reference
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 { SocketIOServerHelper } from '@venizia/ignis-helpers';
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 `BaseController` is created with `@controller({ path: basePath })`
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. The controller is registered via `this.application.controller()`
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 BaseController { ... }
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; folderPath?: string }) => 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 `'minio'`) |
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 `principalId` fields are only populated during upload when the corresponding query parameters are provided.
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 `principalId` 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.
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: 'disk' | 'minio',
49
+ storage: StaticAssetStorageTypes.DISK | StaticAssetStorageTypes.MINIO | StaticAssetStorageTypes.BUN_S3,
48
50
  helper: IStorageHelper,
49
51
  extra: {}
50
52
  }