@venizia/ignis-docs 0.2.0 → 0.2.1-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 (174) hide show
  1. package/README.md +14 -14
  2. package/content/best-practices/api-usage-examples.md +39 -19
  3. package/content/best-practices/architectural-patterns.md +24 -13
  4. package/content/best-practices/architecture-decisions.md +29 -16
  5. package/content/best-practices/code-style-standards/advanced-patterns.md +43 -31
  6. package/content/best-practices/code-style-standards/constants-configuration.md +19 -4
  7. package/content/best-practices/code-style-standards/control-flow.md +33 -1
  8. package/content/best-practices/code-style-standards/documentation.md +28 -8
  9. package/content/best-practices/code-style-standards/function-patterns.md +15 -4
  10. package/content/best-practices/code-style-standards/index.md +7 -2
  11. package/content/best-practices/code-style-standards/naming-conventions.md +27 -3
  12. package/content/best-practices/code-style-standards/route-definitions.md +9 -5
  13. package/content/best-practices/code-style-standards/tooling.md +14 -1
  14. package/content/best-practices/code-style-standards/type-safety.md +39 -6
  15. package/content/best-practices/common-pitfalls.md +59 -35
  16. package/content/best-practices/contribution-workflow.md +8 -4
  17. package/content/best-practices/data-modeling.md +78 -62
  18. package/content/best-practices/deployment-strategies.md +56 -19
  19. package/content/best-practices/error-handling.md +247 -153
  20. package/content/best-practices/index.md +6 -0
  21. package/content/best-practices/performance-optimization.md +26 -13
  22. package/content/best-practices/security-guidelines.md +35 -9
  23. package/content/best-practices/testing-strategies.md +7 -2
  24. package/content/best-practices/troubleshooting-tips.md +27 -17
  25. package/content/extensions/components/api-reference.md +109 -323
  26. package/content/extensions/components/authentication/api.md +489 -602
  27. package/content/extensions/components/authentication/errors.md +135 -498
  28. package/content/extensions/components/authentication/index.md +89 -801
  29. package/content/extensions/components/authentication/usage.md +231 -955
  30. package/content/extensions/components/authorization/api.md +991 -644
  31. package/content/extensions/components/authorization/errors.md +204 -208
  32. package/content/extensions/components/authorization/getting-started.md +227 -0
  33. package/content/extensions/components/authorization/index.md +88 -795
  34. package/content/extensions/components/authorization/usage.md +219 -528
  35. package/content/extensions/components/health-check.md +77 -243
  36. package/content/extensions/components/index.md +24 -90
  37. package/content/extensions/components/mail/api.md +553 -285
  38. package/content/extensions/components/mail/errors.md +76 -62
  39. package/content/extensions/components/mail/index.md +111 -463
  40. package/content/extensions/components/mail/usage.md +139 -173
  41. package/content/extensions/components/request-tracker.md +70 -173
  42. package/content/extensions/components/socket-io/api.md +462 -785
  43. package/content/extensions/components/socket-io/errors.md +49 -51
  44. package/content/extensions/components/socket-io/index.md +69 -372
  45. package/content/extensions/components/socket-io/usage.md +212 -105
  46. package/content/extensions/components/static-asset/api.md +461 -141
  47. package/content/extensions/components/static-asset/errors.md +121 -53
  48. package/content/extensions/components/static-asset/index.md +84 -606
  49. package/content/extensions/components/static-asset/usage.md +184 -299
  50. package/content/extensions/components/template/index.md +3 -3
  51. package/content/extensions/components/websocket/api.md +311 -404
  52. package/content/extensions/components/websocket/errors.md +47 -56
  53. package/content/extensions/components/websocket/index.md +75 -407
  54. package/content/extensions/components/websocket/usage.md +120 -338
  55. package/content/extensions/helpers/cron/index.md +52 -160
  56. package/content/extensions/helpers/crypto/index.md +67 -480
  57. package/content/extensions/helpers/crypto/reference.md +528 -0
  58. package/content/extensions/helpers/env/index.md +64 -178
  59. package/content/extensions/helpers/error/index.md +286 -196
  60. package/content/extensions/helpers/index.md +61 -47
  61. package/content/extensions/helpers/inversion/index.md +76 -550
  62. package/content/extensions/helpers/inversion/reference.md +530 -0
  63. package/content/extensions/helpers/kafka/admin.md +23 -3
  64. package/content/extensions/helpers/kafka/compile-binary.md +83 -52
  65. package/content/extensions/helpers/kafka/consumer.md +65 -28
  66. package/content/extensions/helpers/kafka/examples.md +46 -253
  67. package/content/extensions/helpers/kafka/index.md +55 -617
  68. package/content/extensions/helpers/kafka/producer.md +156 -22
  69. package/content/extensions/helpers/kafka/schema-registry.md +59 -79
  70. package/content/extensions/helpers/logger/hf-logger.md +220 -0
  71. package/content/extensions/helpers/logger/index.md +78 -552
  72. package/content/extensions/helpers/logger/pino.md +105 -0
  73. package/content/extensions/helpers/logger/reference.md +937 -0
  74. package/content/extensions/helpers/network/api.md +276 -195
  75. package/content/extensions/helpers/network/index.md +87 -524
  76. package/content/extensions/helpers/queue/index.md +80 -897
  77. package/content/extensions/helpers/queue/reference.md +494 -0
  78. package/content/extensions/helpers/redis/index.md +86 -640
  79. package/content/extensions/helpers/redis/reference.md +784 -0
  80. package/content/extensions/helpers/secrets/index.md +136 -0
  81. package/content/extensions/helpers/socket-io/api.md +325 -204
  82. package/content/extensions/helpers/socket-io/index.md +79 -429
  83. package/content/extensions/helpers/storage/api.md +584 -464
  84. package/content/extensions/helpers/storage/index.md +80 -573
  85. package/content/extensions/helpers/types/index.md +75 -495
  86. package/content/extensions/helpers/types/reference.md +689 -0
  87. package/content/extensions/helpers/uid/index.md +176 -189
  88. package/content/extensions/helpers/websocket/api.md +366 -214
  89. package/content/extensions/helpers/websocket/index.md +68 -503
  90. package/content/extensions/helpers/worker-thread/index.md +62 -396
  91. package/content/extensions/helpers/worker-thread/reference.md +428 -0
  92. package/content/extensions/index.md +38 -39
  93. package/content/extensions/src-details/mcp-server.md +96 -548
  94. package/content/guides/core-concepts/persistent/datasources.md +2 -2
  95. package/content/guides/core-concepts/persistent/index.md +5 -1
  96. package/content/guides/core-concepts/persistent/models.md +1 -1
  97. package/content/guides/core-concepts/persistent/pglite.md +218 -0
  98. package/content/guides/core-concepts/persistent/postgres-drivers.md +21 -15
  99. package/content/guides/core-concepts/persistent/search-meilisearch.md +22 -12
  100. package/content/guides/core-concepts/persistent/search-typesense.md +28 -16
  101. package/content/guides/core-concepts/persistent/sqlite.md +296 -0
  102. package/content/guides/core-concepts/persistent/transactions.md +12 -11
  103. package/content/guides/core-concepts/secrets-vault.md +177 -0
  104. package/content/guides/core-concepts/services.md +1 -1
  105. package/content/guides/get-started/5-minute-quickstart.md +59 -206
  106. package/content/guides/get-started/philosophy.md +135 -670
  107. package/content/guides/get-started/setup.md +53 -74
  108. package/content/guides/migrations/redis-helpers-migration.md +5 -4
  109. package/content/guides/migrations/scoped-rbac-migration.md +5 -5
  110. package/content/guides/migrations/unified-connectors-migration.md +8 -7
  111. package/content/guides/tutorials/ecommerce-api.md +3 -8
  112. package/content/guides/tutorials/realtime-chat.md +1 -1
  113. package/content/references/base/application.md +64 -22
  114. package/content/references/base/components.md +3 -3
  115. package/content/references/base/connectors.md +79 -136
  116. package/content/references/base/controllers.md +12 -12
  117. package/content/references/base/datasources-reference.md +600 -0
  118. package/content/references/base/datasources.md +84 -444
  119. package/content/references/base/dependency-injection.md +25 -46
  120. package/content/references/base/filter-system/application-usage.md +95 -123
  121. package/content/references/base/filter-system/array-operators.md +33 -43
  122. package/content/references/base/filter-system/comparison-operators.md +55 -63
  123. package/content/references/base/filter-system/default-filter.md +144 -350
  124. package/content/references/base/filter-system/fields-order-pagination.md +116 -148
  125. package/content/references/base/filter-system/index.md +114 -253
  126. package/content/references/base/filter-system/json-filtering.md +52 -181
  127. package/content/references/base/filter-system/list-operators.md +28 -44
  128. package/content/references/base/filter-system/logical-operators.md +69 -114
  129. package/content/references/base/filter-system/null-operators.md +41 -98
  130. package/content/references/base/filter-system/pattern-matching.md +48 -51
  131. package/content/references/base/filter-system/quick-reference.md +93 -196
  132. package/content/references/base/filter-system/range-operators.md +22 -38
  133. package/content/references/base/filter-system/tips.md +70 -133
  134. package/content/references/base/filter-system/use-cases.md +173 -232
  135. package/content/references/base/grpc-controllers.md +53 -17
  136. package/content/references/base/index.md +5 -3
  137. package/content/references/base/middlewares.md +43 -28
  138. package/content/references/base/models-reference.md +886 -0
  139. package/content/references/base/models.md +81 -1452
  140. package/content/references/base/providers.md +8 -8
  141. package/content/references/base/repositories/advanced.md +281 -419
  142. package/content/references/base/repositories/index.md +84 -644
  143. package/content/references/base/repositories/mixins.md +25 -21
  144. package/content/references/base/repositories/relations.md +194 -375
  145. package/content/references/base/repositories/soft-deletable.md +67 -55
  146. package/content/references/base/secrets.md +267 -0
  147. package/content/references/base/services.md +8 -6
  148. package/content/references/configuration/environment-variables.md +73 -21
  149. package/content/references/configuration/index.md +51 -31
  150. package/content/references/index.md +1 -1
  151. package/content/references/quick-reference.md +3 -16
  152. package/content/references/utilities/crypto.md +35 -76
  153. package/content/references/utilities/date.md +33 -73
  154. package/content/references/utilities/duration.md +85 -0
  155. package/content/references/utilities/index.md +6 -2
  156. package/content/references/utilities/jsx-reference.md +298 -0
  157. package/content/references/utilities/jsx.md +82 -525
  158. package/content/references/utilities/module.md +81 -61
  159. package/content/references/utilities/parse.md +34 -64
  160. package/content/references/utilities/performance.md +33 -58
  161. package/content/references/utilities/promise.md +28 -62
  162. package/content/references/utilities/request.md +58 -218
  163. package/content/references/utilities/retry.md +139 -0
  164. package/content/references/utilities/schema.md +43 -137
  165. package/content/references/utilities/statuses-reference.md +361 -0
  166. package/content/references/utilities/statuses.md +63 -667
  167. package/dist/mcp-server/index.js +0 -0
  168. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
  169. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts.map +1 -1
  170. package/dist/mcp-server/tools/github/list-project-files.tool.js +3 -3
  171. package/dist/mcp-server/tools/github/search-code.tool.js +1 -1
  172. package/dist/mcp-server/tools/github/verify-dependencies.tool.js +1 -1
  173. package/dist/mcp-server/tools/github/view-source-file.tool.js +1 -1
  174. package/package.json +24 -23
@@ -1,419 +1,116 @@
1
- # Socket.IO -- Setup & Configuration
1
+ ---
2
+ title: Socket.IO Component
3
+ description: Wires SocketIOServerHelper into the app lifecycle for Node.js and Bun, with Redis-backed horizontal scaling and a mandatory authentication handshake
4
+ difficulty: intermediate
5
+ ---
2
6
 
3
- > Real-time, bidirectional, event-based communication using Socket.IO -- with automatic runtime detection for both Node.js and Bun.
7
+ # Socket.IO Component
4
8
 
5
- ## Quick Reference
9
+ `SocketIOComponent` registers a [`SocketIOServerHelper`](/extensions/helpers/socket-io/) on your application once the server starts. It runs on both Node.js and Bun, and scales across instances through a Redis adapter. Every client must authenticate before it can send or receive anything.
6
10
 
7
- | Item | Value |
8
- |------|-------|
9
- | **Package** | `@venizia/ignis` (core) |
10
- | **Class** | `SocketIOComponent` |
11
- | **Server Helper** | [`SocketIOServerHelper`](/extensions/helpers/socket-io/) |
12
- | **Client Helper** | [`SocketIOClientHelper`](/extensions/helpers/socket-io/) |
13
- | **Runtimes** | Node.js (`@hono/node-server`) and Bun (native) |
14
- | **Scaling** | `@socket.io/redis-adapter` + `@socket.io/redis-emitter` |
15
-
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
-
21
- ```typescript
22
- // From core -- subpath import (NOT from '@venizia/ignis')
23
- import {
24
- SocketIOComponent,
25
- SocketIOBindingKeys,
26
- } from '@venizia/ignis/socket-io';
27
-
28
- // From helpers -- subpath import
29
- import {
30
- SocketIOServerHelper,
31
- SocketIOClientHelper,
32
- SocketIOConstants,
33
- SocketIOClientStates,
34
- } from '@venizia/ignis-helpers/socket-io';
35
-
36
- // Types from helpers subpath
37
- import type {
38
- TSocketIOAuthenticateFn,
39
- TSocketIOValidateRoomFn,
40
- TSocketIOClientConnectedFn,
41
- ISocketIOClientOptions,
42
- IOptions,
43
- TSocketIOEventHandler,
44
- TSocketIOClientState,
45
- } from '@venizia/ignis-helpers/socket-io';
46
- ```
47
-
48
- ### Use Cases
49
-
50
- - Live notifications and alerts
51
- - Real-time chat and messaging
52
- - Collaborative editing (docs, whiteboards)
53
- - Live data streams (dashboards, monitoring)
54
- - Multiplayer game state synchronization
55
- - Service-to-service real-time communication (via `SocketIOClientHelper`)
56
-
57
- ## Server Helper Setup
58
-
59
- ### Step 1: Install Dependencies
60
-
61
- ```bash
62
- # Core dependency (already included via @venizia/ignis)
63
- # ioredis is required for the Redis adapter
64
-
65
- # For Bun runtime only -- optional peer dependency
66
- bun add @socket.io/bun-engine
67
- ```
68
-
69
- ### Step 2: Bind Required Services
11
+ > [!TIP]
12
+ > Bun-only and don't need Socket.IO's handshake protocol? The [WebSocket Component](../websocket/) is a lighter alternative.
70
13
 
71
- In your application's `preConfigure()` method, bind the required services and register the component:
14
+ ## In one example
72
15
 
73
16
  ```typescript
74
17
  import { BaseApplication } from '@venizia/ignis';
75
- import {
76
- SocketIOComponent,
77
- SocketIOBindingKeys,
78
- } from '@venizia/ignis/socket-io';
18
+ import { SocketIOComponent, SocketIOBindingKeys } from '@venizia/ignis/socket-io';
79
19
  import { RedisSingleHelper, ValueOrPromise } from '@venizia/ignis-helpers';
80
- import type {
81
- TSocketIOAuthenticateFn,
82
- TSocketIOValidateRoomFn,
83
- TSocketIOClientConnectedFn,
84
- } from '@venizia/ignis-helpers/socket-io';
20
+ import type { TSocketIOAuthenticateFn } from '@venizia/ignis-helpers/socket-io';
85
21
 
86
22
  export class Application extends BaseApplication {
87
- private redisHelper: RedisSingleHelper;
88
-
89
23
  preConfigure(): ValueOrPromise<void> {
90
- this.setupSocketIO();
91
- // ... other setup
92
- }
93
-
94
- setupSocketIO() {
95
- // 1. Redis connection (required for adapter + emitter)
96
- this.redisHelper = new RedisSingleHelper({
97
- name: 'socket-io-redis',
98
- host: process.env.REDIS_HOST ?? 'localhost',
99
- port: +(process.env.REDIS_PORT ?? 6379),
100
- password: process.env.REDIS_PASSWORD,
101
- autoConnect: false,
102
- });
103
-
104
- this.bind<RedisSingleHelper>({
105
- key: SocketIOBindingKeys.REDIS_CONNECTION,
106
- }).toValue(this.redisHelper);
24
+ // 1. Redis connection (required - used for the adapter + emitter)
25
+ this.bind({ key: SocketIOBindingKeys.REDIS_CONNECTION }).toValue(
26
+ new RedisSingleHelper({ name: 'socket-io-redis', host: 'localhost', port: 6379, autoConnect: false }),
27
+ );
107
28
 
108
- // 2. Authentication handler (required)
109
- const authenticateFn: TSocketIOAuthenticateFn = handshake => {
110
- const token = handshake.headers.authorization;
111
- // Implement your auth logic -- JWT verification, session check, etc.
112
- return !!token;
113
- };
29
+ // 2. Authenticate handler (required - decides accept/reject per client)
30
+ const authenticateFn: TSocketIOAuthenticateFn = handshake => !!handshake.headers.authorization;
31
+ this.bind({ key: SocketIOBindingKeys.AUTHENTICATE_HANDLER }).toValue(authenticateFn);
114
32
 
115
- this.bind<TSocketIOAuthenticateFn>({
116
- key: SocketIOBindingKeys.AUTHENTICATE_HANDLER,
117
- }).toValue(authenticateFn);
118
-
119
- // 3. Room validation handler (optional -- joins rejected without this)
120
- const validateRoomFn: TSocketIOValidateRoomFn = ({ socket, rooms }) => {
121
- // Return the rooms that the client is allowed to join
122
- const allowedRooms = rooms.filter(room => room.startsWith('public-'));
123
- return allowedRooms;
124
- };
125
-
126
- this.bind<TSocketIOValidateRoomFn>({
127
- key: SocketIOBindingKeys.VALIDATE_ROOM_HANDLER,
128
- }).toValue(validateRoomFn);
129
-
130
- // 4. Client connected handler (optional)
131
- const clientConnectedFn: TSocketIOClientConnectedFn = ({ socket }) => {
132
- console.log('Client connected:', socket.id);
133
- // Register custom event handlers on the socket
134
- };
135
-
136
- this.bind<TSocketIOClientConnectedFn>({
137
- key: SocketIOBindingKeys.CLIENT_CONNECTED_HANDLER,
138
- }).toValue(clientConnectedFn);
139
-
140
- // 5. Register the component -- that's it!
33
+ // 3. Register - binding() validates the two bindings above and defers the rest
141
34
  this.component(SocketIOComponent);
142
35
  }
143
36
  }
144
37
  ```
145
38
 
146
- #### `autoConnect: false` Rationale
39
+ `SocketIOComponent` and `SocketIOBindingKeys` come from the `@venizia/ignis/socket-io` subpath. They are **not** exported from the `@venizia/ignis` root barrel. Helper types (`TSocketIOAuthenticateFn`, `SocketIOServerHelper`, `SocketIOClientHelper`, `SocketIOConstants`, ...) come from `@venizia/ignis-helpers/socket-io`.
147
40
 
148
- The `RedisSingleHelper` is created with `autoConnect: false` because the server helper internally calls `client.duplicate()` to create 3 independent Redis connections (pub, sub, emitter). The duplicated clients inherit the `lazyConnect` setting from the parent. During `configure()`, the helper detects clients in `wait` status and explicitly calls `client.connect()` on each, then awaits all 3 to reach `ready` status before proceeding. This avoids race conditions where the parent connects before the duplicates are created.
149
-
150
- #### Redis Connection Alternatives
151
-
152
- You can use `RedisSingleHelper` (single Redis instance), `RedisClusterHelper` (Redis Cluster mode), or `RedisSentinelHelper` (Sentinel HA). All extend `AbstractRedisHelper` and satisfy the `IRedisHelper` interface that the component validates against:
153
-
154
- ```typescript
155
- import { RedisClusterHelper } from '@venizia/ignis-helpers';
156
-
157
- // For Redis Cluster deployments
158
- const redisHelper = new RedisClusterHelper({
159
- name: 'socket-io-redis-cluster',
160
- nodes: [
161
- { host: 'redis-node-1', port: 6379 },
162
- { host: 'redis-node-2', port: 6380 },
163
- { host: 'redis-node-3', port: 6381 },
164
- ],
165
- password: process.env.REDIS_PASSWORD,
166
- autoConnect: false,
167
- });
168
-
169
- this.bind<RedisClusterHelper>({
170
- key: SocketIOBindingKeys.REDIS_CONNECTION,
171
- }).toValue(redisHelper);
172
- ```
173
-
174
- The internal `TRedisClient` type is `Redis | Cluster`, so both ioredis connection types are supported transparently.
175
-
176
- ## Configuration
177
-
178
- ### Default Server Options
41
+ > [!WARNING]
42
+ > `autoConnect: false` is required on the Redis helper. The server helper duplicates the connection into 3 independent clients and connects them itself during `configure()`. Connect the parent first and it races against the duplicates. Full explanation in [Usage & Examples](./usage#full-setup).
179
43
 
180
- The component applies these defaults if `SocketIOBindingKeys.SERVER_OPTIONS` is not bound or partially overridden:
44
+ ## How it works
181
45
 
182
- | Option | Default | Description |
183
- |--------|---------|-------------|
184
- | `identifier` | `'SOCKET_IO_SERVER'` | Unique identifier for the helper instance |
185
- | `path` | `'/io'` | URL path for Socket.IO handshake/polling |
186
- | `cors.origin` | `'*'` | Allowed origins (restrict in production!) |
187
- | `cors.methods` | `['GET', 'POST']` | Allowed HTTP methods for CORS preflight |
188
- | `cors.preflightContinue` | `false` | Pass preflight to next handler |
189
- | `cors.optionsSuccessStatus` | `204` | Status code for successful OPTIONS requests |
190
- | `cors.credentials` | `true` | Allow cookies/auth headers |
191
- | `perMessageDeflate.threshold` | `4096` | Minimum message size to compress (bytes) |
192
- | `perMessageDeflate.concurrencyLimit` | `20` | Max concurrent compression operations |
193
- | `perMessageDeflate.clientNoContextTakeover` | `true` | Client releases compression context after each message |
194
- | `perMessageDeflate.serverNoContextTakeover` | `true` | Server releases compression context after each message |
195
- | `perMessageDeflate.serverMaxWindowBits` | `10` | Server-side maximum window size (2^10 = 1KB) |
46
+ Socket.IO needs a running server, but components initialize before the server exists. Five mechanisms bridge that gap and keep every client on a security-by-default path:
196
47
 
197
- > [!WARNING]
198
- > The default `cors.origin: '*'` is suitable for development only. In production, restrict this to your specific domains.
48
+ | Mechanism | What happens |
49
+ |---|---|
50
+ | Post-start hook | `binding()` runs during `initialize()`, resolves bindings, and registers a hook. The hook builds `SocketIOServerHelper` and binds it to `SOCKET_IO_INSTANCE` only after `start()` runs. |
51
+ | Runtime detection | `RuntimeModules.detect()` picks Node.js (Socket.IO attaches to `node:http.Server` directly) or Bun (`@socket.io/bun-engine` is dynamically imported and wired into `server.reload()`). See the [runtime comparison](./api#runtime-specific-behavior). |
52
+ | Redis fan-out | The connection you bind is never consumed directly. The helper calls `duplicateClient()` three times: a pub/sub pair for the Redis adapter, and a third client for the Redis emitter. |
53
+ | Mandatory authentication | Every client starts `unauthorized`. It must emit `authenticate` within `authenticateTimeout` (default 10s) or it gets disconnected. Success joins the client to the default rooms and starts a keep-alive ping. |
54
+ | Opt-in rooms | No `VALIDATE_ROOM_HANDLER` bound means every `join` request is rejected. That's security-by-default, not a bug. |
199
55
 
200
- #### Full `DEFAULT_SERVER_OPTIONS`
201
- ```typescript
202
- const DEFAULT_SERVER_OPTIONS: Partial<IServerOptions> = {
203
- identifier: 'SOCKET_IO_SERVER',
204
- path: '/io',
205
- cors: {
206
- origin: '*',
207
- methods: ['GET', 'POST'],
208
- preflightContinue: false,
209
- optionsSuccessStatus: 204,
210
- credentials: true,
211
- },
212
- perMessageDeflate: {
213
- threshold: 4096,
214
- zlibDeflateOptions: { chunkSize: 10 * 1024 },
215
- zlibInflateOptions: { windowBits: 12, memLevel: 8 },
216
- clientNoContextTakeover: true,
217
- serverNoContextTakeover: true,
218
- serverMaxWindowBits: 10,
219
- concurrencyLimit: 20,
220
- },
221
- };
222
- ```
56
+ ## Common tasks
223
57
 
224
- ### Custom Configuration
58
+ ### Restrict CORS for production
225
59
 
226
- Bind custom server options before registering the component:
60
+ Bind `SERVER_OPTIONS` before registering the component. The default (`cors.origin: '*'`) is for local development only.
227
61
 
228
62
  ```typescript
229
- import { SocketIOBindingKeys } from '@venizia/ignis/socket-io';
230
63
  import type { ServerOptions } from 'socket.io';
231
64
 
232
- const customOptions: Partial<ServerOptions> = {
233
- path: '/socket.io',
234
- cors: {
235
- origin: ['https://myapp.com', 'https://admin.myapp.com'],
236
- methods: ['GET', 'POST'],
237
- credentials: true,
238
- },
239
- pingTimeout: 60000,
240
- pingInterval: 25000,
241
- maxHttpBufferSize: 1e6, // 1MB
242
- };
243
-
244
- this.bind<Partial<ServerOptions>>({
245
- key: SocketIOBindingKeys.SERVER_OPTIONS,
246
- }).toValue(customOptions);
247
-
65
+ this.bind<Partial<ServerOptions>>({ key: SocketIOBindingKeys.SERVER_OPTIONS }).toValue({
66
+ cors: { origin: ['https://myapp.com'], credentials: true },
67
+ });
248
68
  this.component(SocketIOComponent);
249
69
  ```
250
70
 
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
-
254
- ## Binding Keys
255
-
256
- All binding keys are available in `SocketIOBindingKeys`:
257
-
258
- | Binding Key | Constant | Type | Required | Default |
259
- |------------|----------|------|----------|---------|
260
- | `@app/socket-io/server-options` | `SERVER_OPTIONS` | `Partial<ServerOptions>` | No | See defaults above |
261
- | `@app/socket-io/redis-connection` | `REDIS_CONNECTION` | `IRedisHelper` (`RedisSingleHelper` / `RedisClusterHelper` / `RedisSentinelHelper`) | **Yes** | `null` |
262
- | `@app/socket-io/authenticate-handler` | `AUTHENTICATE_HANDLER` | `TSocketIOAuthenticateFn` | **Yes** | `null` |
263
- | `@app/socket-io/validate-room-handler` | `VALIDATE_ROOM_HANDLER` | `TSocketIOValidateRoomFn` | No | `null` |
264
- | `@app/socket-io/client-connected-handler` | `CLIENT_CONNECTED_HANDLER` | `TSocketIOClientConnectedFn` | No | `null` |
265
- | `@app/socket-io/instance` | `SOCKET_IO_INSTANCE` | `SocketIOServerHelper` | -- | *Set by component* |
266
-
267
- > [!NOTE]
268
- > `SOCKET_IO_INSTANCE` is **not** set by you -- the component creates and binds it automatically after the server starts. Inject it in services/controllers to interact with Socket.IO.
269
-
270
- ## Constants
271
-
272
- Constants are exported from `@venizia/ignis-helpers/socket-io` and used internally by both the component and the helper.
273
-
274
- ### System Events
275
-
276
- | Constant | Value | Description |
277
- |----------|-------|-------------|
278
- | `SocketIOConstants.EVENT_PING` | `'ping'` | Keep-alive ping emitted at `pingInterval` (default: 30s) |
279
- | `SocketIOConstants.EVENT_CONNECT` | `'connection'` | New client connected (server-side event) |
280
- | `SocketIOConstants.EVENT_DISCONNECT` | `'disconnect'` | Client disconnected |
281
- | `SocketIOConstants.EVENT_JOIN` | `'join'` | Client requests to join room(s) |
282
- | `SocketIOConstants.EVENT_LEAVE` | `'leave'` | Client requests to leave room(s) |
283
- | `SocketIOConstants.EVENT_AUTHENTICATE` | `'authenticate'` | Client sends auth credentials |
284
- | `SocketIOConstants.EVENT_AUTHENTICATED` | `'authenticated'` | Auth success response sent to client |
285
- | `SocketIOConstants.EVENT_UNAUTHENTICATE` | `'unauthenticated'` | Auth failure response sent to client |
286
-
287
- ### Default Rooms
288
-
289
- All authenticated clients are automatically joined to these rooms:
290
-
291
- | Constant | Value | Description |
292
- |----------|-------|-------------|
293
- | `SocketIOConstants.ROOM_DEFAULT` | `'io-default'` | Default room all authenticated clients join |
294
- | `SocketIOConstants.ROOM_NOTIFICATION` | `'io-notification'` | Notification broadcast room |
295
-
296
- > [!TIP]
297
- > You can override default rooms via the `defaultRooms` option on `SocketIOServerHelper`. The component uses the defaults above when not overridden.
298
-
299
- ### Internal Constants (Server Helper)
300
-
301
- These constants are defined at module scope in the server helper and are not exported, but they govern default behavior:
71
+ ### Send a message from a service
302
72
 
303
- | Constant | Value | Description |
304
- |----------|-------|-------------|
305
- | `CLIENT_AUTHENTICATE_TIMEOUT` | `10_000` (10s) | Time allowed for a client to authenticate before forced disconnect |
306
- | `CLIENT_PING_INTERVAL` | `30_000` (30s) | Interval between server-to-client ping emissions |
73
+ `SOCKET_IO_INSTANCE` is bound by the component after the server starts, so resolve it lazily - never `@inject` it in a constructor. Full pattern in [Inject the helper in a service or controller](./usage#inject-the-helper-in-a-service-or-controller).
307
74
 
308
- Both can be overridden via the `authenticateTimeout` and `pingInterval` constructor options on `SocketIOServerHelper`.
309
-
310
- ### Client States
311
-
312
- Each connected client tracks an authentication state that governs what actions are permitted:
313
-
314
- | State | Constant | Description |
315
- |-------|----------|-------------|
316
- | `unauthorized` | `SocketIOClientStates.UNAUTHORIZED` | Initial state -- client must emit `authenticate` within the timeout (default: 10s) |
317
- | `authenticating` | `SocketIOClientStates.AUTHENTICATING` | Auth in progress -- `authenticateFn` is executing |
318
- | `authenticated` | `SocketIOClientStates.AUTHENTICATED` | Auth successful -- client can send/receive events and join rooms |
319
-
320
- #### State Machine Diagram
321
- ```
322
- +------------------+
323
- connect ---------->| unauthorized |
324
- +--------+---------+
325
- | emit('authenticate')
326
- +--------v---------+
327
- | authenticating |
328
- +---+----------+---+
329
- success | | failure
330
- +---------v--+ +-------v-----------+
331
- |authenticated| | unauthorized |--> disconnect
332
- +-------------+ +------------------+
333
- ^
334
- timeout (10s)
335
- ```
336
-
337
- #### `SocketIOClientStates` Source
338
75
  ```typescript
339
- export class SocketIOClientStates {
340
- static readonly UNAUTHORIZED = 'unauthorized';
341
- static readonly AUTHENTICATING = 'authenticating';
342
- static readonly AUTHENTICATED = 'authenticated';
343
-
344
- static readonly SCHEME_SET = new Set([
345
- this.UNAUTHORIZED,
346
- this.AUTHENTICATING,
347
- this.AUTHENTICATED,
348
- ]);
349
-
350
- static isValid(input: string): input is TConstValue<typeof SocketIOClientStates> {
351
- return this.SCHEME_SET.has(input);
352
- }
353
- }
76
+ this.io.send({ destination: userId, payload: { topic: 'notification', data } });
354
77
  ```
355
78
 
356
- ### Resolved Bindings
79
+ ### Scale Redis beyond a single node
357
80
 
358
- The component resolves all binding keys into a single `IResolvedBindings` object during the `binding()` phase:
81
+ Swap `RedisSingleHelper` for `RedisClusterHelper` or `RedisSentinelHelper`. Both satisfy the `IRedisHelper` interface the component validates against. See [Redis connection alternatives](./usage#redis-connection-alternatives) for the full example.
359
82
 
360
- #### `IResolvedBindings` Interface
361
83
  ```typescript
362
- interface IResolvedBindings {
363
- redisConnection: IRedisHelper;
364
- authenticateFn: TSocketIOAuthenticateFn;
365
- validateRoomFn?: TSocketIOValidateRoomFn;
366
- clientConnectedFn?: TSocketIOClientConnectedFn;
367
- }
84
+ import { RedisClusterHelper } from '@venizia/ignis-helpers';
85
+
86
+ this.bind({ key: SocketIOBindingKeys.REDIS_CONNECTION }).toValue(
87
+ new RedisClusterHelper({
88
+ name: 'socket-io-redis-cluster',
89
+ nodes: [{ host: 'redis-node-1', port: 6379 }],
90
+ autoConnect: false,
91
+ }),
92
+ );
368
93
  ```
369
94
 
370
- #### Callback Type Signatures
371
- ```typescript
372
- // Called with the socket handshake -- return true to authenticate, false to reject
373
- type TSocketIOAuthenticateFn = (args: IHandshake) => ValueOrPromise<boolean>;
95
+ ### Look up a default, binding key, or event name
374
96
 
375
- // Called when client emits 'join' -- return the subset of rooms the client is allowed to join
376
- type TSocketIOValidateRoomFn = (opts: {
377
- socket: IOSocket;
378
- rooms: string[];
379
- }) => ValueOrPromise<string[]>;
97
+ Every `DEFAULT_SERVER_OPTIONS` field, the binding key table, system events, default rooms, and the client state machine live in the [Full Reference](./api#configuration-reference).
380
98
 
381
- // Called after successful authentication -- register custom event handlers here
382
- type TSocketIOClientConnectedFn = (opts: { socket: IOSocket }) => ValueOrPromise<void>;
383
- ```
99
+ ## See also
384
100
 
385
- #### `IHandshake` Interface
386
- ```typescript
387
- interface IHandshake {
388
- headers: IncomingHttpHeaders;
389
- time: string;
390
- address: string;
391
- xdomain: boolean;
392
- secure: boolean;
393
- issued: number;
394
- url: string;
395
- query: ParsedUrlQuery;
396
- auth: { [key: string]: any };
397
- }
398
- ```
101
+ - [Usage & Examples](./usage) - full setup steps, server-side usage, client helper, advanced patterns
102
+ - [Full Reference](./api) - architecture, configuration reference, method signatures, internals, types
103
+ - [Error Reference](./errors) - error conditions and troubleshooting
104
+ - [Socket.IO Helper](/extensions/helpers/socket-io/) - full `SocketIOServerHelper` + `SocketIOClientHelper` API reference
105
+ - [WebSocket Component](../websocket/) - Bun-only alternative
106
+ - [Real-Time Chat tutorial](/guides/tutorials/realtime-chat) - building a chat app with Socket.IO
107
+ - [Socket.IO Documentation](https://socket.io/docs/) - official docs
108
+ - [Socket.IO Redis Adapter](https://socket.io/docs/v4/redis-adapter/) - horizontal scaling guide
109
+ - [@socket.io/bun-engine](https://github.com/socketio/bun-engine) - Bun runtime support
110
+ - [2026-02-06: Socket.IO Integration Fix](/changelogs/2026-02-06-socket-io-integration-fix) - lifecycle timing fix + Bun runtime support
399
111
 
400
- ## See Also
112
+ **Files:**
401
113
 
402
- - [Usage & Examples](./usage) -- Server-side usage, client helper, advanced patterns
403
- - [API Reference](./api) -- Architecture, method signatures, internals, types
404
- - [Error Reference](./errors) -- Error conditions and troubleshooting
405
- - **Guides:**
406
- - [Components Overview](/guides/core-concepts/components) -- Component system basics
407
- - [Application](/guides/core-concepts/application/) -- Registering components
408
- - **Components:**
409
- - [Components Index](../index) -- All built-in components
410
- - **Helpers:**
411
- - [Socket.IO Helper](/extensions/helpers/socket-io/) -- Full `SocketIOServerHelper` + `SocketIOClientHelper` API reference
412
- - **External Resources:**
413
- - [Socket.IO Documentation](https://socket.io/docs/) -- Official docs
414
- - [Socket.IO Redis Adapter](https://socket.io/docs/v4/redis-adapter/) -- Horizontal scaling guide
415
- - [@socket.io/bun-engine](https://github.com/socketio/bun-engine) -- Bun runtime support
416
- - **Tutorials:**
417
- - [Real-Time Chat](/guides/tutorials/realtime-chat) -- Building a chat app with Socket.IO
418
- - **Changelog:**
419
- - [2026-02-06: Socket.IO Integration Fix](/changelogs/2026-02-06-socket-io-integration-fix) -- Lifecycle timing fix + Bun runtime support
114
+ - [`packages/core-server/src/components/socket-io/component.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/components/socket-io/component.ts) - `SocketIOComponent`
115
+ - [`packages/core-server/src/components/socket-io/common/keys.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/components/socket-io/common/keys.ts) - `SocketIOBindingKeys`
116
+ - [`packages/core-server/src/components/socket-io/common/types.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/components/socket-io/common/types.ts) - `IServerOptions`, `DEFAULT_SERVER_OPTIONS`