create-request 1.4.3-rc.1 → 1.4.3-rc.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.
- package/README.md +231 -120
- package/dist/library/BaseRequest.d.ts +182 -37
- package/dist/library/BodyRequest.d.ts +56 -10
- package/dist/library/RequestError.d.ts +99 -1
- package/dist/library/ResponseWrapper.d.ts +53 -10
- package/dist/library/apiBuilder.d.ts +0 -2
- package/dist/library/index.cjs +446 -69
- package/dist/library/index.cjs.map +1 -1
- package/dist/library/index.d.ts +23 -1
- package/dist/library/index.esm.js +439 -70
- package/dist/library/index.esm.js.map +1 -1
- package/dist/library/index.esm.min.js +1 -1
- package/dist/library/index.esm.min.js.map +1 -1
- package/dist/library/index.min.cjs +1 -1
- package/dist/library/index.min.cjs.map +1 -1
- package/dist/library/types.d.ts +233 -19
- package/package.json +7 -7
package/dist/library/index.cjs
CHANGED
|
@@ -95,13 +95,50 @@ exports.CacheMode = void 0;
|
|
|
95
95
|
CacheMode["ONLY_IF_CACHED"] = "only-if-cached";
|
|
96
96
|
})(exports.CacheMode || (exports.CacheMode = {}));
|
|
97
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Error class for HTTP request failures.
|
|
100
|
+
* Extends the standard Error class with additional context about the failed request.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* try {
|
|
105
|
+
* await create.get('/api/users').getJson();
|
|
106
|
+
* } catch (error) {
|
|
107
|
+
* console.log(`Request failed: ${error.message}`);
|
|
108
|
+
* console.log(`URL: ${error.url}`);
|
|
109
|
+
* console.log(`Method: ${error.method}`);
|
|
110
|
+
* console.log(`Status: ${error.status}`);
|
|
111
|
+
* console.log(`Is timeout: ${error.isTimeout}`);
|
|
112
|
+
* console.log(`Is aborted: ${error.isAborted}`);
|
|
113
|
+
* }
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
98
116
|
class RequestError extends Error {
|
|
117
|
+
/** HTTP status code if the request received a response (e.g., 404, 500) */
|
|
99
118
|
status;
|
|
119
|
+
/** The Response object if the request received a response before failing */
|
|
100
120
|
response;
|
|
121
|
+
/** The URL that was requested */
|
|
101
122
|
url;
|
|
123
|
+
/** The HTTP method that was used (e.g., 'GET', 'POST') */
|
|
102
124
|
method;
|
|
125
|
+
/** Whether the request failed due to a timeout */
|
|
103
126
|
isTimeout;
|
|
127
|
+
/** Whether the request was aborted (cancelled) */
|
|
104
128
|
isAborted;
|
|
129
|
+
/**
|
|
130
|
+
* Creates a new RequestError instance.
|
|
131
|
+
*
|
|
132
|
+
* @param message - Error message describing what went wrong
|
|
133
|
+
* @param url - The URL that was requested
|
|
134
|
+
* @param method - The HTTP method that was used
|
|
135
|
+
* @param options - Additional error context
|
|
136
|
+
* @param options.status - HTTP status code if available
|
|
137
|
+
* @param options.response - The Response object if available
|
|
138
|
+
* @param options.isTimeout - Whether this was a timeout error
|
|
139
|
+
* @param options.isAborted - Whether the request was aborted
|
|
140
|
+
* @param options.cause - The underlying error that caused this error
|
|
141
|
+
*/
|
|
105
142
|
constructor(message, url, method, options = {}) {
|
|
106
143
|
super(message, { cause: options.cause });
|
|
107
144
|
this.name = "RequestError";
|
|
@@ -119,19 +156,66 @@ class RequestError extends Error {
|
|
|
119
156
|
Object.setPrototypeOf(this, RequestError.prototype);
|
|
120
157
|
}
|
|
121
158
|
/**
|
|
122
|
-
*
|
|
159
|
+
* Creates a RequestError for a timeout failure.
|
|
160
|
+
*
|
|
161
|
+
* @param url - The URL that timed out
|
|
162
|
+
* @param method - The HTTP method that was used
|
|
163
|
+
* @param timeoutMs - The timeout duration in milliseconds
|
|
164
|
+
* @returns A RequestError with `isTimeout` set to `true`
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```typescript
|
|
168
|
+
* throw RequestError.timeout('/api/data', 'GET', 5000);
|
|
169
|
+
* ```
|
|
123
170
|
*/
|
|
124
171
|
static timeout(url, method, timeoutMs) {
|
|
125
172
|
return new RequestError(`Timeout ${timeoutMs}ms`, url, method, {
|
|
126
173
|
isTimeout: true,
|
|
127
174
|
});
|
|
128
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Creates a RequestError from an HTTP error response.
|
|
178
|
+
* Used when the server returns a non-2xx status code.
|
|
179
|
+
*
|
|
180
|
+
* @param response - The Response object from the failed request
|
|
181
|
+
* @param url - The URL that was requested
|
|
182
|
+
* @param method - The HTTP method that was used
|
|
183
|
+
* @returns A RequestError with the status code and response object
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```typescript
|
|
187
|
+
* const response = await fetch('/api/users');
|
|
188
|
+
* if (!response.ok) {
|
|
189
|
+
* throw RequestError.fromResponse(response, '/api/users', 'GET');
|
|
190
|
+
* }
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
129
193
|
static fromResponse(response, url, method) {
|
|
130
194
|
return new RequestError(`HTTP ${response.status}`, url, method, {
|
|
131
195
|
status: response.status,
|
|
132
196
|
response,
|
|
133
197
|
});
|
|
134
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Creates a RequestError from a network-level error.
|
|
201
|
+
* Automatically detects and categorizes common network errors (timeouts, DNS errors, connection errors).
|
|
202
|
+
*
|
|
203
|
+
* @param url - The URL that failed
|
|
204
|
+
* @param method - The HTTP method that was used
|
|
205
|
+
* @param originalError - The original error that occurred (e.g., from fetch)
|
|
206
|
+
* @returns A RequestError with enhanced error message and context
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```typescript
|
|
210
|
+
* try {
|
|
211
|
+
* await fetch('/api/data');
|
|
212
|
+
* } catch (error) {
|
|
213
|
+
* if (error instanceof Error) {
|
|
214
|
+
* throw RequestError.networkError('/api/data', 'GET', error);
|
|
215
|
+
* }
|
|
216
|
+
* }
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
135
219
|
static networkError(url, method, originalError) {
|
|
136
220
|
// Provide more descriptive error messages for common network errors
|
|
137
221
|
let message = originalError.message;
|
|
@@ -189,6 +273,20 @@ class RequestError extends Error {
|
|
|
189
273
|
}
|
|
190
274
|
return error;
|
|
191
275
|
}
|
|
276
|
+
/**
|
|
277
|
+
* Creates a RequestError for an aborted (cancelled) request.
|
|
278
|
+
*
|
|
279
|
+
* @param url - The URL that was aborted
|
|
280
|
+
* @param method - The HTTP method that was used
|
|
281
|
+
* @returns A RequestError with `isAborted` set to `true`
|
|
282
|
+
*
|
|
283
|
+
* @example
|
|
284
|
+
* ```typescript
|
|
285
|
+
* const controller = new AbortController();
|
|
286
|
+
* controller.abort();
|
|
287
|
+
* throw RequestError.abortError('/api/data', 'GET');
|
|
288
|
+
* ```
|
|
289
|
+
*/
|
|
192
290
|
static abortError(url, method) {
|
|
193
291
|
return new RequestError("Aborted", url, method, {
|
|
194
292
|
isAborted: true,
|
|
@@ -197,10 +295,23 @@ class RequestError extends Error {
|
|
|
197
295
|
}
|
|
198
296
|
|
|
199
297
|
/**
|
|
200
|
-
* Wrapper for HTTP responses with methods to transform the response data
|
|
298
|
+
* Wrapper for HTTP responses with methods to transform the response data.
|
|
299
|
+
* Provides convenient methods to parse the response body in different formats.
|
|
300
|
+
* Response bodies are cached after the first read, so you can call multiple methods
|
|
301
|
+
* (e.g., `getJson()` and `getText()`) on the same response.
|
|
302
|
+
*
|
|
303
|
+
* @example
|
|
304
|
+
* ```typescript
|
|
305
|
+
* const response = await create.get('/api/users').getResponse();
|
|
306
|
+
* console.log(response.status); // 200
|
|
307
|
+
* console.log(response.ok); // true
|
|
308
|
+
* const data = await response.getJson();
|
|
309
|
+
* ```
|
|
201
310
|
*/
|
|
202
311
|
class ResponseWrapper {
|
|
312
|
+
/** The URL that was requested (if available) */
|
|
203
313
|
url;
|
|
314
|
+
/** The HTTP method that was used (if available) */
|
|
204
315
|
method;
|
|
205
316
|
response;
|
|
206
317
|
graphQLOptions;
|
|
@@ -219,19 +330,34 @@ class ResponseWrapper {
|
|
|
219
330
|
};
|
|
220
331
|
}
|
|
221
332
|
}
|
|
222
|
-
|
|
333
|
+
/**
|
|
334
|
+
* HTTP status code (e.g., 200, 404, 500)
|
|
335
|
+
*/
|
|
223
336
|
get status() {
|
|
224
337
|
return this.response.status;
|
|
225
338
|
}
|
|
339
|
+
/**
|
|
340
|
+
* HTTP status text (e.g., "OK", "Not Found", "Internal Server Error")
|
|
341
|
+
*/
|
|
226
342
|
get statusText() {
|
|
227
343
|
return this.response.statusText;
|
|
228
344
|
}
|
|
345
|
+
/**
|
|
346
|
+
* Response headers as a Headers object
|
|
347
|
+
*/
|
|
229
348
|
get headers() {
|
|
230
349
|
return this.response.headers;
|
|
231
350
|
}
|
|
351
|
+
/**
|
|
352
|
+
* Whether the response status is in the 200-299 range (successful)
|
|
353
|
+
*/
|
|
232
354
|
get ok() {
|
|
233
355
|
return this.response.ok;
|
|
234
356
|
}
|
|
357
|
+
/**
|
|
358
|
+
* The raw Response object from the fetch API.
|
|
359
|
+
* Use this if you need direct access to the underlying Response.
|
|
360
|
+
*/
|
|
235
361
|
get raw() {
|
|
236
362
|
return this.response;
|
|
237
363
|
}
|
|
@@ -259,7 +385,29 @@ class ResponseWrapper {
|
|
|
259
385
|
if (!Array.isArray(responseData.errors) || responseData.errors.length === 0)
|
|
260
386
|
return;
|
|
261
387
|
const errors = responseData.errors;
|
|
262
|
-
const errorMessages = errors.map(x =>
|
|
388
|
+
const errorMessages = errors.map(x => {
|
|
389
|
+
if (typeof x === "string")
|
|
390
|
+
return x;
|
|
391
|
+
if (x && typeof x === "object" && "message" in x) {
|
|
392
|
+
const message = x.message;
|
|
393
|
+
if (message == null)
|
|
394
|
+
return "Unknown error";
|
|
395
|
+
if (typeof message === "string")
|
|
396
|
+
return message;
|
|
397
|
+
if (typeof message === "object") {
|
|
398
|
+
try {
|
|
399
|
+
return JSON.stringify(message);
|
|
400
|
+
}
|
|
401
|
+
catch {
|
|
402
|
+
return "Unknown error";
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
// For primitives (number, boolean, etc.), safe to convert
|
|
406
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
407
|
+
return String(message);
|
|
408
|
+
}
|
|
409
|
+
return String(x);
|
|
410
|
+
});
|
|
263
411
|
const errorMessage = errorMessages.join(", ");
|
|
264
412
|
throw new RequestError(`GraphQL errors: ${errorMessage}`, this.url || "", this.method || "", {
|
|
265
413
|
status: this.response.status,
|
|
@@ -309,13 +457,17 @@ class ResponseWrapper {
|
|
|
309
457
|
}
|
|
310
458
|
}
|
|
311
459
|
/**
|
|
312
|
-
* Get the response body as text
|
|
460
|
+
* Get the response body as text.
|
|
461
|
+
* The result is cached, so subsequent calls return the same value without re-reading the body.
|
|
313
462
|
*
|
|
314
|
-
* @returns
|
|
315
|
-
* @throws {RequestError} When reading fails
|
|
463
|
+
* @returns A promise that resolves to the response body as a string
|
|
464
|
+
* @throws {RequestError} When the body has already been consumed or reading fails
|
|
316
465
|
*
|
|
317
466
|
* @example
|
|
467
|
+
* ```typescript
|
|
318
468
|
* const text = await response.getText();
|
|
469
|
+
* console.log(text); // "Hello, world!"
|
|
470
|
+
* ```
|
|
319
471
|
*/
|
|
320
472
|
async getText() {
|
|
321
473
|
if (this.cachedText !== undefined)
|
|
@@ -335,14 +487,19 @@ class ResponseWrapper {
|
|
|
335
487
|
}
|
|
336
488
|
}
|
|
337
489
|
/**
|
|
338
|
-
* Get the response body as a Blob
|
|
490
|
+
* Get the response body as a Blob.
|
|
491
|
+
* Useful for downloading files or handling binary data.
|
|
492
|
+
* The result is cached, so subsequent calls return the same value without re-reading the body.
|
|
339
493
|
*
|
|
340
|
-
* @returns
|
|
341
|
-
* @throws {RequestError} When reading fails
|
|
494
|
+
* @returns A promise that resolves to the response body as a Blob
|
|
495
|
+
* @throws {RequestError} When the body has already been consumed or reading fails
|
|
342
496
|
*
|
|
343
497
|
* @example
|
|
498
|
+
* ```typescript
|
|
344
499
|
* const blob = await response.getBlob();
|
|
345
500
|
* const url = URL.createObjectURL(blob);
|
|
501
|
+
* // Use the blob URL for downloading or displaying
|
|
502
|
+
* ```
|
|
346
503
|
*/
|
|
347
504
|
async getBlob() {
|
|
348
505
|
if (this.cachedBlob !== undefined)
|
|
@@ -362,14 +519,19 @@ class ResponseWrapper {
|
|
|
362
519
|
}
|
|
363
520
|
}
|
|
364
521
|
/**
|
|
365
|
-
* Get the response body as an ArrayBuffer
|
|
522
|
+
* Get the response body as an ArrayBuffer.
|
|
523
|
+
* Useful for processing binary data at a low level.
|
|
524
|
+
* The result is cached, so subsequent calls return the same value without re-reading the body.
|
|
366
525
|
*
|
|
367
|
-
* @returns
|
|
368
|
-
* @throws {RequestError} When reading fails
|
|
526
|
+
* @returns A promise that resolves to the response body as an ArrayBuffer
|
|
527
|
+
* @throws {RequestError} When the body has already been consumed or reading fails
|
|
369
528
|
*
|
|
370
529
|
* @example
|
|
530
|
+
* ```typescript
|
|
371
531
|
* const buffer = await response.getArrayBuffer();
|
|
372
532
|
* const uint8Array = new Uint8Array(buffer);
|
|
533
|
+
* // Process the binary data
|
|
534
|
+
* ```
|
|
373
535
|
*/
|
|
374
536
|
async getArrayBuffer() {
|
|
375
537
|
if (this.cachedArrayBuffer !== undefined) {
|
|
@@ -1321,9 +1483,34 @@ class BaseRequest {
|
|
|
1321
1483
|
return this.createFluentSetter("cache", cacheOptions);
|
|
1322
1484
|
}
|
|
1323
1485
|
/**
|
|
1324
|
-
* Adds query parameters to the request URL
|
|
1325
|
-
*
|
|
1326
|
-
*
|
|
1486
|
+
* Adds query parameters to the request URL.
|
|
1487
|
+
* Multiple calls will append parameters. Array values will create multiple query parameters with the same key.
|
|
1488
|
+
* Null and undefined values are ignored.
|
|
1489
|
+
*
|
|
1490
|
+
* @param params - An object containing query parameter key-value pairs.
|
|
1491
|
+
* Values can be strings, numbers, booleans, arrays (for multiple values), or null/undefined (ignored).
|
|
1492
|
+
* @returns The request instance for chaining
|
|
1493
|
+
*
|
|
1494
|
+
* @example
|
|
1495
|
+
* ```typescript
|
|
1496
|
+
* // Simple parameters
|
|
1497
|
+
* request.withQueryParams({ page: 1, limit: 10, active: true });
|
|
1498
|
+
* // Results in: ?page=1&limit=10&active=true
|
|
1499
|
+
* ```
|
|
1500
|
+
*
|
|
1501
|
+
* @example
|
|
1502
|
+
* ```typescript
|
|
1503
|
+
* // Array values create multiple parameters
|
|
1504
|
+
* request.withQueryParams({ tags: ['js', 'ts', 'node'] });
|
|
1505
|
+
* // Results in: ?tags=js&tags=ts&tags=node
|
|
1506
|
+
* ```
|
|
1507
|
+
*
|
|
1508
|
+
* @example
|
|
1509
|
+
* ```typescript
|
|
1510
|
+
* // Null/undefined values are ignored
|
|
1511
|
+
* request.withQueryParams({ page: 1, filter: null, sort: undefined });
|
|
1512
|
+
* // Results in: ?page=1
|
|
1513
|
+
* ```
|
|
1327
1514
|
*/
|
|
1328
1515
|
withQueryParams(params) {
|
|
1329
1516
|
Object.entries(params).forEach(([key, value]) => {
|
|
@@ -1341,10 +1528,25 @@ class BaseRequest {
|
|
|
1341
1528
|
return this;
|
|
1342
1529
|
}
|
|
1343
1530
|
/**
|
|
1344
|
-
* Adds a single query parameter
|
|
1345
|
-
*
|
|
1346
|
-
*
|
|
1347
|
-
* @
|
|
1531
|
+
* Adds a single query parameter to the request URL.
|
|
1532
|
+
* Convenience method for adding one parameter at a time.
|
|
1533
|
+
*
|
|
1534
|
+
* @param key - The query parameter name
|
|
1535
|
+
* @param value - The query parameter value. Can be a string, number, boolean, array (for multiple values), or null/undefined (ignored).
|
|
1536
|
+
* @returns The request instance for chaining
|
|
1537
|
+
*
|
|
1538
|
+
* @example
|
|
1539
|
+
* ```typescript
|
|
1540
|
+
* request.withQueryParam('page', 1).withQueryParam('limit', 10);
|
|
1541
|
+
* // Results in: ?page=1&limit=10
|
|
1542
|
+
* ```
|
|
1543
|
+
*
|
|
1544
|
+
* @example
|
|
1545
|
+
* ```typescript
|
|
1546
|
+
* // Array values create multiple parameters
|
|
1547
|
+
* request.withQueryParam('tags', ['js', 'ts']);
|
|
1548
|
+
* // Results in: ?tags=js&tags=ts
|
|
1549
|
+
* ```
|
|
1348
1550
|
*/
|
|
1349
1551
|
withQueryParam(key, value) {
|
|
1350
1552
|
return this.withQueryParams({ [key]: value });
|
|
@@ -1386,26 +1588,59 @@ class BaseRequest {
|
|
|
1386
1588
|
});
|
|
1387
1589
|
}
|
|
1388
1590
|
/**
|
|
1389
|
-
*
|
|
1390
|
-
*
|
|
1391
|
-
*
|
|
1591
|
+
* Sets the Content-Type header for the request.
|
|
1592
|
+
* Shorthand for `withHeader('Content-Type', contentType)`.
|
|
1593
|
+
*
|
|
1594
|
+
* @param contentType - The MIME type (e.g., `'application/json'`, `'text/plain'`, `'multipart/form-data'`)
|
|
1595
|
+
* @returns The request instance for chaining
|
|
1596
|
+
*
|
|
1597
|
+
* @example
|
|
1598
|
+
* ```typescript
|
|
1599
|
+
* request.withContentType('application/json');
|
|
1600
|
+
* ```
|
|
1601
|
+
*
|
|
1602
|
+
* @example
|
|
1603
|
+
* ```typescript
|
|
1604
|
+
* request.withContentType('application/xml');
|
|
1605
|
+
* ```
|
|
1392
1606
|
*/
|
|
1393
1607
|
withContentType(contentType) {
|
|
1394
1608
|
return this.withHeader("Content-Type", contentType);
|
|
1395
1609
|
}
|
|
1396
1610
|
/**
|
|
1397
|
-
*
|
|
1398
|
-
*
|
|
1399
|
-
*
|
|
1611
|
+
* Sets the Authorization header for the request.
|
|
1612
|
+
* Shorthand for `withHeader('Authorization', authValue)`.
|
|
1613
|
+
* For Bearer tokens, use `withBearerToken()` instead. For Basic auth, use `withBasicAuth()`.
|
|
1614
|
+
*
|
|
1615
|
+
* @param authValue - The full authorization header value (e.g., `'Bearer token123'`, `'Basic base64string'`)
|
|
1616
|
+
* @returns The request instance for chaining
|
|
1617
|
+
*
|
|
1618
|
+
* @example
|
|
1619
|
+
* ```typescript
|
|
1620
|
+
* request.withAuthorization('Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...');
|
|
1621
|
+
* ```
|
|
1622
|
+
*
|
|
1623
|
+
* @example
|
|
1624
|
+
* ```typescript
|
|
1625
|
+
* request.withAuthorization('CustomScheme customToken');
|
|
1626
|
+
* ```
|
|
1400
1627
|
*/
|
|
1401
1628
|
withAuthorization(authValue) {
|
|
1402
1629
|
return this.withHeader("Authorization", authValue);
|
|
1403
1630
|
}
|
|
1404
1631
|
/**
|
|
1405
|
-
*
|
|
1406
|
-
*
|
|
1407
|
-
*
|
|
1408
|
-
* @
|
|
1632
|
+
* Sets up HTTP Basic Authentication.
|
|
1633
|
+
* Encodes the username and password in base64 and sets the Authorization header.
|
|
1634
|
+
*
|
|
1635
|
+
* @param username - The username for Basic authentication
|
|
1636
|
+
* @param password - The password for Basic authentication
|
|
1637
|
+
* @returns The request instance for chaining
|
|
1638
|
+
*
|
|
1639
|
+
* @example
|
|
1640
|
+
* ```typescript
|
|
1641
|
+
* request.withBasicAuth('myuser', 'mypassword');
|
|
1642
|
+
* // Sets: Authorization: Basic bXl1c2VyOm15cGFzc3dvcmQ=
|
|
1643
|
+
* ```
|
|
1409
1644
|
*/
|
|
1410
1645
|
withBasicAuth(username, password) {
|
|
1411
1646
|
const credentials = this.encodeBase64(`${username}:${password}`);
|
|
@@ -1432,9 +1667,17 @@ class BaseRequest {
|
|
|
1432
1667
|
throw new RequestError("Encoding not supported", this.url, this.method);
|
|
1433
1668
|
}
|
|
1434
1669
|
/**
|
|
1435
|
-
* Sets
|
|
1436
|
-
*
|
|
1437
|
-
*
|
|
1670
|
+
* Sets a Bearer token for authentication.
|
|
1671
|
+
* Shorthand for `withAuthorization('Bearer ' + token)`.
|
|
1672
|
+
*
|
|
1673
|
+
* @param token - The Bearer token (JWT, OAuth token, etc.)
|
|
1674
|
+
* @returns The request instance for chaining
|
|
1675
|
+
*
|
|
1676
|
+
* @example
|
|
1677
|
+
* ```typescript
|
|
1678
|
+
* request.withBearerToken('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...');
|
|
1679
|
+
* // Sets: Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
|
1680
|
+
* ```
|
|
1438
1681
|
*/
|
|
1439
1682
|
withBearerToken(token) {
|
|
1440
1683
|
return this.withAuthorization(`Bearer ${token}`);
|
|
@@ -1459,9 +1702,29 @@ class BaseRequest {
|
|
|
1459
1702
|
return Object.keys(headers).some(key => key.toLowerCase() === headerName.toLowerCase());
|
|
1460
1703
|
}
|
|
1461
1704
|
/**
|
|
1462
|
-
* Sets cookies for the request
|
|
1463
|
-
*
|
|
1464
|
-
*
|
|
1705
|
+
* Sets cookies for the request.
|
|
1706
|
+
* Cookies are sent in the Cookie header. Multiple calls will merge cookies.
|
|
1707
|
+
* Cookie values can be simple strings or objects with additional cookie options.
|
|
1708
|
+
*
|
|
1709
|
+
* @param cookies - An object where keys are cookie names and values are either:
|
|
1710
|
+
* - A string (the cookie value)
|
|
1711
|
+
* - A CookieOptions object with `value` and optional properties (secure, httpOnly, sameSite, expires, path, domain, maxAge)
|
|
1712
|
+
* @returns The request instance for chaining
|
|
1713
|
+
*
|
|
1714
|
+
* @example
|
|
1715
|
+
* ```typescript
|
|
1716
|
+
* // Simple string cookies
|
|
1717
|
+
* request.withCookies({ sessionId: 'abc123', userId: '456' });
|
|
1718
|
+
* ```
|
|
1719
|
+
*
|
|
1720
|
+
* @example
|
|
1721
|
+
* ```typescript
|
|
1722
|
+
* // Cookies with options (note: options are for documentation only in request cookies)
|
|
1723
|
+
* request.withCookies({
|
|
1724
|
+
* sessionId: 'abc123',
|
|
1725
|
+
* token: { value: 'xyz789', secure: true }
|
|
1726
|
+
* });
|
|
1727
|
+
* ```
|
|
1465
1728
|
*/
|
|
1466
1729
|
withCookies(cookies) {
|
|
1467
1730
|
const cookieEntries = Object.entries(cookies || {});
|
|
@@ -1499,19 +1762,45 @@ class BaseRequest {
|
|
|
1499
1762
|
return this;
|
|
1500
1763
|
}
|
|
1501
1764
|
/**
|
|
1502
|
-
*
|
|
1503
|
-
*
|
|
1504
|
-
*
|
|
1505
|
-
* @
|
|
1765
|
+
* Sets a single cookie for the request.
|
|
1766
|
+
* Convenience method for adding one cookie at a time.
|
|
1767
|
+
*
|
|
1768
|
+
* @param name - The cookie name
|
|
1769
|
+
* @param value - The cookie value as a string, or a CookieOptions object with `value` and optional properties
|
|
1770
|
+
* @returns The request instance for chaining
|
|
1771
|
+
*
|
|
1772
|
+
* @example
|
|
1773
|
+
* ```typescript
|
|
1774
|
+
* request.withCookie('sessionId', 'abc123');
|
|
1775
|
+
* ```
|
|
1776
|
+
*
|
|
1777
|
+
* @example
|
|
1778
|
+
* ```typescript
|
|
1779
|
+
* request.withCookie('token', { value: 'xyz789', secure: true });
|
|
1780
|
+
* ```
|
|
1506
1781
|
*/
|
|
1507
1782
|
withCookie(name, value) {
|
|
1508
1783
|
return this.withCookies({ [name]: value });
|
|
1509
1784
|
}
|
|
1510
1785
|
/**
|
|
1511
|
-
* Sets a CSRF token in the request headers
|
|
1512
|
-
*
|
|
1513
|
-
*
|
|
1514
|
-
* @
|
|
1786
|
+
* Sets a CSRF (Cross-Site Request Forgery) token in the request headers.
|
|
1787
|
+
* This is commonly used to protect against CSRF attacks in web applications.
|
|
1788
|
+
*
|
|
1789
|
+
* @param token - The CSRF token value
|
|
1790
|
+
* @param headerName - The name of the header to use. Defaults to `'X-CSRF-Token'`.
|
|
1791
|
+
* @returns The request instance for chaining
|
|
1792
|
+
*
|
|
1793
|
+
* @example
|
|
1794
|
+
* ```typescript
|
|
1795
|
+
* request.withCsrfToken('csrf-token-123');
|
|
1796
|
+
* // Sets: X-CSRF-Token: csrf-token-123
|
|
1797
|
+
* ```
|
|
1798
|
+
*
|
|
1799
|
+
* @example
|
|
1800
|
+
* ```typescript
|
|
1801
|
+
* request.withCsrfToken('token', 'X-Custom-CSRF-Header');
|
|
1802
|
+
* // Sets: X-Custom-CSRF-Header: token
|
|
1803
|
+
* ```
|
|
1515
1804
|
*/
|
|
1516
1805
|
withCsrfToken(token, headerName = "X-CSRF-Token") {
|
|
1517
1806
|
return this.withHeader(headerName, token);
|
|
@@ -1626,36 +1915,54 @@ class BaseRequest {
|
|
|
1626
1915
|
return response.getJson();
|
|
1627
1916
|
}
|
|
1628
1917
|
/**
|
|
1629
|
-
* Execute the request and get the response as text
|
|
1918
|
+
* Execute the request and get the response body as text.
|
|
1630
1919
|
*
|
|
1631
|
-
* @returns A promise that resolves to the response
|
|
1920
|
+
* @returns A promise that resolves to the response body as a string
|
|
1921
|
+
* @throws {RequestError} When the request fails or reading the response fails
|
|
1632
1922
|
*
|
|
1633
1923
|
* @example
|
|
1924
|
+
* ```typescript
|
|
1634
1925
|
* const text = await request.getText();
|
|
1926
|
+
* console.log(text); // "Hello, world!"
|
|
1927
|
+
* ```
|
|
1635
1928
|
*/
|
|
1636
1929
|
async getText() {
|
|
1637
1930
|
const response = await this.getResponse();
|
|
1638
1931
|
return response.getText();
|
|
1639
1932
|
}
|
|
1640
1933
|
/**
|
|
1641
|
-
* Execute the request and get the response as a Blob
|
|
1934
|
+
* Execute the request and get the response body as a Blob.
|
|
1935
|
+
* Useful for downloading files or handling binary data.
|
|
1642
1936
|
*
|
|
1643
|
-
* @returns A promise that resolves to the response Blob
|
|
1937
|
+
* @returns A promise that resolves to the response body as a Blob
|
|
1938
|
+
* @throws {RequestError} When the request fails or reading the response fails
|
|
1644
1939
|
*
|
|
1645
1940
|
* @example
|
|
1941
|
+
* ```typescript
|
|
1646
1942
|
* const blob = await request.getBlob();
|
|
1943
|
+
* const url = URL.createObjectURL(blob);
|
|
1944
|
+
* // Use the blob URL (e.g., for downloading or displaying)
|
|
1945
|
+
* ```
|
|
1647
1946
|
*/
|
|
1648
1947
|
async getBlob() {
|
|
1649
1948
|
const response = await this.getResponse();
|
|
1650
1949
|
return response.getBlob();
|
|
1651
1950
|
}
|
|
1652
1951
|
/**
|
|
1653
|
-
* Execute the request and get the response body as a ReadableStream
|
|
1952
|
+
* Execute the request and get the response body as a ReadableStream.
|
|
1953
|
+
* Note: Unlike other methods, streams cannot be cached. The body can only be consumed once.
|
|
1654
1954
|
*
|
|
1655
|
-
* @returns A promise that resolves to the response body
|
|
1955
|
+
* @returns A promise that resolves to the response body as a ReadableStream, or `null` if the body is not available
|
|
1956
|
+
* @throws {RequestError} When the request fails or the body has already been consumed
|
|
1656
1957
|
*
|
|
1657
1958
|
* @example
|
|
1959
|
+
* ```typescript
|
|
1658
1960
|
* const stream = await request.getBody();
|
|
1961
|
+
* if (stream) {
|
|
1962
|
+
* const reader = stream.getReader();
|
|
1963
|
+
* // Process the stream chunk by chunk
|
|
1964
|
+
* }
|
|
1965
|
+
* ```
|
|
1659
1966
|
*/
|
|
1660
1967
|
async getBody() {
|
|
1661
1968
|
const response = await this.getResponse();
|
|
@@ -1741,7 +2048,7 @@ class BaseRequest {
|
|
|
1741
2048
|
});
|
|
1742
2049
|
return urlObj.toString();
|
|
1743
2050
|
}
|
|
1744
|
-
catch (
|
|
2051
|
+
catch (_error) {
|
|
1745
2052
|
// Handle relative URLs
|
|
1746
2053
|
const hasExistingParams = url.includes("?");
|
|
1747
2054
|
const separator = hasExistingParams ? "&" : "?";
|
|
@@ -1871,17 +2178,13 @@ class BaseRequest {
|
|
|
1871
2178
|
response: currentError.response,
|
|
1872
2179
|
});
|
|
1873
2180
|
}
|
|
1874
|
-
else if (currentError instanceof ResponseWrapper && currentError.url && currentError.method) {
|
|
1875
|
-
// If it's a ResponseWrapper, we can still create a proper RequestError from its context
|
|
1876
|
-
currentError = new RequestError(`Err Interceptor ${i + 1} failed: ${errorMessage}`, currentError.url, currentError.method, {
|
|
1877
|
-
status: currentError.status,
|
|
1878
|
-
});
|
|
1879
|
-
}
|
|
1880
2181
|
else {
|
|
2182
|
+
/* c8 ignore start */
|
|
1881
2183
|
// Last resort: if we have no context at all, use the original error's context
|
|
1882
2184
|
// This shouldn't happen in practice, but handle it gracefully
|
|
1883
2185
|
const errorObj = interceptorError instanceof Error ? interceptorError : new Error(String(interceptorError));
|
|
1884
2186
|
currentError = RequestError.networkError(error.url, error.method, errorObj);
|
|
2187
|
+
/* c8 ignore end */
|
|
1885
2188
|
}
|
|
1886
2189
|
}
|
|
1887
2190
|
}
|
|
@@ -2089,8 +2392,39 @@ class BodyRequest extends BaseRequest {
|
|
|
2089
2392
|
super(url);
|
|
2090
2393
|
}
|
|
2091
2394
|
/**
|
|
2092
|
-
* Sets the body
|
|
2093
|
-
*
|
|
2395
|
+
* Sets the request body. Automatically detects the body type and sets appropriate Content-Type header.
|
|
2396
|
+
* Supports JSON objects/arrays, strings, FormData, Blob, ArrayBuffer, URLSearchParams, and ReadableStream.
|
|
2397
|
+
*
|
|
2398
|
+
* @param body - The request body. Can be:
|
|
2399
|
+
* - A JSON-serializable object or array (automatically stringified)
|
|
2400
|
+
* - A string (sets Content-Type to `text/plain` if not already set)
|
|
2401
|
+
* - FormData, Blob, File, ArrayBuffer, TypedArray, URLSearchParams, or ReadableStream
|
|
2402
|
+
* @returns The request instance for chaining
|
|
2403
|
+
* @throws {RequestError} If the body is a JSON object that cannot be stringified
|
|
2404
|
+
*
|
|
2405
|
+
* @example
|
|
2406
|
+
* ```typescript
|
|
2407
|
+
* // JSON object (automatically stringified)
|
|
2408
|
+
* request.withBody({ name: 'John', age: 30 });
|
|
2409
|
+
*
|
|
2410
|
+
* @example
|
|
2411
|
+
* // JSON array
|
|
2412
|
+
* request.withBody([1, 2, 3]);
|
|
2413
|
+
*
|
|
2414
|
+
* @example
|
|
2415
|
+
* // String
|
|
2416
|
+
* request.withBody('plain text');
|
|
2417
|
+
*
|
|
2418
|
+
* @example
|
|
2419
|
+
* // FormData
|
|
2420
|
+
* const formData = new FormData();
|
|
2421
|
+
* formData.append('file', fileBlob);
|
|
2422
|
+
* request.withBody(formData);
|
|
2423
|
+
*
|
|
2424
|
+
* @example
|
|
2425
|
+
* // Blob
|
|
2426
|
+
* request.withBody(new Blob(['content'], { type: 'text/plain' }));
|
|
2427
|
+
* ```
|
|
2094
2428
|
*/
|
|
2095
2429
|
withBody(body) {
|
|
2096
2430
|
this.body = body;
|
|
@@ -2125,26 +2459,41 @@ class BodyRequest extends BaseRequest {
|
|
|
2125
2459
|
return this;
|
|
2126
2460
|
}
|
|
2127
2461
|
/**
|
|
2128
|
-
* Sets a GraphQL query or mutation as the request body
|
|
2129
|
-
* Automatically formats the body as JSON and sets Content-Type to application/json
|
|
2462
|
+
* Sets a GraphQL query or mutation as the request body.
|
|
2463
|
+
* Automatically formats the body as JSON and sets Content-Type to `application/json`.
|
|
2464
|
+
* If `throwOnError` is enabled in options, the response will be checked for GraphQL errors
|
|
2465
|
+
* and a RequestError will be thrown if any are found.
|
|
2130
2466
|
*
|
|
2131
|
-
* @param query - The GraphQL query or mutation string
|
|
2132
|
-
* @param variables - Optional variables object to pass with the query
|
|
2467
|
+
* @param query - The GraphQL query or mutation string (e.g., `'query { user { id } }'`)
|
|
2468
|
+
* @param variables - Optional variables object to pass with the query. Must be a plain object.
|
|
2133
2469
|
* @param options - Optional GraphQL-specific options
|
|
2470
|
+
* @param options.throwOnError - If `true`, throws a RequestError when the GraphQL response contains errors
|
|
2134
2471
|
* @returns The request instance for chaining
|
|
2472
|
+
* @throws {RequestError} If the query is empty, variables is invalid, or JSON stringification fails
|
|
2135
2473
|
*
|
|
2136
2474
|
* @example
|
|
2137
|
-
*
|
|
2475
|
+
* ```typescript
|
|
2476
|
+
* // Simple query with variables
|
|
2477
|
+
* const request = create.post('/graphql')
|
|
2138
2478
|
* .withGraphQL('query { user(id: $id) { name email } }', { id: '123' });
|
|
2479
|
+
* const data = await request.getJson();
|
|
2480
|
+
* ```
|
|
2139
2481
|
*
|
|
2140
2482
|
* @example
|
|
2141
|
-
*
|
|
2483
|
+
* ```typescript
|
|
2484
|
+
* // Mutation with variables
|
|
2485
|
+
* const request = create.post('/graphql')
|
|
2142
2486
|
* .withGraphQL('mutation { createUser(name: $name) { id } }', { name: 'John' });
|
|
2487
|
+
* ```
|
|
2143
2488
|
*
|
|
2144
2489
|
* @example
|
|
2145
|
-
*
|
|
2146
|
-
*
|
|
2490
|
+
* ```typescript
|
|
2491
|
+
* // Throw error if GraphQL response contains errors
|
|
2492
|
+
* const request = create.post('/graphql')
|
|
2147
2493
|
* .withGraphQL('query { user { id } }', undefined, { throwOnError: true });
|
|
2494
|
+
* // If the response has errors, this will throw a RequestError
|
|
2495
|
+
* const data = await request.getJson();
|
|
2496
|
+
* ```
|
|
2148
2497
|
*/
|
|
2149
2498
|
withGraphQL(query, variables, options) {
|
|
2150
2499
|
if (typeof query !== "string" || query.length === 0) {
|
|
@@ -2659,7 +3008,7 @@ class ApiBuilder {
|
|
|
2659
3008
|
return propertyValue;
|
|
2660
3009
|
}
|
|
2661
3010
|
if (typeof prop === "string" && prop.startsWith("with") && prop !== "withBaseURL") {
|
|
2662
|
-
if (prop === "withAbortController" || prop === "withBody" || prop === "withGraphQL")
|
|
3011
|
+
if (prop === "withAbortController" || prop === "withBody" || prop === "withGraphQL" || prop === "withQueryParam" || prop === "withQueryParams")
|
|
2663
3012
|
return undefined;
|
|
2664
3013
|
const prototypeMethod = BaseRequest.prototype[prop];
|
|
2665
3014
|
if (typeof prototypeMethod === "function") {
|
|
@@ -2700,8 +3049,28 @@ function api() {
|
|
|
2700
3049
|
}
|
|
2701
3050
|
|
|
2702
3051
|
/**
|
|
2703
|
-
* Main API object for creating HTTP requests
|
|
3052
|
+
* Main API object for creating HTTP requests.
|
|
2704
3053
|
* Provides factory methods for all HTTP methods and access to global configuration.
|
|
3054
|
+
*
|
|
3055
|
+
* @example
|
|
3056
|
+
* ```typescript
|
|
3057
|
+
* import create from 'create-request';
|
|
3058
|
+
*
|
|
3059
|
+
* // Simple GET request
|
|
3060
|
+
* const users = await create.get('/api/users').getJson();
|
|
3061
|
+
*
|
|
3062
|
+
* // POST request with body
|
|
3063
|
+
* const newUser = await create.post('/api/users')
|
|
3064
|
+
* .withJson({ name: 'John', email: 'john@example.com' })
|
|
3065
|
+
* .getJson();
|
|
3066
|
+
*
|
|
3067
|
+
* // Configure API instance with defaults
|
|
3068
|
+
* const api = create.api()
|
|
3069
|
+
* .withBaseURL('https://api.example.com')
|
|
3070
|
+
* .withBearerToken('token123');
|
|
3071
|
+
*
|
|
3072
|
+
* const data = await api.get('/users').getJson();
|
|
3073
|
+
* ```
|
|
2705
3074
|
*/
|
|
2706
3075
|
const create = {
|
|
2707
3076
|
api,
|
|
@@ -2725,5 +3094,13 @@ exports.PostRequest = PostRequest;
|
|
|
2725
3094
|
exports.PutRequest = PutRequest;
|
|
2726
3095
|
exports.RequestError = RequestError;
|
|
2727
3096
|
exports.ResponseWrapper = ResponseWrapper;
|
|
3097
|
+
exports.api = api;
|
|
2728
3098
|
exports["default"] = create;
|
|
3099
|
+
exports.del = del;
|
|
3100
|
+
exports.get = get;
|
|
3101
|
+
exports.head = head;
|
|
3102
|
+
exports.options = options;
|
|
3103
|
+
exports.patch = patch;
|
|
3104
|
+
exports.post = post;
|
|
3105
|
+
exports.put = put;
|
|
2729
3106
|
//# sourceMappingURL=index.cjs.map
|