@defjs/core 0.0.0-test-0014 → 0.0.0-test-000
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 +21 -0
- package/{dist/index.d.ts → index.d.ts} +75 -27
- package/{dist/index.js → index.js} +281 -105
- package/package.json +14 -14
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 MunMunMiao
|
|
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,15 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
declare const HTTP_CONTEXT_TOKEN: unique symbol;
|
|
2
|
+
export type HttpContextToken<T> = (() => T) & {
|
|
3
|
+
readonly [HTTP_CONTEXT_TOKEN]: () => T;
|
|
4
|
+
};
|
|
2
5
|
export declare function makeHttpContextToken<T>(defaultValue: () => T): HttpContextToken<T>;
|
|
6
|
+
export declare function isHttpContextToken(value: unknown): value is HttpContextToken<unknown>;
|
|
3
7
|
export type HttpContext = {
|
|
4
8
|
set<T>(token: HttpContextToken<T>, value: T): HttpContext;
|
|
5
9
|
get<T>(token: HttpContextToken<T>): T;
|
|
6
|
-
|
|
10
|
+
del(token: HttpContextToken<unknown>): HttpContext;
|
|
7
11
|
has(token: HttpContextToken<unknown>): boolean;
|
|
8
12
|
keys(): IterableIterator<HttpContextToken<unknown>>;
|
|
9
13
|
};
|
|
10
14
|
export declare function makeHttpContext(): HttpContext;
|
|
11
15
|
export type ValidatorFn<T = unknown> = (value: T) => Error | null | undefined;
|
|
12
16
|
export type AsyncValidatorFn<T = unknown> = (value: T) => Promise<Error | null | undefined>;
|
|
17
|
+
export declare const required: ValidatorFn;
|
|
18
|
+
export declare const requiredTrue: ValidatorFn;
|
|
19
|
+
export declare const minLength: (min: number) => ValidatorFn;
|
|
20
|
+
export declare const maxLength: (max: number) => ValidatorFn;
|
|
21
|
+
export declare const min: (min: number) => ValidatorFn;
|
|
22
|
+
export declare const max: (max: number) => ValidatorFn;
|
|
23
|
+
export declare const pattern: (pattern: string | RegExp) => ValidatorFn;
|
|
13
24
|
declare const FIELD: unique symbol;
|
|
14
25
|
declare enum FieldType {
|
|
15
26
|
Json = 1,
|
|
@@ -38,25 +49,31 @@ export type Field<T = undefined> = (() => T) & {
|
|
|
38
49
|
export declare function field(): Field;
|
|
39
50
|
export declare function field<T>(): Field<T | undefined>;
|
|
40
51
|
export declare function field<T>(defaultValue: T): Field<T>;
|
|
52
|
+
export declare function validatorField(validators: ValidatorFn<any>[], value: unknown): void;
|
|
53
|
+
export declare function asyncValidatorField(asyncValidator: AsyncValidatorFn<any>[], value: unknown): Promise<void>;
|
|
41
54
|
export declare function isField(value: unknown): value is Field;
|
|
42
55
|
export declare function isFieldGroup(value: unknown): value is Record<PropertyKey, Field>;
|
|
56
|
+
declare const HTTP_RESPONSE: unique symbol;
|
|
43
57
|
export type HttpResponseBody = string | ArrayBuffer | Blob | object | null;
|
|
44
|
-
export type HttpResponse<R> = {
|
|
45
|
-
ok: true;
|
|
46
|
-
status: number;
|
|
47
|
-
statusText: string;
|
|
48
|
-
url: string;
|
|
49
|
-
headers: Headers;
|
|
50
|
-
body: R | null;
|
|
58
|
+
export type HttpResponse<R> = ({
|
|
59
|
+
readonly ok: true;
|
|
60
|
+
readonly status: number;
|
|
61
|
+
readonly statusText: string;
|
|
62
|
+
readonly url: string;
|
|
63
|
+
readonly headers: Headers;
|
|
64
|
+
readonly body: R | null;
|
|
51
65
|
} | {
|
|
52
|
-
ok: false;
|
|
53
|
-
error: Error;
|
|
54
|
-
status: number;
|
|
55
|
-
statusText: string;
|
|
56
|
-
url: string;
|
|
57
|
-
headers: Headers;
|
|
58
|
-
body:
|
|
66
|
+
readonly ok: false;
|
|
67
|
+
readonly error: Error;
|
|
68
|
+
readonly status: number;
|
|
69
|
+
readonly statusText: string;
|
|
70
|
+
readonly url: string;
|
|
71
|
+
readonly headers: Headers;
|
|
72
|
+
readonly body: null;
|
|
73
|
+
}) & {
|
|
74
|
+
readonly [HTTP_RESPONSE]: unknown;
|
|
59
75
|
};
|
|
76
|
+
export declare function isHttpResponse<R>(value: unknown): value is HttpResponse<R>;
|
|
60
77
|
export type MakeResponseOptions<R> = {
|
|
61
78
|
status?: number;
|
|
62
79
|
statusText?: string;
|
|
@@ -67,6 +84,14 @@ export type MakeResponseOptions<R> = {
|
|
|
67
84
|
};
|
|
68
85
|
export declare function makeResponse<R>(options: MakeResponseOptions<R>): HttpResponse<R>;
|
|
69
86
|
export type InterceptorFn = (req: HttpRequest, next: HttpHandler) => Promise<HttpResponse<unknown>>;
|
|
87
|
+
export type BasicCredential = {
|
|
88
|
+
username: string;
|
|
89
|
+
password: string;
|
|
90
|
+
};
|
|
91
|
+
export type BasicAuthInterceptorOptions = {
|
|
92
|
+
encode?: (credential: BasicCredential) => string;
|
|
93
|
+
};
|
|
94
|
+
export declare function basicAuthInterceptor(fn: () => BasicCredential, options?: BasicAuthInterceptorOptions): InterceptorFn;
|
|
70
95
|
export type HttpResponseType = "arraybuffer" | "blob" | "json" | "text";
|
|
71
96
|
export interface HttpProgressEvent {
|
|
72
97
|
/**
|
|
@@ -83,7 +108,7 @@ export interface HttpProgressEvent {
|
|
|
83
108
|
readonly total: number;
|
|
84
109
|
}
|
|
85
110
|
export type HttpProgressFn = (event: HttpProgressEvent) => void;
|
|
86
|
-
export type TransformRequestFn = (request: HttpRequest) => HttpRequest["body"];
|
|
111
|
+
export type TransformRequestFn<Input = unknown> = (input: Input, request: HttpRequest) => HttpRequest["body"];
|
|
87
112
|
export type TransformResponseFn<Output = unknown> = (response: HttpResponse<unknown>) => Output;
|
|
88
113
|
export interface HttpRequest {
|
|
89
114
|
host?: string;
|
|
@@ -100,7 +125,11 @@ export interface HttpRequest {
|
|
|
100
125
|
/** when use fetch handler, no upload progress */
|
|
101
126
|
uploadProgress?: HttpProgressFn;
|
|
102
127
|
downloadProgress?: HttpProgressFn;
|
|
103
|
-
/**
|
|
128
|
+
/**
|
|
129
|
+
* default:body
|
|
130
|
+
*
|
|
131
|
+
* @todo Implement streaming response
|
|
132
|
+
*/
|
|
104
133
|
observe?: "body" | "stream" | "response";
|
|
105
134
|
abort?: AbortSignal;
|
|
106
135
|
}
|
|
@@ -125,7 +154,7 @@ export type RequestOptions<Output = unknown, Input extends Field<any> | Record<P
|
|
|
125
154
|
export type DoRequestOptions = {
|
|
126
155
|
abort?: AbortSignal;
|
|
127
156
|
handler?: HttpHandler;
|
|
128
|
-
client?:
|
|
157
|
+
client?: Client;
|
|
129
158
|
timeout?: number;
|
|
130
159
|
};
|
|
131
160
|
export type DoRequestFn<Input = unknown, Output = unknown> = Input extends undefined ? (options?: DoRequestOptions) => Promise<Output> : (input: RequestInputValue<Input>, options?: DoRequestOptions) => Promise<Output>;
|
|
@@ -150,7 +179,7 @@ export declare function defineRequest<Output = unknown, Input extends Field<any>
|
|
|
150
179
|
context?: HttpContext;
|
|
151
180
|
withCredentials?: boolean;
|
|
152
181
|
validators?: (ValidatorFn<RequestInputValue<Input>> | AsyncValidatorFn<RequestInputValue<Input>>)[];
|
|
153
|
-
transformRequest?: TransformRequestFn
|
|
182
|
+
transformRequest?: TransformRequestFn<RequestInputValue<Input>>;
|
|
154
183
|
transformResponse?: TransformResponseFn<Output>;
|
|
155
184
|
}): UseRequestFn<Output, Input>;
|
|
156
185
|
export declare function defineRequest<Input extends Field<any> | Record<PropertyKey, Field<any>> | undefined = undefined>(options: {
|
|
@@ -163,7 +192,7 @@ export declare function defineRequest<Input extends Field<any> | Record<Property
|
|
|
163
192
|
context?: HttpContext;
|
|
164
193
|
withCredentials?: boolean;
|
|
165
194
|
validators?: (ValidatorFn<RequestInputValue<Input>> | AsyncValidatorFn<RequestInputValue<Input>>)[];
|
|
166
|
-
transformRequest?: TransformRequestFn
|
|
195
|
+
transformRequest?: TransformRequestFn<RequestInputValue<Input>>;
|
|
167
196
|
transformResponse?: TransformResponseFn;
|
|
168
197
|
}): UseRequestFn<string, Input>;
|
|
169
198
|
export declare function defineRequest<Input extends Field<any> | Record<PropertyKey, Field<any>> | undefined = undefined>(options: {
|
|
@@ -176,7 +205,7 @@ export declare function defineRequest<Input extends Field<any> | Record<Property
|
|
|
176
205
|
context?: HttpContext;
|
|
177
206
|
withCredentials?: boolean;
|
|
178
207
|
validators?: (ValidatorFn<RequestInputValue<Input>> | AsyncValidatorFn<RequestInputValue<Input>>)[];
|
|
179
|
-
transformRequest?: TransformRequestFn
|
|
208
|
+
transformRequest?: TransformRequestFn<RequestInputValue<Input>>;
|
|
180
209
|
transformResponse?: TransformResponseFn;
|
|
181
210
|
}): UseRequestFn<Blob, Input>;
|
|
182
211
|
export declare function defineRequest<Input extends Field<any> | Record<PropertyKey, Field<any>> | undefined = undefined>(options: {
|
|
@@ -189,7 +218,7 @@ export declare function defineRequest<Input extends Field<any> | Record<Property
|
|
|
189
218
|
context?: HttpContext;
|
|
190
219
|
withCredentials?: boolean;
|
|
191
220
|
validators?: (ValidatorFn<RequestInputValue<Input>> | AsyncValidatorFn<RequestInputValue<Input>>)[];
|
|
192
|
-
transformRequest?: TransformRequestFn
|
|
221
|
+
transformRequest?: TransformRequestFn<RequestInputValue<Input>>;
|
|
193
222
|
transformResponse?: TransformResponseFn;
|
|
194
223
|
}): UseRequestFn<ArrayBuffer, Input>;
|
|
195
224
|
/** Observe: Response */
|
|
@@ -203,7 +232,7 @@ export declare function defineRequest<Output = unknown, Input extends Field<any>
|
|
|
203
232
|
context?: HttpContext;
|
|
204
233
|
withCredentials?: boolean;
|
|
205
234
|
validators?: (ValidatorFn<RequestInputValue<Input>> | AsyncValidatorFn<RequestInputValue<Input>>)[];
|
|
206
|
-
transformRequest?: TransformRequestFn
|
|
235
|
+
transformRequest?: TransformRequestFn<RequestInputValue<Input>>;
|
|
207
236
|
transformResponse?: TransformResponseFn<Output>;
|
|
208
237
|
}): UseRequestFn<HttpResponse<Output>, Input>;
|
|
209
238
|
export declare function defineRequest<Input extends Field<any> | Record<PropertyKey, Field<any>> | undefined = undefined>(options: {
|
|
@@ -216,7 +245,7 @@ export declare function defineRequest<Input extends Field<any> | Record<Property
|
|
|
216
245
|
context?: HttpContext;
|
|
217
246
|
withCredentials?: boolean;
|
|
218
247
|
validators?: (ValidatorFn<RequestInputValue<Input>> | AsyncValidatorFn<RequestInputValue<Input>>)[];
|
|
219
|
-
transformRequest?: TransformRequestFn
|
|
248
|
+
transformRequest?: TransformRequestFn<RequestInputValue<Input>>;
|
|
220
249
|
transformResponse?: TransformResponseFn;
|
|
221
250
|
}): UseRequestFn<HttpResponse<string>, Input>;
|
|
222
251
|
export declare function defineRequest<Input extends Field<any> | Record<PropertyKey, Field<any>> | undefined = undefined>(options: {
|
|
@@ -229,7 +258,7 @@ export declare function defineRequest<Input extends Field<any> | Record<Property
|
|
|
229
258
|
context?: HttpContext;
|
|
230
259
|
withCredentials?: boolean;
|
|
231
260
|
validators?: (ValidatorFn<RequestInputValue<Input>> | AsyncValidatorFn<RequestInputValue<Input>>)[];
|
|
232
|
-
transformRequest?: TransformRequestFn
|
|
261
|
+
transformRequest?: TransformRequestFn<RequestInputValue<Input>>;
|
|
233
262
|
transformResponse?: TransformResponseFn;
|
|
234
263
|
}): UseRequestFn<HttpResponse<Blob>, Input>;
|
|
235
264
|
export declare function defineRequest<Input extends Field<any> | Record<PropertyKey, Field<any>> | undefined = undefined>(options: {
|
|
@@ -242,10 +271,28 @@ export declare function defineRequest<Input extends Field<any> | Record<Property
|
|
|
242
271
|
context?: HttpContext;
|
|
243
272
|
withCredentials?: boolean;
|
|
244
273
|
validators?: (ValidatorFn<RequestInputValue<Input>> | AsyncValidatorFn<RequestInputValue<Input>>)[];
|
|
245
|
-
transformRequest?: TransformRequestFn
|
|
274
|
+
transformRequest?: TransformRequestFn<RequestInputValue<Input>>;
|
|
246
275
|
transformResponse?: TransformResponseFn;
|
|
247
276
|
}): UseRequestFn<HttpResponse<ArrayBuffer>, Input>;
|
|
248
277
|
export type HttpHandler = (req: HttpRequest) => Promise<HttpResponse<unknown>>;
|
|
278
|
+
export interface FetchConfig {
|
|
279
|
+
/** A string indicating how the request will interact with the browser's cache to set request's cache. */
|
|
280
|
+
cache?: RequestCache;
|
|
281
|
+
/** A string indicating whether credentials will be sent with the request always, never, or only when sent to a same-origin URL. Sets request's credentials. */
|
|
282
|
+
credentials?: RequestCredentials;
|
|
283
|
+
/** A boolean to set request's keepalive. */
|
|
284
|
+
keepalive?: boolean;
|
|
285
|
+
/** A string to indicate whether the request will use CORS, or will be restricted to same-origin URLs. Sets request's mode. */
|
|
286
|
+
mode?: RequestMode;
|
|
287
|
+
priority?: RequestPriority;
|
|
288
|
+
/** A string indicating whether request follows redirects, results in an error upon encountering a redirect, or returns the redirect (in an opaque fashion). Sets request's redirect. */
|
|
289
|
+
redirect?: RequestRedirect;
|
|
290
|
+
/** A string whose value is a same-origin URL, "about:client", or the empty string, to set request's referrer. */
|
|
291
|
+
referrer?: string;
|
|
292
|
+
/** A referrer policy to set request's referrerPolicy. */
|
|
293
|
+
referrerPolicy?: ReferrerPolicy;
|
|
294
|
+
}
|
|
295
|
+
export declare const FETCH_CONFIG_KEY: HttpContextToken<FetchConfig>;
|
|
249
296
|
export declare function fetchHandler(httpRequest: HttpRequest): Promise<HttpResponse<unknown>>;
|
|
250
297
|
export interface ClientOptions {
|
|
251
298
|
host: string;
|
|
@@ -263,6 +310,7 @@ export type Client = {} & {
|
|
|
263
310
|
};
|
|
264
311
|
export declare function isClient(value: unknown): value is Client;
|
|
265
312
|
export declare function createClient(options: ClientOptions): Client;
|
|
313
|
+
export declare function cloneClient(client: Client, options: ClientOptions): Client;
|
|
266
314
|
export declare function getGlobalClient(): Client;
|
|
267
315
|
export declare function setGlobalClient(client: Client): void;
|
|
268
316
|
export declare function restGlobalClient(): void;
|
|
@@ -1,21 +1,31 @@
|
|
|
1
1
|
// src/context.ts
|
|
2
2
|
function makeHttpContextToken(defaultValue) {
|
|
3
|
+
Object.defineProperty(defaultValue, HTTP_CONTEXT_TOKEN, { value: defaultValue });
|
|
3
4
|
return defaultValue;
|
|
4
5
|
}
|
|
6
|
+
function isHttpContextToken(value) {
|
|
7
|
+
return typeof value === "function" && HTTP_CONTEXT_TOKEN in value;
|
|
8
|
+
}
|
|
5
9
|
function makeHttpContext() {
|
|
6
10
|
const ctx = new Map;
|
|
7
11
|
return {
|
|
8
12
|
set(token, value) {
|
|
13
|
+
if (!isHttpContextToken(token)) {
|
|
14
|
+
throw new Error("Invalid HttpContextToken");
|
|
15
|
+
}
|
|
9
16
|
ctx.set(token, value);
|
|
10
17
|
return this;
|
|
11
18
|
},
|
|
12
19
|
get(token) {
|
|
20
|
+
if (!isHttpContextToken(token)) {
|
|
21
|
+
throw new Error("Invalid HttpContextToken");
|
|
22
|
+
}
|
|
13
23
|
if (!ctx.has(token)) {
|
|
14
24
|
ctx.set(token, token());
|
|
15
25
|
}
|
|
16
26
|
return ctx.get(token);
|
|
17
27
|
},
|
|
18
|
-
|
|
28
|
+
del(token) {
|
|
19
29
|
ctx.delete(token);
|
|
20
30
|
return this;
|
|
21
31
|
},
|
|
@@ -27,6 +37,7 @@ function makeHttpContext() {
|
|
|
27
37
|
}
|
|
28
38
|
};
|
|
29
39
|
}
|
|
40
|
+
var HTTP_CONTEXT_TOKEN = Symbol("HttpContextToken");
|
|
30
41
|
|
|
31
42
|
// src/field.ts
|
|
32
43
|
function field(defaultValue) {
|
|
@@ -76,6 +87,22 @@ function field(defaultValue) {
|
|
|
76
87
|
function getFieldMetadata(field2) {
|
|
77
88
|
return field2[FIELD];
|
|
78
89
|
}
|
|
90
|
+
function validatorField(validators, value) {
|
|
91
|
+
for (const fn of validators) {
|
|
92
|
+
const err = fn(value);
|
|
93
|
+
if (err) {
|
|
94
|
+
throw err;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async function asyncValidatorField(asyncValidator, value) {
|
|
99
|
+
for (const fn of asyncValidator) {
|
|
100
|
+
const err = await fn(value);
|
|
101
|
+
if (err) {
|
|
102
|
+
throw err;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
79
106
|
function isField(value) {
|
|
80
107
|
return !!value && typeof value === "function" && FIELD in value;
|
|
81
108
|
}
|
|
@@ -88,13 +115,49 @@ var FIELD = Symbol("field");
|
|
|
88
115
|
var globalHttpHandler = undefined;
|
|
89
116
|
var getGlobalHttpHandler = () => globalHttpHandler;
|
|
90
117
|
|
|
91
|
-
// src/interceptor.ts
|
|
118
|
+
// src/interceptor/interceptor.ts
|
|
92
119
|
function makeInterceptorChain(interceptors) {
|
|
93
120
|
return interceptors.reduceRight((fn, interceptor) => {
|
|
94
121
|
return (initReq, finalHandlerFn) => interceptor(initReq, (req) => fn(req, finalHandlerFn));
|
|
95
122
|
}, (req, fn) => fn(req));
|
|
96
123
|
}
|
|
97
124
|
|
|
125
|
+
// src/response.ts
|
|
126
|
+
function isHttpResponse(value) {
|
|
127
|
+
return typeof value === "object" && value !== null && HTTP_RESPONSE in value;
|
|
128
|
+
}
|
|
129
|
+
function makeResponse(options) {
|
|
130
|
+
const status = options.status ?? 0;
|
|
131
|
+
const statusText = options.statusText ?? "";
|
|
132
|
+
const ok = status >= 200 && status < 300;
|
|
133
|
+
const url = options.url ?? "";
|
|
134
|
+
const headers = options.headers ?? new Headers;
|
|
135
|
+
const body = options.body ?? null;
|
|
136
|
+
if (!ok || options.error) {
|
|
137
|
+
const error = options.error || new Error(`Http failure response for ${options.url}: ${status} ${statusText}`);
|
|
138
|
+
return {
|
|
139
|
+
ok: false,
|
|
140
|
+
error,
|
|
141
|
+
status,
|
|
142
|
+
statusText,
|
|
143
|
+
url,
|
|
144
|
+
headers,
|
|
145
|
+
body: null,
|
|
146
|
+
[HTTP_RESPONSE]: null
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
ok: true,
|
|
151
|
+
status,
|
|
152
|
+
statusText,
|
|
153
|
+
url,
|
|
154
|
+
headers,
|
|
155
|
+
body,
|
|
156
|
+
[HTTP_RESPONSE]: null
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
var HTTP_RESPONSE = Symbol("HTTP_RESPONSE");
|
|
160
|
+
|
|
98
161
|
// src/request.ts
|
|
99
162
|
function serializeBody(body) {
|
|
100
163
|
switch (true) {
|
|
@@ -163,17 +226,31 @@ function defineRequest(options) {
|
|
|
163
226
|
const setDownloadProgress = (fn) => {
|
|
164
227
|
downloadProgress = fn;
|
|
165
228
|
};
|
|
166
|
-
const doRequest = async (
|
|
229
|
+
const doRequest = async (...args) => {
|
|
230
|
+
let input;
|
|
231
|
+
let doRequestOptions;
|
|
232
|
+
switch (args.length) {
|
|
233
|
+
case 1: {
|
|
234
|
+
doRequestOptions = args[0];
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
case 2: {
|
|
238
|
+
input = args[0];
|
|
239
|
+
doRequestOptions = args[1];
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
167
243
|
if (requiredInput && !input) {
|
|
168
244
|
throw new Error("input is required");
|
|
169
245
|
}
|
|
170
|
-
if (
|
|
171
|
-
abortSignal =
|
|
246
|
+
if (doRequestOptions?.abort) {
|
|
247
|
+
abortSignal = doRequestOptions.abort;
|
|
172
248
|
} else {
|
|
173
249
|
abortController = new AbortController;
|
|
174
250
|
abortSignal = abortController.signal;
|
|
175
251
|
}
|
|
176
|
-
const
|
|
252
|
+
const client2 = isClient(doRequestOptions?.client) ? doRequestOptions.client : getGlobalClient();
|
|
253
|
+
const clientOptions = getClientConfig(client2);
|
|
177
254
|
const req = {
|
|
178
255
|
host: clientOptions?.host,
|
|
179
256
|
method: requestOptions.method,
|
|
@@ -187,10 +264,10 @@ function defineRequest(options) {
|
|
|
187
264
|
observe: requestOptions.observe ?? "body",
|
|
188
265
|
uploadProgress,
|
|
189
266
|
downloadProgress,
|
|
190
|
-
timeout:
|
|
267
|
+
timeout: doRequestOptions?.timeout || 0,
|
|
191
268
|
abort: abortSignal
|
|
192
269
|
};
|
|
193
|
-
const handler2 =
|
|
270
|
+
const handler2 = doRequestOptions?.handler || clientOptions?.handler || getGlobalHttpHandler();
|
|
194
271
|
if (!handler2) {
|
|
195
272
|
throw new Error("no handler");
|
|
196
273
|
}
|
|
@@ -198,7 +275,7 @@ function defineRequest(options) {
|
|
|
198
275
|
await fillRequestFromField(req, requestOptions.input, input);
|
|
199
276
|
}
|
|
200
277
|
if (typeof requestOptions.transformRequest === "function") {
|
|
201
|
-
req.body = requestOptions.transformRequest(req);
|
|
278
|
+
req.body = requestOptions.transformRequest(input, req);
|
|
202
279
|
}
|
|
203
280
|
const chain = makeInterceptorChain([...clientOptions?.interceptors || [], ...requestOptions?.interceptors || []]);
|
|
204
281
|
if (typeof req.timeout === "number" && req.timeout > 0 && abortController) {
|
|
@@ -208,9 +285,26 @@ function defineRequest(options) {
|
|
|
208
285
|
}
|
|
209
286
|
}, req.timeout);
|
|
210
287
|
}
|
|
211
|
-
|
|
288
|
+
let res;
|
|
289
|
+
try {
|
|
290
|
+
res = await chain(req, handler2);
|
|
291
|
+
} catch (error) {
|
|
292
|
+
throw makeResponse({
|
|
293
|
+
error: error instanceof Error ? error : new Error("Transform response error", { cause: error })
|
|
294
|
+
});
|
|
295
|
+
}
|
|
212
296
|
if (typeof requestOptions.transformResponse === "function") {
|
|
213
|
-
|
|
297
|
+
try {
|
|
298
|
+
res = makeResponse({
|
|
299
|
+
...res,
|
|
300
|
+
body: requestOptions.transformResponse(res)
|
|
301
|
+
});
|
|
302
|
+
} catch (error) {
|
|
303
|
+
throw makeResponse({
|
|
304
|
+
...res,
|
|
305
|
+
error: error instanceof Error ? error : new Error("Transform response error", { cause: error })
|
|
306
|
+
});
|
|
307
|
+
}
|
|
214
308
|
}
|
|
215
309
|
switch (req.observe) {
|
|
216
310
|
case "body":
|
|
@@ -384,75 +478,24 @@ async function fillRequestFromField(request, fieldOrFieldGroup, input) {
|
|
|
384
478
|
throw new Error("unsupported field type");
|
|
385
479
|
}
|
|
386
480
|
|
|
387
|
-
// src/
|
|
388
|
-
function
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
const url = options.url ?? "";
|
|
393
|
-
const headers = options.headers ?? new Headers;
|
|
394
|
-
const body = options.body ?? null;
|
|
395
|
-
if (!ok || options.error) {
|
|
396
|
-
const error = options.error || new Error(`Http failure response for ${options.url}: ${status} ${statusText}`);
|
|
397
|
-
return {
|
|
398
|
-
ok: false,
|
|
399
|
-
error,
|
|
400
|
-
status,
|
|
401
|
-
statusText,
|
|
402
|
-
url,
|
|
403
|
-
headers,
|
|
404
|
-
body
|
|
405
|
-
};
|
|
406
|
-
}
|
|
407
|
-
return {
|
|
408
|
-
ok: true,
|
|
409
|
-
status,
|
|
410
|
-
statusText,
|
|
411
|
-
url,
|
|
412
|
-
headers,
|
|
413
|
-
body
|
|
414
|
-
};
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
// src/handler/fetch/fetch.ts
|
|
418
|
-
function createRequest(request2) {
|
|
419
|
-
const url = new URL(request2.endpoint, request2.host);
|
|
420
|
-
if (request2.queryParams) {
|
|
421
|
-
url.search = request2.queryParams.toString();
|
|
481
|
+
// src/handler/util.ts
|
|
482
|
+
function getContentLength(headers) {
|
|
483
|
+
const value = headers.get("Content-Length");
|
|
484
|
+
if (!value) {
|
|
485
|
+
return 0;
|
|
422
486
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
if (detectedType) {
|
|
427
|
-
request2.headers.set("Content-Type", detectedType);
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
if (!request2.headers.has("Accept")) {
|
|
431
|
-
request2.headers.set("Accept", "application/json, text/plain, */*");
|
|
432
|
-
}
|
|
487
|
+
const num = Number(value);
|
|
488
|
+
if (isNaN(num)) {
|
|
489
|
+
return 0;
|
|
433
490
|
}
|
|
434
|
-
|
|
435
|
-
const fetchConfig = request2.context?.get(FETCH_CONFIG_KEY) || {};
|
|
436
|
-
return new Request(url, {
|
|
437
|
-
...fetchConfig,
|
|
438
|
-
headers: request2.headers,
|
|
439
|
-
method: request2.method,
|
|
440
|
-
body: serializeBody(request2.body),
|
|
441
|
-
signal: request2.abort,
|
|
442
|
-
credentials
|
|
443
|
-
});
|
|
491
|
+
return num;
|
|
444
492
|
}
|
|
445
|
-
function
|
|
446
|
-
|
|
447
|
-
let position = 0;
|
|
448
|
-
for (const chunk of chunks) {
|
|
449
|
-
chunksAll.set(chunk, position);
|
|
450
|
-
position += chunk.length;
|
|
451
|
-
}
|
|
452
|
-
return chunksAll;
|
|
493
|
+
function getContentType(headers) {
|
|
494
|
+
return headers.get("Content-Type") || "";
|
|
453
495
|
}
|
|
454
|
-
function parseBody(
|
|
455
|
-
const
|
|
496
|
+
function parseBody(params) {
|
|
497
|
+
const { request, content, contentType } = params;
|
|
498
|
+
const responseType = request.responseType;
|
|
456
499
|
if (!responseType) {
|
|
457
500
|
return null;
|
|
458
501
|
}
|
|
@@ -467,7 +510,6 @@ function parseBody(request2, response2, content) {
|
|
|
467
510
|
case "text":
|
|
468
511
|
return new TextDecoder().decode(content);
|
|
469
512
|
case "blob": {
|
|
470
|
-
const contentType = response2.headers.get("Content-Type") || undefined;
|
|
471
513
|
return new Blob([content], { type: contentType });
|
|
472
514
|
}
|
|
473
515
|
case "arraybuffer":
|
|
@@ -476,35 +518,59 @@ function parseBody(request2, response2, content) {
|
|
|
476
518
|
return null;
|
|
477
519
|
}
|
|
478
520
|
}
|
|
479
|
-
function
|
|
480
|
-
const
|
|
481
|
-
|
|
482
|
-
|
|
521
|
+
function concatChunks(chunks, totalLength) {
|
|
522
|
+
const chunksAll = new Uint8Array(totalLength);
|
|
523
|
+
let position = 0;
|
|
524
|
+
for (const chunk of chunks) {
|
|
525
|
+
chunksAll.set(chunk, position);
|
|
526
|
+
position += chunk.length;
|
|
483
527
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
528
|
+
return chunksAll;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// src/handler/fetch/fetch.ts
|
|
532
|
+
function createRequest(request2) {
|
|
533
|
+
const url = new URL(request2.endpoint, request2.host);
|
|
534
|
+
if (request2.queryParams) {
|
|
535
|
+
url.search = request2.queryParams.toString();
|
|
487
536
|
}
|
|
488
|
-
|
|
537
|
+
const headers = request2.headers ?? new Headers;
|
|
538
|
+
if (!headers.has("Content-Type")) {
|
|
539
|
+
const detectedType = detectContentTypeHeader(request2.body);
|
|
540
|
+
if (detectedType) {
|
|
541
|
+
headers.set("Content-Type", detectedType);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
if (!headers.has("Accept")) {
|
|
545
|
+
headers.set("Accept", "application/json, text/plain, */*");
|
|
546
|
+
}
|
|
547
|
+
const credentials = request2.withCredentials ? "include" : undefined;
|
|
548
|
+
const fetchConfig = request2.context?.get(FETCH_CONFIG_KEY) || {};
|
|
549
|
+
return new Request(url, {
|
|
550
|
+
...fetchConfig,
|
|
551
|
+
headers,
|
|
552
|
+
method: request2.method,
|
|
553
|
+
body: serializeBody(request2.body),
|
|
554
|
+
signal: request2.abort,
|
|
555
|
+
credentials
|
|
556
|
+
});
|
|
489
557
|
}
|
|
490
558
|
async function fetchHandler(httpRequest) {
|
|
491
|
-
const
|
|
559
|
+
const downloadProgress = httpRequest.downloadProgress;
|
|
492
560
|
const request2 = createRequest(httpRequest);
|
|
493
|
-
let
|
|
561
|
+
let response3;
|
|
494
562
|
try {
|
|
495
|
-
|
|
563
|
+
response3 = await (globalThis || window).fetch(request2);
|
|
496
564
|
} catch (error) {
|
|
497
|
-
throw
|
|
498
|
-
error: error instanceof Error ? error : new Error("Network Error"),
|
|
499
|
-
url: request2.url
|
|
500
|
-
});
|
|
565
|
+
throw new Error("Network Error", { cause: error });
|
|
501
566
|
}
|
|
502
|
-
const { headers, status, statusText, url } =
|
|
567
|
+
const { headers, status, statusText, url } = response3;
|
|
503
568
|
const contentLength = getContentLength(headers);
|
|
569
|
+
const contentType = getContentType(headers);
|
|
504
570
|
let body = null;
|
|
505
|
-
if (
|
|
571
|
+
if (response3.body) {
|
|
506
572
|
const chunks = [];
|
|
507
|
-
const reader =
|
|
573
|
+
const reader = response3.body.getReader();
|
|
508
574
|
let receivedLength = 0;
|
|
509
575
|
while (true) {
|
|
510
576
|
const { done, value } = await reader.read();
|
|
@@ -521,15 +587,13 @@ async function fetchHandler(httpRequest) {
|
|
|
521
587
|
}
|
|
522
588
|
const chunksAll = concatChunks(chunks, receivedLength);
|
|
523
589
|
try {
|
|
524
|
-
body = parseBody(
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
url,
|
|
529
|
-
status,
|
|
530
|
-
statusText,
|
|
531
|
-
headers
|
|
590
|
+
body = parseBody({
|
|
591
|
+
request: httpRequest,
|
|
592
|
+
content: chunksAll,
|
|
593
|
+
contentType
|
|
532
594
|
});
|
|
595
|
+
} catch (error) {
|
|
596
|
+
throw new Error("Parse response body error", { cause: error });
|
|
533
597
|
}
|
|
534
598
|
}
|
|
535
599
|
return makeResponse({
|
|
@@ -547,7 +611,7 @@ function isClient(value) {
|
|
|
547
611
|
}
|
|
548
612
|
function getClientConfig(client2) {
|
|
549
613
|
if (!isClient(client2)) {
|
|
550
|
-
|
|
614
|
+
throw new Error("Invalid client");
|
|
551
615
|
}
|
|
552
616
|
return client2[CLIENT];
|
|
553
617
|
}
|
|
@@ -561,6 +625,16 @@ function createClient(options) {
|
|
|
561
625
|
[CLIENT]: conf
|
|
562
626
|
};
|
|
563
627
|
}
|
|
628
|
+
function cloneClient(client2, options) {
|
|
629
|
+
const preConf = getClientConfig(client2);
|
|
630
|
+
const conf = {
|
|
631
|
+
...preConf,
|
|
632
|
+
...options
|
|
633
|
+
};
|
|
634
|
+
return {
|
|
635
|
+
[CLIENT]: conf
|
|
636
|
+
};
|
|
637
|
+
}
|
|
564
638
|
function getGlobalClient() {
|
|
565
639
|
if (!globalClient) {
|
|
566
640
|
throw new Error("Global client not set");
|
|
@@ -578,12 +652,110 @@ function createGlobalClient(options) {
|
|
|
578
652
|
}
|
|
579
653
|
var CLIENT = Symbol("Client");
|
|
580
654
|
var globalClient;
|
|
655
|
+
// src/interceptor/authorization/basic_auth_interceptor.ts
|
|
656
|
+
function basicAuthInterceptor(fn, options) {
|
|
657
|
+
let encode = options?.encode;
|
|
658
|
+
if (!encode) {
|
|
659
|
+
const btoa = (globalThis || window).btoa;
|
|
660
|
+
if (typeof btoa !== "function") {
|
|
661
|
+
throw new Error("BasicAuthInterceptor is not supported in this environment");
|
|
662
|
+
}
|
|
663
|
+
encode = (data) => btoa(`${data.username}:${data.password}`);
|
|
664
|
+
}
|
|
665
|
+
return (req, next) => {
|
|
666
|
+
const headers = req.headers || new Headers;
|
|
667
|
+
headers.set("Authorization", `Basic ${encode(fn())}`);
|
|
668
|
+
req.headers = headers;
|
|
669
|
+
return next(req);
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
// src/validator.ts
|
|
673
|
+
var required = (value) => {
|
|
674
|
+
if (!value) {
|
|
675
|
+
return new Error("required");
|
|
676
|
+
}
|
|
677
|
+
return null;
|
|
678
|
+
};
|
|
679
|
+
var requiredTrue = (value) => {
|
|
680
|
+
if (typeof value !== "boolean" || !value) {
|
|
681
|
+
return new Error("requiredTrue");
|
|
682
|
+
}
|
|
683
|
+
return null;
|
|
684
|
+
};
|
|
685
|
+
var minLength = (min) => {
|
|
686
|
+
return (value) => {
|
|
687
|
+
if (typeof value !== "string") {
|
|
688
|
+
return new Error("invalid string");
|
|
689
|
+
}
|
|
690
|
+
if (value.length < min) {
|
|
691
|
+
return new Error(`minLength ${min}`);
|
|
692
|
+
}
|
|
693
|
+
return null;
|
|
694
|
+
};
|
|
695
|
+
};
|
|
696
|
+
var maxLength = (max) => {
|
|
697
|
+
return (value) => {
|
|
698
|
+
if (typeof value !== "string") {
|
|
699
|
+
return new Error("invalid string");
|
|
700
|
+
}
|
|
701
|
+
if (value.length > max) {
|
|
702
|
+
return new Error(`maxLength ${max}`);
|
|
703
|
+
}
|
|
704
|
+
return null;
|
|
705
|
+
};
|
|
706
|
+
};
|
|
707
|
+
var min = (min2) => {
|
|
708
|
+
return (value) => {
|
|
709
|
+
if (typeof value !== "number" || isNaN(value)) {
|
|
710
|
+
return new Error("invalid number");
|
|
711
|
+
}
|
|
712
|
+
if (value < min2) {
|
|
713
|
+
return new Error(`minLength ${min2}`);
|
|
714
|
+
}
|
|
715
|
+
return null;
|
|
716
|
+
};
|
|
717
|
+
};
|
|
718
|
+
var max = (max2) => {
|
|
719
|
+
return (value) => {
|
|
720
|
+
if (typeof value !== "number" || isNaN(value)) {
|
|
721
|
+
return new Error("invalid number");
|
|
722
|
+
}
|
|
723
|
+
if (value > max2) {
|
|
724
|
+
return new Error(`maxLength ${max2}`);
|
|
725
|
+
}
|
|
726
|
+
return null;
|
|
727
|
+
};
|
|
728
|
+
};
|
|
729
|
+
var pattern = (pattern2) => {
|
|
730
|
+
return (value) => {
|
|
731
|
+
if (typeof value !== "string") {
|
|
732
|
+
return new Error("invalid string");
|
|
733
|
+
}
|
|
734
|
+
if (typeof pattern2 === "string") {
|
|
735
|
+
pattern2 = new RegExp(pattern2);
|
|
736
|
+
}
|
|
737
|
+
if (!pattern2.test(value)) {
|
|
738
|
+
return new Error("pattern");
|
|
739
|
+
}
|
|
740
|
+
return null;
|
|
741
|
+
};
|
|
742
|
+
};
|
|
581
743
|
export {
|
|
744
|
+
validatorField,
|
|
582
745
|
setGlobalClient,
|
|
583
746
|
restGlobalClient,
|
|
747
|
+
requiredTrue,
|
|
748
|
+
required,
|
|
749
|
+
pattern,
|
|
750
|
+
minLength,
|
|
751
|
+
min,
|
|
752
|
+
maxLength,
|
|
753
|
+
max,
|
|
584
754
|
makeResponse,
|
|
585
755
|
makeHttpContextToken,
|
|
586
756
|
makeHttpContext,
|
|
757
|
+
isHttpResponse,
|
|
758
|
+
isHttpContextToken,
|
|
587
759
|
isFieldGroup,
|
|
588
760
|
isField,
|
|
589
761
|
isClient,
|
|
@@ -592,5 +764,9 @@ export {
|
|
|
592
764
|
fetchHandler,
|
|
593
765
|
defineRequest,
|
|
594
766
|
createGlobalClient,
|
|
595
|
-
createClient
|
|
767
|
+
createClient,
|
|
768
|
+
cloneClient,
|
|
769
|
+
basicAuthInterceptor,
|
|
770
|
+
asyncValidatorField,
|
|
771
|
+
FETCH_CONFIG_KEY
|
|
596
772
|
};
|
package/package.json
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defjs/core",
|
|
3
|
-
"version": "0.0.0-test-
|
|
3
|
+
"version": "0.0.0-test-000",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
"
|
|
5
|
+
"module": "index.js",
|
|
6
|
+
"typings": "index.d.ts",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/defjs/defjs.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/defjs/defjs/issues"
|
|
11
14
|
},
|
|
12
15
|
"peerDependencies": {
|
|
13
|
-
"typescript": "^5.0"
|
|
16
|
+
"typescript": "^5.0.0"
|
|
14
17
|
},
|
|
15
|
-
"files": ["dist"],
|
|
16
|
-
"module": "dist/index.js",
|
|
17
|
-
"typings": "dist/index.d.ts",
|
|
18
18
|
"exports": {
|
|
19
19
|
"./package.json": "./package.json",
|
|
20
20
|
".": {
|
|
21
|
-
"types": "./
|
|
22
|
-
"default": "./
|
|
21
|
+
"types": "./index.d.ts",
|
|
22
|
+
"default": "./index.js"
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
}
|
|
25
|
+
}
|