@ahoo-wang/fetcher 0.8.3 → 0.8.5

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/README.md CHANGED
@@ -51,8 +51,10 @@ const fetcher = new Fetcher({
51
51
 
52
52
  // GET request with path and query parameters
53
53
  const response = await fetcher.get('/users/{id}', {
54
- path: { id: 123 },
55
- query: { include: 'profile' },
54
+ urlParams: {
55
+ path: { id: 123 },
56
+ query: { include: 'profile' },
57
+ },
56
58
  });
57
59
  const userData = await response.json<User>();
58
60
 
package/README.zh-CN.md CHANGED
@@ -50,8 +50,10 @@ const fetcher = new Fetcher({
50
50
 
51
51
  // 带路径和查询参数的 GET 请求
52
52
  const response = await fetcher.get('/users/{id}', {
53
- path: { id: 123 },
54
- query: { include: 'profile' },
53
+ urlParams: {
54
+ path: { id: 123 },
55
+ query: { include: 'profile' },
56
+ },
55
57
  });
56
58
  const userData = await response.json<User>();
57
59
 
@@ -1,89 +1,5 @@
1
1
  import { Fetcher } from './fetcher';
2
- import { HeadersCapable } from './types';
3
- import { TimeoutCapable } from './timeout';
4
- /**
5
- * Fetcher request configuration interface
6
- *
7
- * This interface defines all the configuration options available for making HTTP requests
8
- * with the Fetcher client. It extends the standard RequestInit interface while adding
9
- * Fetcher-specific features like path parameters, query parameters, and timeout control.
10
- *
11
- * @example
12
- * ```typescript
13
- * const request: FetcherRequest = {
14
- * method: 'GET',
15
- * path: { id: 123 },
16
- * query: { include: 'profile' },
17
- * headers: { 'Authorization': 'Bearer token' },
18
- * timeout: 5000
19
- * };
20
- *
21
- * const response = await fetcher.fetch('/users/{id}', request);
22
- * ```
23
- */
24
- export interface FetcherRequest extends TimeoutCapable, HeadersCapable, Omit<RequestInit, 'body' | 'headers'> {
25
- /**
26
- * Path parameters for URL templating
27
- *
28
- * An object containing key-value pairs that will be used to replace placeholders
29
- * in the URL path. Placeholders are specified using curly braces, e.g., '/users/{id}'.
30
- *
31
- * @example
32
- * ```typescript
33
- * // With URL '/users/{id}/posts/{postId}'
34
- * const request = {
35
- * path: { id: 123, postId: 456 }
36
- * };
37
- * // Results in URL: '/users/123/posts/456'
38
- * ```
39
- */
40
- path?: Record<string, any>;
41
- /**
42
- * Query parameters for URL query string
43
- *
44
- * An object containing key-value pairs that will be serialized and appended
45
- * to the URL as query parameters. Arrays are serialized as multiple parameters
46
- * with the same name, and objects are JSON-stringified.
47
- *
48
- * @example
49
- * ```typescript
50
- * const request = {
51
- * query: {
52
- * limit: 10,
53
- * filter: 'active',
54
- * tags: ['important', 'urgent']
55
- * }
56
- * };
57
- * // Results in query string: '?limit=10&filter=active&tags=important&tags=urgent'
58
- * ```
59
- */
60
- query?: Record<string, any>;
61
- /**
62
- * Request body
63
- *
64
- * The body of the request. Can be a string, Blob, ArrayBuffer, FormData,
65
- * URLSearchParams, or a plain object. Plain objects are automatically
66
- * converted to JSON and the appropriate Content-Type header is set.
67
- *
68
- * @example
69
- * ```typescript
70
- * // Plain object (automatically converted to JSON)
71
- * const request = {
72
- * method: 'POST',
73
- * body: { name: 'John', email: 'john@example.com' }
74
- * };
75
- *
76
- * // FormData
77
- * const formData = new FormData();
78
- * formData.append('name', 'John');
79
- * const request = {
80
- * method: 'POST',
81
- * body: formData
82
- * };
83
- * ```
84
- */
85
- body?: BodyInit | Record<string, any> | null;
86
- }
2
+ import { FetchRequest } from './fetchRequest';
87
3
  /**
88
4
  * FetchExchange Interface
89
5
  *
@@ -129,13 +45,9 @@ export interface FetchExchange {
129
45
  */
130
46
  fetcher: Fetcher;
131
47
  /**
132
- * The URL for this request
133
- */
134
- url: string;
135
- /**
136
- * The request configuration including method, headers, body, etc.
48
+ * The request configuration including url, method, headers, body, etc.
137
49
  */
138
- request: FetcherRequest;
50
+ request: FetchRequest;
139
51
  /**
140
52
  * The response object, undefined until the request completes successfully
141
53
  */
@@ -1 +1 @@
1
- {"version":3,"file":"fetchExchange.d.ts","sourceRoot":"","sources":["../src/fetchExchange.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG3C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,cACf,SAAQ,cAAc,EACpB,cAAc,EACd,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC;;;;;;;;;;;;;;OAcG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE3B;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE5B;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;CAC9C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,OAAO,EAAE,cAAc,CAAC;IAExB;;OAEG;IACH,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC;IAE/B;;OAEG;IACH,KAAK,EAAE,KAAK,GAAG,GAAG,GAAG,SAAS,CAAC;IAE/B;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAClC"}
1
+ {"version":3,"file":"fetchExchange.d.ts","sourceRoot":"","sources":["../src/fetchExchange.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,OAAO,EAAE,YAAY,CAAC;IAEtB;;OAEG;IACH,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC;IAE/B;;OAEG;IACH,KAAK,EAAE,KAAK,GAAG,GAAG,GAAG,SAAS,CAAC;IAE/B;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAClC"}
@@ -1 +1 @@
1
- {"version":3,"file":"fetchInterceptor.d.ts","sourceRoot":"","sources":["../src/fetchInterceptor.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;;;;;GAYG;AACH,qBAAa,gBAAiB,YAAW,WAAW;IAClD;;;;;;OAMG;IACH,IAAI,SAAsB;IAE1B;;;;;;;;;OASG;IACH,KAAK,SAAiC;IAEtC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACG,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;CAQjE"}
1
+ {"version":3,"file":"fetchInterceptor.d.ts","sourceRoot":"","sources":["../src/fetchInterceptor.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;;;;;GAYG;AACH,qBAAa,gBAAiB,YAAW,WAAW;IAClD;;;;;;OAMG;IACH,IAAI,SAAsB;IAE1B;;;;;;;;;OASG;IACH,KAAK,SAAiC;IAEtC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACG,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;CAIjE"}
@@ -0,0 +1,60 @@
1
+ import { TimeoutCapable } from './timeout';
2
+ import { HeadersCapable } from './types';
3
+ import { UrlParams } from './urlBuilder';
4
+ /**
5
+ * Fetcher request configuration interface
6
+ *
7
+ * This interface defines all the configuration options available for making HTTP requests
8
+ * with the Fetcher client. It extends the standard RequestInit interface while adding
9
+ * Fetcher-specific features like path parameters, query parameters, and timeout control.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const request: FetchRequestInit = {
14
+ * method: 'GET',
15
+ * urlParams: {
16
+ * path: { id: 123 },
17
+ * query: { include: 'profile' }
18
+ * },
19
+ * headers: { 'Authorization': 'Bearer token' },
20
+ * timeout: 5000
21
+ * };
22
+ *
23
+ * const response = await fetcher.fetch('/users/{id}', request);
24
+ * ```
25
+ */
26
+ export interface FetchRequestInit extends TimeoutCapable, HeadersCapable, Omit<RequestInit, 'body' | 'headers'> {
27
+ urlParams?: UrlParams;
28
+ /**
29
+ * Request body
30
+ *
31
+ * The body of the request. Can be a string, Blob, ArrayBuffer, FormData,
32
+ * URLSearchParams, or a plain object. Plain objects are automatically
33
+ * converted to JSON and the appropriate Content-Type header is set.
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * // Plain object (automatically converted to JSON)
38
+ * const request = {
39
+ * method: 'POST',
40
+ * body: { name: 'John', email: 'john@example.com' }
41
+ * };
42
+ *
43
+ * // FormData
44
+ * const formData = new FormData();
45
+ * formData.append('name', 'John');
46
+ * const request = {
47
+ * method: 'POST',
48
+ * body: formData
49
+ * };
50
+ * ```
51
+ */
52
+ body?: BodyInit | Record<string, any> | string | null;
53
+ }
54
+ export interface FetchRequest extends FetchRequestInit {
55
+ /**
56
+ * The URL for this request
57
+ */
58
+ url: string;
59
+ }
60
+ //# sourceMappingURL=fetchRequest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetchRequest.d.ts","sourceRoot":"","sources":["../src/fetchRequest.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,gBACf,SAAQ,cAAc,EACpB,cAAc,EACd,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC;CACvD;AAED,MAAM,WAAW,YAAa,SAAQ,gBAAgB;IACpD;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;CACb"}
package/dist/fetcher.d.ts CHANGED
@@ -1,10 +1,21 @@
1
1
  import { UrlBuilder, UrlBuilderCapable } from './urlBuilder';
2
2
  import { TimeoutCapable } from './timeout';
3
- import { BaseURLCapable, HeadersCapable, RequestField } from './types';
3
+ import { BaseURLCapable, HeadersCapable } from './types';
4
4
  import { FetcherInterceptors } from './interceptor';
5
- import { FetcherRequest, FetchExchange } from './fetchExchange';
5
+ import { FetchExchange } from './fetchExchange';
6
+ import { FetchRequest, FetchRequestInit } from './fetchRequest';
6
7
  /**
7
8
  * Fetcher configuration options interface
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const options: FetcherOptions = {
13
+ * baseURL: 'https://api.example.com',
14
+ * headers: { 'Content-Type': 'application/json' },
15
+ * timeout: 5000,
16
+ * interceptors: new FetcherInterceptors()
17
+ * };
18
+ * ```
8
19
  */
9
20
  export interface FetcherOptions extends BaseURLCapable, HeadersCapable, TimeoutCapable {
10
21
  interceptors?: FetcherInterceptors;
@@ -14,12 +25,16 @@ export declare const DEFAULT_OPTIONS: FetcherOptions;
14
25
  * HTTP client class that supports URL building, timeout control, and more
15
26
  *
16
27
  * @example
28
+ * ```typescript
17
29
  * const fetcher = new Fetcher({ baseURL: 'https://api.example.com' });
18
30
  * const response = await fetcher.fetch('/users/{id}', {
19
- * pathParams: { id: 123 },
20
- * queryParams: { filter: 'active' },
31
+ * urlParams: {
32
+ * path: { id: 123 },
33
+ * query: { filter: 'active' }
34
+ * },
21
35
  * timeout: 5000
22
36
  * });
37
+ * ```
23
38
  */
24
39
  export declare class Fetcher implements UrlBuilderCapable, HeadersCapable, TimeoutCapable {
25
40
  urlBuilder: UrlBuilder;
@@ -39,17 +54,16 @@ export declare class Fetcher implements UrlBuilderCapable, HeadersCapable, Timeo
39
54
  * @param request - Request options, including path parameters, query parameters, etc.
40
55
  * @returns Promise<Response> HTTP response
41
56
  */
42
- fetch(url: string, request?: FetcherRequest): Promise<Response>;
57
+ fetch(url: string, request?: FetchRequestInit): Promise<Response>;
43
58
  /**
44
59
  * Send an HTTP request
45
60
  *
46
- * @param url - Request URL address, supports path parameter placeholders
47
- * @param request - Request configuration object, including method, headers, body, etc.
61
+ * @param request - Request configuration object, including url, method, headers, body, etc.
48
62
  * @returns Promise that resolves to a FetchExchange object containing request and response information
49
63
  *
50
64
  * @throws Throws an exception when an error occurs during the request and is not handled by error interceptors
51
65
  */
52
- request(url: string, request?: FetcherRequest): Promise<FetchExchange>;
66
+ request(request: FetchRequest): Promise<FetchExchange>;
53
67
  /**
54
68
  * Process a fetch exchange through the interceptor chain
55
69
  *
@@ -83,7 +97,7 @@ export declare class Fetcher implements UrlBuilderCapable, HeadersCapable, Timeo
83
97
  * @param request - Request options, including path parameters, query parameters, etc.
84
98
  * @returns Promise<Response> HTTP response
85
99
  */
86
- get(url: string, request?: Omit<FetcherRequest, RequestField.METHOD | RequestField.BODY>): Promise<Response>;
100
+ get(url: string, request?: Omit<FetchRequestInit, 'method' | 'body'>): Promise<Response>;
87
101
  /**
88
102
  * Make a POST request
89
103
  *
@@ -91,7 +105,7 @@ export declare class Fetcher implements UrlBuilderCapable, HeadersCapable, Timeo
91
105
  * @param request - Request options, including path parameters, query parameters, request body, etc.
92
106
  * @returns Promise<Response> HTTP response
93
107
  */
94
- post(url: string, request?: Omit<FetcherRequest, RequestField.METHOD>): Promise<Response>;
108
+ post(url: string, request?: Omit<FetchRequestInit, 'method'>): Promise<Response>;
95
109
  /**
96
110
  * Make a PUT request
97
111
  *
@@ -99,7 +113,7 @@ export declare class Fetcher implements UrlBuilderCapable, HeadersCapable, Timeo
99
113
  * @param request - Request options, including path parameters, query parameters, request body, etc.
100
114
  * @returns Promise<Response> HTTP response
101
115
  */
102
- put(url: string, request?: Omit<FetcherRequest, RequestField.METHOD>): Promise<Response>;
116
+ put(url: string, request?: Omit<FetchRequestInit, 'method'>): Promise<Response>;
103
117
  /**
104
118
  * Make a DELETE request
105
119
  *
@@ -107,7 +121,7 @@ export declare class Fetcher implements UrlBuilderCapable, HeadersCapable, Timeo
107
121
  * @param request - Request options, including path parameters, query parameters, etc.
108
122
  * @returns Promise<Response> HTTP response
109
123
  */
110
- delete(url: string, request?: Omit<FetcherRequest, RequestField.METHOD>): Promise<Response>;
124
+ delete(url: string, request?: Omit<FetchRequestInit, 'method'>): Promise<Response>;
111
125
  /**
112
126
  * Make a PATCH request
113
127
  *
@@ -115,7 +129,7 @@ export declare class Fetcher implements UrlBuilderCapable, HeadersCapable, Timeo
115
129
  * @param request - Request options, including path parameters, query parameters, request body, etc.
116
130
  * @returns Promise<Response> HTTP response
117
131
  */
118
- patch(url: string, request?: Omit<FetcherRequest, RequestField.METHOD>): Promise<Response>;
132
+ patch(url: string, request?: Omit<FetchRequestInit, 'method'>): Promise<Response>;
119
133
  /**
120
134
  * Make a HEAD request
121
135
  *
@@ -123,7 +137,7 @@ export declare class Fetcher implements UrlBuilderCapable, HeadersCapable, Timeo
123
137
  * @param request - Request options, including path parameters, query parameters, etc.
124
138
  * @returns Promise<Response> HTTP response
125
139
  */
126
- head(url: string, request?: Omit<FetcherRequest, RequestField.METHOD | RequestField.BODY>): Promise<Response>;
140
+ head(url: string, request?: Omit<FetchRequestInit, 'method' | 'body'>): Promise<Response>;
127
141
  /**
128
142
  * Make an OPTIONS request
129
143
  *
@@ -131,6 +145,6 @@ export declare class Fetcher implements UrlBuilderCapable, HeadersCapable, Timeo
131
145
  * @param request - Request options, including path parameters, query parameters, etc.
132
146
  * @returns Promise<Response> HTTP response
133
147
  */
134
- options(url: string, request?: Omit<FetcherRequest, RequestField.METHOD | RequestField.BODY>): Promise<Response>;
148
+ options(url: string, request?: Omit<FetchRequestInit, 'method' | 'body'>): Promise<Response>;
135
149
  }
136
150
  //# sourceMappingURL=fetcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../src/fetcher.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAkB,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EACL,cAAc,EAGd,cAAc,EAEd,YAAY,EACb,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,cACf,SAAQ,cAAc,EACpB,cAAc,EACd,cAAc;IAChB,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAMD,eAAO,MAAM,eAAe,EAAE,cAG7B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,qBAAa,OAAQ,YAAW,iBAAiB,EAAE,cAAc,EAAE,cAAc;IAC/E,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAmB;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,mBAAmB,CAAC;IAElC;;;;OAIG;gBACS,OAAO,GAAE,cAAgC;IAOrD;;;;;;OAMG;IACG,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAQzE;;;;;;;;OAQG;IACG,OAAO,CACX,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,aAAa,CAAC;IAwBzB;;;;;;;;;;;;;;;OAeG;IACG,QAAQ,CAAC,aAAa,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAkBpE;;;;;;;OAOG;YACW,WAAW;IAWzB;;;;;;OAMG;IACG,GAAG,CACP,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,GAAG,YAAY,CAAC,IAAI,CAAM,GAC1E,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,IAAI,CACR,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,CAAM,GACtD,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,GAAG,CACP,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,CAAM,GACtD,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,MAAM,CACV,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,CAAM,GACtD,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,KAAK,CACT,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,CAAM,GACtD,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,IAAI,CACR,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,GAAG,YAAY,CAAC,IAAI,CAAM,GAC1E,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,OAAO,CACX,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,MAAM,GAAG,YAAY,CAAC,IAAI,CAAM,GAC1E,OAAO,CAAC,QAAQ,CAAC;CAGrB"}
1
+ {"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../src/fetcher.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAkB,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EACL,cAAc,EAGd,cAAc,EAEf,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGhE;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,cACf,SAAQ,cAAc,EACpB,cAAc,EACd,cAAc;IAChB,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAMD,eAAO,MAAM,eAAe,EAAE,cAG7B,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,qBAAa,OACX,YAAW,iBAAiB,EAAE,cAAc,EAAE,cAAc;IAE5D,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAmB;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,mBAAmB,CAAC;IAElC;;;;OAIG;gBACS,OAAO,GAAE,cAAgC;IAOrD;;;;;;OAMG;IACG,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAU3E;;;;;;;OAOG;IACG,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;IAmB5D;;;;;;;;;;;;;;;OAeG;IACG,QAAQ,CAAC,aAAa,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAkBpE;;;;;;;OAOG;YACW,WAAW;IAWzB;;;;;;OAMG;IACG,GAAG,CACP,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,GAAG,MAAM,CAAM,GACtD,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,IAAI,CACR,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAM,GAC7C,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,GAAG,CACP,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAM,GAC7C,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,MAAM,CACV,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAM,GAC7C,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,KAAK,CACT,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAM,GAC7C,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,IAAI,CACR,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,GAAG,MAAM,CAAM,GACtD,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;OAMG;IACG,OAAO,CACX,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,GAAG,MAAM,CAAM,GACtD,OAAO,CAAC,QAAQ,CAAC;CAGrB"}
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export * from './fetcher';
2
2
  export * from './fetcherRegistrar';
3
3
  export * from './fetchExchange';
4
4
  export * from './fetchInterceptor';
5
+ export * from './fetchRequest';
5
6
  export * from './interceptor';
6
7
  export * from './mergeRequest';
7
8
  export * from './namedFetcher';
@@ -12,4 +13,5 @@ export * from './types';
12
13
  export * from './urlBuilder';
13
14
  export * from './urlResolveInterceptor';
14
15
  export * from './urls';
16
+ export * from './utils';
15
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC;AACxC,cAAc,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC;AACxC,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC"}
package/dist/index.es.js CHANGED
@@ -1,14 +1,19 @@
1
1
  function E(r) {
2
2
  return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(r);
3
3
  }
4
- function I(r, e) {
4
+ function w(r, e) {
5
5
  return E(e) ? e : e ? r.replace(/\/?\/$/, "") + "/" + e.replace(/^\/+/, "") : r;
6
6
  }
7
- class w {
7
+ class P {
8
8
  /**
9
9
  * Creates a UrlBuilder instance
10
10
  *
11
11
  * @param baseURL - Base URL that all constructed URLs will be based on
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const urlBuilder = new UrlBuilder('https://api.example.com');
16
+ * ```
12
17
  */
13
18
  constructor(e) {
14
19
  this.baseURL = e;
@@ -16,30 +21,41 @@ class w {
16
21
  /**
17
22
  * Builds a complete URL, including path parameter replacement and query parameter addition
18
23
  *
19
- * @param url - URL path to build
20
- * @param path - Path parameter object used to replace placeholders in the URL (e.g., {id})
21
- * @param query - Query parameter object to be added to the URL query string
22
- * @returns Complete URL string
24
+ * @param url - URL path to build (e.g., '/users/{id}/posts')
25
+ * @param params - URL parameters including path and query parameters
26
+ * @returns Complete URL string with base URL, path parameters interpolated, and query string appended
23
27
  * @throws Error when required path parameters are missing
24
28
  *
25
29
  * @example
26
30
  * ```typescript
27
31
  * const urlBuilder = new UrlBuilder('https://api.example.com');
28
- * const url = urlBuilder.build('/users/{id}/posts/{postId}',
29
- * { id: 123, postId: 456 },
30
- * { filter: 'active', limit: 10 }
31
- * );
32
+ * const url = urlBuilder.build('/users/{id}/posts/{postId}', {
33
+ * path: { id: 123, postId: 456 },
34
+ * query: { filter: 'active', limit: 10 }
35
+ * });
32
36
  * // Result: https://api.example.com/users/123/posts/456?filter=active&limit=10
33
37
  * ```
34
38
  */
35
- build(e, t, s) {
36
- const n = I(this.baseURL, e);
37
- let o = this.interpolateUrl(n, t);
38
- if (s) {
39
- const c = new URLSearchParams(s).toString();
40
- c && (o += "?" + c);
39
+ build(e, t) {
40
+ const s = t?.path, o = t?.query, i = w(this.baseURL, e);
41
+ let n = this.interpolateUrl(i, s);
42
+ if (o) {
43
+ const c = new URLSearchParams(o).toString();
44
+ c && (n += "?" + c);
41
45
  }
42
- return o;
46
+ return n;
47
+ }
48
+ /**
49
+ * Resolves a complete URL from a FetchRequest
50
+ *
51
+ * This method is used internally by the Fetcher to build the final URL for a request
52
+ * by combining the request URL with its URL parameters using this UrlBuilder.
53
+ *
54
+ * @param request - The FetchRequest containing URL and URL parameters
55
+ * @returns Complete resolved URL string
56
+ */
57
+ resolveRequestUrl(e) {
58
+ return this.build(e.url, e.urlParams);
43
59
  }
44
60
  /**
45
61
  * Replaces placeholders in the URL with path parameters
@@ -52,66 +68,74 @@ class w {
52
68
  * @example
53
69
  * ```typescript
54
70
  * const urlBuilder = new UrlBuilder('https://api.example.com');
55
- * const result = urlBuilder.interpolateUrl('/users/{id}/posts/{postId}', { id: 123, postId: 456 });
56
- * // Result: /users/123/posts/456
71
+ * const result = urlBuilder.interpolateUrl('/users/{id}/posts/{postId}', {
72
+ * path: { id: 123, postId: 456 }
73
+ * });
74
+ * // Result: https://api.example.com/users/123/posts/456
75
+ * ```
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * // Missing required parameter throws an error
80
+ * try {
81
+ * urlBuilder.interpolateUrl('/users/{id}', { name: 'John' });
82
+ * } catch (error) {
83
+ * console.error(error.message); // "Missing required path parameter: id"
84
+ * }
57
85
  * ```
58
86
  */
59
87
  interpolateUrl(e, t) {
60
- return t ? e.replace(/{([^}]+)}/g, (s, n) => {
61
- const o = t[n];
62
- if (o === void 0)
63
- throw new Error(`Missing required path parameter: ${n}`);
64
- return String(o);
88
+ return t ? e.replace(/{([^}]+)}/g, (s, o) => {
89
+ const i = t[o];
90
+ if (i === void 0)
91
+ throw new Error(`Missing required path parameter: ${o}`);
92
+ return String(i);
65
93
  }) : e;
66
94
  }
67
95
  }
68
- function A(r, e) {
96
+ function R(r, e) {
69
97
  return typeof r < "u" ? r : e;
70
98
  }
71
- class p extends Error {
99
+ class f extends Error {
72
100
  /**
73
101
  * Creates a new FetchTimeoutError instance
74
102
  *
75
- * @param url - The URL that timed out
76
103
  * @param request - The request options that timed out
77
- * @param timeout - The timeout value in milliseconds
78
104
  */
79
- constructor(e, t, s) {
80
- const n = t.method || "GET", o = `Request timeout of ${s}ms exceeded for ${n} ${e}`;
81
- super(o), this.name = "FetchTimeoutError", this.url = e, this.request = t, this.timeout = s, Object.setPrototypeOf(this, p.prototype);
105
+ constructor(e) {
106
+ const t = e.method || "GET", s = `Request timeout of ${e.timeout}ms exceeded for ${t} ${e.url}`;
107
+ super(s), this.name = "FetchTimeoutError", this.request = e, Object.setPrototypeOf(this, f.prototype);
82
108
  }
83
109
  }
84
- async function F(r, e, t) {
110
+ async function A(r) {
111
+ const e = r.url, t = r.timeout, s = r;
85
112
  if (!t)
86
- return fetch(r, e);
87
- const s = new AbortController(), n = {
88
- ...e,
89
- signal: s.signal
113
+ return fetch(e, s);
114
+ const o = new AbortController(), i = {
115
+ ...s,
116
+ signal: o.signal
90
117
  };
91
- let o = null;
92
- const c = new Promise((y, u) => {
93
- o = setTimeout(() => {
94
- o && clearTimeout(o);
95
- const T = new p(r, e, t);
96
- s.abort(T), u(T);
118
+ let n = null;
119
+ const c = new Promise((v, b) => {
120
+ n = setTimeout(() => {
121
+ n && clearTimeout(n);
122
+ const T = new f(r);
123
+ o.abort(T), b(T);
97
124
  }, t);
98
125
  });
99
126
  try {
100
- return await Promise.race([
101
- fetch(r, n),
102
- c
103
- ]);
127
+ return await Promise.race([fetch(e, i), c]);
104
128
  } finally {
105
- o && clearTimeout(o);
129
+ n && clearTimeout(n);
106
130
  }
107
131
  }
108
- var i = /* @__PURE__ */ ((r) => (r.GET = "GET", r.POST = "POST", r.PUT = "PUT", r.DELETE = "DELETE", r.PATCH = "PATCH", r.HEAD = "HEAD", r.OPTIONS = "OPTIONS", r))(i || {}), N = /* @__PURE__ */ ((r) => (r.METHOD = "method", r.BODY = "body", r))(N || {});
132
+ var u = /* @__PURE__ */ ((r) => (r.GET = "GET", r.POST = "POST", r.PUT = "PUT", r.DELETE = "DELETE", r.PATCH = "PATCH", r.HEAD = "HEAD", r.OPTIONS = "OPTIONS", r))(u || {});
109
133
  const d = "Content-Type";
110
- var f = /* @__PURE__ */ ((r) => (r.APPLICATION_JSON = "application/json", r.TEXT_EVENT_STREAM = "text/event-stream", r))(f || {});
134
+ var y = /* @__PURE__ */ ((r) => (r.APPLICATION_JSON = "application/json", r.TEXT_EVENT_STREAM = "text/event-stream", r))(y || {});
111
135
  function a(r, e) {
112
136
  return e ? r.filter(e).sort((t, s) => t.order - s.order) : [...r].sort((t, s) => t.order - s.order);
113
137
  }
114
- class O {
138
+ class F {
115
139
  constructor() {
116
140
  this.name = "RequestBodyInterceptor", this.order = Number.MIN_SAFE_INTEGER + 200;
117
141
  }
@@ -158,11 +182,11 @@ class O {
158
182
  return e;
159
183
  const s = { ...t };
160
184
  s.body = JSON.stringify(t.body), s.headers || (s.headers = {});
161
- const n = s.headers;
162
- return n[d] || (n[d] = f.APPLICATION_JSON), e.request = s, e;
185
+ const o = s.headers;
186
+ return o[d] || (o[d] = y.APPLICATION_JSON), e.request = s, e;
163
187
  }
164
188
  }
165
- class P {
189
+ class g {
166
190
  constructor() {
167
191
  this.name = "FetchInterceptor", this.order = Number.MAX_SAFE_INTEGER - 100;
168
192
  }
@@ -191,14 +215,10 @@ class P {
191
215
  * console.log(result.response); // HTTP response object
192
216
  */
193
217
  async intercept(e) {
194
- return e.response = await F(
195
- e.url,
196
- e.request,
197
- e.request.timeout
198
- ), e;
218
+ return e.response = await A(e.request), e;
199
219
  }
200
220
  }
201
- class R {
221
+ class N {
202
222
  constructor() {
203
223
  this.name = "UrlResolveInterceptor", this.order = Number.MIN_SAFE_INTEGER + 100;
204
224
  }
@@ -209,11 +229,8 @@ class R {
209
229
  * @returns The modified exchange with the resolved URL
210
230
  */
211
231
  intercept(e) {
212
- return e.url = e.fetcher.urlBuilder.build(
213
- e.url,
214
- e.request.path,
215
- e.request.query
216
- ), e;
232
+ const t = e.request;
233
+ return t.url = e.fetcher.urlBuilder.resolveRequestUrl(t), e;
217
234
  }
218
235
  }
219
236
  class h {
@@ -308,26 +325,30 @@ class h {
308
325
  class S {
309
326
  constructor() {
310
327
  this.request = new h([
311
- new R(),
312
- new O(),
313
- new P()
328
+ new N(),
329
+ new F(),
330
+ new g()
314
331
  ]), this.response = new h(), this.error = new h();
315
332
  }
316
333
  }
317
- const l = {
318
- [d]: f.APPLICATION_JSON
319
- }, b = {
334
+ function l(r, e) {
335
+ if (!(r === void 0 && e === void 0))
336
+ return e === void 0 ? r : r === void 0 ? e : { ...r, ...e };
337
+ }
338
+ const m = {
339
+ [d]: y.APPLICATION_JSON
340
+ }, I = {
320
341
  baseURL: "",
321
- headers: l
342
+ headers: m
322
343
  };
323
- class g {
344
+ class q {
324
345
  /**
325
346
  * Create a Fetcher instance
326
347
  *
327
348
  * @param options - Fetcher configuration options
328
349
  */
329
- constructor(e = b) {
330
- this.headers = l, this.urlBuilder = new w(e.baseURL), this.headers = e.headers ?? l, this.timeout = e.timeout, this.interceptors = e.interceptors ?? new S();
350
+ constructor(e = I) {
351
+ this.headers = m, this.urlBuilder = new P(e.baseURL), this.headers = e.headers ?? m, this.timeout = e.timeout, this.interceptors = e.interceptors ?? new S();
331
352
  }
332
353
  /**
333
354
  * Make an HTTP request
@@ -337,32 +358,29 @@ class g {
337
358
  * @returns Promise<Response> HTTP response
338
359
  */
339
360
  async fetch(e, t = {}) {
340
- const s = await this.request(e, t);
341
- if (!s.response)
361
+ const s = t;
362
+ s.url = e;
363
+ const o = await this.request(s);
364
+ if (!o.response)
342
365
  throw new Error(`Request to ${s.url} failed with no response`);
343
- return s.response;
366
+ return o.response;
344
367
  }
345
368
  /**
346
369
  * Send an HTTP request
347
370
  *
348
- * @param url - Request URL address, supports path parameter placeholders
349
- * @param request - Request configuration object, including method, headers, body, etc.
371
+ * @param request - Request configuration object, including url, method, headers, body, etc.
350
372
  * @returns Promise that resolves to a FetchExchange object containing request and response information
351
373
  *
352
374
  * @throws Throws an exception when an error occurs during the request and is not handled by error interceptors
353
375
  */
354
- async request(e, t = {}) {
355
- const s = {
356
- ...this.headers || {},
357
- ...t.headers || {}
358
- }, n = {
359
- ...t,
360
- headers: Object.keys(s).length > 0 ? s : void 0,
361
- timeout: A(t.timeout, this.timeout)
376
+ async request(e) {
377
+ const t = l(e.headers, this.headers), s = {
378
+ ...e,
379
+ headers: t,
380
+ timeout: R(e.timeout, this.timeout)
362
381
  }, o = {
363
382
  fetcher: this,
364
- url: e,
365
- request: n,
383
+ request: s,
366
384
  response: void 0,
367
385
  error: void 0,
368
386
  attributes: {}
@@ -416,7 +434,7 @@ class g {
416
434
  * @returns Promise<Response> HTTP response
417
435
  */
418
436
  async get(e, t = {}) {
419
- return this.methodFetch(i.GET, e, t);
437
+ return this.methodFetch(u.GET, e, t);
420
438
  }
421
439
  /**
422
440
  * Make a POST request
@@ -426,7 +444,7 @@ class g {
426
444
  * @returns Promise<Response> HTTP response
427
445
  */
428
446
  async post(e, t = {}) {
429
- return this.methodFetch(i.POST, e, t);
447
+ return this.methodFetch(u.POST, e, t);
430
448
  }
431
449
  /**
432
450
  * Make a PUT request
@@ -436,7 +454,7 @@ class g {
436
454
  * @returns Promise<Response> HTTP response
437
455
  */
438
456
  async put(e, t = {}) {
439
- return this.methodFetch(i.PUT, e, t);
457
+ return this.methodFetch(u.PUT, e, t);
440
458
  }
441
459
  /**
442
460
  * Make a DELETE request
@@ -446,7 +464,7 @@ class g {
446
464
  * @returns Promise<Response> HTTP response
447
465
  */
448
466
  async delete(e, t = {}) {
449
- return this.methodFetch(i.DELETE, e, t);
467
+ return this.methodFetch(u.DELETE, e, t);
450
468
  }
451
469
  /**
452
470
  * Make a PATCH request
@@ -456,7 +474,7 @@ class g {
456
474
  * @returns Promise<Response> HTTP response
457
475
  */
458
476
  async patch(e, t = {}) {
459
- return this.methodFetch(i.PATCH, e, t);
477
+ return this.methodFetch(u.PATCH, e, t);
460
478
  }
461
479
  /**
462
480
  * Make a HEAD request
@@ -466,7 +484,7 @@ class g {
466
484
  * @returns Promise<Response> HTTP response
467
485
  */
468
486
  async head(e, t = {}) {
469
- return this.methodFetch(i.HEAD, e, t);
487
+ return this.methodFetch(u.HEAD, e, t);
470
488
  }
471
489
  /**
472
490
  * Make an OPTIONS request
@@ -476,11 +494,11 @@ class g {
476
494
  * @returns Promise<Response> HTTP response
477
495
  */
478
496
  async options(e, t = {}) {
479
- return this.methodFetch(i.OPTIONS, e, t);
497
+ return this.methodFetch(u.OPTIONS, e, t);
480
498
  }
481
499
  }
482
- const m = "default";
483
- class q {
500
+ const p = "default";
501
+ class O {
484
502
  constructor() {
485
503
  this.registrar = /* @__PURE__ */ new Map();
486
504
  }
@@ -553,7 +571,7 @@ class q {
553
571
  * const defaultFetcher = fetcherRegistrar.default;
554
572
  */
555
573
  get default() {
556
- return this.requiredGet(m);
574
+ return this.requiredGet(p);
557
575
  }
558
576
  /**
559
577
  * Set the default Fetcher instance
@@ -564,7 +582,7 @@ class q {
564
582
  * fetcherRegistrar.default = fetcher;
565
583
  */
566
584
  set default(e) {
567
- this.register(m, e);
585
+ this.register(p, e);
568
586
  }
569
587
  /**
570
588
  * Get a copy of all registered fetchers
@@ -580,35 +598,31 @@ class q {
580
598
  return new Map(this.registrar);
581
599
  }
582
600
  }
583
- const _ = new q();
601
+ const U = new O();
584
602
  function L(r, e) {
585
603
  if (Object.keys(r).length === 0)
586
604
  return e;
587
605
  if (Object.keys(e).length === 0)
588
606
  return r;
589
607
  const t = {
590
- ...r.path,
591
- ...e.path
608
+ path: l(r.urlParams?.path, e.urlParams?.path),
609
+ query: l(r.urlParams?.query, e.urlParams?.query)
592
610
  }, s = {
593
- ...r.query,
594
- ...e.query
595
- }, n = {
596
611
  ...r.headers,
597
612
  ...e.headers
598
- }, o = e.method ?? r.method, c = e.body ?? r.body, y = e.timeout ?? r.timeout, u = e.signal ?? r.signal;
613
+ }, o = e.method ?? r.method, i = e.body ?? r.body, n = e.timeout ?? r.timeout, c = e.signal ?? r.signal;
599
614
  return {
600
615
  ...r,
601
616
  ...e,
602
617
  method: o,
603
- path: t,
604
- query: s,
605
- headers: n,
606
- body: c,
607
- timeout: y,
608
- signal: u
618
+ urlParams: t,
619
+ headers: s,
620
+ body: i,
621
+ timeout: n,
622
+ signal: c
609
623
  };
610
624
  }
611
- class U extends g {
625
+ class _ extends q {
612
626
  /**
613
627
  * Create a NamedFetcher instance and automatically register it with the global fetcherRegistrar
614
628
  *
@@ -626,34 +640,34 @@ class U extends g {
626
640
  * headers: { 'Authorization': 'Bearer token' }
627
641
  * });
628
642
  */
629
- constructor(e, t = b) {
630
- super(t), this.name = e, _.register(e, this);
643
+ constructor(e, t = I) {
644
+ super(t), this.name = e, U.register(e, this);
631
645
  }
632
646
  }
633
- const D = new U(m);
647
+ const D = new _(p);
634
648
  export {
635
649
  d as ContentTypeHeader,
636
- f as ContentTypeValues,
637
- m as DEFAULT_FETCHER_NAME,
638
- b as DEFAULT_OPTIONS,
639
- P as FetchInterceptor,
640
- p as FetchTimeoutError,
641
- g as Fetcher,
650
+ y as ContentTypeValues,
651
+ p as DEFAULT_FETCHER_NAME,
652
+ I as DEFAULT_OPTIONS,
653
+ g as FetchInterceptor,
654
+ f as FetchTimeoutError,
655
+ q as Fetcher,
642
656
  S as FetcherInterceptors,
643
- q as FetcherRegistrar,
644
- i as HttpMethod,
657
+ O as FetcherRegistrar,
658
+ u as HttpMethod,
645
659
  h as InterceptorManager,
646
- U as NamedFetcher,
647
- O as RequestBodyInterceptor,
648
- N as RequestField,
649
- w as UrlBuilder,
650
- R as UrlResolveInterceptor,
651
- I as combineURLs,
660
+ _ as NamedFetcher,
661
+ F as RequestBodyInterceptor,
662
+ P as UrlBuilder,
663
+ N as UrlResolveInterceptor,
664
+ w as combineURLs,
652
665
  D as fetcher,
653
- _ as fetcherRegistrar,
666
+ U as fetcherRegistrar,
654
667
  E as isAbsoluteURL,
668
+ l as mergeRecords,
655
669
  L as mergeRequest,
656
- A as resolveTimeout,
657
- F as timeoutFetch,
670
+ R as resolveTimeout,
671
+ A as timeoutFetch,
658
672
  a as toSorted
659
673
  };
package/dist/index.umd.js CHANGED
@@ -1 +1 @@
1
- (function(n,u){typeof exports=="object"&&typeof module<"u"?u(exports):typeof define=="function"&&define.amd?define(["exports"],u):(n=typeof globalThis<"u"?globalThis:n||self,u(n.Fetcher={}))})(this,(function(n){"use strict";function u(r){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(r)}function E(r,e){return u(e)?e:e?r.replace(/\/?\/$/,"")+"/"+e.replace(/^\/+/,""):r}class I{constructor(e){this.baseURL=e}build(e,t,s){const i=E(this.baseURL,e);let o=this.interpolateUrl(i,t);if(s){const a=new URLSearchParams(s).toString();a&&(o+="?"+a)}return o}interpolateUrl(e,t){return t?e.replace(/{([^}]+)}/g,(s,i)=>{const o=t[i];if(o===void 0)throw new Error(`Missing required path parameter: ${i}`);return String(o)}):e}}function F(r,e){return typeof r<"u"?r:e}class h extends Error{constructor(e,t,s){const i=t.method||"GET",o=`Request timeout of ${s}ms exceeded for ${i} ${e}`;super(o),this.name="FetchTimeoutError",this.url=e,this.request=t,this.timeout=s,Object.setPrototypeOf(this,h.prototype)}}async function R(r,e,t){if(!t)return fetch(r,e);const s=new AbortController,i={...e,signal:s.signal};let o=null;const a=new Promise((_,b)=>{o=setTimeout(()=>{o&&clearTimeout(o);const L=new h(r,e,t);s.abort(L),b(L)},t)});try{return await Promise.race([fetch(r,i),a])}finally{o&&clearTimeout(o)}}var c=(r=>(r.GET="GET",r.POST="POST",r.PUT="PUT",r.DELETE="DELETE",r.PATCH="PATCH",r.HEAD="HEAD",r.OPTIONS="OPTIONS",r))(c||{}),w=(r=>(r.METHOD="method",r.BODY="body",r))(w||{});const d="Content-Type";var l=(r=>(r.APPLICATION_JSON="application/json",r.TEXT_EVENT_STREAM="text/event-stream",r))(l||{});function m(r,e){return e?r.filter(e).sort((t,s)=>t.order-s.order):[...r].sort((t,s)=>t.order-s.order)}class A{constructor(){this.name="RequestBodyInterceptor",this.order=Number.MIN_SAFE_INTEGER+200}intercept(e){const t=e.request;if(t.body===void 0||t.body===null||typeof t.body!="object"||t.body instanceof ArrayBuffer||ArrayBuffer.isView(t.body)||t.body instanceof Blob||t.body instanceof File||t.body instanceof URLSearchParams||t.body instanceof FormData||t.body instanceof ReadableStream)return e;const s={...t};s.body=JSON.stringify(t.body),s.headers||(s.headers={});const i=s.headers;return i[d]||(i[d]=l.APPLICATION_JSON),e.request=s,e}}class N{constructor(){this.name="FetchInterceptor",this.order=Number.MAX_SAFE_INTEGER-100}async intercept(e){return e.response=await R(e.url,e.request,e.request.timeout),e}}class O{constructor(){this.name="UrlResolveInterceptor",this.order=Number.MIN_SAFE_INTEGER+100}intercept(e){return e.url=e.fetcher.urlBuilder.build(e.url,e.request.path,e.request.query),e}}class f{constructor(e=[]){this.sortedInterceptors=[],this.sortedInterceptors=m(e)}get name(){return this.constructor.name}get order(){return Number.MIN_SAFE_INTEGER}use(e){return this.sortedInterceptors.some(t=>t.name===e.name)?!1:(this.sortedInterceptors=m([...this.sortedInterceptors,e]),!0)}eject(e){const t=this.sortedInterceptors;return this.sortedInterceptors=m(t,s=>s.name!==e),t.length!==this.sortedInterceptors.length}clear(){this.sortedInterceptors=[]}async intercept(e){let t=e;for(const s of this.sortedInterceptors)t=await s.intercept(t);return t}}class S{constructor(){this.request=new f([new O,new A,new N]),this.response=new f,this.error=new f}}const T={[d]:l.APPLICATION_JSON},p={baseURL:"",headers:T};class g{constructor(e=p){this.headers=T,this.urlBuilder=new I(e.baseURL),this.headers=e.headers??T,this.timeout=e.timeout,this.interceptors=e.interceptors??new S}async fetch(e,t={}){const s=await this.request(e,t);if(!s.response)throw new Error(`Request to ${s.url} failed with no response`);return s.response}async request(e,t={}){const s={...this.headers||{},...t.headers||{}},i={...t,headers:Object.keys(s).length>0?s:void 0,timeout:F(t.timeout,this.timeout)},o={fetcher:this,url:e,request:i,response:void 0,error:void 0,attributes:{}};return this.exchange(o)}async exchange(e){try{return e=await this.interceptors.request.intercept(e),e=await this.interceptors.response.intercept(e),e}catch(t){if(e.error=t,e=await this.interceptors.error.intercept(e),e.response)return e;throw e.error}}async methodFetch(e,t,s={}){return this.fetch(t,{...s,method:e})}async get(e,t={}){return this.methodFetch(c.GET,e,t)}async post(e,t={}){return this.methodFetch(c.POST,e,t)}async put(e,t={}){return this.methodFetch(c.PUT,e,t)}async delete(e,t={}){return this.methodFetch(c.DELETE,e,t)}async patch(e,t={}){return this.methodFetch(c.PATCH,e,t)}async head(e,t={}){return this.methodFetch(c.HEAD,e,t)}async options(e,t={}){return this.methodFetch(c.OPTIONS,e,t)}}const y="default";class P{constructor(){this.registrar=new Map}register(e,t){this.registrar.set(e,t)}unregister(e){return this.registrar.delete(e)}get(e){return this.registrar.get(e)}requiredGet(e){const t=this.get(e);if(!t)throw new Error(`Fetcher ${e} not found`);return t}get default(){return this.requiredGet(y)}set default(e){this.register(y,e)}get fetchers(){return new Map(this.registrar)}}const q=new P;function D(r,e){if(Object.keys(r).length===0)return e;if(Object.keys(e).length===0)return r;const t={...r.path,...e.path},s={...r.query,...e.query},i={...r.headers,...e.headers},o=e.method??r.method,a=e.body??r.body,_=e.timeout??r.timeout,b=e.signal??r.signal;return{...r,...e,method:o,path:t,query:s,headers:i,body:a,timeout:_,signal:b}}class U extends g{constructor(e,t=p){super(t),this.name=e,q.register(e,this)}}const v=new U(y);n.ContentTypeHeader=d,n.ContentTypeValues=l,n.DEFAULT_FETCHER_NAME=y,n.DEFAULT_OPTIONS=p,n.FetchInterceptor=N,n.FetchTimeoutError=h,n.Fetcher=g,n.FetcherInterceptors=S,n.FetcherRegistrar=P,n.HttpMethod=c,n.InterceptorManager=f,n.NamedFetcher=U,n.RequestBodyInterceptor=A,n.RequestField=w,n.UrlBuilder=I,n.UrlResolveInterceptor=O,n.combineURLs=E,n.fetcher=v,n.fetcherRegistrar=q,n.isAbsoluteURL=u,n.mergeRequest=D,n.resolveTimeout=F,n.timeoutFetch=R,n.toSorted=m,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(n,a){typeof exports=="object"&&typeof module<"u"?a(exports):typeof define=="function"&&define.amd?define(["exports"],a):(n=typeof globalThis<"u"?globalThis:n||self,a(n.Fetcher={}))})(this,(function(n){"use strict";function a(r){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(r)}function b(r,e){return a(e)?e:e?r.replace(/\/?\/$/,"")+"/"+e.replace(/^\/+/,""):r}class F{constructor(e){this.baseURL=e}build(e,t){const s=t?.path,o=t?.query,c=b(this.baseURL,e);let i=this.interpolateUrl(c,s);if(o){const h=new URLSearchParams(o).toString();h&&(i+="?"+h)}return i}resolveRequestUrl(e){return this.build(e.url,e.urlParams)}interpolateUrl(e,t){return t?e.replace(/{([^}]+)}/g,(s,o)=>{const c=t[o];if(c===void 0)throw new Error(`Missing required path parameter: ${o}`);return String(c)}):e}}function R(r,e){return typeof r<"u"?r:e}class d extends Error{constructor(e){const t=e.method||"GET",s=`Request timeout of ${e.timeout}ms exceeded for ${t} ${e.url}`;super(s),this.name="FetchTimeoutError",this.request=e,Object.setPrototypeOf(this,d.prototype)}}async function g(r){const e=r.url,t=r.timeout,s=r;if(!t)return fetch(e,s);const o=new AbortController,c={...s,signal:o.signal};let i=null;const h=new Promise((C,D)=>{i=setTimeout(()=>{i&&clearTimeout(i);const _=new d(r);o.abort(_),D(_)},t)});try{return await Promise.race([fetch(e,c),h])}finally{i&&clearTimeout(i)}}var u=(r=>(r.GET="GET",r.POST="POST",r.PUT="PUT",r.DELETE="DELETE",r.PATCH="PATCH",r.HEAD="HEAD",r.OPTIONS="OPTIONS",r))(u||{});const l="Content-Type";var m=(r=>(r.APPLICATION_JSON="application/json",r.TEXT_EVENT_STREAM="text/event-stream",r))(m||{});function f(r,e){return e?r.filter(e).sort((t,s)=>t.order-s.order):[...r].sort((t,s)=>t.order-s.order)}class P{constructor(){this.name="RequestBodyInterceptor",this.order=Number.MIN_SAFE_INTEGER+200}intercept(e){const t=e.request;if(t.body===void 0||t.body===null||typeof t.body!="object"||t.body instanceof ArrayBuffer||ArrayBuffer.isView(t.body)||t.body instanceof Blob||t.body instanceof File||t.body instanceof URLSearchParams||t.body instanceof FormData||t.body instanceof ReadableStream)return e;const s={...t};s.body=JSON.stringify(t.body),s.headers||(s.headers={});const o=s.headers;return o[l]||(o[l]=m.APPLICATION_JSON),e.request=s,e}}class w{constructor(){this.name="FetchInterceptor",this.order=Number.MAX_SAFE_INTEGER-100}async intercept(e){return e.response=await g(e.request),e}}class A{constructor(){this.name="UrlResolveInterceptor",this.order=Number.MIN_SAFE_INTEGER+100}intercept(e){const t=e.request;return t.url=e.fetcher.urlBuilder.resolveRequestUrl(t),e}}class y{constructor(e=[]){this.sortedInterceptors=[],this.sortedInterceptors=f(e)}get name(){return this.constructor.name}get order(){return Number.MIN_SAFE_INTEGER}use(e){return this.sortedInterceptors.some(t=>t.name===e.name)?!1:(this.sortedInterceptors=f([...this.sortedInterceptors,e]),!0)}eject(e){const t=this.sortedInterceptors;return this.sortedInterceptors=f(t,s=>s.name!==e),t.length!==this.sortedInterceptors.length}clear(){this.sortedInterceptors=[]}async intercept(e){let t=e;for(const s of this.sortedInterceptors)t=await s.intercept(t);return t}}class N{constructor(){this.request=new y([new A,new P,new w]),this.response=new y,this.error=new y}}function T(r,e){if(!(r===void 0&&e===void 0))return e===void 0?r:r===void 0?e:{...r,...e}}const I={[l]:m.APPLICATION_JSON},E={baseURL:"",headers:I};class S{constructor(e=E){this.headers=I,this.urlBuilder=new F(e.baseURL),this.headers=e.headers??I,this.timeout=e.timeout,this.interceptors=e.interceptors??new N}async fetch(e,t={}){const s=t;s.url=e;const o=await this.request(s);if(!o.response)throw new Error(`Request to ${s.url} failed with no response`);return o.response}async request(e){const t=T(e.headers,this.headers),s={...e,headers:t,timeout:R(e.timeout,this.timeout)},o={fetcher:this,request:s,response:void 0,error:void 0,attributes:{}};return this.exchange(o)}async exchange(e){try{return e=await this.interceptors.request.intercept(e),e=await this.interceptors.response.intercept(e),e}catch(t){if(e.error=t,e=await this.interceptors.error.intercept(e),e.response)return e;throw e.error}}async methodFetch(e,t,s={}){return this.fetch(t,{...s,method:e})}async get(e,t={}){return this.methodFetch(u.GET,e,t)}async post(e,t={}){return this.methodFetch(u.POST,e,t)}async put(e,t={}){return this.methodFetch(u.PUT,e,t)}async delete(e,t={}){return this.methodFetch(u.DELETE,e,t)}async patch(e,t={}){return this.methodFetch(u.PATCH,e,t)}async head(e,t={}){return this.methodFetch(u.HEAD,e,t)}async options(e,t={}){return this.methodFetch(u.OPTIONS,e,t)}}const p="default";class q{constructor(){this.registrar=new Map}register(e,t){this.registrar.set(e,t)}unregister(e){return this.registrar.delete(e)}get(e){return this.registrar.get(e)}requiredGet(e){const t=this.get(e);if(!t)throw new Error(`Fetcher ${e} not found`);return t}get default(){return this.requiredGet(p)}set default(e){this.register(p,e)}get fetchers(){return new Map(this.registrar)}}const O=new q;function v(r,e){if(Object.keys(r).length===0)return e;if(Object.keys(e).length===0)return r;const t={path:T(r.urlParams?.path,e.urlParams?.path),query:T(r.urlParams?.query,e.urlParams?.query)},s={...r.headers,...e.headers},o=e.method??r.method,c=e.body??r.body,i=e.timeout??r.timeout,h=e.signal??r.signal;return{...r,...e,method:o,urlParams:t,headers:s,body:c,timeout:i,signal:h}}class U extends S{constructor(e,t=E){super(t),this.name=e,O.register(e,this)}}const L=new U(p);n.ContentTypeHeader=l,n.ContentTypeValues=m,n.DEFAULT_FETCHER_NAME=p,n.DEFAULT_OPTIONS=E,n.FetchInterceptor=w,n.FetchTimeoutError=d,n.Fetcher=S,n.FetcherInterceptors=N,n.FetcherRegistrar=q,n.HttpMethod=u,n.InterceptorManager=y,n.NamedFetcher=U,n.RequestBodyInterceptor=P,n.UrlBuilder=F,n.UrlResolveInterceptor=A,n.combineURLs=b,n.fetcher=L,n.fetcherRegistrar=O,n.isAbsoluteURL=a,n.mergeRecords=T,n.mergeRequest=v,n.resolveTimeout=R,n.timeoutFetch=g,n.toSorted=f,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})}));
@@ -1,4 +1,4 @@
1
- import { FetcherRequest } from './fetchExchange';
1
+ import { FetchRequestInit } from './fetchRequest';
2
2
  /**
3
3
  * Merges two FetcherRequest objects into one.
4
4
  *
@@ -15,21 +15,27 @@ import { FetcherRequest } from './fetchExchange';
15
15
  * ```typescript
16
16
  * const request1 = {
17
17
  * method: 'GET',
18
- * path: { id: 1 },
18
+ * urlParams: {
19
+ * path: { id: 1 }
20
+ * },
19
21
  * headers: { 'Content-Type': 'application/json' }
20
22
  * };
21
23
  *
22
24
  * const request2 = {
23
25
  * method: 'POST',
24
- * query: { filter: 'active' },
26
+ * urlParams: {
27
+ * query: { filter: 'active' }
28
+ * },
25
29
  * headers: { 'Authorization': 'Bearer token' }
26
30
  * };
27
31
  *
28
32
  * const merged = mergeRequest(request1, request2);
29
33
  * // Result: {
30
34
  * // method: 'POST',
31
- * // path: { id: 1 },
32
- * // query: { filter: 'active' },
35
+ * // urlParams: {
36
+ * // path: { id: 1 },
37
+ * // query: { filter: 'active' }
38
+ * // },
33
39
  * // headers: {
34
40
  * // 'Content-Type': 'application/json',
35
41
  * // 'Authorization': 'Bearer token'
@@ -37,5 +43,5 @@ import { FetcherRequest } from './fetchExchange';
37
43
  * // }
38
44
  * ```
39
45
  */
40
- export declare function mergeRequest(first: FetcherRequest, second: FetcherRequest): FetcherRequest;
46
+ export declare function mergeRequest(first: FetchRequestInit, second: FetchRequestInit): FetchRequestInit;
41
47
  //# sourceMappingURL=mergeRequest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mergeRequest.d.ts","sourceRoot":"","sources":["../src/mergeRequest.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,cAAc,GACrB,cAAc,CA6ChB"}
1
+ {"version":3,"file":"mergeRequest.d.ts","sourceRoot":"","sources":["../src/mergeRequest.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIlD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,gBAAgB,EACvB,MAAM,EAAE,gBAAgB,GACvB,gBAAgB,CAuClB"}
package/dist/timeout.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { FetchRequest } from './fetchRequest';
1
2
  /**
2
3
  * TimeoutCapable Interface
3
4
  *
@@ -42,26 +43,16 @@ export declare function resolveTimeout(requestTimeout?: number, optionsTimeout?:
42
43
  * ```
43
44
  */
44
45
  export declare class FetchTimeoutError extends Error {
45
- /**
46
- * The URL that timed out
47
- */
48
- url: string;
49
46
  /**
50
47
  * The request options that timed out
51
48
  */
52
- request: RequestInit;
53
- /**
54
- * The timeout value in milliseconds
55
- */
56
- timeout: number;
49
+ request: FetchRequest;
57
50
  /**
58
51
  * Creates a new FetchTimeoutError instance
59
52
  *
60
- * @param url - The URL that timed out
61
53
  * @param request - The request options that timed out
62
- * @param timeout - The timeout value in milliseconds
63
54
  */
64
- constructor(url: string, request: RequestInit, timeout: number);
55
+ constructor(request: FetchRequest);
65
56
  }
66
57
  /**
67
58
  * HTTP request method with timeout control
@@ -70,7 +61,6 @@ export declare class FetchTimeoutError extends Error {
70
61
  * fetch request and timeout Promise simultaneously. When either Promise completes,
71
62
  * it returns the result or throws an exception.
72
63
  *
73
- * @param url - The URL to fetch
74
64
  * @param request - The request initialization options
75
65
  * @param timeout - Optional timeout in milliseconds
76
66
  * @returns Promise<Response> HTTP response Promise
@@ -92,5 +82,5 @@ export declare class FetchTimeoutError extends Error {
92
82
  * const response = await timeoutFetch('https://api.example.com/users', { method: 'GET' });
93
83
  * ```
94
84
  */
95
- export declare function timeoutFetch(url: string, request: RequestInit, timeout?: number): Promise<Response>;
85
+ export declare function timeoutFetch(request: FetchRequest): Promise<Response>;
96
86
  //# sourceMappingURL=timeout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"timeout.d.ts","sourceRoot":"","sources":["../src/timeout.ts"],"names":[],"mappings":"AAaA;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,cAAc,CAAC,EAAE,MAAM,EACvB,cAAc,CAAC,EAAE,MAAM,GACtB,MAAM,GAAG,SAAS,CAKpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,OAAO,EAAE,WAAW,CAAC;IAErB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;;;OAMG;gBACS,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM;CAW/D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,QAAQ,CAAC,CAyCnB"}
1
+ {"version":3,"file":"timeout.d.ts","sourceRoot":"","sources":["../src/timeout.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,cAAc,CAAC,EAAE,MAAM,EACvB,cAAc,CAAC,EAAE,MAAM,GACtB,MAAM,GAAG,SAAS,CAKpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C;;OAEG;IACH,OAAO,EAAE,YAAY,CAAC;IAEtB;;;;OAIG;gBACS,OAAO,EAAE,YAAY;CASlC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAyC3E"}
package/dist/types.d.ts CHANGED
@@ -23,10 +23,6 @@ export declare enum HttpMethod {
23
23
  HEAD = "HEAD",
24
24
  OPTIONS = "OPTIONS"
25
25
  }
26
- export declare enum RequestField {
27
- METHOD = "method",
28
- BODY = "body"
29
- }
30
26
  export declare const ContentTypeHeader = "Content-Type";
31
27
  export declare enum ContentTypeValues {
32
28
  APPLICATION_JSON = "application/json",
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,oBAAY,UAAU;IACpB,GAAG,QAAQ;IACX,IAAI,SAAS;IACb,GAAG,QAAQ;IACX,MAAM,WAAW;IACjB,KAAK,UAAU;IACf,IAAI,SAAS;IACb,OAAO,YAAY;CACpB;AAED,oBAAY,YAAY;IACtB,MAAM,WAAW;IACjB,IAAI,SAAS;CACd;AAED,eAAO,MAAM,iBAAiB,iBAAiB,CAAC;AAEhD,oBAAY,iBAAiB;IAC3B,gBAAgB,qBAAqB;IACrC,iBAAiB,sBAAsB;CACxC;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,QAAQ;QAChB;;;;WAIG;QACH,IAAI,CAAC,CAAC,GAAG,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;KAC7B;CACF"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,oBAAY,UAAU;IACpB,GAAG,QAAQ;IACX,IAAI,SAAS;IACb,GAAG,QAAQ;IACX,MAAM,WAAW;IACjB,KAAK,UAAU;IACf,IAAI,SAAS;IACb,OAAO,YAAY;CACpB;AAGD,eAAO,MAAM,iBAAiB,iBAAiB,CAAC;AAEhD,oBAAY,iBAAiB;IAC3B,gBAAgB,qBAAqB;IACrC,iBAAiB,sBAAsB;CACxC;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,QAAQ;QAChB;;;;WAIG;QACH,IAAI,CAAC,CAAC,GAAG,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;KAC7B;CACF"}
@@ -1,48 +1,96 @@
1
1
  import { BaseURLCapable } from './types';
2
+ import { FetchRequest } from './fetchRequest';
2
3
  /**
3
- * UrlBuilder Class
4
+ * Interface for URL parameters including path and query parameters
5
+ */
6
+ export interface UrlParams {
7
+ /**
8
+ * Path parameter object used to replace placeholders in the URL (e.g., {id})
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // For URL template '/users/{id}/posts/{postId}'
13
+ * const path = { id: 123, postId: 456 };
14
+ * ```
15
+ */
16
+ path?: Record<string, any>;
17
+ /**
18
+ * Query parameter object to be added to the URL query string
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const query = { filter: 'active', page: 1, limit: 10 };
23
+ * // Results in query string: ?filter=active&page=1&limit=10
24
+ * ```
25
+ */
26
+ query?: Record<string, any>;
27
+ }
28
+ /**
29
+ * URL Builder class for constructing complete URLs with path parameters and query parameters
4
30
  *
5
- * URL builder class for constructing complete URLs with path parameters and query parameters.
6
31
  * This class handles URL composition, path parameter interpolation, and query string generation.
32
+ * It combines a base URL with a path, replaces path placeholders with actual values, and appends
33
+ * query parameters to create a complete URL.
7
34
  *
8
35
  * @example
9
36
  * ```typescript
10
37
  * const urlBuilder = new UrlBuilder('https://api.example.com');
11
- * const url = urlBuilder.build('/users/{id}', { id: 123 }, { filter: 'active' });
38
+ * const url = urlBuilder.build('/users/{id}', {
39
+ * urlParams: {
40
+ * path: { id: 123 },
41
+ * query: { filter: 'active' }
42
+ * }
43
+ * });
12
44
  * // Result: https://api.example.com/users/123?filter=active
13
45
  * ```
14
46
  */
15
47
  export declare class UrlBuilder implements BaseURLCapable {
16
48
  /**
17
49
  * Base URL that all constructed URLs will be based on
50
+ *
51
+ * This is typically the root of your API endpoint (e.g., 'https://api.example.com')
18
52
  */
19
53
  baseURL: string;
20
54
  /**
21
55
  * Creates a UrlBuilder instance
22
56
  *
23
57
  * @param baseURL - Base URL that all constructed URLs will be based on
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * const urlBuilder = new UrlBuilder('https://api.example.com');
62
+ * ```
24
63
  */
25
64
  constructor(baseURL: string);
26
65
  /**
27
66
  * Builds a complete URL, including path parameter replacement and query parameter addition
28
67
  *
29
- * @param url - URL path to build
30
- * @param path - Path parameter object used to replace placeholders in the URL (e.g., {id})
31
- * @param query - Query parameter object to be added to the URL query string
32
- * @returns Complete URL string
68
+ * @param url - URL path to build (e.g., '/users/{id}/posts')
69
+ * @param params - URL parameters including path and query parameters
70
+ * @returns Complete URL string with base URL, path parameters interpolated, and query string appended
33
71
  * @throws Error when required path parameters are missing
34
72
  *
35
73
  * @example
36
74
  * ```typescript
37
75
  * const urlBuilder = new UrlBuilder('https://api.example.com');
38
- * const url = urlBuilder.build('/users/{id}/posts/{postId}',
39
- * { id: 123, postId: 456 },
40
- * { filter: 'active', limit: 10 }
41
- * );
76
+ * const url = urlBuilder.build('/users/{id}/posts/{postId}', {
77
+ * path: { id: 123, postId: 456 },
78
+ * query: { filter: 'active', limit: 10 }
79
+ * });
42
80
  * // Result: https://api.example.com/users/123/posts/456?filter=active&limit=10
43
81
  * ```
44
82
  */
45
- build(url: string, path?: Record<string, any>, query?: Record<string, any>): string;
83
+ build(url: string, params?: UrlParams): string;
84
+ /**
85
+ * Resolves a complete URL from a FetchRequest
86
+ *
87
+ * This method is used internally by the Fetcher to build the final URL for a request
88
+ * by combining the request URL with its URL parameters using this UrlBuilder.
89
+ *
90
+ * @param request - The FetchRequest containing URL and URL parameters
91
+ * @returns Complete resolved URL string
92
+ */
93
+ resolveRequestUrl(request: FetchRequest): string;
46
94
  /**
47
95
  * Replaces placeholders in the URL with path parameters
48
96
  *
@@ -54,13 +102,31 @@ export declare class UrlBuilder implements BaseURLCapable {
54
102
  * @example
55
103
  * ```typescript
56
104
  * const urlBuilder = new UrlBuilder('https://api.example.com');
57
- * const result = urlBuilder.interpolateUrl('/users/{id}/posts/{postId}', { id: 123, postId: 456 });
58
- * // Result: /users/123/posts/456
105
+ * const result = urlBuilder.interpolateUrl('/users/{id}/posts/{postId}', {
106
+ * path: { id: 123, postId: 456 }
107
+ * });
108
+ * // Result: https://api.example.com/users/123/posts/456
109
+ * ```
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * // Missing required parameter throws an error
114
+ * try {
115
+ * urlBuilder.interpolateUrl('/users/{id}', { name: 'John' });
116
+ * } catch (error) {
117
+ * console.error(error.message); // "Missing required path parameter: id"
118
+ * }
59
119
  * ```
60
120
  */
61
- interpolateUrl(url: string, path?: Record<string, any>): string;
121
+ interpolateUrl(url: string, path?: Record<string, any> | null): string;
62
122
  }
123
+ /**
124
+ * Interface for objects that have a UrlBuilder capability
125
+ */
63
126
  export interface UrlBuilderCapable {
127
+ /**
128
+ * The UrlBuilder instance
129
+ */
64
130
  urlBuilder: UrlBuilder;
65
131
  }
66
132
  //# sourceMappingURL=urlBuilder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"urlBuilder.d.ts","sourceRoot":"","sources":["../src/urlBuilder.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC;;;;;;;;;;;;GAYG;AACH,qBAAa,UAAW,YAAW,cAAc;IAC/C;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;OAIG;gBACS,OAAO,EAAE,MAAM;IAI3B;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAK,CACH,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC1B,MAAM;IAYT;;;;;;;;;;;;;;OAcG;IACH,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM;CAWhE;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,UAAU,CAAC;CACxB"}
1
+ {"version":3,"file":"urlBuilder.d.ts","sourceRoot":"","sources":["../src/urlBuilder.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE3B;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,UAAW,YAAW,cAAc;IAC/C;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;;;;;;OASG;gBACS,OAAO,EAAE,MAAM;IAI3B;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM;IAc9C;;;;;;;;OAQG;IACH,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM;IAIhD;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,GAAG,MAAM;CAWvE;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,UAAU,EAAE,UAAU,CAAC;CACxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"urlResolveInterceptor.d.ts","sourceRoot":"","sources":["../src/urlResolveInterceptor.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,qBAAsB,YAAW,WAAW;IACvD;;OAEG;IACH,IAAI,SAA2B;IAE/B;;;;;;;;OAQG;IACH,KAAK,SAAiC;IAEtC;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa;CAQlD"}
1
+ {"version":3,"file":"urlResolveInterceptor.d.ts","sourceRoot":"","sources":["../src/urlResolveInterceptor.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,qBAAsB,YAAW,WAAW;IACvD;;OAEG;IACH,IAAI,SAA2B;IAE/B;;;;;;;;OAQG;IACH,KAAK,SAAiC;IAEtC;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa;CAKlD"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Merges two record objects, giving precedence to the second record for overlapping keys.
3
+ *
4
+ * This utility function is used to merge configuration objects where the second object
5
+ * takes precedence over the first when there are conflicting keys.
6
+ *
7
+ * @template V - The type of values in the records
8
+ * @param first - The first record to merge (lower precedence)
9
+ * @param second - The second record to merge (higher precedence)
10
+ * @returns A new merged record, or undefined if both inputs are undefined
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * // Merge two objects
15
+ * const defaults = { timeout: 5000, retries: 3 };
16
+ * const overrides = { timeout: 10000 };
17
+ * const result = mergeRecords(defaults, overrides);
18
+ * // Result: { timeout: 10000, retries: 3 }
19
+ *
20
+ * // Handle undefined values
21
+ * const result2 = mergeRecords(undefined, { timeout: 5000 });
22
+ * // Result: { timeout: 5000 }
23
+ *
24
+ * // Return undefined when both are undefined
25
+ * const result3 = mergeRecords(undefined, undefined);
26
+ * // Result: undefined
27
+ * ```
28
+ */
29
+ export declare function mergeRecords<V>(first?: Record<string, V>, second?: Record<string, V>): Record<string, V> | undefined;
30
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAC5B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EACzB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GACzB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,SAAS,CAkB/B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ahoo-wang/fetcher",
3
- "version": "0.8.3",
3
+ "version": "0.8.5",
4
4
  "description": "Ultra-lightweight (1.9kB) HTTP client with built-in path parameters and Axios-like API",
5
5
  "keywords": [
6
6
  "fetch",