@nestia/fetcher 12.0.0-rc.1 → 12.0.0-rc.3

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2021 Jeongho Nam
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Jeongho Nam
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestia/fetcher",
3
- "version": "12.0.0-rc.1",
3
+ "version": "12.0.0-rc.3",
4
4
  "description": "Fetcher library of Nestia SDK",
5
5
  "types": "lib/index.d.ts",
6
6
  "main": "lib/index.js",
@@ -38,8 +38,8 @@
38
38
  },
39
39
  "homepage": "https://nestia.io",
40
40
  "dependencies": {
41
- "@typia/interface": "13.0.0-rc.1",
42
- "@typia/utils": "13.0.0-rc.1"
41
+ "@typia/interface": "^13.0.0",
42
+ "@typia/utils": "^13.0.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@rollup/plugin-commonjs": "^29.0.0",
package/src/AesPkcs5.ts CHANGED
@@ -1,41 +1,41 @@
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.createCipheriv(`AES-${bytes}-CBC`, key, iv);
25
- return cipher.update(data, "utf8", "base64") + cipher.final("base64");
26
- }
27
-
28
- /**
29
- * Decrypt data.
30
- *
31
- * @param data Target data
32
- * @param key Key value of the decryption.
33
- * @param iv Initializer Vector for the decryption
34
- * @returns Decrypted data.
35
- */
36
- export function decrypt(data: string, key: string, iv: string): string {
37
- const bytes: number = key.length * 8;
38
- const decipher = crypto.createDecipheriv(`AES-${bytes}-CBC`, key, iv);
39
- return decipher.update(data, "base64", "utf8") + decipher.final("utf8");
40
- }
41
- }
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.createCipheriv(`AES-${bytes}-CBC`, key, iv);
25
+ return cipher.update(data, "utf8", "base64") + cipher.final("base64");
26
+ }
27
+
28
+ /**
29
+ * Decrypt data.
30
+ *
31
+ * @param data Target data
32
+ * @param key Key value of the decryption.
33
+ * @param iv Initializer Vector for the decryption
34
+ * @returns Decrypted data.
35
+ */
36
+ export function decrypt(data: string, key: string, iv: string): string {
37
+ const bytes: number = key.length * 8;
38
+ const decipher = crypto.createDecipheriv(`AES-${bytes}-CBC`, key, iv);
39
+ return decipher.update(data, "base64", "utf8") + decipher.final("utf8");
40
+ }
41
+ }
@@ -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
+ }
@@ -1,80 +1,80 @@
1
- /**
2
- * FormData input type.
3
- *
4
- * `FormDataInput<T>` is a type for the input of the `FormData` request, casting
5
- * `File` property value type as an union of `File` and
6
- * {@link FormDataInput.IFileProps}, especially for the React Native
7
- * environment.
8
- *
9
- * You know what? In the React Native environment, `File` class is not
10
- * supported. Therefore, when composing a `FormData` request, you have to put
11
- * the URI address of the local filesystem with file name and content type that
12
- * is represented by the {@link FormDataInput.IFileProps} type.
13
- *
14
- * This `FormDataInput<T>` type is designed for that purpose. If the property
15
- * value type is a `File` class, it converts it to an union type of `File` and
16
- * {@link FormDataInput.IFileProps} type. Also, if the property value type is an
17
- * array of `File` class, it converts it to an array of union type of `File` and
18
- * {@link FormDataInput.IFileProps} type too.
19
- *
20
- * Before | After ----------|------------------------ `boolean` | `boolean`
21
- * `bigint` | `bigint` `number` | `number` `string` | `string` `File` | `File \|
22
- * IFileProps`
23
- *
24
- * @author Jeongho Nam - https://github.com/samchon
25
- * @template T Target object type.
26
- */
27
- export type FormDataInput<T extends object> =
28
- T extends Array<any>
29
- ? never
30
- : T extends Function
31
- ? never
32
- : {
33
- [P in keyof T]: T[P] extends Array<infer U>
34
- ? FormDataInput.Value<U>[]
35
- : FormDataInput.Value<T[P]>;
36
- };
37
- export namespace FormDataInput {
38
- /**
39
- * Value type of the `FormDataInput`.
40
- *
41
- * `Value<T>` is a type for the property value defined in the `FormDataInput`.
42
- *
43
- * If the original value type is a `File` class, `Value<T>` converts it to an
44
- * union type of `File` and {@link IFileProps} type which is a structured data
45
- * for the URI file location in the React Native environment.
46
- */
47
- export type Value<T> = T extends File ? T | IFileProps : T;
48
-
49
- /**
50
- * Properties of a file.
51
- *
52
- * In the React Native, this `IFileProps` structured data can replace the
53
- * `File` class instance in the `FormData` request.
54
- *
55
- * Just put the {@link uri URI address} of the local file system with the
56
- * file's {@link name} and {@link type}. It would be casted to the `File` class
57
- * instance automatically in the `FormData` request.
58
- *
59
- * Note that, this `IFileProps` type works only in the React Native
60
- * environment. If you are developing a Web or NodeJS application, you have to
61
- * utilize the `File` class instance directly.
62
- */
63
- export interface IFileProps {
64
- /**
65
- * URI address of the file.
66
- *
67
- * In the React Native, the URI address in the local file system can replace
68
- * the `File` class instance. If
69
- *
70
- * @format uri
71
- */
72
- uri: string;
73
-
74
- /** Name of the file. */
75
- name: string;
76
-
77
- /** Content type of the file. */
78
- type: string;
79
- }
80
- }
1
+ /**
2
+ * FormData input type.
3
+ *
4
+ * `FormDataInput<T>` is a type for the input of the `FormData` request, casting
5
+ * `File` property value type as an union of `File` and
6
+ * {@link FormDataInput.IFileProps}, especially for the React Native
7
+ * environment.
8
+ *
9
+ * You know what? In the React Native environment, `File` class is not
10
+ * supported. Therefore, when composing a `FormData` request, you have to put
11
+ * the URI address of the local filesystem with file name and content type that
12
+ * is represented by the {@link FormDataInput.IFileProps} type.
13
+ *
14
+ * This `FormDataInput<T>` type is designed for that purpose. If the property
15
+ * value type is a `File` class, it converts it to an union type of `File` and
16
+ * {@link FormDataInput.IFileProps} type. Also, if the property value type is an
17
+ * array of `File` class, it converts it to an array of union type of `File` and
18
+ * {@link FormDataInput.IFileProps} type too.
19
+ *
20
+ * Before | After ----------|------------------------ `boolean` | `boolean`
21
+ * `bigint` | `bigint` `number` | `number` `string` | `string` `File` | `File \|
22
+ * IFileProps`
23
+ *
24
+ * @author Jeongho Nam - https://github.com/samchon
25
+ * @template T Target object type.
26
+ */
27
+ export type FormDataInput<T extends object> =
28
+ T extends Array<any>
29
+ ? never
30
+ : T extends Function
31
+ ? never
32
+ : {
33
+ [P in keyof T]: T[P] extends Array<infer U>
34
+ ? FormDataInput.Value<U>[]
35
+ : FormDataInput.Value<T[P]>;
36
+ };
37
+ export namespace FormDataInput {
38
+ /**
39
+ * Value type of the `FormDataInput`.
40
+ *
41
+ * `Value<T>` is a type for the property value defined in the `FormDataInput`.
42
+ *
43
+ * If the original value type is a `File` class, `Value<T>` converts it to an
44
+ * union type of `File` and {@link IFileProps} type which is a structured data
45
+ * for the URI file location in the React Native environment.
46
+ */
47
+ export type Value<T> = T extends File ? T | IFileProps : T;
48
+
49
+ /**
50
+ * Properties of a file.
51
+ *
52
+ * In the React Native, this `IFileProps` structured data can replace the
53
+ * `File` class instance in the `FormData` request.
54
+ *
55
+ * Just put the {@link uri URI address} of the local file system with the
56
+ * file's {@link name} and {@link type}. It would be casted to the `File` class
57
+ * instance automatically in the `FormData` request.
58
+ *
59
+ * Note that, this `IFileProps` type works only in the React Native
60
+ * environment. If you are developing a Web or NodeJS application, you have to
61
+ * utilize the `File` class instance directly.
62
+ */
63
+ export interface IFileProps {
64
+ /**
65
+ * URI address of the file.
66
+ *
67
+ * In the React Native, the URI address in the local file system can replace
68
+ * the `File` class instance. If
69
+ *
70
+ * @format uri
71
+ */
72
+ uri: string;
73
+
74
+ /** Name of the file. */
75
+ name: string;
76
+
77
+ /** Content type of the file. */
78
+ type: string;
79
+ }
80
+ }
package/src/HttpError.ts CHANGED
@@ -1 +1 @@
1
- export { HttpError } from "@typia/utils";
1
+ export { HttpError } from "@typia/utils";