keq 2.6.2 → 2.6.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.
Files changed (64) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/esm/src/core.d.ts +10 -9
  3. package/dist/esm/src/core.js +1 -1
  4. package/dist/esm/src/create-request.d.ts +2 -1
  5. package/dist/esm/src/index.d.ts +3 -4
  6. package/dist/esm/src/keq.d.ts +28 -12
  7. package/dist/esm/src/keq.js +2 -8
  8. package/dist/esm/src/request.d.ts +1 -1
  9. package/dist/esm/src/types/content-type.d.ts +2 -0
  10. package/dist/esm/src/types/exclude-property.d.ts +3 -0
  11. package/dist/esm/src/types/extract-property.d.ts +3 -0
  12. package/dist/esm/src/types/keq-context-request.d.ts +18 -0
  13. package/dist/esm/src/types/keq-context.d.ts +2 -19
  14. package/dist/esm/src/types/keq-init.d.ts +2 -0
  15. package/dist/esm/src/types/keq-operation.d.ts +51 -0
  16. package/dist/esm/src/types/keq-options.d.ts +5 -7
  17. package/dist/esm/src/types/keq-request.d.ts +25 -11
  18. package/dist/esm/src/types/{keq-retry-on.d.ts → keq-retry.d.ts} +1 -0
  19. package/dist/esm/src/types/keq-retry.js +1 -0
  20. package/dist/esm/src/util/assign-keq-request-body.d.ts +2 -2
  21. package/dist/esm/src/util/fix-content-type.d.ts +3 -2
  22. package/dist/umd/src/core.d.ts +10 -9
  23. package/dist/umd/src/core.js +2 -2
  24. package/dist/umd/src/create-request.d.ts +2 -1
  25. package/dist/umd/src/index.d.ts +3 -4
  26. package/dist/umd/src/keq.d.ts +28 -12
  27. package/dist/umd/src/keq.js +2 -8
  28. package/dist/umd/src/request.d.ts +1 -1
  29. package/dist/umd/src/types/content-type.d.ts +2 -0
  30. package/dist/umd/src/types/exclude-property.d.ts +3 -0
  31. package/dist/umd/src/types/extract-property.d.ts +3 -0
  32. package/dist/umd/src/types/keq-context-request.d.ts +18 -0
  33. package/dist/umd/src/types/keq-context.d.ts +2 -19
  34. package/dist/umd/src/types/keq-init.d.ts +2 -0
  35. package/dist/umd/src/types/keq-operation.d.ts +51 -0
  36. package/dist/umd/src/types/keq-options.d.ts +5 -7
  37. package/dist/umd/src/types/keq-request.d.ts +25 -11
  38. package/dist/umd/src/types/{keq-retry-on.d.ts → keq-retry.d.ts} +1 -0
  39. package/dist/umd/src/types/keq-retry.js +12 -0
  40. package/dist/umd/src/util/assign-keq-request-body.d.ts +2 -2
  41. package/dist/umd/src/util/fix-content-type.d.ts +3 -2
  42. package/package.json +2 -2
  43. package/dist/esm/src/types/keq-request-body.d.ts +0 -1
  44. package/dist/esm/src/types/keq-request-init.d.ts +0 -2
  45. package/dist/esm/src/types/keq-request-method.d.ts +0 -1
  46. package/dist/esm/src/types/keq-retry-delay.d.ts +0 -2
  47. package/dist/esm/src/types/shorthand-content-type.d.ts +0 -1
  48. package/dist/umd/src/types/keq-request-body.d.ts +0 -1
  49. package/dist/umd/src/types/keq-request-init.d.ts +0 -2
  50. package/dist/umd/src/types/keq-request-method.d.ts +0 -1
  51. package/dist/umd/src/types/keq-retry-delay.d.ts +0 -2
  52. package/dist/umd/src/types/shorthand-content-type.d.ts +0 -1
  53. /package/dist/esm/src/types/{keq-request-body.js → content-type.js} +0 -0
  54. /package/dist/esm/src/types/{keq-request-init.js → exclude-property.js} +0 -0
  55. /package/dist/esm/src/types/{keq-request-method.js → extract-property.js} +0 -0
  56. /package/dist/esm/src/types/{keq-retry-delay.js → keq-context-request.js} +0 -0
  57. /package/dist/esm/src/types/{keq-retry-on.js → keq-init.js} +0 -0
  58. /package/dist/esm/src/types/{shorthand-content-type.js → keq-operation.js} +0 -0
  59. /package/dist/umd/src/types/{keq-request-body.js → content-type.js} +0 -0
  60. /package/dist/umd/src/types/{keq-request-init.js → exclude-property.js} +0 -0
  61. /package/dist/umd/src/types/{keq-request-method.js → extract-property.js} +0 -0
  62. /package/dist/umd/src/types/{keq-retry-delay.js → keq-context-request.js} +0 -0
  63. /package/dist/umd/src/types/{keq-retry-on.js → keq-init.js} +0 -0
  64. /package/dist/umd/src/types/{shorthand-content-type.js → keq-operation.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [2.6.3](https://github.com/keq-request/keq/compare/v2.6.2...v2.6.3) (2024-05-30)
6
+
7
+
8
+ ### Performance Improvements
9
+
10
+ * human warn when set undefined query ([e9695ab](https://github.com/keq-request/keq/commit/e9695ab1df78920980acc9ce18facc251925c65d))
11
+ * interface type could be extends through generics ([62797e3](https://github.com/keq-request/keq/commit/62797e398df25e1caed1ae726c03a89246834928))
12
+
5
13
  ## [2.6.2](https://github.com/keq-request/keq/compare/v2.6.1...v2.6.2) (2024-05-29)
6
14
 
7
15
 
@@ -1,31 +1,32 @@
1
1
  import { URL } from 'whatwg-url';
2
- import type { KeqContextOptions, KeqRequestContext } from './types/keq-context.js';
2
+ import type { KeqContextOptions } from './types/keq-context.js';
3
3
  import type { KeqMiddleware } from './types/keq-middleware.js';
4
- import type { KeqRequestInit } from './types/keq-request-init.js';
5
- import { KeqEvents, KeqListeners } from './types/keq-events.js';
4
+ import type { KeqInit } from './types/keq-init.js';
5
+ import type { KeqEvents, KeqListeners } from './types/keq-events.js';
6
+ import type { KeqContextRequest } from './types/keq-context-request.js';
6
7
  /**
7
8
  * @description Keq 核心 API,发送请求必要的原子化的API
8
9
  */
9
- export declare class Core<T> {
10
+ export declare class Core<OUTPUT> {
10
11
  private requestPromise?;
11
- protected requestContext: Omit<KeqRequestContext, 'abort'>;
12
+ protected requestContext: Omit<KeqContextRequest, 'abort'>;
12
13
  protected __listeners__: KeqListeners;
13
14
  protected __global__: Record<string, any>;
14
15
  protected __prepend_middlewares__: KeqMiddleware[];
15
16
  protected __append_middlewares__: KeqMiddleware[];
16
17
  protected __options__: KeqContextOptions;
17
- constructor(url: (URL | globalThis.URL), init: KeqRequestInit, global?: Record<string, any>);
18
+ constructor(url: (URL | globalThis.URL), init: KeqInit, global?: Record<string, any>);
18
19
  prependMiddlewares(...middlewares: KeqMiddleware[]): this;
19
20
  appendMiddlewares(...middlewares: KeqMiddleware[]): this;
20
21
  on<K extends keyof KeqEvents>(event: K, listener: (data: KeqEvents[K]) => void): this;
21
22
  private run;
22
- end(): Promise<T>;
23
+ end(): Promise<OUTPUT>;
23
24
  /**
24
25
  * Attaches callbacks for the resolution and/or rejection of the Promise.
25
26
  * @param onfulfilled The callback to execute when the Promise is resolved.
26
27
  * @param onrejected The callback to execute when the Promise is rejected.
27
28
  * @returns A Promise for the completion of which ever callback is executed.
28
29
  */
29
- then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
30
- catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
30
+ then<TResult1 = OUTPUT, TResult2 = never>(onfulfilled?: ((value: OUTPUT) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
31
+ catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<OUTPUT | TResult>;
31
32
  }
@@ -1,10 +1,10 @@
1
+ import mitt from 'mitt';
1
2
  import { URL } from 'whatwg-url';
2
3
  import { Exception } from "./exception/exception.js";
3
4
  import { clone } from "./util/clone.js";
4
5
  import { ABORT_PROPERTY, NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from './constant.js';
5
6
  import { composeMiddleware } from './util/compose-middleware.js';
6
7
  import { shadowClone } from './util/shadow-clone.js';
7
- import mitt from 'mitt';
8
8
  /**
9
9
  * @description Keq 核心 API,发送请求必要的原子化的API
10
10
  */
@@ -1,8 +1,9 @@
1
1
  import type { KeqMiddleware } from './types/keq-middleware.js';
2
2
  import type { KeqRequest } from './types/keq-request.js';
3
+ import { KeqOperations } from './types/keq-operation.js';
3
4
  interface CreateRequestOptions {
4
5
  initMiddlewares?: KeqMiddleware[];
5
6
  baseOrigin?: string;
6
7
  }
7
- export declare function createRequest(options?: CreateRequestOptions): KeqRequest;
8
+ export declare function createRequest<OPERATIONS extends KeqOperations>(options?: CreateRequestOptions): KeqRequest<OPERATIONS>;
8
9
  export {};
@@ -7,14 +7,13 @@ export type { KeqContext, KeqContextOptions } from './types/keq-context.js';
7
7
  export type { KeqMiddleware } from './types/keq-middleware.js';
8
8
  export type { KeqNext } from './types/keq-next.js';
9
9
  export type { KeqOptions } from './types/keq-options.js';
10
- export type { KeqRequestBody } from './types/keq-request-body.js';
11
- export type { KeqRequestInit } from './types/keq-request-init.js';
10
+ export type { KeqInit } from './types/keq-init.js';
12
11
  export type { KeqRequest } from './types/keq-request.js';
13
- export type { KeqRetryDelay } from './types/keq-retry-delay.js';
14
- export type { KeqRetryOn } from './types/keq-retry-on.js';
15
12
  export type { KeqRoute } from './types/keq-route.js';
16
13
  export type { KeqGlobal } from './types/keq-global.js';
17
14
  export type { KeqEvents } from './types/keq-events.js';
15
+ export type { KeqRetryOn, KeqRetryDelay } from './types/keq-retry.js';
16
+ export type { KeqOperations, KeqBaseOperation } from './types/keq-operation.js';
18
17
  export { keqHostRoute } from './router/keq-host-route.js';
19
18
  export { keqLocationRoute } from './router/keq-location-route.js';
20
19
  export { keqMethodRoute } from './router/keq-method-route.js';
@@ -1,20 +1,20 @@
1
1
  /// <reference types="node" />
2
2
  import { Core } from './core.js';
3
3
  import { KeqFlowControlMode, KeqFlowControlSignal } from './types/keq-flow-control.js';
4
- import type { KeqRetryOn } from './types/keq-retry-on.js';
4
+ import type { KeqRetryOn, KeqRetryDelay } from './types/keq-retry.js';
5
5
  import type { KeqMiddleware } from './types/keq-middleware.js';
6
6
  import type { KeqOptionsParameter, KeqOptionsReturnType } from './types/keq-options.js';
7
7
  import type { KeqQueryValue } from './types/keq-query-value.js';
8
- import type { KeqRequestBody } from './types/keq-request-body.js';
9
- import type { KeqRetryDelay } from './types/keq-retry-delay.js';
10
- import type { ShorthandContentType } from './types/shorthand-content-type.js';
11
- import { KeqContextOptions } from './types/keq-context.js';
8
+ import type { CommonContentType, ShorthandContentType } from './types/content-type.js';
9
+ import type { KeqContextOptions } from './types/keq-context.js';
10
+ import type { ExtractFields, ExtractFiles, ExtractHeaders, ExtractParams, ExtractQuery, KeqBaseOperation, KeqOperation } from './types/keq-operation.js';
11
+ import type { KeqContextRequestBody } from './types/keq-context-request.js';
12
12
  /**
13
13
  * @description Keq 扩展 API,人性化的常用的API
14
14
  */
15
- export declare class Keq<T> extends Core<T> {
15
+ export declare class Keq<OUTPUT, OPERATION extends Omit<KeqOperation, 'responseBody'> = KeqBaseOperation> extends Core<OUTPUT> {
16
16
  use(...middlewares: KeqMiddleware[]): this;
17
- option<K extends keyof KeqOptionsReturnType<T>>(key: K, value?: KeqOptionsParameter[K]): KeqOptionsReturnType<T>[K];
17
+ option<K extends keyof KeqOptionsReturnType<OUTPUT>>(key: K, value?: KeqOptionsParameter[K]): KeqOptionsReturnType<OUTPUT>[K];
18
18
  option(key: string, value?: any): this;
19
19
  options(opts: KeqContextOptions): this;
20
20
  /**
@@ -22,27 +22,36 @@ export declare class Keq<T> extends Core<T> {
22
22
  *
23
23
  * @description 设置请求头
24
24
  */
25
+ set(headers: ExtractHeaders<OPERATION>): this;
26
+ set<T extends keyof ExtractHeaders<OPERATION>>(name: T, value: ExtractHeaders<OPERATION>[T]): this;
27
+ set<T extends keyof KeqBaseOperation['requestHeaders']>(name: T, value: KeqBaseOperation['requestHeaders'][T]): this;
25
28
  set(headers: Headers): this;
26
29
  set(headers: Record<string, string>): this;
27
30
  set(name: string, value: string): this;
28
31
  /**
29
32
  * Set request query/searchParams
30
33
  */
34
+ query(key: ExtractQuery<OPERATION>): this;
35
+ query<T extends keyof ExtractQuery<OPERATION>>(key: T, value: ExtractQuery<OPERATION>[T]): this;
31
36
  query(key: Record<string, KeqQueryValue | KeqQueryValue[]>): this;
32
37
  query(key: string, value: KeqQueryValue | KeqQueryValue[]): this;
33
38
  /**
34
39
  * Set request route params
35
40
  */
41
+ params(key: ExtractParams<OPERATION>): this;
42
+ params<T extends keyof ExtractParams<OPERATION>>(key: T, value: ExtractParams<OPERATION>[T]): this;
36
43
  params(key: Record<string, string | number>): this;
37
44
  params(key: string, value: string | number): this;
38
45
  /**
39
46
  * Set request body
40
47
  */
41
- body(value: KeqRequestBody): this;
48
+ body(value: KeqContextRequestBody): this;
42
49
  /**
43
50
  * Setting the Content-Type
44
51
  */
45
- type(contentType: ShorthandContentType | string): this;
52
+ type(contentType: ShorthandContentType): this;
53
+ type(contentType: CommonContentType): this;
54
+ type(contentType: string): this;
46
55
  /**
47
56
  * Http Basic Authentication
48
57
  */
@@ -51,10 +60,17 @@ export declare class Keq<T> extends Core<T> {
51
60
  /**
52
61
  * set request body
53
62
  */
54
- send(value: FormData | URLSearchParams | object | Array<any> | string): this;
63
+ send(value: OPERATION['requestBody'] | object): this;
64
+ send(value: FormData): this;
65
+ send(value: URLSearchParams): this;
66
+ send(value: Array<any>): this;
67
+ send(value: string): this;
68
+ field<T extends keyof ExtractFields<OPERATION>>(arg1: T, value: ExtractFields<OPERATION>[T]): this;
69
+ field(arg1: ExtractFields<OPERATION>): this;
55
70
  field(arg1: string, value: string | string[]): this;
56
71
  field(arg1: Record<string, string>): this;
57
- attach(key: string, value: Blob | File | Buffer): this;
72
+ attach<T extends keyof ExtractFiles<OPERATION>>(key: T, value: Blob | File | Buffer, filename: string): this;
73
+ attach<T extends keyof ExtractFiles<OPERATION>>(key: T, value: Blob | File | Buffer): this;
58
74
  attach(key: string, value: Blob | File | Buffer, filename: string): this;
59
75
  attach(key: string, value: Blob | File | Buffer): this;
60
76
  /**
@@ -63,7 +79,7 @@ export declare class Keq<T> extends Core<T> {
63
79
  * @param retryDelay Initial value used to calculate the retry in milliseconds (This is still randomized following the randomization factor)
64
80
  * @param retryCallback Will be called after request failed
65
81
  */
66
- retry(retryTimes: number, retryDelay?: KeqRetryDelay, retryOn?: KeqRetryOn): Keq<T>;
82
+ retry(retryTimes: number, retryDelay?: KeqRetryDelay, retryOn?: KeqRetryOn): Keq<OUTPUT>;
67
83
  redirect(mod: RequestRedirect): this;
68
84
  credentials(mod: RequestCredentials): this;
69
85
  mode(mod: RequestMode): this;
@@ -61,11 +61,11 @@ export class Keq extends Core {
61
61
  else if (typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint') {
62
62
  this.requestContext.url.searchParams.append(key, String(value));
63
63
  }
64
- else if (value === 'undefined' || value === null) {
64
+ else if (value === 'undefined' || value === null || value === undefined) {
65
65
  // skip
66
66
  }
67
67
  else {
68
- console.warn(`query value type is invalid, key: ${key}`);
68
+ console.warn(`query value type(${typeof value}) is invalid, key: ${key}`);
69
69
  }
70
70
  return this;
71
71
  }
@@ -92,9 +92,6 @@ export class Keq extends Core {
92
92
  this.requestContext.body = value;
93
93
  return this;
94
94
  }
95
- /**
96
- * Setting the Content-Type
97
- */
98
95
  type(contentType) {
99
96
  const type = fixContentType(contentType);
100
97
  this.set('Content-Type', type);
@@ -111,9 +108,6 @@ export class Keq extends Core {
111
108
  if (!this.requestContext.headers.has('Content-Type'))
112
109
  void this.type(contentType);
113
110
  }
114
- /**
115
- * set request body
116
- */
117
111
  send(value) {
118
112
  this.requestContext.body = assignKeqRequestBody(this.requestContext.body, value);
119
113
  if (isUrlSearchParams(value)) {
@@ -1 +1 @@
1
- export declare const request: import("./index.js").KeqRequest;
1
+ export declare const request: import("./index.js").KeqRequest<import("./index.js").KeqOperations>;
@@ -0,0 +1,2 @@
1
+ export type ShorthandContentType = 'json' | 'form-data' | 'form' | 'jpeg' | 'bmp' | 'apng' | 'gif' | 'x-icon' | 'png' | 'webp' | 'tiff' | 'svg' | 'xml' | 'html' | 'css';
2
+ export type CommonContentType = 'application/json' | 'multipart/form-data' | 'application/x-www-form-urlencoded' | 'image/jpeg' | 'image/bmp' | 'image/apng' | 'image/gif' | 'image/x-icon' | 'image/png' | 'image/webp' | 'image/tiff' | 'image/svg+xml' | 'text/xml' | 'text/html' | 'text/css';
@@ -0,0 +1,3 @@
1
+ export type ExcludeProperty<T, U> = Pick<T, {
2
+ [K in keyof T]: T[K] extends U ? never : K;
3
+ }[keyof T]>;
@@ -0,0 +1,3 @@
1
+ export type ExtractProperty<T, U> = {
2
+ [K in keyof T as T[K] extends U ? K : never]: T[K];
3
+ };
@@ -0,0 +1,18 @@
1
+ import { URL } from 'whatwg-url';
2
+ export type KeqContextRequestMethod = 'get' | 'post' | 'put' | 'delete' | 'head' | 'patch';
3
+ export type KeqContextRequestBody = object | Array<any> | string | undefined;
4
+ export interface KeqContextRequest {
5
+ url: URL | globalThis.URL;
6
+ method: KeqContextRequestMethod;
7
+ headers: Headers;
8
+ routeParams: Record<string, string>;
9
+ body: KeqContextRequestBody;
10
+ cache?: RequestCache;
11
+ credentials?: RequestCredentials;
12
+ integrity?: string;
13
+ keepalive?: boolean;
14
+ mode?: RequestMode;
15
+ redirect?: RequestRedirect;
16
+ referrer?: string;
17
+ referrerPolicy?: ReferrerPolicy;
18
+ }
@@ -1,29 +1,12 @@
1
1
  import { Emitter } from 'mitt';
2
- import { URL } from 'whatwg-url';
3
2
  import { ABORT_PROPERTY, NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from "../constant.js";
4
- import type { KeqRequestBody } from './keq-request-body.js';
5
- import type { KeqRequestMethod } from './keq-request-method.js';
6
3
  import type { KeqOptionsParameter } from './keq-options.js';
7
4
  import type { KeqEvents } from './keq-events.js';
8
5
  import type { KeqGlobal } from './keq-global.js';
6
+ import type { KeqContextRequest } from './keq-context-request.js';
9
7
  export interface KeqContextOptions extends KeqOptionsParameter {
10
8
  [key: string]: any;
11
9
  }
12
- export interface KeqRequestContext {
13
- url: URL | globalThis.URL;
14
- method: KeqRequestMethod;
15
- headers: Headers;
16
- routeParams: Record<string, string>;
17
- body: KeqRequestBody;
18
- cache?: RequestCache;
19
- credentials?: RequestCredentials;
20
- integrity?: string;
21
- keepalive?: boolean;
22
- mode?: RequestMode;
23
- redirect?: RequestRedirect;
24
- referrer?: string;
25
- referrerPolicy?: ReferrerPolicy;
26
- }
27
10
  export interface KeqContext {
28
11
  /**
29
12
  * Middleware invoker counter
@@ -47,7 +30,7 @@ export interface KeqContext {
47
30
  /**
48
31
  * keq request context
49
32
  */
50
- request: KeqRequestContext;
33
+ request: KeqContextRequest;
51
34
  /** original response */
52
35
  res?: Response;
53
36
  /** proxy response */
@@ -0,0 +1,2 @@
1
+ import { KeqContextRequest } from './keq-context-request.js';
2
+ export type KeqInit = Partial<Omit<KeqContextRequest, 'url'>>;
@@ -0,0 +1,51 @@
1
+ /// <reference types="node" />
2
+ import { ExtractProperty } from './extract-property.js';
3
+ import { KeqContextRequestMethod } from './keq-context-request.js';
4
+ export interface KeqOperation {
5
+ requestParams: {
6
+ [key: string]: string;
7
+ };
8
+ requestQuery: {
9
+ [key: string]: string | string[];
10
+ };
11
+ requestHeaders: {
12
+ [key: string]: string;
13
+ };
14
+ requestBody: FormData | URLSearchParams | object | Array<any> | string;
15
+ responseBody: any;
16
+ }
17
+ export type ExtractHeaders<T extends Pick<KeqOperation, 'requestHeaders'>> = ExtractProperty<T['requestHeaders'], string>;
18
+ export type ExtractQuery<T extends Pick<KeqOperation, 'requestQuery'>> = ExtractProperty<T['requestQuery'], string | string[]>;
19
+ export type ExtractParams<T extends Pick<KeqOperation, 'requestParams'>> = ExtractProperty<T['requestParams'], string>;
20
+ export type ExtractFields<T extends Pick<KeqOperation, 'requestBody'>> = ExtractProperty<Exclude<Extract<T['requestBody'], object>, FormData | URLSearchParams | Array<any>>, string>;
21
+ export type ExtractFiles<T extends Pick<KeqOperation, 'requestBody'>> = ExtractProperty<Exclude<Extract<T['requestBody'], object>, FormData | URLSearchParams | Array<any>>, Buffer | Blob | File>;
22
+ export type KeqOperations = {
23
+ [url: string]: {
24
+ [method in KeqContextRequestMethod]?: KeqOperation;
25
+ };
26
+ };
27
+ export type FlattenOperations<T extends KeqOperations, M extends KeqContextRequestMethod> = {
28
+ [P in keyof T as T[P][M] extends KeqOperation ? P : never]: T[P][M] extends KeqOperation ? T[P][M] : never;
29
+ };
30
+ export interface KeqBaseOperation extends KeqOperation {
31
+ url: string;
32
+ method: KeqContextRequestMethod;
33
+ output: any;
34
+ requestParams: {
35
+ [key: string]: string;
36
+ };
37
+ requestQuery: {
38
+ [key: string]: string | string[];
39
+ };
40
+ requestHeaders: {
41
+ 'content-type': string;
42
+ cookie: string;
43
+ host: string;
44
+ authorization: string;
45
+ 'cache-control': string;
46
+ 'content-encoding': string;
47
+ referer: string;
48
+ 'user-agent': string;
49
+ };
50
+ requestBody: FormData | URLSearchParams | object | Array<any> | string;
51
+ }
@@ -1,9 +1,9 @@
1
1
  import type { Keq } from "../keq.js";
2
2
  import type { KeqFlowControl } from './keq-flow-control.js';
3
3
  import type { KeqResolveMethod } from './keq-resolve-with-mode.js';
4
- import type { KeqRetryDelay } from './keq-retry-delay.js';
5
- import type { KeqRetryOn } from './keq-retry-on.js';
4
+ import type { KeqRetryOn, KeqRetryDelay } from './keq-retry.js';
6
5
  import type { KeqTimeout } from './keq-timeout.js';
6
+ import { ExcludeProperty } from './exclude-property.js';
7
7
  export interface KeqOptions<T> {
8
8
  /**
9
9
  * replace the default fetch api
@@ -45,13 +45,11 @@ export interface KeqOptions<T> {
45
45
  }
46
46
  type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
47
47
  type FirstArgType<T> = T extends (arg1: infer P, ...args: any[]) => any ? P : never;
48
- type ExcludeNever<T> = Pick<T, {
49
- [K in keyof T]: T[K] extends never ? never : K;
50
- }[keyof T]>;
51
- export type KeqOptionsParameter = ExcludeNever<{
48
+ type ExcludeNeverProperty<T> = ExcludeProperty<T, never>;
49
+ export type KeqOptionsParameter = ExcludeNeverProperty<{
52
50
  [key in keyof KeqOptions<any>]?: FirstArgType<KeqOptions<any>[key]>;
53
51
  }>;
54
- export type KeqOptionsReturnType<T> = ExcludeNever<{
52
+ export type KeqOptionsReturnType<T> = ExcludeNeverProperty<{
55
53
  [key in keyof KeqOptions<T>]: ReturnType<KeqOptions<T>[key]>;
56
54
  }>;
57
55
  export {};
@@ -2,19 +2,33 @@ import type { URL } from 'whatwg-url';
2
2
  import type { KeqRouter } from "../router/keq-router.js";
3
3
  import type { Keq } from "../keq.js";
4
4
  import type { KeqMiddleware } from './keq-middleware.js';
5
- import type { KeqRequestInit } from './keq-request-init.js';
6
- type KeqRequestFn = <T = any>(url: string | URL | globalThis.URL) => Keq<T>;
5
+ import type { KeqInit } from './keq-init.js';
6
+ import { FlattenOperations, KeqOperation, KeqOperations } from './keq-operation.js';
7
7
  type GlobalURL = globalThis.URL;
8
- export interface KeqRequest {
9
- <T = any>(url: string | URL | GlobalURL, init: Omit<KeqRequestInit, 'global'>): Keq<T>;
8
+ interface KeqRequestFn<OPERATIONS extends Record<string, KeqOperation>> {
9
+ <Path extends keyof OPERATIONS>(url: Path): Keq<OPERATIONS[Path]['responseBody'], OPERATIONS[Path]>;
10
+ <OUTPUT = any>(url: string): Keq<OUTPUT>;
11
+ <OUTPUT = any>(url: URL): Keq<OUTPUT>;
12
+ <OUTPUT = any>(url: GlobalURL): Keq<OUTPUT>;
13
+ }
14
+ type PickKeqOperationsProperty<T extends KeqOperations, P extends keyof T, X extends keyof KeqOperation> = T extends {
15
+ [Path in keyof T as Path extends P ? Path : never]: {
16
+ [Method in keyof T[Path] as T[Path][Method] extends KeqOperation ? Method : never]: infer R;
17
+ };
18
+ } ? R extends KeqOperation ? R[X] : never : never;
19
+ export interface KeqRequest<OPERATIONS extends KeqOperations> {
20
+ <Path extends keyof OPERATIONS>(url: Path, init: Omit<KeqInit, 'global'>): Keq<Exclude<PickKeqOperationsProperty<OPERATIONS, Path, 'responseBody'>, undefined>>;
21
+ <OUTPUT = any>(url: string, init: Omit<KeqInit, 'global'>): Keq<OUTPUT>;
22
+ <OUTPUT = any>(url: URL, init: Omit<KeqInit, 'global'>): Keq<OUTPUT>;
23
+ <OUTPUT = any>(url: GlobalURL, init: Omit<KeqInit, 'global'>): Keq<OUTPUT>;
10
24
  baseOrigin: (baseOrigin: string) => void;
11
- get: KeqRequestFn;
12
- post: KeqRequestFn;
13
- del: KeqRequestFn;
14
- delete: KeqRequestFn;
15
- put: KeqRequestFn;
16
- patch: KeqRequestFn;
17
- head: KeqRequestFn;
25
+ get: KeqRequestFn<FlattenOperations<OPERATIONS, 'get'>>;
26
+ post: KeqRequestFn<FlattenOperations<OPERATIONS, 'post'>>;
27
+ del: KeqRequestFn<FlattenOperations<OPERATIONS, 'delete'>>;
28
+ delete: KeqRequestFn<FlattenOperations<OPERATIONS, 'delete'>>;
29
+ put: KeqRequestFn<FlattenOperations<OPERATIONS, 'put'>>;
30
+ patch: KeqRequestFn<FlattenOperations<OPERATIONS, 'patch'>>;
31
+ head: KeqRequestFn<FlattenOperations<OPERATIONS, 'head'>>;
18
32
  use(firstMiddleware: KeqMiddleware, ...middleware: KeqMiddleware[]): this;
19
33
  useRouter(): KeqRouter;
20
34
  }
@@ -1,2 +1,3 @@
1
1
  import type { KeqContext } from './keq-context.js';
2
2
  export type KeqRetryOn = (attempt: number, error: unknown | null, ctx: KeqContext) => (boolean | Promise<boolean>);
3
+ export type KeqRetryDelay = number | ((attempt: number, error: unknown | null, ctx: KeqContext) => number | Promise<number>);
@@ -0,0 +1 @@
1
+ export {};
@@ -1,2 +1,2 @@
1
- import type { KeqRequestBody } from "../types/keq-request-body.js";
2
- export declare function assignKeqRequestBody(left: KeqRequestBody, right: object | Array<any> | FormData | URLSearchParams | string): KeqRequestBody;
1
+ import { KeqContextRequestBody } from "../types/keq-context-request.js";
2
+ export declare function assignKeqRequestBody(left: KeqContextRequestBody, right: object | Array<any> | FormData | URLSearchParams | string): KeqContextRequestBody;
@@ -1,2 +1,3 @@
1
- import type { ShorthandContentType } from "../types/shorthand-content-type.js";
2
- export declare function fixContentType(contentType: ShorthandContentType | string): string;
1
+ import { ShorthandContentType } from "../types/content-type.js";
2
+ export declare function fixContentType(contentType: ShorthandContentType): string;
3
+ export declare function fixContentType(contentType: string): string;
@@ -1,31 +1,32 @@
1
1
  import { URL } from 'whatwg-url';
2
- import type { KeqContextOptions, KeqRequestContext } from './types/keq-context.js';
2
+ import type { KeqContextOptions } from './types/keq-context.js';
3
3
  import type { KeqMiddleware } from './types/keq-middleware.js';
4
- import type { KeqRequestInit } from './types/keq-request-init.js';
5
- import { KeqEvents, KeqListeners } from './types/keq-events.js';
4
+ import type { KeqInit } from './types/keq-init.js';
5
+ import type { KeqEvents, KeqListeners } from './types/keq-events.js';
6
+ import type { KeqContextRequest } from './types/keq-context-request.js';
6
7
  /**
7
8
  * @description Keq 核心 API,发送请求必要的原子化的API
8
9
  */
9
- export declare class Core<T> {
10
+ export declare class Core<OUTPUT> {
10
11
  private requestPromise?;
11
- protected requestContext: Omit<KeqRequestContext, 'abort'>;
12
+ protected requestContext: Omit<KeqContextRequest, 'abort'>;
12
13
  protected __listeners__: KeqListeners;
13
14
  protected __global__: Record<string, any>;
14
15
  protected __prepend_middlewares__: KeqMiddleware[];
15
16
  protected __append_middlewares__: KeqMiddleware[];
16
17
  protected __options__: KeqContextOptions;
17
- constructor(url: (URL | globalThis.URL), init: KeqRequestInit, global?: Record<string, any>);
18
+ constructor(url: (URL | globalThis.URL), init: KeqInit, global?: Record<string, any>);
18
19
  prependMiddlewares(...middlewares: KeqMiddleware[]): this;
19
20
  appendMiddlewares(...middlewares: KeqMiddleware[]): this;
20
21
  on<K extends keyof KeqEvents>(event: K, listener: (data: KeqEvents[K]) => void): this;
21
22
  private run;
22
- end(): Promise<T>;
23
+ end(): Promise<OUTPUT>;
23
24
  /**
24
25
  * Attaches callbacks for the resolution and/or rejection of the Promise.
25
26
  * @param onfulfilled The callback to execute when the Promise is resolved.
26
27
  * @param onrejected The callback to execute when the Promise is rejected.
27
28
  * @returns A Promise for the completion of which ever callback is executed.
28
29
  */
29
- then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
30
- catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
30
+ then<TResult1 = OUTPUT, TResult2 = never>(onfulfilled?: ((value: OUTPUT) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
31
+ catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<OUTPUT | TResult>;
31
32
  }
@@ -7,19 +7,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
7
7
  if (v !== undefined) module.exports = v;
8
8
  }
9
9
  else if (typeof define === "function" && define.amd) {
10
- define(["require", "exports", "whatwg-url", "./exception/exception.js", "./util/clone.js", "./constant.js", "./util/compose-middleware.js", "./util/shadow-clone.js", "mitt"], factory);
10
+ define(["require", "exports", "mitt", "whatwg-url", "./exception/exception.js", "./util/clone.js", "./constant.js", "./util/compose-middleware.js", "./util/shadow-clone.js"], factory);
11
11
  }
12
12
  })(function (require, exports) {
13
13
  "use strict";
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.Core = void 0;
16
+ const mitt_1 = __importDefault(require("mitt"));
16
17
  const whatwg_url_1 = require("whatwg-url");
17
18
  const exception_js_1 = require("./exception/exception.js");
18
19
  const clone_js_1 = require("./util/clone.js");
19
20
  const constant_js_1 = require("./constant.js");
20
21
  const compose_middleware_js_1 = require("./util/compose-middleware.js");
21
22
  const shadow_clone_js_1 = require("./util/shadow-clone.js");
22
- const mitt_1 = __importDefault(require("mitt"));
23
23
  /**
24
24
  * @description Keq 核心 API,发送请求必要的原子化的API
25
25
  */
@@ -1,8 +1,9 @@
1
1
  import type { KeqMiddleware } from './types/keq-middleware.js';
2
2
  import type { KeqRequest } from './types/keq-request.js';
3
+ import { KeqOperations } from './types/keq-operation.js';
3
4
  interface CreateRequestOptions {
4
5
  initMiddlewares?: KeqMiddleware[];
5
6
  baseOrigin?: string;
6
7
  }
7
- export declare function createRequest(options?: CreateRequestOptions): KeqRequest;
8
+ export declare function createRequest<OPERATIONS extends KeqOperations>(options?: CreateRequestOptions): KeqRequest<OPERATIONS>;
8
9
  export {};
@@ -7,14 +7,13 @@ export type { KeqContext, KeqContextOptions } from './types/keq-context.js';
7
7
  export type { KeqMiddleware } from './types/keq-middleware.js';
8
8
  export type { KeqNext } from './types/keq-next.js';
9
9
  export type { KeqOptions } from './types/keq-options.js';
10
- export type { KeqRequestBody } from './types/keq-request-body.js';
11
- export type { KeqRequestInit } from './types/keq-request-init.js';
10
+ export type { KeqInit } from './types/keq-init.js';
12
11
  export type { KeqRequest } from './types/keq-request.js';
13
- export type { KeqRetryDelay } from './types/keq-retry-delay.js';
14
- export type { KeqRetryOn } from './types/keq-retry-on.js';
15
12
  export type { KeqRoute } from './types/keq-route.js';
16
13
  export type { KeqGlobal } from './types/keq-global.js';
17
14
  export type { KeqEvents } from './types/keq-events.js';
15
+ export type { KeqRetryOn, KeqRetryDelay } from './types/keq-retry.js';
16
+ export type { KeqOperations, KeqBaseOperation } from './types/keq-operation.js';
18
17
  export { keqHostRoute } from './router/keq-host-route.js';
19
18
  export { keqLocationRoute } from './router/keq-location-route.js';
20
19
  export { keqMethodRoute } from './router/keq-method-route.js';
@@ -1,20 +1,20 @@
1
1
  /// <reference types="node" />
2
2
  import { Core } from './core.js';
3
3
  import { KeqFlowControlMode, KeqFlowControlSignal } from './types/keq-flow-control.js';
4
- import type { KeqRetryOn } from './types/keq-retry-on.js';
4
+ import type { KeqRetryOn, KeqRetryDelay } from './types/keq-retry.js';
5
5
  import type { KeqMiddleware } from './types/keq-middleware.js';
6
6
  import type { KeqOptionsParameter, KeqOptionsReturnType } from './types/keq-options.js';
7
7
  import type { KeqQueryValue } from './types/keq-query-value.js';
8
- import type { KeqRequestBody } from './types/keq-request-body.js';
9
- import type { KeqRetryDelay } from './types/keq-retry-delay.js';
10
- import type { ShorthandContentType } from './types/shorthand-content-type.js';
11
- import { KeqContextOptions } from './types/keq-context.js';
8
+ import type { CommonContentType, ShorthandContentType } from './types/content-type.js';
9
+ import type { KeqContextOptions } from './types/keq-context.js';
10
+ import type { ExtractFields, ExtractFiles, ExtractHeaders, ExtractParams, ExtractQuery, KeqBaseOperation, KeqOperation } from './types/keq-operation.js';
11
+ import type { KeqContextRequestBody } from './types/keq-context-request.js';
12
12
  /**
13
13
  * @description Keq 扩展 API,人性化的常用的API
14
14
  */
15
- export declare class Keq<T> extends Core<T> {
15
+ export declare class Keq<OUTPUT, OPERATION extends Omit<KeqOperation, 'responseBody'> = KeqBaseOperation> extends Core<OUTPUT> {
16
16
  use(...middlewares: KeqMiddleware[]): this;
17
- option<K extends keyof KeqOptionsReturnType<T>>(key: K, value?: KeqOptionsParameter[K]): KeqOptionsReturnType<T>[K];
17
+ option<K extends keyof KeqOptionsReturnType<OUTPUT>>(key: K, value?: KeqOptionsParameter[K]): KeqOptionsReturnType<OUTPUT>[K];
18
18
  option(key: string, value?: any): this;
19
19
  options(opts: KeqContextOptions): this;
20
20
  /**
@@ -22,27 +22,36 @@ export declare class Keq<T> extends Core<T> {
22
22
  *
23
23
  * @description 设置请求头
24
24
  */
25
+ set(headers: ExtractHeaders<OPERATION>): this;
26
+ set<T extends keyof ExtractHeaders<OPERATION>>(name: T, value: ExtractHeaders<OPERATION>[T]): this;
27
+ set<T extends keyof KeqBaseOperation['requestHeaders']>(name: T, value: KeqBaseOperation['requestHeaders'][T]): this;
25
28
  set(headers: Headers): this;
26
29
  set(headers: Record<string, string>): this;
27
30
  set(name: string, value: string): this;
28
31
  /**
29
32
  * Set request query/searchParams
30
33
  */
34
+ query(key: ExtractQuery<OPERATION>): this;
35
+ query<T extends keyof ExtractQuery<OPERATION>>(key: T, value: ExtractQuery<OPERATION>[T]): this;
31
36
  query(key: Record<string, KeqQueryValue | KeqQueryValue[]>): this;
32
37
  query(key: string, value: KeqQueryValue | KeqQueryValue[]): this;
33
38
  /**
34
39
  * Set request route params
35
40
  */
41
+ params(key: ExtractParams<OPERATION>): this;
42
+ params<T extends keyof ExtractParams<OPERATION>>(key: T, value: ExtractParams<OPERATION>[T]): this;
36
43
  params(key: Record<string, string | number>): this;
37
44
  params(key: string, value: string | number): this;
38
45
  /**
39
46
  * Set request body
40
47
  */
41
- body(value: KeqRequestBody): this;
48
+ body(value: KeqContextRequestBody): this;
42
49
  /**
43
50
  * Setting the Content-Type
44
51
  */
45
- type(contentType: ShorthandContentType | string): this;
52
+ type(contentType: ShorthandContentType): this;
53
+ type(contentType: CommonContentType): this;
54
+ type(contentType: string): this;
46
55
  /**
47
56
  * Http Basic Authentication
48
57
  */
@@ -51,10 +60,17 @@ export declare class Keq<T> extends Core<T> {
51
60
  /**
52
61
  * set request body
53
62
  */
54
- send(value: FormData | URLSearchParams | object | Array<any> | string): this;
63
+ send(value: OPERATION['requestBody'] | object): this;
64
+ send(value: FormData): this;
65
+ send(value: URLSearchParams): this;
66
+ send(value: Array<any>): this;
67
+ send(value: string): this;
68
+ field<T extends keyof ExtractFields<OPERATION>>(arg1: T, value: ExtractFields<OPERATION>[T]): this;
69
+ field(arg1: ExtractFields<OPERATION>): this;
55
70
  field(arg1: string, value: string | string[]): this;
56
71
  field(arg1: Record<string, string>): this;
57
- attach(key: string, value: Blob | File | Buffer): this;
72
+ attach<T extends keyof ExtractFiles<OPERATION>>(key: T, value: Blob | File | Buffer, filename: string): this;
73
+ attach<T extends keyof ExtractFiles<OPERATION>>(key: T, value: Blob | File | Buffer): this;
58
74
  attach(key: string, value: Blob | File | Buffer, filename: string): this;
59
75
  attach(key: string, value: Blob | File | Buffer): this;
60
76
  /**
@@ -63,7 +79,7 @@ export declare class Keq<T> extends Core<T> {
63
79
  * @param retryDelay Initial value used to calculate the retry in milliseconds (This is still randomized following the randomization factor)
64
80
  * @param retryCallback Will be called after request failed
65
81
  */
66
- retry(retryTimes: number, retryDelay?: KeqRetryDelay, retryOn?: KeqRetryOn): Keq<T>;
82
+ retry(retryTimes: number, retryDelay?: KeqRetryDelay, retryOn?: KeqRetryOn): Keq<OUTPUT>;
67
83
  redirect(mod: RequestRedirect): this;
68
84
  credentials(mod: RequestCredentials): this;
69
85
  mode(mod: RequestMode): this;
@@ -73,11 +73,11 @@
73
73
  else if (typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint') {
74
74
  this.requestContext.url.searchParams.append(key, String(value));
75
75
  }
76
- else if (value === 'undefined' || value === null) {
76
+ else if (value === 'undefined' || value === null || value === undefined) {
77
77
  // skip
78
78
  }
79
79
  else {
80
- console.warn(`query value type is invalid, key: ${key}`);
80
+ console.warn(`query value type(${typeof value}) is invalid, key: ${key}`);
81
81
  }
82
82
  return this;
83
83
  }
@@ -104,9 +104,6 @@
104
104
  this.requestContext.body = value;
105
105
  return this;
106
106
  }
107
- /**
108
- * Setting the Content-Type
109
- */
110
107
  type(contentType) {
111
108
  const type = (0, fix_content_type_js_1.fixContentType)(contentType);
112
109
  this.set('Content-Type', type);
@@ -123,9 +120,6 @@
123
120
  if (!this.requestContext.headers.has('Content-Type'))
124
121
  void this.type(contentType);
125
122
  }
126
- /**
127
- * set request body
128
- */
129
123
  send(value) {
130
124
  this.requestContext.body = (0, assign_keq_request_body_js_1.assignKeqRequestBody)(this.requestContext.body, value);
131
125
  if ((0, is_url_search_params_js_1.isUrlSearchParams)(value)) {
@@ -1 +1 @@
1
- export declare const request: import("./index.js").KeqRequest;
1
+ export declare const request: import("./index.js").KeqRequest<import("./index.js").KeqOperations>;
@@ -0,0 +1,2 @@
1
+ export type ShorthandContentType = 'json' | 'form-data' | 'form' | 'jpeg' | 'bmp' | 'apng' | 'gif' | 'x-icon' | 'png' | 'webp' | 'tiff' | 'svg' | 'xml' | 'html' | 'css';
2
+ export type CommonContentType = 'application/json' | 'multipart/form-data' | 'application/x-www-form-urlencoded' | 'image/jpeg' | 'image/bmp' | 'image/apng' | 'image/gif' | 'image/x-icon' | 'image/png' | 'image/webp' | 'image/tiff' | 'image/svg+xml' | 'text/xml' | 'text/html' | 'text/css';
@@ -0,0 +1,3 @@
1
+ export type ExcludeProperty<T, U> = Pick<T, {
2
+ [K in keyof T]: T[K] extends U ? never : K;
3
+ }[keyof T]>;
@@ -0,0 +1,3 @@
1
+ export type ExtractProperty<T, U> = {
2
+ [K in keyof T as T[K] extends U ? K : never]: T[K];
3
+ };
@@ -0,0 +1,18 @@
1
+ import { URL } from 'whatwg-url';
2
+ export type KeqContextRequestMethod = 'get' | 'post' | 'put' | 'delete' | 'head' | 'patch';
3
+ export type KeqContextRequestBody = object | Array<any> | string | undefined;
4
+ export interface KeqContextRequest {
5
+ url: URL | globalThis.URL;
6
+ method: KeqContextRequestMethod;
7
+ headers: Headers;
8
+ routeParams: Record<string, string>;
9
+ body: KeqContextRequestBody;
10
+ cache?: RequestCache;
11
+ credentials?: RequestCredentials;
12
+ integrity?: string;
13
+ keepalive?: boolean;
14
+ mode?: RequestMode;
15
+ redirect?: RequestRedirect;
16
+ referrer?: string;
17
+ referrerPolicy?: ReferrerPolicy;
18
+ }
@@ -1,29 +1,12 @@
1
1
  import { Emitter } from 'mitt';
2
- import { URL } from 'whatwg-url';
3
2
  import { ABORT_PROPERTY, NEXT_INVOKED_PROPERTY, OUTPUT_PROPERTY } from "../constant.js";
4
- import type { KeqRequestBody } from './keq-request-body.js';
5
- import type { KeqRequestMethod } from './keq-request-method.js';
6
3
  import type { KeqOptionsParameter } from './keq-options.js';
7
4
  import type { KeqEvents } from './keq-events.js';
8
5
  import type { KeqGlobal } from './keq-global.js';
6
+ import type { KeqContextRequest } from './keq-context-request.js';
9
7
  export interface KeqContextOptions extends KeqOptionsParameter {
10
8
  [key: string]: any;
11
9
  }
12
- export interface KeqRequestContext {
13
- url: URL | globalThis.URL;
14
- method: KeqRequestMethod;
15
- headers: Headers;
16
- routeParams: Record<string, string>;
17
- body: KeqRequestBody;
18
- cache?: RequestCache;
19
- credentials?: RequestCredentials;
20
- integrity?: string;
21
- keepalive?: boolean;
22
- mode?: RequestMode;
23
- redirect?: RequestRedirect;
24
- referrer?: string;
25
- referrerPolicy?: ReferrerPolicy;
26
- }
27
10
  export interface KeqContext {
28
11
  /**
29
12
  * Middleware invoker counter
@@ -47,7 +30,7 @@ export interface KeqContext {
47
30
  /**
48
31
  * keq request context
49
32
  */
50
- request: KeqRequestContext;
33
+ request: KeqContextRequest;
51
34
  /** original response */
52
35
  res?: Response;
53
36
  /** proxy response */
@@ -0,0 +1,2 @@
1
+ import { KeqContextRequest } from './keq-context-request.js';
2
+ export type KeqInit = Partial<Omit<KeqContextRequest, 'url'>>;
@@ -0,0 +1,51 @@
1
+ /// <reference types="node" />
2
+ import { ExtractProperty } from './extract-property.js';
3
+ import { KeqContextRequestMethod } from './keq-context-request.js';
4
+ export interface KeqOperation {
5
+ requestParams: {
6
+ [key: string]: string;
7
+ };
8
+ requestQuery: {
9
+ [key: string]: string | string[];
10
+ };
11
+ requestHeaders: {
12
+ [key: string]: string;
13
+ };
14
+ requestBody: FormData | URLSearchParams | object | Array<any> | string;
15
+ responseBody: any;
16
+ }
17
+ export type ExtractHeaders<T extends Pick<KeqOperation, 'requestHeaders'>> = ExtractProperty<T['requestHeaders'], string>;
18
+ export type ExtractQuery<T extends Pick<KeqOperation, 'requestQuery'>> = ExtractProperty<T['requestQuery'], string | string[]>;
19
+ export type ExtractParams<T extends Pick<KeqOperation, 'requestParams'>> = ExtractProperty<T['requestParams'], string>;
20
+ export type ExtractFields<T extends Pick<KeqOperation, 'requestBody'>> = ExtractProperty<Exclude<Extract<T['requestBody'], object>, FormData | URLSearchParams | Array<any>>, string>;
21
+ export type ExtractFiles<T extends Pick<KeqOperation, 'requestBody'>> = ExtractProperty<Exclude<Extract<T['requestBody'], object>, FormData | URLSearchParams | Array<any>>, Buffer | Blob | File>;
22
+ export type KeqOperations = {
23
+ [url: string]: {
24
+ [method in KeqContextRequestMethod]?: KeqOperation;
25
+ };
26
+ };
27
+ export type FlattenOperations<T extends KeqOperations, M extends KeqContextRequestMethod> = {
28
+ [P in keyof T as T[P][M] extends KeqOperation ? P : never]: T[P][M] extends KeqOperation ? T[P][M] : never;
29
+ };
30
+ export interface KeqBaseOperation extends KeqOperation {
31
+ url: string;
32
+ method: KeqContextRequestMethod;
33
+ output: any;
34
+ requestParams: {
35
+ [key: string]: string;
36
+ };
37
+ requestQuery: {
38
+ [key: string]: string | string[];
39
+ };
40
+ requestHeaders: {
41
+ 'content-type': string;
42
+ cookie: string;
43
+ host: string;
44
+ authorization: string;
45
+ 'cache-control': string;
46
+ 'content-encoding': string;
47
+ referer: string;
48
+ 'user-agent': string;
49
+ };
50
+ requestBody: FormData | URLSearchParams | object | Array<any> | string;
51
+ }
@@ -1,9 +1,9 @@
1
1
  import type { Keq } from "../keq.js";
2
2
  import type { KeqFlowControl } from './keq-flow-control.js';
3
3
  import type { KeqResolveMethod } from './keq-resolve-with-mode.js';
4
- import type { KeqRetryDelay } from './keq-retry-delay.js';
5
- import type { KeqRetryOn } from './keq-retry-on.js';
4
+ import type { KeqRetryOn, KeqRetryDelay } from './keq-retry.js';
6
5
  import type { KeqTimeout } from './keq-timeout.js';
6
+ import { ExcludeProperty } from './exclude-property.js';
7
7
  export interface KeqOptions<T> {
8
8
  /**
9
9
  * replace the default fetch api
@@ -45,13 +45,11 @@ export interface KeqOptions<T> {
45
45
  }
46
46
  type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
47
47
  type FirstArgType<T> = T extends (arg1: infer P, ...args: any[]) => any ? P : never;
48
- type ExcludeNever<T> = Pick<T, {
49
- [K in keyof T]: T[K] extends never ? never : K;
50
- }[keyof T]>;
51
- export type KeqOptionsParameter = ExcludeNever<{
48
+ type ExcludeNeverProperty<T> = ExcludeProperty<T, never>;
49
+ export type KeqOptionsParameter = ExcludeNeverProperty<{
52
50
  [key in keyof KeqOptions<any>]?: FirstArgType<KeqOptions<any>[key]>;
53
51
  }>;
54
- export type KeqOptionsReturnType<T> = ExcludeNever<{
52
+ export type KeqOptionsReturnType<T> = ExcludeNeverProperty<{
55
53
  [key in keyof KeqOptions<T>]: ReturnType<KeqOptions<T>[key]>;
56
54
  }>;
57
55
  export {};
@@ -2,19 +2,33 @@ import type { URL } from 'whatwg-url';
2
2
  import type { KeqRouter } from "../router/keq-router.js";
3
3
  import type { Keq } from "../keq.js";
4
4
  import type { KeqMiddleware } from './keq-middleware.js';
5
- import type { KeqRequestInit } from './keq-request-init.js';
6
- type KeqRequestFn = <T = any>(url: string | URL | globalThis.URL) => Keq<T>;
5
+ import type { KeqInit } from './keq-init.js';
6
+ import { FlattenOperations, KeqOperation, KeqOperations } from './keq-operation.js';
7
7
  type GlobalURL = globalThis.URL;
8
- export interface KeqRequest {
9
- <T = any>(url: string | URL | GlobalURL, init: Omit<KeqRequestInit, 'global'>): Keq<T>;
8
+ interface KeqRequestFn<OPERATIONS extends Record<string, KeqOperation>> {
9
+ <Path extends keyof OPERATIONS>(url: Path): Keq<OPERATIONS[Path]['responseBody'], OPERATIONS[Path]>;
10
+ <OUTPUT = any>(url: string): Keq<OUTPUT>;
11
+ <OUTPUT = any>(url: URL): Keq<OUTPUT>;
12
+ <OUTPUT = any>(url: GlobalURL): Keq<OUTPUT>;
13
+ }
14
+ type PickKeqOperationsProperty<T extends KeqOperations, P extends keyof T, X extends keyof KeqOperation> = T extends {
15
+ [Path in keyof T as Path extends P ? Path : never]: {
16
+ [Method in keyof T[Path] as T[Path][Method] extends KeqOperation ? Method : never]: infer R;
17
+ };
18
+ } ? R extends KeqOperation ? R[X] : never : never;
19
+ export interface KeqRequest<OPERATIONS extends KeqOperations> {
20
+ <Path extends keyof OPERATIONS>(url: Path, init: Omit<KeqInit, 'global'>): Keq<Exclude<PickKeqOperationsProperty<OPERATIONS, Path, 'responseBody'>, undefined>>;
21
+ <OUTPUT = any>(url: string, init: Omit<KeqInit, 'global'>): Keq<OUTPUT>;
22
+ <OUTPUT = any>(url: URL, init: Omit<KeqInit, 'global'>): Keq<OUTPUT>;
23
+ <OUTPUT = any>(url: GlobalURL, init: Omit<KeqInit, 'global'>): Keq<OUTPUT>;
10
24
  baseOrigin: (baseOrigin: string) => void;
11
- get: KeqRequestFn;
12
- post: KeqRequestFn;
13
- del: KeqRequestFn;
14
- delete: KeqRequestFn;
15
- put: KeqRequestFn;
16
- patch: KeqRequestFn;
17
- head: KeqRequestFn;
25
+ get: KeqRequestFn<FlattenOperations<OPERATIONS, 'get'>>;
26
+ post: KeqRequestFn<FlattenOperations<OPERATIONS, 'post'>>;
27
+ del: KeqRequestFn<FlattenOperations<OPERATIONS, 'delete'>>;
28
+ delete: KeqRequestFn<FlattenOperations<OPERATIONS, 'delete'>>;
29
+ put: KeqRequestFn<FlattenOperations<OPERATIONS, 'put'>>;
30
+ patch: KeqRequestFn<FlattenOperations<OPERATIONS, 'patch'>>;
31
+ head: KeqRequestFn<FlattenOperations<OPERATIONS, 'head'>>;
18
32
  use(firstMiddleware: KeqMiddleware, ...middleware: KeqMiddleware[]): this;
19
33
  useRouter(): KeqRouter;
20
34
  }
@@ -1,2 +1,3 @@
1
1
  import type { KeqContext } from './keq-context.js';
2
2
  export type KeqRetryOn = (attempt: number, error: unknown | null, ctx: KeqContext) => (boolean | Promise<boolean>);
3
+ export type KeqRetryDelay = number | ((attempt: number, error: unknown | null, ctx: KeqContext) => number | Promise<number>);
@@ -0,0 +1,12 @@
1
+ (function (factory) {
2
+ if (typeof module === "object" && typeof module.exports === "object") {
3
+ var v = factory(require, exports);
4
+ if (v !== undefined) module.exports = v;
5
+ }
6
+ else if (typeof define === "function" && define.amd) {
7
+ define(["require", "exports"], factory);
8
+ }
9
+ })(function (require, exports) {
10
+ "use strict";
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ });
@@ -1,2 +1,2 @@
1
- import type { KeqRequestBody } from "../types/keq-request-body.js";
2
- export declare function assignKeqRequestBody(left: KeqRequestBody, right: object | Array<any> | FormData | URLSearchParams | string): KeqRequestBody;
1
+ import { KeqContextRequestBody } from "../types/keq-context-request.js";
2
+ export declare function assignKeqRequestBody(left: KeqContextRequestBody, right: object | Array<any> | FormData | URLSearchParams | string): KeqContextRequestBody;
@@ -1,2 +1,3 @@
1
- import type { ShorthandContentType } from "../types/shorthand-content-type.js";
2
- export declare function fixContentType(contentType: ShorthandContentType | string): string;
1
+ import { ShorthandContentType } from "../types/content-type.js";
2
+ export declare function fixContentType(contentType: ShorthandContentType): string;
3
+ export declare function fixContentType(contentType: string): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keq",
3
- "version": "2.6.2",
3
+ "version": "2.6.3",
4
4
  "description": "Request API write by Typescript for flexibility, readability, and a low learning curve.",
5
5
  "keywords": [
6
6
  "request",
@@ -72,7 +72,7 @@
72
72
  "typescript": "^5.4.5",
73
73
  "typescript-transform-paths": "^3.4.7"
74
74
  },
75
- "packageManager": "pnpm@9.1.2",
75
+ "packageManager": "pnpm@9.1.4",
76
76
  "engines": {
77
77
  "node": ">=18.0.0"
78
78
  }
@@ -1 +0,0 @@
1
- export type KeqRequestBody = object | Array<any> | string | undefined;
@@ -1,2 +0,0 @@
1
- import type { KeqRequestContext } from './keq-context.js';
2
- export type KeqRequestInit = Partial<Omit<KeqRequestContext, 'url'>>;
@@ -1 +0,0 @@
1
- export type KeqRequestMethod = 'get' | 'post' | 'put' | 'delete' | 'head' | 'patch';
@@ -1,2 +0,0 @@
1
- import type { KeqContext } from './keq-context';
2
- export type KeqRetryDelay = number | ((attempt: number, error: unknown | null, ctx: KeqContext) => number | Promise<number>);
@@ -1 +0,0 @@
1
- export type ShorthandContentType = 'json' | 'form-data' | 'form' | 'jpeg' | 'bmp' | 'apng' | 'gif' | 'x-icon' | 'png' | 'webp' | 'tiff' | 'svg' | 'xml' | 'html' | 'css';
@@ -1 +0,0 @@
1
- export type KeqRequestBody = object | Array<any> | string | undefined;
@@ -1,2 +0,0 @@
1
- import type { KeqRequestContext } from './keq-context.js';
2
- export type KeqRequestInit = Partial<Omit<KeqRequestContext, 'url'>>;
@@ -1 +0,0 @@
1
- export type KeqRequestMethod = 'get' | 'post' | 'put' | 'delete' | 'head' | 'patch';
@@ -1,2 +0,0 @@
1
- import type { KeqContext } from './keq-context';
2
- export type KeqRetryDelay = number | ((attempt: number, error: unknown | null, ctx: KeqContext) => number | Promise<number>);
@@ -1 +0,0 @@
1
- export type ShorthandContentType = 'json' | 'form-data' | 'form' | 'jpeg' | 'bmp' | 'apng' | 'gif' | 'x-icon' | 'png' | 'webp' | 'tiff' | 'svg' | 'xml' | 'html' | 'css';