@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,12 +1,141 @@
1
- # Socket.IO -- Usage & Examples
1
+ ---
2
+ title: Socket.IO Component - Usage & Examples
3
+ description: Full setup steps, server-side usage, the client helper, and advanced patterns
4
+ difficulty: intermediate
5
+ ---
2
6
 
3
- > Server-side usage patterns, client helper setup, and advanced examples.
7
+ # Usage & Examples
4
8
 
5
- ## Server-Side Usage
9
+ Task-oriented patterns for the Socket.IO component: full setup, sending messages from a service, using the standalone client helper, and reading the example app.
6
10
 
7
- ### Inject and Use in Services/Controllers
11
+ ## Full setup
8
12
 
9
- Inject `SocketIOServerHelper` to interact with Socket.IO:
13
+ ### 1. Install dependencies
14
+
15
+ ```bash
16
+ # Core dependency (already included via @venizia/ignis)
17
+ # ioredis is required for the Redis adapter
18
+
19
+ # Bun runtime only - optional peer dependency
20
+ bun add @socket.io/bun-engine
21
+ ```
22
+
23
+ ### 2. Bind required and optional services
24
+
25
+ ```typescript
26
+ import { BaseApplication } from '@venizia/ignis';
27
+ import { SocketIOComponent, SocketIOBindingKeys } from '@venizia/ignis/socket-io';
28
+ import { RedisSingleHelper, ValueOrPromise } from '@venizia/ignis-helpers';
29
+ import type {
30
+ TSocketIOAuthenticateFn,
31
+ TSocketIOValidateRoomFn,
32
+ TSocketIOClientConnectedFn,
33
+ } from '@venizia/ignis-helpers/socket-io';
34
+
35
+ export class Application extends BaseApplication {
36
+ private redisHelper: RedisSingleHelper;
37
+
38
+ preConfigure(): ValueOrPromise<void> {
39
+ this.setupSocketIO();
40
+ // ... other setup
41
+ }
42
+
43
+ setupSocketIO() {
44
+ // 1. Redis connection (required for adapter + emitter)
45
+ this.redisHelper = new RedisSingleHelper({
46
+ name: 'socket-io-redis',
47
+ host: process.env.REDIS_HOST ?? 'localhost',
48
+ port: +(process.env.REDIS_PORT ?? 6379),
49
+ password: process.env.REDIS_PASSWORD,
50
+ autoConnect: false,
51
+ });
52
+
53
+ this.bind<RedisSingleHelper>({
54
+ key: SocketIOBindingKeys.REDIS_CONNECTION,
55
+ }).toValue(this.redisHelper);
56
+
57
+ // 2. Authentication handler (required)
58
+ const authenticateFn: TSocketIOAuthenticateFn = handshake => {
59
+ const token = handshake.headers.authorization;
60
+ // Implement your auth logic: JWT verification, session check, etc.
61
+ return !!token;
62
+ };
63
+
64
+ this.bind<TSocketIOAuthenticateFn>({
65
+ key: SocketIOBindingKeys.AUTHENTICATE_HANDLER,
66
+ }).toValue(authenticateFn);
67
+
68
+ // 3. Room validation handler (optional - joins rejected without this)
69
+ const validateRoomFn: TSocketIOValidateRoomFn = ({ socket, rooms }) => {
70
+ // Return the rooms that the client is allowed to join
71
+ return rooms.filter(room => room.startsWith('public-'));
72
+ };
73
+
74
+ this.bind<TSocketIOValidateRoomFn>({
75
+ key: SocketIOBindingKeys.VALIDATE_ROOM_HANDLER,
76
+ }).toValue(validateRoomFn);
77
+
78
+ // 4. Client connected handler (optional)
79
+ const clientConnectedFn: TSocketIOClientConnectedFn = ({ socket }) => {
80
+ console.log('Client connected:', socket.id);
81
+ // Register custom event handlers on the socket
82
+ };
83
+
84
+ this.bind<TSocketIOClientConnectedFn>({
85
+ key: SocketIOBindingKeys.CLIENT_CONNECTED_HANDLER,
86
+ }).toValue(clientConnectedFn);
87
+
88
+ // 5. Register the component - that's it!
89
+ this.component(SocketIOComponent);
90
+ }
91
+ }
92
+ ```
93
+
94
+ ### 3. Why `autoConnect: false`
95
+
96
+ The helper owns the connection timing, not you. `RedisSingleHelper` is created with `autoConnect: false` because the server helper calls `duplicateClient()` three times:
97
+
98
+ | Duplicate | Role |
99
+ |---|---|
100
+ | `redisPub` | Redis adapter - publishes room broadcasts |
101
+ | `redisSub` | Redis adapter - subscribes to room broadcasts |
102
+ | `redisEmitter` | Redis emitter - direct cross-instance send |
103
+
104
+ - **Duplicates inherit `lazyConnect`, not connection state.** During `configure()`, the helper checks each client's status. Any client still `wait`ing gets `connect()` called on it explicitly. The helper then waits for all three to reach `ready` before proceeding.
105
+ - **This avoids a race.** If the parent connects before the duplicates exist, the duplicates can end up in a state inconsistent with the parent's connection lifecycle.
106
+
107
+ ### Redis connection alternatives
108
+
109
+ `RedisSingleHelper` (single instance), `RedisClusterHelper` (cluster mode), and `RedisSentinelHelper` (Sentinel HA) all extend `AbstractRedisHelper` and satisfy the `IRedisHelper` interface the component validates against.
110
+
111
+ ```typescript
112
+ import { RedisClusterHelper } from '@venizia/ignis-helpers';
113
+
114
+ // For Redis Cluster deployments
115
+ const redisHelper = new RedisClusterHelper({
116
+ name: 'socket-io-redis-cluster',
117
+ nodes: [
118
+ { host: 'redis-node-1', port: 6379 },
119
+ { host: 'redis-node-2', port: 6380 },
120
+ { host: 'redis-node-3', port: 6381 },
121
+ ],
122
+ password: process.env.REDIS_PASSWORD,
123
+ autoConnect: false,
124
+ });
125
+
126
+ this.bind<RedisClusterHelper>({
127
+ key: SocketIOBindingKeys.REDIS_CONNECTION,
128
+ }).toValue(redisHelper);
129
+ ```
130
+
131
+ The internal `TRedisClient` type is `Redis | Cluster`, so both ioredis connection types work transparently.
132
+
133
+ > [!NOTE]
134
+ > Full defaults, the complete binding key table, and every system event/room constant are in the [Full Reference](./api#configuration-reference).
135
+
136
+ ## Inject the helper in a service or controller
137
+
138
+ `SocketIOServerHelper` is bound to `SOCKET_IO_INSTANCE` inside a post-start hook. That hook runs after the server starts - well after the DI container already built every service and controller. Use a lazy getter that resolves the helper on first access. Never `@inject` it in a constructor.
10
139
 
11
140
  ```typescript
12
141
  import {
@@ -19,7 +148,6 @@ import { SocketIOBindingKeys } from '@venizia/ignis/socket-io';
19
148
  import { SocketIOServerHelper } from '@venizia/ignis-helpers/socket-io';
20
149
 
21
150
  export class NotificationService extends BaseService {
22
- // Lazy getter pattern -- helper is bound AFTER server starts
23
151
  private _io: SocketIOServerHelper | null = null;
24
152
 
25
153
  constructor(
@@ -59,47 +187,37 @@ export class NotificationService extends BaseService {
59
187
  notifyRoom(opts: { room: string; message: string }) {
60
188
  this.io.send({
61
189
  destination: opts.room,
62
- payload: {
63
- topic: 'room:update',
64
- data: { message: opts.message },
65
- },
190
+ payload: { topic: 'room:update', data: { message: opts.message } },
66
191
  });
67
192
  }
68
193
 
69
194
  // Broadcast to all clients
70
195
  broadcastAnnouncement(opts: { message: string }) {
71
196
  this.io.send({
72
- payload: {
73
- topic: 'system:announcement',
74
- data: { message: opts.message },
75
- },
197
+ payload: { topic: 'system:announcement', data: { message: opts.message } },
76
198
  });
77
199
  }
78
200
  }
79
201
  ```
80
202
 
81
- > [!IMPORTANT]
82
- > **Lazy getter pattern**: Since `SocketIOServerHelper` is bound via a post-start hook, it's not available during DI construction. Use a lazy getter that resolves from the application container on first access.
203
+ - **Never `@inject` `SOCKET_IO_INSTANCE` in a constructor.** It is not bound yet at that point.
204
+ - **`send()` reads via the Redis emitter.** It works even if the destination client is connected to a different server instance - see [`send()` in the Full Reference](./api#messaging-via-send).
83
205
 
84
- ## Client Helper
206
+ ## Use the client helper
85
207
 
86
- `SocketIOClientHelper` provides a managed Socket.IO client for connecting to Socket.IO servers -- useful for service-to-service communication, testing, or building relay services. It extends `BaseHelper` for scoped logging and wraps the `socket.io-client` library with authentication flow, lifecycle callbacks, and error-safe event subscription.
208
+ `SocketIOClientHelper` wraps `socket.io-client` with authentication flow, lifecycle callbacks, and error-safe event subscription. Use it when your process needs to connect *to* a Socket.IO server, not run one - service-to-service communication, testing, or relay services.
87
209
 
88
- ### Client Setup
210
+ ### Client setup
89
211
 
90
212
  ```typescript
91
- import {
92
- SocketIOClientHelper,
93
- } from '@venizia/ignis-helpers/socket-io';
213
+ import { SocketIOClientHelper } from '@venizia/ignis-helpers/socket-io';
94
214
 
95
215
  const client = new SocketIOClientHelper({
96
216
  identifier: 'notification-relay',
97
217
  host: 'http://localhost:3000',
98
218
  options: {
99
219
  path: '/io',
100
- extraHeaders: {
101
- authorization: 'Bearer <token>',
102
- },
220
+ extraHeaders: { authorization: 'Bearer <token>' },
103
221
  },
104
222
 
105
223
  // Lifecycle callbacks (all optional)
@@ -107,56 +225,52 @@ const client = new SocketIOClientHelper({
107
225
  console.log('Connected to server');
108
226
  client.authenticate();
109
227
  },
110
- onDisconnected: (reason) => {
111
- console.log('Disconnected:', reason);
112
- },
113
- onError: (error) => {
114
- console.error('Connection error:', error);
115
- },
116
- onAuthenticated: () => {
117
- console.log('Authentication successful');
118
- },
119
- onUnauthenticated: (message) => {
120
- console.warn('Authentication failed:', message);
121
- },
228
+ onDisconnected: reason => console.log('Disconnected:', reason),
229
+ onError: error => console.error('Connection error:', error),
230
+ onAuthenticated: () => console.log('Authentication successful'),
231
+ onUnauthenticated: message => console.warn('Authentication failed:', message),
122
232
  });
123
233
  ```
124
234
 
125
- #### Constructor Behavior
235
+ - **The constructor calls `configure()` immediately.** It creates the `socket.io-client` `Socket` instance via `io(host, options)` and registers the internal event handlers. See the [full handler table](./api#client-configure-event-handlers) in the Full Reference.
236
+ - **The socket connects on its own unless you disable it.** Set `autoConnect: false` in `options` and call `client.connect()` yourself when you're ready.
237
+
238
+ #### `connect` vs `connection` event
126
239
 
127
- The constructor immediately calls `configure()`, which creates the `socket.io-client` `Socket` instance via `io(host, options)` and registers all internal event handlers (`connect`, `disconnect`, `connect_error`, `authenticated`, `unauthenticated`, `ping`). The socket is **not** connected until you call `client.connect()` (if using `autoConnect: false` in the options) or it connects automatically if `autoConnect` is not explicitly disabled.
240
+ Client and server fire different event names for the same moment:
128
241
 
129
- #### `connect` vs `connection` Event
242
+ | Side | Fires |
243
+ |---|---|
244
+ | Client (`socket.io-client`) | `connect` - no suffix |
245
+ | Server (`socket.io`) | `connection` - with the suffix |
130
246
 
131
- The client-side `socket.io-client` library fires the `connect` event (no "ion" suffix) when the connection is established. The server-side `socket.io` library fires `connection` (with the suffix). This is a Socket.IO convention, not an IGNIS-specific behavior. The client helper registers on `'connect'` while the server helper registers on `SocketIOConstants.EVENT_CONNECT` which equals `'connection'`.
247
+ This is a Socket.IO convention, not an IGNIS one. The client helper listens on `'connect'`. The server helper listens on `SocketIOConstants.EVENT_CONNECT`, which equals `'connection'`.
132
248
 
133
- ### Authentication Flow
249
+ ### Authentication flow
134
250
 
135
- After connecting, the client must emit `authenticate` to start the auth handshake. The server validates credentials from the socket handshake (headers, query params, `auth` object) and responds with either `authenticated` or `unauthenticated`.
251
+ After connecting, the client must emit `authenticate` to start the handshake. The server validates credentials from the socket handshake (headers, query params, `auth` object) and responds with either `authenticated` or `unauthenticated`.
136
252
 
137
253
  ```typescript
138
- // Manual authentication after connection
139
254
  client.authenticate();
140
255
  ```
141
256
 
142
- The `authenticate()` method has two guard conditions:
143
- 1. The socket must be connected (`client.connected === true`)
144
- 2. The current state must be `unauthorized` -- calling `authenticate()` while `authenticating` or already `authenticated` is a no-op with a warning log
257
+ `authenticate()` is a no-op with a warning log unless both conditions hold:
145
258
 
146
- #### Authentication Failure Details
259
+ 1. The socket is connected (`client.connected === true`).
260
+ 2. The current state is `unauthorized` - calling `authenticate()` while `authenticating` or already `authenticated` does nothing.
147
261
 
148
- The server sends two distinct error messages depending on how the `authenticateFn` fails:
262
+ #### Authentication failure messages
149
263
 
150
- | Failure Mode | Message | Cause |
151
- |-------------|---------|-------|
152
- | `authenticateFn` returned `false` | `"Invalid token to authenticate! Please login again!"` | Credentials were checked but deemed invalid |
153
- | `authenticateFn` threw an error | `"Failed to authenticate connection! Please login again!"` | An unexpected error occurred during validation |
264
+ The server sends a different message depending on how `authenticateFn` failed. Both paths reset the client to `unauthorized`, emit `unauthenticated` with the message, and disconnect the socket after delivery (via `setImmediate`).
154
265
 
155
- Both failure paths set the client state back to `unauthorized`, emit the `unauthenticated` event to the client with the message, and then disconnect the socket after the message is delivered (via `setImmediate` callback).
266
+ | Failure mode | Message |
267
+ |---|---|
268
+ | `authenticateFn` returned `false` | `"Invalid token to authenticate! Please login again!"` |
269
+ | `authenticateFn` threw an error | `"Failed to authenticate connection! Please login again!"` |
156
270
 
157
- ### Event Subscription
271
+ ### Event subscription
158
272
 
159
- Subscribe to custom events with automatic error safety. Handlers are wrapped in a dual try-catch that catches both synchronous throws and asynchronous rejections:
273
+ Handlers are wrapped in a dual try-catch. It catches both synchronous throws and asynchronous rejections, so a broken handler never crashes the client.
160
274
 
161
275
  ```typescript
162
276
  // Subscribe to a single event
@@ -167,26 +281,24 @@ client.subscribe({
167
281
  },
168
282
  });
169
283
 
170
- // Subscribe with duplicate detection disabled
284
+ // ignoreDuplicate: false stacks a second handler for the same event
171
285
  client.subscribe({
172
286
  event: 'chat:message',
173
- handler: (data) => { /* second handler */ },
174
- ignoreDuplicate: false, // default: true -- set to false to allow multiple handlers
287
+ handler: data => { /* second handler */ },
288
+ ignoreDuplicate: false,
175
289
  });
176
290
 
177
291
  // Subscribe to multiple events at once
178
292
  client.subscribeMany({
179
293
  events: {
180
- 'user:joined': (data) => console.log('User joined:', data),
181
- 'user:left': (data) => console.log('User left:', data),
182
- 'room:updated': (data) => console.log('Room updated:', data),
294
+ 'user:joined': data => console.log('User joined:', data),
295
+ 'user:left': data => console.log('User left:', data),
296
+ 'room:updated': data => console.log('Room updated:', data),
183
297
  },
184
298
  });
185
299
  ```
186
300
 
187
- #### Deduplication Behavior
188
-
189
- By default (`ignoreDuplicate: true`), `subscribe()` checks `socket.hasListeners(event)` before registering. If listeners already exist for the event, the call is a no-op and logs an info message. Set `ignoreDuplicate: false` to allow multiple handlers for the same event.
301
+ The default (`ignoreDuplicate: true`) checks `socket.hasListeners(event)` first. If a listener already exists, `subscribe()` is a no-op that logs an info message. Set `ignoreDuplicate: false` to stack handlers instead.
190
302
 
191
303
  ### Unsubscribing
192
304
 
@@ -201,22 +313,22 @@ client.unsubscribe({ event: 'chat:message', handler: myHandler });
201
313
  client.unsubscribeMany({ events: ['chat:message', 'user:joined', 'room:updated'] });
202
314
  ```
203
315
 
204
- ### Emitting Events
316
+ ### Emitting events
205
317
 
206
318
  ```typescript
207
319
  client.emit({
208
320
  topic: 'chat:send',
209
321
  data: { text: 'Hello world' },
210
- doLog: true, // optional: log the emission
211
- cb: () => { // optional: callback via setImmediate after emit
322
+ doLog: true, // optional: log the emission
323
+ callback: () => { // optional: invoked via setImmediate after emit
212
324
  console.log('Message sent');
213
325
  },
214
326
  });
215
327
  ```
216
328
 
217
- The `emit()` method throws if the socket is not connected or if no `topic` is provided. Unlike `send()` on the server helper, this method does **not** silently swallow errors.
329
+ `emit()` throws if the socket is not connected or if `topic` is missing. The server helper's `send()` silently drops a message with a missing field - `emit()` never does that. It always throws instead.
218
330
 
219
- ### Room Management
331
+ ### Room management
220
332
 
221
333
  ```typescript
222
334
  // Request to join rooms (server validates via validateRoomFn)
@@ -226,9 +338,9 @@ client.joinRooms({ rooms: ['chat-room-1', 'notifications'] });
226
338
  client.leaveRooms({ rooms: ['chat-room-1'] });
227
339
  ```
228
340
 
229
- Both methods emit Socket.IO events (`join` / `leave`) to the server. The actual join/leave happens server-side. If the socket is not connected, the call is a no-op with a warning log.
341
+ Both methods emit a Socket.IO event to the server: `join` or `leave`. The actual join or leave happens server-side. If the socket isn't connected, the call is a no-op with a warning log.
230
342
 
231
- ### Connection Management
343
+ ### Connection management
232
344
 
233
345
  ```typescript
234
346
  // Manually connect (useful when autoConnect: false in options)
@@ -247,34 +359,30 @@ const rawSocket = client.getSocketClient();
247
359
  ### Shutdown
248
360
 
249
361
  ```typescript
250
- // Clean shutdown: removes all listeners, disconnects, resets state
251
362
  client.shutdown();
252
363
  ```
253
364
 
254
- The `shutdown()` method:
255
- 1. Calls `removeAllListeners()` on the underlying socket to prevent memory leaks
256
- 2. Disconnects if still connected
257
- 3. Resets state to `unauthorized`
365
+ `shutdown()` does three things, in order:
258
366
 
259
- ## Advanced Usage
367
+ 1. Calls `removeAllListeners()` on the underlying socket to prevent memory leaks.
368
+ 2. Disconnects if still connected.
369
+ 3. Resets state to `unauthorized`.
260
370
 
261
- ### Complete Example
371
+ ## Run the complete example
262
372
 
263
- A full working example is available at `examples/socket-io-test/`. It demonstrates:
373
+ A full working example lives at `examples/socket-io-test/`.
264
374
 
265
375
  | Feature | Implementation |
266
- |---------|---------------|
267
- | Application setup | `src/application.ts` -- bindings, component registration, graceful shutdown |
268
- | REST endpoints | `src/controllers/socket-test.controller.ts` -- 9 endpoints for Socket.IO management |
269
- | Event handling | `src/services/socket-event.service.ts` -- chat, echo, room management |
270
- | Automated test client | `client.ts` -- 15+ test cases covering all features |
271
-
272
- #### REST API Endpoints
376
+ |---|---|
377
+ | Application setup | `src/application.ts` - bindings, component registration, graceful shutdown |
378
+ | REST endpoints | `src/controllers/socket-test.controller.ts` - 9 endpoints for Socket.IO management |
379
+ | Event handling | `src/services/socket-event.service.ts` - chat, echo, room management |
380
+ | Automated test client | `client.ts` - 15+ test cases covering all features |
273
381
 
274
- The example provides a REST API for managing Socket.IO:
382
+ ### REST API endpoints
275
383
 
276
384
  | Method | Path | Description |
277
- |--------|------|-------------|
385
+ |---|---|---|
278
386
  | `GET` | `/socket/info` | Server status + connected client count |
279
387
  | `GET` | `/socket/clients` | List all connected client IDs |
280
388
  | `GET` | `/socket/health` | Health check (is SocketIO ready?) |
@@ -285,38 +393,37 @@ The example provides a REST API for managing Socket.IO:
285
393
  | `POST` | `/socket/client/{clientId}/leave` | Remove client from <code v-pre>{{ rooms: string[] }}</code> |
286
394
  | `GET` | `/socket/client/{clientId}/rooms` | List rooms a client belongs to |
287
395
 
288
- #### Running the Example
396
+ ### Running the example
289
397
 
290
398
  ```bash
291
399
  # Start the server
292
400
  cd examples/socket-io-test
293
401
  bun run server:dev
294
402
 
295
- # In another terminal -- run automated tests
403
+ # In another terminal - run automated tests
296
404
  bun client.ts
297
405
  ```
298
406
 
299
- The automated client tests the following features:
407
+ The automated client exercises:
300
408
 
301
- - Authentication (valid and invalid tokens)
409
+ - Authentication with valid and invalid tokens
302
410
  - Ping/pong keepalive
303
411
  - Room join/leave with validation
304
412
  - Client-to-client messaging
305
- - Room broadcasting
306
- - Global broadcasting
307
- - REST API for Socket.IO management
413
+ - Room and global broadcasting
414
+ - The REST API
308
415
  - Graceful disconnection
309
416
 
310
- Review the example code to understand production-ready patterns for:
417
+ Read the example for these production-ready patterns:
311
418
 
312
- - Binding multiple handlers in a single `setupSocketIO()` method
313
- - Lazy getter pattern for accessing `SocketIOServerHelper` in services
419
+ - Binding multiple handlers in one `setupSocketIO()` method
420
+ - The lazy getter pattern for `SocketIOServerHelper`
314
421
  - Custom event registration via `CLIENT_CONNECTED_HANDLER`
315
- - Room validation logic preventing unauthorized room access
316
- - Graceful shutdown sequence in `application.stop()`
422
+ - Room validation that blocks unauthorized rooms
423
+ - A graceful shutdown sequence in `application.stop()`
317
424
 
318
- ## See Also
425
+ ## See also
319
426
 
320
- - [Setup & Configuration](./) -- Quick reference, installation, bindings, constants
321
- - [API Reference](./api) -- Architecture, method signatures, internals, types
322
- - [Error Reference](./errors) -- Error conditions and troubleshooting
427
+ - [Overview](./) - quick start, imports, common configuration tasks
428
+ - [Full Reference](./api) - architecture, configuration reference, method signatures, internals, types
429
+ - [Error Reference](./errors) - error conditions and troubleshooting