@venizia/ignis-docs 0.2.1-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 (145) hide show
  1. package/content/best-practices/architectural-patterns.md +3 -3
  2. package/content/best-practices/code-style-standards/naming-conventions.md +1 -1
  3. package/content/best-practices/contribution-workflow.md +2 -2
  4. package/content/best-practices/error-handling.md +94 -89
  5. package/content/best-practices/security-guidelines.md +5 -5
  6. package/content/extensions/components/api-reference.md +22 -21
  7. package/content/extensions/components/authentication/api.md +64 -28
  8. package/content/extensions/components/authentication/errors.md +19 -5
  9. package/content/extensions/components/authentication/index.md +19 -18
  10. package/content/extensions/components/authentication/usage.md +55 -30
  11. package/content/extensions/components/authorization/api.md +351 -84
  12. package/content/extensions/components/authorization/errors.md +51 -17
  13. package/content/extensions/components/authorization/getting-started.md +227 -0
  14. package/content/extensions/components/authorization/index.md +24 -16
  15. package/content/extensions/components/authorization/usage.md +45 -21
  16. package/content/extensions/components/health-check.md +15 -9
  17. package/content/extensions/components/index.md +24 -90
  18. package/content/extensions/components/mail/api.md +105 -54
  19. package/content/extensions/components/mail/errors.md +12 -10
  20. package/content/extensions/components/mail/index.md +32 -13
  21. package/content/extensions/components/mail/usage.md +26 -18
  22. package/content/extensions/components/request-tracker.md +18 -14
  23. package/content/extensions/components/socket-io/api.md +377 -882
  24. package/content/extensions/components/socket-io/errors.md +49 -51
  25. package/content/extensions/components/socket-io/index.md +72 -88
  26. package/content/extensions/components/socket-io/usage.md +107 -117
  27. package/content/extensions/components/static-asset/api.md +83 -31
  28. package/content/extensions/components/static-asset/errors.md +18 -7
  29. package/content/extensions/components/static-asset/index.md +18 -11
  30. package/content/extensions/components/static-asset/usage.md +11 -6
  31. package/content/extensions/components/template/index.md +3 -3
  32. package/content/extensions/components/websocket/api.md +58 -27
  33. package/content/extensions/components/websocket/errors.md +3 -3
  34. package/content/extensions/components/websocket/index.md +8 -7
  35. package/content/extensions/components/websocket/usage.md +21 -8
  36. package/content/extensions/helpers/cron/index.md +8 -7
  37. package/content/extensions/helpers/crypto/index.md +16 -8
  38. package/content/extensions/helpers/crypto/reference.md +96 -24
  39. package/content/extensions/helpers/env/index.md +14 -10
  40. package/content/extensions/helpers/error/index.md +99 -23
  41. package/content/extensions/helpers/index.md +61 -47
  42. package/content/extensions/helpers/inversion/index.md +23 -6
  43. package/content/extensions/helpers/inversion/reference.md +30 -22
  44. package/content/extensions/helpers/kafka/admin.md +3 -2
  45. package/content/extensions/helpers/kafka/compile-binary.md +69 -44
  46. package/content/extensions/helpers/kafka/consumer.md +24 -21
  47. package/content/extensions/helpers/kafka/examples.md +22 -234
  48. package/content/extensions/helpers/kafka/index.md +30 -62
  49. package/content/extensions/helpers/kafka/producer.md +31 -26
  50. package/content/extensions/helpers/kafka/schema-registry.md +19 -14
  51. package/content/extensions/helpers/logger/hf-logger.md +49 -22
  52. package/content/extensions/helpers/logger/index.md +37 -12
  53. package/content/extensions/helpers/logger/pino.md +31 -11
  54. package/content/extensions/helpers/logger/reference.md +243 -52
  55. package/content/extensions/helpers/network/api.md +65 -30
  56. package/content/extensions/helpers/network/index.md +32 -11
  57. package/content/extensions/helpers/queue/index.md +17 -6
  58. package/content/extensions/helpers/queue/reference.md +52 -25
  59. package/content/extensions/helpers/redis/index.md +29 -11
  60. package/content/extensions/helpers/redis/reference.md +85 -28
  61. package/content/extensions/helpers/secrets/index.md +82 -12
  62. package/content/extensions/helpers/socket-io/api.md +40 -21
  63. package/content/extensions/helpers/socket-io/index.md +26 -10
  64. package/content/extensions/helpers/storage/api.md +42 -24
  65. package/content/extensions/helpers/storage/index.md +10 -7
  66. package/content/extensions/helpers/types/index.md +20 -7
  67. package/content/extensions/helpers/types/reference.md +53 -14
  68. package/content/extensions/helpers/uid/index.md +166 -10
  69. package/content/extensions/helpers/websocket/api.md +52 -13
  70. package/content/extensions/helpers/websocket/index.md +7 -4
  71. package/content/extensions/helpers/worker-thread/index.md +9 -5
  72. package/content/extensions/helpers/worker-thread/reference.md +20 -20
  73. package/content/extensions/index.md +38 -39
  74. package/content/extensions/src-details/mcp-server.md +96 -548
  75. package/content/guides/core-concepts/persistent/datasources.md +2 -2
  76. package/content/guides/core-concepts/persistent/index.md +5 -1
  77. package/content/guides/core-concepts/persistent/pglite.md +218 -0
  78. package/content/guides/core-concepts/persistent/postgres-drivers.md +21 -15
  79. package/content/guides/core-concepts/persistent/search-meilisearch.md +22 -12
  80. package/content/guides/core-concepts/persistent/search-typesense.md +26 -14
  81. package/content/guides/core-concepts/persistent/sqlite.md +296 -0
  82. package/content/guides/core-concepts/persistent/transactions.md +12 -11
  83. package/content/guides/get-started/5-minute-quickstart.md +59 -206
  84. package/content/guides/get-started/philosophy.md +135 -670
  85. package/content/guides/get-started/setup.md +53 -74
  86. package/content/guides/migrations/redis-helpers-migration.md +4 -3
  87. package/content/guides/migrations/scoped-rbac-migration.md +5 -5
  88. package/content/guides/migrations/unified-connectors-migration.md +7 -6
  89. package/content/guides/tutorials/realtime-chat.md +1 -1
  90. package/content/references/base/application.md +63 -21
  91. package/content/references/base/components.md +3 -3
  92. package/content/references/base/connectors.md +14 -14
  93. package/content/references/base/controllers.md +12 -12
  94. package/content/references/base/datasources-reference.md +32 -31
  95. package/content/references/base/datasources.md +6 -6
  96. package/content/references/base/dependency-injection.md +12 -11
  97. package/content/references/base/filter-system/application-usage.md +54 -30
  98. package/content/references/base/filter-system/array-operators.md +24 -46
  99. package/content/references/base/filter-system/comparison-operators.md +47 -67
  100. package/content/references/base/filter-system/default-filter.md +59 -53
  101. package/content/references/base/filter-system/fields-order-pagination.md +92 -146
  102. package/content/references/base/filter-system/index.md +25 -13
  103. package/content/references/base/filter-system/json-filtering.md +45 -184
  104. package/content/references/base/filter-system/list-operators.md +23 -53
  105. package/content/references/base/filter-system/logical-operators.md +63 -121
  106. package/content/references/base/filter-system/null-operators.md +34 -104
  107. package/content/references/base/filter-system/pattern-matching.md +40 -55
  108. package/content/references/base/filter-system/quick-reference.md +86 -198
  109. package/content/references/base/filter-system/range-operators.md +18 -46
  110. package/content/references/base/filter-system/tips.md +6 -6
  111. package/content/references/base/filter-system/use-cases.md +33 -15
  112. package/content/references/base/grpc-controllers.md +53 -17
  113. package/content/references/base/index.md +5 -3
  114. package/content/references/base/middlewares.md +11 -10
  115. package/content/references/base/models-reference.md +17 -17
  116. package/content/references/base/models.md +4 -3
  117. package/content/references/base/providers.md +8 -8
  118. package/content/references/base/repositories/advanced.md +224 -326
  119. package/content/references/base/repositories/index.md +19 -6
  120. package/content/references/base/repositories/mixins.md +5 -5
  121. package/content/references/base/repositories/relations.md +160 -293
  122. package/content/references/base/repositories/soft-deletable.md +16 -6
  123. package/content/references/base/secrets.md +17 -13
  124. package/content/references/base/services.md +6 -4
  125. package/content/references/configuration/environment-variables.md +31 -23
  126. package/content/references/configuration/index.md +6 -4
  127. package/content/references/index.md +1 -1
  128. package/content/references/utilities/duration.md +85 -0
  129. package/content/references/utilities/index.md +5 -1
  130. package/content/references/utilities/jsx-reference.md +11 -11
  131. package/content/references/utilities/jsx.md +2 -2
  132. package/content/references/utilities/module.md +78 -25
  133. package/content/references/utilities/request.md +2 -1
  134. package/content/references/utilities/retry.md +139 -0
  135. package/content/references/utilities/schema.md +2 -2
  136. package/content/references/utilities/statuses-reference.md +4 -4
  137. package/content/references/utilities/statuses.md +5 -5
  138. package/dist/mcp-server/index.js +0 -0
  139. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
  140. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts.map +1 -1
  141. package/dist/mcp-server/tools/github/list-project-files.tool.js +3 -3
  142. package/dist/mcp-server/tools/github/search-code.tool.js +1 -1
  143. package/dist/mcp-server/tools/github/verify-dependencies.tool.js +1 -1
  144. package/dist/mcp-server/tools/github/view-source-file.tool.js +1 -1
  145. package/package.json +17 -16
@@ -1,20 +1,26 @@
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
- > Full setup steps, server-side usage patterns, client helper, and advanced examples.
7
+ # Usage & Examples
4
8
 
5
- ## Full Setup
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
- ### 1. Install Dependencies
11
+ ## Full setup
12
+
13
+ ### 1. Install dependencies
8
14
 
9
15
  ```bash
10
16
  # Core dependency (already included via @venizia/ignis)
11
17
  # ioredis is required for the Redis adapter
12
18
 
13
- # For Bun runtime only -- optional peer dependency
19
+ # Bun runtime only - optional peer dependency
14
20
  bun add @socket.io/bun-engine
15
21
  ```
16
22
 
17
- ### 2. Bind Required + Optional Services
23
+ ### 2. Bind required and optional services
18
24
 
19
25
  ```typescript
20
26
  import { BaseApplication } from '@venizia/ignis';
@@ -51,7 +57,7 @@ export class Application extends BaseApplication {
51
57
  // 2. Authentication handler (required)
52
58
  const authenticateFn: TSocketIOAuthenticateFn = handshake => {
53
59
  const token = handshake.headers.authorization;
54
- // Implement your auth logic -- JWT verification, session check, etc.
60
+ // Implement your auth logic: JWT verification, session check, etc.
55
61
  return !!token;
56
62
  };
57
63
 
@@ -59,11 +65,10 @@ export class Application extends BaseApplication {
59
65
  key: SocketIOBindingKeys.AUTHENTICATE_HANDLER,
60
66
  }).toValue(authenticateFn);
61
67
 
62
- // 3. Room validation handler (optional -- joins rejected without this)
68
+ // 3. Room validation handler (optional - joins rejected without this)
63
69
  const validateRoomFn: TSocketIOValidateRoomFn = ({ socket, rooms }) => {
64
70
  // Return the rooms that the client is allowed to join
65
- const allowedRooms = rooms.filter(room => room.startsWith('public-'));
66
- return allowedRooms;
71
+ return rooms.filter(room => room.startsWith('public-'));
67
72
  };
68
73
 
69
74
  this.bind<TSocketIOValidateRoomFn>({
@@ -80,7 +85,7 @@ export class Application extends BaseApplication {
80
85
  key: SocketIOBindingKeys.CLIENT_CONNECTED_HANDLER,
81
86
  }).toValue(clientConnectedFn);
82
87
 
83
- // 5. Register the component -- that's it!
88
+ // 5. Register the component - that's it!
84
89
  this.component(SocketIOComponent);
85
90
  }
86
91
  }
@@ -88,11 +93,18 @@ export class Application extends BaseApplication {
88
93
 
89
94
  ### 3. Why `autoConnect: false`
90
95
 
91
- - **The helper owns connection, not you.** `RedisSingleHelper` is created with `autoConnect: false` because the server helper internally calls `client.duplicate()` to create 3 independent Redis connections (pub, sub, emitter).
92
- - **Duplicates inherit `lazyConnect`, not connection state.** 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.
93
- - **This avoids a race.** If the parent connects before the duplicates exist, the duplicates can end up in an inconsistent state relative to the parent's connection lifecycle.
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.
94
106
 
95
- ### Redis Connection Alternatives
107
+ ### Redis connection alternatives
96
108
 
97
109
  `RedisSingleHelper` (single instance), `RedisClusterHelper` (cluster mode), and `RedisSentinelHelper` (Sentinel HA) all extend `AbstractRedisHelper` and satisfy the `IRedisHelper` interface the component validates against.
98
110
 
@@ -116,17 +128,14 @@ this.bind<RedisClusterHelper>({
116
128
  }).toValue(redisHelper);
117
129
  ```
118
130
 
119
- The internal `TRedisClient` type is `Redis | Cluster`, so both ioredis connection types are supported transparently.
131
+ The internal `TRedisClient` type is `Redis | Cluster`, so both ioredis connection types work transparently.
120
132
 
121
133
  > [!NOTE]
122
- > Full defaults, the complete binding key table, and every system event/room constant are in the [API Reference](./api#configuration-reference).
134
+ > Full defaults, the complete binding key table, and every system event/room constant are in the [Full Reference](./api#configuration-reference).
123
135
 
124
- ## Server-Side Usage
136
+ ## Inject the helper in a service or controller
125
137
 
126
- ### Inject and Use in Services/Controllers
127
-
128
- - **`SOCKET_IO_INSTANCE` does not exist at construction time.** The component binds `SocketIOServerHelper` from a post-start hook, which runs after the server starts -- well after every service/controller has already been constructed by the DI container.
129
- - **Use a lazy getter, not `@inject`.** Resolve the helper from the application container on first access, and cache it. `@inject`-ing `SOCKET_IO_INSTANCE` directly in a constructor will resolve to nothing.
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.
130
139
 
131
140
  ```typescript
132
141
  import {
@@ -178,30 +187,27 @@ export class NotificationService extends BaseService {
178
187
  notifyRoom(opts: { room: string; message: string }) {
179
188
  this.io.send({
180
189
  destination: opts.room,
181
- payload: {
182
- topic: 'room:update',
183
- data: { message: opts.message },
184
- },
190
+ payload: { topic: 'room:update', data: { message: opts.message } },
185
191
  });
186
192
  }
187
193
 
188
194
  // Broadcast to all clients
189
195
  broadcastAnnouncement(opts: { message: string }) {
190
196
  this.io.send({
191
- payload: {
192
- topic: 'system:announcement',
193
- data: { message: opts.message },
194
- },
197
+ payload: { topic: 'system:announcement', data: { message: opts.message } },
195
198
  });
196
199
  }
197
200
  }
198
201
  ```
199
202
 
200
- ## Client Helper
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).
201
205
 
202
- `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 `socket.io-client` with authentication flow, lifecycle callbacks, and error-safe event subscription.
206
+ ## Use the client helper
203
207
 
204
- ### Client Setup
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.
209
+
210
+ ### Client setup
205
211
 
206
212
  ```typescript
207
213
  import { SocketIOClientHelper } from '@venizia/ignis-helpers/socket-io';
@@ -211,9 +217,7 @@ const client = new SocketIOClientHelper({
211
217
  host: 'http://localhost:3000',
212
218
  options: {
213
219
  path: '/io',
214
- extraHeaders: {
215
- authorization: 'Bearer <token>',
216
- },
220
+ extraHeaders: { authorization: 'Bearer <token>' },
217
221
  },
218
222
 
219
223
  // Lifecycle callbacks (all optional)
@@ -221,57 +225,52 @@ const client = new SocketIOClientHelper({
221
225
  console.log('Connected to server');
222
226
  client.authenticate();
223
227
  },
224
- onDisconnected: (reason) => {
225
- console.log('Disconnected:', reason);
226
- },
227
- onError: (error) => {
228
- console.error('Connection error:', error);
229
- },
230
- onAuthenticated: () => {
231
- console.log('Authentication successful');
232
- },
233
- onUnauthenticated: (message) => {
234
- console.warn('Authentication failed:', message);
235
- },
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),
236
232
  });
237
233
  ```
238
234
 
239
- - **The constructor calls `configure()` immediately.** `configure()` creates the `socket.io-client` `Socket` instance via `io(host, options)` and registers all internal event handlers (`connect`, `disconnect`, `connect_error`, `authenticated`, `unauthenticated`, `ping`).
240
- - **The socket does not connect on its own accord unless `autoConnect` allows it.** Call `client.connect()` explicitly when `autoConnect: false` is set in `options`; otherwise the socket connects automatically.
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
239
+
240
+ Client and server fire different event names for the same moment:
241
241
 
242
- #### `connect` vs `connection` Event
242
+ | Side | Fires |
243
+ |---|---|
244
+ | Client (`socket.io-client`) | `connect` - no suffix |
245
+ | Server (`socket.io`) | `connection` - with the suffix |
243
246
 
244
- - **Client and server use different event names.** `socket.io-client` fires `connect` (no suffix) when the connection is established; server-side `socket.io` fires `connection` (with the suffix). This is a Socket.IO convention, not IGNIS-specific.
245
- - **The two helpers mirror this.** The client helper registers on `'connect'`; 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'`.
246
248
 
247
- ### Authentication Flow
249
+ ### Authentication flow
248
250
 
249
- 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`.
250
252
 
251
253
  ```typescript
252
- // Manual authentication after connection
253
254
  client.authenticate();
254
255
  ```
255
256
 
256
- `authenticate()` has two guard conditions -- both make the call a no-op with a warning log:
257
+ `authenticate()` is a no-op with a warning log unless both conditions hold:
257
258
 
258
- 1. The socket must be connected (`client.connected === true`)
259
- 2. The current state must be `unauthorized` -- calling `authenticate()` while `authenticating` or already `authenticated` does nothing
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.
260
261
 
261
- #### Authentication Failure Details
262
+ #### Authentication failure messages
262
263
 
263
- The server sends two distinct error messages depending on how `authenticateFn` fails:
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`).
264
265
 
265
- | Failure Mode | Message | Cause |
266
- |-------------|---------|-------|
267
- | `authenticateFn` returned `false` | `"Invalid token to authenticate! Please login again!"` | Credentials were checked but deemed invalid |
268
- | `authenticateFn` threw an error | `"Failed to authenticate connection! Please login again!"` | An unexpected error occurred during validation |
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!"` |
269
270
 
270
- Both failure paths set the client state back to `unauthorized`, emit the `unauthenticated` event to the client with the message, and disconnect the socket after the message is delivered (via a `setImmediate` callback).
271
+ ### Event subscription
271
272
 
272
- ### Event Subscription
273
-
274
- 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.
275
274
 
276
275
  ```typescript
277
276
  // Subscribe to a single event
@@ -282,27 +281,24 @@ client.subscribe({
282
281
  },
283
282
  });
284
283
 
285
- // Subscribe with duplicate detection disabled
284
+ // ignoreDuplicate: false stacks a second handler for the same event
286
285
  client.subscribe({
287
286
  event: 'chat:message',
288
- handler: (data) => { /* second handler */ },
289
- ignoreDuplicate: false, // default: true -- set to false to allow multiple handlers
287
+ handler: data => { /* second handler */ },
288
+ ignoreDuplicate: false,
290
289
  });
291
290
 
292
291
  // Subscribe to multiple events at once
293
292
  client.subscribeMany({
294
293
  events: {
295
- 'user:joined': (data) => console.log('User joined:', data),
296
- 'user:left': (data) => console.log('User left:', data),
297
- '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),
298
297
  },
299
298
  });
300
299
  ```
301
300
 
302
- #### Deduplication Behavior
303
-
304
- - **The default (`ignoreDuplicate: true`) checks `socket.hasListeners(event)` first.** If listeners already exist for the event, `subscribe()` is a no-op and logs an info message.
305
- - **Set `ignoreDuplicate: false` to stack handlers.** This allows multiple handlers to run 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.
306
302
 
307
303
  ### Unsubscribing
308
304
 
@@ -317,7 +313,7 @@ client.unsubscribe({ event: 'chat:message', handler: myHandler });
317
313
  client.unsubscribeMany({ events: ['chat:message', 'user:joined', 'room:updated'] });
318
314
  ```
319
315
 
320
- ### Emitting Events
316
+ ### Emitting events
321
317
 
322
318
  ```typescript
323
319
  client.emit({
@@ -330,9 +326,9 @@ client.emit({
330
326
  });
331
327
  ```
332
328
 
333
- `emit()` 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 missing-argument 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.
334
330
 
335
- ### Room Management
331
+ ### Room management
336
332
 
337
333
  ```typescript
338
334
  // Request to join rooms (server validates via validateRoomFn)
@@ -342,9 +338,9 @@ client.joinRooms({ rooms: ['chat-room-1', 'notifications'] });
342
338
  client.leaveRooms({ rooms: ['chat-room-1'] });
343
339
  ```
344
340
 
345
- 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.
346
342
 
347
- ### Connection Management
343
+ ### Connection management
348
344
 
349
345
  ```typescript
350
346
  // Manually connect (useful when autoConnect: false in options)
@@ -363,35 +359,30 @@ const rawSocket = client.getSocketClient();
363
359
  ### Shutdown
364
360
 
365
361
  ```typescript
366
- // Clean shutdown: removes all listeners, disconnects, resets state
367
362
  client.shutdown();
368
363
  ```
369
364
 
370
365
  `shutdown()` does three things, in order:
371
366
 
372
- 1. Calls `removeAllListeners()` on the underlying socket to prevent memory leaks
373
- 2. Disconnects if still connected
374
- 3. Resets state to `unauthorized`
367
+ 1. Calls `removeAllListeners()` on the underlying socket to prevent memory leaks.
368
+ 2. Disconnects if still connected.
369
+ 3. Resets state to `unauthorized`.
375
370
 
376
- ## Advanced Usage
371
+ ## Run the complete example
377
372
 
378
- ### Complete Example
379
-
380
- A full working example is available at `examples/socket-io-test/`. It demonstrates:
373
+ A full working example lives at `examples/socket-io-test/`.
381
374
 
382
375
  | Feature | Implementation |
383
- |---------|---------------|
384
- | Application setup | `src/application.ts` -- bindings, component registration, graceful shutdown |
385
- | REST endpoints | `src/controllers/socket-test.controller.ts` -- 9 endpoints for Socket.IO management |
386
- | Event handling | `src/services/socket-event.service.ts` -- chat, echo, room management |
387
- | Automated test client | `client.ts` -- 15+ test cases covering all features |
388
-
389
- #### 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 |
390
381
 
391
- The example provides a REST API for managing Socket.IO:
382
+ ### REST API endpoints
392
383
 
393
384
  | Method | Path | Description |
394
- |--------|------|-------------|
385
+ |---|---|---|
395
386
  | `GET` | `/socket/info` | Server status + connected client count |
396
387
  | `GET` | `/socket/clients` | List all connected client IDs |
397
388
  | `GET` | `/socket/health` | Health check (is SocketIO ready?) |
@@ -402,38 +393,37 @@ The example provides a REST API for managing Socket.IO:
402
393
  | `POST` | `/socket/client/{clientId}/leave` | Remove client from <code v-pre>{{ rooms: string[] }}</code> |
403
394
  | `GET` | `/socket/client/{clientId}/rooms` | List rooms a client belongs to |
404
395
 
405
- #### Running the Example
396
+ ### Running the example
406
397
 
407
398
  ```bash
408
399
  # Start the server
409
400
  cd examples/socket-io-test
410
401
  bun run server:dev
411
402
 
412
- # In another terminal -- run automated tests
403
+ # In another terminal - run automated tests
413
404
  bun client.ts
414
405
  ```
415
406
 
416
- The automated client tests the following features:
407
+ The automated client exercises:
417
408
 
418
- - Authentication (valid and invalid tokens)
409
+ - Authentication with valid and invalid tokens
419
410
  - Ping/pong keepalive
420
411
  - Room join/leave with validation
421
412
  - Client-to-client messaging
422
- - Room broadcasting
423
- - Global broadcasting
424
- - REST API for Socket.IO management
413
+ - Room and global broadcasting
414
+ - The REST API
425
415
  - Graceful disconnection
426
416
 
427
- Review the example code to understand production-ready patterns for:
417
+ Read the example for these production-ready patterns:
428
418
 
429
- - Binding multiple handlers in a single `setupSocketIO()` method
430
- - Lazy getter pattern for accessing `SocketIOServerHelper` in services
419
+ - Binding multiple handlers in one `setupSocketIO()` method
420
+ - The lazy getter pattern for `SocketIOServerHelper`
431
421
  - Custom event registration via `CLIENT_CONNECTED_HANDLER`
432
- - Room validation logic preventing unauthorized room access
433
- - Graceful shutdown sequence in `application.stop()`
422
+ - Room validation that blocks unauthorized rooms
423
+ - A graceful shutdown sequence in `application.stop()`
434
424
 
435
- ## See Also
425
+ ## See also
436
426
 
437
- - [Setup & Configuration](./) -- Quick reference, import paths, use cases
438
- - [API Reference](./api) -- Architecture, configuration reference, method signatures, internals, types
439
- - [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