create-request 1.4.3-rc.4 → 1.5.0

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
@@ -16,6 +16,8 @@
16
16
  - [Why create-request](#why-create-request)
17
17
  - [Mental Model](#mental-model)
18
18
  - [Installation](#installation)
19
+ - [Named Exports](#named-exports)
20
+ - [Tree-Shaking Guide](#tree-shaking-guide)
19
21
  - [Basic Usage](#basic-usage)
20
22
  - [URL Handling](#url-handling)
21
23
  - [Advanced Usage](#advanced-usage)
@@ -28,7 +30,7 @@
28
30
  - [CSRF Protection](#csrf-protection)
29
31
  - [Subresource Integrity and Cache Control](#subresource-integrity-and-cache-control)
30
32
  - [Performance Considerations](#performance-considerations)
31
- - [Browser Support](#browser-support)
33
+ - [Browser & Node.js Support](#browser--nodejs-support)
32
34
  - [Comparison of JavaScript HTTP Client Libraries](#comparison-of-javascript-http-client-libraries)
33
35
  - [License](#license)
34
36
 
@@ -97,6 +99,80 @@ function createUser(userData) {
97
99
  }
98
100
  ```
99
101
 
102
+ ### Why Not Object-Based Configuration?
103
+
104
+ Many HTTP client libraries (like Axios, Got, and even the native Fetch API) use object-based configuration where all options are passed in a single configuration object. While this approach works, it creates a poor developer experience:
105
+
106
+ **The Developer Experience Problem:**
107
+
108
+ With object-based configuration, you're constantly context-switching between your code and documentation. You need to:
109
+
110
+ - Remember exact option names and their structure
111
+ - Look up documentation to discover available options
112
+ - Guess at nested object structures
113
+ - Hope your IDE autocomplete works with complex nested types
114
+
115
+ ```typescript
116
+ // Object-based: What options are available? What's the structure? Need to check docs
117
+ axios.post("https://api.example.com/users", userData, {
118
+ headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
119
+ timeout: 5000,
120
+ params: { validate: true },
121
+ withCredentials: true,
122
+ });
123
+ ```
124
+
125
+ **Superior Developer Experience with Fluent API:**
126
+
127
+ `create-request`'s fluent API is designed for an exceptional developer experience. Every method is discoverable, self-documenting, and provides rich IDE support:
128
+
129
+ #### 1. Intelligent Autocomplete & IntelliSense
130
+
131
+ As you type, your IDE suggests the exact methods you need. No guessing, no documentation lookup:
132
+
133
+ ```typescript
134
+ // Start typing and see all available methods
135
+ create
136
+ .post(url)
137
+ .withBearerToken() // ← IDE suggests: withBearerToken(token: string)
138
+ .withTimeout() // ← IDE suggests: withTimeout(ms: number)
139
+ .withRetries(); // ← IDE suggests: withRetries(count: number | RetryConfig)
140
+ ```
141
+
142
+ #### 2. Rich JSDoc Documentation in Your IDE
143
+
144
+ Hover over any method to see comprehensive documentation, examples, and parameter details - all without leaving your editor:
145
+
146
+ ```typescript
147
+ // Hover over withRetries to see:
148
+ // "Configures automatic retry behavior for failed requests.
149
+ // @param retries - Number of retry attempts or retry configuration object
150
+ // @example
151
+ // .withRetries(3)
152
+ // .withRetries({ attempts: 3, delay: 1000 })"
153
+ create.get(url).withRetries(3);
154
+ ```
155
+
156
+ #### 3. Discoverability Through Method Chaining
157
+
158
+ Each method reveals what's available next. Explore the API naturally through autocomplete:
159
+
160
+ ```typescript
161
+ // Discover available options as you chain
162
+ create
163
+ .post(url)
164
+ .withHeaders() // ← See all header methods
165
+ .withBearerToken() // ← See all auth methods
166
+ .withTimeout() // ← See all timeout/retry methods
167
+ .withQueryParams(); // ← See all query param methods
168
+ ```
169
+
170
+ #### 4. No Context Switching
171
+
172
+ Stay in your flow. Everything you need is in your IDE - documentation, types, examples, and autocomplete. No alt-tabbing to documentation websites.
173
+
174
+ This developer-first approach means you spend less time looking things up and more time writing code that works.
175
+
100
176
  ## Mental Model
101
177
 
102
178
  ### 1. **Separation of Building and Execution**
@@ -180,7 +256,7 @@ This pattern makes the API self-documenting - any method starting with `with...`
180
256
 
181
257
  The typical request lifecycle follows this pattern:
182
258
 
183
- ```
259
+ ```text
184
260
  Build → Configure → Execute → Transform → Handle
185
261
  ```
186
262
 
@@ -231,6 +307,68 @@ yarn add create-request
231
307
  pnpm add create-request
232
308
  ```
233
309
 
310
+ ## Named Exports
311
+
312
+ The library provides both default and named exports:
313
+
314
+ **Default Export:**
315
+
316
+ - `create` - Main API object with factory methods (`get`, `post`, `put`, `del`, `patch`, `head`, `options`, `api`) and global `config`
317
+
318
+ **Named Exports:**
319
+
320
+ **Enums:**
321
+
322
+ - `HttpMethod`, `RequestPriority`, `CredentialsPolicy`, `RequestMode`, `RedirectMode`, `SameSitePolicy`, `ReferrerPolicy`, `CacheMode`
323
+
324
+ **Types:**
325
+
326
+ - `RetryCallback`, `RetryConfig`, `CookiesRecord`, `CookieOptions`, `RequestConfig`, `GraphQLOptions`, `RequestOptions`, `ErrorInterceptor`, `RequestInterceptor`, `RetryDelayFunction`, `ResponseInterceptor`
327
+
328
+ **Classes:**
329
+
330
+ - `ResponseWrapper`, `CookieUtils`, `RequestError`
331
+
332
+ **Request Classes:**
333
+
334
+ - `GetRequest`, `PostRequest`, `PutRequest`, `DeleteRequest`, `PatchRequest`, `HeadRequest`, `OptionsRequest`
335
+
336
+ **Factory Functions:**
337
+
338
+ - `createGet`, `createPost`, `createPut`, `createDelete`, `createPatch`, `createHead`, `createOptions`, `createApi`
339
+
340
+ ```typescript
341
+ // Default export
342
+ import create from "create-request";
343
+
344
+ // Named exports
345
+ import { RequestError, CacheMode, createGet } from "create-request";
346
+ ```
347
+
348
+ ## Tree-Shaking Guide
349
+
350
+ All named exports are tree-shakeable. The library is marked with `"sideEffects": false`, enabling bundlers to eliminate unused code.
351
+
352
+ **Tree-shakeable:**
353
+
354
+ - ✅ All named exports (enums, types, classes, factory functions)
355
+ - ✅ Individual factory functions (`createGet`, `createPost`, etc.)
356
+ - ✅ Individual request classes (`GetRequest`, `PostRequest`, etc.)
357
+
358
+ **Not tree-shakeable:**
359
+
360
+ - Default export (`create`) - imports the entire API object (library is small, so this is usually fine)
361
+
362
+ **Tip:** For maximum tree-shaking, you can use named exports when you only need specific functionality:
363
+
364
+ ```typescript
365
+ // Tree-shakeable - only imports what you use
366
+ import { createGet } from "create-request";
367
+
368
+ // Imports entire library (recommended for most use cases)
369
+ import create from "create-request";
370
+ ```
371
+
234
372
  ## Basic Usage
235
373
 
236
374
  ### Creating Requests
@@ -305,15 +443,15 @@ const request = create
305
443
 
306
444
  // Fetch API options
307
445
  // Note: These methods support three styles - Fluent API (shown below), Enum-based (e.g., .withMode(RequestMode.CORS)), or String-based (e.g., .withMode("cors"))
308
- .withCredentials.INCLUDE() // Includes cookies with cross-origin requests
446
+ .withCredentials.INCLUDE() // Includes cookies with cross-origin requests (Fluent API)
309
447
  .withMode.CORS() // Controls CORS behavior
310
- .withRedirect.FOLLOW() // Controls redirect behavior (follow, error, manual)
448
+ .withRedirect.FOLLOW() // Controls redirect behavior
311
449
  .withReferrer("https://example.com") // Sets request referrer
312
450
  .withReferrerPolicy.NO_REFERRER_WHEN_DOWNGRADE() // Controls referrer policy
313
451
  .withPriority.HIGH() // Sets request priority
314
452
  .withKeepAlive(true) // Keeps connection alive after the page is unloaded
315
453
  .withIntegrity("sha256-abcdef1234567890...") // Sets subresource integrity hash
316
- .withCache("no-cache"); // Controls cache behavior (or use .withCache.NO_CACHE())
454
+ .withCache("no-cache"); // Direct string value (or use .withCache.NO_CACHE() for Fluent API)
317
455
  ```
318
456
 
319
457
  Each configuration method returns the request object, allowing for a fluent interface where methods can be chained together. You can configure only what you need for a specific request:
@@ -557,7 +695,14 @@ const newUser = await api.post().withBody({ name: "John" }).getJson();
557
695
 
558
696
  #### Available Request Methods
559
697
 
560
- The API builder provides access to all request configuration methods from `BaseRequest` that can be used as defaults. These methods will apply to all requests made through the API instance:
698
+ The API builder provides access to most request configuration methods from `BaseRequest` that can be used as defaults. These methods will apply to all requests made through the API instance.
699
+
700
+ **Important limitations:**
701
+
702
+ - Methods that are request-specific (like `withBody`, `withGraphQL`, `withAbortController`) are not available in ApiBuilder
703
+ - The Fluent API (e.g., `.withCache.NO_STORE()`) is not supported - use direct calls with string or enum values instead
704
+
705
+ Available methods:
561
706
 
562
707
  **Authentication & Headers:**
563
708
 
@@ -573,13 +718,24 @@ The API builder provides access to all request configuration methods from `BaseR
573
718
  - `withCookies(cookies)` - Add cookies to all requests
574
719
  - `withCookie(name, value)` - Add a single cookie
575
720
 
721
+ **Query Parameters:**
722
+
723
+ - `withQueryParams(params)` - Add default query parameters to all requests
724
+ - `withQueryParam(key, value)` - Add a single default query parameter
725
+
576
726
  **Request Configuration:**
577
727
 
578
728
  - `withTimeout(timeout)` - Set default timeout for all requests
579
729
  - `withRetries(retries)` - Configure default retry behavior
580
730
  - `withReferrer(referrer)` - Set default referrer
731
+ - `withReferrerPolicy(policy)` - Set default referrer policy (use string or enum)
581
732
  - `withKeepAlive(keepalive)` - Configure keep-alive
582
733
  - `withIntegrity(integrity)` - Set integrity check
734
+ - `withMode(mode)` - Set request mode (use string or enum)
735
+ - `withCredentials(credentials)` - Set credentials policy (use string or enum)
736
+ - `withRedirect(redirect)` - Set redirect behavior (use string or enum)
737
+ - `withPriority(priority)` - Set request priority (use string or enum)
738
+ - `withCache(cache)` - Set cache mode (use string or enum)
583
739
 
584
740
  **CSRF Protection:**
585
741
 
@@ -596,15 +752,23 @@ The API builder provides access to all request configuration methods from `BaseR
596
752
  These methods can be chained together and will apply to all requests made through the API instance:
597
753
 
598
754
  ```typescript
755
+ import { CacheMode, CredentialsPolicy, RequestMode } from "create-request";
756
+
599
757
  const api = create
600
758
  .api()
601
759
  .withBaseURL("https://api.example.com")
602
760
  .withBearerToken("token123")
603
761
  .withCookies({ session: "abc123" })
604
762
  .withTimeout(5000)
605
- .withHeaders({ "X-Custom": "value" });
606
-
607
- // All requests will include the Bearer token, cookies, timeout, and headers
763
+ .withHeaders({ "X-Custom": "value" })
764
+ .withQueryParams({ apiVersion: "v2" }) // Default query params
765
+ .withCache("no-store") // Direct string value
766
+ // Or use enum: .withCache(CacheMode.NO_STORE)
767
+ .withCredentials("include"); // Direct string value
768
+ // Or use enum: .withCredentials(CredentialsPolicy.INCLUDE)
769
+ // Note: Fluent API like .withCache.NO_STORE() is NOT supported in ApiBuilder
770
+
771
+ // All requests will include the Bearer token, cookies, timeout, headers, query params, and cache settings
608
772
  await api.get("/users").getJson();
609
773
  await api.post("/posts").withBody({ title: "Hello" }).getJson();
610
774
  ```
@@ -687,13 +851,17 @@ const api = create
687
851
 
688
852
  ```typescript
689
853
  // Set up your API once
854
+ import { CacheMode } from "create-request";
855
+
690
856
  const api = create
691
857
  .api()
692
858
  .withBaseURL("https://api.example.com/v1")
693
859
  .withHeaders({ "Content-Type": "application/json" })
694
860
  .withCookies({ session: "abc123" })
695
861
  .withBearerToken("token123")
696
- .withTimeout(20000);
862
+ .withTimeout(20000)
863
+ .withQueryParams({ format: "json" })
864
+ .withCache(CacheMode.NO_CACHE);
697
865
 
698
866
  // Use throughout your application
699
867
  async function getUsers() {
@@ -1100,7 +1268,7 @@ create-request is designed to be lightweight and efficient:
1100
1268
  - **Memory Efficient**: Doesn't create unnecessary objects
1101
1269
  - **Clean API**: Simple and intuitive interface
1102
1270
 
1103
- ## Browser Support
1271
+ ## Browser & Node.js Support
1104
1272
 
1105
1273
  This library works with all browsers that support the Fetch API:
1106
1274
 
@@ -1110,11 +1278,15 @@ This library works with all browsers that support the Fetch API:
1110
1278
  - Edge 14+
1111
1279
  - Opera 29+
1112
1280
 
1281
+ For Node.js:
1282
+
1283
+ - Node.js 18.3.0+ (native fetch support required)
1284
+
1113
1285
  ## Comparison of JavaScript HTTP Client Libraries
1114
1286
 
1115
1287
  | Feature | create-request | Fetch | Axios | SuperAgent | Got | Ky | node-fetch | Redaxios |
1116
1288
  | --------------------- | -------------- | ------ | ------- | ---------- | ------- | ------ | ---------- | -------- |
1117
- | **Size (min+gzip)** | ~6.3KB | Native | ~13.6KB | ~17.8KB | ~17.8KB | ~3.4KB | ~7.7KB | ~1KB |
1289
+ | **Size (min+gzip)** | ~6.4KB | Native | ~13.6KB | ~17.8KB | ~17.8KB | ~3.4KB | ~7.7KB | ~1KB |
1118
1290
  | **Browser** | Modern | Modern | IE11+ | IE9+ | ❌ No | Modern | ❌ No | Modern |
1119
1291
  | **Node.js** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
1120
1292
  | **HTTP/2** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
@@ -711,6 +711,21 @@ export declare abstract class BaseRequest {
711
711
  * ```
712
712
  */
713
713
  getBlob(): Promise<Blob>;
714
+ /**
715
+ * Execute the request and get the response body as an ArrayBuffer.
716
+ * Useful for processing binary data at a low level.
717
+ *
718
+ * @returns A promise that resolves to the response body as an ArrayBuffer
719
+ * @throws {RequestError} When the request fails or reading the response fails
720
+ *
721
+ * @example
722
+ * ```typescript
723
+ * const buffer = await request.getArrayBuffer();
724
+ * const uint8Array = new Uint8Array(buffer);
725
+ * // Process the binary data
726
+ * ```
727
+ */
728
+ getArrayBuffer(): Promise<ArrayBuffer>;
714
729
  /**
715
730
  * Execute the request and get the response body as a ReadableStream.
716
731
  * Note: Unlike other methods, streams cannot be cached. The body can only be consumed once.
@@ -26,9 +26,9 @@ export declare class RequestError extends Error {
26
26
  /** The HTTP method that was used (e.g., 'GET', 'POST') */
27
27
  readonly method: string;
28
28
  /** Whether the request failed due to a timeout */
29
- readonly isTimeout?: boolean;
29
+ readonly isTimeout: boolean;
30
30
  /** Whether the request was aborted (cancelled) */
31
- readonly isAborted?: boolean;
31
+ readonly isAborted: boolean;
32
32
  /**
33
33
  * Creates a new RequestError instance.
34
34
  *