@venizia/ignis-docs 0.2.0 → 0.2.1-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) 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 +22 -11
  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 +26 -2
  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 +6 -2
  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 +182 -93
  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 +107 -322
  26. package/content/extensions/components/authentication/api.md +454 -603
  27. package/content/extensions/components/authentication/errors.md +121 -498
  28. package/content/extensions/components/authentication/index.md +88 -801
  29. package/content/extensions/components/authentication/usage.md +207 -956
  30. package/content/extensions/components/authorization/api.md +736 -656
  31. package/content/extensions/components/authorization/errors.md +168 -206
  32. package/content/extensions/components/authorization/index.md +82 -797
  33. package/content/extensions/components/authorization/usage.md +194 -527
  34. package/content/extensions/components/health-check.md +71 -243
  35. package/content/extensions/components/mail/api.md +504 -287
  36. package/content/extensions/components/mail/errors.md +73 -61
  37. package/content/extensions/components/mail/index.md +96 -467
  38. package/content/extensions/components/mail/usage.md +130 -172
  39. package/content/extensions/components/request-tracker.md +66 -173
  40. package/content/extensions/components/socket-io/api.md +195 -13
  41. package/content/extensions/components/socket-io/errors.md +3 -3
  42. package/content/extensions/components/socket-io/index.md +50 -337
  43. package/content/extensions/components/socket-io/usage.md +143 -26
  44. package/content/extensions/components/static-asset/api.md +410 -142
  45. package/content/extensions/components/static-asset/errors.md +110 -53
  46. package/content/extensions/components/static-asset/index.md +79 -608
  47. package/content/extensions/components/static-asset/usage.md +180 -300
  48. package/content/extensions/components/websocket/api.md +275 -399
  49. package/content/extensions/components/websocket/errors.md +47 -56
  50. package/content/extensions/components/websocket/index.md +74 -407
  51. package/content/extensions/components/websocket/usage.md +110 -341
  52. package/content/extensions/helpers/cron/index.md +51 -160
  53. package/content/extensions/helpers/crypto/index.md +62 -483
  54. package/content/extensions/helpers/crypto/reference.md +456 -0
  55. package/content/extensions/helpers/env/index.md +60 -178
  56. package/content/extensions/helpers/error/index.md +221 -207
  57. package/content/extensions/helpers/inversion/index.md +65 -556
  58. package/content/extensions/helpers/inversion/reference.md +522 -0
  59. package/content/extensions/helpers/kafka/admin.md +20 -1
  60. package/content/extensions/helpers/kafka/compile-binary.md +41 -35
  61. package/content/extensions/helpers/kafka/consumer.md +54 -20
  62. package/content/extensions/helpers/kafka/examples.md +21 -16
  63. package/content/extensions/helpers/kafka/index.md +80 -610
  64. package/content/extensions/helpers/kafka/producer.md +134 -5
  65. package/content/extensions/helpers/kafka/schema-registry.md +45 -70
  66. package/content/extensions/helpers/logger/hf-logger.md +193 -0
  67. package/content/extensions/helpers/logger/index.md +64 -563
  68. package/content/extensions/helpers/logger/pino.md +85 -0
  69. package/content/extensions/helpers/logger/reference.md +746 -0
  70. package/content/extensions/helpers/network/api.md +241 -195
  71. package/content/extensions/helpers/network/index.md +72 -530
  72. package/content/extensions/helpers/queue/index.md +72 -900
  73. package/content/extensions/helpers/queue/reference.md +467 -0
  74. package/content/extensions/helpers/redis/index.md +73 -645
  75. package/content/extensions/helpers/redis/reference.md +727 -0
  76. package/content/extensions/helpers/secrets/index.md +66 -0
  77. package/content/extensions/helpers/socket-io/api.md +305 -203
  78. package/content/extensions/helpers/socket-io/index.md +66 -432
  79. package/content/extensions/helpers/storage/api.md +564 -462
  80. package/content/extensions/helpers/storage/index.md +77 -573
  81. package/content/extensions/helpers/types/index.md +66 -499
  82. package/content/extensions/helpers/types/reference.md +650 -0
  83. package/content/extensions/helpers/uid/index.md +58 -227
  84. package/content/extensions/helpers/websocket/api.md +329 -216
  85. package/content/extensions/helpers/websocket/index.md +65 -503
  86. package/content/extensions/helpers/worker-thread/index.md +58 -396
  87. package/content/extensions/helpers/worker-thread/reference.md +428 -0
  88. package/content/guides/core-concepts/persistent/models.md +1 -1
  89. package/content/guides/core-concepts/persistent/search-typesense.md +3 -3
  90. package/content/guides/core-concepts/persistent/transactions.md +1 -1
  91. package/content/guides/core-concepts/secrets-vault.md +177 -0
  92. package/content/guides/core-concepts/services.md +1 -1
  93. package/content/guides/migrations/redis-helpers-migration.md +1 -1
  94. package/content/guides/migrations/unified-connectors-migration.md +2 -2
  95. package/content/guides/tutorials/ecommerce-api.md +3 -8
  96. package/content/references/base/application.md +1 -1
  97. package/content/references/base/connectors.md +79 -136
  98. package/content/references/base/datasources-reference.md +599 -0
  99. package/content/references/base/datasources.md +84 -444
  100. package/content/references/base/dependency-injection.md +17 -39
  101. package/content/references/base/filter-system/application-usage.md +69 -121
  102. package/content/references/base/filter-system/array-operators.md +12 -0
  103. package/content/references/base/filter-system/comparison-operators.md +12 -0
  104. package/content/references/base/filter-system/default-filter.md +136 -348
  105. package/content/references/base/filter-system/fields-order-pagination.md +38 -16
  106. package/content/references/base/filter-system/index.md +106 -257
  107. package/content/references/base/filter-system/json-filtering.md +12 -2
  108. package/content/references/base/filter-system/list-operators.md +16 -2
  109. package/content/references/base/filter-system/logical-operators.md +13 -0
  110. package/content/references/base/filter-system/null-operators.md +13 -0
  111. package/content/references/base/filter-system/pattern-matching.md +12 -0
  112. package/content/references/base/filter-system/quick-reference.md +11 -2
  113. package/content/references/base/filter-system/range-operators.md +12 -0
  114. package/content/references/base/filter-system/tips.md +70 -133
  115. package/content/references/base/filter-system/use-cases.md +156 -233
  116. package/content/references/base/middlewares.md +35 -21
  117. package/content/references/base/models-reference.md +886 -0
  118. package/content/references/base/models.md +80 -1452
  119. package/content/references/base/repositories/advanced.md +156 -192
  120. package/content/references/base/repositories/index.md +77 -650
  121. package/content/references/base/repositories/mixins.md +22 -18
  122. package/content/references/base/repositories/relations.md +123 -171
  123. package/content/references/base/repositories/soft-deletable.md +58 -56
  124. package/content/references/base/secrets.md +263 -0
  125. package/content/references/base/services.md +2 -2
  126. package/content/references/configuration/environment-variables.md +48 -4
  127. package/content/references/configuration/index.md +49 -31
  128. package/content/references/quick-reference.md +3 -16
  129. package/content/references/utilities/crypto.md +35 -76
  130. package/content/references/utilities/date.md +33 -73
  131. package/content/references/utilities/index.md +1 -1
  132. package/content/references/utilities/jsx-reference.md +298 -0
  133. package/content/references/utilities/jsx.md +82 -525
  134. package/content/references/utilities/module.md +29 -62
  135. package/content/references/utilities/parse.md +34 -64
  136. package/content/references/utilities/performance.md +33 -58
  137. package/content/references/utilities/promise.md +28 -62
  138. package/content/references/utilities/request.md +57 -218
  139. package/content/references/utilities/schema.md +43 -137
  140. package/content/references/utilities/statuses-reference.md +361 -0
  141. package/content/references/utilities/statuses.md +63 -667
  142. package/package.json +8 -8
@@ -1,6 +1,6 @@
1
1
  # Socket.IO -- Setup & Configuration
2
2
 
3
- > Real-time, bidirectional, event-based communication using Socket.IO -- with automatic runtime detection for both Node.js and Bun.
3
+ > Real-time, bidirectional, event-based communication using Socket.IO -- with automatic runtime detection for Node.js and Bun, horizontal scaling via Redis, and a built-in authentication handshake.
4
4
 
5
5
  ## Quick Reference
6
6
 
@@ -13,394 +13,101 @@
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
- #### Import Paths
17
-
18
16
  > [!IMPORTANT]
19
- > `SocketIOComponent` and `SocketIOBindingKeys` are **not** exported from the `@venizia/ignis` barrel. You must import from the `@venizia/ignis/socket-io` subpath.
17
+ > `SocketIOComponent` and `SocketIOBindingKeys` are **not** exported from the `@venizia/ignis` barrel -- import from the `@venizia/ignis/socket-io` subpath.
20
18
 
21
19
  ```typescript
22
20
  // From core -- subpath import (NOT from '@venizia/ignis')
23
- import {
24
- SocketIOComponent,
25
- SocketIOBindingKeys,
26
- } from '@venizia/ignis/socket-io';
21
+ import { SocketIOComponent, SocketIOBindingKeys } from '@venizia/ignis/socket-io';
27
22
 
28
23
  // 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';
24
+ import { SocketIOServerHelper, SocketIOClientHelper, SocketIOConstants } from '@venizia/ignis-helpers/socket-io';
25
+ import type { TSocketIOAuthenticateFn, TSocketIOValidateRoomFn } from '@venizia/ignis-helpers/socket-io';
46
26
  ```
47
27
 
48
- ### Use Cases
28
+ **Use cases:**
49
29
 
50
30
  - Live notifications and alerts
51
- - Real-time chat and messaging
52
- - Collaborative editing (docs, whiteboards)
53
- - Live data streams (dashboards, monitoring)
31
+ - Real-time chat and collaborative editing
32
+ - Live dashboards and monitoring streams
54
33
  - 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
34
+ - Service-to-service real-time messaging (via `SocketIOClientHelper`)
64
35
 
65
- # For Bun runtime only -- optional peer dependency
66
- bun add @socket.io/bun-engine
67
- ```
36
+ ## Setup
68
37
 
69
- ### Step 2: Bind Required Services
38
+ Three pieces are bound in `preConfigure()`, before the component itself is registered:
70
39
 
71
- In your application's `preConfigure()` method, bind the required services and register the component:
40
+ | Step | Binding key | Required |
41
+ |------|-------------|----------|
42
+ | 1. Redis connection | `SocketIOBindingKeys.REDIS_CONNECTION` | Yes |
43
+ | 2. Authenticate handler | `SocketIOBindingKeys.AUTHENTICATE_HANDLER` | Yes |
44
+ | 3. Room / connected handlers | `VALIDATE_ROOM_HANDLER`, `CLIENT_CONNECTED_HANDLER` | No |
72
45
 
73
46
  ```typescript
74
47
  import { BaseApplication } from '@venizia/ignis';
75
- import {
76
- SocketIOComponent,
77
- SocketIOBindingKeys,
78
- } from '@venizia/ignis/socket-io';
48
+ import { SocketIOComponent, SocketIOBindingKeys } from '@venizia/ignis/socket-io';
79
49
  import { RedisSingleHelper, ValueOrPromise } from '@venizia/ignis-helpers';
80
- import type {
81
- TSocketIOAuthenticateFn,
82
- TSocketIOValidateRoomFn,
83
- TSocketIOClientConnectedFn,
84
- } from '@venizia/ignis-helpers/socket-io';
50
+ import type { TSocketIOAuthenticateFn } from '@venizia/ignis-helpers/socket-io';
85
51
 
86
52
  export class Application extends BaseApplication {
87
- private redisHelper: RedisSingleHelper;
88
-
89
53
  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({
54
+ // 1. Redis connection -- required for the adapter + emitter
55
+ const redisHelper = new RedisSingleHelper({
97
56
  name: 'socket-io-redis',
98
57
  host: process.env.REDIS_HOST ?? 'localhost',
99
58
  port: +(process.env.REDIS_PORT ?? 6379),
100
- password: process.env.REDIS_PASSWORD,
101
59
  autoConnect: false,
102
60
  });
61
+ this.bind({ key: SocketIOBindingKeys.REDIS_CONNECTION }).toValue(redisHelper);
103
62
 
104
- this.bind<RedisSingleHelper>({
105
- key: SocketIOBindingKeys.REDIS_CONNECTION,
106
- }).toValue(this.redisHelper);
107
-
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
- };
63
+ // 2. Authentication handler -- required
64
+ const authenticateFn: TSocketIOAuthenticateFn = handshake => !!handshake.headers.authorization;
65
+ this.bind({ key: SocketIOBindingKeys.AUTHENTICATE_HANDLER }).toValue(authenticateFn);
114
66
 
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!
67
+ // 3. Register the component
141
68
  this.component(SocketIOComponent);
142
69
  }
143
70
  }
144
71
  ```
145
72
 
146
- #### `autoConnect: false` Rationale
147
-
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
179
-
180
- The component applies these defaults if `SocketIOBindingKeys.SERVER_OPTIONS` is not bound or partially overridden:
181
-
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) |
196
-
197
73
  > [!WARNING]
198
- > The default `cors.origin: '*'` is suitable for development only. In production, restrict this to your specific domains.
74
+ > `autoConnect: false` is required on the Redis helper -- the server helper duplicates the connection into 3 independent clients and connects them itself during `configure()`. Connecting the parent first races against the duplicates. Full step-by-step setup (Bun peer dependency, room validation, cluster/sentinel Redis, the `autoConnect` rationale) is in [Usage & Examples](./usage#full-setup).
199
75
 
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
- ```
76
+ ## How It Works
77
+
78
+ - **Post-start hook, not immediate init.** Socket.IO needs a running server, but components initialize *before* the server starts. `binding()` resolves all bindings and registers a post-start hook; the hook builds `SocketIOServerHelper` and binds it to `SOCKET_IO_INSTANCE` only after `start()` brings the server up.
79
+ - **Runtime detection picks the wiring.** `RuntimeModules.detect()` selects 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 matrix](./api#runtime-specific-behavior) for the full comparison.
80
+ - **One Redis connection becomes three.** The connection you bind is never consumed directly -- the helper calls `duplicateClient()` three times: a pub/sub pair for the Redis adapter (cross-instance room broadcast) and a third client for the Redis emitter (cross-instance direct send).
81
+ - **Authentication is mandatory.** Every client starts `unauthorized` and must emit `authenticate` within `authenticateTimeout` (default 10s) or it is disconnected. Success joins the client to the default rooms and starts a keep-alive ping.
82
+ - **Room joins are opt-in by default.** Without a bound `VALIDATE_ROOM_HANDLER`, every `join` request is silently rejected -- security-by-default, not a bug.
223
83
 
224
- ### Custom Configuration
84
+ ## Common Tasks
225
85
 
226
- Bind custom server options before registering the component:
86
+ **Restrict CORS for production.** Bind `SERVER_OPTIONS` before registering the component -- the default (`cors.origin: '*'`) is for local development only.
227
87
 
228
88
  ```typescript
229
- import { SocketIOBindingKeys } from '@venizia/ignis/socket-io';
230
89
  import type { ServerOptions } from 'socket.io';
231
90
 
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
-
91
+ this.bind<Partial<ServerOptions>>({ key: SocketIOBindingKeys.SERVER_OPTIONS }).toValue({
92
+ cors: { origin: ['https://myapp.com'], credentials: true },
93
+ });
248
94
  this.component(SocketIOComponent);
249
95
  ```
250
96
 
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* |
97
+ **Send a message from a service.** `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 [Usage & Examples](./usage).
266
98
 
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:
302
-
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 |
307
-
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
99
  ```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
- }
100
+ this.io.send({ destination: userId, payload: { topic: 'notification', data } });
354
101
  ```
355
102
 
356
- ### Resolved Bindings
357
-
358
- The component resolves all binding keys into a single `IResolvedBindings` object during the `binding()` phase:
103
+ **Scale Redis beyond a single node.** Swap `RedisSingleHelper` for `RedisClusterHelper` or `RedisSentinelHelper` -- both satisfy the `IRedisHelper` interface the component validates against. See [Redis Connection Alternatives](./usage#redis-connection-alternatives).
359
104
 
360
- #### `IResolvedBindings` Interface
361
- ```typescript
362
- interface IResolvedBindings {
363
- redisConnection: IRedisHelper;
364
- authenticateFn: TSocketIOAuthenticateFn;
365
- validateRoomFn?: TSocketIOValidateRoomFn;
366
- clientConnectedFn?: TSocketIOClientConnectedFn;
367
- }
368
- ```
369
-
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>;
374
-
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[]>;
380
-
381
- // Called after successful authentication -- register custom event handlers here
382
- type TSocketIOClientConnectedFn = (opts: { socket: IOSocket }) => ValueOrPromise<void>;
383
- ```
384
-
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
- ```
105
+ **Look up every default, binding key, and constant.** Full `DEFAULT_SERVER_OPTIONS`, the binding key table, system events, default rooms, and the client state machine are in the [API Reference](./api#configuration-reference).
399
106
 
400
107
  ## See Also
401
108
 
402
- - [Usage & Examples](./usage) -- Server-side usage, client helper, advanced patterns
403
- - [API Reference](./api) -- Architecture, method signatures, internals, types
109
+ - [Usage & Examples](./usage) -- Full setup steps, server-side usage, client helper, advanced patterns
110
+ - [API Reference](./api) -- Architecture, configuration reference, method signatures, internals, types
404
111
  - [Error Reference](./errors) -- Error conditions and troubleshooting
405
112
  - **Guides:**
406
113
  - [Components Overview](/guides/core-concepts/components) -- Component system basics
@@ -417,3 +124,9 @@ interface IHandshake {
417
124
  - [Real-Time Chat](/guides/tutorials/realtime-chat) -- Building a chat app with Socket.IO
418
125
  - **Changelog:**
419
126
  - [2026-02-06: Socket.IO Integration Fix](/changelogs/2026-02-06-socket-io-integration-fix) -- Lifecycle timing fix + Bun runtime support
127
+
128
+ **Files:**
129
+
130
+ - [`packages/core/src/components/socket-io/component.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/components/socket-io/component.ts) -- `SocketIOComponent`
131
+ - [`packages/core/src/components/socket-io/common/keys.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/components/socket-io/common/keys.ts) -- `SocketIOBindingKeys`
132
+ - [`packages/core/src/components/socket-io/common/types.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core/src/components/socket-io/common/types.ts) -- `IServerOptions`, `DEFAULT_SERVER_OPTIONS`