@nestia/fetcher 2.0.0-dev.20230991 → 2.0.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/lib/EncryptedFetcher.d.ts +3 -0
- package/lib/EncryptedFetcher.js +39 -0
- package/lib/EncryptedFetcher.js.map +1 -1
- package/lib/HttpError.d.ts +3 -1
- package/lib/HttpError.js +3 -1
- package/lib/HttpError.js.map +1 -1
- package/lib/IPropagation.d.ts +71 -0
- package/lib/IPropagation.js +3 -0
- package/lib/IPropagation.js.map +1 -0
- package/lib/PlainFetcher.d.ts +3 -0
- package/lib/PlainFetcher.js +16 -0
- package/lib/PlainFetcher.js.map +1 -1
- package/lib/Primitive.d.ts +15 -13
- package/lib/Resolved.d.ts +46 -0
- package/lib/Resolved.js +3 -0
- package/lib/Resolved.js.map +1 -0
- package/lib/index.d.ts +3 -1
- package/lib/index.js +3 -1
- package/lib/index.js.map +1 -1
- package/lib/internal/FetcherBase.d.ts +2 -0
- package/lib/internal/FetcherBase.js +153 -99
- package/lib/internal/FetcherBase.js.map +1 -1
- package/package.json +2 -2
- package/src/EncryptedFetcher.ts +76 -0
- package/src/HttpError.ts +3 -0
- package/src/IPropagation.ts +103 -0
- package/src/PlainFetcher.ts +40 -0
- package/src/Primitive.ts +20 -16
- package/src/Resolved.ts +116 -0
- package/src/index.ts +3 -1
- package/src/internal/FetcherBase.ts +87 -39
package/src/Primitive.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Primitive type.
|
|
2
|
+
* Primitive type of JSON.
|
|
3
3
|
*
|
|
4
|
-
* `Primitive
|
|
5
|
-
* primitive type.
|
|
4
|
+
* `Primitive<T>` is a TMP (Type Meta Programming) type which converts
|
|
5
|
+
* its argument as a primitive type within framework JSON.
|
|
6
6
|
*
|
|
7
|
-
* If the target argument is a built-in class
|
|
8
|
-
* the `valueOf()` method like the `String` or `Number`, its return type would
|
|
9
|
-
* `string` or `number`.
|
|
7
|
+
* If the target argument is a built-in class which returns its origin primitive type
|
|
8
|
+
* through the `valueOf()` method like the `String` or `Number`, its return type would
|
|
9
|
+
* be the `string` or `number`. Otherwise, the built-in class does not have the
|
|
10
|
+
* `valueOf()` method, the return type would be an empty object (`{}`).
|
|
10
11
|
*
|
|
11
|
-
* Otherwise, the target argument is a type of custom class, all of its custom method
|
|
12
|
-
* be erased and its prototype would be changed to the primitive `object`.
|
|
13
|
-
* type of the TMP type finally be the primitive object.
|
|
12
|
+
* Otherwise, the target argument is a type of custom class, all of its custom method
|
|
13
|
+
* would be erased and its prototype would be changed to the primitive `object`.
|
|
14
|
+
* Therefore, return type of the TMP type finally be the primitive object.
|
|
14
15
|
*
|
|
15
16
|
* In addition, if the target argument is a type of custom class and it has a special
|
|
16
17
|
* method `toJSON()`, return type of this `Primitive` would be not `Primitive<Instance>`
|
|
@@ -23,10 +24,11 @@
|
|
|
23
24
|
* `String` | `string`
|
|
24
25
|
* `Class` | `object`
|
|
25
26
|
* `Class` with `toJSON()` | `Primitive<ReturnType<Class.toJSON>>`
|
|
27
|
+
* Native Class | `{}`
|
|
26
28
|
* Others | No change
|
|
27
29
|
*
|
|
28
30
|
* @template Instance Target argument type.
|
|
29
|
-
* @author
|
|
31
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
30
32
|
* @author Kyungsu Kang - https://github.com/kakasoo
|
|
31
33
|
* @author Michael - https://github.com/8471919
|
|
32
34
|
*/
|
|
@@ -38,8 +40,12 @@ type Equal<X, Y> = X extends Y ? (Y extends X ? true : false) : false;
|
|
|
38
40
|
|
|
39
41
|
type PrimitiveMain<Instance> = Instance extends [never]
|
|
40
42
|
? never // (special trick for jsonable | null) type
|
|
41
|
-
: ValueOf<Instance> extends
|
|
43
|
+
: ValueOf<Instance> extends bigint
|
|
44
|
+
? never
|
|
45
|
+
: ValueOf<Instance> extends boolean | number | string
|
|
42
46
|
? ValueOf<Instance>
|
|
47
|
+
: Instance extends Function
|
|
48
|
+
? never
|
|
43
49
|
: ValueOf<Instance> extends object
|
|
44
50
|
? Instance extends object
|
|
45
51
|
? Instance extends NativeClass
|
|
@@ -59,9 +65,7 @@ type PrimitiveObject<Instance extends object> = Instance extends Array<infer T>
|
|
|
59
65
|
? PrimitiveTuple<Instance>
|
|
60
66
|
: PrimitiveMain<T>[]
|
|
61
67
|
: {
|
|
62
|
-
[P in keyof Instance]: Instance[P]
|
|
63
|
-
? never
|
|
64
|
-
: PrimitiveMain<Instance[P]>;
|
|
68
|
+
[P in keyof Instance]: PrimitiveMain<Instance[P]>;
|
|
65
69
|
};
|
|
66
70
|
|
|
67
71
|
type PrimitiveTuple<T extends readonly any[]> = T extends []
|
|
@@ -115,8 +119,8 @@ type IsTuple<T extends readonly any[] | { length: number }> = [T] extends [
|
|
|
115
119
|
: false;
|
|
116
120
|
|
|
117
121
|
type IsValueOf<Instance, Object extends IValueOf<any>> = Instance extends Object
|
|
118
|
-
? Object extends IValueOf<infer
|
|
119
|
-
? Instance extends
|
|
122
|
+
? Object extends IValueOf<infer U>
|
|
123
|
+
? Instance extends U
|
|
120
124
|
? false
|
|
121
125
|
: true // not Primitive, but Object
|
|
122
126
|
: false // cannot be
|
package/src/Resolved.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolved type erased every methods.
|
|
3
|
+
*
|
|
4
|
+
* `Resolved` is a type of TMP (Type Meta Programming) type which converts
|
|
5
|
+
* its argument as a resolved type that erased every method properties.
|
|
6
|
+
*
|
|
7
|
+
* If the target argument is a built-in class which returns its origin primitive type
|
|
8
|
+
* through the `valueOf()` method like the `String` or `Number`, its return type would
|
|
9
|
+
* be the `string` or `number`. Otherwise, the built-in class does not have the
|
|
10
|
+
* `valueOf()` method, the return type would be same with the target argument.
|
|
11
|
+
*
|
|
12
|
+
* Otherwise, the target argument is a type of custom class, all of its custom methods
|
|
13
|
+
* would be erased and its prototype would be changed to the primitive `object`.
|
|
14
|
+
* Therefore, return type of the TMP type finally be the resolved object.
|
|
15
|
+
*
|
|
16
|
+
* Before | After
|
|
17
|
+
* ------------------------|----------------------------------------
|
|
18
|
+
* `Boolean` | `boolean`
|
|
19
|
+
* `Number` | `number`
|
|
20
|
+
* `BigInt` | `bigint`
|
|
21
|
+
* `String` | `string`
|
|
22
|
+
* `Class` | `interface`
|
|
23
|
+
* Native Class or Others | No change
|
|
24
|
+
*
|
|
25
|
+
* @template Instance Target argument type.
|
|
26
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
27
|
+
* @author Kyungsu Kang - https://github.com/kakasoo
|
|
28
|
+
*/
|
|
29
|
+
export type Resolved<T> = Equal<T, ResolvedMain<T>> extends true
|
|
30
|
+
? T
|
|
31
|
+
: ResolvedMain<T>;
|
|
32
|
+
|
|
33
|
+
type Equal<X, Y> = X extends Y ? (Y extends X ? true : false) : false;
|
|
34
|
+
|
|
35
|
+
type ResolvedMain<Instance> = Instance extends [never]
|
|
36
|
+
? never // (special trick for jsonable | null) type
|
|
37
|
+
: ValueOf<Instance> extends boolean | number | bigint | string
|
|
38
|
+
? ValueOf<Instance>
|
|
39
|
+
: Instance extends Function
|
|
40
|
+
? never
|
|
41
|
+
: Instance extends object
|
|
42
|
+
? ResolvedObject<Instance>
|
|
43
|
+
: ValueOf<Instance>;
|
|
44
|
+
|
|
45
|
+
type ResolvedObject<Instance extends object> = Instance extends Array<infer T>
|
|
46
|
+
? IsTuple<Instance> extends true
|
|
47
|
+
? ResolvedTuple<Instance>
|
|
48
|
+
: ResolvedMain<T>[]
|
|
49
|
+
: Instance extends Set<infer U>
|
|
50
|
+
? Set<ResolvedMain<U>>
|
|
51
|
+
: Instance extends Map<infer K, infer V>
|
|
52
|
+
? Map<ResolvedMain<K>, ResolvedMain<V>>
|
|
53
|
+
: Instance extends WeakSet<any> | WeakMap<any, any>
|
|
54
|
+
? never
|
|
55
|
+
: Instance extends
|
|
56
|
+
| Date
|
|
57
|
+
| Uint8Array
|
|
58
|
+
| Uint8ClampedArray
|
|
59
|
+
| Uint16Array
|
|
60
|
+
| Uint32Array
|
|
61
|
+
| BigUint64Array
|
|
62
|
+
| Int8Array
|
|
63
|
+
| Int16Array
|
|
64
|
+
| Int32Array
|
|
65
|
+
| BigInt64Array
|
|
66
|
+
| Float32Array
|
|
67
|
+
| Float64Array
|
|
68
|
+
| ArrayBuffer
|
|
69
|
+
| SharedArrayBuffer
|
|
70
|
+
| DataView
|
|
71
|
+
? Instance
|
|
72
|
+
: {
|
|
73
|
+
[P in keyof Instance]: ResolvedMain<Instance[P]>;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
type ResolvedTuple<T extends readonly any[]> = T extends []
|
|
77
|
+
? []
|
|
78
|
+
: T extends [infer F]
|
|
79
|
+
? [ResolvedMain<F>]
|
|
80
|
+
: T extends [infer F, ...infer Rest extends readonly any[]]
|
|
81
|
+
? [ResolvedMain<F>, ...ResolvedTuple<Rest>]
|
|
82
|
+
: T extends [(infer F)?]
|
|
83
|
+
? [ResolvedMain<F>?]
|
|
84
|
+
: T extends [(infer F)?, ...infer Rest extends readonly any[]]
|
|
85
|
+
? [ResolvedMain<F>?, ...ResolvedTuple<Rest>]
|
|
86
|
+
: [];
|
|
87
|
+
|
|
88
|
+
type ValueOf<Instance> = IsValueOf<Instance, Boolean> extends true
|
|
89
|
+
? boolean
|
|
90
|
+
: IsValueOf<Instance, Number> extends true
|
|
91
|
+
? number
|
|
92
|
+
: IsValueOf<Instance, String> extends true
|
|
93
|
+
? string
|
|
94
|
+
: Instance;
|
|
95
|
+
|
|
96
|
+
type IsTuple<T extends readonly any[] | { length: number }> = [T] extends [
|
|
97
|
+
never,
|
|
98
|
+
]
|
|
99
|
+
? false
|
|
100
|
+
: T extends readonly any[]
|
|
101
|
+
? number extends T["length"]
|
|
102
|
+
? false
|
|
103
|
+
: true
|
|
104
|
+
: false;
|
|
105
|
+
|
|
106
|
+
type IsValueOf<Instance, Object extends IValueOf<any>> = Instance extends Object
|
|
107
|
+
? Object extends IValueOf<infer Primitive>
|
|
108
|
+
? Instance extends Primitive
|
|
109
|
+
? false
|
|
110
|
+
: true // not Primitive, but Object
|
|
111
|
+
: false // cannot be
|
|
112
|
+
: false;
|
|
113
|
+
|
|
114
|
+
interface IValueOf<T> {
|
|
115
|
+
valueOf(): T;
|
|
116
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export * from "./IConnection";
|
|
2
2
|
export * from "./IEncryptionPassword";
|
|
3
|
+
export * from "./IPropagation";
|
|
3
4
|
export * from "./IRandomGenerator";
|
|
4
|
-
export * from "./Primitive";
|
|
5
5
|
export * from "./HttpError";
|
|
6
|
+
export * from "./Primitive";
|
|
7
|
+
export * from "./Resolved";
|
|
@@ -4,6 +4,7 @@ import { Primitive } from "../Primitive";
|
|
|
4
4
|
import { IFetchRoute } from "./IFetchRoute";
|
|
5
5
|
import { Singleton } from "./Singleton";
|
|
6
6
|
import { HttpError } from "../HttpError";
|
|
7
|
+
import { IPropagation } from "../IPropagation";
|
|
7
8
|
|
|
8
9
|
export namespace FetcherBase {
|
|
9
10
|
export interface IProps {
|
|
@@ -28,6 +29,49 @@ export namespace FetcherBase {
|
|
|
28
29
|
input?: Input,
|
|
29
30
|
stringify?: (input: Input) => string,
|
|
30
31
|
): Promise<Primitive<Output>> => {
|
|
32
|
+
const result = await _Propagate("fetch")(props)(
|
|
33
|
+
connection,
|
|
34
|
+
route,
|
|
35
|
+
input,
|
|
36
|
+
stringify,
|
|
37
|
+
);
|
|
38
|
+
if ((result as any).success === false)
|
|
39
|
+
throw new HttpError(
|
|
40
|
+
route.method,
|
|
41
|
+
route.path,
|
|
42
|
+
result.status as any as number,
|
|
43
|
+
result.headers,
|
|
44
|
+
result.data as string,
|
|
45
|
+
);
|
|
46
|
+
return result.data as Primitive<Output>;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const propagate =
|
|
50
|
+
(props: IProps) =>
|
|
51
|
+
async <Input>(
|
|
52
|
+
connection: IConnection,
|
|
53
|
+
route: IFetchRoute<
|
|
54
|
+
"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT"
|
|
55
|
+
>,
|
|
56
|
+
input?: Input,
|
|
57
|
+
stringify?: (input: Input) => string,
|
|
58
|
+
): Promise<IPropagation<any, any>> =>
|
|
59
|
+
_Propagate("propagate")(props)(connection, route, input, stringify);
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @internal
|
|
63
|
+
*/
|
|
64
|
+
const _Propagate =
|
|
65
|
+
(method: string) =>
|
|
66
|
+
(props: IProps) =>
|
|
67
|
+
async <Input>(
|
|
68
|
+
connection: IConnection,
|
|
69
|
+
route: IFetchRoute<
|
|
70
|
+
"DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT"
|
|
71
|
+
>,
|
|
72
|
+
input?: Input,
|
|
73
|
+
stringify?: (input: Input) => string,
|
|
74
|
+
): Promise<IPropagation<any, any>> => {
|
|
31
75
|
//----
|
|
32
76
|
// REQUEST MESSSAGE
|
|
33
77
|
//----
|
|
@@ -86,46 +130,47 @@ export namespace FetcherBase {
|
|
|
86
130
|
await polyfill.get()
|
|
87
131
|
)(url.href, init);
|
|
88
132
|
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
response.status
|
|
94
|
-
response.status
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
133
|
+
// CONSTRUCT RESULT DATA
|
|
134
|
+
const result: IPropagation<any, any> = {
|
|
135
|
+
success:
|
|
136
|
+
response.status === 200 ||
|
|
137
|
+
response.status === 201 ||
|
|
138
|
+
response.status == route.status,
|
|
139
|
+
status: response.status,
|
|
140
|
+
headers: response_headers_to_object(response.headers),
|
|
141
|
+
data: undefined!,
|
|
142
|
+
} as any;
|
|
143
|
+
if ((result as any).success === false) {
|
|
144
|
+
// WHEN FAILED
|
|
145
|
+
result.data = await response.text();
|
|
146
|
+
const type = response.headers.get("content-type");
|
|
147
|
+
if (
|
|
148
|
+
method !== "fetch" &&
|
|
149
|
+
type &&
|
|
150
|
+
type.indexOf("application/json") !== -1
|
|
151
|
+
)
|
|
152
|
+
try {
|
|
153
|
+
result.data = JSON.parse(result.data);
|
|
154
|
+
} catch {}
|
|
155
|
+
} else {
|
|
156
|
+
// WHEN SUCCESS
|
|
157
|
+
if (route.method === "HEAD") result.data = undefined!;
|
|
158
|
+
else if (route.response?.type === "application/json") {
|
|
159
|
+
const text: string = await response.text();
|
|
160
|
+
result.data = text.length ? JSON.parse(text) : undefined;
|
|
161
|
+
} else
|
|
162
|
+
result.data = props.decode(
|
|
163
|
+
await response.text(),
|
|
164
|
+
result.headers,
|
|
165
|
+
);
|
|
121
166
|
}
|
|
122
|
-
return
|
|
123
|
-
await response.text(),
|
|
124
|
-
response_headers_to_object(response.headers),
|
|
125
|
-
) as Primitive<Output>;
|
|
167
|
+
return result;
|
|
126
168
|
};
|
|
127
169
|
}
|
|
128
170
|
|
|
171
|
+
/**
|
|
172
|
+
* @internal
|
|
173
|
+
*/
|
|
129
174
|
const polyfill = new Singleton(async (): Promise<typeof fetch> => {
|
|
130
175
|
if (
|
|
131
176
|
typeof global === "object" &&
|
|
@@ -134,16 +179,19 @@ const polyfill = new Singleton(async (): Promise<typeof fetch> => {
|
|
|
134
179
|
typeof global.process.versions.node !== undefined
|
|
135
180
|
) {
|
|
136
181
|
if (global.fetch === undefined)
|
|
137
|
-
global.fetch
|
|
182
|
+
global.fetch ??= ((await import2("node-fetch")) as any).default;
|
|
138
183
|
return (global as any).fetch;
|
|
139
184
|
}
|
|
140
185
|
return window.fetch;
|
|
141
186
|
});
|
|
142
187
|
|
|
188
|
+
/**
|
|
189
|
+
* @internal
|
|
190
|
+
*/
|
|
143
191
|
const response_headers_to_object = (
|
|
144
192
|
headers: Headers,
|
|
145
|
-
): Record<string,
|
|
146
|
-
const output: Record<string,
|
|
193
|
+
): Record<string, string | string[]> => {
|
|
194
|
+
const output: Record<string, string | string[]> = {};
|
|
147
195
|
headers.forEach((value, key) => {
|
|
148
196
|
if (key === "set-cookie") {
|
|
149
197
|
output[key] ??= [];
|