@nestia/fetcher 9.0.0-dev.20251107-3 → 9.0.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 CHANGED
@@ -1,93 +1,93 @@
1
- # Nestia
2
- ![Nestia Logo](https://nestia.io/logo.png)
3
-
4
- [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/samchon/nestia/blob/master/LICENSE)
5
- [![npm version](https://img.shields.io/npm/v/@nestia/fetcher.svg)](https://www.npmjs.com/package/@nestia/fetcher)
6
- [![Downloads](https://img.shields.io/npm/dm/@nestia/fetcher.svg)](https://www.npmjs.com/package/@nestia/fetcher)
7
- [![Build Status](https://github.com/samchon/nestia/workflows/build/badge.svg)](https://github.com/samchon/nestia/actions?query=workflow%3Abuild)
8
- [![Guide Documents](https://img.shields.io/badge/Guide-Documents-forestgreen)](https://nestia.io/docs/)
9
- [![Gurubase](https://img.shields.io/badge/Gurubase-Document%20Chatbot-006BFF)](https://gurubase.io/g/nestia)
10
- [![Discord Badge](https://img.shields.io/badge/discord-samchon-d91965?style=flat&labelColor=5866f2&logo=discord&logoColor=white&link=https://discord.gg/E94XhzrUCZ)](https://discord.gg/E94XhzrUCZ)
11
-
12
- Nestia is a set of helper libraries for NestJS, supporting below features:
13
-
14
- - `@nestia/core`:
15
- - Super-fast/easy decorators
16
- - Advanced WebSocket routes
17
- - `@nestia/sdk`:
18
- - Swagger generator, more evolved than ever
19
- - SDK library generator for clients
20
- - Mockup Simulator for client applications
21
- - Automatic E2E test functions generator
22
- - `@nestia/e2e`: Test program utilizing e2e test functions
23
- - `@nestia/benchmark`: Benchmark program using e2e test functions
24
- - `@nestia/editor`: Swagger-UI with Online TypeScript Editor
25
- - [`@agentica`](https://github.com/wrtnlabs/agentica): Agentic AI library specialized in LLM function calling
26
- - [`@autobe`](https://github.com/wrtnlabs/autobe): Vibe coding agent generating NestJS application
27
- - `nestia`: Just CLI (command line interface) tool
28
-
29
- > [!NOTE]
30
- >
31
- > - **Only one line** required, with pure TypeScript type
32
- > - Enhance performance **30x** up
33
- > - Runtime validator is **20,000x faster** than `class-validator`
34
- > - JSON serialization is **200x faster** than `class-transformer`
35
- > - Software Development Kit
36
- > - Collection of typed `fetch` functions with DTO structures like [tRPC](https://trpc.io/)
37
- > - Mockup simulator means embedded backend simulator in the SDK
38
- > - similar with [msw](https://mswjs.io/), but fully automated
39
-
40
- ![nestia-sdk-demo](https://user-images.githubusercontent.com/13158709/215004990-368c589d-7101-404e-b81b-fbc936382f05.gif)
41
-
42
- > Left is NestJS server code, and right is client (frontend) code utilizing SDK
43
-
44
-
45
-
46
-
47
- ## Sponsors and Backers
48
- Thanks for your support.
49
-
50
- Your donation would encourage `nestia` development.
51
-
52
- [![Backers](https://opencollective.com/nestia/backers.svg?avatarHeight=75&width=600)](https://opencollective.com/nestia)
53
-
54
-
55
-
56
-
57
- ## Guide Documents
58
- Check out the document in the [website](https://nestia.io/docs/):
59
-
60
- ### 🏠 Home
61
- - [Introduction](https://nestia.io/docs/)
62
- - [Setup](https://nestia.io/docs/setup/)
63
- - [Pure TypeScript](https://nestia.io/docs/pure)
64
-
65
- ### 📖 Features
66
- - Core Library
67
- - [`@WebSocketRoute`](https://nestia.io/docs/core/WebSocketRoute)
68
- - [`@TypedRoute`](https://nestia.io/docs/core/TypedRoute/)
69
- - [**`@TypedBody`**](https://nestia.io/docs/core/TypedBody/)
70
- - [`@TypedParam`](https://nestia.io/docs/core/TypedParam/)
71
- - [`@TypedQuery`](https://nestia.io/docs/core/TypedQuery/)
72
- - [`@TypedFormData`](https://nestia.io/docs/core/TypedFormData/)
73
- - [`@TypedHeaders`](https://nestia.io/docs/core/TypedHeaders/)
74
- - [`@TypedException`](https://nestia.io/docs/core/TypedException/)
75
- - Software Development Kit
76
- - [SDK Builder](https://nestia.io/docs/sdk/)
77
- - [Mockup Simulator](https://nestia.io/docs/sdk/simulate/)
78
- - [E2E Test Functions](https://nestia.io/docs/sdk/e2e/)
79
- - [Distribution](https://nestia.io/docs/sdk/distribute/)
80
- - Swagger Document
81
- - [Swagger Builder](https://nestia.io/docs/swagger/)
82
- - [**AI Chatbot Development**](https://nestia.io/docs/swagger/chat/)
83
- - [Cloud Swagger Editor](https://nestia.io/docs/swagger/editor/)
84
- - [Documentation Strategy](https://nestia.io/docs/swagger/strategy/)
85
- - E2E Testing
86
- - [Why E2E Test?](https://nestia.io/docs/e2e/why/)
87
- - [Test Program Development](https://nestia.io/docs/e2e/development/)
88
- - [Performance Benchmark](https://nestia.io/docs/e2e/benchmark/)
89
-
90
- ### 🔗 Appendix
91
- - [API Documents](https://nestia.io/api)
92
- - [⇲ Benchmark Result](https://github.com/samchon/nestia/tree/master/benchmark/results/11th%20Gen%20Intel(R)%20Core(TM)%20i5-1135G7%20%40%202.40GHz)
93
- - [⇲ `dev.to` Articles](https://dev.to/samchon/series/22751)
1
+ # Nestia
2
+ ![Nestia Logo](https://nestia.io/logo.png)
3
+
4
+ [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/samchon/nestia/blob/master/LICENSE)
5
+ [![npm version](https://img.shields.io/npm/v/@nestia/fetcher.svg)](https://www.npmjs.com/package/@nestia/fetcher)
6
+ [![Downloads](https://img.shields.io/npm/dm/@nestia/fetcher.svg)](https://www.npmjs.com/package/@nestia/fetcher)
7
+ [![Build Status](https://github.com/samchon/nestia/workflows/build/badge.svg)](https://github.com/samchon/nestia/actions?query=workflow%3Abuild)
8
+ [![Guide Documents](https://img.shields.io/badge/Guide-Documents-forestgreen)](https://nestia.io/docs/)
9
+ [![Gurubase](https://img.shields.io/badge/Gurubase-Document%20Chatbot-006BFF)](https://gurubase.io/g/nestia)
10
+ [![Discord Badge](https://img.shields.io/badge/discord-samchon-d91965?style=flat&labelColor=5866f2&logo=discord&logoColor=white&link=https://discord.gg/E94XhzrUCZ)](https://discord.gg/E94XhzrUCZ)
11
+
12
+ Nestia is a set of helper libraries for NestJS, supporting below features:
13
+
14
+ - `@nestia/core`:
15
+ - Super-fast/easy decorators
16
+ - Advanced WebSocket routes
17
+ - `@nestia/sdk`:
18
+ - Swagger generator, more evolved than ever
19
+ - SDK library generator for clients
20
+ - Mockup Simulator for client applications
21
+ - Automatic E2E test functions generator
22
+ - `@nestia/e2e`: Test program utilizing e2e test functions
23
+ - `@nestia/benchmark`: Benchmark program using e2e test functions
24
+ - `@nestia/editor`: Swagger-UI with Online TypeScript Editor
25
+ - [`@agentica`](https://github.com/wrtnlabs/agentica): Agentic AI library specialized in LLM function calling
26
+ - [`@autobe`](https://github.com/wrtnlabs/autobe): Vibe coding agent generating NestJS application
27
+ - `nestia`: Just CLI (command line interface) tool
28
+
29
+ > [!NOTE]
30
+ >
31
+ > - **Only one line** required, with pure TypeScript type
32
+ > - Enhance performance **30x** up
33
+ > - Runtime validator is **20,000x faster** than `class-validator`
34
+ > - JSON serialization is **200x faster** than `class-transformer`
35
+ > - Software Development Kit
36
+ > - Collection of typed `fetch` functions with DTO structures like [tRPC](https://trpc.io/)
37
+ > - Mockup simulator means embedded backend simulator in the SDK
38
+ > - similar with [msw](https://mswjs.io/), but fully automated
39
+
40
+ ![nestia-sdk-demo](https://user-images.githubusercontent.com/13158709/215004990-368c589d-7101-404e-b81b-fbc936382f05.gif)
41
+
42
+ > Left is NestJS server code, and right is client (frontend) code utilizing SDK
43
+
44
+
45
+
46
+
47
+ ## Sponsors and Backers
48
+ Thanks for your support.
49
+
50
+ Your donation would encourage `nestia` development.
51
+
52
+ [![Backers](https://opencollective.com/nestia/backers.svg?avatarHeight=75&width=600)](https://opencollective.com/nestia)
53
+
54
+
55
+
56
+
57
+ ## Guide Documents
58
+ Check out the document in the [website](https://nestia.io/docs/):
59
+
60
+ ### 🏠 Home
61
+ - [Introduction](https://nestia.io/docs/)
62
+ - [Setup](https://nestia.io/docs/setup/)
63
+ - [Pure TypeScript](https://nestia.io/docs/pure)
64
+
65
+ ### 📖 Features
66
+ - Core Library
67
+ - [`@WebSocketRoute`](https://nestia.io/docs/core/WebSocketRoute)
68
+ - [`@TypedRoute`](https://nestia.io/docs/core/TypedRoute/)
69
+ - [**`@TypedBody`**](https://nestia.io/docs/core/TypedBody/)
70
+ - [`@TypedParam`](https://nestia.io/docs/core/TypedParam/)
71
+ - [`@TypedQuery`](https://nestia.io/docs/core/TypedQuery/)
72
+ - [`@TypedFormData`](https://nestia.io/docs/core/TypedFormData/)
73
+ - [`@TypedHeaders`](https://nestia.io/docs/core/TypedHeaders/)
74
+ - [`@TypedException`](https://nestia.io/docs/core/TypedException/)
75
+ - Software Development Kit
76
+ - [SDK Builder](https://nestia.io/docs/sdk/)
77
+ - [Mockup Simulator](https://nestia.io/docs/sdk/simulate/)
78
+ - [E2E Test Functions](https://nestia.io/docs/sdk/e2e/)
79
+ - [Distribution](https://nestia.io/docs/sdk/distribute/)
80
+ - Swagger Document
81
+ - [Swagger Builder](https://nestia.io/docs/swagger/)
82
+ - [**AI Chatbot Development**](https://nestia.io/docs/swagger/chat/)
83
+ - [Cloud Swagger Editor](https://nestia.io/docs/swagger/editor/)
84
+ - [Documentation Strategy](https://nestia.io/docs/swagger/strategy/)
85
+ - E2E Testing
86
+ - [Why E2E Test?](https://nestia.io/docs/e2e/why/)
87
+ - [Test Program Development](https://nestia.io/docs/e2e/development/)
88
+ - [Performance Benchmark](https://nestia.io/docs/e2e/benchmark/)
89
+
90
+ ### 🔗 Appendix
91
+ - [API Documents](https://nestia.io/api)
92
+ - [⇲ Benchmark Result](https://github.com/samchon/nestia/tree/master/benchmark/results/11th%20Gen%20Intel(R)%20Core(TM)%20i5-1135G7%20%40%202.40GHz)
93
+ - [⇲ `dev.to` Articles](https://dev.to/samchon/series/22751)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestia/fetcher",
3
- "version": "9.0.0-dev.20251107-3",
3
+ "version": "9.0.1",
4
4
  "description": "Fetcher library of Nestia SDK",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
package/src/AesPkcs5.ts CHANGED
@@ -1,49 +1,49 @@
1
- import crypto from "crypto";
2
-
3
- /**
4
- * Utility class for the AES-128/256 encryption.
5
- *
6
- * - AES-128/256
7
- * - CBC mode
8
- * - PKCS#5 Padding
9
- * - Base64 Encoding
10
- *
11
- * @author Jeongho Nam - https://github.com/samchon
12
- */
13
- export namespace AesPkcs5 {
14
- /**
15
- * Encrypt data
16
- *
17
- * @param data Target data
18
- * @param key Key value of the encryption.
19
- * @param iv Initializer Vector for the encryption
20
- * @returns Encrypted data
21
- */
22
- export function encrypt(data: string, key: string, iv: string): string {
23
- const bytes: number = key.length * 8;
24
- const cipher: crypto.Cipher = crypto.createCipheriv(
25
- `AES-${bytes}-CBC`,
26
- key,
27
- iv,
28
- );
29
- return cipher.update(data, "utf8", "base64") + cipher.final("base64");
30
- }
31
-
32
- /**
33
- * Decrypt data.
34
- *
35
- * @param data Target data
36
- * @param key Key value of the decryption.
37
- * @param iv Initializer Vector for the decryption
38
- * @returns Decrypted data.
39
- */
40
- export function decrypt(data: string, key: string, iv: string): string {
41
- const bytes: number = key.length * 8;
42
- const decipher: crypto.Decipher = crypto.createDecipheriv(
43
- `AES-${bytes}-CBC`,
44
- key,
45
- iv,
46
- );
47
- return decipher.update(data, "base64", "utf8") + decipher.final("utf8");
48
- }
49
- }
1
+ import crypto from "crypto";
2
+
3
+ /**
4
+ * Utility class for the AES-128/256 encryption.
5
+ *
6
+ * - AES-128/256
7
+ * - CBC mode
8
+ * - PKCS#5 Padding
9
+ * - Base64 Encoding
10
+ *
11
+ * @author Jeongho Nam - https://github.com/samchon
12
+ */
13
+ export namespace AesPkcs5 {
14
+ /**
15
+ * Encrypt data
16
+ *
17
+ * @param data Target data
18
+ * @param key Key value of the encryption.
19
+ * @param iv Initializer Vector for the encryption
20
+ * @returns Encrypted data
21
+ */
22
+ export function encrypt(data: string, key: string, iv: string): string {
23
+ const bytes: number = key.length * 8;
24
+ const cipher: crypto.Cipher = crypto.createCipheriv(
25
+ `AES-${bytes}-CBC`,
26
+ key,
27
+ iv,
28
+ );
29
+ return cipher.update(data, "utf8", "base64") + cipher.final("base64");
30
+ }
31
+
32
+ /**
33
+ * Decrypt data.
34
+ *
35
+ * @param data Target data
36
+ * @param key Key value of the decryption.
37
+ * @param iv Initializer Vector for the decryption
38
+ * @returns Decrypted data.
39
+ */
40
+ export function decrypt(data: string, key: string, iv: string): string {
41
+ const bytes: number = key.length * 8;
42
+ const decipher: crypto.Decipher = crypto.createDecipheriv(
43
+ `AES-${bytes}-CBC`,
44
+ key,
45
+ iv,
46
+ );
47
+ return decipher.update(data, "base64", "utf8") + decipher.final("utf8");
48
+ }
49
+ }
@@ -1,176 +1,176 @@
1
- import { AesPkcs5 } from "./AesPkcs5";
2
- import { IConnection } from "./IConnection";
3
- import { IEncryptionPassword } from "./IEncryptionPassword";
4
- import { IFetchRoute } from "./IFetchRoute";
5
- import { IPropagation } from "./IPropagation";
6
- import { FetcherBase } from "./internal/FetcherBase";
7
-
8
- /**
9
- * Utility class for `fetch` functions used in `@nestia/sdk` with encryption.
10
- *
11
- * `EncryptedFetcher` is a utility class designed for SDK functions generated by
12
- * [`@nestia/sdk`](https://nestia.io/docs/sdk/sdk), interacting with the remote
13
- * HTTP API encrypted by AES-PKCS algorithm. In other words, this is a
14
- * collection of dedicated `fetch()` functions for `@nestia/sdk` with
15
- * encryption.
16
- *
17
- * For reference, `EncryptedFetcher` class being used only when target
18
- * controller method is encrypting body data by `@EncryptedRoute` or
19
- * `@EncryptedBody` decorators. If those decorators are not used,
20
- * {@link PlainFetcher} class would be used instead.
21
- *
22
- * @author Jeongho Nam - https://github.com/samchon
23
- */
24
- export namespace EncryptedFetcher {
25
- /**
26
- * Fetch function only for `HEAD` method.
27
- *
28
- * @param connection Connection information for the remote HTTP server
29
- * @param route Route information about the target API
30
- * @returns Nothing because of `HEAD` method
31
- */
32
- export function fetch(
33
- connection: IConnection,
34
- route: IFetchRoute<"HEAD">,
35
- ): Promise<void>;
36
-
37
- /**
38
- * Fetch function only for `GET` method.
39
- *
40
- * @param connection Connection information for the remote HTTP server
41
- * @param route Route information about the target API
42
- * @returns Response body data from the remote API
43
- */
44
- export function fetch<Output>(
45
- connection: IConnection,
46
- route: IFetchRoute<"GET">,
47
- ): Promise<Output>;
48
-
49
- /**
50
- * Fetch function for the `POST`, `PUT`, `PATCH` and `DELETE` methods.
51
- *
52
- * @param connection Connection information for the remote HTTP server
53
- * @param route Route information about the target API
54
- * @returns Response body data from the remote API
55
- */
56
- export function fetch<Input, Output>(
57
- connection: IConnection,
58
- route: IFetchRoute<"POST" | "PUT" | "PATCH" | "DELETE">,
59
- input?: Input,
60
- stringify?: (input: Input) => string,
61
- ): Promise<Output>;
62
-
63
- export async function fetch<Input, Output>(
64
- connection: IConnection,
65
- route: IFetchRoute<"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT">,
66
- input?: Input,
67
- stringify?: (input: Input) => string,
68
- ): Promise<Output> {
69
- if (
70
- (route.request?.encrypted === true || route.response?.encrypted) &&
71
- connection.encryption === undefined
72
- )
73
- throw new Error(
74
- "Error on EncryptedFetcher.fetch(): the encryption password has not been configured.",
75
- );
76
- const closure =
77
- typeof connection.encryption === "function"
78
- ? (direction: "encode" | "decode") =>
79
- (
80
- headers: Record<string, IConnection.HeaderValue | undefined>,
81
- body: string,
82
- ) =>
83
- (connection.encryption as IEncryptionPassword.Closure)({
84
- headers,
85
- body,
86
- direction,
87
- })
88
- : () => () => connection.encryption as IEncryptionPassword;
89
-
90
- return FetcherBase.request({
91
- className: "EncryptedFetcher",
92
- encode:
93
- route.request?.encrypted === true
94
- ? (input, headers) => {
95
- const p: IEncryptionPassword = closure("encode")(headers, input);
96
- return AesPkcs5.encrypt(
97
- (stringify ?? JSON.stringify)(input),
98
- p.key,
99
- p.iv,
100
- );
101
- }
102
- : (input) => input,
103
- decode:
104
- route.response?.encrypted === true
105
- ? (input, headers) => {
106
- const p: IEncryptionPassword = closure("decode")(headers, input);
107
- const s: string = AesPkcs5.decrypt(input, p.key, p.iv);
108
- return s.length ? JSON.parse(s) : s;
109
- }
110
- : (input) => input,
111
- })(connection, route, input, stringify);
112
- }
113
-
114
- export function propagate<Output extends IPropagation<any, any>>(
115
- connection: IConnection,
116
- route: IFetchRoute<"GET" | "HEAD">,
117
- ): Promise<Output>;
118
-
119
- export function propagate<Input, Output extends IPropagation<any, any>>(
120
- connection: IConnection,
121
- route: IFetchRoute<"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT">,
122
- input?: Input,
123
- stringify?: (input: Input) => string,
124
- ): Promise<Output>;
125
-
126
- export async function propagate<Input, Output extends IPropagation<any, any>>(
127
- connection: IConnection,
128
- route: IFetchRoute<"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT">,
129
- input?: Input,
130
- stringify?: (input: Input) => string,
131
- ): Promise<Output> {
132
- if (
133
- (route.request?.encrypted === true || route.response?.encrypted) &&
134
- connection.encryption === undefined
135
- )
136
- throw new Error(
137
- "Error on EncryptedFetcher.propagate(): the encryption password has not been configured.",
138
- );
139
- const closure =
140
- typeof connection.encryption === "function"
141
- ? (direction: "encode" | "decode") =>
142
- (
143
- headers: Record<string, IConnection.HeaderValue | undefined>,
144
- body: string,
145
- ) =>
146
- (connection.encryption as IEncryptionPassword.Closure)({
147
- headers,
148
- body,
149
- direction,
150
- })
151
- : () => () => connection.encryption as IEncryptionPassword;
152
-
153
- return FetcherBase.propagate({
154
- className: "EncryptedFetcher",
155
- encode:
156
- route.request?.encrypted === true
157
- ? (input, headers) => {
158
- const p: IEncryptionPassword = closure("encode")(headers, input);
159
- return AesPkcs5.encrypt(
160
- (stringify ?? JSON.stringify)(input),
161
- p.key,
162
- p.iv,
163
- );
164
- }
165
- : (input) => input,
166
- decode:
167
- route.response?.encrypted === true
168
- ? (input, headers) => {
169
- const p: IEncryptionPassword = closure("decode")(headers, input);
170
- const s: string = AesPkcs5.decrypt(input, p.key, p.iv);
171
- return s.length ? JSON.parse(s) : s;
172
- }
173
- : (input) => input,
174
- })(connection, route, input, stringify) as Promise<Output>;
175
- }
176
- }
1
+ import { AesPkcs5 } from "./AesPkcs5";
2
+ import { IConnection } from "./IConnection";
3
+ import { IEncryptionPassword } from "./IEncryptionPassword";
4
+ import { IFetchRoute } from "./IFetchRoute";
5
+ import { IPropagation } from "./IPropagation";
6
+ import { FetcherBase } from "./internal/FetcherBase";
7
+
8
+ /**
9
+ * Utility class for `fetch` functions used in `@nestia/sdk` with encryption.
10
+ *
11
+ * `EncryptedFetcher` is a utility class designed for SDK functions generated by
12
+ * [`@nestia/sdk`](https://nestia.io/docs/sdk/sdk), interacting with the remote
13
+ * HTTP API encrypted by AES-PKCS algorithm. In other words, this is a
14
+ * collection of dedicated `fetch()` functions for `@nestia/sdk` with
15
+ * encryption.
16
+ *
17
+ * For reference, `EncryptedFetcher` class being used only when target
18
+ * controller method is encrypting body data by `@EncryptedRoute` or
19
+ * `@EncryptedBody` decorators. If those decorators are not used,
20
+ * {@link PlainFetcher} class would be used instead.
21
+ *
22
+ * @author Jeongho Nam - https://github.com/samchon
23
+ */
24
+ export namespace EncryptedFetcher {
25
+ /**
26
+ * Fetch function only for `HEAD` method.
27
+ *
28
+ * @param connection Connection information for the remote HTTP server
29
+ * @param route Route information about the target API
30
+ * @returns Nothing because of `HEAD` method
31
+ */
32
+ export function fetch(
33
+ connection: IConnection,
34
+ route: IFetchRoute<"HEAD">,
35
+ ): Promise<void>;
36
+
37
+ /**
38
+ * Fetch function only for `GET` method.
39
+ *
40
+ * @param connection Connection information for the remote HTTP server
41
+ * @param route Route information about the target API
42
+ * @returns Response body data from the remote API
43
+ */
44
+ export function fetch<Output>(
45
+ connection: IConnection,
46
+ route: IFetchRoute<"GET">,
47
+ ): Promise<Output>;
48
+
49
+ /**
50
+ * Fetch function for the `POST`, `PUT`, `PATCH` and `DELETE` methods.
51
+ *
52
+ * @param connection Connection information for the remote HTTP server
53
+ * @param route Route information about the target API
54
+ * @returns Response body data from the remote API
55
+ */
56
+ export function fetch<Input, Output>(
57
+ connection: IConnection,
58
+ route: IFetchRoute<"POST" | "PUT" | "PATCH" | "DELETE">,
59
+ input?: Input,
60
+ stringify?: (input: Input) => string,
61
+ ): Promise<Output>;
62
+
63
+ export async function fetch<Input, Output>(
64
+ connection: IConnection,
65
+ route: IFetchRoute<"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT">,
66
+ input?: Input,
67
+ stringify?: (input: Input) => string,
68
+ ): Promise<Output> {
69
+ if (
70
+ (route.request?.encrypted === true || route.response?.encrypted) &&
71
+ connection.encryption === undefined
72
+ )
73
+ throw new Error(
74
+ "Error on EncryptedFetcher.fetch(): the encryption password has not been configured.",
75
+ );
76
+ const closure =
77
+ typeof connection.encryption === "function"
78
+ ? (direction: "encode" | "decode") =>
79
+ (
80
+ headers: Record<string, IConnection.HeaderValue | undefined>,
81
+ body: string,
82
+ ) =>
83
+ (connection.encryption as IEncryptionPassword.Closure)({
84
+ headers,
85
+ body,
86
+ direction,
87
+ })
88
+ : () => () => connection.encryption as IEncryptionPassword;
89
+
90
+ return FetcherBase.request({
91
+ className: "EncryptedFetcher",
92
+ encode:
93
+ route.request?.encrypted === true
94
+ ? (input, headers) => {
95
+ const p: IEncryptionPassword = closure("encode")(headers, input);
96
+ return AesPkcs5.encrypt(
97
+ (stringify ?? JSON.stringify)(input),
98
+ p.key,
99
+ p.iv,
100
+ );
101
+ }
102
+ : (input) => input,
103
+ decode:
104
+ route.response?.encrypted === true
105
+ ? (input, headers) => {
106
+ const p: IEncryptionPassword = closure("decode")(headers, input);
107
+ const s: string = AesPkcs5.decrypt(input, p.key, p.iv);
108
+ return s.length ? JSON.parse(s) : s;
109
+ }
110
+ : (input) => input,
111
+ })(connection, route, input, stringify);
112
+ }
113
+
114
+ export function propagate<Output extends IPropagation<any, any>>(
115
+ connection: IConnection,
116
+ route: IFetchRoute<"GET" | "HEAD">,
117
+ ): Promise<Output>;
118
+
119
+ export function propagate<Input, Output extends IPropagation<any, any>>(
120
+ connection: IConnection,
121
+ route: IFetchRoute<"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT">,
122
+ input?: Input,
123
+ stringify?: (input: Input) => string,
124
+ ): Promise<Output>;
125
+
126
+ export async function propagate<Input, Output extends IPropagation<any, any>>(
127
+ connection: IConnection,
128
+ route: IFetchRoute<"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT">,
129
+ input?: Input,
130
+ stringify?: (input: Input) => string,
131
+ ): Promise<Output> {
132
+ if (
133
+ (route.request?.encrypted === true || route.response?.encrypted) &&
134
+ connection.encryption === undefined
135
+ )
136
+ throw new Error(
137
+ "Error on EncryptedFetcher.propagate(): the encryption password has not been configured.",
138
+ );
139
+ const closure =
140
+ typeof connection.encryption === "function"
141
+ ? (direction: "encode" | "decode") =>
142
+ (
143
+ headers: Record<string, IConnection.HeaderValue | undefined>,
144
+ body: string,
145
+ ) =>
146
+ (connection.encryption as IEncryptionPassword.Closure)({
147
+ headers,
148
+ body,
149
+ direction,
150
+ })
151
+ : () => () => connection.encryption as IEncryptionPassword;
152
+
153
+ return FetcherBase.propagate({
154
+ className: "EncryptedFetcher",
155
+ encode:
156
+ route.request?.encrypted === true
157
+ ? (input, headers) => {
158
+ const p: IEncryptionPassword = closure("encode")(headers, input);
159
+ return AesPkcs5.encrypt(
160
+ (stringify ?? JSON.stringify)(input),
161
+ p.key,
162
+ p.iv,
163
+ );
164
+ }
165
+ : (input) => input,
166
+ decode:
167
+ route.response?.encrypted === true
168
+ ? (input, headers) => {
169
+ const p: IEncryptionPassword = closure("decode")(headers, input);
170
+ const s: string = AesPkcs5.decrypt(input, p.key, p.iv);
171
+ return s.length ? JSON.parse(s) : s;
172
+ }
173
+ : (input) => input,
174
+ })(connection, route, input, stringify) as Promise<Output>;
175
+ }
176
+ }