accessio 1.1.2 → 1.3.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.
Files changed (40) hide show
  1. package/README.md +109 -14
  2. package/cjs/accessio.cjs +59 -3
  3. package/cjs/accessio.cjs.map +1 -1
  4. package/cjs/core/accessioError.cjs +28 -3
  5. package/cjs/core/accessioError.cjs.map +1 -1
  6. package/cjs/core/buildURL.cjs +15 -1
  7. package/cjs/core/buildURL.cjs.map +1 -1
  8. package/cjs/core/fetchAdapter.cjs +54 -10
  9. package/cjs/core/fetchAdapter.cjs.map +1 -1
  10. package/cjs/core/request.cjs +107 -31
  11. package/cjs/core/request.cjs.map +1 -1
  12. package/cjs/core/retry.cjs +48 -4
  13. package/cjs/core/retry.cjs.map +1 -1
  14. package/cjs/helpers/flattenHeaders.cjs +37 -0
  15. package/cjs/helpers/flattenHeaders.cjs.map +1 -1
  16. package/cjs/helpers/memoryCache.cjs +51 -0
  17. package/cjs/helpers/memoryCache.cjs.map +1 -0
  18. package/cjs/helpers/rateLimiter.cjs +11 -22
  19. package/cjs/helpers/rateLimiter.cjs.map +1 -1
  20. package/cjs/helpers/toFormData.cjs +50 -0
  21. package/cjs/helpers/toFormData.cjs.map +1 -0
  22. package/cjs/helpers/transformData.cjs +2 -2
  23. package/cjs/helpers/transformData.cjs.map +1 -1
  24. package/cjs/index.cjs +4 -1
  25. package/cjs/index.cjs.map +1 -1
  26. package/index.d.ts +7 -0
  27. package/package.json +3 -2
  28. package/src/accessio.ts +81 -3
  29. package/src/core/accessioError.ts +26 -1
  30. package/src/core/buildURL.ts +16 -1
  31. package/src/core/fetchAdapter.ts +62 -10
  32. package/src/core/request.ts +134 -44
  33. package/src/core/retry.ts +44 -6
  34. package/src/helpers/flattenHeaders.ts +30 -0
  35. package/src/helpers/memoryCache.ts +30 -0
  36. package/src/helpers/rateLimiter.ts +11 -24
  37. package/src/helpers/toFormData.ts +25 -0
  38. package/src/helpers/transformData.ts +2 -1
  39. package/src/index.ts +4 -1
  40. package/src/types.ts +27 -0
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Fast, flexible HTTP client — simple, modular, and dependency-free.**
4
4
 
5
- `accessio` is a lightweight, modern HTTP client built on top of the native `fetch` API. It provides a familiar, Promise-based interface with advanced features like interceptors, automatic retries, rate limiting, and structured debug logging, all while maintaining **zero external dependencies**.
5
+ `Accessio` is a lightweight, modern HTTP client built on top of the native `fetch` API. It provides a familiar, Promise-based interface with advanced features like interceptors, automatic retries, rate limiting, and structured debug logging, all while maintaining **zero external dependencies**.
6
6
 
7
7
  ---
8
8
 
@@ -22,6 +22,12 @@
22
22
  - 🚥 **Rate Limiter** — built-in concurrency control for high-throughput applications
23
23
  - 🐞 **Debug Mode** — structured, beautiful console logging for easy development
24
24
  - ⏱️ **Duration Tracking** — every response includes precise timing metadata
25
+ - 🧬 **GraphQL Support** — built-in `gql` method for easy querying
26
+ - 📡 **SSE Streaming** — async iterators for Server-Sent Events via `stream`
27
+ - 📚 **Auto-Pagination** — seamlessly iterate through paginated APIs via `autoPaginate`
28
+ - 🛡️ **Schema Validation** — validate responses automatically using Zod or custom schemas
29
+ - 🗂️ **Caching & Deduplication** — prevent redundant requests and cache responses
30
+ - 🪝 **Lifecycle Hooks** — simple hooks for request/response/error events
25
31
 
26
32
  ---
27
33
 
@@ -63,17 +69,22 @@ console.log(`User created in ${response.duration}ms`);
63
69
 
64
70
  ### Request Methods
65
71
 
66
- | Method | Description |
67
- | :--------------------------------------- | :-------------------------------------- |
68
- | `accessio(config)` | Generic request using config object |
69
- | `accessio.get(url, config?)` | GET request |
70
- | `accessio.post(url, data?, config?)` | POST request |
71
- | `accessio.put(url, data?, config?)` | PUT request |
72
- | `accessio.patch(url, data?, config?)` | PATCH request |
73
- | `accessio.delete(url, config?)` | DELETE request |
74
- | `accessio.head(url, config?)` | HEAD request |
75
- | `accessio.options(url, config?)` | OPTIONS request |
76
- | `accessio.postForm(url, data?, config?)` | POST request with `multipart/form-data` |
72
+ | Method | Description |
73
+ | :----------------------------------------- | :--------------------------------------- |
74
+ | `accessio(config)` | Generic request using config object |
75
+ | `accessio.get(url, config?)` | GET request |
76
+ | `accessio.post(url, data?, config?)` | POST request |
77
+ | `accessio.put(url, data?, config?)` | PUT request |
78
+ | `accessio.patch(url, data?, config?)` | PATCH request |
79
+ | `accessio.delete(url, config?)` | DELETE request |
80
+ | `accessio.head(url, config?)` | HEAD request |
81
+ | `accessio.options(url, config?)` | OPTIONS request |
82
+ | `accessio.postForm(url, data?, config?)` | POST request with `multipart/form-data` |
83
+ | `accessio.putForm(url, data?, config?)` | PUT request with `multipart/form-data` |
84
+ | `accessio.patchForm(url, data?, config?)` | PATCH request with `multipart/form-data` |
85
+ | `accessio.stream(url, config?)` | Server-Sent Events (SSE) streaming |
86
+ | `accessio.autoPaginate(url, config?)` | Async iterator for paginated endpoints |
87
+ | `accessio.gql(url, query, vars?, config?)` | GraphQL query/mutation wrapper |
77
88
 
78
89
  ### Configuration Options
79
90
 
@@ -94,6 +105,17 @@ console.log(`User created in ${response.duration}ms`);
94
105
  rateLimiter: limiter, // Concurrency limiter instance
95
106
  validateStatus: (s) => s < 400, // Resolve/reject predicate
96
107
  signal: abortController.signal, // Custom AbortSignal
108
+ dedupe: true, // Prevent duplicate in-flight requests
109
+ cache: true, // Cache responses (boolean or CacheProvider)
110
+ cacheTTL: 60000, // Cache time-to-live in ms
111
+ schema: z.object({...}), // Schema validator (e.g., Zod)
112
+ fetch: customFetch, // Custom fetch implementation
113
+ retryOn429: true, // Automatically retry on rate limits
114
+ hooks: { // Lifecycle hooks
115
+ onBeforeRequest: (config) => {},
116
+ onRequestResponse: (response) => {},
117
+ onRequestError: (error) => {}
118
+ }
97
119
  }
98
120
  ```
99
121
 
@@ -124,7 +146,7 @@ accessio.interceptors.response.use(
124
146
 
125
147
  ### Error Handling
126
148
 
127
- `accessio` provides a structured error object with specific codes to help you handle failures gracefully.
149
+ `Accessio` provides a structured error object with specific codes to help you handle failures gracefully.
128
150
 
129
151
  | Code | Description |
130
152
  | :----------------- | :---------------------------- |
@@ -138,7 +160,7 @@ accessio.interceptors.response.use(
138
160
 
139
161
  ### Automatic Retries
140
162
 
141
- `accessio` includes a powerful retry mechanism that handles network errors and 5xx responses automatically.
163
+ `Accessio` includes a powerful retry mechanism that handles network errors and 5xx responses automatically.
142
164
 
143
165
  ```typescript
144
166
  const response = await accessio.get('/flaky-endpoint', {
@@ -178,6 +200,79 @@ Get beautiful, structured logs in your console by enabling `debug: true`.
178
200
  // Size: ~3.2 KB
179
201
  ```
180
202
 
203
+ ### Caching & Deduplication
204
+
205
+ Prevent duplicate requests and cache responses to improve performance.
206
+
207
+ ```typescript
208
+ const api = accessio.create({
209
+ dedupe: true, // Prevents identical requests while one is pending
210
+ cache: true, // Caches responses in memory
211
+ cacheTTL: 5 * 60 * 1000, // Cache for 5 minutes
212
+ });
213
+ ```
214
+
215
+ ### Schema Validation
216
+
217
+ Automatically parse and validate responses using libraries like Zod.
218
+
219
+ ```typescript
220
+ import { z } from 'zod';
221
+
222
+ const userSchema = z.object({ id: z.number(), name: z.string() });
223
+
224
+ const response = await accessio.get('/user/1', { schema: userSchema });
225
+ // response.data is strictly typed and validated against userSchema
226
+ ```
227
+
228
+ ### Server-Sent Events (SSE)
229
+
230
+ Easily consume SSE streams using async iterators.
231
+
232
+ ```typescript
233
+ for await (const chunk of accessio.stream('/stream')) {
234
+ console.log(chunk); // Parsed JSON or string data from SSE
235
+ }
236
+ ```
237
+
238
+ ### Auto-Pagination
239
+
240
+ Iterate through paginated endpoints effortlessly.
241
+
242
+ ```typescript
243
+ for await (const user of accessio.autoPaginate('/users')) {
244
+ console.log(user); // Automatically fetches the next page when needed
245
+ }
246
+ ```
247
+
248
+ ### GraphQL
249
+
250
+ Send GraphQL queries and mutations with ease.
251
+
252
+ ```typescript
253
+ const query = `
254
+ query GetUser($id: ID!) {
255
+ user(id: $id) { name, email }
256
+ }
257
+ `;
258
+
259
+ const response = await accessio.gql('/graphql', query, { id: '1' });
260
+ ```
261
+
262
+ ### Lifecycle Hooks
263
+
264
+ Use hooks for simple global or request-specific event handling.
265
+
266
+ ```typescript
267
+ accessio.create({
268
+ hooks: {
269
+ onBeforeRequest: (config) => console.log('Starting request...'),
270
+ onRequestResponse: (response) => console.log('Request succeeded!'),
271
+ onRequestError: (error) => console.error('Request failed!'),
272
+ },
273
+ });
274
+ ```
275
+
181
276
  ---
182
277
 
183
278
  ## 🛠️ Developer Guide
package/cjs/accessio.cjs CHANGED
@@ -40,6 +40,7 @@ var import_buildURL = __toESM(require("./core/buildURL"), 1);
40
40
  var import_retry = __toESM(require("./core/retry"), 1);
41
41
  var import_debug = require("./helpers/debug");
42
42
  var import_rateLimiter = require("./helpers/rateLimiter");
43
+ var import_toFormData = require("./helpers/toFormData");
43
44
  var import_defaults = __toESM(require("./defaults/index"), 1);
44
45
  class Accessio {
45
46
  defaults;
@@ -177,35 +178,90 @@ class Accessio {
177
178
  return this.request((0, import_mergeConfig.default)(config || {}, { method: "patch", url, data }));
178
179
  }
179
180
  postForm(url, data, config) {
181
+ const formData = data && !(data instanceof FormData) ? (0, import_toFormData.toFormData)(data) : data;
180
182
  return this.request(
181
183
  (0, import_mergeConfig.default)(config || {}, {
182
184
  method: "post",
183
185
  url,
184
- data,
186
+ data: formData,
185
187
  headers: { "Content-Type": "multipart/form-data" }
186
188
  })
187
189
  );
188
190
  }
189
191
  putForm(url, data, config) {
192
+ const formData = data && !(data instanceof FormData) ? (0, import_toFormData.toFormData)(data) : data;
190
193
  return this.request(
191
194
  (0, import_mergeConfig.default)(config || {}, {
192
195
  method: "put",
193
196
  url,
194
- data,
197
+ data: formData,
195
198
  headers: { "Content-Type": "multipart/form-data" }
196
199
  })
197
200
  );
198
201
  }
199
202
  patchForm(url, data, config) {
203
+ const formData = data && !(data instanceof FormData) ? (0, import_toFormData.toFormData)(data) : data;
200
204
  return this.request(
201
205
  (0, import_mergeConfig.default)(config || {}, {
202
206
  method: "patch",
203
207
  url,
204
- data,
208
+ data: formData,
205
209
  headers: { "Content-Type": "multipart/form-data" }
206
210
  })
207
211
  );
208
212
  }
213
+ async *stream(url, config) {
214
+ const response = await this.request(
215
+ (0, import_mergeConfig.default)(config || {}, { method: "get", url, responseType: "stream" })
216
+ );
217
+ if (!response.data) return;
218
+ const reader = response.data.getReader();
219
+ const decoder = new TextDecoder();
220
+ let buffer = "";
221
+ while (true) {
222
+ const { done, value } = await reader.read();
223
+ if (done) break;
224
+ buffer += decoder.decode(value, { stream: true });
225
+ const lines = buffer.split("\n");
226
+ buffer = lines.pop() || "";
227
+ for (const line of lines) {
228
+ if (line.trim().startsWith("data:")) {
229
+ const dataStr = line.replace(/^data:\s*/, "");
230
+ if (dataStr === "[DONE]") return;
231
+ try {
232
+ yield JSON.parse(dataStr);
233
+ } catch (e) {
234
+ yield dataStr;
235
+ }
236
+ } else if (line.trim().startsWith("{") || line.trim().startsWith("[")) {
237
+ try {
238
+ yield JSON.parse(line);
239
+ } catch (e) {
240
+ }
241
+ }
242
+ }
243
+ }
244
+ }
245
+ async *autoPaginate(url, config) {
246
+ let nextUrl = url;
247
+ let currentConfig = config || {};
248
+ while (nextUrl) {
249
+ const response = await this.get(nextUrl, currentConfig);
250
+ const items = Array.isArray(response.data) ? response.data : response.data.data;
251
+ if (Array.isArray(items)) {
252
+ for (const item of items) {
253
+ yield item;
254
+ }
255
+ }
256
+ nextUrl = response.data.next || response.data.links?.next || null;
257
+ if (nextUrl) {
258
+ currentConfig = (0, import_mergeConfig.default)(currentConfig, { url: nextUrl, params: {} });
259
+ }
260
+ }
261
+ }
262
+ gql(url, query, variables, config) {
263
+ return this.post(url, { query, variables }, config);
264
+ }
209
265
  }
210
266
  var accessio_default = Accessio;
211
267
  // Annotate the CommonJS export names for ESM import in node:
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/accessio.ts"],"sourcesContent":["import InterceptorManager from './interceptors/interceptorManager';\nimport AccessioError from './core/accessioError';\nimport mergeConfig from './core/mergeConfig';\nimport dispatchRequest from './core/request';\nimport buildURL from './core/buildURL';\nimport retryRequest from './core/retry';\nimport { logRequest, logResponse, logError } from './helpers/debug';\nimport { rateLimitedRequest } from './helpers/rateLimiter';\nimport type {\n AccessioRequestConfig,\n AccessioResponse,\n Interceptors,\n InterceptorHandler,\n} from './types';\nimport defaultsConfig from './defaults/index';\n\nexport class Accessio {\n defaults: AccessioRequestConfig;\n interceptors: Interceptors;\n\n constructor(instanceConfig: AccessioRequestConfig = {}) {\n this.defaults = mergeConfig(defaultsConfig, instanceConfig);\n this.interceptors = {\n request: new InterceptorManager(),\n response: new InterceptorManager(),\n };\n }\n\n request<T = any>(\n configOrUrl: string | AccessioRequestConfig,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n if (typeof configOrUrl === 'string') {\n config = { ...config, url: configOrUrl };\n } else {\n config = configOrUrl ? { ...configOrUrl } : {};\n }\n\n const mergedConfig = mergeConfig(this.defaults, config);\n\n mergedConfig.method = (mergedConfig.method || 'get').toLowerCase();\n\n if (!mergedConfig.url && !mergedConfig.baseURL) {\n throw new AccessioError(\n 'Request URL is required. Provide a `url` or `baseURL` in the config.',\n AccessioError.ERR_BAD_OPTION,\n mergedConfig,\n null,\n null,\n );\n }\n\n const requestInterceptors: any[] = [];\n const responseInterceptors: any[] = [];\n let synchronousRequestInterceptors = true;\n\n this.interceptors.request.forEach((interceptor: InterceptorHandler) => {\n if (interceptor.runWhen && !interceptor.runWhen(mergedConfig)) {\n return;\n }\n synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;\n requestInterceptors.unshift(interceptor);\n });\n\n this.interceptors.response.forEach((interceptor: InterceptorHandler) => {\n responseInterceptors.push(interceptor);\n });\n\n let promise: Promise<any>;\n\n if (synchronousRequestInterceptors) {\n let newConfig = mergedConfig;\n let rejectReason: any = null;\n let isRejected = false;\n\n for (const interceptor of requestInterceptors) {\n if (!isRejected) {\n try {\n if (interceptor.fulfilled) {\n newConfig = interceptor.fulfilled(newConfig);\n }\n } catch (err) {\n rejectReason = err;\n isRejected = true;\n }\n } else {\n if (interceptor.rejected) {\n try {\n newConfig = interceptor.rejected(rejectReason);\n isRejected = false;\n } catch (err) {\n rejectReason = err;\n isRejected = true;\n }\n }\n }\n }\n\n if (isRejected) {\n promise = Promise.reject(rejectReason);\n } else {\n promise = Promise.resolve(newConfig);\n }\n } else {\n promise = Promise.resolve(mergedConfig);\n for (const interceptor of requestInterceptors) {\n promise = promise.then((value: any) => {\n if (interceptor.fulfilled) {\n return interceptor.fulfilled(value);\n }\n return value;\n }, interceptor.rejected);\n }\n }\n\n promise = promise.then((cfg: any) => {\n const fullUrl = buildURL(cfg.url ?? '', cfg.baseURL, cfg.params, cfg.paramsSerializer);\n\n logRequest(cfg, fullUrl);\n\n const enrichedCfg = fullUrl !== (cfg.url || '') ? { ...cfg, _builtUrl: fullUrl } : cfg;\n\n const dispatchFn = cfg.rateLimiter\n ? (config: AccessioRequestConfig) =>\n rateLimitedRequest(dispatchRequest, config.rateLimiter!, config)\n : dispatchRequest;\n\n return retryRequest(dispatchFn, enrichedCfg);\n });\n\n promise = promise.then(\n (value: any) => {\n logResponse(value);\n return value;\n },\n (error: any) => {\n logError(error, mergedConfig);\n throw error;\n },\n );\n\n for (const interceptor of responseInterceptors) {\n promise = promise.then((value: any) => {\n if (interceptor.fulfilled) {\n return interceptor.fulfilled(value);\n }\n return value;\n }, interceptor.rejected);\n }\n\n return promise;\n }\n\n getUri(config?: AccessioRequestConfig): string {\n const merged = mergeConfig(this.defaults, config);\n return buildURL(merged.url ?? '', merged.baseURL, merged.params, merged.paramsSerializer);\n }\n\n get<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'get', url }));\n }\n\n delete<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'delete', url }));\n }\n\n head<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'head', url }));\n }\n\n options<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'options', url }));\n }\n\n post<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'post', url, data }));\n }\n\n put<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'put', url, data }));\n }\n\n patch<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'patch', url, data }));\n }\n\n postForm<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.request<T>(\n mergeConfig(config || {}, {\n method: 'post',\n url,\n data,\n headers: { 'Content-Type': 'multipart/form-data' },\n }),\n );\n }\n\n putForm<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.request<T>(\n mergeConfig(config || {}, {\n method: 'put',\n url,\n data,\n headers: { 'Content-Type': 'multipart/form-data' },\n }),\n );\n }\n\n patchForm<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.request<T>(\n mergeConfig(config || {}, {\n method: 'patch',\n url,\n data,\n headers: { 'Content-Type': 'multipart/form-data' },\n }),\n );\n }\n}\n\nexport default Accessio;\n"],"mappings":"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","names":["mergeConfig","defaultsConfig","InterceptorManager","AccessioError","buildURL","config","dispatchRequest","retryRequest"]}
1
+ {"version":3,"sources":["../src/accessio.ts"],"sourcesContent":["import InterceptorManager from './interceptors/interceptorManager';\nimport AccessioError from './core/accessioError';\nimport mergeConfig from './core/mergeConfig';\nimport dispatchRequest from './core/request';\nimport buildURL from './core/buildURL';\nimport retryRequest from './core/retry';\nimport { logRequest, logResponse, logError } from './helpers/debug';\nimport { rateLimitedRequest } from './helpers/rateLimiter';\nimport { toFormData } from './helpers/toFormData';\nimport type {\n AccessioRequestConfig,\n AccessioResponse,\n Interceptors,\n InterceptorHandler,\n} from './types';\nimport defaultsConfig from './defaults/index';\n\nexport class Accessio {\n defaults: AccessioRequestConfig;\n interceptors: Interceptors;\n\n constructor(instanceConfig: AccessioRequestConfig = {}) {\n this.defaults = mergeConfig(defaultsConfig, instanceConfig);\n this.interceptors = {\n request: new InterceptorManager(),\n response: new InterceptorManager(),\n };\n }\n\n request<T = any>(\n configOrUrl: string | AccessioRequestConfig,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n if (typeof configOrUrl === 'string') {\n config = { ...config, url: configOrUrl };\n } else {\n config = configOrUrl ? { ...configOrUrl } : {};\n }\n\n const mergedConfig = mergeConfig(this.defaults, config);\n\n mergedConfig.method = (mergedConfig.method || 'get').toLowerCase();\n\n if (!mergedConfig.url && !mergedConfig.baseURL) {\n throw new AccessioError(\n 'Request URL is required. Provide a `url` or `baseURL` in the config.',\n AccessioError.ERR_BAD_OPTION,\n mergedConfig,\n null,\n null,\n );\n }\n\n const requestInterceptors: any[] = [];\n const responseInterceptors: any[] = [];\n let synchronousRequestInterceptors = true;\n\n this.interceptors.request.forEach((interceptor: InterceptorHandler) => {\n if (interceptor.runWhen && !interceptor.runWhen(mergedConfig)) {\n return;\n }\n synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;\n requestInterceptors.unshift(interceptor);\n });\n\n this.interceptors.response.forEach((interceptor: InterceptorHandler) => {\n responseInterceptors.push(interceptor);\n });\n\n let promise: Promise<any>;\n\n if (synchronousRequestInterceptors) {\n let newConfig = mergedConfig;\n let rejectReason: any = null;\n let isRejected = false;\n\n for (const interceptor of requestInterceptors) {\n if (!isRejected) {\n try {\n if (interceptor.fulfilled) {\n newConfig = interceptor.fulfilled(newConfig);\n }\n } catch (err) {\n rejectReason = err;\n isRejected = true;\n }\n } else {\n if (interceptor.rejected) {\n try {\n newConfig = interceptor.rejected(rejectReason);\n isRejected = false;\n } catch (err) {\n rejectReason = err;\n isRejected = true;\n }\n }\n }\n }\n\n if (isRejected) {\n promise = Promise.reject(rejectReason);\n } else {\n promise = Promise.resolve(newConfig);\n }\n } else {\n promise = Promise.resolve(mergedConfig);\n for (const interceptor of requestInterceptors) {\n promise = promise.then((value: any) => {\n if (interceptor.fulfilled) {\n return interceptor.fulfilled(value);\n }\n return value;\n }, interceptor.rejected);\n }\n }\n\n promise = promise.then((cfg: any) => {\n const fullUrl = buildURL(cfg.url ?? '', cfg.baseURL, cfg.params, cfg.paramsSerializer);\n\n logRequest(cfg, fullUrl);\n\n const enrichedCfg = fullUrl !== (cfg.url || '') ? { ...cfg, _builtUrl: fullUrl } : cfg;\n\n const dispatchFn = cfg.rateLimiter\n ? (config: AccessioRequestConfig) =>\n rateLimitedRequest(dispatchRequest, config.rateLimiter!, config)\n : dispatchRequest;\n\n return retryRequest(dispatchFn, enrichedCfg);\n });\n\n promise = promise.then(\n (value: any) => {\n logResponse(value);\n return value;\n },\n (error: any) => {\n logError(error, mergedConfig);\n throw error;\n },\n );\n\n for (const interceptor of responseInterceptors) {\n promise = promise.then((value: any) => {\n if (interceptor.fulfilled) {\n return interceptor.fulfilled(value);\n }\n return value;\n }, interceptor.rejected);\n }\n\n return promise;\n }\n\n getUri(config?: AccessioRequestConfig): string {\n const merged = mergeConfig(this.defaults, config);\n return buildURL(merged.url ?? '', merged.baseURL, merged.params, merged.paramsSerializer);\n }\n\n get<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'get', url }));\n }\n\n delete<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'delete', url }));\n }\n\n head<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'head', url }));\n }\n\n options<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'options', url }));\n }\n\n post<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'post', url, data }));\n }\n\n put<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'put', url, data }));\n }\n\n patch<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'patch', url, data }));\n }\n\n postForm<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n const formData = data && !(data instanceof FormData) ? toFormData(data) : data;\n return this.request<T>(\n mergeConfig(config || {}, {\n method: 'post',\n url,\n data: formData,\n headers: { 'Content-Type': 'multipart/form-data' },\n }),\n );\n }\n\n putForm<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n const formData = data && !(data instanceof FormData) ? toFormData(data) : data;\n return this.request<T>(\n mergeConfig(config || {}, {\n method: 'put',\n url,\n data: formData,\n headers: { 'Content-Type': 'multipart/form-data' },\n }),\n );\n }\n\n patchForm<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n const formData = data && !(data instanceof FormData) ? toFormData(data) : data;\n return this.request<T>(\n mergeConfig(config || {}, {\n method: 'patch',\n url,\n data: formData,\n headers: { 'Content-Type': 'multipart/form-data' },\n }),\n );\n }\n\n async *stream<T = any>(\n url: string,\n config?: AccessioRequestConfig,\n ): AsyncGenerator<T, void, unknown> {\n const response = await this.request<ReadableStream<Uint8Array>>(\n mergeConfig(config || {}, { method: 'get', url, responseType: 'stream' }),\n );\n if (!response.data) return;\n\n const reader = response.data.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.trim().startsWith('data:')) {\n const dataStr = line.replace(/^data:\\s*/, '');\n if (dataStr === '[DONE]') return;\n try {\n yield JSON.parse(dataStr);\n } catch (e) {\n yield dataStr as any;\n }\n } else if (line.trim().startsWith('{') || line.trim().startsWith('[')) {\n try {\n yield JSON.parse(line);\n } catch (e) {\n // ignore partial json\n }\n }\n }\n }\n }\n\n async *autoPaginate<T = any>(\n url: string,\n config?: AccessioRequestConfig,\n ): AsyncGenerator<T, void, unknown> {\n let nextUrl: string | null = url;\n let currentConfig = config || {};\n\n while (nextUrl) {\n const response: AccessioResponse<any> = await this.get(nextUrl, currentConfig);\n\n const items = Array.isArray(response.data) ? response.data : response.data.data;\n if (Array.isArray(items)) {\n for (const item of items) {\n yield item;\n }\n }\n\n nextUrl = response.data.next || response.data.links?.next || null;\n if (nextUrl) {\n currentConfig = mergeConfig(currentConfig, { url: nextUrl, params: {} });\n }\n }\n }\n\n gql<T = any>(\n url: string,\n query: string,\n variables?: Record<string, any>,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.post<T>(url, { query, variables }, config);\n }\n}\n\nexport default Accessio;\n"],"mappings":"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","names":["mergeConfig","defaultsConfig","InterceptorManager","AccessioError","buildURL","config","dispatchRequest","retryRequest"]}
@@ -29,10 +29,33 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  var accessioError_exports = {};
30
30
  __export(accessioError_exports, {
31
31
  AccessioError: () => AccessioError,
32
- default: () => accessioError_default
32
+ default: () => accessioError_default,
33
+ redactConfig: () => redactConfig
33
34
  });
34
35
  module.exports = __toCommonJS(accessioError_exports);
35
36
  var import_errorCodes = __toESM(require("../constants/errorCodes"), 1);
37
+ function redactHeaders(headers) {
38
+ if (!headers || typeof headers !== "object") return headers;
39
+ const out = {};
40
+ for (const key of Object.keys(headers)) {
41
+ const value = headers[key];
42
+ if (/^authorization$/i.test(key)) {
43
+ out[key] = "[REDACTED]";
44
+ } else if (value && typeof value === "object" && !Array.isArray(value)) {
45
+ out[key] = redactHeaders(value);
46
+ } else {
47
+ out[key] = value;
48
+ }
49
+ }
50
+ return out;
51
+ }
52
+ function redactConfig(config) {
53
+ if (!config) return config;
54
+ const clone = { ...config };
55
+ if ("auth" in clone) delete clone.auth;
56
+ if (clone.headers) clone.headers = redactHeaders(clone.headers);
57
+ return clone;
58
+ }
36
59
  class AccessioError extends Error {
37
60
  static ERR_BAD_OPTION_VALUE = import_errorCodes.default.ERR_BAD_OPTION_VALUE;
38
61
  static ERR_BAD_OPTION = import_errorCodes.default.ERR_BAD_OPTION;
@@ -51,11 +74,12 @@ class AccessioError extends Error {
51
74
  response;
52
75
  isAccessioError;
53
76
  cause;
77
+ name = "AccessioError";
54
78
  constructor(message, code, config, request, response) {
55
79
  super(message);
56
80
  this.name = "AccessioError";
57
81
  this.code = code ?? null;
58
- this.config = config ?? null;
82
+ this.config = redactConfig(config ?? null);
59
83
  this.request = request ?? null;
60
84
  this.response = response ?? null;
61
85
  this.isAccessioError = true;
@@ -82,6 +106,7 @@ class AccessioError extends Error {
82
106
  var accessioError_default = AccessioError;
83
107
  // Annotate the CommonJS export names for ESM import in node:
84
108
  0 && (module.exports = {
85
- AccessioError
109
+ AccessioError,
110
+ redactConfig
86
111
  });
87
112
  //# sourceMappingURL=accessioError.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/accessioError.ts"],"sourcesContent":["import ErrorCodes from '../constants/errorCodes';\nimport type { AccessioRequestConfig, AccessioResponse } from '../types';\n\nexport class AccessioError extends Error {\n static ERR_BAD_OPTION_VALUE: string = ErrorCodes.ERR_BAD_OPTION_VALUE;\n static ERR_BAD_OPTION: string = ErrorCodes.ERR_BAD_OPTION;\n static ECONNABORTED: string = ErrorCodes.ECONNABORTED;\n static ETIMEDOUT: string = ErrorCodes.ETIMEDOUT;\n static ERR_NETWORK: string = ErrorCodes.ERR_NETWORK;\n static ERR_FR_TOO_MANY_REDIRECTS: string = ErrorCodes.ERR_FR_TOO_MANY_REDIRECTS;\n static ERR_BAD_RESPONSE: string = ErrorCodes.ERR_BAD_RESPONSE;\n static ERR_BAD_REQUEST: string = ErrorCodes.ERR_BAD_REQUEST;\n static ERR_CANCELED: string = ErrorCodes.ERR_CANCELED;\n static ERR_NOT_SUPPORT: string = ErrorCodes.ERR_NOT_SUPPORT;\n static ERR_INVALID_URL: string = ErrorCodes.ERR_INVALID_URL;\n\n readonly code: string | null;\n readonly config: AccessioRequestConfig | null;\n readonly request: unknown;\n readonly response: AccessioResponse | null;\n readonly isAccessioError: true;\n cause?: Error;\n\n constructor(\n message: string,\n code: string | null,\n config: AccessioRequestConfig | null,\n request: unknown,\n response: AccessioResponse | null,\n ) {\n super(message);\n this.name = 'AccessioError';\n this.code = code ?? null;\n this.config = config ?? null;\n this.request = request ?? null;\n this.response = response ?? null;\n this.isAccessioError = true;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, AccessioError);\n }\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n status: this.response ? this.response.status : null,\n config: this.config,\n };\n }\n\n static from(\n error: Error,\n code: string,\n config: AccessioRequestConfig | null,\n request: unknown,\n response: AccessioResponse | null,\n ): AccessioError {\n const accessioError = new AccessioError(error.message, code, config, request, response);\n accessioError.cause = error;\n accessioError.stack = error.stack;\n return accessioError;\n }\n}\n\nexport default AccessioError;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAuB;AAGhB,MAAM,sBAAsB,MAAM;AAAA,EACvC,OAAO,uBAA+B,kBAAAA,QAAW;AAAA,EACjD,OAAO,iBAAyB,kBAAAA,QAAW;AAAA,EAC3C,OAAO,eAAuB,kBAAAA,QAAW;AAAA,EACzC,OAAO,YAAoB,kBAAAA,QAAW;AAAA,EACtC,OAAO,cAAsB,kBAAAA,QAAW;AAAA,EACxC,OAAO,4BAAoC,kBAAAA,QAAW;AAAA,EACtD,OAAO,mBAA2B,kBAAAA,QAAW;AAAA,EAC7C,OAAO,kBAA0B,kBAAAA,QAAW;AAAA,EAC5C,OAAO,eAAuB,kBAAAA,QAAW;AAAA,EACzC,OAAO,kBAA0B,kBAAAA,QAAW;AAAA,EAC5C,OAAO,kBAA0B,kBAAAA,QAAW;AAAA,EAEnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EAEA,YACE,SACA,MACA,QACA,SACA,UACA;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO,QAAQ;AACpB,SAAK,SAAS,UAAU;AACxB,SAAK,UAAU,WAAW;AAC1B,SAAK,WAAW,YAAY;AAC5B,SAAK,kBAAkB;AAEvB,QAAI,MAAM,mBAAmB;AAC3B,YAAM,kBAAkB,MAAM,aAAa;AAAA,IAC7C;AAAA,EACF;AAAA,EAEA,SAAkC;AAChC,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK,WAAW,KAAK,SAAS,SAAS;AAAA,MAC/C,QAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAAA,EAEA,OAAO,KACL,OACA,MACA,QACA,SACA,UACe;AACf,UAAM,gBAAgB,IAAI,cAAc,MAAM,SAAS,MAAM,QAAQ,SAAS,QAAQ;AACtF,kBAAc,QAAQ;AACtB,kBAAc,QAAQ,MAAM;AAC5B,WAAO;AAAA,EACT;AACF;AAEA,IAAO,wBAAQ;","names":["ErrorCodes"]}
1
+ {"version":3,"sources":["../../src/core/accessioError.ts"],"sourcesContent":["import ErrorCodes from '../constants/errorCodes';\nimport type { AccessioRequestConfig, AccessioResponse } from '../types';\n\nfunction redactHeaders(headers: unknown): unknown {\n if (!headers || typeof headers !== 'object') return headers;\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(headers as Record<string, unknown>)) {\n const value = (headers as Record<string, unknown>)[key];\n if (/^authorization$/i.test(key)) {\n out[key] = '[REDACTED]';\n } else if (value && typeof value === 'object' && !Array.isArray(value)) {\n out[key] = redactHeaders(value);\n } else {\n out[key] = value;\n }\n }\n return out;\n}\n\nexport function redactConfig(config: AccessioRequestConfig | null): AccessioRequestConfig | null {\n if (!config) return config;\n const clone = { ...config } as AccessioRequestConfig & { auth?: unknown };\n if ('auth' in clone) delete clone.auth;\n if (clone.headers) clone.headers = redactHeaders(clone.headers) as typeof clone.headers;\n return clone;\n}\n\nexport class AccessioError extends Error {\n static ERR_BAD_OPTION_VALUE: string = ErrorCodes.ERR_BAD_OPTION_VALUE;\n static ERR_BAD_OPTION: string = ErrorCodes.ERR_BAD_OPTION;\n static ECONNABORTED: string = ErrorCodes.ECONNABORTED;\n static ETIMEDOUT: string = ErrorCodes.ETIMEDOUT;\n static ERR_NETWORK: string = ErrorCodes.ERR_NETWORK;\n static ERR_FR_TOO_MANY_REDIRECTS: string = ErrorCodes.ERR_FR_TOO_MANY_REDIRECTS;\n static ERR_BAD_RESPONSE: string = ErrorCodes.ERR_BAD_RESPONSE;\n static ERR_BAD_REQUEST: string = ErrorCodes.ERR_BAD_REQUEST;\n static ERR_CANCELED: string = ErrorCodes.ERR_CANCELED;\n static ERR_NOT_SUPPORT: string = ErrorCodes.ERR_NOT_SUPPORT;\n static ERR_INVALID_URL: string = ErrorCodes.ERR_INVALID_URL;\n\n readonly code: string | null;\n readonly config: AccessioRequestConfig | null;\n readonly request: unknown;\n readonly response: AccessioResponse | null;\n readonly isAccessioError: true;\n cause?: Error;\n override name = 'AccessioError' as const;\n\n constructor(\n message: string,\n code: string | null,\n config: AccessioRequestConfig | null,\n request: unknown,\n response: AccessioResponse | null,\n ) {\n super(message);\n this.name = 'AccessioError';\n this.code = code ?? null;\n this.config = redactConfig(config ?? null);\n this.request = request ?? null;\n this.response = response ?? null;\n this.isAccessioError = true;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, AccessioError);\n }\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n status: this.response ? this.response.status : null,\n config: this.config,\n };\n }\n\n static from(\n error: Error,\n code: string,\n config: AccessioRequestConfig | null,\n request: unknown,\n response: AccessioResponse | null,\n ): AccessioError {\n const accessioError = new AccessioError(error.message, code, config, request, response);\n accessioError.cause = error;\n accessioError.stack = error.stack;\n return accessioError;\n }\n}\n\nexport default AccessioError;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAuB;AAGvB,SAAS,cAAc,SAA2B;AAChD,MAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAM,MAA+B,CAAC;AACtC,aAAW,OAAO,OAAO,KAAK,OAAkC,GAAG;AACjE,UAAM,QAAS,QAAoC,GAAG;AACtD,QAAI,mBAAmB,KAAK,GAAG,GAAG;AAChC,UAAI,GAAG,IAAI;AAAA,IACb,WAAW,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GAAG;AACtE,UAAI,GAAG,IAAI,cAAc,KAAK;AAAA,IAChC,OAAO;AACL,UAAI,GAAG,IAAI;AAAA,IACb;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,aAAa,QAAoE;AAC/F,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,QAAQ,EAAE,GAAG,OAAO;AAC1B,MAAI,UAAU,MAAO,QAAO,MAAM;AAClC,MAAI,MAAM,QAAS,OAAM,UAAU,cAAc,MAAM,OAAO;AAC9D,SAAO;AACT;AAEO,MAAM,sBAAsB,MAAM;AAAA,EACvC,OAAO,uBAA+B,kBAAAA,QAAW;AAAA,EACjD,OAAO,iBAAyB,kBAAAA,QAAW;AAAA,EAC3C,OAAO,eAAuB,kBAAAA,QAAW;AAAA,EACzC,OAAO,YAAoB,kBAAAA,QAAW;AAAA,EACtC,OAAO,cAAsB,kBAAAA,QAAW;AAAA,EACxC,OAAO,4BAAoC,kBAAAA,QAAW;AAAA,EACtD,OAAO,mBAA2B,kBAAAA,QAAW;AAAA,EAC7C,OAAO,kBAA0B,kBAAAA,QAAW;AAAA,EAC5C,OAAO,eAAuB,kBAAAA,QAAW;AAAA,EACzC,OAAO,kBAA0B,kBAAAA,QAAW;AAAA,EAC5C,OAAO,kBAA0B,kBAAAA,QAAW;AAAA,EAEnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EACS,OAAO;AAAA,EAEhB,YACE,SACA,MACA,QACA,SACA,UACA;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO,QAAQ;AACpB,SAAK,SAAS,aAAa,UAAU,IAAI;AACzC,SAAK,UAAU,WAAW;AAC1B,SAAK,WAAW,YAAY;AAC5B,SAAK,kBAAkB;AAEvB,QAAI,MAAM,mBAAmB;AAC3B,YAAM,kBAAkB,MAAM,aAAa;AAAA,IAC7C;AAAA,EACF;AAAA,EAEA,SAAkC;AAChC,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK,WAAW,KAAK,SAAS,SAAS;AAAA,MAC/C,QAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAAA,EAEA,OAAO,KACL,OACA,MACA,QACA,SACA,UACe;AACf,UAAM,gBAAgB,IAAI,cAAc,MAAM,SAAS,MAAM,QAAQ,SAAS,QAAQ;AACtF,kBAAc,QAAQ;AACtB,kBAAc,QAAQ,MAAM;AAC5B,WAAO;AAAA,EACT;AACF;AAEA,IAAO,wBAAQ;","names":["ErrorCodes"]}
@@ -77,7 +77,21 @@ function isAbsoluteURL(url) {
77
77
  }
78
78
  function buildURL(url, baseURL, params, paramsSerializer) {
79
79
  let fullURL = baseURL && !isAbsoluteURL(url) ? combineURLs(baseURL, url) : url || "";
80
- const serialized = serializeParams(params, paramsSerializer);
80
+ let finalParams = params;
81
+ if (params && typeof params === "object") {
82
+ const unusedParams = { ...params };
83
+ fullURL = fullURL.replace(/(?::([a-zA-Z0-9_]+))|(?:{([a-zA-Z0-9_]+)})/g, (match, p1, p2) => {
84
+ const key = p1 || p2;
85
+ if (key && unusedParams[key] !== void 0) {
86
+ const val = unusedParams[key];
87
+ delete unusedParams[key];
88
+ return encodeURIComponent(String(val));
89
+ }
90
+ return match;
91
+ });
92
+ finalParams = unusedParams;
93
+ }
94
+ const serialized = serializeParams(finalParams, paramsSerializer);
81
95
  if (serialized) {
82
96
  const hashIndex = fullURL.indexOf("#");
83
97
  if (hashIndex !== -1) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/buildURL.ts"],"sourcesContent":["import type { ParamsSerializer } from '../types';\n\nfunction serializeParams(\n params: Record<string, unknown>,\n paramsSerializer?: ParamsSerializer,\n): string {\n if (!params) return '';\n\n if (typeof paramsSerializer === 'function') {\n return paramsSerializer(params);\n }\n\n if (typeof URLSearchParams !== 'undefined' && params instanceof URLSearchParams) {\n return params.toString();\n }\n\n const parts: string[] = [];\n\n function encode(prefix: string, value: unknown): void {\n if (value === null || value === undefined) {\n return;\n }\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n if (typeof item === 'object' && item !== null) {\n encode(`${prefix}[${index}]`, item);\n } else {\n encode(prefix, item);\n }\n });\n } else if (typeof value === 'object' && !(value instanceof Date)) {\n Object.keys(value as Record<string, unknown>).forEach((key) => {\n encode(`${prefix}[${key}]`, (value as Record<string, unknown>)[key]);\n });\n } else {\n const encodedValue = value instanceof Date ? value.toISOString() : value;\n parts.push(`${encodeURIComponent(prefix)}=${encodeURIComponent(encodedValue as string)}`);\n }\n }\n\n Object.keys(params).forEach((key) => {\n encode(key, params[key]);\n });\n\n return parts.join('&');\n}\n\nfunction combineURLs(baseURL: string, relativeURL: string): string {\n if (!baseURL) return relativeURL || '';\n if (!relativeURL) return baseURL;\n\n let base = baseURL;\n while (base.endsWith('/')) {\n base = base.slice(0, -1);\n }\n\n let relative = relativeURL;\n while (relative.startsWith('/')) {\n relative = relative.slice(1);\n }\n\n return `${base}/${relative}`;\n}\n\nfunction isAbsoluteURL(url: string): boolean {\n return /^([a-z][a-z\\d+\\-.]*:)/i.test(url);\n}\n\nexport default function buildURL(\n url: string,\n baseURL?: string,\n params?: Record<string, unknown>,\n paramsSerializer?: ParamsSerializer,\n): string {\n let fullURL = baseURL && !isAbsoluteURL(url) ? combineURLs(baseURL, url) : url || '';\n\n const serialized = serializeParams(params as Record<string, unknown>, paramsSerializer);\n if (serialized) {\n const hashIndex = fullURL.indexOf('#');\n if (hashIndex !== -1) {\n fullURL = fullURL.slice(0, hashIndex);\n }\n fullURL += (fullURL.indexOf('?') === -1 ? '?' : '&') + serialized;\n }\n\n return fullURL;\n}\n\nexport { serializeParams, combineURLs, isAbsoluteURL };\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,SAAS,gBACP,QACA,kBACQ;AACR,MAAI,CAAC,OAAQ,QAAO;AAEpB,MAAI,OAAO,qBAAqB,YAAY;AAC1C,WAAO,iBAAiB,MAAM;AAAA,EAChC;AAEA,MAAI,OAAO,oBAAoB,eAAe,kBAAkB,iBAAiB;AAC/E,WAAO,OAAO,SAAS;AAAA,EACzB;AAEA,QAAM,QAAkB,CAAC;AAEzB,WAAS,OAAO,QAAgB,OAAsB;AACpD,QAAI,UAAU,QAAQ,UAAU,QAAW;AACzC;AAAA,IACF;AAEA,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,YAAM,QAAQ,CAAC,MAAM,UAAU;AAC7B,YAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,iBAAO,GAAG,MAAM,IAAI,KAAK,KAAK,IAAI;AAAA,QACpC,OAAO;AACL,iBAAO,QAAQ,IAAI;AAAA,QACrB;AAAA,MACF,CAAC;AAAA,IACH,WAAW,OAAO,UAAU,YAAY,EAAE,iBAAiB,OAAO;AAChE,aAAO,KAAK,KAAgC,EAAE,QAAQ,CAAC,QAAQ;AAC7D,eAAO,GAAG,MAAM,IAAI,GAAG,KAAM,MAAkC,GAAG,CAAC;AAAA,MACrE,CAAC;AAAA,IACH,OAAO;AACL,YAAM,eAAe,iBAAiB,OAAO,MAAM,YAAY,IAAI;AACnE,YAAM,KAAK,GAAG,mBAAmB,MAAM,CAAC,IAAI,mBAAmB,YAAsB,CAAC,EAAE;AAAA,IAC1F;AAAA,EACF;AAEA,SAAO,KAAK,MAAM,EAAE,QAAQ,CAAC,QAAQ;AACnC,WAAO,KAAK,OAAO,GAAG,CAAC;AAAA,EACzB,CAAC;AAED,SAAO,MAAM,KAAK,GAAG;AACvB;AAEA,SAAS,YAAY,SAAiB,aAA6B;AACjE,MAAI,CAAC,QAAS,QAAO,eAAe;AACpC,MAAI,CAAC,YAAa,QAAO;AAEzB,MAAI,OAAO;AACX,SAAO,KAAK,SAAS,GAAG,GAAG;AACzB,WAAO,KAAK,MAAM,GAAG,EAAE;AAAA,EACzB;AAEA,MAAI,WAAW;AACf,SAAO,SAAS,WAAW,GAAG,GAAG;AAC/B,eAAW,SAAS,MAAM,CAAC;AAAA,EAC7B;AAEA,SAAO,GAAG,IAAI,IAAI,QAAQ;AAC5B;AAEA,SAAS,cAAc,KAAsB;AAC3C,SAAO,yBAAyB,KAAK,GAAG;AAC1C;AAEe,SAAR,SACL,KACA,SACA,QACA,kBACQ;AACR,MAAI,UAAU,WAAW,CAAC,cAAc,GAAG,IAAI,YAAY,SAAS,GAAG,IAAI,OAAO;AAElF,QAAM,aAAa,gBAAgB,QAAmC,gBAAgB;AACtF,MAAI,YAAY;AACd,UAAM,YAAY,QAAQ,QAAQ,GAAG;AACrC,QAAI,cAAc,IAAI;AACpB,gBAAU,QAAQ,MAAM,GAAG,SAAS;AAAA,IACtC;AACA,gBAAY,QAAQ,QAAQ,GAAG,MAAM,KAAK,MAAM,OAAO;AAAA,EACzD;AAEA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/core/buildURL.ts"],"sourcesContent":["import type { ParamsSerializer } from '../types';\n\nfunction serializeParams(\n params: Record<string, unknown>,\n paramsSerializer?: ParamsSerializer,\n): string {\n if (!params) return '';\n\n if (typeof paramsSerializer === 'function') {\n return paramsSerializer(params);\n }\n\n if (typeof URLSearchParams !== 'undefined' && params instanceof URLSearchParams) {\n return params.toString();\n }\n\n const parts: string[] = [];\n\n function encode(prefix: string, value: unknown): void {\n if (value === null || value === undefined) {\n return;\n }\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n if (typeof item === 'object' && item !== null) {\n encode(`${prefix}[${index}]`, item);\n } else {\n encode(prefix, item);\n }\n });\n } else if (typeof value === 'object' && !(value instanceof Date)) {\n Object.keys(value as Record<string, unknown>).forEach((key) => {\n encode(`${prefix}[${key}]`, (value as Record<string, unknown>)[key]);\n });\n } else {\n const encodedValue = value instanceof Date ? value.toISOString() : value;\n parts.push(`${encodeURIComponent(prefix)}=${encodeURIComponent(encodedValue as string)}`);\n }\n }\n\n Object.keys(params).forEach((key) => {\n encode(key, params[key]);\n });\n\n return parts.join('&');\n}\n\nfunction combineURLs(baseURL: string, relativeURL: string): string {\n if (!baseURL) return relativeURL || '';\n if (!relativeURL) return baseURL;\n\n let base = baseURL;\n while (base.endsWith('/')) {\n base = base.slice(0, -1);\n }\n\n let relative = relativeURL;\n while (relative.startsWith('/')) {\n relative = relative.slice(1);\n }\n\n return `${base}/${relative}`;\n}\n\nfunction isAbsoluteURL(url: string): boolean {\n return /^([a-z][a-z\\d+\\-.]*:)/i.test(url);\n}\n\nexport default function buildURL(\n url: string,\n baseURL?: string,\n params?: Record<string, unknown>,\n paramsSerializer?: ParamsSerializer,\n): string {\n let fullURL = baseURL && !isAbsoluteURL(url) ? combineURLs(baseURL, url) : url || '';\n\n let finalParams = params;\n if (params && typeof params === 'object') {\n const unusedParams = { ...params };\n fullURL = fullURL.replace(/(?::([a-zA-Z0-9_]+))|(?:{([a-zA-Z0-9_]+)})/g, (match, p1, p2) => {\n const key = p1 || p2;\n if (key && unusedParams[key] !== undefined) {\n const val = unusedParams[key];\n delete unusedParams[key];\n return encodeURIComponent(String(val));\n }\n return match;\n });\n finalParams = unusedParams;\n }\n\n const serialized = serializeParams(finalParams as Record<string, unknown>, paramsSerializer);\n if (serialized) {\n const hashIndex = fullURL.indexOf('#');\n if (hashIndex !== -1) {\n fullURL = fullURL.slice(0, hashIndex);\n }\n fullURL += (fullURL.indexOf('?') === -1 ? '?' : '&') + serialized;\n }\n\n return fullURL;\n}\n\nexport { serializeParams, combineURLs, isAbsoluteURL };\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,SAAS,gBACP,QACA,kBACQ;AACR,MAAI,CAAC,OAAQ,QAAO;AAEpB,MAAI,OAAO,qBAAqB,YAAY;AAC1C,WAAO,iBAAiB,MAAM;AAAA,EAChC;AAEA,MAAI,OAAO,oBAAoB,eAAe,kBAAkB,iBAAiB;AAC/E,WAAO,OAAO,SAAS;AAAA,EACzB;AAEA,QAAM,QAAkB,CAAC;AAEzB,WAAS,OAAO,QAAgB,OAAsB;AACpD,QAAI,UAAU,QAAQ,UAAU,QAAW;AACzC;AAAA,IACF;AAEA,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,YAAM,QAAQ,CAAC,MAAM,UAAU;AAC7B,YAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,iBAAO,GAAG,MAAM,IAAI,KAAK,KAAK,IAAI;AAAA,QACpC,OAAO;AACL,iBAAO,QAAQ,IAAI;AAAA,QACrB;AAAA,MACF,CAAC;AAAA,IACH,WAAW,OAAO,UAAU,YAAY,EAAE,iBAAiB,OAAO;AAChE,aAAO,KAAK,KAAgC,EAAE,QAAQ,CAAC,QAAQ;AAC7D,eAAO,GAAG,MAAM,IAAI,GAAG,KAAM,MAAkC,GAAG,CAAC;AAAA,MACrE,CAAC;AAAA,IACH,OAAO;AACL,YAAM,eAAe,iBAAiB,OAAO,MAAM,YAAY,IAAI;AACnE,YAAM,KAAK,GAAG,mBAAmB,MAAM,CAAC,IAAI,mBAAmB,YAAsB,CAAC,EAAE;AAAA,IAC1F;AAAA,EACF;AAEA,SAAO,KAAK,MAAM,EAAE,QAAQ,CAAC,QAAQ;AACnC,WAAO,KAAK,OAAO,GAAG,CAAC;AAAA,EACzB,CAAC;AAED,SAAO,MAAM,KAAK,GAAG;AACvB;AAEA,SAAS,YAAY,SAAiB,aAA6B;AACjE,MAAI,CAAC,QAAS,QAAO,eAAe;AACpC,MAAI,CAAC,YAAa,QAAO;AAEzB,MAAI,OAAO;AACX,SAAO,KAAK,SAAS,GAAG,GAAG;AACzB,WAAO,KAAK,MAAM,GAAG,EAAE;AAAA,EACzB;AAEA,MAAI,WAAW;AACf,SAAO,SAAS,WAAW,GAAG,GAAG;AAC/B,eAAW,SAAS,MAAM,CAAC;AAAA,EAC7B;AAEA,SAAO,GAAG,IAAI,IAAI,QAAQ;AAC5B;AAEA,SAAS,cAAc,KAAsB;AAC3C,SAAO,yBAAyB,KAAK,GAAG;AAC1C;AAEe,SAAR,SACL,KACA,SACA,QACA,kBACQ;AACR,MAAI,UAAU,WAAW,CAAC,cAAc,GAAG,IAAI,YAAY,SAAS,GAAG,IAAI,OAAO;AAElF,MAAI,cAAc;AAClB,MAAI,UAAU,OAAO,WAAW,UAAU;AACxC,UAAM,eAAe,EAAE,GAAG,OAAO;AACjC,cAAU,QAAQ,QAAQ,+CAA+C,CAAC,OAAO,IAAI,OAAO;AAC1F,YAAM,MAAM,MAAM;AAClB,UAAI,OAAO,aAAa,GAAG,MAAM,QAAW;AAC1C,cAAM,MAAM,aAAa,GAAG;AAC5B,eAAO,aAAa,GAAG;AACvB,eAAO,mBAAmB,OAAO,GAAG,CAAC;AAAA,MACvC;AACA,aAAO;AAAA,IACT,CAAC;AACD,kBAAc;AAAA,EAChB;AAEA,QAAM,aAAa,gBAAgB,aAAwC,gBAAgB;AAC3F,MAAI,YAAY;AACd,UAAM,YAAY,QAAQ,QAAQ,GAAG;AACrC,QAAI,cAAc,IAAI;AACpB,gBAAU,QAAQ,MAAM,GAAG,SAAS;AAAA,IACtC;AACA,gBAAY,QAAQ,QAAQ,GAAG,MAAM,KAAK,MAAM,OAAO;AAAA,EACzD;AAEA,SAAO;AACT;","names":[]}
@@ -33,7 +33,8 @@ __export(fetchAdapter_exports, {
33
33
  module.exports = __toCommonJS(fetchAdapter_exports);
34
34
  var import_accessioError = __toESM(require("./accessioError"), 1);
35
35
  var import_parseHeaders = __toESM(require("../helpers/parseHeaders"), 1);
36
- async function readResponseData(fetchResponse, responseType) {
36
+ async function readResponseData(fetchResponse, config) {
37
+ const responseType = config.responseType || "json";
37
38
  switch (responseType) {
38
39
  case "arraybuffer":
39
40
  return await fetchResponse.arrayBuffer();
@@ -45,12 +46,18 @@ async function readResponseData(fetchResponse, responseType) {
45
46
  default: {
46
47
  const contentType = fetchResponse.headers.get("content-type") || "";
47
48
  if (contentType.includes("application/json")) {
48
- if (typeof fetchResponse.clone === "function") {
49
- const text = await fetchResponse.clone().text();
50
- return text ? await fetchResponse.json() : "";
51
- } else {
52
- const text = await fetchResponse.text();
53
- return text ? JSON.parse(text) : "";
49
+ const text = await fetchResponse.text();
50
+ if (!text) return "";
51
+ try {
52
+ return JSON.parse(text);
53
+ } catch (err) {
54
+ throw new import_accessioError.default(
55
+ `Failed to parse JSON response: ${err.message}. Raw body: ${text.length > 500 ? text.slice(0, 500) + "\u2026" : text}`,
56
+ import_accessioError.default.ERR_BAD_RESPONSE,
57
+ config,
58
+ fetchResponse,
59
+ null
60
+ );
54
61
  }
55
62
  }
56
63
  return await fetchResponse.text();
@@ -111,9 +118,38 @@ async function fetchAdapter(config, fullURL, fetchOptions, requestStartTime) {
111
118
  fetchOptions.signal = config.signal;
112
119
  }
113
120
  try {
114
- const fetchResponse = await fetch(fullURL, fetchOptions);
121
+ const fetchImpl = config.fetch || fetch;
122
+ let fetchResponse = await fetchImpl(fullURL, fetchOptions);
123
+ if (config.onDownloadProgress && fetchResponse.body && config.responseType !== "stream") {
124
+ const contentLength2 = fetchResponse.headers.get("content-length");
125
+ const total = contentLength2 ? parseInt(contentLength2, 10) : 0;
126
+ let loaded = 0;
127
+ const reader = fetchResponse.body.getReader();
128
+ const stream = new ReadableStream({
129
+ async start(controller) {
130
+ try {
131
+ while (true) {
132
+ const { done, value } = await reader.read();
133
+ if (done) {
134
+ controller.close();
135
+ break;
136
+ }
137
+ loaded += value.byteLength;
138
+ config.onDownloadProgress({ loaded, total });
139
+ controller.enqueue(value);
140
+ }
141
+ } catch (e) {
142
+ controller.error(e);
143
+ }
144
+ }
145
+ });
146
+ fetchResponse = new Response(stream, {
147
+ headers: fetchResponse.headers,
148
+ status: fetchResponse.status,
149
+ statusText: fetchResponse.statusText
150
+ });
151
+ }
115
152
  let responseData;
116
- const responseType = config.responseType || "json";
117
153
  const contentLength = fetchResponse.headers.get("content-length");
118
154
  if (contentLength && config.maxContentLength && parseInt(contentLength, 10) > config.maxContentLength) {
119
155
  throw new import_accessioError.default(
@@ -125,8 +161,16 @@ async function fetchAdapter(config, fullURL, fetchOptions, requestStartTime) {
125
161
  );
126
162
  }
127
163
  try {
128
- responseData = await readResponseData(fetchResponse, responseType);
164
+ responseData = await readResponseData(fetchResponse, config);
165
+ if (config.schema) {
166
+ if (typeof config.schema.parseAsync === "function") {
167
+ responseData = await config.schema.parseAsync(responseData);
168
+ } else {
169
+ responseData = config.schema.parse(responseData);
170
+ }
171
+ }
129
172
  } catch (readError) {
173
+ if (readError instanceof import_accessioError.default) throw readError;
130
174
  throw import_accessioError.default.from(
131
175
  readError,
132
176
  import_accessioError.default.ERR_BAD_RESPONSE,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/fetchAdapter.ts"],"sourcesContent":["import AccessioError from './accessioError';\nimport parseHeaders from '../helpers/parseHeaders';\nimport type { AccessioRequestConfig, AccessioResponse } from '../types';\n\nasync function readResponseData(fetchResponse: Response, responseType: string): Promise<unknown> {\n switch (responseType) {\n case 'arraybuffer':\n return await fetchResponse.arrayBuffer();\n case 'blob':\n return await fetchResponse.blob();\n case 'stream':\n return fetchResponse.body;\n case 'json':\n default: {\n const contentType = fetchResponse.headers.get('content-type') || '';\n if (contentType.includes('application/json')) {\n if (typeof fetchResponse.clone === 'function') {\n const text = await fetchResponse.clone().text();\n return text ? await fetchResponse.json() : '';\n } else {\n const text = await fetchResponse.text();\n return text ? JSON.parse(text) : '';\n }\n }\n return await fetchResponse.text();\n }\n }\n}\n\nexport default async function fetchAdapter(\n config: AccessioRequestConfig,\n fullURL: string,\n fetchOptions: RequestInit,\n requestStartTime: number,\n): Promise<AccessioResponse> {\n let abortController: AbortController | null = null;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let isTimedOut = false;\n let onUserAbort: (() => void) | null = null;\n\n if (\n config.timeout !== undefined &&\n (typeof config.timeout !== 'number' || isNaN(config.timeout) || config.timeout < 0)\n ) {\n throw new AccessioError(\n `Invalid timeout value: ${config.timeout}`,\n AccessioError.ERR_BAD_OPTION_VALUE,\n config,\n null,\n null,\n );\n }\n\n const timeoutValue = Number(config.timeout);\n if (!isNaN(timeoutValue) && timeoutValue > 0) {\n abortController = new AbortController();\n\n timeoutId = setTimeout(() => {\n isTimedOut = true;\n abortController!.abort(\n new AccessioError(\n `timeout of ${timeoutValue}ms exceeded`,\n AccessioError.ETIMEDOUT,\n config,\n null,\n null,\n ),\n );\n }, timeoutValue);\n\n if (config.signal) {\n if (typeof AbortSignal.any === 'function') {\n fetchOptions.signal = AbortSignal.any([config.signal, abortController.signal]);\n } else {\n if (config.signal.aborted) {\n abortController.abort(config.signal.reason);\n } else {\n onUserAbort = () => {\n if (!isTimedOut && abortController) {\n abortController.abort(config.signal!.reason);\n }\n };\n config.signal.addEventListener('abort', onUserAbort, {\n once: true,\n });\n }\n fetchOptions.signal = abortController.signal;\n }\n } else {\n fetchOptions.signal = abortController.signal;\n }\n } else if (config.signal) {\n fetchOptions.signal = config.signal;\n }\n\n try {\n const fetchResponse = await fetch(fullURL, fetchOptions);\n\n let responseData: unknown;\n const responseType = config.responseType || 'json';\n\n const contentLength = fetchResponse.headers.get('content-length');\n if (\n contentLength &&\n config.maxContentLength &&\n parseInt(contentLength, 10) > config.maxContentLength\n ) {\n throw new AccessioError(\n `maxContentLength size of ${config.maxContentLength} exceeded`,\n AccessioError.ERR_BAD_RESPONSE,\n config,\n fetchResponse,\n null,\n );\n }\n\n try {\n responseData = await readResponseData(fetchResponse, responseType);\n } catch (readError) {\n throw AccessioError.from(\n readError as Error,\n AccessioError.ERR_BAD_RESPONSE,\n config,\n fetchResponse,\n null,\n );\n }\n\n const responseHeaders = parseHeaders(fetchResponse.headers);\n\n return {\n data: responseData,\n status: fetchResponse.status,\n statusText: fetchResponse.statusText,\n headers: responseHeaders,\n config: config,\n request: fetchResponse,\n duration: Date.now() - requestStartTime,\n };\n } catch (error) {\n if (error instanceof AccessioError) {\n throw error;\n }\n\n if (error instanceof Error && error.name === 'AbortError') {\n if (isTimedOut) {\n throw new AccessioError(\n `timeout of ${config.timeout}ms exceeded`,\n AccessioError.ETIMEDOUT,\n config,\n null,\n null,\n );\n }\n throw new AccessioError('Request aborted', AccessioError.ERR_CANCELED, config, null, null);\n }\n\n if (\n error instanceof TypeError &&\n (error.message.toLowerCase().includes('url') || error.message.toLowerCase().includes('fetch'))\n ) {\n throw new AccessioError(\n `Invalid URL: ${fullURL}`,\n AccessioError.ERR_INVALID_URL,\n config,\n null,\n null,\n );\n }\n\n throw AccessioError.from(\n error instanceof Error ? error : new Error(String(error)),\n AccessioError.ERR_NETWORK,\n config,\n null,\n null,\n );\n } finally {\n if (timeoutId) clearTimeout(timeoutId);\n if (config.signal && onUserAbort) {\n config.signal.removeEventListener('abort', onUserAbort);\n }\n }\n}\n"],"mappings":"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","names":["AccessioError","parseHeaders"]}
1
+ {"version":3,"sources":["../../src/core/fetchAdapter.ts"],"sourcesContent":["import AccessioError from './accessioError';\nimport parseHeaders from '../helpers/parseHeaders';\nimport type { AccessioRequestConfig, AccessioResponse } from '../types';\n\nasync function readResponseData(\n fetchResponse: Response,\n config: AccessioRequestConfig,\n): Promise<unknown> {\n const responseType = config.responseType || 'json';\n switch (responseType) {\n case 'arraybuffer':\n return await fetchResponse.arrayBuffer();\n case 'blob':\n return await fetchResponse.blob();\n case 'stream':\n return fetchResponse.body;\n case 'json':\n default: {\n const contentType = fetchResponse.headers.get('content-type') || '';\n if (contentType.includes('application/json')) {\n const text = await fetchResponse.text();\n if (!text) return '';\n try {\n return JSON.parse(text);\n } catch (err) {\n throw new AccessioError(\n `Failed to parse JSON response: ${(err as Error).message}. Raw body: ${\n text.length > 500 ? text.slice(0, 500) + '…' : text\n }`,\n AccessioError.ERR_BAD_RESPONSE,\n config,\n fetchResponse,\n null,\n );\n }\n }\n return await fetchResponse.text();\n }\n }\n}\n\nexport default async function fetchAdapter(\n config: AccessioRequestConfig,\n fullURL: string,\n fetchOptions: RequestInit,\n requestStartTime: number,\n): Promise<AccessioResponse> {\n let abortController: AbortController | null = null;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let isTimedOut = false;\n let onUserAbort: (() => void) | null = null;\n\n if (\n config.timeout !== undefined &&\n (typeof config.timeout !== 'number' || isNaN(config.timeout) || config.timeout < 0)\n ) {\n throw new AccessioError(\n `Invalid timeout value: ${config.timeout}`,\n AccessioError.ERR_BAD_OPTION_VALUE,\n config,\n null,\n null,\n );\n }\n\n const timeoutValue = Number(config.timeout);\n if (!isNaN(timeoutValue) && timeoutValue > 0) {\n abortController = new AbortController();\n\n timeoutId = setTimeout(() => {\n isTimedOut = true;\n abortController!.abort(\n new AccessioError(\n `timeout of ${timeoutValue}ms exceeded`,\n AccessioError.ETIMEDOUT,\n config,\n null,\n null,\n ),\n );\n }, timeoutValue);\n\n if (config.signal) {\n if (typeof AbortSignal.any === 'function') {\n fetchOptions.signal = AbortSignal.any([config.signal, abortController.signal]);\n } else {\n if (config.signal.aborted) {\n abortController.abort(config.signal.reason);\n } else {\n onUserAbort = () => {\n if (!isTimedOut && abortController) {\n abortController.abort(config.signal!.reason);\n }\n };\n config.signal.addEventListener('abort', onUserAbort, {\n once: true,\n });\n }\n fetchOptions.signal = abortController.signal;\n }\n } else {\n fetchOptions.signal = abortController.signal;\n }\n } else if (config.signal) {\n fetchOptions.signal = config.signal;\n }\n\n try {\n const fetchImpl = config.fetch || fetch;\n let fetchResponse = await fetchImpl(fullURL, fetchOptions);\n\n if (config.onDownloadProgress && fetchResponse.body && config.responseType !== 'stream') {\n const contentLength = fetchResponse.headers.get('content-length');\n const total = contentLength ? parseInt(contentLength, 10) : 0;\n let loaded = 0;\n\n const reader = fetchResponse.body.getReader();\n const stream = new ReadableStream({\n async start(controller) {\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n controller.close();\n break;\n }\n loaded += value.byteLength;\n config.onDownloadProgress!({ loaded, total });\n controller.enqueue(value);\n }\n } catch (e) {\n controller.error(e);\n }\n },\n });\n\n fetchResponse = new Response(stream, {\n headers: fetchResponse.headers,\n status: fetchResponse.status,\n statusText: fetchResponse.statusText,\n });\n }\n\n let responseData: unknown;\n\n const contentLength = fetchResponse.headers.get('content-length');\n if (\n contentLength &&\n config.maxContentLength &&\n parseInt(contentLength, 10) > config.maxContentLength\n ) {\n throw new AccessioError(\n `maxContentLength size of ${config.maxContentLength} exceeded`,\n AccessioError.ERR_BAD_RESPONSE,\n config,\n fetchResponse,\n null,\n );\n }\n\n try {\n responseData = await readResponseData(fetchResponse, config);\n if (config.schema) {\n if (typeof config.schema.parseAsync === 'function') {\n responseData = await config.schema.parseAsync(responseData);\n } else {\n responseData = config.schema.parse(responseData);\n }\n }\n } catch (readError) {\n if (readError instanceof AccessioError) throw readError;\n throw AccessioError.from(\n readError as Error,\n AccessioError.ERR_BAD_RESPONSE,\n config,\n fetchResponse,\n null,\n );\n }\n\n const responseHeaders = parseHeaders(fetchResponse.headers);\n\n return {\n data: responseData,\n status: fetchResponse.status,\n statusText: fetchResponse.statusText,\n headers: responseHeaders,\n config: config,\n request: fetchResponse,\n duration: Date.now() - requestStartTime,\n };\n } catch (error) {\n if (error instanceof AccessioError) {\n throw error;\n }\n\n if (error instanceof Error && error.name === 'AbortError') {\n if (isTimedOut) {\n throw new AccessioError(\n `timeout of ${config.timeout}ms exceeded`,\n AccessioError.ETIMEDOUT,\n config,\n null,\n null,\n );\n }\n throw new AccessioError('Request aborted', AccessioError.ERR_CANCELED, config, null, null);\n }\n\n if (\n error instanceof TypeError &&\n (error.message.toLowerCase().includes('url') || error.message.toLowerCase().includes('fetch'))\n ) {\n throw new AccessioError(\n `Invalid URL: ${fullURL}`,\n AccessioError.ERR_INVALID_URL,\n config,\n null,\n null,\n );\n }\n\n throw AccessioError.from(\n error instanceof Error ? error : new Error(String(error)),\n AccessioError.ERR_NETWORK,\n config,\n null,\n null,\n );\n } finally {\n if (timeoutId) clearTimeout(timeoutId);\n if (config.signal && onUserAbort) {\n config.signal.removeEventListener('abort', onUserAbort);\n }\n }\n}\n"],"mappings":"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","names":["AccessioError","contentLength","parseHeaders"]}