@flow-conductor/adapter-fetch 1.0.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 +422 -0
- package/build/index.d.ts +38 -0
- package/build/index.js +36 -0
- package/build/index.js.map +1 -0
- package/package.json +67 -0
package/README.md
ADDED
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
# @flow-conductor/adapter-fetch
|
|
2
|
+
|
|
3
|
+
Fetch API adapter for flow-conductor. This adapter uses the native Fetch API available in Node.js 18+ and modern browsers.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @flow-conductor/adapter-fetch @flow-conductor/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Note**: `@flow-conductor/core` is a peer dependency and must be installed alongside this package.
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { begin } from "@flow-conductor/core";
|
|
17
|
+
import { FetchRequestAdapter } from "@flow-conductor/adapter-fetch";
|
|
18
|
+
|
|
19
|
+
const adapter = new FetchRequestAdapter();
|
|
20
|
+
|
|
21
|
+
const result = await begin(
|
|
22
|
+
{
|
|
23
|
+
config: {
|
|
24
|
+
url: "https://api.example.com/users",
|
|
25
|
+
method: "GET",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
adapter
|
|
29
|
+
).execute();
|
|
30
|
+
|
|
31
|
+
const data = await result.json();
|
|
32
|
+
console.log(data);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
### Basic GET Request
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { begin } from "@flow-conductor/core";
|
|
41
|
+
import { FetchRequestAdapter } from "@flow-conductor/adapter-fetch";
|
|
42
|
+
|
|
43
|
+
const adapter = new FetchRequestAdapter();
|
|
44
|
+
|
|
45
|
+
const result = await begin(
|
|
46
|
+
{
|
|
47
|
+
config: {
|
|
48
|
+
url: "https://api.example.com/users/1",
|
|
49
|
+
method: "GET",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
adapter
|
|
53
|
+
).execute();
|
|
54
|
+
|
|
55
|
+
const user = await result.json();
|
|
56
|
+
console.log(user);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### POST Request with Data
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { begin } from "@flow-conductor/core";
|
|
63
|
+
import { FetchRequestAdapter } from "@flow-conductor/adapter-fetch";
|
|
64
|
+
|
|
65
|
+
const adapter = new FetchRequestAdapter();
|
|
66
|
+
|
|
67
|
+
const result = await begin(
|
|
68
|
+
{
|
|
69
|
+
config: {
|
|
70
|
+
url: "https://api.example.com/users",
|
|
71
|
+
method: "POST",
|
|
72
|
+
data: {
|
|
73
|
+
name: "John Doe",
|
|
74
|
+
email: "john@example.com",
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
adapter
|
|
79
|
+
).execute();
|
|
80
|
+
|
|
81
|
+
const newUser = await result.json();
|
|
82
|
+
console.log(newUser);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Request with Custom Headers
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { begin } from "@flow-conductor/core";
|
|
89
|
+
import { FetchRequestAdapter } from "@flow-conductor/adapter-fetch";
|
|
90
|
+
|
|
91
|
+
const adapter = new FetchRequestAdapter();
|
|
92
|
+
|
|
93
|
+
const result = await begin(
|
|
94
|
+
{
|
|
95
|
+
config: {
|
|
96
|
+
url: "https://api.example.com/users",
|
|
97
|
+
method: "GET",
|
|
98
|
+
headers: {
|
|
99
|
+
Authorization: "Bearer your-token-here",
|
|
100
|
+
"X-Custom-Header": "value",
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
adapter
|
|
105
|
+
).execute();
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Chained Requests
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
import { begin } from "@flow-conductor/core";
|
|
112
|
+
import { FetchRequestAdapter } from "@flow-conductor/adapter-fetch";
|
|
113
|
+
|
|
114
|
+
const adapter = new FetchRequestAdapter();
|
|
115
|
+
|
|
116
|
+
const result = await begin(
|
|
117
|
+
{
|
|
118
|
+
config: {
|
|
119
|
+
url: "https://api.example.com/users/1",
|
|
120
|
+
method: "GET",
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
adapter
|
|
124
|
+
)
|
|
125
|
+
.next({
|
|
126
|
+
config: async (previousResult) => {
|
|
127
|
+
const user = await previousResult.json();
|
|
128
|
+
return {
|
|
129
|
+
url: `https://api.example.com/users/${user.id}/posts`,
|
|
130
|
+
method: "GET",
|
|
131
|
+
};
|
|
132
|
+
},
|
|
133
|
+
})
|
|
134
|
+
.execute();
|
|
135
|
+
|
|
136
|
+
const posts = await result.json();
|
|
137
|
+
console.log(posts);
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Configuration
|
|
141
|
+
|
|
142
|
+
The `FetchRequestAdapter` accepts standard `IRequestConfig` objects compatible with the Fetch API. The adapter automatically:
|
|
143
|
+
|
|
144
|
+
- JSON stringifies `data` for non-GET requests
|
|
145
|
+
- Sets `Content-Type: application/json` header when data is provided
|
|
146
|
+
- Passes through all other Fetch API options
|
|
147
|
+
|
|
148
|
+
### Request Config Interface
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
interface FetchRequestConfig extends IRequestConfig {
|
|
152
|
+
url: string;
|
|
153
|
+
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS";
|
|
154
|
+
data?: any; // Will be JSON stringified for non-GET requests
|
|
155
|
+
headers?: Record<string, string>;
|
|
156
|
+
// ... other fetch options (credentials, cache, mode, etc.)
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Supported Fetch Options
|
|
161
|
+
|
|
162
|
+
All standard Fetch API options are supported:
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const result = await begin(
|
|
166
|
+
{
|
|
167
|
+
config: {
|
|
168
|
+
url: "https://api.example.com/users",
|
|
169
|
+
method: "GET",
|
|
170
|
+
headers: {
|
|
171
|
+
"Authorization": "Bearer token",
|
|
172
|
+
},
|
|
173
|
+
credentials: "include", // Include cookies
|
|
174
|
+
cache: "no-cache", // Cache control
|
|
175
|
+
mode: "cors", // CORS mode
|
|
176
|
+
redirect: "follow", // Redirect handling
|
|
177
|
+
// ... any other RequestInit options
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
adapter
|
|
181
|
+
).execute();
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Data Handling
|
|
185
|
+
|
|
186
|
+
The adapter automatically handles data serialization:
|
|
187
|
+
|
|
188
|
+
- **GET requests**: Data is ignored (use query parameters in URL instead)
|
|
189
|
+
- **Other methods**: Data is JSON stringified and sent as the request body
|
|
190
|
+
- **Content-Type**: Automatically set to `application/json` when data is provided
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
// POST with JSON data
|
|
194
|
+
const result = await begin(
|
|
195
|
+
{
|
|
196
|
+
config: {
|
|
197
|
+
url: "https://api.example.com/users",
|
|
198
|
+
method: "POST",
|
|
199
|
+
data: { name: "John", email: "john@example.com" },
|
|
200
|
+
// Content-Type: application/json is automatically added
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
adapter
|
|
204
|
+
).execute();
|
|
205
|
+
|
|
206
|
+
// PUT with JSON data
|
|
207
|
+
const updateResult = await begin(
|
|
208
|
+
{
|
|
209
|
+
config: {
|
|
210
|
+
url: "https://api.example.com/users/1",
|
|
211
|
+
method: "PUT",
|
|
212
|
+
data: { name: "Jane" },
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
adapter
|
|
216
|
+
).execute();
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Custom Headers
|
|
220
|
+
|
|
221
|
+
You can provide custom headers, which will be merged with default headers:
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
const result = await begin(
|
|
225
|
+
{
|
|
226
|
+
config: {
|
|
227
|
+
url: "https://api.example.com/users",
|
|
228
|
+
method: "POST",
|
|
229
|
+
data: { name: "John" },
|
|
230
|
+
headers: {
|
|
231
|
+
"Authorization": "Bearer token",
|
|
232
|
+
"X-Custom-Header": "value",
|
|
233
|
+
// Content-Type will be automatically added if not specified
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
adapter
|
|
238
|
+
).execute();
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Response Handling
|
|
242
|
+
|
|
243
|
+
The adapter returns a standard `Response` object from the Fetch API. You can use all standard Response methods:
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
const result = await begin(
|
|
247
|
+
{
|
|
248
|
+
config: {
|
|
249
|
+
url: "https://api.example.com/users",
|
|
250
|
+
method: "GET",
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
adapter
|
|
254
|
+
).execute();
|
|
255
|
+
|
|
256
|
+
// Standard Response methods
|
|
257
|
+
const json = await result.json();
|
|
258
|
+
const text = await result.text();
|
|
259
|
+
const blob = await result.blob();
|
|
260
|
+
const arrayBuffer = await result.arrayBuffer();
|
|
261
|
+
|
|
262
|
+
// Response properties
|
|
263
|
+
console.log(result.status); // HTTP status code
|
|
264
|
+
console.log(result.statusText); // Status text
|
|
265
|
+
console.log(result.ok); // true if status 200-299
|
|
266
|
+
console.log(result.headers); // Headers object
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Error Handling
|
|
270
|
+
|
|
271
|
+
The Fetch API only rejects on network errors, not HTTP error statuses. You may want to check the response status:
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
import { begin } from "@flow-conductor/core";
|
|
275
|
+
import { FetchRequestAdapter } from "@flow-conductor/adapter-fetch";
|
|
276
|
+
|
|
277
|
+
const adapter = new FetchRequestAdapter();
|
|
278
|
+
|
|
279
|
+
try {
|
|
280
|
+
const result = await begin(
|
|
281
|
+
{
|
|
282
|
+
config: {
|
|
283
|
+
url: "https://api.example.com/users",
|
|
284
|
+
method: "GET",
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
adapter
|
|
288
|
+
)
|
|
289
|
+
.withErrorHandler((error) => {
|
|
290
|
+
console.error("Request failed:", error);
|
|
291
|
+
})
|
|
292
|
+
.execute();
|
|
293
|
+
|
|
294
|
+
if (!result.ok) {
|
|
295
|
+
throw new Error(`HTTP error! status: ${result.status}`);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const data = await result.json();
|
|
299
|
+
console.log(data);
|
|
300
|
+
} catch (error) {
|
|
301
|
+
console.error("Error:", error);
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## Browser vs Node.js
|
|
306
|
+
|
|
307
|
+
### Browser
|
|
308
|
+
|
|
309
|
+
The Fetch API is natively available in modern browsers. No additional setup needed.
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
// Works in browsers with native fetch support
|
|
313
|
+
import { FetchRequestAdapter } from "@flow-conductor/adapter-fetch";
|
|
314
|
+
const adapter = new FetchRequestAdapter();
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Node.js
|
|
318
|
+
|
|
319
|
+
Node.js 18+ includes native Fetch API support. For older versions, you may need a polyfill:
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
// Node.js 18+
|
|
323
|
+
import { FetchRequestAdapter } from "@flow-conductor/adapter-fetch";
|
|
324
|
+
const adapter = new FetchRequestAdapter();
|
|
325
|
+
|
|
326
|
+
// Node.js < 18 (requires polyfill)
|
|
327
|
+
import fetch from "node-fetch";
|
|
328
|
+
import { FetchRequestAdapter } from "@flow-conductor/adapter-fetch";
|
|
329
|
+
|
|
330
|
+
// Note: You may need to configure the adapter to use the polyfill
|
|
331
|
+
// or use a different adapter implementation
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## Examples
|
|
335
|
+
|
|
336
|
+
### Authentication Flow
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
import { begin } from "@flow-conductor/core";
|
|
340
|
+
import { FetchRequestAdapter } from "@flow-conductor/adapter-fetch";
|
|
341
|
+
|
|
342
|
+
const adapter = new FetchRequestAdapter();
|
|
343
|
+
|
|
344
|
+
// Login and use token
|
|
345
|
+
const userData = await begin(
|
|
346
|
+
{
|
|
347
|
+
config: {
|
|
348
|
+
url: "https://api.example.com/auth/login",
|
|
349
|
+
method: "POST",
|
|
350
|
+
data: { username: "user", password: "pass" },
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
adapter
|
|
354
|
+
)
|
|
355
|
+
.next({
|
|
356
|
+
config: async (previousResult) => {
|
|
357
|
+
const auth = await previousResult.json();
|
|
358
|
+
return {
|
|
359
|
+
url: "https://api.example.com/user/profile",
|
|
360
|
+
method: "GET",
|
|
361
|
+
headers: { Authorization: `Bearer ${auth.token}` },
|
|
362
|
+
};
|
|
363
|
+
},
|
|
364
|
+
})
|
|
365
|
+
.execute();
|
|
366
|
+
|
|
367
|
+
const profile = await userData.json();
|
|
368
|
+
console.log(profile);
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### File Upload
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
import { begin } from "@flow-conductor/core";
|
|
375
|
+
import { FetchRequestAdapter } from "@flow-conductor/adapter-fetch";
|
|
376
|
+
|
|
377
|
+
const adapter = new FetchRequestAdapter();
|
|
378
|
+
|
|
379
|
+
// Note: For file uploads, you may need to customize the adapter
|
|
380
|
+
// to handle FormData instead of JSON
|
|
381
|
+
const result = await begin(
|
|
382
|
+
{
|
|
383
|
+
config: {
|
|
384
|
+
url: "https://api.example.com/upload",
|
|
385
|
+
method: "POST",
|
|
386
|
+
data: formData, // FormData object
|
|
387
|
+
headers: {
|
|
388
|
+
// Don't set Content-Type, let browser set it with boundary
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
adapter
|
|
393
|
+
).execute();
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
## API Reference
|
|
397
|
+
|
|
398
|
+
### FetchRequestAdapter
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
class FetchRequestAdapter extends RequestAdapter<Response, FetchRequestConfig> {
|
|
402
|
+
createRequest(requestConfig: IRequestConfig): Promise<Response>;
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### FetchRequestConfig
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
type FetchRequestConfig = IRequestConfig;
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
Extends `IRequestConfig` with all standard Fetch API options.
|
|
413
|
+
|
|
414
|
+
## Requirements
|
|
415
|
+
|
|
416
|
+
- `@flow-conductor/core` (peer dependency)
|
|
417
|
+
- Node.js 18+ (for native Fetch API) or a Fetch polyfill
|
|
418
|
+
- TypeScript 5.0+
|
|
419
|
+
|
|
420
|
+
## License
|
|
421
|
+
|
|
422
|
+
MIT
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { RequestAdapter, IRequestConfig, UrlValidationOptions } from '@flow-conductor/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Request configuration type for Fetch adapter.
|
|
5
|
+
* Extends IRequestConfig with fetch-specific options via the index signature.
|
|
6
|
+
*/
|
|
7
|
+
type FetchRequestConfig = IRequestConfig;
|
|
8
|
+
/**
|
|
9
|
+
* Request adapter implementation using the native Fetch API.
|
|
10
|
+
* Provides a lightweight, dependency-free HTTP client adapter.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const adapter = new FetchRequestAdapter();
|
|
15
|
+
* const chain = begin(
|
|
16
|
+
* { config: { url: 'https://api.example.com/users', method: 'GET' } },
|
|
17
|
+
* adapter
|
|
18
|
+
* );
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
declare class FetchRequestAdapter extends RequestAdapter<Response, FetchRequestConfig> {
|
|
22
|
+
/**
|
|
23
|
+
* Creates a new FetchRequestAdapter instance.
|
|
24
|
+
*
|
|
25
|
+
* @param urlValidationOptions - Optional URL validation options to prevent SSRF attacks
|
|
26
|
+
*/
|
|
27
|
+
constructor(urlValidationOptions?: UrlValidationOptions);
|
|
28
|
+
/**
|
|
29
|
+
* Creates and executes an HTTP request using the Fetch API.
|
|
30
|
+
* Automatically handles JSON serialization for request bodies.
|
|
31
|
+
*
|
|
32
|
+
* @param requestConfig - The request configuration object
|
|
33
|
+
* @returns A promise that resolves to a Response object
|
|
34
|
+
*/
|
|
35
|
+
createRequest(requestConfig: IRequestConfig): Promise<Response>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { type FetchRequestConfig, FetchRequestAdapter as default };
|
package/build/index.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { RequestAdapter } from '@flow-conductor/core';
|
|
2
|
+
|
|
3
|
+
// src/fetch-request-adapter.ts
|
|
4
|
+
var FetchRequestAdapter = class extends RequestAdapter {
|
|
5
|
+
/**
|
|
6
|
+
* Creates a new FetchRequestAdapter instance.
|
|
7
|
+
*
|
|
8
|
+
* @param urlValidationOptions - Optional URL validation options to prevent SSRF attacks
|
|
9
|
+
*/
|
|
10
|
+
constructor(urlValidationOptions) {
|
|
11
|
+
super(urlValidationOptions);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Creates and executes an HTTP request using the Fetch API.
|
|
15
|
+
* Automatically handles JSON serialization for request bodies.
|
|
16
|
+
*
|
|
17
|
+
* @param requestConfig - The request configuration object
|
|
18
|
+
* @returns A promise that resolves to a Response object
|
|
19
|
+
*/
|
|
20
|
+
createRequest(requestConfig) {
|
|
21
|
+
const { data, url, ...rest } = requestConfig;
|
|
22
|
+
const fetchConfig = { ...rest };
|
|
23
|
+
if (data) {
|
|
24
|
+
fetchConfig.body = typeof data === "string" ? data : JSON.stringify(data);
|
|
25
|
+
fetchConfig.headers = {
|
|
26
|
+
"Content-Type": "application/json",
|
|
27
|
+
...fetchConfig.headers
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return fetch(url, fetchConfig);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export { FetchRequestAdapter as default };
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
36
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/fetch-request-adapter.ts"],"names":[],"mappings":";;;AAyBA,IAAqB,mBAAA,GAArB,cAAiD,cAAA,CAG/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,oBAAA,EAA6C;AACvD,IAAA,KAAA,CAAM,oBAAoB,CAAA;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,cAAc,aAAA,EAAkD;AACrE,IAAA,MAAM,EAAE,IAAA,EAAM,GAAA,EAAK,GAAG,MAAK,GAAI,aAAA;AAC/B,IAAA,MAAM,WAAA,GAA2B,EAAE,GAAG,IAAA,EAAK;AAC3C,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,WAAA,CAAY,OAAO,OAAO,IAAA,KAAS,WAAW,IAAA,GAAO,IAAA,CAAK,UAAU,IAAI,CAAA;AACxE,MAAA,WAAA,CAAY,OAAA,GAAU;AAAA,QACpB,cAAA,EAAgB,kBAAA;AAAA,QAChB,GAAI,WAAA,CAAY;AAAA,OAClB;AAAA,IACF;AACA,IAAA,OAAO,KAAA,CAAM,KAAK,WAAW,CAAA;AAAA,EAC/B;AACF","file":"index.js","sourcesContent":["import { RequestAdapter } from \"@flow-conductor/core\";\nimport type {\n IRequestConfig,\n UrlValidationOptions,\n} from \"@flow-conductor/core\";\n\n/**\n * Request configuration type for Fetch adapter.\n * Extends IRequestConfig with fetch-specific options via the index signature.\n */\nexport type FetchRequestConfig = IRequestConfig;\n\n/**\n * Request adapter implementation using the native Fetch API.\n * Provides a lightweight, dependency-free HTTP client adapter.\n *\n * @example\n * ```typescript\n * const adapter = new FetchRequestAdapter();\n * const chain = begin(\n * { config: { url: 'https://api.example.com/users', method: 'GET' } },\n * adapter\n * );\n * ```\n */\nexport default class FetchRequestAdapter extends RequestAdapter<\n Response,\n FetchRequestConfig\n> {\n /**\n * Creates a new FetchRequestAdapter instance.\n *\n * @param urlValidationOptions - Optional URL validation options to prevent SSRF attacks\n */\n constructor(urlValidationOptions?: UrlValidationOptions) {\n super(urlValidationOptions);\n }\n\n /**\n * Creates and executes an HTTP request using the Fetch API.\n * Automatically handles JSON serialization for request bodies.\n *\n * @param requestConfig - The request configuration object\n * @returns A promise that resolves to a Response object\n */\n public createRequest(requestConfig: IRequestConfig): Promise<Response> {\n const { data, url, ...rest } = requestConfig;\n const fetchConfig: RequestInit = { ...rest };\n if (data) {\n fetchConfig.body = typeof data === \"string\" ? data : JSON.stringify(data);\n fetchConfig.headers = {\n \"Content-Type\": \"application/json\",\n ...(fetchConfig.headers as Record<string, string>),\n };\n }\n return fetch(url, fetchConfig);\n }\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@flow-conductor/adapter-fetch",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Fetch API adapter for flow-conductor",
|
|
6
|
+
"main": "./build/index.js",
|
|
7
|
+
"types": "./build/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./build/index.d.ts",
|
|
11
|
+
"import": "./build/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"build/**/*.js",
|
|
16
|
+
"build/**/*.d.ts",
|
|
17
|
+
"build/**/*.js.map",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"keywords": [
|
|
22
|
+
"flow-conductor",
|
|
23
|
+
"request",
|
|
24
|
+
"adapter",
|
|
25
|
+
"fetch",
|
|
26
|
+
"http",
|
|
27
|
+
"typescript"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"test": "echo \"No tests specified\" && exit 0",
|
|
31
|
+
"build": "tsup",
|
|
32
|
+
"clean": "rm -rf build",
|
|
33
|
+
"lint": "eslint src --ext .ts",
|
|
34
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
35
|
+
"type-check": "tsc --noEmit",
|
|
36
|
+
"prepublishOnly": "npm run clean && npm run lint && npm run type-check && npm run build"
|
|
37
|
+
},
|
|
38
|
+
"author": "Dawid Hermann",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "https://github.com/dawidhermann/flow-conductor.git",
|
|
43
|
+
"directory": "packages/adapter-fetch"
|
|
44
|
+
},
|
|
45
|
+
"sideEffects": false,
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=18.0.0"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"@flow-conductor/core": "^1.0.0"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@eslint/js": "^9.39.2",
|
|
57
|
+
"@flow-conductor/core": "*",
|
|
58
|
+
"@typescript-eslint/eslint-plugin": "^8.50.1",
|
|
59
|
+
"@typescript-eslint/parser": "^8.50.1",
|
|
60
|
+
"eslint": "^9.39.2",
|
|
61
|
+
"eslint-config-prettier": "^10.1.8",
|
|
62
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
63
|
+
"prettier": "^3.7.4",
|
|
64
|
+
"typescript": "^5.9.3",
|
|
65
|
+
"typescript-eslint": "^8.50.1"
|
|
66
|
+
}
|
|
67
|
+
}
|