@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,4 +1,43 @@
1
- # Network -- API Reference
1
+ ---
2
+ title: Network - Full Reference
3
+ description: Complete reference for every network helper class - HTTP fetchers, TCP/TLS socket client and server, UDP client - and every option and type
4
+ difficulty: intermediate
5
+ ---
6
+
7
+ # Network - Full Reference
8
+
9
+ Exhaustive reference for `BaseNetworkRequest` and its fetchers, the TCP/TLS client-server hierarchy, `NetworkUdpClient`, and every option type. For a readable introduction and the most common tasks, start with the [Network overview](/extensions/helpers/network/).
10
+
11
+ ## Find what you need
12
+
13
+ | You're looking for | Go to |
14
+ |---|---|
15
+ | The HTTP client base class and URL helpers | [BaseNetworkRequest](#basenetworkrequest) |
16
+ | Axios-backed HTTP client | [AxiosFetcher](#axiosfetcher) / [AxiosNetworkRequest](#axiosnetworkrequest) |
17
+ | Native-`fetch`-backed HTTP client | [NodeFetcher](#nodefetcher) / [NodeFetchNetworkRequest](#nodefetchnetworkrequest) |
18
+ | Why the `QUERY` method must reach the wire uppercase | [HTTP.Methods](#http-methods) |
19
+ | Secret redaction in request logs | [Request Logging and Redaction](#request-logging-and-redaction) |
20
+ | Plain TCP or TLS server, client tracking, authentication | [BaseNetworkTcpServer](#basenetworktcpserver) |
21
+ | Plain TCP or TLS client, auto-reconnect behavior | [BaseNetworkTcpClient](#basenetworktcpclient) |
22
+ | UDP client and multicast | [NetworkUdpClient](#networkudpclient) |
23
+ | Every option and type in one place | [Types Reference](#types-reference) |
24
+
25
+ **Files:**
26
+
27
+ - [`packages/helpers/src/modules/network/http-request/base-network-request.helper.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/network/http-request/base-network-request.helper.ts) - `BaseNetworkRequest`
28
+ - [`packages/helpers/src/modules/network/http-request/fetcher/base-fetcher.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/network/http-request/fetcher/base-fetcher.ts) - `IFetchable`, `IRequestOptions`, `AbstractNetworkFetchableHelper`
29
+ - [`packages/helpers/src/modules/network/http-request/fetcher/node-fetcher.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/network/http-request/fetcher/node-fetcher.ts) - `NodeFetcher`, `NodeFetchNetworkRequest`
30
+ - [`packages/helpers/src/modules/network/http-request/fetcher/axios-fetcher.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/network/http-request/fetcher/axios-fetcher.ts) - `AxiosFetcher`, `AxiosNetworkRequest` (`@venizia/ignis-helpers/axios` sub-path)
31
+ - [`packages/helpers/src/modules/network/http-request/types.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/network/http-request/types.ts) - `TFetcherVariant`, `TFetcherResponse`, `TFetcherWorker`
32
+ - [`packages/helpers/src/modules/network/tcp-socket/base-tcp-server.helper.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/network/tcp-socket/base-tcp-server.helper.ts) - `BaseNetworkTcpServer`, `ITcpSocketClient`, `ITcpSocketServerOptions`
33
+ - [`packages/helpers/src/modules/network/tcp-socket/base-tcp-client.helper.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/network/tcp-socket/base-tcp-client.helper.ts) - `BaseNetworkTcpClient`, `INetworkTcpClientProps`
34
+ - [`packages/helpers/src/modules/network/tcp-socket/network-tcp-server.helper.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/network/tcp-socket/network-tcp-server.helper.ts) - `NetworkTcpServer`
35
+ - [`packages/helpers/src/modules/network/tcp-socket/network-tcp-client.helper.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/network/tcp-socket/network-tcp-client.helper.ts) - `NetworkTcpClient`
36
+ - [`packages/helpers/src/modules/network/tcp-socket/network-tls-tcp-server.helper.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/network/tcp-socket/network-tls-tcp-server.helper.ts) - `NetworkTlsTcpServer`
37
+ - [`packages/helpers/src/modules/network/tcp-socket/network-tls-tcp-client.helper.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/network/tcp-socket/network-tls-tcp-client.helper.ts) - `NetworkTlsTcpClient`
38
+ - [`packages/helpers/src/modules/network/udp-socket/network-udp-client.helper.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/network/udp-socket/network-udp-client.helper.ts) - `NetworkUdpClient`, `INetworkUdpClientProps`
39
+ - [`packages/helpers/src/common/redact.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/common/redact.ts) - `redactSecrets`, `redactUrlCredentials`
40
+ - [`packages/helpers/src/common/constants/http.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/common/constants/http.ts) - `HTTP.Methods`, `THttpMethod`
2
41
 
3
42
  ## Architecture
4
43
 
@@ -9,21 +48,21 @@ BaseHelper
9
48
  │ └── NodeFetchNetworkRequest (T = 'node-fetch')
10
49
 
11
50
  ├── BaseNetworkTcpServer<ServerOpts, ServerType, ClientType>
12
- │ ├── NetworkTcpServer (net.Server, net.Socket)
13
- │ └── NetworkTlsTcpServer (tls.Server, tls.TLSSocket)
51
+ │ ├── NetworkTcpServer (net.createServer, net.Socket)
52
+ │ └── NetworkTlsTcpServer (tls.createServer, tls.TLSSocket)
14
53
 
15
54
  ├── BaseNetworkTcpClient<ClientOpts, ClientType>
16
- │ ├── NetworkTcpClient (net.TcpSocketConnectOpts, net.Socket)
17
- │ └── NetworkTlsTcpClient (tls.ConnectionOptions, tls.TLSSocket)
55
+ │ ├── NetworkTcpClient (net.connect, net.Socket)
56
+ │ └── NetworkTlsTcpClient (tls.connect, tls.TLSSocket)
18
57
 
19
58
  └── NetworkUdpClient
20
59
 
21
- AbstractNetworkFetchableHelper<V, RQ, RS> (implements IFetchable)
60
+ AbstractNetworkFetchableHelper<V, RQ, RS> (implements IFetchable, NOT a BaseHelper)
22
61
  ├── AxiosFetcher (V = 'axios')
23
62
  └── NodeFetcher (V = 'node-fetch')
24
63
  ```
25
64
 
26
- All classes that extend `BaseHelper` inherit scoped logging via `this.logger`.
65
+ Every class that extends `BaseHelper` inherits scoped logging via `this.logger`. `AbstractNetworkFetchableHelper` and its two fetchers do **not** extend `BaseHelper`. They accept an optional `logger` parameter per call instead - see [Request Logging and Redaction](#request-logging-and-redaction).
27
66
 
28
67
  ---
29
68
 
@@ -68,10 +107,10 @@ getRequestUrl(opts: {
68
107
 
69
108
  | Parameter | Type | Description |
70
109
  |-----------|------|-------------|
71
- | `baseUrl` | `string` | Overrides the instance's base URL. Falls back to `this.baseUrl` |
110
+ | `baseUrl` | `string` | Overrides the instance's base URL. Falls back to `this.baseUrl`. An explicit empty string does **not** fall back - it throws |
72
111
  | `paths` | `string[]` | Path segments to append. Each is prefixed with `/` if missing |
73
112
 
74
- **Throws:** `Error` with message `'[getRequestUrl] Invalid configuration for third party request base url!'` when both `opts.baseUrl` and `this.baseUrl` are empty.
113
+ **Throws:** `ApplicationError` (via `getError`, `statusCode: 500`) with message `'[getRequestUrl] Invalid configuration for third party request base url!'` when both `opts.baseUrl` and `this.baseUrl` resolve to empty.
75
114
 
76
115
  **Example:**
77
116
 
@@ -85,7 +124,7 @@ client.getRequestUrl({ baseUrl: 'https://other.api.com', paths: ['health'] });
85
124
 
86
125
  ##### `getRequestPath(opts)`
87
126
 
88
- Joins path segments, ensuring each starts with `/`.
127
+ Joins path segments, ensuring each starts with `/`. An empty `paths` array joins to `''`.
89
128
 
90
129
  ```typescript
91
130
  getRequestPath(opts: { paths: Array<string> }): string
@@ -108,7 +147,7 @@ getNetworkService(): IFetchable<T, IRequestOptions, TFetcherResponse<T>>
108
147
 
109
148
  ##### `getWorker()`
110
149
 
111
- Returns the raw HTTP client from the fetcher (`AxiosInstance` for Axios, `typeof fetch` for Node Fetch).
150
+ Returns the raw HTTP client from the fetcher (`AxiosInstance` for Axios, `typeof fetch` for Node Fetch). Delegates to `fetcher.getWorker()`.
112
151
 
113
152
  ```typescript
114
153
  getWorker(): TFetcherWorker<T>
@@ -130,24 +169,51 @@ interface IFetchable<
130
169
  put(opts: RQ, logger?: any): Promise<RS>;
131
170
  patch(opts: RQ, logger?: any): Promise<RS>;
132
171
  delete(opts: RQ, logger?: any): Promise<RS>;
172
+ query(opts: RQ, logger?: any): Promise<RS>;
173
+
133
174
  getWorker(): TFetcherWorker<V>;
134
175
  }
135
176
  ```
136
177
 
137
- All HTTP method shortcuts (`get`, `post`, `put`, `patch`, `delete`) delegate to `send()` with the `method` field set accordingly.
178
+ All HTTP method shortcuts (`get`, `post`, `put`, `patch`, `delete`, `query`) delegate to `send()` with the `method` field set accordingly. `query` sends the HTTP `QUERY` method ([RFC 9110/10008](https://www.ietf.org/archive/id/draft-ietf-httpbis-safe-method-w-body-10.html)). It behaves like `GET` but carries a body - useful for search payloads too large to fit a query string.
138
179
 
139
180
  ### IRequestOptions
140
181
 
141
182
  ```typescript
142
183
  interface IRequestOptions {
143
184
  url: string;
144
- params?: Record<string | symbol, any>;
145
- method?: string;
185
+ method?: THttpMethod;
186
+ params?: AnyObject;
146
187
  timeout?: number;
147
188
  [extra: symbol | string]: any;
148
189
  }
149
190
  ```
150
191
 
192
+ ### HTTP.Methods
193
+
194
+ The const-class every fetcher dispatches on:
195
+
196
+ ```typescript
197
+ HTTP.Methods = {
198
+ GET: 'get', POST: 'post', PUT: 'put', PATCH: 'patch',
199
+ DELETE: 'delete', HEAD: 'head', OPTIONS: 'options', QUERY: 'query',
200
+ } as const;
201
+
202
+ type THttpMethod = ValueOf<typeof HTTP.Methods> | Uppercase<ValueOf<typeof HTTP.Methods>>;
203
+ ```
204
+
205
+ > [!IMPORTANT]
206
+ > - **Every `HTTP.Methods` token is lowercase.** `@hono/zod-openapi` route definitions accept no other case.
207
+ > - **Both fetchers accept either case on input**, `'post'` or `'POST'`. Each calls `method.toUpperCase()` immediately before dispatching to its transport.
208
+ > - **This is not cosmetic.** Node's undici is the `fetch` implementation on Node - not Bun - and it auto-normalizes only some methods:
209
+ >
210
+ > | Auto-normalized by undici | Sent through verbatim |
211
+ > |---|---|
212
+ > | `DELETE`, `GET`, `HEAD`, `OPTIONS`, `POST`, `PUT` | `PATCH`, `QUERY` |
213
+ >
214
+ > A lowercase `patch` or `query` reaches the server unchanged, and most servers reject it.
215
+ > - **Bun and Axios hide the bug.** Bun's `fetch` and Axios both uppercase every method themselves - Axios via `node:http`. The bug surfaces only once the app runs on Node with undici.
216
+
151
217
  ---
152
218
 
153
219
  ### AbstractNetworkFetchableHelper
@@ -160,7 +226,7 @@ abstract class AbstractNetworkFetchableHelper<
160
226
  > implements IFetchable<V, RQ, RS>
161
227
  ```
162
228
 
163
- Abstract base for fetcher implementations. Provides convenience HTTP method wrappers and protocol detection.
229
+ Abstract base for fetcher implementations. Provides convenience HTTP method wrappers and protocol detection. Does **not** extend `BaseHelper` - it has no `this.logger`.
164
230
 
165
231
  #### Constructor
166
232
 
@@ -178,49 +244,22 @@ Subclasses must implement the actual request dispatch.
178
244
  abstract send(opts: RQ, logger?: any): Promise<RS>;
179
245
  ```
180
246
 
181
- ##### `get(opts, logger?)`
247
+ ##### `get(opts, logger?)` / `post(opts, logger?)` / `put(opts, logger?)` / `patch(opts, logger?)` / `delete(opts, logger?)` / `query(opts, logger?)`
182
248
 
183
249
  ```typescript
184
250
  get(opts: RQ, logger?: any): Promise<RS>
185
- ```
186
-
187
- Calls `send()` with `method: 'get'`.
188
-
189
- ##### `post(opts, logger?)`
190
-
191
- ```typescript
192
251
  post(opts: RQ, logger?: any): Promise<RS>
193
- ```
194
-
195
- Calls `send()` with `method: 'post'`.
196
-
197
- ##### `put(opts, logger?)`
198
-
199
- ```typescript
200
252
  put(opts: RQ, logger?: any): Promise<RS>
201
- ```
202
-
203
- Calls `send()` with `method: 'put'`.
204
-
205
- ##### `patch(opts, logger?)`
206
-
207
- ```typescript
208
253
  patch(opts: RQ, logger?: any): Promise<RS>
209
- ```
210
-
211
- Calls `send()` with `method: 'patch'`.
212
-
213
- ##### `delete(opts, logger?)`
214
-
215
- ```typescript
216
254
  delete(opts: RQ, logger?: any): Promise<RS>
255
+ query(opts: RQ, logger?: any): Promise<RS>
217
256
  ```
218
257
 
219
- Calls `send()` with `method: 'delete'`.
258
+ Each calls `send()` with `method` set to the matching `HTTP.Methods` token (`get` → `HTTP.Methods.GET`, ... `query` → `HTTP.Methods.QUERY`). Any other field on `opts` (`body`, `headers`, `params`, ...) passes through untouched.
220
259
 
221
260
  ##### `getProtocol(url)`
222
261
 
223
- Returns `'http'` or `'https'` based on the URL prefix.
262
+ Returns `HTTP.Protocols.HTTP` (`'http'`) if `url` starts with `'http:'`, otherwise `HTTP.Protocols.HTTPS` (`'https'`).
224
263
 
225
264
  ```typescript
226
265
  getProtocol(url: string): 'http' | 'https'
@@ -228,7 +267,7 @@ getProtocol(url: string): 'http' | 'https'
228
267
 
229
268
  ##### `getWorker()`
230
269
 
231
- Returns the underlying HTTP client instance.
270
+ Returns the underlying HTTP client instance (set by the concrete fetcher's constructor).
232
271
 
233
272
  ```typescript
234
273
  getWorker(): TFetcherWorker<V>
@@ -258,12 +297,14 @@ constructor(opts: {
258
297
  })
259
298
  ```
260
299
 
300
+ `opts.logger`, if provided, logs `'Creating new network request worker instance! Name: %s'` once at construction time. This is unrelated to the per-call `logger` argument on `send()`.
301
+
261
302
  #### IAxiosRequestOptions
262
303
 
263
304
  ```typescript
264
305
  interface IAxiosRequestOptions extends AxiosRequestConfig, IRequestOptions {
265
306
  url: string;
266
- method?: 'get' | 'post' | 'put' | 'patch' | 'delete' | 'options';
307
+ method?: THttpMethod;
267
308
  params?: AnyObject;
268
309
  body?: AnyObject; // Mapped to Axios `data`
269
310
  headers?: AnyObject;
@@ -271,7 +312,9 @@ interface IAxiosRequestOptions extends AxiosRequestConfig, IRequestOptions {
271
312
  ```
272
313
 
273
314
  > [!NOTE]
274
- > The `body` field is mapped to Axios's `data` field internally. Query parameters are serialized using `node:querystring`. For HTTPS URLs, an `https.Agent` is automatically created with `rejectUnauthorized` defaulting to `false`.
315
+ > - **`body` maps to Axios's `data`** field internally.
316
+ > - **Query `params` are serialized** using `node:querystring` via Axios's `paramsSerializer`.
317
+ > - **HTTPS gets an `https.Agent` automatically.** Certificate verification is ON, and connections are kept alive. Pass `rejectUnauthorized: false` - on the fetcher, for the whole instance, or on a single request - only when you genuinely mean to accept an unverified certificate. A caller-supplied `httpsAgent` always wins, so a custom CA, pinning or mTLS agent is honoured as given.
275
318
 
276
319
  #### Methods
277
320
 
@@ -281,7 +324,11 @@ interface IAxiosRequestOptions extends AxiosRequestConfig, IRequestOptions {
281
324
  override send<T = any>(opts: IAxiosRequestOptions, logger?: any): Promise<AxiosResponse<T>>
282
325
  ```
283
326
 
284
- Dispatches the request via the internal `axios` instance. For HTTPS URLs, automatically configures an `https.Agent`.
327
+ Dispatches the request via the internal `axios` instance.
328
+
329
+ - `method` defaults to `HTTP.Methods.GET` and is uppercased before dispatch.
330
+ - HTTPS URLs automatically get an `https.Agent` configured.
331
+ - If `logger` is passed, logs `'URL: %s | Props: %s'` at `info` level with the assembled request config run through `redactSecrets()`.
285
332
 
286
333
  ---
287
334
 
@@ -291,7 +338,7 @@ Dispatches the request via the internal `axios` instance. For HTTPS URLs, automa
291
338
  class AxiosNetworkRequest extends BaseNetworkRequest<'axios'>
292
339
  ```
293
340
 
294
- Pre-configured HTTP client using Axios.
341
+ Pre-configured HTTP client using Axios. Import only from the sub-path - `import { AxiosNetworkRequest } from '@venizia/ignis-helpers/axios'`.
295
342
 
296
343
  #### Constructor
297
344
 
@@ -317,7 +364,7 @@ interface IAxiosNetworkRequestOptions {
317
364
  | `validateStatus` | `(status) => status < 500` |
318
365
  | `timeout` | `60000` (1 minute) |
319
366
 
320
- User-provided values in `networkOptions` override all defaults.
367
+ User-provided values in `networkOptions` override all defaults. `networkOptions.baseUrl` maps to Axios's `baseURL`.
321
368
 
322
369
  ---
323
370
 
@@ -331,7 +378,7 @@ class NodeFetcher extends AbstractNetworkFetchableHelper<
331
378
  >
332
379
  ```
333
380
 
334
- Native `fetch` based fetcher implementation.
381
+ Native `fetch`-based fetcher implementation.
335
382
 
336
383
  #### Constructor
337
384
 
@@ -348,7 +395,8 @@ constructor(opts: {
348
395
  ```typescript
349
396
  interface INodeFetchRequestOptions extends RequestInit, IRequestOptions {
350
397
  url: string;
351
- params?: Record<string | symbol, any>;
398
+ method?: THttpMethod;
399
+ params?: AnyObject;
352
400
  }
353
401
  ```
354
402
 
@@ -360,7 +408,14 @@ interface INodeFetchRequestOptions extends RequestInit, IRequestOptions {
360
408
  override async send(opts: INodeFetchRequestOptions, logger?: any): Promise<Response>
361
409
  ```
362
410
 
363
- Dispatches the request using the native `fetch` API. If `timeout` is provided, creates an `AbortController` that aborts the request after the specified duration in milliseconds. Query `params` are serialized using `node:querystring` and appended to the URL.
411
+ Dispatches the request using the native `fetch` API. Behavior:
412
+
413
+ - `method` defaults to `HTTP.Methods.GET` and is uppercased before dispatch.
414
+ - Query `params` are serialized with `node:querystring` and appended to `url`. The separator adapts: `?` when the URL carries no query string yet, `&` when it already does - never a double `?`.
415
+ - If `timeout` is provided, an internal `AbortController` aborts the request after that many milliseconds.
416
+ - The internal timeout signal is **composed**, never substituted, with a caller-supplied `signal`. When both are present, IGNIS builds `AbortSignal.any([signal, timeoutController.signal])`. That way a caller aborting its own signal still cancels the request, even while a timeout is also armed.
417
+ - The timer is cleared as soon as the request settles.
418
+ - If `logger` is passed, logs `'URL: %s | Props: %s | Timeout: %s'` at `info` level with the request config run through `redactSecrets()`.
364
419
 
365
420
  ---
366
421
 
@@ -370,7 +425,7 @@ Dispatches the request using the native `fetch` API. If `timeout` is provided, c
370
425
  class NodeFetchNetworkRequest extends BaseNetworkRequest<'node-fetch'>
371
426
  ```
372
427
 
373
- Pre-configured HTTP client using native `fetch`.
428
+ Pre-configured HTTP client using native `fetch`. Exported from the root barrel - no extra dependency.
374
429
 
375
430
  #### Constructor
376
431
 
@@ -393,7 +448,36 @@ interface INodeFetchNetworkRequestOptions {
393
448
  |---------|---------|
394
449
  | `headers['content-type']` | `'application/json; charset=utf-8'` |
395
450
 
396
- If `headers` is a `Headers` instance, it is converted to a plain object via `Object.fromEntries()` before merging.
451
+ If `headers` is a `Headers` instance, it is converted to a plain object via `Object.fromEntries(headers.entries())` before merging with the default.
452
+
453
+ > [!WARNING] `timeout` is per-call, not per-instance
454
+ > `networkOptions` is `RequestInit`, which has no `timeout` field. Passing one there has no effect on request cancellation. `NodeFetcher.send()` only reads `timeout` from the arguments of each individual `send()`/`get()`/... call. Pass it every time you need an abort:
455
+ >
456
+ > ```typescript
457
+ > await this.getNetworkService().send({ url: '/slow-endpoint', method: 'get', timeout: 5000 });
458
+ > ```
459
+
460
+ ---
461
+
462
+ ### Request Logging and Redaction
463
+
464
+ Neither fetcher logs anything by default. `send()` and every shortcut accept an **optional** `logger` as the second argument, guarded internally with `logger?.for(...)`. Pass a logger to get an `info`-level line per request - typically `this.logger`, whether the caller is a `BaseHelper` subclass or extends `BaseNetworkRequest` directly:
465
+
466
+ ```typescript
467
+ await this.getNetworkService().post({ url, body }, this.logger);
468
+ ```
469
+
470
+ Whenever a logger is passed, IGNIS runs the assembled request config through `redactSecrets()` before the log line is written. That covers `url`, `method`, `headers`, `body`/`data`, and any other option. Redaction matches by key name, case-insensitively, at any depth, against `SECRET_KEY_PATTERN`:
471
+
472
+ | Key group | Matched spellings |
473
+ |-----------|--------------------|
474
+ | Options-object (camelCase) | `pass`, `password`, `passphrase`, `secret`, `token`, `apiKey`, `accessKey`, `secretKey`, `privateKey`, `key`, `cert`, `ca`, `pfx`, `credentials`, `authorization`, `auth`, `jwtSecret`, `applicationSecret`, `connectionString` |
475
+ | Options-object (snake_case) | `api_key`, `access_key`, `secret_key`, `private_key` |
476
+ | HTTP header spellings | `cookie`, `set-cookie`, `proxy-authorization`, `www-authenticate`, and any `(x-)?(api\|auth\|access\|secret\|session\|csrf\|xsrf)-(key\|token\|secret\|id)` pattern (e.g. `x-api-key`, `x-auth-token`, `x-csrf-token`) |
477
+
478
+ Source: [`redact.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/common/redact.ts) `SECRET_KEY_PATTERN`.
479
+
480
+ A matched value is replaced with `'[REDACTED]'`. `Buffer`/typed-array values under a non-matching key are summarized as `'[Binary N bytes]'` rather than serialized. There is nothing to configure beyond passing the logger - you never call `redactSecrets()` yourself at the call site.
397
481
 
398
482
  ---
399
483
 
@@ -417,9 +501,9 @@ Abstract TCP server with client tracking, authentication flow, and event delegat
417
501
  constructor(opts: ITcpSocketServerOptions<SocketServerOptions, SocketServerType, SocketClientType>)
418
502
  ```
419
503
 
420
- **Throws:** `Error` with message `'TCP Server | Invalid authenticate duration | Required duration for authenticateOptions'` when `authenticateOptions.required` is `true` and `duration` is missing or negative.
504
+ **Throws:** `ApplicationError` when `authenticateOptions.required` is `true` and `duration` is missing, `0`, or negative. Message: `'TCP Server | Invalid authenticate duration | Required duration for authenticateOptions'`.
421
505
 
422
- The constructor automatically calls `configure()`, which creates the server and starts listening.
506
+ The constructor calls `configure()`, which creates the server via `createServerFn` and starts listening.
423
507
 
424
508
  #### Protected Properties
425
509
 
@@ -430,13 +514,16 @@ The constructor automatically calls `configure()`, which creates the server and
430
514
  | `authenticateOptions` | `{ required: boolean; duration?: number }` | Auth settings |
431
515
  | `clients` | `Record<string, ITcpSocketClient<SocketClientType>>` | Connected client registry |
432
516
  | `server` | `SocketServerType` | The underlying server instance |
433
- | `extraEvents` | `Record<string, (opts) => void>` | Additional per-client socket events |
517
+ | `extraEvents` | `Record<string, (opts) => ValueOrPromise<void>>` | Additional per-client socket events to register |
518
+
519
+ - **Hooks never crash the process.** `onClientData`, `onClientConnected`, `onClientClose`, `onClientError`, `onServerReady`, `onServerError`, and each `extraEvents` entry all run through an internal `invokeHook()` wrapper.
520
+ - **Why it exists.** A hook throwing synchronously inside a raw `net`/`tls` event listener would otherwise be an uncaught exception. That crashes the process. `invokeHook()` catches the throw and logs it instead.
434
521
 
435
522
  #### Methods
436
523
 
437
524
  ##### `configure()`
438
525
 
439
- Creates the server using `createServerFn` and starts listening. Called automatically by the constructor.
526
+ Creates the server using `createServerFn`, registers a server-level `error` listener (routed to `onServerError`, never left to crash the process), and starts listening. Called automatically by the constructor.
440
527
 
441
528
  ```typescript
442
529
  configure(): void
@@ -444,39 +531,29 @@ configure(): void
444
531
 
445
532
  ##### `onNewConnection(opts)`
446
533
 
447
- Handles a new client connection. Assigns a unique ID, registers `data`, `error`, `close`, and extra events, tracks the client, and starts the authentication timer if required.
534
+ Handles a new client connection:
535
+
536
+ - Assigns a unique ID via `getUID()`.
537
+ - Registers `data`/`error`/`close`/`extraEvents` listeners on the socket.
538
+ - Tracks the client in the `clients` registry.
539
+ - Invokes `onClientConnected`.
540
+ - Starts the authentication kick-timer when `authenticateOptions.required` is `true`.
448
541
 
449
542
  ```typescript
450
543
  onNewConnection(opts: { socket: SocketClientType }): void
451
544
  ```
452
545
 
453
- ##### `getClients()`
454
-
455
- Returns all connected clients as a record keyed by client ID.
546
+ ##### `getClients()` / `getClient(opts)` / `getServer()`
456
547
 
457
548
  ```typescript
458
549
  getClients(): Record<string, ITcpSocketClient<SocketClientType>>
459
- ```
460
-
461
- ##### `getClient(opts)`
462
-
463
- Returns a specific connected client by ID, or `undefined` if not found.
464
-
465
- ```typescript
466
550
  getClient(opts: { id: string }): ITcpSocketClient<SocketClientType> | undefined
467
- ```
468
-
469
- ##### `getServer()`
470
-
471
- Returns the underlying server instance.
472
-
473
- ```typescript
474
551
  getServer(): SocketServerType
475
552
  ```
476
553
 
477
554
  ##### `doAuthenticate(opts)`
478
555
 
479
- Transitions a client's authentication state. Sets `authenticatedAt` timestamp when state becomes `'authenticated'`, clears it otherwise.
556
+ Transitions a client's authentication state.
480
557
 
481
558
  ```typescript
482
559
  doAuthenticate(opts: {
@@ -485,14 +562,45 @@ doAuthenticate(opts: {
485
562
  }): void
486
563
  ```
487
564
 
565
+ | New state | Effect |
566
+ |---|---|
567
+ | `'authenticated'` | Sets `storage.authenticatedAt`; clears the pending kick-timer |
568
+ | `'unauthorized'` / `'authenticating'` | Clears `storage.authenticatedAt` |
569
+
488
570
  ##### `emit(opts)`
489
571
 
490
- Writes data to a specific client's socket. Silently returns (with a log warning) if the client is not found, the socket is not writable, or the payload is empty.
572
+ Writes data to a specific client's socket. Never throws - each failure case logs and returns instead:
573
+
574
+ | Condition | Log level |
575
+ |-----------|-----------|
576
+ | Client not found for `clientId` | `error` |
577
+ | Socket not writable | `error` |
578
+ | Payload empty (`!payload?.length`) | `info` |
491
579
 
492
580
  ```typescript
493
581
  emit(opts: { clientId: string; payload: Buffer | string }): void
494
582
  ```
495
583
 
584
+ ##### `shutdown()`
585
+
586
+ Tears the server down completely and resolves even while clients are still attached.
587
+
588
+ ```typescript
589
+ async shutdown(): Promise<void>
590
+ ```
591
+
592
+ **Order of operations:**
593
+
594
+ 1. Clears every client's pending authenticate kick-timer.
595
+ 2. Destroys every client socket.
596
+ 3. Empties the `clients` registry.
597
+ 4. Calls `server.close()` and awaits its callback.
598
+
599
+ - **Why this order.** `server.close()` alone never resolves while a socket is still attached. A caller reaching through `getServer().close()` on a busy server would hang forever.
600
+ - **Idempotent.** A second call is a no-op that resolves cleanly.
601
+ - **Safe on a server that never finished `listen()`.** Logs the resulting `ERR_SERVER_NOT_RUNNING` rather than throwing.
602
+ - **After `shutdown()`**, new connection attempts are refused.
603
+
496
604
  ---
497
605
 
498
606
  ### ITcpSocketClient
@@ -506,6 +614,7 @@ interface ITcpSocketClient<SocketClientType> {
506
614
  storage: {
507
615
  connectedAt: dayjs.Dayjs;
508
616
  authenticatedAt: dayjs.Dayjs | null;
617
+ authenticateTimeout?: ReturnType<typeof setTimeout> | null;
509
618
  [additionField: symbol | string]: any;
510
619
  };
511
620
  }
@@ -527,14 +636,12 @@ Plain TCP server using `net.createServer`.
527
636
  constructor(opts: Omit<ITcpSocketServerOptions, 'createServerFn'>)
528
637
  ```
529
638
 
530
- The `createServerFn` is pre-set to `net.createServer`. The `scope` is set to `'NetworkTcpServer'`.
639
+ The `createServerFn` is pre-set to `net.createServer`. `scope` is hardcoded to `'NetworkTcpServer'`, overriding any `opts.scope`.
531
640
 
532
641
  #### Static Methods
533
642
 
534
643
  ##### `newInstance(opts)`
535
644
 
536
- Factory method that creates a new `NetworkTcpServer`.
537
-
538
645
  ```typescript
539
646
  static newInstance(
540
647
  opts: Omit<ITcpSocketServerOptions, 'createServerFn'>
@@ -554,10 +661,10 @@ TLS-encrypted TCP server using `tls.createServer`.
554
661
  #### Constructor
555
662
 
556
663
  ```typescript
557
- constructor(opts: Omit<ITcpSocketServerOptions, 'createServerFn'>)
664
+ constructor(opts: Omit<ITcpSocketServerOptions<TlsOptions, tls.Server, TLSSocket>, 'createServerFn'>)
558
665
  ```
559
666
 
560
- The `createServerFn` is pre-set to `tls.createServer`. The `scope` is set to `'NetworkTlsTcpServer'`. Pass TLS certificates and keys in `serverOptions` (type `TlsOptions` from `node:tls`).
667
+ The `createServerFn` is pre-set to `tls.createServer`. `scope` is hardcoded to `'NetworkTlsTcpServer'`. Pass TLS certificates and keys in `serverOptions` (type `TlsOptions` from `node:tls`). Every method, including `shutdown()`, is identical to `NetworkTcpServer`.
561
668
 
562
669
  #### Static Methods
563
670
 
@@ -565,7 +672,7 @@ The `createServerFn` is pre-set to `tls.createServer`. The `scope` is set to `'N
565
672
 
566
673
  ```typescript
567
674
  static newInstance(
568
- opts: Omit<ITcpSocketServerOptions, 'createServerFn'>
675
+ opts: Omit<ITcpSocketServerOptions<TlsOptions, tls.Server, TLSSocket>, 'createServerFn'>
569
676
  ): NetworkTlsTcpServer
570
677
  ```
571
678
 
@@ -588,21 +695,38 @@ Abstract TCP client with auto-reconnect, encoding support, and lifecycle hooks.
588
695
  constructor(opts: INetworkTcpClientProps<SocketClientOptions, SocketClientType>)
589
696
  ```
590
697
 
698
+ Does **not** call `connect()` automatically. Construction only stores options - call `connect({ resetReconnectCounter })` explicitly.
699
+
591
700
  #### Protected Properties
592
701
 
593
702
  | Property | Type | Description |
594
703
  |----------|------|-------------|
595
- | `client` | `SocketClientType \| null` | The underlying socket, or `null` when disconnected |
704
+ | `client` | `SocketClientType \| null` | The underlying socket, or `null`/`undefined` when disconnected |
596
705
  | `options` | `SocketClientOptions` | Connection options |
597
706
  | `reconnect` | `boolean` | Whether auto-reconnect is enabled (default: `false`) |
598
707
  | `retry` | `{ maxReconnect: number; currentReconnect: number }` | Reconnect state. `maxReconnect` defaults to `5` |
599
708
  | `encoding` | `BufferEncoding \| undefined` | Socket encoding |
600
709
 
710
+ ##### `getLoggableOptions()`
711
+
712
+ ```typescript
713
+ protected getLoggableOptions(): unknown
714
+ ```
715
+
716
+ Returns `redactSecrets(this.options)`. A TLS client's `options` **is** its private key material - `key`/`cert`/`passphrase`. Every internal log call uses this method instead of logging `this.options` directly, or the key would be written to every log file and aggregator downstream.
717
+
601
718
  #### Methods
602
719
 
603
720
  ##### `connect(opts)`
604
721
 
605
- Establishes the connection. If already connected, logs and returns. Creates the socket using `createClientFn`, registers `data`, `close`, and `error` events, and applies encoding if set.
722
+ Establishes the connection:
723
+
724
+ - No-op with a log line if already connected (`isConnected()`) or if `options` is empty.
725
+ - Otherwise, in order:
726
+ 1. Destroys any stale `client` first.
727
+ 2. Creates the socket via `createClientFn`.
728
+ 3. Registers `data`/`close`/`error` listeners.
729
+ 4. Applies `encoding`, if set.
606
730
 
607
731
  ```typescript
608
732
  connect(opts: { resetReconnectCounter: boolean }): void
@@ -610,11 +734,11 @@ connect(opts: { resetReconnectCounter: boolean }): void
610
734
 
611
735
  | Parameter | Type | Description |
612
736
  |-----------|------|-------------|
613
- | `resetReconnectCounter` | `boolean` | If `true`, resets `retry.currentReconnect` to `0` |
737
+ | `resetReconnectCounter` | `boolean` | If `true`, resets `retry.currentReconnect` to `0` before connecting |
614
738
 
615
739
  ##### `disconnect()`
616
740
 
617
- Destroys the socket, clears the reconnect timeout, and sets `client` to `null`.
741
+ Destroys the socket, clears the reconnect timeout, and sets `client` to `null`. No-op with a log line if `client` is not set.
618
742
 
619
743
  ```typescript
620
744
  disconnect(): void
@@ -630,7 +754,7 @@ forceReconnect(): void
630
754
 
631
755
  ##### `isConnected()`
632
756
 
633
- Returns a truthy value if the client exists and its `readyState` is not `'closed'`.
757
+ Returns a truthy value if `client` exists and its `readyState` is not `'closed'`.
634
758
 
635
759
  ```typescript
636
760
  isConnected(): SocketClientType | null | undefined
@@ -638,7 +762,7 @@ isConnected(): SocketClientType | null | undefined
638
762
 
639
763
  ##### `emit(opts)`
640
764
 
641
- Writes data to the server. Silently returns (with a log) if the client is not initialized or the payload is empty.
765
+ Writes data to the server. Logs and returns without throwing if `client` is not initialized or the payload is empty.
642
766
 
643
767
  ```typescript
644
768
  emit(opts: { payload: Buffer | string }): void
@@ -646,43 +770,36 @@ emit(opts: { payload: Buffer | string }): void
646
770
 
647
771
  ##### `getClient()`
648
772
 
649
- Returns the underlying socket instance, or `null`/`undefined` if not connected.
650
-
651
773
  ```typescript
652
774
  getClient(): SocketClientType | null | undefined
653
775
  ```
654
776
 
655
- ##### `handleConnected()`
656
-
657
- Default connection handler. Logs the connection and resets the reconnect counter.
658
-
659
- ```typescript
660
- handleConnected(): void
661
- ```
662
-
663
- ##### `handleData(_opts)`
777
+ ##### `handleConnected()` / `handleData(_opts)` / `handleClosed()` / `handleError(error)`
664
778
 
665
- Default data handler. No-op.
779
+ Default handlers used when the matching `onConnected`/`onData`/`onClosed`/`onError` option is omitted.
666
780
 
667
781
  ```typescript
668
- handleData(_opts: { identifier: string; message: string | Buffer }): void
782
+ handleConnected(): void // Logs, resets retry.currentReconnect to 0
783
+ handleData(_opts: { identifier: string; message: string | Buffer }): void // No-op
784
+ handleClosed(): void // Logs the closure
785
+ handleError(error: any): void // Logs; schedules a reconnect if eligible
669
786
  ```
670
787
 
671
- ##### `handleClosed()`
788
+ **Reconnect gate on `handleError`:**
672
789
 
673
- Default close handler. Logs the closure.
790
+ | Condition | Result |
791
+ |-----------|--------|
792
+ | `reconnect` is `false` | No reconnect - the first guard returns immediately |
793
+ | `retry.currentReconnect >= retry.maxReconnect` | No reconnect - the first guard returns immediately |
794
+ | `maxReconnect === -1` | **No reconnect, ever.** `currentReconnect` starts at `0`, and `0 >= -1` is already true, so the first guard returns before any attempt is made |
795
+ | `reconnect` is `true` and `currentReconnect < maxReconnect` (with `maxReconnect >= 0`) | Reconnect scheduled |
674
796
 
675
- ```typescript
676
- handleClosed(): void
677
- ```
678
-
679
- ##### `handleError(error)`
680
-
681
- Default error handler. Logs the error. If `reconnect` is enabled and the retry limit has not been reached, schedules a reconnect after 5 seconds.
797
+ > [!IMPORTANT]
798
+ > - **`maxReconnect: -1` does not mean unlimited reconnects - it disables reconnection entirely.** That is the opposite of the "`-1` = unlimited" convention used elsewhere in the framework - the Redis retry helper, for example.
799
+ > - **A second guard further down the method is dead code.** `if (maxReconnect > -1 && currentReconnect >= maxReconnect)` can never be true. By the time control reaches it, the first guard has already ruled out `currentReconnect >= maxReconnect`.
800
+ > - Source: [`base-tcp-client.helper.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/modules/network/tcp-socket/base-tcp-client.helper.ts).
682
801
 
683
- ```typescript
684
- handleError(error: any): void
685
- ```
802
+ The reconnect delay is a **fixed 5000 ms**. There is no backoff growth on the TCP/TLS client, unlike the Redis helper's exponential strategy.
686
803
 
687
804
  ---
688
805
 
@@ -702,7 +819,7 @@ constructor(
702
819
  )
703
820
  ```
704
821
 
705
- The `createClientFn` is pre-set to `net.connect`. The `scope` is set to `'NetworkTcpClient'`.
822
+ The `createClientFn` is pre-set to `net.connect`. `scope` is hardcoded to `'NetworkTcpClient'`.
706
823
 
707
824
  #### Static Methods
708
825
 
@@ -732,7 +849,7 @@ constructor(
732
849
  )
733
850
  ```
734
851
 
735
- The `createClientFn` is pre-set to `tls.connect`. The `scope` is set to `'NetworkTlsTcpClient'`. Pass TLS certificates and keys in `options` (type `ConnectionOptions` from `node:tls`).
852
+ The `createClientFn` is pre-set to `tls.connect`. `scope` is hardcoded to `'NetworkTlsTcpClient'`. Pass TLS certificates and keys in `options` (type `ConnectionOptions` from `node:tls`). Every method is identical to `NetworkTcpClient`.
736
853
 
737
854
  #### Static Methods
738
855
 
@@ -754,7 +871,7 @@ static newInstance(
754
871
  class NetworkUdpClient extends BaseHelper
755
872
  ```
756
873
 
757
- UDP datagram client with multicast support, using `node:dgram` internally (UDP4).
874
+ UDP datagram client with multicast support, using `node:dgram` internally (`type: 'udp4'`). No client/server split - one class handles both send and receive. `scope` is always hardcoded to `'NetworkUdpClient'` (no `scope` option exists on `INetworkUdpClientProps`).
758
875
 
759
876
  #### Constructor
760
877
 
@@ -762,41 +879,12 @@ UDP datagram client with multicast support, using `node:dgram` internally (UDP4)
762
879
  constructor(opts: INetworkUdpClientProps)
763
880
  ```
764
881
 
765
- ```typescript
766
- interface INetworkUdpClientProps {
767
- identifier: string;
768
- host?: string;
769
- port: number;
770
- reuseAddr?: boolean;
771
- multicastAddress?: {
772
- groups?: Array<string>;
773
- interface?: string;
774
- };
775
- onConnected?: (opts: { identifier: string; host?: string; port: number }) => void;
776
- onData?: (opts: {
777
- identifier: string;
778
- message: string | Buffer;
779
- remoteInfo: dgram.RemoteInfo;
780
- }) => void;
781
- onClosed?: (opts: { identifier: string; host?: string; port: number }) => void;
782
- onError?: (opts: { identifier: string; host?: string; port: number; error: Error }) => void;
783
- onBind?: (opts: {
784
- identifier: string;
785
- socket: dgram.Socket;
786
- host?: string;
787
- port: number;
788
- reuseAddr?: boolean;
789
- multicastAddress?: { groups?: Array<string>; interface?: string };
790
- }) => ValueOrPromise<void>;
791
- }
792
- ```
882
+ Construction only stores options; call `connect()` explicitly to bind the socket.
793
883
 
794
884
  #### Static Methods
795
885
 
796
886
  ##### `newInstance(opts)`
797
887
 
798
- Factory method that creates a new `NetworkUdpClient`.
799
-
800
888
  ```typescript
801
889
  static newInstance(opts: INetworkUdpClientProps): NetworkUdpClient
802
890
  ```
@@ -805,17 +893,23 @@ static newInstance(opts: INetworkUdpClientProps): NetworkUdpClient
805
893
 
806
894
  ##### `connect()`
807
895
 
808
- Creates a `dgram.Socket` (type `'udp4'`), registers `close`, `error`, `listening`, and `message` events, then binds to the configured `port` and `host`. The `onBind` callback is invoked after binding completes -- use it to join multicast groups.
896
+ Creates a `dgram.Socket` and binds it, in order:
897
+
898
+ 1. Creates the socket (`type: 'udp4'`, `reuseAddr` from options).
899
+ 2. Registers `close`/`error`/`listening`/`message` listeners.
900
+ 3. Binds to `port`/`host`.
901
+
902
+ Each listener routes through an internal `invokeHook()` wrapper - the same synchronous-throw guard as the TCP server. `onBind` fires after binding completes; it's the place to join multicast groups via `socket.addMembership(group, iface)`.
809
903
 
810
904
  ```typescript
811
905
  connect(): void
812
906
  ```
813
907
 
814
- If the client is already initialized, logs a message and returns. If `port` is not set, logs a message and returns.
908
+ No-op with a log line in two cases: `client` is already set, or `port` fails `Number.isInteger(port) && port >= 0`. Port `0` itself is valid - it means "let the OS assign a free port" - and is accepted.
815
909
 
816
910
  ##### `disconnect()`
817
911
 
818
- Closes the underlying `dgram.Socket` and sets the client to `null`.
912
+ Closes the socket and sets `client` to `null`. No-op with a log line if `client` is not set.
819
913
 
820
914
  ```typescript
821
915
  disconnect(): void
@@ -823,7 +917,7 @@ disconnect(): void
823
917
 
824
918
  ##### `isConnected()`
825
919
 
826
- Returns the underlying socket if connected, or `null`/`undefined` if not.
920
+ Returns the underlying socket if bound, or `null`/`undefined` otherwise.
827
921
 
828
922
  ```typescript
829
923
  isConnected(): dgram.Socket | null | undefined
@@ -831,45 +925,25 @@ isConnected(): dgram.Socket | null | undefined
831
925
 
832
926
  ##### `getClient()`
833
927
 
834
- Returns the underlying `dgram.Socket` instance, or `null`/`undefined` if not connected.
835
-
836
928
  ```typescript
837
929
  getClient(): dgram.Socket | null | undefined
838
930
  ```
839
931
 
840
- ##### `handleConnected()`
841
-
842
- Default connection handler. Logs the bind success with host, port, and multicast address.
843
-
844
- ```typescript
845
- handleConnected(): void
846
- ```
847
-
848
- ##### `handleData(opts)`
849
-
850
- Default data handler. Logs the received message and remote info.
851
-
852
- ```typescript
853
- handleData(opts: {
854
- identifier: string;
855
- message: string | Buffer;
856
- remoteInfo: dgram.RemoteInfo;
857
- }): void
858
- ```
932
+ ##### `handleConnected()` / `handleData(opts)` / `handleClosed()` / `handleError(opts)`
859
933
 
860
- ##### `handleClosed()`
934
+ Default handlers used when the matching `onConnected`/`onData`/`onClosed`/`onError` option is omitted:
861
935
 
862
- Default close handler. Logs the closure with host and port.
936
+ | Handler | Log level | Logged context |
937
+ |---------|-----------|-----------------|
938
+ | `handleConnected` | `info` | `host`, `port`, `multicastAddress` |
939
+ | `handleClosed` | `info` | `host`, `port`, `multicastAddress` |
940
+ | `handleData` | `info` | `host`, `port` only - no `multicastAddress` |
941
+ | `handleError` | `error` | `host`, `port` only - no `multicastAddress` |
863
942
 
864
943
  ```typescript
944
+ handleConnected(): void
945
+ handleData(opts: { identifier: string; message: string | Buffer; remoteInfo: dgram.RemoteInfo }): void
865
946
  handleClosed(): void
866
- ```
867
-
868
- ##### `handleError(opts)`
869
-
870
- Default error handler. Logs the error with host and port.
871
-
872
- ```typescript
873
947
  handleError(opts: { identifier: string; error: Error }): void
874
948
  ```
875
949
 
@@ -877,24 +951,24 @@ handleError(opts: { identifier: string; error: Error }): void
877
951
 
878
952
  ## Types Reference
879
953
 
880
- ### TFetcherVariant
954
+ ### TFetcherVariant / TFetcherResponse / TFetcherWorker
881
955
 
882
956
  ```typescript
883
957
  type TFetcherVariant = 'node-fetch' | 'axios';
884
- ```
885
958
 
886
- ### TFetcherResponse
887
-
888
- ```typescript
889
959
  type TFetcherResponse<T extends TFetcherVariant> =
890
960
  T extends 'node-fetch' ? Response : AxiosResponse;
961
+
962
+ type TFetcherWorker<T extends TFetcherVariant> =
963
+ T extends 'axios' ? AxiosInstance : typeof fetch;
891
964
  ```
892
965
 
893
- ### TFetcherWorker
966
+ ### THttpMethod
894
967
 
895
968
  ```typescript
896
- type TFetcherWorker<T extends TFetcherVariant> =
897
- T extends 'axios' ? AxiosInstance : typeof fetch;
969
+ type THttpMethod = ValueOf<typeof HTTP.Methods> | Uppercase<ValueOf<typeof HTTP.Methods>>;
970
+ // 'get' | 'post' | 'put' | 'patch' | 'delete' | 'head' | 'options' | 'query'
971
+ // | 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'QUERY'
898
972
  ```
899
973
 
900
974
  ### ITcpSocketServerOptions
@@ -907,25 +981,32 @@ interface ITcpSocketServerOptions<
907
981
  > {
908
982
  scope?: string;
909
983
  identifier: string;
984
+
910
985
  serverOptions: Partial<SocketServerOptions>;
911
986
  listenOptions: Partial<ListenOptions>;
912
987
  authenticateOptions: { required: boolean; duration?: number };
988
+
913
989
  extraEvents?: Record<
914
990
  string,
915
991
  (opts: { id: string; socket: SocketClientType; args: any }) => ValueOrPromise<void>
916
992
  >;
993
+
917
994
  createServerFn: (
918
995
  options: Partial<SocketServerOptions>,
919
996
  connectionListener: (socket: SocketClientType) => void,
920
997
  ) => SocketServerType;
998
+
921
999
  onServerReady?: (opts: { server: SocketServerType }) => void;
922
1000
  onClientConnected?: (opts: { id: string; socket: SocketClientType }) => void;
923
1001
  onClientData?: (opts: { id: string; socket: SocketClientType; data: Buffer | string }) => void;
924
1002
  onClientClose?: (opts: { id: string; socket: SocketClientType }) => void;
925
1003
  onClientError?: (opts: { id: string; socket: SocketClientType; error: Error }) => void;
1004
+ onServerError?: (opts: { server: SocketServerType; error: Error }) => void;
926
1005
  }
927
1006
  ```
928
1007
 
1008
+ `onServerError` fires when the underlying `net`/`tls` server emits `'error'` - for example `EADDRINUSE` from a port already in use. Without this listener, the event is unhandled and takes the whole process down with it.
1009
+
929
1010
  ### INetworkTcpClientProps
930
1011
 
931
1012
  ```typescript
@@ -981,6 +1062,6 @@ interface INetworkUdpClientProps {
981
1062
  }
982
1063
  ```
983
1064
 
984
- ## See Also
1065
+ ## See also
985
1066
 
986
- - [Setup & Usage](./) -- Getting started and examples
1067
+ - [Network overview](/extensions/helpers/network/) - introduction and the most common tasks