@flow-conductor/adapter-superagent 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 ADDED
@@ -0,0 +1,464 @@
1
+ # @flow-conductor/adapter-superagent
2
+
3
+ Superagent adapter for flow-conductor. This adapter uses Superagent for making HTTP requests, providing a fluent API and excellent browser/Node.js support.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @flow-conductor/adapter-superagent @flow-conductor/core superagent
9
+ ```
10
+
11
+ **Note**: Both `@flow-conductor/core` and `superagent` are peer dependencies and must be installed alongside this package.
12
+
13
+ ## Quick Start
14
+
15
+ ```typescript
16
+ import { begin } from "@flow-conductor/core";
17
+ import { SuperagentRequestAdapter } from "@flow-conductor/adapter-superagent";
18
+
19
+ const adapter = new SuperagentRequestAdapter();
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
+ console.log(result.body); // Response body
32
+ console.log(result.status); // HTTP status code
33
+ console.log(result.headers); // Response headers
34
+ ```
35
+
36
+ ## Usage
37
+
38
+ ### Basic GET Request
39
+
40
+ ```typescript
41
+ import { begin } from "@flow-conductor/core";
42
+ import { SuperagentRequestAdapter } from "@flow-conductor/adapter-superagent";
43
+
44
+ const adapter = new SuperagentRequestAdapter();
45
+
46
+ const result = await begin(
47
+ {
48
+ config: {
49
+ url: "https://api.example.com/users/1",
50
+ method: "GET",
51
+ },
52
+ },
53
+ adapter
54
+ ).execute();
55
+
56
+ const user = result.body; // Response body
57
+ console.log(user);
58
+ ```
59
+
60
+ ### POST Request with Data
61
+
62
+ ```typescript
63
+ import { begin } from "@flow-conductor/core";
64
+ import { SuperagentRequestAdapter } from "@flow-conductor/adapter-superagent";
65
+
66
+ const adapter = new SuperagentRequestAdapter();
67
+
68
+ const result = await begin(
69
+ {
70
+ config: {
71
+ url: "https://api.example.com/users",
72
+ method: "POST",
73
+ data: {
74
+ name: "John Doe",
75
+ email: "john@example.com",
76
+ },
77
+ },
78
+ },
79
+ adapter
80
+ ).execute();
81
+
82
+ const newUser = result.body;
83
+ console.log(newUser);
84
+ ```
85
+
86
+ ### Request with Custom Headers
87
+
88
+ ```typescript
89
+ import { begin } from "@flow-conductor/core";
90
+ import { SuperagentRequestAdapter } from "@flow-conductor/adapter-superagent";
91
+
92
+ const adapter = new SuperagentRequestAdapter();
93
+
94
+ const result = await begin(
95
+ {
96
+ config: {
97
+ url: "https://api.example.com/users",
98
+ method: "GET",
99
+ headers: {
100
+ Authorization: "Bearer your-token-here",
101
+ "X-Custom-Header": "value",
102
+ },
103
+ },
104
+ },
105
+ adapter
106
+ ).execute();
107
+ ```
108
+
109
+ ### Chained Requests
110
+
111
+ ```typescript
112
+ import { begin } from "@flow-conductor/core";
113
+ import { SuperagentRequestAdapter } from "@flow-conductor/adapter-superagent";
114
+
115
+ const adapter = new SuperagentRequestAdapter();
116
+
117
+ const result = await begin(
118
+ {
119
+ config: {
120
+ url: "https://api.example.com/users/1",
121
+ method: "GET",
122
+ },
123
+ },
124
+ adapter
125
+ )
126
+ .next({
127
+ config: (previousResult) => {
128
+ const user = previousResult.body;
129
+ return {
130
+ url: `https://api.example.com/users/${user.id}/posts`,
131
+ method: "GET",
132
+ };
133
+ },
134
+ })
135
+ .execute();
136
+
137
+ const posts = result.body;
138
+ console.log(posts);
139
+ ```
140
+
141
+ ## Configuration
142
+
143
+ The `SuperagentRequestAdapter` accepts `IRequestConfig` objects. The adapter automatically:
144
+
145
+ - Handles request data serialization
146
+ - Sets headers appropriately
147
+ - Supports all HTTP methods (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)
148
+
149
+ ### Request Config Interface
150
+
151
+ ```typescript
152
+ interface SuperagentRequestConfig extends IRequestConfig {
153
+ url: string;
154
+ method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS";
155
+ data?: any; // Request body
156
+ headers?: Record<string, string>;
157
+ }
158
+ ```
159
+
160
+ ### Supported HTTP Methods
161
+
162
+ All standard HTTP methods are supported:
163
+
164
+ ```typescript
165
+ // GET
166
+ const getResult = await begin(
167
+ {
168
+ config: {
169
+ url: "https://api.example.com/users",
170
+ method: "GET",
171
+ },
172
+ },
173
+ adapter
174
+ ).execute();
175
+
176
+ // POST
177
+ const postResult = await begin(
178
+ {
179
+ config: {
180
+ url: "https://api.example.com/users",
181
+ method: "POST",
182
+ data: { name: "John" },
183
+ },
184
+ },
185
+ adapter
186
+ ).execute();
187
+
188
+ // PUT
189
+ const putResult = await begin(
190
+ {
191
+ config: {
192
+ url: "https://api.example.com/users/1",
193
+ method: "PUT",
194
+ data: { name: "Jane" },
195
+ },
196
+ },
197
+ adapter
198
+ ).execute();
199
+
200
+ // DELETE
201
+ const deleteResult = await begin(
202
+ {
203
+ config: {
204
+ url: "https://api.example.com/users/1",
205
+ method: "DELETE",
206
+ },
207
+ },
208
+ adapter
209
+ ).execute();
210
+ ```
211
+
212
+ ### Data Handling
213
+
214
+ Superagent automatically handles data serialization:
215
+
216
+ - **Objects**: Automatically JSON stringified
217
+ - **FormData**: Sent as multipart/form-data
218
+ - **URLSearchParams**: Sent as application/x-www-form-urlencoded
219
+ - **Strings**: Sent as-is
220
+
221
+ ```typescript
222
+ // POST with JSON data
223
+ const result = await begin(
224
+ {
225
+ config: {
226
+ url: "https://api.example.com/users",
227
+ method: "POST",
228
+ data: { name: "John", email: "john@example.com" },
229
+ // Content-Type: application/json is automatically set
230
+ },
231
+ },
232
+ adapter
233
+ ).execute();
234
+
235
+ // POST with FormData
236
+ const formData = new FormData();
237
+ formData.append("file", fileBlob);
238
+
239
+ const uploadResult = await begin(
240
+ {
241
+ config: {
242
+ url: "https://api.example.com/upload",
243
+ method: "POST",
244
+ data: formData,
245
+ // Content-Type: multipart/form-data is automatically set
246
+ },
247
+ },
248
+ adapter
249
+ ).execute();
250
+ ```
251
+
252
+ ## Response Handling
253
+
254
+ The adapter returns a Superagent `Response` object with the following properties:
255
+
256
+ ```typescript
257
+ const result = await begin(
258
+ {
259
+ config: {
260
+ url: "https://api.example.com/users",
261
+ method: "GET",
262
+ },
263
+ },
264
+ adapter
265
+ ).execute();
266
+
267
+ // Response properties
268
+ console.log(result.body); // Response body (automatically parsed JSON)
269
+ console.log(result.text); // Response text
270
+ console.log(result.status); // HTTP status code
271
+ console.log(result.headers); // Response headers
272
+ console.log(result.type); // Content-Type
273
+ ```
274
+
275
+ ### Automatic JSON Parsing
276
+
277
+ Superagent automatically parses JSON responses:
278
+
279
+ ```typescript
280
+ const result = await begin(
281
+ {
282
+ config: {
283
+ url: "https://api.example.com/users/1",
284
+ method: "GET",
285
+ },
286
+ },
287
+ adapter
288
+ ).execute();
289
+
290
+ // No need to call .json() - body is already parsed
291
+ const user = result.body; // Already a JavaScript object
292
+ console.log(user.name);
293
+ ```
294
+
295
+ ## Error Handling
296
+
297
+ Superagent throws errors for HTTP error statuses (4xx, 5xx):
298
+
299
+ ```typescript
300
+ import { begin } from "@flow-conductor/core";
301
+ import { SuperagentRequestAdapter } from "@flow-conductor/adapter-superagent";
302
+
303
+ const adapter = new SuperagentRequestAdapter();
304
+
305
+ try {
306
+ const result = await begin(
307
+ {
308
+ config: {
309
+ url: "https://api.example.com/users",
310
+ method: "GET",
311
+ },
312
+ },
313
+ adapter
314
+ )
315
+ .withErrorHandler((error) => {
316
+ console.error("Request failed:", error.message);
317
+ if (error.status) {
318
+ console.error("Status:", error.status);
319
+ console.error("Response:", error.response?.body);
320
+ }
321
+ })
322
+ .execute();
323
+
324
+ const data = result.body;
325
+ console.log(data);
326
+ } catch (error: any) {
327
+ if (error.status) {
328
+ // Handle HTTP errors
329
+ console.error("Status:", error.status);
330
+ console.error("Response:", error.response?.body);
331
+ } else {
332
+ console.error("Error:", error);
333
+ }
334
+ }
335
+ ```
336
+
337
+ ### Error Response Access
338
+
339
+ Superagent provides detailed error information:
340
+
341
+ ```typescript
342
+ try {
343
+ await begin(
344
+ {
345
+ config: {
346
+ url: "https://api.example.com/users",
347
+ method: "GET",
348
+ },
349
+ },
350
+ adapter
351
+ ).execute();
352
+ } catch (error: any) {
353
+ if (error.status) {
354
+ // Server responded with error status
355
+ console.error("Status:", error.status);
356
+ console.error("Body:", error.response?.body);
357
+ console.error("Headers:", error.response?.headers);
358
+ } else {
359
+ // Network or other error
360
+ console.error("Error:", error.message);
361
+ }
362
+ }
363
+ ```
364
+
365
+ ## Examples
366
+
367
+ ### Authentication Flow
368
+
369
+ ```typescript
370
+ import { begin } from "@flow-conductor/core";
371
+ import { SuperagentRequestAdapter } from "@flow-conductor/adapter-superagent";
372
+
373
+ const adapter = new SuperagentRequestAdapter();
374
+
375
+ // Login and use token
376
+ const userData = await begin(
377
+ {
378
+ config: {
379
+ url: "https://api.example.com/auth/login",
380
+ method: "POST",
381
+ data: { username: "user", password: "pass" },
382
+ },
383
+ },
384
+ adapter
385
+ )
386
+ .next({
387
+ config: (previousResult) => {
388
+ const auth = previousResult.body;
389
+ return {
390
+ url: "https://api.example.com/user/profile",
391
+ method: "GET",
392
+ headers: { Authorization: `Bearer ${auth.token}` },
393
+ };
394
+ },
395
+ })
396
+ .execute();
397
+
398
+ const profile = userData.body;
399
+ console.log(profile);
400
+ ```
401
+
402
+ ### File Upload
403
+
404
+ ```typescript
405
+ import { begin } from "@flow-conductor/core";
406
+ import { SuperagentRequestAdapter } from "@flow-conductor/adapter-superagent";
407
+
408
+ const adapter = new SuperagentRequestAdapter();
409
+
410
+ const formData = new FormData();
411
+ formData.append("file", fileBlob);
412
+ formData.append("name", "document.pdf");
413
+
414
+ const result = await begin(
415
+ {
416
+ config: {
417
+ url: "https://api.example.com/upload",
418
+ method: "POST",
419
+ data: formData,
420
+ },
421
+ },
422
+ adapter
423
+ ).execute();
424
+
425
+ console.log(result.body);
426
+ ```
427
+
428
+ ## API Reference
429
+
430
+ ### SuperagentRequestAdapter
431
+
432
+ ```typescript
433
+ class SuperagentRequestAdapter extends RequestAdapter<Response, SuperagentRequestConfig> {
434
+ createRequest(requestConfig: SuperagentRequestConfig): Promise<Response>;
435
+ }
436
+ ```
437
+
438
+ ### SuperagentRequestConfig
439
+
440
+ ```typescript
441
+ type SuperagentRequestConfig = IRequestConfig;
442
+ ```
443
+
444
+ Extends `IRequestConfig` with standard request configuration options.
445
+
446
+ ## Advantages
447
+
448
+ - **Fluent API**: Clean and intuitive request building
449
+ - **Automatic JSON parsing**: No need to call `.json()` on responses
450
+ - **Cross-platform**: Works in both browser and Node.js
451
+ - **Lightweight**: Smaller bundle size compared to some alternatives
452
+ - **Flexible**: Supports various data formats (JSON, FormData, etc.)
453
+
454
+ ## Requirements
455
+
456
+ - `@flow-conductor/core` (peer dependency)
457
+ - `superagent` ^8.0.0 (peer dependency)
458
+ - Node.js 18+
459
+ - TypeScript 5.0+
460
+
461
+ ## License
462
+
463
+ MIT
464
+
@@ -0,0 +1,39 @@
1
+ import { RequestAdapter, IRequestConfig, UrlValidationOptions } from '@flow-conductor/core';
2
+ import { Response } from 'superagent';
3
+
4
+ /**
5
+ * Request configuration type for Superagent adapter.
6
+ * Extends IRequestConfig with Superagent-specific options via the index signature.
7
+ */
8
+ type SuperagentRequestConfig = IRequestConfig & {};
9
+ /**
10
+ * Request adapter implementation using Superagent as the underlying HTTP client.
11
+ * Provides a fluent API for building HTTP requests with Superagent.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const adapter = new SuperagentRequestAdapter();
16
+ * const chain = begin(
17
+ * { config: { url: 'https://api.example.com/users', method: 'GET' } },
18
+ * adapter
19
+ * );
20
+ * ```
21
+ */
22
+ declare class SuperagentRequestAdapter extends RequestAdapter<Response, SuperagentRequestConfig> {
23
+ /**
24
+ * Creates a new SuperagentRequestAdapter instance.
25
+ *
26
+ * @param urlValidationOptions - Optional URL validation options to prevent SSRF attacks
27
+ */
28
+ constructor(urlValidationOptions?: UrlValidationOptions);
29
+ /**
30
+ * Creates and executes an HTTP request using Superagent.
31
+ * Supports all standard HTTP methods and automatically handles headers and body data.
32
+ *
33
+ * @param requestConfig - The request configuration object
34
+ * @returns A promise that resolves to a Superagent Response object
35
+ */
36
+ createRequest(requestConfig: SuperagentRequestConfig): Promise<Response>;
37
+ }
38
+
39
+ export { type SuperagentRequestConfig, SuperagentRequestAdapter as default };
package/build/index.js ADDED
@@ -0,0 +1,62 @@
1
+ import { RequestAdapter } from '@flow-conductor/core';
2
+ import superagent from 'superagent';
3
+
4
+ // src/superagent-request-adapter.ts
5
+ var SuperagentRequestAdapter = class extends RequestAdapter {
6
+ /**
7
+ * Creates a new SuperagentRequestAdapter instance.
8
+ *
9
+ * @param urlValidationOptions - Optional URL validation options to prevent SSRF attacks
10
+ */
11
+ constructor(urlValidationOptions) {
12
+ super(urlValidationOptions);
13
+ }
14
+ /**
15
+ * Creates and executes an HTTP request using Superagent.
16
+ * Supports all standard HTTP methods and automatically handles headers and body data.
17
+ *
18
+ * @param requestConfig - The request configuration object
19
+ * @returns A promise that resolves to a Superagent Response object
20
+ */
21
+ async createRequest(requestConfig) {
22
+ const { url, method, data, headers } = requestConfig;
23
+ let request;
24
+ const methodLower = method.toLowerCase();
25
+ switch (methodLower) {
26
+ case "get":
27
+ request = superagent.get(url);
28
+ break;
29
+ case "post":
30
+ request = superagent.post(url);
31
+ break;
32
+ case "put":
33
+ request = superagent.put(url);
34
+ break;
35
+ case "patch":
36
+ request = superagent.patch(url);
37
+ break;
38
+ case "delete":
39
+ request = superagent.delete(url);
40
+ break;
41
+ case "head":
42
+ request = superagent.head(url);
43
+ break;
44
+ case "options":
45
+ request = superagent.options(url);
46
+ break;
47
+ default:
48
+ request = superagent(methodLower, url);
49
+ }
50
+ if (headers) {
51
+ request.set(headers);
52
+ }
53
+ if (data !== void 0) {
54
+ request.send(data);
55
+ }
56
+ return request;
57
+ }
58
+ };
59
+
60
+ export { SuperagentRequestAdapter as default };
61
+ //# sourceMappingURL=index.js.map
62
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/superagent-request-adapter.ts"],"names":[],"mappings":";;;;AA0BA,IAAqB,wBAAA,GAArB,cAAsD,cAAA,CAGpD;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,EASA,MAAa,cACX,aAAA,EACmB;AACnB,IAAA,MAAM,EAAE,GAAA,EAAK,MAAA,EAAQ,IAAA,EAAM,SAAQ,GAAI,aAAA;AAGvC,IAAA,IAAI,OAAA;AACJ,IAAA,MAAM,WAAA,GAAc,OAAO,WAAA,EAAY;AAEvC,IAAA,QAAQ,WAAA;AAAa,MACnB,KAAK,KAAA;AACH,QAAA,OAAA,GAAU,UAAA,CAAW,IAAI,GAAG,CAAA;AAC5B,QAAA;AAAA,MACF,KAAK,MAAA;AACH,QAAA,OAAA,GAAU,UAAA,CAAW,KAAK,GAAG,CAAA;AAC7B,QAAA;AAAA,MACF,KAAK,KAAA;AACH,QAAA,OAAA,GAAU,UAAA,CAAW,IAAI,GAAG,CAAA;AAC5B,QAAA;AAAA,MACF,KAAK,OAAA;AACH,QAAA,OAAA,GAAU,UAAA,CAAW,MAAM,GAAG,CAAA;AAC9B,QAAA;AAAA,MACF,KAAK,QAAA;AACH,QAAA,OAAA,GAAU,UAAA,CAAW,OAAO,GAAG,CAAA;AAC/B,QAAA;AAAA,MACF,KAAK,MAAA;AACH,QAAA,OAAA,GAAU,UAAA,CAAW,KAAK,GAAG,CAAA;AAC7B,QAAA;AAAA,MACF,KAAK,SAAA;AACH,QAAA,OAAA,GAAU,UAAA,CAAW,QAAQ,GAAG,CAAA;AAChC,QAAA;AAAA,MACF;AACE,QAAA,OAAA,GAAU,UAAA,CAAW,aAAa,GAAG,CAAA;AAAA;AAIzC,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,OAAA,CAAQ,IAAI,OAAiC,CAAA;AAAA,IAC/C;AAGA,IAAA,IAAI,SAAS,MAAA,EAAW;AACtB,MAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AAAA,IACnB;AAEA,IAAA,OAAO,OAAA;AAAA,EACT;AACF","file":"index.js","sourcesContent":["import { RequestAdapter } from \"@flow-conductor/core\";\nimport type {\n IRequestConfig,\n UrlValidationOptions,\n} from \"@flow-conductor/core\";\nimport superagent, { type Response, type Request } from \"superagent\";\n\n/**\n * Request configuration type for Superagent adapter.\n * Extends IRequestConfig with Superagent-specific options via the index signature.\n */\nexport type SuperagentRequestConfig = IRequestConfig & {};\n\n/**\n * Request adapter implementation using Superagent as the underlying HTTP client.\n * Provides a fluent API for building HTTP requests with Superagent.\n *\n * @example\n * ```typescript\n * const adapter = new SuperagentRequestAdapter();\n * const chain = begin(\n * { config: { url: 'https://api.example.com/users', method: 'GET' } },\n * adapter\n * );\n * ```\n */\nexport default class SuperagentRequestAdapter extends RequestAdapter<\n Response,\n SuperagentRequestConfig\n> {\n /**\n * Creates a new SuperagentRequestAdapter 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 Superagent.\n * Supports all standard HTTP methods and automatically handles headers and body data.\n *\n * @param requestConfig - The request configuration object\n * @returns A promise that resolves to a Superagent Response object\n */\n public async createRequest(\n requestConfig: SuperagentRequestConfig\n ): Promise<Response> {\n const { url, method, data, headers } = requestConfig;\n\n // Create the request based on method\n let request: Request;\n const methodLower = method.toLowerCase();\n\n switch (methodLower) {\n case \"get\":\n request = superagent.get(url);\n break;\n case \"post\":\n request = superagent.post(url);\n break;\n case \"put\":\n request = superagent.put(url);\n break;\n case \"patch\":\n request = superagent.patch(url);\n break;\n case \"delete\":\n request = superagent.delete(url);\n break;\n case \"head\":\n request = superagent.head(url);\n break;\n case \"options\":\n request = superagent.options(url);\n break;\n default:\n request = superagent(methodLower, url);\n }\n\n // Set headers if provided\n if (headers) {\n request.set(headers as Record<string, string>);\n }\n\n // Set data/body if provided\n if (data !== undefined) {\n request.send(data);\n }\n\n return request;\n }\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@flow-conductor/adapter-superagent",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "Superagent 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
+ "superagent",
26
+ "http",
27
+ "typescript"
28
+ ],
29
+ "scripts": {
30
+ "test": "node --test --import tsx/esm 'src/__test__/**/*.test.ts'",
31
+ "test:watch": "node --test --import tsx/esm --watch 'src/__test__/**/*.test.ts'",
32
+ "build": "tsup",
33
+ "clean": "rm -rf build",
34
+ "lint": "eslint src --ext .ts",
35
+ "lint:fix": "eslint src --ext .ts --fix",
36
+ "type-check": "tsc --noEmit",
37
+ "prepublishOnly": "npm run clean && npm run lint && npm run type-check && npm run build"
38
+ },
39
+ "author": "Dawid Hermann",
40
+ "license": "MIT",
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/dawidhermann/flow-conductor.git",
44
+ "directory": "packages/adapter-superagent"
45
+ },
46
+ "sideEffects": false,
47
+ "publishConfig": {
48
+ "access": "public"
49
+ },
50
+ "engines": {
51
+ "node": ">=18.0.0"
52
+ },
53
+ "peerDependencies": {
54
+ "@flow-conductor/core": "^1.0.0",
55
+ "superagent": "^8.0.0"
56
+ },
57
+ "devDependencies": {
58
+ "@eslint/js": "^9.39.2",
59
+ "@flow-conductor/core": "*",
60
+ "@types/superagent": "^4.1.16",
61
+ "@typescript-eslint/eslint-plugin": "^8.50.1",
62
+ "@typescript-eslint/parser": "^8.50.1",
63
+ "eslint": "^9.39.2",
64
+ "eslint-config-prettier": "^10.1.8",
65
+ "eslint-plugin-prettier": "^5.5.4",
66
+ "prettier": "^3.7.4",
67
+ "superagent": "^8.1.2",
68
+ "tsx": "^4.7.0",
69
+ "typescript": "^5.9.3",
70
+ "typescript-eslint": "^8.50.1"
71
+ }
72
+ }