@nestia/fetcher 4.4.0-dev.20241216-2 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,87 +1,87 @@
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
- [![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)
10
-
11
- Nestia is a set of helper libraries for NestJS, supporting below features:
12
-
13
- - `@nestia/core`:
14
- - Super-fast/easy decorators
15
- - Advanced WebSocket routes
16
- - `@nestia/sdk`:
17
- - Swagger generator evolved than ever
18
- - SDK library generator for clients
19
- - Mockup Simulator for client applications
20
- - Automatic E2E test functions generator
21
- - `@nestia/e2e`: Test program utilizing e2e test functions
22
- - `@nestia/benchmark`: Benchmark program using e2e test functions
23
- - `@nestia/migrate`: OpenAPI generator from Swagger to NestJS/SDK
24
- - `@nestia/editor`: Swagger-UI with Online TypeScript Editor
25
- - `nestia`: Just CLI (command line interface) tool
26
-
27
- > [!NOTE]
28
- >
29
- > - **Only one line** required, with pure TypeScript type
30
- > - Enhance performance **30x** up
31
- > - Runtime validator is **20,000x faster** than `class-validator`
32
- > - JSON serialization is **200x faster** than `class-transformer`
33
- > - Software Development Kit
34
- > - Collection of typed `fetch` functions with DTO structures like [tRPC](https://trpc.io/)
35
- > - Mockup simulator means embedded backend simulator in the SDK
36
- > - similar with [msw](https://mswjs.io/), but fully automated
37
-
38
- ![nestia-sdk-demo](https://user-images.githubusercontent.com/13158709/215004990-368c589d-7101-404e-b81b-fbc936382f05.gif)
39
-
40
- > Left is NestJS server code, and right is client (frontend) code utilizing SDK
41
-
42
-
43
-
44
-
45
- ## Sponsors and Backers
46
- Thanks for your support.
47
-
48
- Your donation would encourage `nestia` development.
49
-
50
- [![Backers](https://opencollective.com/nestia/backers.svg?avatarHeight=75&width=600)](https://opencollective.com/nestia)
51
-
52
-
53
-
54
-
55
- ## Guide Documents
56
- Check out the document in the [website](https://nestia.io/docs/):
57
-
58
- ### 🏠 Home
59
- - [Introduction](https://nestia.io/docs/)
60
- - [Setup](https://nestia.io/docs/setup/)
61
- - [Pure TypeScript](https://nestia.io/docs/pure)
62
-
63
- ### 📖 Features
64
- - Core Library
65
- - [WebSocketRoute](https://nestia.io/docs/core/WebSocketRoute)
66
- - [TypedRoute](https://nestia.io/docs/core/TypedRoute/)
67
- - [TypedBody](https://nestia.io/docs/core/TypedBody/)
68
- - [TypedParam](https://nestia.io/docs/core/TypedParam/)
69
- - [TypedQuery](https://nestia.io/docs/core/TypedQuery/)
70
- - [TypedHeaders](https://nestia.io/docs/core/TypedHeaders/)
71
- - [TypedException](https://nestia.io/docs/core/TypedException/)
72
- - Generators
73
- - [Swagger Documents](https://nestia.io/docs/sdk/swagger/)
74
- - [Software Development Kit](https://nestia.io/docs/sdk/sdk/)
75
- - [E2E Functions](https://nestia.io/docs/sdk/e2e/)
76
- - [Mockup Simulator](https://nestia.io/docs/sdk/simulator/)
77
- - E2E Testing
78
- - [Why E2E Test?](https://nestia.io/docs/e2e/why/)
79
- - [Test Program Development](https://nestia.io/docs/e2e/development/)
80
- - [Performance Benchmark](https://nestia.io/docs/e2e/benchmark/)
81
- - [Swagger to NestJS](https://nestia.io/docs/migrate/)
82
- - [TypeScript Swagger Editor](https://nestia.io/docs/editor/)
83
-
84
- ### 🔗 Appendix
85
- - [API Documents](https://nestia.io/api)
86
- - [⇲ Benchmark Result](https://github.com/samchon/nestia/tree/master/benchmark/results/11th%20Gen%20Intel(R)%20Core(TM)%20i5-1135G7%20%40%202.40GHz)
87
- - [⇲ `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
+ [![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)
10
+
11
+ Nestia is a set of helper libraries for NestJS, supporting below features:
12
+
13
+ - `@nestia/core`:
14
+ - Super-fast/easy decorators
15
+ - Advanced WebSocket routes
16
+ - `@nestia/sdk`:
17
+ - Swagger generator evolved than ever
18
+ - SDK library generator for clients
19
+ - Mockup Simulator for client applications
20
+ - Automatic E2E test functions generator
21
+ - `@nestia/e2e`: Test program utilizing e2e test functions
22
+ - `@nestia/benchmark`: Benchmark program using e2e test functions
23
+ - `@nestia/migrate`: OpenAPI generator from Swagger to NestJS/SDK
24
+ - `@nestia/editor`: Swagger-UI with Online TypeScript Editor
25
+ - `nestia`: Just CLI (command line interface) tool
26
+
27
+ > [!NOTE]
28
+ >
29
+ > - **Only one line** required, with pure TypeScript type
30
+ > - Enhance performance **30x** up
31
+ > - Runtime validator is **20,000x faster** than `class-validator`
32
+ > - JSON serialization is **200x faster** than `class-transformer`
33
+ > - Software Development Kit
34
+ > - Collection of typed `fetch` functions with DTO structures like [tRPC](https://trpc.io/)
35
+ > - Mockup simulator means embedded backend simulator in the SDK
36
+ > - similar with [msw](https://mswjs.io/), but fully automated
37
+
38
+ ![nestia-sdk-demo](https://user-images.githubusercontent.com/13158709/215004990-368c589d-7101-404e-b81b-fbc936382f05.gif)
39
+
40
+ > Left is NestJS server code, and right is client (frontend) code utilizing SDK
41
+
42
+
43
+
44
+
45
+ ## Sponsors and Backers
46
+ Thanks for your support.
47
+
48
+ Your donation would encourage `nestia` development.
49
+
50
+ [![Backers](https://opencollective.com/nestia/backers.svg?avatarHeight=75&width=600)](https://opencollective.com/nestia)
51
+
52
+
53
+
54
+
55
+ ## Guide Documents
56
+ Check out the document in the [website](https://nestia.io/docs/):
57
+
58
+ ### 🏠 Home
59
+ - [Introduction](https://nestia.io/docs/)
60
+ - [Setup](https://nestia.io/docs/setup/)
61
+ - [Pure TypeScript](https://nestia.io/docs/pure)
62
+
63
+ ### 📖 Features
64
+ - Core Library
65
+ - [WebSocketRoute](https://nestia.io/docs/core/WebSocketRoute)
66
+ - [TypedRoute](https://nestia.io/docs/core/TypedRoute/)
67
+ - [TypedBody](https://nestia.io/docs/core/TypedBody/)
68
+ - [TypedParam](https://nestia.io/docs/core/TypedParam/)
69
+ - [TypedQuery](https://nestia.io/docs/core/TypedQuery/)
70
+ - [TypedHeaders](https://nestia.io/docs/core/TypedHeaders/)
71
+ - [TypedException](https://nestia.io/docs/core/TypedException/)
72
+ - Generators
73
+ - [Swagger Documents](https://nestia.io/docs/sdk/swagger/)
74
+ - [Software Development Kit](https://nestia.io/docs/sdk/sdk/)
75
+ - [E2E Functions](https://nestia.io/docs/sdk/e2e/)
76
+ - [Mockup Simulator](https://nestia.io/docs/sdk/simulator/)
77
+ - E2E Testing
78
+ - [Why E2E Test?](https://nestia.io/docs/e2e/why/)
79
+ - [Test Program Development](https://nestia.io/docs/e2e/development/)
80
+ - [Performance Benchmark](https://nestia.io/docs/e2e/benchmark/)
81
+ - [Swagger to NestJS](https://nestia.io/docs/migrate/)
82
+ - [TypeScript Swagger Editor](https://nestia.io/docs/editor/)
83
+
84
+ ### 🔗 Appendix
85
+ - [API Documents](https://nestia.io/api)
86
+ - [⇲ Benchmark Result](https://github.com/samchon/nestia/tree/master/benchmark/results/11th%20Gen%20Intel(R)%20Core(TM)%20i5-1135G7%20%40%202.40GHz)
87
+ - [⇲ `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": "4.4.0-dev.20241216-2",
3
+ "version": "4.4.0",
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,50 +1,50 @@
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
- * @return 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
- * @return 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
-
48
- return decipher.update(data, "base64", "utf8") + decipher.final("utf8");
49
- }
50
- }
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
+ * @return 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
+ * @return 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
+
48
+ return decipher.update(data, "base64", "utf8") + decipher.final("utf8");
49
+ }
50
+ }
@@ -1,174 +1,174 @@
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 collection of
14
- * dedicated `fetch()` functions for `@nestia/sdk` with encryption.
15
- *
16
- * For reference, `EncryptedFetcher` class being used only when target controller
17
- * method is encrypting body data by `@EncryptedRoute` or `@EncryptedBody` decorators.
18
- * If those decorators are not used, {@link PlainFetcher} class would be used instead.
19
- *
20
- * @author Jeongho Nam - https://github.com/samchon
21
- */
22
- export namespace EncryptedFetcher {
23
- /**
24
- * Fetch function only for `HEAD` method.
25
- *
26
- * @param connection Connection information for the remote HTTP server
27
- * @param route Route information about the target API
28
- * @return Nothing because of `HEAD` method
29
- */
30
- export function fetch(
31
- connection: IConnection,
32
- route: IFetchRoute<"HEAD">,
33
- ): Promise<void>;
34
-
35
- /**
36
- * Fetch function only for `GET` method.
37
- *
38
- * @param connection Connection information for the remote HTTP server
39
- * @param route Route information about the target API
40
- * @return Response body data from the remote API
41
- */
42
- export function fetch<Output>(
43
- connection: IConnection,
44
- route: IFetchRoute<"GET">,
45
- ): Promise<Output>;
46
-
47
- /**
48
- * Fetch function for the `POST`, `PUT`, `PATCH` and `DELETE` methods.
49
- *
50
- * @param connection Connection information for the remote HTTP server
51
- * @param route Route information about the target API
52
- * @return Response body data from the remote API
53
- */
54
- export function fetch<Input, Output>(
55
- connection: IConnection,
56
- route: IFetchRoute<"POST" | "PUT" | "PATCH" | "DELETE">,
57
- input?: Input,
58
- stringify?: (input: Input) => string,
59
- ): Promise<Output>;
60
-
61
- export async function fetch<Input, Output>(
62
- connection: IConnection,
63
- route: IFetchRoute<"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT">,
64
- input?: Input,
65
- stringify?: (input: Input) => string,
66
- ): Promise<Output> {
67
- if (
68
- (route.request?.encrypted === true || route.response?.encrypted) &&
69
- connection.encryption === undefined
70
- )
71
- throw new Error(
72
- "Error on EncryptedFetcher.fetch(): the encryption password has not been configured.",
73
- );
74
- const closure =
75
- typeof connection.encryption === "function"
76
- ? (direction: "encode" | "decode") =>
77
- (
78
- headers: Record<string, IConnection.HeaderValue | undefined>,
79
- body: string,
80
- ) =>
81
- (connection.encryption as IEncryptionPassword.Closure)({
82
- headers,
83
- body,
84
- direction,
85
- })
86
- : () => () => connection.encryption as IEncryptionPassword;
87
-
88
- return FetcherBase.request({
89
- className: "EncryptedFetcher",
90
- encode:
91
- route.request?.encrypted === true
92
- ? (input, headers) => {
93
- const p: IEncryptionPassword = closure("encode")(headers, input);
94
- return AesPkcs5.encrypt(
95
- (stringify ?? JSON.stringify)(input),
96
- p.key,
97
- p.iv,
98
- );
99
- }
100
- : (input) => input,
101
- decode:
102
- route.response?.encrypted === true
103
- ? (input, headers) => {
104
- const p: IEncryptionPassword = closure("decode")(headers, input);
105
- const s: string = AesPkcs5.decrypt(input, p.key, p.iv);
106
- return s.length ? JSON.parse(s) : s;
107
- }
108
- : (input) => input,
109
- })(connection, route, input, stringify);
110
- }
111
-
112
- export function propagate<Output extends IPropagation<any, any>>(
113
- connection: IConnection,
114
- route: IFetchRoute<"GET" | "HEAD">,
115
- ): Promise<Output>;
116
-
117
- export function propagate<Input, Output extends IPropagation<any, any>>(
118
- connection: IConnection,
119
- route: IFetchRoute<"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT">,
120
- input?: Input,
121
- stringify?: (input: Input) => string,
122
- ): Promise<Output>;
123
-
124
- export async function propagate<Input, Output extends IPropagation<any, any>>(
125
- connection: IConnection,
126
- route: IFetchRoute<"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT">,
127
- input?: Input,
128
- stringify?: (input: Input) => string,
129
- ): Promise<Output> {
130
- if (
131
- (route.request?.encrypted === true || route.response?.encrypted) &&
132
- connection.encryption === undefined
133
- )
134
- throw new Error(
135
- "Error on EncryptedFetcher.propagate(): the encryption password has not been configured.",
136
- );
137
- const closure =
138
- typeof connection.encryption === "function"
139
- ? (direction: "encode" | "decode") =>
140
- (
141
- headers: Record<string, IConnection.HeaderValue | undefined>,
142
- body: string,
143
- ) =>
144
- (connection.encryption as IEncryptionPassword.Closure)({
145
- headers,
146
- body,
147
- direction,
148
- })
149
- : () => () => connection.encryption as IEncryptionPassword;
150
-
151
- return FetcherBase.propagate({
152
- className: "EncryptedFetcher",
153
- encode:
154
- route.request?.encrypted === true
155
- ? (input, headers) => {
156
- const p: IEncryptionPassword = closure("encode")(headers, input);
157
- return AesPkcs5.encrypt(
158
- (stringify ?? JSON.stringify)(input),
159
- p.key,
160
- p.iv,
161
- );
162
- }
163
- : (input) => input,
164
- decode:
165
- route.response?.encrypted === true
166
- ? (input, headers) => {
167
- const p: IEncryptionPassword = closure("decode")(headers, input);
168
- const s: string = AesPkcs5.decrypt(input, p.key, p.iv);
169
- return s.length ? JSON.parse(s) : s;
170
- }
171
- : (input) => input,
172
- })(connection, route, input, stringify) as Promise<Output>;
173
- }
174
- }
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 collection of
14
+ * dedicated `fetch()` functions for `@nestia/sdk` with encryption.
15
+ *
16
+ * For reference, `EncryptedFetcher` class being used only when target controller
17
+ * method is encrypting body data by `@EncryptedRoute` or `@EncryptedBody` decorators.
18
+ * If those decorators are not used, {@link PlainFetcher} class would be used instead.
19
+ *
20
+ * @author Jeongho Nam - https://github.com/samchon
21
+ */
22
+ export namespace EncryptedFetcher {
23
+ /**
24
+ * Fetch function only for `HEAD` method.
25
+ *
26
+ * @param connection Connection information for the remote HTTP server
27
+ * @param route Route information about the target API
28
+ * @return Nothing because of `HEAD` method
29
+ */
30
+ export function fetch(
31
+ connection: IConnection,
32
+ route: IFetchRoute<"HEAD">,
33
+ ): Promise<void>;
34
+
35
+ /**
36
+ * Fetch function only for `GET` method.
37
+ *
38
+ * @param connection Connection information for the remote HTTP server
39
+ * @param route Route information about the target API
40
+ * @return Response body data from the remote API
41
+ */
42
+ export function fetch<Output>(
43
+ connection: IConnection,
44
+ route: IFetchRoute<"GET">,
45
+ ): Promise<Output>;
46
+
47
+ /**
48
+ * Fetch function for the `POST`, `PUT`, `PATCH` and `DELETE` methods.
49
+ *
50
+ * @param connection Connection information for the remote HTTP server
51
+ * @param route Route information about the target API
52
+ * @return Response body data from the remote API
53
+ */
54
+ export function fetch<Input, Output>(
55
+ connection: IConnection,
56
+ route: IFetchRoute<"POST" | "PUT" | "PATCH" | "DELETE">,
57
+ input?: Input,
58
+ stringify?: (input: Input) => string,
59
+ ): Promise<Output>;
60
+
61
+ export async function fetch<Input, Output>(
62
+ connection: IConnection,
63
+ route: IFetchRoute<"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT">,
64
+ input?: Input,
65
+ stringify?: (input: Input) => string,
66
+ ): Promise<Output> {
67
+ if (
68
+ (route.request?.encrypted === true || route.response?.encrypted) &&
69
+ connection.encryption === undefined
70
+ )
71
+ throw new Error(
72
+ "Error on EncryptedFetcher.fetch(): the encryption password has not been configured.",
73
+ );
74
+ const closure =
75
+ typeof connection.encryption === "function"
76
+ ? (direction: "encode" | "decode") =>
77
+ (
78
+ headers: Record<string, IConnection.HeaderValue | undefined>,
79
+ body: string,
80
+ ) =>
81
+ (connection.encryption as IEncryptionPassword.Closure)({
82
+ headers,
83
+ body,
84
+ direction,
85
+ })
86
+ : () => () => connection.encryption as IEncryptionPassword;
87
+
88
+ return FetcherBase.request({
89
+ className: "EncryptedFetcher",
90
+ encode:
91
+ route.request?.encrypted === true
92
+ ? (input, headers) => {
93
+ const p: IEncryptionPassword = closure("encode")(headers, input);
94
+ return AesPkcs5.encrypt(
95
+ (stringify ?? JSON.stringify)(input),
96
+ p.key,
97
+ p.iv,
98
+ );
99
+ }
100
+ : (input) => input,
101
+ decode:
102
+ route.response?.encrypted === true
103
+ ? (input, headers) => {
104
+ const p: IEncryptionPassword = closure("decode")(headers, input);
105
+ const s: string = AesPkcs5.decrypt(input, p.key, p.iv);
106
+ return s.length ? JSON.parse(s) : s;
107
+ }
108
+ : (input) => input,
109
+ })(connection, route, input, stringify);
110
+ }
111
+
112
+ export function propagate<Output extends IPropagation<any, any>>(
113
+ connection: IConnection,
114
+ route: IFetchRoute<"GET" | "HEAD">,
115
+ ): Promise<Output>;
116
+
117
+ export function propagate<Input, Output extends IPropagation<any, any>>(
118
+ connection: IConnection,
119
+ route: IFetchRoute<"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT">,
120
+ input?: Input,
121
+ stringify?: (input: Input) => string,
122
+ ): Promise<Output>;
123
+
124
+ export async function propagate<Input, Output extends IPropagation<any, any>>(
125
+ connection: IConnection,
126
+ route: IFetchRoute<"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT">,
127
+ input?: Input,
128
+ stringify?: (input: Input) => string,
129
+ ): Promise<Output> {
130
+ if (
131
+ (route.request?.encrypted === true || route.response?.encrypted) &&
132
+ connection.encryption === undefined
133
+ )
134
+ throw new Error(
135
+ "Error on EncryptedFetcher.propagate(): the encryption password has not been configured.",
136
+ );
137
+ const closure =
138
+ typeof connection.encryption === "function"
139
+ ? (direction: "encode" | "decode") =>
140
+ (
141
+ headers: Record<string, IConnection.HeaderValue | undefined>,
142
+ body: string,
143
+ ) =>
144
+ (connection.encryption as IEncryptionPassword.Closure)({
145
+ headers,
146
+ body,
147
+ direction,
148
+ })
149
+ : () => () => connection.encryption as IEncryptionPassword;
150
+
151
+ return FetcherBase.propagate({
152
+ className: "EncryptedFetcher",
153
+ encode:
154
+ route.request?.encrypted === true
155
+ ? (input, headers) => {
156
+ const p: IEncryptionPassword = closure("encode")(headers, input);
157
+ return AesPkcs5.encrypt(
158
+ (stringify ?? JSON.stringify)(input),
159
+ p.key,
160
+ p.iv,
161
+ );
162
+ }
163
+ : (input) => input,
164
+ decode:
165
+ route.response?.encrypted === true
166
+ ? (input, headers) => {
167
+ const p: IEncryptionPassword = closure("decode")(headers, input);
168
+ const s: string = AesPkcs5.decrypt(input, p.key, p.iv);
169
+ return s.length ? JSON.parse(s) : s;
170
+ }
171
+ : (input) => input,
172
+ })(connection, route, input, stringify) as Promise<Output>;
173
+ }
174
+ }