create-request 0.0.1-beta.5 → 0.0.1-beta.7

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
@@ -14,6 +14,7 @@
14
14
  - 🔐 **Auth Helpers** - Simple methods for common authentication patterns
15
15
  - 📦 **Typed Responses** - Full TypeScript support for response data
16
16
  - 🚧 **Error Handling** - Detailed error info with custom error class
17
+ - 📝 **Response Caching** - Flexible caching system with multiple storage options
17
18
 
18
19
  ## Why create-request?
19
20
 
@@ -206,6 +207,39 @@ try {
206
207
  }
207
208
  ```
208
209
 
210
+ ### Caching Requests
211
+
212
+ ```typescript
213
+ import create, { createMemoryStorage, createLocalStorageStorage, createSessionStorageStorage } from 'create-request';
214
+
215
+ // Simple in-memory caching
216
+ const request = create.get()
217
+ .withCache({
218
+ storage: createMemoryStorage(),
219
+ ttl: 60000 // 1 minute in milliseconds
220
+ })
221
+ .sendTo('https://api.example.com/data');
222
+
223
+ // Using localStorage storage
224
+ const request = create.get()
225
+ .withCache({
226
+ storage: createLocalStorageStorage(),
227
+ ttl: 5 * 60 * 1000, // 5 minutes
228
+ maxSize: '1MB',
229
+ keyPrefix: 'user-data'
230
+ })
231
+ .sendTo('https://api.example.com/users');
232
+
233
+ // Using sessionStorage for per-session caching
234
+ const request = create.get()
235
+ .withCache({
236
+ storage: createSessionStorageStorage(),
237
+ maxEntries: 50,
238
+ varyByHeaders: ['x-api-version']
239
+ })
240
+ .sendTo('https://api.example.com/data');
241
+ ```
242
+
209
243
  ## Advanced Usage
210
244
 
211
245
  ### Request Reuse
@@ -277,6 +311,117 @@ request.sendTo('https://api.example.com/data')
277
311
  });
278
312
  ```
279
313
 
314
+ ### Advanced Caching
315
+
316
+ ```typescript
317
+ import create, { createMemoryStorage, StorageProvider } from 'create-request';
318
+
319
+ // Custom key generation
320
+ const request = create.get()
321
+ .withCache({
322
+ storage: createMemoryStorage(),
323
+ keyGenerator: (url, method, headers) => {
324
+ // Include user ID from authorization header in the cache key
325
+ const authHeader = headers?.['Authorization'] || '';
326
+ const userId = extractUserIdFromToken(authHeader);
327
+ return `${method}:${url}:${userId}`;
328
+ }
329
+ });
330
+
331
+ // Simple custom storage provider example
332
+ const customStorage: StorageProvider = {
333
+ get(key: string): string | null {
334
+ // Get from your custom storage
335
+ return localStorage.getItem(`my-app:${key}`);
336
+ },
337
+ set(key: string, value: string): void {
338
+ // Set in your custom storage
339
+ localStorage.setItem(`my-app:${key}`, value);
340
+ },
341
+ has(key: string): boolean {
342
+ // Check if exists in your custom storage
343
+ return localStorage.getItem(`my-app:${key}`) !== null;
344
+ },
345
+ delete(key: string): void {
346
+ // Remove from your custom storage
347
+ localStorage.removeItem(`my-app:${key}`);
348
+ },
349
+ clear(): void {
350
+ // Clear all items from your namespace
351
+ Object.keys(localStorage)
352
+ .filter(key => key.startsWith('my-app:'))
353
+ .forEach(key => localStorage.removeItem(key));
354
+ }
355
+ };
356
+
357
+ const request = create.get()
358
+ .withCache({ storage: customStorage })
359
+ .sendTo('https://api.example.com/data');
360
+ ```
361
+
362
+ ### Implementing Custom Storage Providers
363
+
364
+ You can create your own storage provider by implementing the `StorageProvider` interface:
365
+
366
+ ```typescript
367
+ import { StorageProvider } from 'create-request';
368
+
369
+ // Create a simple custom storage provider
370
+ export function createNamespacedStorage(namespace: string): StorageProvider {
371
+ return {
372
+ get(key: string): string | null {
373
+ return localStorage.getItem(`${namespace}:${key}`);
374
+ },
375
+
376
+ set(key: string, value: string): void {
377
+ try {
378
+ localStorage.setItem(`${namespace}:${key}`, value);
379
+ } catch (e) {
380
+ // Handle quota exceeded errors
381
+ console.warn("Storage quota exceeded, clearing cache");
382
+ this.clear();
383
+ try {
384
+ localStorage.setItem(`${namespace}:${key}`, value);
385
+ } catch (e) {
386
+ console.error("Failed to set cache item even after clearing cache");
387
+ }
388
+ }
389
+ },
390
+
391
+ has(key: string): boolean {
392
+ return localStorage.getItem(`${namespace}:${key}`) !== null;
393
+ },
394
+
395
+ delete(key: string): void {
396
+ localStorage.removeItem(`${namespace}:${key}`);
397
+ },
398
+
399
+ clear(): void {
400
+ // Only clear items in our namespace
401
+ Object.keys(localStorage)
402
+ .filter(key => key.startsWith(`${namespace}:`))
403
+ .forEach(key => localStorage.removeItem(key));
404
+ }
405
+ };
406
+ }
407
+
408
+ // Usage:
409
+ const request = create.get()
410
+ .withCache({
411
+ storage: createNamespacedStorage('api-cache'),
412
+ ttl: 24 * 60 * 60 * 1000 // 24 hours
413
+ })
414
+ .sendTo('https://api.example.com/data');
415
+ ```
416
+
417
+ With custom storage providers, you can integrate with any storage system, such as:
418
+
419
+ - Custom browser storage solutions
420
+ - Memory caches with expiration policies
421
+ - Session-based storage mechanisms
422
+ - Encrypted storage providers
423
+ - Third-party storage libraries
424
+
280
425
  ## CSRF Protection
281
426
 
282
427
  ### Global CSRF Configuration
@@ -1,12 +1,16 @@
1
1
  import { type HttpMethod, type RedirectMode, type RequestMode, type RequestPriority, CredentialsPolicy } from "./enums";
2
2
  import { type ResponsePromise } from "./ResponseWrapper";
3
3
  import type { RequestOptions, RetryCallback, CookiesRecord, CookieOptions } from "./types";
4
+ import type { CacheOptions } from "./types/cache";
5
+ import { CacheManager } from "./utils/CacheManager";
4
6
  export declare abstract class BaseRequest {
5
7
  protected abstract method: HttpMethod;
6
8
  protected requestOptions: RequestOptions;
7
9
  protected abortController?: AbortController;
8
10
  protected queryParams: URLSearchParams;
9
11
  protected autoApplyCsrfProtection: boolean;
12
+ protected cacheManager?: CacheManager;
13
+ protected cacheEnabled: boolean;
10
14
  constructor();
11
15
  withHeaders(headers: Record<string, string>): this;
12
16
  withTimeout(timeout: number): this;
@@ -57,10 +61,10 @@ export declare abstract class BaseRequest {
57
61
  /**
58
62
  * Adds a single query parameter
59
63
  * @param key - The parameter name
60
- * @param value - The parameter value
64
+ * @param value - The parameter value, can be a single value or array of values
61
65
  * @returns The instance for chaining
62
66
  */
63
- withQueryParam(key: string, value: string | number | boolean | null | undefined): this;
67
+ withQueryParam(key: string, value: string | string[] | number | boolean | null | undefined): this;
64
68
  /**
65
69
  * Sets the mode of the request
66
70
  * @param mode - The mode for the request (cors, no-cors, same-origin, navigate)
@@ -86,12 +90,24 @@ export declare abstract class BaseRequest {
86
90
  * @returns The instance for chaining
87
91
  */
88
92
  withBasicAuth(username: string, password: string): this;
93
+ /**
94
+ * Cross-environment base64 encoding
95
+ * Works in both browser and Node.js environments
96
+ */
97
+ private encodeBase64;
89
98
  /**
90
99
  * Sets the bearer token for authentication
91
100
  * @param token - The bearer token
92
101
  * @returns The instance for chaining
93
102
  */
94
103
  withBearerToken(token: string): this;
104
+ /**
105
+ * Helper function to check for header presence in a case-insensitive way
106
+ * @param headers Headers object
107
+ * @param headerName Header name to check
108
+ * @returns Boolean indicating if the header exists (case-insensitive)
109
+ */
110
+ private hasHeader;
95
111
  /**
96
112
  * Sets cookies for the request
97
113
  * @param cookies Object containing cookie name-value pairs or cookie options
@@ -123,6 +139,12 @@ export declare abstract class BaseRequest {
123
139
  * @returns The instance for chaining
124
140
  */
125
141
  withAntiCsrfHeaders(): this;
142
+ /**
143
+ * Enables caching for the request with the specified options
144
+ * @param options The cache configuration options
145
+ * @returns The instance for chaining
146
+ */
147
+ withCache(options?: CacheOptions): this;
126
148
  /**
127
149
  * Send the request to the specified URL
128
150
  * @param url The URL to send the request to
@@ -142,4 +164,11 @@ export declare abstract class BaseRequest {
142
164
  */
143
165
  private executeWithRetries;
144
166
  private executeRequest;
167
+ /**
168
+ * Executes a request using cache when possible
169
+ * @param url The formatted URL to send the request to
170
+ * @param fetchOptions The fetch options to use
171
+ * @param cacheKey The cache key for this request
172
+ */
173
+ private executeWithCache;
145
174
  }
@@ -5,7 +5,6 @@ import type { Body } from "./types";
5
5
  */
6
6
  export declare abstract class BodyRequest extends BaseRequest {
7
7
  protected body?: Body;
8
- private bodyProcessed;
9
8
  private bodyType?;
10
9
  /**
11
10
  * Sets the body of the request
@@ -2,55 +2,22 @@
2
2
  * Wrapper for HTTP responses with methods to transform the response data
3
3
  */
4
4
  export declare class ResponseWrapper {
5
- readonly ok: boolean;
6
- private response;
5
+ private readonly response;
6
+ private textCache;
7
+ private jsonCache;
8
+ private blobCache;
9
+ private arrayBufferCache;
10
+ private bodyUsed;
7
11
  constructor(response: Response);
8
- /**
9
- * Get the raw Response object
10
- */
11
- get raw(): Response;
12
- /**
13
- * Get the HTTP status code
14
- */
15
12
  get status(): number;
16
- /**
17
- * Get the HTTP status text
18
- */
19
13
  get statusText(): string;
20
- /**
21
- * Get response headers
22
- */
23
14
  get headers(): Headers;
24
- /**
25
- * Parse response as JSON
26
- */
15
+ get ok(): boolean;
16
+ get raw(): Response;
27
17
  getJson<T = unknown>(): Promise<T>;
28
- /**
29
- * Get response as text
30
- */
31
18
  getText(): Promise<string>;
32
- /**
33
- * Get response as Blob
34
- */
35
19
  getBlob(): Promise<Blob>;
36
- /**
37
- * Get response as ArrayBuffer
38
- */
39
20
  getArrayBuffer(): Promise<ArrayBuffer>;
40
- /**
41
- * Get response as ReadableStream for true streaming consumption.
42
- * This allows you to process data incrementally as it arrives.
43
- *
44
- * @example
45
- * const stream = await request.sendTo('https://example.com/large-file').getBody();
46
- * const reader = stream.getReader();
47
- *
48
- * while (true) {
49
- * const { done, value } = await reader.read();
50
- * if (done) break;
51
- * // Process chunk of data in 'value'
52
- * }
53
- */
54
21
  getBody(): ReadableStream<Uint8Array> | null;
55
22
  }
56
23
  /**
@@ -1,11 +1,15 @@
1
1
  import { get, put, head, post, patch, del, options } from "./requestFactories";
2
2
  import { Config } from "./utils/Config";
3
- export { HttpMethod, RequestPriority, CredentialsPolicy, RequestMode, RedirectMode, CacheMode, SameSitePolicy, } from "./enums";
3
+ export { HttpMethod, RequestPriority, CredentialsPolicy, RequestMode, RedirectMode, CacheMode, SameSitePolicy } from "./enums";
4
4
  export type { RetryCallback, RequestOptions, CookieOptions, CookiesRecord } from "./types";
5
5
  export { RequestError } from "./RequestError";
6
6
  export { ResponseWrapper } from "./ResponseWrapper";
7
7
  export { CookieUtils } from "./utils/CookieUtils";
8
- export { GetRequest, PostRequest, PutRequest, DeleteRequest, PatchRequest, HeadRequest, OptionsRequest, } from "./requestMethods";
8
+ export { GetRequest, PostRequest, PutRequest, DeleteRequest, PatchRequest, HeadRequest, OptionsRequest } from "./requestMethods";
9
+ export { createMemoryStorage, createLocalStorageStorage, createSessionStorageStorage } from "./utils/CacheStorage";
10
+ export { CacheManager } from "./utils/CacheManager";
11
+ export type { CacheOptions } from "./types/cache";
12
+ export type { StorageProvider } from "./utils/StorageProvider";
9
13
  declare const create: {
10
14
  readonly get: typeof get;
11
15
  readonly post: typeof post;