@foundatiofx/fetchclient 1.0.0 → 1.0.1

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.
@@ -248,7 +248,8 @@ export class FetchClient {
248
248
  return this.problemToResponse(problem, url);
249
249
  }
250
250
  }
251
- if (init?.body && typeof init.body === "object") {
251
+ if (init?.body && typeof init.body === "object" &&
252
+ !(init.body instanceof FormData)) {
252
253
  init.body = JSON.stringify(init.body);
253
254
  }
254
255
  const accessToken = this.options.accessTokenFunc?.() ?? null;
@@ -419,11 +420,12 @@ export class FetchClient {
419
420
  return value;
420
421
  }
421
422
  buildRequestInit(method, body, options) {
422
- const isDefinitelyJsonBody = body !== undefined &&
423
- body !== null &&
424
- typeof body === "object";
423
+ const isFormData = typeof FormData !== "undefined" &&
424
+ body instanceof FormData;
425
+ const isJsonLikeObject = body !== undefined && body !== null &&
426
+ typeof body === "object" && !isFormData;
425
427
  const headers = {};
426
- if (isDefinitelyJsonBody) {
428
+ if (isJsonLikeObject) {
427
429
  headers["Content-Type"] = "application/json";
428
430
  }
429
431
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foundatiofx/fetchclient",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "A typed JSON fetch client with middleware support for Deno, Node and the browser.",
5
5
  "keywords": [
6
6
  "Fetch",
@@ -43,7 +43,7 @@
43
43
  "devDependencies": {
44
44
  "@types/node": "^20.9.0",
45
45
  "picocolors": "^1.0.0",
46
- "zod": "^4.1.4",
46
+ "zod": "^4.1.11",
47
47
  "@deno/shim-deno": "~0.18.0"
48
48
  },
49
49
  "_generatedBy": "dnt@dev"
package/readme.md CHANGED
@@ -6,298 +6,36 @@
6
6
  [![Build status](https://github.com/foundatiofx/foundatio/workflows/Build/badge.svg)](https://github.com/foundatiofx/foundatio/actions)
7
7
  [![Discord](https://img.shields.io/discord/715744504891703319)](https://discord.gg/6HxgFCx)
8
8
 
9
- <!-- deno-fmt-ignore-file -->
10
-
11
- FetchClient is a library that makes it easier to use the fetch API for JSON
12
- APIs. It provides the following features:
13
-
14
- - [Typed Response](#typed-response) - Full TypeScript support with strongly
15
- typed responses
16
- - [Functional](#functional) - Standalone functions for simple usage
17
- - [Model Validator](#model-validator) - Built-in validation with Problem Details
18
- support
19
- - [Caching](#caching) - Response caching with TTL and programmatic invalidation
20
- - [Middleware](#middleware) - Extensible middleware pipeline for
21
- request/response handling
22
- - [Rate Limiting](#rate-limiting) - Built-in rate limiting with per-domain
23
- support
24
- - [Request Timeout](#request-timeout) - Configurable timeouts with AbortSignal
25
- support
26
- - [Error Handling](#error-handling) - Comprehensive error handling with Problem
27
- Details
28
- - [Authentication](#authentication) - Built-in Bearer token support
29
- - [Base URL](#base-url) - Global base URL configuration
30
- - [Loading State](#loading-state) - Track request loading state with events
9
+ FetchClient is a tiny, typed wrapper around `fetch` with JSON helpers, caching,
10
+ middleware, rate limiting, timeouts, and friendly error handling.
31
11
 
32
12
  ## Install
33
13
 
34
- ```shell
35
- npm install --save @foundatiofx/fetchclient
14
+ ```bash
15
+ npm install @foundatiofx/fetchclient
36
16
  ```
37
17
 
38
- ## Docs
39
-
40
- [API Documentation](https://jsr.io/@foundatiofx/fetchclient/doc)
41
-
42
- ## Usage
43
-
44
- ### Typed Response
18
+ ## Quick Example
45
19
 
46
20
  ```ts
47
21
  import { FetchClient } from "@foundatiofx/fetchclient";
48
22
 
49
- type Products = {
50
- products: Array<{ id: number; name: string }>;
51
- };
23
+ type Products = { products: Array<{ id: number; name: string }> };
52
24
 
53
25
  const client = new FetchClient();
54
- const response = await client.getJSON<Products>(
26
+ const { data } = await client.getJSON<Products>(
55
27
  `https://dummyjson.com/products/search?q=iphone&limit=10`,
56
28
  );
57
29
 
58
- const products = response.data;
59
- ```
60
-
61
- ### Functional
62
-
63
- ```ts
64
- import { getJSON, postJSON } from "@foundatiofx/fetchclient";
65
-
66
- type Product = { id: number; title: string };
67
- type Products = { products: Product[] };
68
-
69
- const response = await postJSON<Product>(
70
- "https://dummyjson.com/products/add",
71
- {
72
- name: "iPhone 13",
73
- },
74
- );
75
-
76
- const product = await getJSON<Product>(
77
- `https://dummyjson.com/products/${response.data!.id}`,
78
- );
79
- ```
80
-
81
- ### Model Validator
82
-
83
- ```ts
84
- import { FetchClient, setModelValidator } from "@foundatiofx/fetchclient";
85
-
86
- setModelValidator(async (data: object | null) => {
87
- // use zod or any other validator
88
- const problem = new ProblemDetails();
89
- const d = data as { password: string };
90
- if (d?.password?.length < 6) {
91
- problem.errors.password = [
92
- "Password must be longer than or equal to 6 characters.",
93
- ];
94
- }
95
- return problem;
96
- });
97
-
98
- const client = new FetchClient();
99
- const data = {
100
- email: "test@test",
101
- password: "test",
102
- };
103
-
104
- const response = await client.postJSON(
105
- "https://jsonplaceholder.typicode.com/todos/1",
106
- data,
107
- );
108
-
109
- if (!response.ok) {
110
- // check response problem
111
- console.log(response.problem.detail);
112
- }
113
- ```
114
-
115
- ### Caching
116
-
117
- ```ts
118
- import { FetchClient } from "@foundatiofx/fetchclient";
119
-
120
- type Todo = { userId: number; id: number; title: string; completed: boolean };
121
-
122
- const client = new FetchClient();
123
- const response = await client.getJSON<Todo>(
124
- `https://jsonplaceholder.typicode.com/todos/1`,
125
- {
126
- cacheKey: ["todos", "1"],
127
- cacheDuration: 1000 * 60, // expires in 1 minute
128
- },
129
- );
130
-
131
- // invalidate programmatically
132
- client.cache.delete(["todos", "1"]);
133
- ```
134
-
135
- ### Middleware
136
-
137
- ```ts
138
- import { FetchClient, useMiddleware } from "@foundatiofx/fetchclient";
139
-
140
- type Products = {
141
- products: Array<{ id: number; name: string }>;
142
- };
143
-
144
- useMiddleware(async (ctx, next) => {
145
- console.log("starting request");
146
- await next();
147
- console.log("completed request");
148
- });
149
-
150
- const client = new FetchClient();
151
- const response = await client.getJSON<Products>(
152
- `https://dummyjson.com/products/search?q=iphone&limit=10`,
153
- );
154
- ```
155
-
156
- ### Rate Limiting
157
-
158
- ```ts
159
- import { FetchClient, useRateLimit } from "@foundatiofx/fetchclient";
160
-
161
- // Enable rate limiting globally with 100 requests per minute
162
- useRateLimit({
163
- maxRequests: 100,
164
- windowSeconds: 60,
165
- });
166
-
167
- const client = new FetchClient();
168
- const response = await client.getJSON(
169
- `https://api.example.com/data`,
170
- );
171
- ```
172
-
173
- ### Request Timeout
174
-
175
- ```ts
176
- import { FetchClient } from "@foundatiofx/fetchclient";
177
-
178
- const client = new FetchClient();
179
-
180
- // Set timeout for individual requests
181
- const response = await client.getJSON(
182
- `https://api.example.com/data`,
183
- { timeout: 5000 }, // 5 seconds
184
- );
185
-
186
- // Use AbortSignal for cancellation
187
- const controller = new AbortController();
188
- setTimeout(() => controller.abort(), 1000);
189
-
190
- const response2 = await client.getJSON(
191
- `https://api.example.com/data`,
192
- { signal: controller.signal },
193
- );
194
- ```
195
-
196
- ### Error Handling
197
-
198
- ```ts
199
- import { FetchClient } from "@foundatiofx/fetchclient";
200
-
201
- const client = new FetchClient();
202
-
203
- try {
204
- const response = await client.getJSON(`https://api.example.com/data`);
205
- } catch (error) {
206
- // Handle HTTP errors (4xx, 5xx)
207
- if (error.problem) {
208
- console.log(error.problem.title);
209
- console.log(error.problem.detail);
210
- }
211
- }
212
-
213
- // Or handle specific status codes
214
- const response = await client.getJSON(
215
- `https://api.example.com/data`,
216
- {
217
- expectedStatusCodes: [404, 500],
218
- errorCallback: (response) => {
219
- if (response.status === 404) {
220
- console.log("Resource not found");
221
- return true; // Don't throw
222
- }
223
- },
224
- },
225
- );
226
- ```
227
-
228
- ### Authentication
229
-
230
- ```ts
231
- import { FetchClient, setAccessTokenFunc } from "@foundatiofx/fetchclient";
232
-
233
- // Set global access token function
234
- setAccessTokenFunc(() => localStorage.getItem("token"));
235
-
236
- const client = new FetchClient();
237
- const response = await client.getJSON(`https://api.example.com/data`);
238
- // Automatically adds Authorization: Bearer <token> header
30
+ console.log(data?.products.length);
239
31
  ```
240
32
 
241
- ### Base URL
242
-
243
- ```ts
244
- import { FetchClient, setBaseUrl } from "@foundatiofx/fetchclient";
33
+ ## Documentation
245
34
 
246
- // Set global base URL
247
- setBaseUrl("https://api.example.com");
248
-
249
- const client = new FetchClient();
250
- const response = await client.getJSON(`/users/123`);
251
- // Requests to https://api.example.com/users/123
252
- ```
253
-
254
- ### Loading State
255
-
256
- ```ts
257
- import { FetchClient } from "@foundatiofx/fetchclient";
258
-
259
- const client = new FetchClient();
260
-
261
- // Track loading state
262
- client.loading.on((isLoading) => {
263
- console.log(`Loading: ${isLoading}`);
264
- });
265
-
266
- // Check current loading state
267
- console.log(client.isLoading);
268
- console.log(client.requestCount);
269
- ```
270
-
271
- Also, take a look at the tests:
272
-
273
- [FetchClient Tests](src/FetchClient.test.ts)
274
-
275
- ## Contributing
276
-
277
- Run tests:
278
-
279
- ```shell
280
- deno run test
281
- ```
282
-
283
- Lint code:
284
-
285
- ```shell
286
- deno lint
287
- ```
288
-
289
- Format code:
290
-
291
- ```shell
292
- deno fmt
293
- ```
294
-
295
- Type check code:
296
-
297
- ```shell
298
- deno run check
299
- ```
35
+ - Guide & Examples: <https://fetchclient.foundatio.dev>
36
+ - Getting Started, Usage Examples, Contributing
37
+ - API Reference: <https://jsr.io/@foundatiofx/fetchclient/doc>
300
38
 
301
- ## License
39
+ ---
302
40
 
303
41
  MIT © [Foundatio](https://exceptionless.com)
@@ -251,7 +251,8 @@ class FetchClient {
251
251
  return this.problemToResponse(problem, url);
252
252
  }
253
253
  }
254
- if (init?.body && typeof init.body === "object") {
254
+ if (init?.body && typeof init.body === "object" &&
255
+ !(init.body instanceof FormData)) {
255
256
  init.body = JSON.stringify(init.body);
256
257
  }
257
258
  const accessToken = this.options.accessTokenFunc?.() ?? null;
@@ -422,11 +423,12 @@ class FetchClient {
422
423
  return value;
423
424
  }
424
425
  buildRequestInit(method, body, options) {
425
- const isDefinitelyJsonBody = body !== undefined &&
426
- body !== null &&
427
- typeof body === "object";
426
+ const isFormData = typeof FormData !== "undefined" &&
427
+ body instanceof FormData;
428
+ const isJsonLikeObject = body !== undefined && body !== null &&
429
+ typeof body === "object" && !isFormData;
428
430
  const headers = {};
429
- if (isDefinitelyJsonBody) {
431
+ if (isJsonLikeObject) {
430
432
  headers["Content-Type"] = "application/json";
431
433
  }
432
434
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"FetchClient.d.ts","sourceRoot":"","sources":["../../src/src/FetchClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FetchClient.d.ts","sourceRoot":"","sources":["../../src/src/FetchClient.ts"],"names":[],"mappings":"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"}