@venizia/ignis-docs 0.2.0 → 0.2.1-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/README.md +14 -14
  2. package/content/best-practices/api-usage-examples.md +39 -19
  3. package/content/best-practices/architectural-patterns.md +22 -11
  4. package/content/best-practices/architecture-decisions.md +29 -16
  5. package/content/best-practices/code-style-standards/advanced-patterns.md +43 -31
  6. package/content/best-practices/code-style-standards/constants-configuration.md +19 -4
  7. package/content/best-practices/code-style-standards/control-flow.md +33 -1
  8. package/content/best-practices/code-style-standards/documentation.md +28 -8
  9. package/content/best-practices/code-style-standards/function-patterns.md +15 -4
  10. package/content/best-practices/code-style-standards/index.md +7 -2
  11. package/content/best-practices/code-style-standards/naming-conventions.md +26 -2
  12. package/content/best-practices/code-style-standards/route-definitions.md +9 -5
  13. package/content/best-practices/code-style-standards/tooling.md +14 -1
  14. package/content/best-practices/code-style-standards/type-safety.md +39 -6
  15. package/content/best-practices/common-pitfalls.md +59 -35
  16. package/content/best-practices/contribution-workflow.md +6 -2
  17. package/content/best-practices/data-modeling.md +78 -62
  18. package/content/best-practices/deployment-strategies.md +56 -19
  19. package/content/best-practices/error-handling.md +182 -93
  20. package/content/best-practices/index.md +6 -0
  21. package/content/best-practices/performance-optimization.md +26 -13
  22. package/content/best-practices/security-guidelines.md +35 -9
  23. package/content/best-practices/testing-strategies.md +7 -2
  24. package/content/best-practices/troubleshooting-tips.md +27 -17
  25. package/content/extensions/components/api-reference.md +107 -322
  26. package/content/extensions/components/authentication/api.md +454 -603
  27. package/content/extensions/components/authentication/errors.md +121 -498
  28. package/content/extensions/components/authentication/index.md +88 -801
  29. package/content/extensions/components/authentication/usage.md +207 -956
  30. package/content/extensions/components/authorization/api.md +736 -656
  31. package/content/extensions/components/authorization/errors.md +168 -206
  32. package/content/extensions/components/authorization/index.md +82 -797
  33. package/content/extensions/components/authorization/usage.md +194 -527
  34. package/content/extensions/components/health-check.md +71 -243
  35. package/content/extensions/components/mail/api.md +504 -287
  36. package/content/extensions/components/mail/errors.md +73 -61
  37. package/content/extensions/components/mail/index.md +96 -467
  38. package/content/extensions/components/mail/usage.md +130 -172
  39. package/content/extensions/components/request-tracker.md +66 -173
  40. package/content/extensions/components/socket-io/api.md +195 -13
  41. package/content/extensions/components/socket-io/errors.md +3 -3
  42. package/content/extensions/components/socket-io/index.md +50 -337
  43. package/content/extensions/components/socket-io/usage.md +143 -26
  44. package/content/extensions/components/static-asset/api.md +410 -142
  45. package/content/extensions/components/static-asset/errors.md +110 -53
  46. package/content/extensions/components/static-asset/index.md +79 -608
  47. package/content/extensions/components/static-asset/usage.md +180 -300
  48. package/content/extensions/components/websocket/api.md +275 -399
  49. package/content/extensions/components/websocket/errors.md +47 -56
  50. package/content/extensions/components/websocket/index.md +74 -407
  51. package/content/extensions/components/websocket/usage.md +110 -341
  52. package/content/extensions/helpers/cron/index.md +51 -160
  53. package/content/extensions/helpers/crypto/index.md +62 -483
  54. package/content/extensions/helpers/crypto/reference.md +456 -0
  55. package/content/extensions/helpers/env/index.md +60 -178
  56. package/content/extensions/helpers/error/index.md +221 -207
  57. package/content/extensions/helpers/inversion/index.md +65 -556
  58. package/content/extensions/helpers/inversion/reference.md +522 -0
  59. package/content/extensions/helpers/kafka/admin.md +20 -1
  60. package/content/extensions/helpers/kafka/compile-binary.md +41 -35
  61. package/content/extensions/helpers/kafka/consumer.md +54 -20
  62. package/content/extensions/helpers/kafka/examples.md +21 -16
  63. package/content/extensions/helpers/kafka/index.md +80 -610
  64. package/content/extensions/helpers/kafka/producer.md +134 -5
  65. package/content/extensions/helpers/kafka/schema-registry.md +45 -70
  66. package/content/extensions/helpers/logger/hf-logger.md +193 -0
  67. package/content/extensions/helpers/logger/index.md +64 -563
  68. package/content/extensions/helpers/logger/pino.md +85 -0
  69. package/content/extensions/helpers/logger/reference.md +746 -0
  70. package/content/extensions/helpers/network/api.md +241 -195
  71. package/content/extensions/helpers/network/index.md +72 -530
  72. package/content/extensions/helpers/queue/index.md +72 -900
  73. package/content/extensions/helpers/queue/reference.md +467 -0
  74. package/content/extensions/helpers/redis/index.md +73 -645
  75. package/content/extensions/helpers/redis/reference.md +727 -0
  76. package/content/extensions/helpers/secrets/index.md +66 -0
  77. package/content/extensions/helpers/socket-io/api.md +305 -203
  78. package/content/extensions/helpers/socket-io/index.md +66 -432
  79. package/content/extensions/helpers/storage/api.md +564 -462
  80. package/content/extensions/helpers/storage/index.md +77 -573
  81. package/content/extensions/helpers/types/index.md +66 -499
  82. package/content/extensions/helpers/types/reference.md +650 -0
  83. package/content/extensions/helpers/uid/index.md +58 -227
  84. package/content/extensions/helpers/websocket/api.md +329 -216
  85. package/content/extensions/helpers/websocket/index.md +65 -503
  86. package/content/extensions/helpers/worker-thread/index.md +58 -396
  87. package/content/extensions/helpers/worker-thread/reference.md +428 -0
  88. package/content/guides/core-concepts/persistent/models.md +1 -1
  89. package/content/guides/core-concepts/persistent/search-typesense.md +3 -3
  90. package/content/guides/core-concepts/persistent/transactions.md +1 -1
  91. package/content/guides/core-concepts/secrets-vault.md +177 -0
  92. package/content/guides/core-concepts/services.md +1 -1
  93. package/content/guides/migrations/redis-helpers-migration.md +1 -1
  94. package/content/guides/migrations/unified-connectors-migration.md +2 -2
  95. package/content/guides/tutorials/ecommerce-api.md +3 -8
  96. package/content/references/base/application.md +1 -1
  97. package/content/references/base/connectors.md +79 -136
  98. package/content/references/base/datasources-reference.md +599 -0
  99. package/content/references/base/datasources.md +84 -444
  100. package/content/references/base/dependency-injection.md +17 -39
  101. package/content/references/base/filter-system/application-usage.md +69 -121
  102. package/content/references/base/filter-system/array-operators.md +12 -0
  103. package/content/references/base/filter-system/comparison-operators.md +12 -0
  104. package/content/references/base/filter-system/default-filter.md +136 -348
  105. package/content/references/base/filter-system/fields-order-pagination.md +38 -16
  106. package/content/references/base/filter-system/index.md +106 -257
  107. package/content/references/base/filter-system/json-filtering.md +12 -2
  108. package/content/references/base/filter-system/list-operators.md +16 -2
  109. package/content/references/base/filter-system/logical-operators.md +13 -0
  110. package/content/references/base/filter-system/null-operators.md +13 -0
  111. package/content/references/base/filter-system/pattern-matching.md +12 -0
  112. package/content/references/base/filter-system/quick-reference.md +11 -2
  113. package/content/references/base/filter-system/range-operators.md +12 -0
  114. package/content/references/base/filter-system/tips.md +70 -133
  115. package/content/references/base/filter-system/use-cases.md +156 -233
  116. package/content/references/base/middlewares.md +35 -21
  117. package/content/references/base/models-reference.md +886 -0
  118. package/content/references/base/models.md +80 -1452
  119. package/content/references/base/repositories/advanced.md +156 -192
  120. package/content/references/base/repositories/index.md +77 -650
  121. package/content/references/base/repositories/mixins.md +22 -18
  122. package/content/references/base/repositories/relations.md +123 -171
  123. package/content/references/base/repositories/soft-deletable.md +58 -56
  124. package/content/references/base/secrets.md +263 -0
  125. package/content/references/base/services.md +2 -2
  126. package/content/references/configuration/environment-variables.md +48 -4
  127. package/content/references/configuration/index.md +49 -31
  128. package/content/references/quick-reference.md +3 -16
  129. package/content/references/utilities/crypto.md +35 -76
  130. package/content/references/utilities/date.md +33 -73
  131. package/content/references/utilities/index.md +1 -1
  132. package/content/references/utilities/jsx-reference.md +298 -0
  133. package/content/references/utilities/jsx.md +82 -525
  134. package/content/references/utilities/module.md +29 -62
  135. package/content/references/utilities/parse.md +34 -64
  136. package/content/references/utilities/performance.md +33 -58
  137. package/content/references/utilities/promise.md +28 -62
  138. package/content/references/utilities/request.md +57 -218
  139. package/content/references/utilities/schema.md +43 -137
  140. package/content/references/utilities/statuses-reference.md +361 -0
  141. package/content/references/utilities/statuses.md +63 -667
  142. package/package.json +8 -8
@@ -1,4 +1,29 @@
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
+ **Files:**
12
+
13
+ - [`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`
14
+ - [`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`
15
+ - [`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`
16
+ - [`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)
17
+ - [`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`
18
+ - [`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`
19
+ - [`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`
20
+ - [`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`
21
+ - [`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`
22
+ - [`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`
23
+ - [`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`
24
+ - [`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`
25
+ - [`packages/helpers/src/common/redact.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/common/redact.ts) - `redactSecrets`, `redactUrlCredentials`
26
+ - [`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
27
 
3
28
  ## Architecture
4
29
 
@@ -9,21 +34,21 @@ BaseHelper
9
34
  │ └── NodeFetchNetworkRequest (T = 'node-fetch')
10
35
 
11
36
  ├── BaseNetworkTcpServer<ServerOpts, ServerType, ClientType>
12
- │ ├── NetworkTcpServer (net.Server, net.Socket)
13
- │ └── NetworkTlsTcpServer (tls.Server, tls.TLSSocket)
37
+ │ ├── NetworkTcpServer (net.createServer, net.Socket)
38
+ │ └── NetworkTlsTcpServer (tls.createServer, tls.TLSSocket)
14
39
 
15
40
  ├── BaseNetworkTcpClient<ClientOpts, ClientType>
16
- │ ├── NetworkTcpClient (net.TcpSocketConnectOpts, net.Socket)
17
- │ └── NetworkTlsTcpClient (tls.ConnectionOptions, tls.TLSSocket)
41
+ │ ├── NetworkTcpClient (net.connect, net.Socket)
42
+ │ └── NetworkTlsTcpClient (tls.connect, tls.TLSSocket)
18
43
 
19
44
  └── NetworkUdpClient
20
45
 
21
- AbstractNetworkFetchableHelper<V, RQ, RS> (implements IFetchable)
46
+ AbstractNetworkFetchableHelper<V, RQ, RS> (implements IFetchable, NOT a BaseHelper)
22
47
  ├── AxiosFetcher (V = 'axios')
23
48
  └── NodeFetcher (V = 'node-fetch')
24
49
  ```
25
50
 
26
- All classes that extend `BaseHelper` inherit scoped logging via `this.logger`.
51
+ All classes that extend `BaseHelper` inherit scoped logging via `this.logger`. `AbstractNetworkFetchableHelper` and its two fetchers do **not** extend `BaseHelper` - they accept an optional `logger` parameter per call instead (see the Request Logging & Redaction section under HTTP Request API).
27
52
 
28
53
  ---
29
54
 
@@ -68,10 +93,10 @@ getRequestUrl(opts: {
68
93
 
69
94
  | Parameter | Type | Description |
70
95
  |-----------|------|-------------|
71
- | `baseUrl` | `string` | Overrides the instance's base URL. Falls back to `this.baseUrl` |
96
+ | `baseUrl` | `string` | Overrides the instance's base URL. Falls back to `this.baseUrl`. An explicit empty string does **not** fall back - it throws |
72
97
  | `paths` | `string[]` | Path segments to append. Each is prefixed with `/` if missing |
73
98
 
74
- **Throws:** `Error` with message `'[getRequestUrl] Invalid configuration for third party request base url!'` when both `opts.baseUrl` and `this.baseUrl` are empty.
99
+ **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
100
 
76
101
  **Example:**
77
102
 
@@ -85,7 +110,7 @@ client.getRequestUrl({ baseUrl: 'https://other.api.com', paths: ['health'] });
85
110
 
86
111
  ##### `getRequestPath(opts)`
87
112
 
88
- Joins path segments, ensuring each starts with `/`.
113
+ Joins path segments, ensuring each starts with `/`. An empty `paths` array joins to `''`.
89
114
 
90
115
  ```typescript
91
116
  getRequestPath(opts: { paths: Array<string> }): string
@@ -108,7 +133,7 @@ getNetworkService(): IFetchable<T, IRequestOptions, TFetcherResponse<T>>
108
133
 
109
134
  ##### `getWorker()`
110
135
 
111
- Returns the raw HTTP client from the fetcher (`AxiosInstance` for Axios, `typeof fetch` for Node Fetch).
136
+ Returns the raw HTTP client from the fetcher (`AxiosInstance` for Axios, `typeof fetch` for Node Fetch). Delegates to `fetcher.getWorker()`.
112
137
 
113
138
  ```typescript
114
139
  getWorker(): TFetcherWorker<T>
@@ -130,24 +155,43 @@ interface IFetchable<
130
155
  put(opts: RQ, logger?: any): Promise<RS>;
131
156
  patch(opts: RQ, logger?: any): Promise<RS>;
132
157
  delete(opts: RQ, logger?: any): Promise<RS>;
158
+ query(opts: RQ, logger?: any): Promise<RS>;
159
+
133
160
  getWorker(): TFetcherWorker<V>;
134
161
  }
135
162
  ```
136
163
 
137
- All HTTP method shortcuts (`get`, `post`, `put`, `patch`, `delete`) delegate to `send()` with the `method` field set accordingly.
164
+ 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)) - a `GET`-semantics request that carries a body, useful for search payloads too large for a query string.
138
165
 
139
166
  ### IRequestOptions
140
167
 
141
168
  ```typescript
142
169
  interface IRequestOptions {
143
170
  url: string;
144
- params?: Record<string | symbol, any>;
145
- method?: string;
171
+ method?: THttpMethod;
172
+ params?: AnyObject;
146
173
  timeout?: number;
147
174
  [extra: symbol | string]: any;
148
175
  }
149
176
  ```
150
177
 
178
+ ### HTTP.Methods - the const-class every fetcher dispatches on
179
+
180
+ ```typescript
181
+ HTTP.Methods = {
182
+ GET: 'get', POST: 'post', PUT: 'put', PATCH: 'patch',
183
+ DELETE: 'delete', HEAD: 'head', OPTIONS: 'options', QUERY: 'query',
184
+ } as const;
185
+
186
+ type THttpMethod = ValueOf<typeof HTTP.Methods> | Uppercase<ValueOf<typeof HTTP.Methods>>;
187
+ ```
188
+
189
+ > [!IMPORTANT]
190
+ > - **Every `HTTP.Methods` token is lowercase.** `@hono/zod-openapi` route definitions accept no other case.
191
+ > - **Both fetchers accept either case on input** (`method: 'post'` or `method: 'POST'`) but always call `method.toUpperCase()` immediately before dispatching to their transport.
192
+ > - **This is not cosmetic.** Node's undici (the `fetch` implementation on Node, not Bun) auto-normalizes only `DELETE`/`GET`/`HEAD`/`OPTIONS`/`POST`/`PUT` and sends any other token (`PATCH`, `QUERY`) through verbatim - a lowercase `patch` would reach the server unchanged and most servers reject it.
193
+ > - **Bun and Axios hide the bug.** Bun's `fetch` and Axios (via `node:http`) uppercase every method themselves, so the bug surfaces only once the app runs on Node with undici.
194
+
151
195
  ---
152
196
 
153
197
  ### AbstractNetworkFetchableHelper
@@ -160,7 +204,7 @@ abstract class AbstractNetworkFetchableHelper<
160
204
  > implements IFetchable<V, RQ, RS>
161
205
  ```
162
206
 
163
- Abstract base for fetcher implementations. Provides convenience HTTP method wrappers and protocol detection.
207
+ Abstract base for fetcher implementations. Provides convenience HTTP method wrappers and protocol detection. Does **not** extend `BaseHelper` - it has no `this.logger`.
164
208
 
165
209
  #### Constructor
166
210
 
@@ -178,49 +222,22 @@ Subclasses must implement the actual request dispatch.
178
222
  abstract send(opts: RQ, logger?: any): Promise<RS>;
179
223
  ```
180
224
 
181
- ##### `get(opts, logger?)`
225
+ ##### `get(opts, logger?)` / `post(opts, logger?)` / `put(opts, logger?)` / `patch(opts, logger?)` / `delete(opts, logger?)` / `query(opts, logger?)`
182
226
 
183
227
  ```typescript
184
228
  get(opts: RQ, logger?: any): Promise<RS>
185
- ```
186
-
187
- Calls `send()` with `method: 'get'`.
188
-
189
- ##### `post(opts, logger?)`
190
-
191
- ```typescript
192
229
  post(opts: RQ, logger?: any): Promise<RS>
193
- ```
194
-
195
- Calls `send()` with `method: 'post'`.
196
-
197
- ##### `put(opts, logger?)`
198
-
199
- ```typescript
200
230
  put(opts: RQ, logger?: any): Promise<RS>
201
- ```
202
-
203
- Calls `send()` with `method: 'put'`.
204
-
205
- ##### `patch(opts, logger?)`
206
-
207
- ```typescript
208
231
  patch(opts: RQ, logger?: any): Promise<RS>
209
- ```
210
-
211
- Calls `send()` with `method: 'patch'`.
212
-
213
- ##### `delete(opts, logger?)`
214
-
215
- ```typescript
216
232
  delete(opts: RQ, logger?: any): Promise<RS>
233
+ query(opts: RQ, logger?: any): Promise<RS>
217
234
  ```
218
235
 
219
- Calls `send()` with `method: 'delete'`.
236
+ 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
237
 
221
238
  ##### `getProtocol(url)`
222
239
 
223
- Returns `'http'` or `'https'` based on the URL prefix.
240
+ Returns `HTTP.Protocols.HTTP` (`'http'`) if `url` starts with `'http:'`, otherwise `HTTP.Protocols.HTTPS` (`'https'`).
224
241
 
225
242
  ```typescript
226
243
  getProtocol(url: string): 'http' | 'https'
@@ -228,7 +245,7 @@ getProtocol(url: string): 'http' | 'https'
228
245
 
229
246
  ##### `getWorker()`
230
247
 
231
- Returns the underlying HTTP client instance.
248
+ Returns the underlying HTTP client instance (set by the concrete fetcher's constructor).
232
249
 
233
250
  ```typescript
234
251
  getWorker(): TFetcherWorker<V>
@@ -258,12 +275,14 @@ constructor(opts: {
258
275
  })
259
276
  ```
260
277
 
278
+ `opts.logger`, if provided, logs `'Creating new network request worker instance! Name: %s'` once at construction time - unrelated to the per-call `logger` argument on `send()`.
279
+
261
280
  #### IAxiosRequestOptions
262
281
 
263
282
  ```typescript
264
283
  interface IAxiosRequestOptions extends AxiosRequestConfig, IRequestOptions {
265
284
  url: string;
266
- method?: 'get' | 'post' | 'put' | 'patch' | 'delete' | 'options';
285
+ method?: THttpMethod;
267
286
  params?: AnyObject;
268
287
  body?: AnyObject; // Mapped to Axios `data`
269
288
  headers?: AnyObject;
@@ -271,7 +290,9 @@ interface IAxiosRequestOptions extends AxiosRequestConfig, IRequestOptions {
271
290
  ```
272
291
 
273
292
  > [!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`.
293
+ > - **`body` maps to Axios's `data`** field internally.
294
+ > - **Query `params` are serialized** using `node:querystring` via Axios's `paramsSerializer`.
295
+ > - **HTTPS gets an `https.Agent` automatically**, with `rejectUnauthorized` defaulting to `false` - override it per request with `rejectUnauthorized: true`.
275
296
 
276
297
  #### Methods
277
298
 
@@ -281,7 +302,11 @@ interface IAxiosRequestOptions extends AxiosRequestConfig, IRequestOptions {
281
302
  override send<T = any>(opts: IAxiosRequestOptions, logger?: any): Promise<AxiosResponse<T>>
282
303
  ```
283
304
 
284
- Dispatches the request via the internal `axios` instance. For HTTPS URLs, automatically configures an `https.Agent`.
305
+ Dispatches the request via the internal `axios` instance.
306
+
307
+ - `method` defaults to `HTTP.Methods.GET` and is uppercased before dispatch.
308
+ - HTTPS URLs automatically get an `https.Agent` configured.
309
+ - If `logger` is passed, logs `'URL: %s | Props: %s'` at `info` level with the assembled request config run through `redactSecrets()`.
285
310
 
286
311
  ---
287
312
 
@@ -291,7 +316,7 @@ Dispatches the request via the internal `axios` instance. For HTTPS URLs, automa
291
316
  class AxiosNetworkRequest extends BaseNetworkRequest<'axios'>
292
317
  ```
293
318
 
294
- Pre-configured HTTP client using Axios.
319
+ Pre-configured HTTP client using Axios. Import only from the sub-path - `import { AxiosNetworkRequest } from '@venizia/ignis-helpers/axios'`.
295
320
 
296
321
  #### Constructor
297
322
 
@@ -317,7 +342,7 @@ interface IAxiosNetworkRequestOptions {
317
342
  | `validateStatus` | `(status) => status < 500` |
318
343
  | `timeout` | `60000` (1 minute) |
319
344
 
320
- User-provided values in `networkOptions` override all defaults.
345
+ User-provided values in `networkOptions` override all defaults. `networkOptions.baseUrl` maps to Axios's `baseURL`.
321
346
 
322
347
  ---
323
348
 
@@ -331,7 +356,7 @@ class NodeFetcher extends AbstractNetworkFetchableHelper<
331
356
  >
332
357
  ```
333
358
 
334
- Native `fetch` based fetcher implementation.
359
+ Native `fetch`-based fetcher implementation.
335
360
 
336
361
  #### Constructor
337
362
 
@@ -348,7 +373,8 @@ constructor(opts: {
348
373
  ```typescript
349
374
  interface INodeFetchRequestOptions extends RequestInit, IRequestOptions {
350
375
  url: string;
351
- params?: Record<string | symbol, any>;
376
+ method?: THttpMethod;
377
+ params?: AnyObject;
352
378
  }
353
379
  ```
354
380
 
@@ -360,7 +386,14 @@ interface INodeFetchRequestOptions extends RequestInit, IRequestOptions {
360
386
  override async send(opts: INodeFetchRequestOptions, logger?: any): Promise<Response>
361
387
  ```
362
388
 
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.
389
+ Dispatches the request using the native `fetch` API. Behavior:
390
+
391
+ - `method` defaults to `HTTP.Methods.GET` and is uppercased before dispatch.
392
+ - Query `params` are serialized with `node:querystring` and appended to `url` - with `?` if the URL carries no query string yet, `&` if it already does (never a double `?`).
393
+ - If `timeout` is provided, an internal `AbortController` aborts the request after that many milliseconds.
394
+ - The internal timeout signal is **composed**, never substituted, with a caller-supplied `signal`: `AbortSignal.any([signal, timeoutController.signal])` when both are present - so a caller aborting its own signal still cancels the request even while a timeout is also armed.
395
+ - The timer is cleared as soon as the request settles.
396
+ - If `logger` is passed, logs `'URL: %s | Props: %s | Timeout: %s'` at `info` level with the request config run through `redactSecrets()`.
364
397
 
365
398
  ---
366
399
 
@@ -370,7 +403,7 @@ Dispatches the request using the native `fetch` API. If `timeout` is provided, c
370
403
  class NodeFetchNetworkRequest extends BaseNetworkRequest<'node-fetch'>
371
404
  ```
372
405
 
373
- Pre-configured HTTP client using native `fetch`.
406
+ Pre-configured HTTP client using native `fetch`. Exported from the root barrel - no extra dependency.
374
407
 
375
408
  #### Constructor
376
409
 
@@ -393,7 +426,36 @@ interface INodeFetchNetworkRequestOptions {
393
426
  |---------|---------|
394
427
  | `headers['content-type']` | `'application/json; charset=utf-8'` |
395
428
 
396
- If `headers` is a `Headers` instance, it is converted to a plain object via `Object.fromEntries()` before merging.
429
+ If `headers` is a `Headers` instance, it is converted to a plain object via `Object.fromEntries(headers.entries())` before merging with the default.
430
+
431
+ > [!WARNING] `timeout` is per-call, not per-instance
432
+ > `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:
433
+ >
434
+ > ```typescript
435
+ > await this.getNetworkService().send({ url: '/slow-endpoint', method: 'get', timeout: 5000 });
436
+ > ```
437
+
438
+ ---
439
+
440
+ ### Request Logging & Redaction
441
+
442
+ Neither fetcher logs anything by default - `send()` and every shortcut accept an **optional** `logger` as the second argument, and the log call is guarded with `logger?.for(...)`. Pass one (typically `this.logger` from a `BaseHelper` subclass, or `this.logger` on a class extending `BaseNetworkRequest`) to get an `info`-level line per request:
443
+
444
+ ```typescript
445
+ await this.getNetworkService().post({ url, body }, this.logger);
446
+ ```
447
+
448
+ Whenever a logger is passed, the assembled request config - `url`, `method`, `headers`, `body`/`data`, and any other options - is run through `redactSecrets()` **before** the log line is written. Redaction matches by key name, case-insensitively, at any depth, against `SECRET_KEY_PATTERN`:
449
+
450
+ | Key group | Matched spellings |
451
+ |-----------|--------------------|
452
+ | Options-object (camelCase) | `pass`, `password`, `passphrase`, `secret`, `token`, `apiKey`, `accessKey`, `secretKey`, `privateKey`, `key`, `cert`, `ca`, `pfx`, `credentials`, `authorization`, `auth`, `jwtSecret`, `applicationSecret`, `connectionString` |
453
+ | Options-object (snake_case) | `api_key`, `access_key`, `secret_key`, `private_key` |
454
+ | 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`) |
455
+
456
+ Source: [`redact.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/common/redact.ts) `SECRET_KEY_PATTERN`.
457
+
458
+ 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
459
 
398
460
  ---
399
461
 
@@ -417,9 +479,9 @@ Abstract TCP server with client tracking, authentication flow, and event delegat
417
479
  constructor(opts: ITcpSocketServerOptions<SocketServerOptions, SocketServerType, SocketClientType>)
418
480
  ```
419
481
 
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.
482
+ **Throws:** `ApplicationError` with message `'TCP Server | Invalid authenticate duration | Required duration for authenticateOptions'` when `authenticateOptions.required` is `true` and `duration` is missing, `0`, or negative.
421
483
 
422
- The constructor automatically calls `configure()`, which creates the server and starts listening.
484
+ The constructor calls `configure()`, which creates the server via `createServerFn` and starts listening.
423
485
 
424
486
  #### Protected Properties
425
487
 
@@ -430,13 +492,16 @@ The constructor automatically calls `configure()`, which creates the server and
430
492
  | `authenticateOptions` | `{ required: boolean; duration?: number }` | Auth settings |
431
493
  | `clients` | `Record<string, ITcpSocketClient<SocketClientType>>` | Connected client registry |
432
494
  | `server` | `SocketServerType` | The underlying server instance |
433
- | `extraEvents` | `Record<string, (opts) => void>` | Additional per-client socket events |
495
+ | `extraEvents` | `Record<string, (opts) => ValueOrPromise<void>>` | Additional per-client socket events to register |
496
+
497
+ - **Hooks never crash the process.** `onClientData`, `onClientConnected`, `onClientClose`, `onClientError`, `onServerReady`, `onServerError`, and each `extraEvents` entry all run through an internal `invokeHook()` wrapper.
498
+ - **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 it and logs instead.
434
499
 
435
500
  #### Methods
436
501
 
437
502
  ##### `configure()`
438
503
 
439
- Creates the server using `createServerFn` and starts listening. Called automatically by the constructor.
504
+ 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
505
 
441
506
  ```typescript
442
507
  configure(): void
@@ -444,39 +509,29 @@ configure(): void
444
509
 
445
510
  ##### `onNewConnection(opts)`
446
511
 
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.
512
+ Handles a new client connection:
513
+
514
+ - Assigns a unique ID via `getUID()`.
515
+ - Registers `data`/`error`/`close`/`extraEvents` listeners on the socket.
516
+ - Tracks the client in the `clients` registry.
517
+ - Invokes `onClientConnected`.
518
+ - Starts the authentication kick-timer when `authenticateOptions.required` is `true`.
448
519
 
449
520
  ```typescript
450
521
  onNewConnection(opts: { socket: SocketClientType }): void
451
522
  ```
452
523
 
453
- ##### `getClients()`
454
-
455
- Returns all connected clients as a record keyed by client ID.
524
+ ##### `getClients()` / `getClient(opts)` / `getServer()`
456
525
 
457
526
  ```typescript
458
527
  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
528
  getClient(opts: { id: string }): ITcpSocketClient<SocketClientType> | undefined
467
- ```
468
-
469
- ##### `getServer()`
470
-
471
- Returns the underlying server instance.
472
-
473
- ```typescript
474
529
  getServer(): SocketServerType
475
530
  ```
476
531
 
477
532
  ##### `doAuthenticate(opts)`
478
533
 
479
- Transitions a client's authentication state. Sets `authenticatedAt` timestamp when state becomes `'authenticated'`, clears it otherwise.
534
+ Transitions a client's authentication state. Sets `storage.authenticatedAt` when the state becomes `'authenticated'` and clears the pending kick-timer; clears `authenticatedAt` for the other two states.
480
535
 
481
536
  ```typescript
482
537
  doAuthenticate(opts: {
@@ -487,12 +542,38 @@ doAuthenticate(opts: {
487
542
 
488
543
  ##### `emit(opts)`
489
544
 
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.
545
+ Writes data to a specific client's socket. Never throws - each failure case logs and returns instead:
546
+
547
+ | Condition | Log level |
548
+ |-----------|-----------|
549
+ | Client not found for `clientId` | `error` |
550
+ | Socket not writable | `error` |
551
+ | Payload empty (`!payload?.length`) | `info` |
491
552
 
492
553
  ```typescript
493
554
  emit(opts: { clientId: string; payload: Buffer | string }): void
494
555
  ```
495
556
 
557
+ ##### `shutdown()`
558
+
559
+ Tears the server down completely and resolves even while clients are still attached.
560
+
561
+ ```typescript
562
+ async shutdown(): Promise<void>
563
+ ```
564
+
565
+ **Order of operations:**
566
+
567
+ 1. Clears every client's pending authenticate kick-timer.
568
+ 2. Destroys every client socket.
569
+ 3. Empties the `clients` registry.
570
+ 4. Calls `server.close()` and awaits its callback.
571
+
572
+ - **Why this order.** `server.close()` alone never resolves while a socket is still attached, so a caller reaching through `getServer().close()` on a busy server hangs forever.
573
+ - **Idempotent.** A second call is a no-op that resolves cleanly.
574
+ - **Safe on a server that never finished `listen()`.** Logs the resulting `ERR_SERVER_NOT_RUNNING` rather than throwing.
575
+ - **After `shutdown()`**, new connection attempts are refused.
576
+
496
577
  ---
497
578
 
498
579
  ### ITcpSocketClient
@@ -506,6 +587,7 @@ interface ITcpSocketClient<SocketClientType> {
506
587
  storage: {
507
588
  connectedAt: dayjs.Dayjs;
508
589
  authenticatedAt: dayjs.Dayjs | null;
590
+ authenticateTimeout?: ReturnType<typeof setTimeout> | null;
509
591
  [additionField: symbol | string]: any;
510
592
  };
511
593
  }
@@ -527,14 +609,12 @@ Plain TCP server using `net.createServer`.
527
609
  constructor(opts: Omit<ITcpSocketServerOptions, 'createServerFn'>)
528
610
  ```
529
611
 
530
- The `createServerFn` is pre-set to `net.createServer`. The `scope` is set to `'NetworkTcpServer'`.
612
+ The `createServerFn` is pre-set to `net.createServer`. `scope` is hardcoded to `'NetworkTcpServer'`, overriding any `opts.scope`.
531
613
 
532
614
  #### Static Methods
533
615
 
534
616
  ##### `newInstance(opts)`
535
617
 
536
- Factory method that creates a new `NetworkTcpServer`.
537
-
538
618
  ```typescript
539
619
  static newInstance(
540
620
  opts: Omit<ITcpSocketServerOptions, 'createServerFn'>
@@ -554,10 +634,10 @@ TLS-encrypted TCP server using `tls.createServer`.
554
634
  #### Constructor
555
635
 
556
636
  ```typescript
557
- constructor(opts: Omit<ITcpSocketServerOptions, 'createServerFn'>)
637
+ constructor(opts: Omit<ITcpSocketServerOptions<TlsOptions, tls.Server, TLSSocket>, 'createServerFn'>)
558
638
  ```
559
639
 
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`).
640
+ 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
641
 
562
642
  #### Static Methods
563
643
 
@@ -565,7 +645,7 @@ The `createServerFn` is pre-set to `tls.createServer`. The `scope` is set to `'N
565
645
 
566
646
  ```typescript
567
647
  static newInstance(
568
- opts: Omit<ITcpSocketServerOptions, 'createServerFn'>
648
+ opts: Omit<ITcpSocketServerOptions<TlsOptions, tls.Server, TLSSocket>, 'createServerFn'>
569
649
  ): NetworkTlsTcpServer
570
650
  ```
571
651
 
@@ -588,21 +668,34 @@ Abstract TCP client with auto-reconnect, encoding support, and lifecycle hooks.
588
668
  constructor(opts: INetworkTcpClientProps<SocketClientOptions, SocketClientType>)
589
669
  ```
590
670
 
671
+ Does **not** call `connect()` automatically - construction only stores options; call `connect({ resetReconnectCounter })` explicitly.
672
+
591
673
  #### Protected Properties
592
674
 
593
675
  | Property | Type | Description |
594
676
  |----------|------|-------------|
595
- | `client` | `SocketClientType \| null` | The underlying socket, or `null` when disconnected |
677
+ | `client` | `SocketClientType \| null` | The underlying socket, or `null`/`undefined` when disconnected |
596
678
  | `options` | `SocketClientOptions` | Connection options |
597
679
  | `reconnect` | `boolean` | Whether auto-reconnect is enabled (default: `false`) |
598
680
  | `retry` | `{ maxReconnect: number; currentReconnect: number }` | Reconnect state. `maxReconnect` defaults to `5` |
599
681
  | `encoding` | `BufferEncoding \| undefined` | Socket encoding |
600
682
 
683
+ ##### `getLoggableOptions()`
684
+
685
+ ```typescript
686
+ protected getLoggableOptions(): unknown
687
+ ```
688
+
689
+ Returns `redactSecrets(this.options)`. A TLS client's `options` **is** its private key material (`key`/`cert`/`passphrase`), so every internal log call uses this instead of logging `this.options` directly - otherwise the key would be written to every log file and aggregator downstream.
690
+
601
691
  #### Methods
602
692
 
603
693
  ##### `connect(opts)`
604
694
 
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.
695
+ Establishes the connection:
696
+
697
+ - No-op with a log line if already connected (`isConnected()`) or if `options` is empty.
698
+ - Otherwise, destroys any stale `client` first, creates the socket via `createClientFn`, registers `data`/`close`/`error` listeners, and applies `encoding` if set.
606
699
 
607
700
  ```typescript
608
701
  connect(opts: { resetReconnectCounter: boolean }): void
@@ -610,11 +703,11 @@ connect(opts: { resetReconnectCounter: boolean }): void
610
703
 
611
704
  | Parameter | Type | Description |
612
705
  |-----------|------|-------------|
613
- | `resetReconnectCounter` | `boolean` | If `true`, resets `retry.currentReconnect` to `0` |
706
+ | `resetReconnectCounter` | `boolean` | If `true`, resets `retry.currentReconnect` to `0` before connecting |
614
707
 
615
708
  ##### `disconnect()`
616
709
 
617
- Destroys the socket, clears the reconnect timeout, and sets `client` to `null`.
710
+ Destroys the socket, clears the reconnect timeout, and sets `client` to `null`. No-op with a log line if `client` is not set.
618
711
 
619
712
  ```typescript
620
713
  disconnect(): void
@@ -630,7 +723,7 @@ forceReconnect(): void
630
723
 
631
724
  ##### `isConnected()`
632
725
 
633
- Returns a truthy value if the client exists and its `readyState` is not `'closed'`.
726
+ Returns a truthy value if `client` exists and its `readyState` is not `'closed'`.
634
727
 
635
728
  ```typescript
636
729
  isConnected(): SocketClientType | null | undefined
@@ -638,7 +731,7 @@ isConnected(): SocketClientType | null | undefined
638
731
 
639
732
  ##### `emit(opts)`
640
733
 
641
- Writes data to the server. Silently returns (with a log) if the client is not initialized or the payload is empty.
734
+ Writes data to the server. Logs and returns without throwing if `client` is not initialized or the payload is empty.
642
735
 
643
736
  ```typescript
644
737
  emit(opts: { payload: Buffer | string }): void
@@ -646,43 +739,36 @@ emit(opts: { payload: Buffer | string }): void
646
739
 
647
740
  ##### `getClient()`
648
741
 
649
- Returns the underlying socket instance, or `null`/`undefined` if not connected.
650
-
651
742
  ```typescript
652
743
  getClient(): SocketClientType | null | undefined
653
744
  ```
654
745
 
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)`
746
+ ##### `handleConnected()` / `handleData(_opts)` / `handleClosed()` / `handleError(error)`
664
747
 
665
- Default data handler. No-op.
748
+ Default handlers used when the matching `onConnected`/`onData`/`onClosed`/`onError` option is omitted.
666
749
 
667
750
  ```typescript
668
- handleData(_opts: { identifier: string; message: string | Buffer }): void
751
+ handleConnected(): void // Logs, resets retry.currentReconnect to 0
752
+ handleData(_opts: { identifier: string; message: string | Buffer }): void // No-op
753
+ handleClosed(): void // Logs the closure
754
+ handleError(error: any): void // Logs; schedules a reconnect if eligible
669
755
  ```
670
756
 
671
- ##### `handleClosed()`
672
-
673
- Default close handler. Logs the closure.
674
-
675
- ```typescript
676
- handleClosed(): void
677
- ```
757
+ **Reconnect gate on `handleError`:**
678
758
 
679
- ##### `handleError(error)`
759
+ | Condition | Result |
760
+ |-----------|--------|
761
+ | `reconnect` is `false` | No reconnect - the first guard returns immediately |
762
+ | `retry.currentReconnect >= retry.maxReconnect` | No reconnect - the first guard returns immediately |
763
+ | `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 |
764
+ | `reconnect` is `true` and `currentReconnect < maxReconnect` (with `maxReconnect >= 0`) | Reconnect scheduled |
680
765
 
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.
766
+ > [!IMPORTANT]
767
+ > - **`maxReconnect: -1` does not mean unlimited reconnects - it disables reconnection entirely.** This is the opposite of the common "`-1` = unlimited" convention elsewhere in the framework (e.g. Redis retry).
768
+ > - **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`.
769
+ > - 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
770
 
683
- ```typescript
684
- handleError(error: any): void
685
- ```
771
+ 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
772
 
687
773
  ---
688
774
 
@@ -702,7 +788,7 @@ constructor(
702
788
  )
703
789
  ```
704
790
 
705
- The `createClientFn` is pre-set to `net.connect`. The `scope` is set to `'NetworkTcpClient'`.
791
+ The `createClientFn` is pre-set to `net.connect`. `scope` is hardcoded to `'NetworkTcpClient'`.
706
792
 
707
793
  #### Static Methods
708
794
 
@@ -732,7 +818,7 @@ constructor(
732
818
  )
733
819
  ```
734
820
 
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`).
821
+ 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
822
 
737
823
  #### Static Methods
738
824
 
@@ -754,7 +840,7 @@ static newInstance(
754
840
  class NetworkUdpClient extends BaseHelper
755
841
  ```
756
842
 
757
- UDP datagram client with multicast support, using `node:dgram` internally (UDP4).
843
+ 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
844
 
759
845
  #### Constructor
760
846
 
@@ -762,41 +848,12 @@ UDP datagram client with multicast support, using `node:dgram` internally (UDP4)
762
848
  constructor(opts: INetworkUdpClientProps)
763
849
  ```
764
850
 
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
- ```
851
+ Construction only stores options; call `connect()` explicitly to bind the socket.
793
852
 
794
853
  #### Static Methods
795
854
 
796
855
  ##### `newInstance(opts)`
797
856
 
798
- Factory method that creates a new `NetworkUdpClient`.
799
-
800
857
  ```typescript
801
858
  static newInstance(opts: INetworkUdpClientProps): NetworkUdpClient
802
859
  ```
@@ -805,17 +862,19 @@ static newInstance(opts: INetworkUdpClientProps): NetworkUdpClient
805
862
 
806
863
  ##### `connect()`
807
864
 
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.
865
+ - Creates a `dgram.Socket` (`type: 'udp4'`, `reuseAddr` from options), registers `close`/`error`/`listening`/`message` listeners, then binds to `port`/`host`.
866
+ - Each listener routes through an internal `invokeHook()` wrapper (same synchronous-throw guard as the TCP server).
867
+ - `onBind` fires after binding completes - the place to join multicast groups via `socket.addMembership(group, iface)`.
809
868
 
810
869
  ```typescript
811
870
  connect(): void
812
871
  ```
813
872
 
814
- If the client is already initialized, logs a message and returns. If `port` is not set, logs a message and returns.
873
+ No-op with a log line if `client` is already set, or if `port` is not a non-negative integer (`Number.isInteger(port) && port >= 0`) - port `0` is a valid "OS assigns a free port" request and is accepted.
815
874
 
816
875
  ##### `disconnect()`
817
876
 
818
- Closes the underlying `dgram.Socket` and sets the client to `null`.
877
+ Closes the socket and sets `client` to `null`. No-op with a log line if `client` is not set.
819
878
 
820
879
  ```typescript
821
880
  disconnect(): void
@@ -823,7 +882,7 @@ disconnect(): void
823
882
 
824
883
  ##### `isConnected()`
825
884
 
826
- Returns the underlying socket if connected, or `null`/`undefined` if not.
885
+ Returns the underlying socket if bound, or `null`/`undefined` otherwise.
827
886
 
828
887
  ```typescript
829
888
  isConnected(): dgram.Socket | null | undefined
@@ -831,45 +890,25 @@ isConnected(): dgram.Socket | null | undefined
831
890
 
832
891
  ##### `getClient()`
833
892
 
834
- Returns the underlying `dgram.Socket` instance, or `null`/`undefined` if not connected.
835
-
836
893
  ```typescript
837
894
  getClient(): dgram.Socket | null | undefined
838
895
  ```
839
896
 
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
- ```
897
+ ##### `handleConnected()` / `handleData(opts)` / `handleClosed()` / `handleError(opts)`
859
898
 
860
- ##### `handleClosed()`
899
+ Default handlers used when the matching `onConnected`/`onData`/`onClosed`/`onError` option is omitted:
861
900
 
862
- Default close handler. Logs the closure with host and port.
901
+ | Handler | Log level | Logged context |
902
+ |---------|-----------|-----------------|
903
+ | `handleConnected` | `info` | `host`, `port`, `multicastAddress` |
904
+ | `handleClosed` | `info` | `host`, `port`, `multicastAddress` |
905
+ | `handleData` | `info` | `host`, `port` only - no `multicastAddress` |
906
+ | `handleError` | `error` | `host`, `port` only - no `multicastAddress` |
863
907
 
864
908
  ```typescript
909
+ handleConnected(): void
910
+ handleData(opts: { identifier: string; message: string | Buffer; remoteInfo: dgram.RemoteInfo }): void
865
911
  handleClosed(): void
866
- ```
867
-
868
- ##### `handleError(opts)`
869
-
870
- Default error handler. Logs the error with host and port.
871
-
872
- ```typescript
873
912
  handleError(opts: { identifier: string; error: Error }): void
874
913
  ```
875
914
 
@@ -877,24 +916,24 @@ handleError(opts: { identifier: string; error: Error }): void
877
916
 
878
917
  ## Types Reference
879
918
 
880
- ### TFetcherVariant
919
+ ### TFetcherVariant / TFetcherResponse / TFetcherWorker
881
920
 
882
921
  ```typescript
883
922
  type TFetcherVariant = 'node-fetch' | 'axios';
884
- ```
885
-
886
- ### TFetcherResponse
887
923
 
888
- ```typescript
889
924
  type TFetcherResponse<T extends TFetcherVariant> =
890
925
  T extends 'node-fetch' ? Response : AxiosResponse;
926
+
927
+ type TFetcherWorker<T extends TFetcherVariant> =
928
+ T extends 'axios' ? AxiosInstance : typeof fetch;
891
929
  ```
892
930
 
893
- ### TFetcherWorker
931
+ ### THttpMethod
894
932
 
895
933
  ```typescript
896
- type TFetcherWorker<T extends TFetcherVariant> =
897
- T extends 'axios' ? AxiosInstance : typeof fetch;
934
+ type THttpMethod = ValueOf<typeof HTTP.Methods> | Uppercase<ValueOf<typeof HTTP.Methods>>;
935
+ // 'get' | 'post' | 'put' | 'patch' | 'delete' | 'head' | 'options' | 'query'
936
+ // | 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'QUERY'
898
937
  ```
899
938
 
900
939
  ### ITcpSocketServerOptions
@@ -907,25 +946,32 @@ interface ITcpSocketServerOptions<
907
946
  > {
908
947
  scope?: string;
909
948
  identifier: string;
949
+
910
950
  serverOptions: Partial<SocketServerOptions>;
911
951
  listenOptions: Partial<ListenOptions>;
912
952
  authenticateOptions: { required: boolean; duration?: number };
953
+
913
954
  extraEvents?: Record<
914
955
  string,
915
956
  (opts: { id: string; socket: SocketClientType; args: any }) => ValueOrPromise<void>
916
957
  >;
958
+
917
959
  createServerFn: (
918
960
  options: Partial<SocketServerOptions>,
919
961
  connectionListener: (socket: SocketClientType) => void,
920
962
  ) => SocketServerType;
963
+
921
964
  onServerReady?: (opts: { server: SocketServerType }) => void;
922
965
  onClientConnected?: (opts: { id: string; socket: SocketClientType }) => void;
923
966
  onClientData?: (opts: { id: string; socket: SocketClientType; data: Buffer | string }) => void;
924
967
  onClientClose?: (opts: { id: string; socket: SocketClientType }) => void;
925
968
  onClientError?: (opts: { id: string; socket: SocketClientType; error: Error }) => void;
969
+ onServerError?: (opts: { server: SocketServerType; error: Error }) => void;
926
970
  }
927
971
  ```
928
972
 
973
+ `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, the error is routed here and the process keeps running.
974
+
929
975
  ### INetworkTcpClientProps
930
976
 
931
977
  ```typescript
@@ -981,6 +1027,6 @@ interface INetworkUdpClientProps {
981
1027
  }
982
1028
  ```
983
1029
 
984
- ## See Also
1030
+ ## See also
985
1031
 
986
- - [Setup & Usage](./) -- Getting started and examples
1032
+ - [Network overview](/extensions/helpers/network/) - introduction and the most common tasks