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