@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 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
- export type HttpContextToken<T> = () => T;
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
- delete(token: HttpContextToken<unknown>): HttpContext;
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: R | null;
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
- /** default:body */
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?: ClientOptions;
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
- delete(token) {
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 (input, options2) => {
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 (options2?.abort) {
171
- abortSignal = options2.abort;
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 clientOptions = getClientConfig(options2?.client || getGlobalClient());
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: options2?.timeout || 0,
267
+ timeout: doRequestOptions?.timeout || 0,
191
268
  abort: abortSignal
192
269
  };
193
- const handler2 = options2?.handler || clientOptions?.handler || getGlobalHttpHandler();
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
- const res = await chain(req, handler2);
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
- res.body = requestOptions.transformResponse(res);
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/response.ts
388
- function makeResponse(options) {
389
- const status = options.status ?? 0;
390
- const statusText = options.statusText ?? "";
391
- const ok = status >= 200 && status < 300;
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
- if (request2.headers) {
424
- if (!request2.headers.has("Content-Type")) {
425
- const detectedType = detectContentTypeHeader(request2.body);
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
- const credentials = request2.withCredentials ? "include" : undefined;
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 concatChunks(chunks, totalLength) {
446
- const chunksAll = new Uint8Array(totalLength);
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(request2, response2, content) {
455
- const responseType = request2.responseType;
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 getContentLength(headers) {
480
- const value = headers.get("Content-Length");
481
- if (!value) {
482
- return 0;
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
- const num = Number(value);
485
- if (isNaN(num)) {
486
- return 0;
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
- return num;
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 { downloadProgress } = httpRequest;
559
+ const downloadProgress = httpRequest.downloadProgress;
492
560
  const request2 = createRequest(httpRequest);
493
- let response2;
561
+ let response3;
494
562
  try {
495
- response2 = await (globalThis || window).fetch(request2);
563
+ response3 = await (globalThis || window).fetch(request2);
496
564
  } catch (error) {
497
- throw makeResponse({
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 } = response2;
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 (response2.body) {
571
+ if (response3.body) {
506
572
  const chunks = [];
507
- const reader = response2.body.getReader();
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(httpRequest, response2, chunksAll);
525
- } catch (error) {
526
- throw makeResponse({
527
- error: new Error("Parse response body error", { cause: error }),
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
- return null;
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-0014",
3
+ "version": "0.0.0-test-000",
4
4
  "type": "module",
5
- "scripts": {
6
- "build": "bun run ./scripts/build.ts",
7
- "test": "bun test",
8
- "lint": "biome check",
9
- "lint:fix": "biome check --write",
10
- "pub": "npm publish"
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": "./dist/index.d.ts",
22
- "default": "./dist/index.js"
21
+ "types": "./index.d.ts",
22
+ "default": "./index.js"
23
23
  }
24
24
  }
25
- }
25
+ }