create-request 1.4.3-rc.0 → 1.4.3-rc.2
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 +81 -100
- package/dist/library/RequestError.d.ts +1 -0
- package/dist/library/ResponseWrapper.d.ts +15 -9
- package/dist/library/apiBuilder.d.ts +0 -2
- package/dist/library/index.cjs +90 -107
- package/dist/library/index.cjs.map +1 -1
- package/dist/library/index.d.ts +3 -1
- package/dist/library/index.esm.js +81 -106
- 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/package.json +4 -4
- package/dist/library/utils/sizeUtils.d.ts +0 -8
package/README.md
CHANGED
|
@@ -16,15 +16,16 @@
|
|
|
16
16
|
- [Why create-request](#why-create-request)
|
|
17
17
|
- [Installation](#installation)
|
|
18
18
|
- [Basic Usage](#basic-usage)
|
|
19
|
-
- [API Builder](#api-builder)
|
|
20
|
-
- [Automatic Retries with Delay](#automatic-retries-with-delay)
|
|
21
|
-
- [Interceptors](#interceptors)
|
|
22
|
-
- [Request Cancellation](#request-cancellation)
|
|
23
19
|
- [URL Handling](#url-handling)
|
|
24
|
-
- [
|
|
25
|
-
- [
|
|
26
|
-
- [
|
|
27
|
-
- [
|
|
20
|
+
- [Advanced Usage](#advanced-usage)
|
|
21
|
+
- [API Builder](#api-builder)
|
|
22
|
+
- [Automatic Retries with Delay](#automatic-retries-with-delay)
|
|
23
|
+
- [Interceptors](#interceptors)
|
|
24
|
+
- [Request Cancellation](#request-cancellation)
|
|
25
|
+
- [Data Selection](#data-selection)
|
|
26
|
+
- [TypeScript Support](#typescript-support)
|
|
27
|
+
- [CSRF Protection](#csrf-protection)
|
|
28
|
+
- [Subresource Integrity and Cache Control](#subresource-integrity-and-cache-control)
|
|
28
29
|
- [Performance Considerations](#performance-considerations)
|
|
29
30
|
- [Browser Support](#browser-support)
|
|
30
31
|
- [Comparison of JavaScript HTTP Client Libraries](#comparison-of-javascript-http-client-libraries)
|
|
@@ -310,44 +311,6 @@ const merged = create
|
|
|
310
311
|
.withQueryParams({ new: "param" }); // Both existing and new params included
|
|
311
312
|
```
|
|
312
313
|
|
|
313
|
-
### Subresource Integrity and Cache Control
|
|
314
|
-
|
|
315
|
-
The library supports subresource integrity verification and cache control options:
|
|
316
|
-
|
|
317
|
-
```typescript
|
|
318
|
-
// Subresource Integrity - ensures the fetched resource hasn't been tampered with
|
|
319
|
-
const secureRequest = create
|
|
320
|
-
.get("https://cdn.example.com/script.js")
|
|
321
|
-
.withIntegrity("sha256-abcdef1234567890..."); // Browser will verify the hash
|
|
322
|
-
|
|
323
|
-
// Cache Control - supports all cache modes via fluent API or string values
|
|
324
|
-
const cachedRequest = create.get("https://api.example.com/data").withCache("no-cache"); // Direct string value
|
|
325
|
-
|
|
326
|
-
// Using fluent API for cache modes
|
|
327
|
-
const fluentCache = create.get("https://api.example.com/data").withCache.NO_CACHE(); // Fluent API method
|
|
328
|
-
|
|
329
|
-
// All available cache modes:
|
|
330
|
-
create
|
|
331
|
-
.get("https://api.example.com/data")
|
|
332
|
-
.withCache.DEFAULT() // Default cache behavior
|
|
333
|
-
.withCache.NO_STORE() // Don't store in cache
|
|
334
|
-
.withCache.RELOAD() // Reload from server
|
|
335
|
-
.withCache.NO_CACHE() // Validate with server before using cache
|
|
336
|
-
.withCache.FORCE_CACHE() // Use cache even if stale
|
|
337
|
-
.withCache.ONLY_IF_CACHED(); // Only use cache, don't fetch from server
|
|
338
|
-
|
|
339
|
-
// Using enum values (import from create-request)
|
|
340
|
-
import { CacheMode } from "create-request";
|
|
341
|
-
|
|
342
|
-
const enumCache = create.get("https://api.example.com/data").withCache(CacheMode.NO_CACHE);
|
|
343
|
-
|
|
344
|
-
// Combining integrity and cache
|
|
345
|
-
const secureCached = create
|
|
346
|
-
.get("https://cdn.example.com/resource.js")
|
|
347
|
-
.withIntegrity("sha256-abcdef1234567890...")
|
|
348
|
-
.withCache("no-store"); // Ensure no caching for sensitive resources
|
|
349
|
-
```
|
|
350
|
-
|
|
351
314
|
### Executing Requests
|
|
352
315
|
|
|
353
316
|
```typescript
|
|
@@ -418,7 +381,34 @@ try {
|
|
|
418
381
|
}
|
|
419
382
|
```
|
|
420
383
|
|
|
421
|
-
##
|
|
384
|
+
## URL Handling
|
|
385
|
+
|
|
386
|
+
The library handles both absolute and relative URLs, and automatically merges query parameters:
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
// Relative URLs (preserved as-is)
|
|
390
|
+
const relative = await create.get("/api/users").getJson();
|
|
391
|
+
|
|
392
|
+
// Absolute URLs
|
|
393
|
+
const absolute = await create.get("https://api.example.com/users").getJson();
|
|
394
|
+
|
|
395
|
+
// Merging query params with existing URL params
|
|
396
|
+
const merged = await create
|
|
397
|
+
.get("https://api.example.com/users?page=1")
|
|
398
|
+
.withQueryParams({ limit: 20, sort: "name" })
|
|
399
|
+
.getJson();
|
|
400
|
+
// Result: https://api.example.com/users?page=1&limit=20&sort=name
|
|
401
|
+
|
|
402
|
+
// Special characters and unicode are properly encoded
|
|
403
|
+
const encoded = await create
|
|
404
|
+
.get("https://api.example.com/search")
|
|
405
|
+
.withQueryParams({ name: "用户名", filter: "status:active" })
|
|
406
|
+
.getJson();
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
## Advanced Usage
|
|
410
|
+
|
|
411
|
+
### API Builder
|
|
422
412
|
|
|
423
413
|
The API builder allows you to create configured API instances with default settings that can be reused across your application. This is perfect for setting up a base URL, default headers, timeout values, and other request configurations once and using them for all requests.
|
|
424
414
|
|
|
@@ -467,8 +457,6 @@ The API builder provides access to all request configuration methods from `BaseR
|
|
|
467
457
|
- `withReferrer(referrer)` - Set default referrer
|
|
468
458
|
- `withKeepAlive(keepalive)` - Configure keep-alive
|
|
469
459
|
- `withIntegrity(integrity)` - Set integrity check
|
|
470
|
-
- `withQueryParams(params)` - Add default query parameters
|
|
471
|
-
- `withQueryParam(key, value)` - Add a single default query parameter
|
|
472
460
|
|
|
473
461
|
**CSRF Protection:**
|
|
474
462
|
|
|
@@ -498,26 +486,6 @@ await api.get("/users").getJson();
|
|
|
498
486
|
await api.post("/posts").withBody({ title: "Hello" }).getJson();
|
|
499
487
|
```
|
|
500
488
|
|
|
501
|
-
#### Methods NOT Available on API Builder
|
|
502
|
-
|
|
503
|
-
The following methods are **not available** on the API builder because they are request-specific and don't make sense as defaults:
|
|
504
|
-
|
|
505
|
-
- **`withAbortController(controller)`** - AbortController is per-request, not a default
|
|
506
|
-
- **`withBody(body)`** - Request bodies are different for each request
|
|
507
|
-
- **`withGraphQL(query, variables, options)`** - GraphQL queries are request-specific
|
|
508
|
-
|
|
509
|
-
These methods should be called directly on individual request instances:
|
|
510
|
-
|
|
511
|
-
```typescript
|
|
512
|
-
const api = create.api().withBaseURL("https://api.example.com");
|
|
513
|
-
|
|
514
|
-
// ✅ Good: Use withBody on individual requests
|
|
515
|
-
await api.post("/users").withBody({ name: "John" }).getJson();
|
|
516
|
-
|
|
517
|
-
// ❌ Bad: withBody is not available on the API builder
|
|
518
|
-
// api.withBody({ name: "John" }); // This will be undefined
|
|
519
|
-
```
|
|
520
|
-
|
|
521
489
|
#### URL Resolution
|
|
522
490
|
|
|
523
491
|
The API builder intelligently resolves URLs:
|
|
@@ -622,7 +590,7 @@ async function deleteUser(id: string) {
|
|
|
622
590
|
}
|
|
623
591
|
```
|
|
624
592
|
|
|
625
|
-
|
|
593
|
+
### Automatic Retries with Delay
|
|
626
594
|
|
|
627
595
|
The `withRetries()` method supports both simple number-based retries and object-based configuration with customizable delays:
|
|
628
596
|
|
|
@@ -669,7 +637,7 @@ const request4 = create.get("https://api.example.com/data").withRetries({
|
|
|
669
637
|
})
|
|
670
638
|
```
|
|
671
639
|
|
|
672
|
-
|
|
640
|
+
### Interceptors
|
|
673
641
|
|
|
674
642
|
Interceptors allow you to modify requests, transform responses, or handle errors globally or per-request. This is perfect for adding authentication tokens, logging, error recovery, and more.
|
|
675
643
|
|
|
@@ -803,7 +771,7 @@ const asyncData = await create
|
|
|
803
771
|
.getJson();
|
|
804
772
|
```
|
|
805
773
|
|
|
806
|
-
|
|
774
|
+
### Request Cancellation
|
|
807
775
|
|
|
808
776
|
```typescript
|
|
809
777
|
const controller = new AbortController();
|
|
@@ -829,32 +797,7 @@ try {
|
|
|
829
797
|
}
|
|
830
798
|
```
|
|
831
799
|
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
The library handles both absolute and relative URLs, and automatically merges query parameters:
|
|
835
|
-
|
|
836
|
-
```typescript
|
|
837
|
-
// Relative URLs (preserved as-is)
|
|
838
|
-
const relative = await create.get("/api/users").getJson();
|
|
839
|
-
|
|
840
|
-
// Absolute URLs
|
|
841
|
-
const absolute = await create.get("https://api.example.com/users").getJson();
|
|
842
|
-
|
|
843
|
-
// Merging query params with existing URL params
|
|
844
|
-
const merged = await create
|
|
845
|
-
.get("https://api.example.com/users?page=1")
|
|
846
|
-
.withQueryParams({ limit: 20, sort: "name" })
|
|
847
|
-
.getJson();
|
|
848
|
-
// Result: https://api.example.com/users?page=1&limit=20&sort=name
|
|
849
|
-
|
|
850
|
-
// Special characters and unicode are properly encoded
|
|
851
|
-
const encoded = await create
|
|
852
|
-
.get("https://api.example.com/search")
|
|
853
|
-
.withQueryParams({ name: "用户名", filter: "status:active" })
|
|
854
|
-
.getJson();
|
|
855
|
-
```
|
|
856
|
-
|
|
857
|
-
## Data Selection
|
|
800
|
+
### Data Selection
|
|
858
801
|
|
|
859
802
|
The `getData` method provides a powerful way to extract and transform specific data from API responses:
|
|
860
803
|
|
|
@@ -896,7 +839,7 @@ try {
|
|
|
896
839
|
}
|
|
897
840
|
```
|
|
898
841
|
|
|
899
|
-
|
|
842
|
+
### TypeScript Support
|
|
900
843
|
|
|
901
844
|
```typescript
|
|
902
845
|
interface User {
|
|
@@ -942,7 +885,7 @@ async function getUserById(id: number): Promise<User> {
|
|
|
942
885
|
}
|
|
943
886
|
```
|
|
944
887
|
|
|
945
|
-
|
|
888
|
+
### CSRF Protection
|
|
946
889
|
|
|
947
890
|
Cross-Site Request Forgery (CSRF) is a type of security vulnerability where unauthorized commands are executed on behalf of an authenticated user. `create-request` provides built-in protection mechanisms to help prevent CSRF attacks.
|
|
948
891
|
|
|
@@ -986,6 +929,44 @@ const request = create
|
|
|
986
929
|
.withoutCsrfProtection(); // Or disable all automatic CSRF protection
|
|
987
930
|
```
|
|
988
931
|
|
|
932
|
+
### Subresource Integrity and Cache Control
|
|
933
|
+
|
|
934
|
+
The library supports subresource integrity verification and cache control options:
|
|
935
|
+
|
|
936
|
+
```typescript
|
|
937
|
+
// Subresource Integrity - ensures the fetched resource hasn't been tampered with
|
|
938
|
+
const secureRequest = create
|
|
939
|
+
.get("https://cdn.example.com/script.js")
|
|
940
|
+
.withIntegrity("sha256-abcdef1234567890..."); // Browser will verify the hash
|
|
941
|
+
|
|
942
|
+
// Cache Control - supports all cache modes via fluent API or string values
|
|
943
|
+
const cachedRequest = create.get("https://api.example.com/data").withCache("no-cache"); // Direct string value
|
|
944
|
+
|
|
945
|
+
// Using fluent API for cache modes
|
|
946
|
+
const fluentCache = create.get("https://api.example.com/data").withCache.NO_CACHE(); // Fluent API method
|
|
947
|
+
|
|
948
|
+
// All available cache modes:
|
|
949
|
+
create
|
|
950
|
+
.get("https://api.example.com/data")
|
|
951
|
+
.withCache.DEFAULT() // Default cache behavior
|
|
952
|
+
.withCache.NO_STORE() // Don't store in cache
|
|
953
|
+
.withCache.RELOAD() // Reload from server
|
|
954
|
+
.withCache.NO_CACHE() // Validate with server before using cache
|
|
955
|
+
.withCache.FORCE_CACHE() // Use cache even if stale
|
|
956
|
+
.withCache.ONLY_IF_CACHED(); // Only use cache, don't fetch from server
|
|
957
|
+
|
|
958
|
+
// Using enum values (import from create-request)
|
|
959
|
+
import { CacheMode } from "create-request";
|
|
960
|
+
|
|
961
|
+
const enumCache = create.get("https://api.example.com/data").withCache(CacheMode.NO_CACHE);
|
|
962
|
+
|
|
963
|
+
// Combining integrity and cache
|
|
964
|
+
const secureCached = create
|
|
965
|
+
.get("https://cdn.example.com/resource.js")
|
|
966
|
+
.withIntegrity("sha256-abcdef1234567890...")
|
|
967
|
+
.withCache("no-store"); // Ensure no caching for sensitive resources
|
|
968
|
+
```
|
|
969
|
+
|
|
989
970
|
## Performance Considerations
|
|
990
971
|
|
|
991
972
|
create-request is designed to be lightweight and efficient:
|
|
@@ -3,16 +3,25 @@ import type { GraphQLOptions } from "./types.js";
|
|
|
3
3
|
* Wrapper for HTTP responses with methods to transform the response data
|
|
4
4
|
*/
|
|
5
5
|
export declare class ResponseWrapper {
|
|
6
|
-
private readonly response;
|
|
7
6
|
readonly url?: string;
|
|
8
7
|
readonly method?: string;
|
|
8
|
+
private readonly response;
|
|
9
9
|
private graphQLOptions?;
|
|
10
|
+
private cachedBlob?;
|
|
11
|
+
private cachedText?;
|
|
12
|
+
private cachedJson?;
|
|
13
|
+
private cachedArrayBuffer?;
|
|
10
14
|
constructor(response: Response, url?: string, method?: string, graphQLOptions?: GraphQLOptions);
|
|
11
15
|
get status(): number;
|
|
12
16
|
get statusText(): string;
|
|
13
17
|
get headers(): Headers;
|
|
14
18
|
get ok(): boolean;
|
|
15
19
|
get raw(): Response;
|
|
20
|
+
/**
|
|
21
|
+
* Check if the response body has already been consumed and throw an error if so
|
|
22
|
+
* @throws RequestError if the body has already been consumed
|
|
23
|
+
*/
|
|
24
|
+
private checkBodyNotConsumed;
|
|
16
25
|
/**
|
|
17
26
|
* Check for GraphQL errors and throw if throwOnError is enabled
|
|
18
27
|
* @param data - The parsed JSON data
|
|
@@ -21,11 +30,10 @@ export declare class ResponseWrapper {
|
|
|
21
30
|
private checkGraphQLErrors;
|
|
22
31
|
/**
|
|
23
32
|
* Parse the response body as JSON
|
|
24
|
-
* Note: This consumes the response body and can only be called once.
|
|
25
33
|
* If GraphQL options are set with throwOnError=true, will check for GraphQL errors and throw.
|
|
26
34
|
*
|
|
27
35
|
* @returns The parsed JSON data
|
|
28
|
-
* @throws {RequestError} When the request fails, JSON parsing fails, GraphQL errors occur (if throwOnError enabled)
|
|
36
|
+
* @throws {RequestError} When the request fails, JSON parsing fails, or GraphQL errors occur (if throwOnError enabled).
|
|
29
37
|
*
|
|
30
38
|
* @example
|
|
31
39
|
* const data = await response.getJson();
|
|
@@ -44,10 +52,9 @@ export declare class ResponseWrapper {
|
|
|
44
52
|
getJson<T = unknown>(): Promise<T>;
|
|
45
53
|
/**
|
|
46
54
|
* Get the response body as text
|
|
47
|
-
* Note: This consumes the response body and can only be called once.
|
|
48
55
|
*
|
|
49
56
|
* @returns The response text
|
|
50
|
-
* @throws {RequestError} When reading fails
|
|
57
|
+
* @throws {RequestError} When reading fails
|
|
51
58
|
*
|
|
52
59
|
* @example
|
|
53
60
|
* const text = await response.getText();
|
|
@@ -55,10 +62,9 @@ export declare class ResponseWrapper {
|
|
|
55
62
|
getText(): Promise<string>;
|
|
56
63
|
/**
|
|
57
64
|
* Get the response body as a Blob
|
|
58
|
-
* Note: This consumes the response body and can only be called once.
|
|
59
65
|
*
|
|
60
66
|
* @returns The response as a Blob
|
|
61
|
-
* @throws {RequestError} When reading fails
|
|
67
|
+
* @throws {RequestError} When reading fails
|
|
62
68
|
*
|
|
63
69
|
* @example
|
|
64
70
|
* const blob = await response.getBlob();
|
|
@@ -67,10 +73,9 @@ export declare class ResponseWrapper {
|
|
|
67
73
|
getBlob(): Promise<Blob>;
|
|
68
74
|
/**
|
|
69
75
|
* Get the response body as an ArrayBuffer
|
|
70
|
-
* Note: This consumes the response body and can only be called once.
|
|
71
76
|
*
|
|
72
77
|
* @returns The response as an ArrayBuffer
|
|
73
|
-
* @throws {RequestError} When reading fails
|
|
78
|
+
* @throws {RequestError} When reading fails
|
|
74
79
|
*
|
|
75
80
|
* @example
|
|
76
81
|
* const buffer = await response.getArrayBuffer();
|
|
@@ -80,6 +85,7 @@ export declare class ResponseWrapper {
|
|
|
80
85
|
/**
|
|
81
86
|
* Get the raw response body as a ReadableStream
|
|
82
87
|
* Note: This consumes the response body and should only be called once.
|
|
88
|
+
* Unlike other methods, streams cannot be cached, so this will throw if the body is already consumed.
|
|
83
89
|
*
|
|
84
90
|
* @returns The response body as a ReadableStream or null
|
|
85
91
|
* @throws {RequestError} When the response body has already been consumed
|
|
@@ -20,8 +20,6 @@ interface ApiBuilderRequestMethods {
|
|
|
20
20
|
withCookie(name: string, value: string | CookieOptions): ApiBuilder;
|
|
21
21
|
withRequestInterceptor(interceptor: RequestInterceptor): ApiBuilder;
|
|
22
22
|
withResponseInterceptor(interceptor: ResponseInterceptor): ApiBuilder;
|
|
23
|
-
withQueryParam(key: string, value: string | string[] | number | boolean | null | undefined): ApiBuilder;
|
|
24
|
-
withQueryParams(params: Record<string, string | string[] | number | boolean | null | undefined>): ApiBuilder;
|
|
25
23
|
}
|
|
26
24
|
/**
|
|
27
25
|
* API builder for creating configured API instances with default settings.
|