@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,626 +1,189 @@
1
- # Network
2
-
3
- Multi-protocol network communication helpers for HTTP requests, TCP/TLS sockets, and UDP datagrams with scoped logging, auto-reconnect, and client authentication support.
4
-
5
- ## Quick Reference
6
-
7
- | Class | Extends | Protocol | Type |
8
- |-------|---------|----------|------|
9
- | `AxiosNetworkRequest` | `BaseNetworkRequest<'axios'>` | HTTP/HTTPS | Client |
10
- | `NodeFetchNetworkRequest` | `BaseNetworkRequest<'node-fetch'>` | HTTP/HTTPS | Client |
11
- | `NetworkTcpClient` | `BaseNetworkTcpClient` | TCP | Client |
12
- | `NetworkTcpServer` | `BaseNetworkTcpServer` | TCP | Server |
13
- | `NetworkTlsTcpClient` | `BaseNetworkTcpClient` | TLS/SSL | Client |
14
- | `NetworkTlsTcpServer` | `BaseNetworkTcpServer` | TLS/SSL | Server |
15
- | `NetworkUdpClient` | `BaseHelper` | UDP | Client |
16
-
17
- #### Import Paths
18
-
19
- ```typescript
20
- // Main package -- TCP, UDP, and Node Fetch
21
- import {
22
- NodeFetchNetworkRequest,
23
- BaseNetworkRequest,
24
- NetworkTcpClient,
25
- NetworkTcpServer,
26
- NetworkTlsTcpClient,
27
- NetworkTlsTcpServer,
28
- BaseNetworkTcpClient,
29
- BaseNetworkTcpServer,
30
- NetworkUdpClient,
31
- } from '@venizia/ignis-helpers';
32
-
33
- // Axios (separate export -- optional peer dependency)
34
- import {
35
- AxiosNetworkRequest,
36
- AxiosFetcher,
37
- type IAxiosNetworkRequestOptions,
38
- type IAxiosRequestOptions,
39
- } from '@venizia/ignis-helpers/axios';
40
-
41
- // Types
42
- import type {
43
- INodeFetchNetworkRequestOptions,
44
- INodeFetchRequestOptions,
45
- INetworkTcpClientProps,
46
- ITcpSocketServerOptions,
47
- ITcpSocketClient,
48
- IRequestOptions,
49
- IFetchable,
50
- TFetcherVariant,
51
- } from '@venizia/ignis-helpers';
52
- ```
1
+ ---
2
+ title: Network
3
+ description: HTTP request clients, TCP/TLS socket clients and servers, and a UDP client, all built on scoped logging with automatic secret redaction
4
+ difficulty: intermediate
5
+ ---
53
6
 
54
- ## Creating an Instance
7
+ # Network
55
8
 
56
- ### HTTP Request
9
+ Network helpers give you HTTP request clients (fetch or Axios), symmetric TCP/TLS socket client-server pairs, and a UDP client. All three share the same options-object construction and scoped logging as the rest of the framework.
57
10
 
58
- HTTP helpers follow a two-layer design: a `BaseNetworkRequest` that holds the base URL and delegates to an underlying `IFetchable` fetcher (either Axios or native `fetch`). You typically extend one of the concrete classes to create a typed API client.
11
+ ## In one example
59
12
 
60
- #### Axios
13
+ Extend `NodeFetchNetworkRequest` to build a typed HTTP client backed by native `fetch` - no extra dependency required.
61
14
 
62
15
  ```typescript
63
- import { AxiosNetworkRequest } from '@venizia/ignis-helpers/axios';
16
+ import { NodeFetchNetworkRequest } from '@venizia/ignis-helpers';
64
17
 
65
- class PaymentGateway extends AxiosNetworkRequest {
18
+ class GitHubApi extends NodeFetchNetworkRequest {
66
19
  constructor() {
67
20
  super({
68
- name: 'PaymentGateway',
69
- networkOptions: {
70
- baseUrl: 'https://api.payments.com',
71
- timeout: 30000,
72
- headers: {
73
- 'X-API-Key': process.env.PAYMENT_API_KEY,
74
- },
75
- },
21
+ name: 'GitHubApi',
22
+ networkOptions: { baseUrl: 'https://api.github.com' },
76
23
  });
77
24
  }
78
- }
79
- ```
80
-
81
- #### `IAxiosNetworkRequestOptions`
82
-
83
- | Option | Type | Default | Description |
84
- |--------|------|---------|-------------|
85
- | `name` | `string` | -- | Helper name, used for scoped logging |
86
- | `networkOptions.baseUrl` | `string` | `undefined` | Base URL prepended to all request paths |
87
- | `networkOptions.timeout` | `number` | `60000` | Request timeout in milliseconds |
88
- | `networkOptions.headers` | `object` | `{ 'content-type': 'application/json; charset=utf-8' }` | Default headers; your values override the default content-type |
89
- | `networkOptions.*` | `AxiosRequestConfig` | -- | All other Axios config options are accepted |
90
-
91
- > [!TIP]
92
- > `AxiosNetworkRequest` sets sensible defaults: `Content-Type: application/json`, `withCredentials: true`, `validateStatus: status < 500`, and `timeout: 60000` (1 minute). Your options override these defaults.
93
-
94
- #### Node.js Fetch
95
25
 
96
- ```typescript
97
- import { NodeFetchNetworkRequest } from '@venizia/ignis-helpers';
98
-
99
- class MyApiClient extends NodeFetchNetworkRequest {
100
- constructor() {
101
- super({
102
- name: 'MyApiClient',
103
- networkOptions: {
104
- baseUrl: 'https://api.example.com',
105
- headers: {
106
- 'Authorization': 'Bearer my-token',
107
- },
108
- credentials: 'include',
109
- mode: 'cors',
110
- },
111
- });
26
+ async getUser(username: string) {
27
+ const url = this.getRequestUrl({ paths: ['users', username] });
28
+ const response = await this.getNetworkService().get({ url });
29
+ return response.json();
112
30
  }
113
31
  }
114
32
  ```
115
33
 
116
- #### `INodeFetchNetworkRequestOptions`
117
-
118
- | Option | Type | Default | Description |
119
- |--------|------|---------|-------------|
120
- | `name` | `string` | -- | Helper name, used for scoped logging |
121
- | `networkOptions.baseUrl` | `string` | `undefined` | Base URL prepended to all request paths |
122
- | `networkOptions.headers` | `HeadersInit` | `{ 'content-type': 'application/json; charset=utf-8' }` | Default headers; supports `Headers` object or plain object |
123
- | `networkOptions.*` | `RequestInit` | -- | All other `fetch` options are accepted |
124
-
125
- ### TCP Client / Server
126
-
127
- #### TCP Client
128
-
129
- ```typescript
130
- import { NetworkTcpClient } from '@venizia/ignis-helpers';
131
-
132
- const tcpClient = new NetworkTcpClient({
133
- identifier: 'sensor-reader',
134
- options: {
135
- host: 'localhost',
136
- port: 8080,
137
- },
138
- reconnect: true,
139
- maxRetry: 10,
140
- encoding: 'utf8',
141
- onConnected: ({ client }) => { console.log('Connected'); },
142
- onData: ({ identifier, message }) => { console.log('Data:', message.toString()); },
143
- onClosed: ({ client }) => { console.log('Closed'); },
144
- onError: (error) => { console.error('Error:', error); },
145
- });
146
- ```
147
-
148
- #### TCP Client Options (`INetworkTcpClientProps`)
149
-
150
- | Option | Type | Default | Description |
151
- |--------|------|---------|-------------|
152
- | `identifier` | `string` | -- | Unique client identifier for logging |
153
- | `scope` | `string` | `identifier` | Logger scope name |
154
- | `options` | `TcpSocketConnectOpts` | -- | Node.js `net.connect` options (`host`, `port`, etc.) |
155
- | `reconnect` | `boolean` | `false` | Enable automatic reconnection on error |
156
- | `maxRetry` | `number` | `5` | Maximum reconnection attempts |
157
- | `encoding` | `BufferEncoding` | `undefined` | Socket encoding (e.g., `'utf8'`) |
158
- | `onConnected` | `(opts: { client }) => void` | Internal logger | Called when connection is established |
159
- | `onData` | `(opts: { identifier, message }) => void` | No-op | Called when data is received |
160
- | `onClosed` | `(opts: { client }) => void` | Internal logger | Called when connection closes |
161
- | `onError` | `(error: any) => void` | Internal handler with auto-reconnect | Called on connection errors |
162
-
163
- #### TCP Server
164
-
165
- ```typescript
166
- import { NetworkTcpServer } from '@venizia/ignis-helpers';
167
-
168
- const tcpServer = new NetworkTcpServer({
169
- identifier: 'my-tcp-server',
170
- serverOptions: {},
171
- listenOptions: { port: 8080, host: '0.0.0.0' },
172
- authenticateOptions: { required: true, duration: 5000 },
173
- onServerReady: ({ server }) => { console.log('Listening'); },
174
- onClientConnected: ({ id, socket }) => { console.log(`Client ${id} connected`); },
175
- onClientData: ({ id, socket, data }) => { console.log(`Data from ${id}:`, data.toString()); },
176
- onClientClose: ({ id, socket }) => { console.log(`Client ${id} disconnected`); },
177
- onClientError: ({ id, socket, error }) => { console.error(`Error from ${id}:`, error); },
178
- });
179
- ```
180
-
181
- > [!IMPORTANT]
182
- > When `authenticateOptions.required` is `true`, you **must** provide a positive `duration` value. Clients that do not authenticate within this duration are automatically disconnected with an "Unauthorized Client" message. Use `doAuthenticate()` in your `onClientData` handler to transition the client's state.
34
+ `getRequestUrl()` joins the constructor's `baseUrl` with the path segments. `getNetworkService()` returns the underlying fetcher, which exposes `send()` plus `get`/`post`/`put`/`patch`/`delete`/`query` shortcuts.
183
35
 
184
- #### TCP Server Options (`ITcpSocketServerOptions`)
36
+ ## How it works
185
37
 
186
- | Option | Type | Default | Description |
187
- |--------|------|---------|-------------|
188
- | `identifier` | `string` | -- | Server identifier for logging |
189
- | `scope` | `string` | `identifier` | Logger scope name |
190
- | `serverOptions` | `Partial<ServerOpts>` | -- | Node.js `net.Server` options |
191
- | `listenOptions` | `Partial<ListenOptions>` | -- | Listen options (`port`, `host`, `backlog`, etc.) |
192
- | `authenticateOptions.required` | `boolean` | -- | Whether clients must authenticate |
193
- | `authenticateOptions.duration` | `number` | `undefined` | Auth timeout in ms (required when `required: true`) |
194
- | `extraEvents` | `Record<string, (opts) => void>` | `{}` | Additional socket events to register per client |
195
- | `onServerReady` | `(opts: { server }) => void` | `undefined` | Called when server starts listening |
196
- | `onClientConnected` | `(opts: { id, socket }) => void` | `undefined` | Called on new client connection |
197
- | `onClientData` | `(opts: { id, socket, data }) => void` | `undefined` | Called when data is received from a client |
198
- | `onClientClose` | `(opts: { id, socket }) => void` | `undefined` | Called when a client disconnects |
199
- | `onClientError` | `(opts: { id, socket, error }) => void` | `undefined` | Called on client socket error |
38
+ - **HTTP is two layers.** `BaseNetworkRequest` holds the base URL and delegates every call to an `IFetchable` fetcher. You extend one of two concrete clients:
200
39
 
201
- ### TLS Client / Server
40
+ | Client | Wraps | Import from |
41
+ |---|---|---|
42
+ | `NodeFetchNetworkRequest` | native `fetch` | root barrel |
43
+ | `AxiosNetworkRequest` | Axios | `@venizia/ignis-helpers/axios` sub-path |
202
44
 
203
- TLS variants are identical to their TCP counterparts but use `node:tls` under the hood for encrypted connections. The constructor options accept TLS-specific fields (`cert`, `key`, `ca`, `rejectUnauthorized`, etc.) in addition to all the same handler options.
45
+ - **`axios` is optional.** It is an optional peer dependency. `AxiosNetworkRequest` is exported only from the `/axios` sub-path, never from the root barrel.
46
+ - **TCP and TLS share one hierarchy.** `BaseNetworkTcpServer`/`BaseNetworkTcpClient` are abstract classes. Each takes a create-function matching its transport, and each concrete pair only pre-wires that function:
204
47
 
205
- #### TLS Client
48
+ | Transport | Server class | Client class | Node module |
49
+ |---|---|---|---|
50
+ | Plain TCP | `NetworkTcpServer` | `NetworkTcpClient` | `net` |
51
+ | TLS | `NetworkTlsTcpServer` | `NetworkTlsTcpClient` | `tls` |
206
52
 
207
- ```typescript
208
- import { NetworkTlsTcpClient } from '@venizia/ignis-helpers';
209
- import fs from 'node:fs';
210
-
211
- const tlsClient = new NetworkTlsTcpClient({
212
- identifier: 'secure-client',
213
- options: {
214
- host: 'secure.example.com',
215
- port: 8443,
216
- rejectUnauthorized: true,
217
- ca: fs.readFileSync('ca.crt'),
218
- cert: fs.readFileSync('client.crt'),
219
- key: fs.readFileSync('client.key'),
220
- },
221
- reconnect: true,
222
- maxRetry: 3,
223
- onData: ({ message }) => { console.log('Secure data:', message); },
224
- });
53
+ Constructor options and every method are otherwise identical between the plain and encrypted variants.
225
54
 
226
- tlsClient.connect({ resetReconnectCounter: true });
227
- ```
55
+ - **Servers track per-client authentication state.** `unauthorized` → `authenticating` → `authenticated`.
56
+ - **Clients auto-reconnect on a fixed delay.** 5 seconds between attempts, up to `maxRetry` attempts, when `reconnect: true`. See the [Full reference](/extensions/helpers/network/api) for the `maxRetry: -1` edge case.
57
+ - **UDP has no client/server split.** `NetworkUdpClient` is a single class wrapping `node:dgram` in UDP4 mode. It supports optional multicast group joining via `onBind`.
58
+ - **Every class extends `BaseHelper`.** `this.logger.for('methodName')` scoped logging is available throughout.
228
59
 
229
- > [!NOTE]
230
- > `NetworkTlsTcpClient` accepts `ConnectionOptions` from `node:tls` in the `options` field. All other options (`reconnect`, `maxRetry`, callbacks) are identical to `NetworkTcpClient`.
60
+ **HTTP method case**
231
61
 
232
- #### TLS Server
62
+ | Layer | Case | Why |
63
+ |-------|------|-----|
64
+ | `HTTP.Methods.GET`/`.POST`/`.QUERY`/... tokens | always lowercase | Required by `@hono/zod-openapi` route definitions |
65
+ | Wire dispatch | uppercased right before send | Node's undici only auto-normalizes `DELETE`/`GET`/`HEAD`/`OPTIONS`/`POST`/`PUT`. A lowercase `patch` or `query` would go out unchanged |
233
66
 
234
- ```typescript
235
- import { NetworkTlsTcpServer } from '@venizia/ignis-helpers';
236
- import fs from 'node:fs';
237
-
238
- const tlsServer = new NetworkTlsTcpServer({
239
- identifier: 'secure-tcp-server',
240
- serverOptions: {
241
- cert: fs.readFileSync('server.crt'),
242
- key: fs.readFileSync('server.key'),
243
- ca: [fs.readFileSync('ca.crt')],
244
- requestCert: true,
245
- },
246
- listenOptions: { port: 8443, host: '0.0.0.0' },
247
- authenticateOptions: { required: false },
248
- onClientData: ({ id, data }) => { console.log(`Secure data from ${id}:`, data.toString()); },
249
- });
250
- ```
67
+ ## Common tasks
251
68
 
252
- > [!NOTE]
253
- > `NetworkTlsTcpServer` accepts `TlsOptions` from `node:tls` in `serverOptions`. All handlers and methods are identical to `NetworkTcpServer`.
69
+ ### Use Axios instead of fetch
254
70
 
255
- ### UDP Client
71
+ Import from the `/axios` sub-path - never from the root barrel, since `axios` is an optional peer dependency.
256
72
 
257
73
  ```typescript
258
- import { NetworkUdpClient } from '@venizia/ignis-helpers';
259
-
260
- const udpClient = NetworkUdpClient.newInstance({
261
- identifier: 'my-udp-client',
262
- port: 8081,
263
- host: '0.0.0.0',
264
- reuseAddr: true,
265
- multicastAddress: {
266
- groups: ['239.1.2.3'],
267
- interface: '0.0.0.0',
268
- },
269
- onData: ({ message, remoteInfo }) => {
270
- console.log(`From ${remoteInfo.address}:${remoteInfo.port}:`, message.toString());
271
- },
272
- onBind: async ({ socket, multicastAddress }) => {
273
- if (multicastAddress?.groups) {
274
- for (const group of multicastAddress.groups) {
275
- socket.addMembership(group, multicastAddress.interface);
276
- }
277
- }
278
- },
279
- });
280
- ```
281
-
282
- #### UDP Client Options (`INetworkUdpClientProps`)
283
-
284
- | Option | Type | Default | Description |
285
- |--------|------|---------|-------------|
286
- | `identifier` | `string` | -- | Unique client identifier for logging |
287
- | `host` | `string` | `undefined` | Bind address |
288
- | `port` | `number` | -- | Bind port |
289
- | `reuseAddr` | `boolean` | `undefined` | Allow address reuse (`SO_REUSEADDR`) |
290
- | `multicastAddress.groups` | `string[]` | `undefined` | Multicast group addresses to join |
291
- | `multicastAddress.interface` | `string` | `undefined` | Network interface for multicast |
292
- | `onConnected` | `(opts: { identifier, host?, port }) => void` | Internal logger | Called when socket starts listening |
293
- | `onData` | `(opts: { identifier, message, remoteInfo }) => void` | Internal logger | Called when data is received |
294
- | `onClosed` | `(opts: { identifier, host?, port }) => void` | Internal logger | Called when socket is closed |
295
- | `onError` | `(opts: { identifier, host?, port, error }) => void` | Internal logger | Called on socket error |
296
- | `onBind` | `(opts: { identifier, socket, host?, port, reuseAddr?, multicastAddress? }) => void` | `undefined` | Called after socket is bound; use to join multicast groups |
297
-
298
- ## Usage
299
-
300
- ### HTTP Requests
301
-
302
- Access the underlying fetcher via `getNetworkService()`, then use `send()` or the convenience methods (`get`, `post`, `put`, `patch`, `delete`):
74
+ import { AxiosNetworkRequest } from '@venizia/ignis-helpers/axios';
303
75
 
304
- ```typescript
305
76
  class PaymentGateway extends AxiosNetworkRequest {
306
77
  constructor() {
307
78
  super({
308
79
  name: 'PaymentGateway',
309
80
  networkOptions: {
310
- baseUrl: process.env.PAYMENT_API_URL,
81
+ baseUrl: 'https://api.payments.com',
311
82
  timeout: 30000,
312
83
  headers: { 'X-API-Key': process.env.PAYMENT_API_KEY },
313
84
  },
314
85
  });
315
86
  }
316
-
317
- async charge(amount: number, currency: string) {
318
- const url = this.getRequestUrl({ paths: ['v1', 'charges'] });
319
- const response = await this.getNetworkService().send({
320
- url,
321
- method: 'post',
322
- body: { amount, currency },
323
- });
324
- this.logger.for('charge').info('Payment processed: %s', response.data.id);
325
- return response.data;
326
- }
327
-
328
- async getTransaction(id: string) {
329
- const url = this.getRequestUrl({ paths: ['v1', 'transactions', id] });
330
- return this.getNetworkService().get({ url });
331
- }
332
87
  }
333
88
  ```
334
89
 
335
- #### Request Logging & Redaction
90
+ `AxiosNetworkRequest` applies these defaults - override any of them in `networkOptions`:
336
91
 
337
- Both `NodeFetcher` and `AxiosFetcher` log every outbound request at `info` level (`URL: %s | Props: %s | ...`), including the request config -- headers, body, and any other options passed to `send()`. Before that log line is written, the request config is run through `redactSecrets()`, so values under secret-looking keys never reach the log.
92
+ | Setting | Default |
93
+ |---|---|
94
+ | `content-type` header | `application/json; charset=utf-8` |
95
+ | `withCredentials` | `true` |
96
+ | `validateStatus` | `status < 500` |
97
+ | `timeout` | `60000` ms |
338
98
 
339
- Redaction matches by key name, case-insensitively, at any depth -- both options-object spellings (`apiKey`, `token`, `password`, `authorization`, ...) and HTTP header spellings (`x-api-key`, `x-csrf-token`, `cookie`, `set-cookie`, `proxy-authorization`, `www-authenticate`, ...). A header like `'X-API-Key': process.env.PAYMENT_API_KEY` or `'Authorization': 'Bearer my-token'` (as in the examples above) is logged as `'[REDACTED]'`, not the real value. This redaction happens automatically -- there is nothing to configure.
99
+ ### Log a request with secrets redacted
340
100
 
341
- #### Convenience Methods
101
+ Pass a logger as the second argument to `send()` or any shortcut method - typically `this.logger` from a `BaseHelper` subclass. The fetcher then logs the URL and config at `info` level. It runs the config through `redactSecrets()` first, so values like `Authorization` or `X-API-Key` reach the log as `'[REDACTED]'`. Without a logger argument, nothing is logged.
342
102
 
343
103
  ```typescript
344
- const fetcher = this.getNetworkService();
345
-
346
- // These are equivalent:
347
- await fetcher.send({ url: '/users', method: 'get' });
348
- await fetcher.get({ url: '/users' });
349
-
350
- // POST with body
351
- await fetcher.post({ url: '/users', body: { name: 'Alice' } });
352
-
353
- // All methods: get(), post(), put(), patch(), delete()
354
- ```
355
-
356
- #### HTTPS with Axios
357
-
358
- For HTTPS requests, the `AxiosFetcher` automatically creates an `https.Agent`. By default, `rejectUnauthorized` is `false`. Override it per request:
359
-
360
- ```typescript
361
- await fetcher.send({
362
- url: 'https://strict-api.example.com/data',
363
- method: 'get',
364
- rejectUnauthorized: true,
365
- });
366
- ```
367
-
368
- #### Timeout with Node Fetch
369
-
370
- The `NodeFetcher` implements timeout via `AbortController`. Pass `timeout` in each `send()` call:
371
-
372
- ```typescript
373
- await fetcher.send({
374
- url: '/slow-endpoint',
375
- method: 'get',
376
- timeout: 5000, // Aborts after 5 seconds
377
- });
104
+ async charge(amount: number, currency: string) {
105
+ const url = this.getRequestUrl({ paths: ['v1', 'charges'] });
106
+ const response = await this.getNetworkService().post(
107
+ { url, body: { amount, currency } },
108
+ this.logger,
109
+ );
110
+ return response.data;
111
+ }
378
112
  ```
379
113
 
380
- ### TCP Communication
114
+ ### Open a TCP connection
381
115
 
382
116
  ```typescript
383
117
  import { NetworkTcpClient, NetworkTcpServer } from '@venizia/ignis-helpers';
384
118
 
385
- // --- Server ---
386
119
  const server = new NetworkTcpServer({
387
120
  identifier: 'echo-server',
388
121
  serverOptions: {},
389
122
  listenOptions: { port: 9000, host: '0.0.0.0' },
390
123
  authenticateOptions: { required: false },
391
- onClientData: ({ id, data }) => {
392
- // Echo back to the sender
393
- server.emit({ clientId: id, payload: data });
394
- },
124
+ onClientData: ({ id, data }) => server.emit({ clientId: id, payload: data }),
395
125
  });
396
126
 
397
- // --- Client ---
398
127
  const client = new NetworkTcpClient({
399
128
  identifier: 'echo-client',
400
129
  options: { host: 'localhost', port: 9000 },
401
130
  reconnect: true,
402
131
  maxRetry: 5,
403
- encoding: 'utf8',
404
- onData: ({ message }) => { console.log('Echo:', message); },
132
+ onData: ({ message }) => console.log('Echo:', message),
405
133
  });
406
134
 
407
135
  client.connect({ resetReconnectCounter: true });
408
136
  client.emit({ payload: 'Hello, Server!' });
409
137
  ```
410
138
 
411
- #### Server with Authentication Flow
139
+ `NetworkTlsTcpServer`/`NetworkTlsTcpClient` use the identical API. Pass certificates in `serverOptions`/`options`, typed `TlsOptions`/`ConnectionOptions` from `node:tls`.
140
+
141
+ ### Require TCP client authentication
142
+
143
+ Set `authenticateOptions.required: true` with a positive `duration` in milliseconds. The constructor throws if `duration` is missing or negative. Clients that never call `doAuthenticate()` within that window are disconnected automatically.
412
144
 
413
145
  ```typescript
414
146
  const server = new NetworkTcpServer({
415
- identifier: 'auth-tcp-server',
147
+ identifier: 'auth-server',
416
148
  serverOptions: {},
417
149
  listenOptions: { port: 9000, host: '0.0.0.0' },
418
150
  authenticateOptions: { required: true, duration: 5000 },
419
-
420
151
  onClientData: ({ id, data }) => {
421
- const message = data.toString();
422
- const client = server.getClient({ id });
423
-
424
- if (client?.state === 'unauthorized') {
425
- if (message === 'secret-token') {
426
- server.doAuthenticate({ id, state: 'authenticated' });
427
- server.emit({ clientId: id, payload: 'Authenticated!' });
428
- } else {
429
- server.emit({ clientId: id, payload: 'Invalid credentials' });
430
- }
431
- return;
152
+ if (data.toString() === 'secret-token') {
153
+ server.doAuthenticate({ id, state: 'authenticated' });
432
154
  }
433
-
434
- // Handle authenticated client messages
435
- console.log(`[${id}] ${message}`);
436
155
  },
437
156
  });
438
157
  ```
439
158
 
440
- #### Client State Tracking
441
-
442
- Each connected client is tracked as an `ITcpSocketClient`:
443
-
444
- ```typescript
445
- interface ITcpSocketClient<SocketClientType> {
446
- id: string;
447
- socket: SocketClientType;
448
- state: 'unauthorized' | 'authenticating' | 'authenticated';
449
- subscriptions: Set<string>;
450
- storage: {
451
- connectedAt: dayjs.Dayjs;
452
- authenticatedAt: dayjs.Dayjs | null;
453
- [additionField: symbol | string]: any; // Extensible storage
454
- };
455
- }
456
- ```
457
-
458
- ### TLS Encrypted Communication
459
-
460
- TLS classes share the same API as their TCP counterparts. Provide TLS certificates in the `options` or `serverOptions` field:
461
-
462
- ```typescript
463
- import { NetworkTlsTcpServer, NetworkTlsTcpClient } from '@venizia/ignis-helpers';
464
- import fs from 'node:fs';
465
-
466
- // --- TLS Server ---
467
- const tlsServer = new NetworkTlsTcpServer({
468
- identifier: 'secure-server',
469
- serverOptions: {
470
- cert: fs.readFileSync('server.crt'),
471
- key: fs.readFileSync('server.key'),
472
- ca: [fs.readFileSync('ca.crt')],
473
- requestCert: true,
474
- },
475
- listenOptions: { port: 8443, host: '0.0.0.0' },
476
- authenticateOptions: { required: false },
477
- onClientData: ({ id, data }) => {
478
- console.log(`Secure data from ${id}:`, data.toString());
479
- },
480
- });
481
-
482
- // --- TLS Client ---
483
- const tlsClient = new NetworkTlsTcpClient({
484
- identifier: 'secure-client',
485
- options: {
486
- host: 'localhost',
487
- port: 8443,
488
- rejectUnauthorized: true,
489
- ca: fs.readFileSync('ca.crt'),
490
- cert: fs.readFileSync('client.crt'),
491
- key: fs.readFileSync('client.key'),
492
- },
493
- onData: ({ message }) => { console.log('Secure:', message); },
494
- });
495
-
496
- tlsClient.connect({ resetReconnectCounter: true });
497
- tlsClient.emit({ payload: 'Hello over TLS!' });
498
- ```
499
-
500
- ### UDP Communication
159
+ ### Send a UDP datagram
501
160
 
502
161
  ```typescript
503
162
  import { NetworkUdpClient } from '@venizia/ignis-helpers';
504
163
 
505
164
  const udpClient = NetworkUdpClient.newInstance({
506
- identifier: 'multicast-listener',
507
- port: 5000,
165
+ identifier: 'my-udp-client',
166
+ port: 8081,
508
167
  host: '0.0.0.0',
509
- reuseAddr: true,
510
- multicastAddress: {
511
- groups: ['239.1.2.3'],
512
- interface: '0.0.0.0',
513
- },
514
168
  onData: ({ message, remoteInfo }) => {
515
169
  console.log(`From ${remoteInfo.address}:${remoteInfo.port}:`, message.toString());
516
170
  },
517
- onBind: async ({ socket, multicastAddress }) => {
518
- // Join multicast groups after socket is bound
519
- if (multicastAddress?.groups) {
520
- for (const group of multicastAddress.groups) {
521
- socket.addMembership(group, multicastAddress.interface);
522
- }
523
- }
524
- },
525
171
  });
526
172
 
527
- // Start listening
528
173
  udpClient.connect();
529
-
530
- // Access the underlying dgram.Socket
531
- const socket = udpClient.getClient();
532
-
533
- // Check if bound
534
- if (udpClient.isConnected()) {
535
- // Send a datagram via the raw socket
536
- socket.send('Hello', 5001, '239.1.2.3');
537
- }
538
-
539
- // Stop listening
540
- udpClient.disconnect();
541
- ```
542
-
543
- ## Troubleshooting
544
-
545
- ### HTTP: "[getRequestUrl] Invalid configuration for third party request base url!"
546
-
547
- **Cause:** `getRequestUrl()` was called but no `baseUrl` was provided at construction time or in the call's `opts.baseUrl` parameter.
548
-
549
- **Fix:** Provide a `baseUrl` either in the constructor's `networkOptions` or pass it in the `opts` parameter of `getRequestUrl()`:
550
-
551
- ```typescript
552
- // At construction
553
- const client = new AxiosNetworkRequest({
554
- name: 'MyClient',
555
- networkOptions: { baseUrl: 'https://api.example.com' },
556
- });
557
-
558
- // Or per call
559
- const url = client.getRequestUrl({
560
- baseUrl: 'https://api.example.com',
561
- paths: ['v1', 'users'],
562
- });
563
- ```
564
-
565
- ### HTTP: Timeout not working with NodeFetchNetworkRequest
566
-
567
- **Cause:** The `timeout` option on the constructor's `networkOptions` is not automatically applied to individual requests. Timeout must be set per-request.
568
-
569
- **Fix:** Pass `timeout` in each `send()` call:
570
-
571
- ```typescript
572
- await this.getNetworkService().send({
573
- url: '/slow-endpoint',
574
- method: 'get',
575
- timeout: 5000,
576
- });
174
+ udpClient.getClient()?.send('Hello', 5001, '239.1.2.3');
577
175
  ```
578
176
 
579
- The `NodeFetcher` internally creates an `AbortController` and aborts the request after the specified timeout.
177
+ ## See also
580
178
 
581
- ### TCP Server: "Invalid authenticate duration"
582
-
583
- **Cause:** `authenticateOptions.required` is `true` but `duration` is missing, zero, or negative.
584
-
585
- **Fix:** Provide a positive `duration` value when authentication is required:
586
-
587
- ```typescript
588
- // Correct
589
- authenticateOptions: { required: true, duration: 5000 }
590
-
591
- // Wrong -- throws at construction time
592
- authenticateOptions: { required: true }
593
- authenticateOptions: { required: true, duration: -1 }
594
- ```
595
-
596
- ### TCP Client: Reconnect loop never stops
597
-
598
- **Cause:** `maxRetry` is set to `-1` (infinite retries) and the target server is unreachable. The reconnect delay is fixed at 5 seconds between attempts.
599
-
600
- **Fix:** Use a finite `maxRetry` value, or set `reconnect: false` if you handle reconnection externally:
601
-
602
- ```typescript
603
- const client = new NetworkTcpClient({
604
- identifier: 'my-client',
605
- options: { host: 'localhost', port: 8080 },
606
- reconnect: true,
607
- maxRetry: 5, // Stop after 5 attempts
608
- });
609
- ```
610
-
611
- ### TCP Server: Client emit does nothing
612
-
613
- **Cause:** The target client socket is not writable (already closed or half-closed), or the payload is empty. The server logs a warning but does not throw.
614
-
615
- **Fix:** Check the client state before emitting:
616
-
617
- ```typescript
618
- const client = server.getClient({ id: clientId });
619
- if (client && client.socket.writable) {
620
- server.emit({ clientId, payload: 'Hello' });
621
- }
622
- ```
179
+ - [Full reference](/extensions/helpers/network/api) - every class, method signature, and type in the module
180
+ - [Redis helper](/extensions/helpers/redis/) - another `BaseHelper`-based connection helper with the same scoped-logging conventions
623
181
 
624
- ## See Also
182
+ **Files:**
625
183
 
626
- - [API Reference](./api) -- Full method signatures and types
184
+ - [`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`
185
+ - [`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`
186
+ - [`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` (sub-path export)
187
+ - [`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`
188
+ - [`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`
189
+ - [`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`