accessio 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +121 -391
  2. package/cjs/accessio.cjs +23 -52
  3. package/cjs/accessio.cjs.map +1 -1
  4. package/cjs/core/accessioError.cjs +1 -7
  5. package/cjs/core/accessioError.cjs.map +1 -1
  6. package/cjs/core/buildURL.cjs +3 -7
  7. package/cjs/core/buildURL.cjs.map +1 -1
  8. package/cjs/core/mergeConfig.cjs +2 -4
  9. package/cjs/core/mergeConfig.cjs.map +1 -1
  10. package/cjs/core/request.cjs +74 -66
  11. package/cjs/core/request.cjs.map +1 -1
  12. package/cjs/core/retry.cjs +2 -11
  13. package/cjs/core/retry.cjs.map +1 -1
  14. package/cjs/defaults/index.cjs.map +1 -1
  15. package/cjs/defaults/transforms.cjs +8 -1
  16. package/cjs/defaults/transforms.cjs.map +1 -1
  17. package/cjs/helpers/debug.cjs +1 -3
  18. package/cjs/helpers/debug.cjs.map +1 -1
  19. package/cjs/helpers/parseHeaders.cjs.map +1 -1
  20. package/cjs/helpers/rateLimiter.cjs +13 -7
  21. package/cjs/helpers/rateLimiter.cjs.map +1 -1
  22. package/cjs/helpers/transformData.cjs.map +1 -1
  23. package/cjs/index.cjs.map +1 -1
  24. package/cjs/interceptors/interceptorManager.cjs +40 -3
  25. package/cjs/interceptors/interceptorManager.cjs.map +1 -1
  26. package/package.json +7 -15
  27. package/src/accessio.ts +28 -72
  28. package/src/core/accessioError.ts +1 -7
  29. package/src/core/buildURL.ts +6 -15
  30. package/src/core/mergeConfig.ts +6 -16
  31. package/src/core/request.ts +90 -74
  32. package/src/core/retry.ts +4 -19
  33. package/src/defaults/index.ts +1 -3
  34. package/src/defaults/transforms.ts +9 -5
  35. package/src/helpers/debug.ts +12 -22
  36. package/src/helpers/parseHeaders.ts +1 -3
  37. package/src/helpers/rateLimiter.ts +19 -16
  38. package/src/helpers/transformData.ts +1 -4
  39. package/src/index.ts +3 -11
  40. package/src/interceptors/interceptorManager.ts +50 -2
  41. package/src/types.ts +8 -68
@@ -36,10 +36,7 @@ function flattenHeaders(
36
36
  }
37
37
 
38
38
  for (const key in headers) {
39
- if (
40
- Object.prototype.hasOwnProperty.call(headers, key) &&
41
- !METHOD_KEYS.has(key)
42
- ) {
39
+ if (Object.prototype.hasOwnProperty.call(headers, key) && !METHOD_KEYS.has(key)) {
43
40
  merged[key] = headers[key] as unknown as string;
44
41
  }
45
42
  }
@@ -48,10 +45,8 @@ function flattenHeaders(
48
45
  }
49
46
 
50
47
  function removeContentType(headers: Record<string, string>): void {
51
- const key = Object.keys(headers).find(
52
- (k) => k.toLowerCase() === 'content-type',
53
- );
54
- if (key) {
48
+ const keys = Object.keys(headers).filter((k) => k.toLowerCase() === 'content-type');
49
+ for (const key of keys) {
55
50
  delete headers[key];
56
51
  }
57
52
  }
@@ -64,9 +59,42 @@ function buildTransformArray(
64
59
  return [transform];
65
60
  }
66
61
 
67
- export default function dispatchRequest(
68
- config: AccessioRequestConfig,
69
- ): Promise<AccessioResponse> {
62
+ function setBasicAuth(config: AccessioRequestConfig, headers: Record<string, string>): void {
63
+ if (!config.auth) return;
64
+ const username = config.auth.username || '';
65
+ const password = config.auth.password || '';
66
+ const credentials = `${username}:${password}`;
67
+
68
+ let encoded: string;
69
+ if (typeof Buffer !== 'undefined') {
70
+ encoded = Buffer.from(credentials).toString('base64');
71
+ } else {
72
+ encoded = btoa(
73
+ encodeURIComponent(credentials).replace(/%([0-9A-F]{2})/g, (match, p1) => {
74
+ return String.fromCharCode(parseInt(p1, 16));
75
+ }),
76
+ );
77
+ }
78
+ headers['Authorization'] = `Basic ${encoded}`;
79
+ }
80
+
81
+ async function readResponseData(fetchResponse: Response, responseType: string): Promise<unknown> {
82
+ switch (responseType) {
83
+ case 'arraybuffer':
84
+ return await fetchResponse.arrayBuffer();
85
+ case 'blob':
86
+ return await fetchResponse.blob();
87
+ case 'text':
88
+ return await fetchResponse.text();
89
+ case 'stream':
90
+ return fetchResponse.body;
91
+ case 'json':
92
+ default:
93
+ return await fetchResponse.text();
94
+ }
95
+ }
96
+
97
+ export default function dispatchRequest(config: AccessioRequestConfig): Promise<AccessioResponse> {
70
98
  const fullURL =
71
99
  config._builtUrl ||
72
100
  buildURL(
@@ -76,19 +104,11 @@ export default function dispatchRequest(
76
104
  config.paramsSerializer,
77
105
  );
78
106
 
79
- const flatHeaders = flattenHeaders(
80
- config.headers as HeadersConfig | undefined,
81
- config.method,
82
- );
107
+ const flatHeaders = flattenHeaders(config.headers as HeadersConfig | undefined, config.method);
83
108
 
84
109
  const requestTransforms = buildTransformArray(config.transformRequest);
85
110
 
86
- const requestData = transformData(
87
- requestTransforms,
88
- config.data,
89
- flatHeaders,
90
- config,
91
- );
111
+ const requestData = transformData(requestTransforms, config.data, flatHeaders, config);
92
112
 
93
113
  if (
94
114
  requestData === null ||
@@ -98,24 +118,7 @@ export default function dispatchRequest(
98
118
  removeContentType(flatHeaders);
99
119
  }
100
120
 
101
- if (config.auth) {
102
- const username = config.auth.username || '';
103
- const password = config.auth.password || '';
104
- const credentials = `${username}:${password}`;
105
-
106
- let encoded: string;
107
- if (typeof Buffer !== 'undefined') {
108
- encoded = Buffer.from(credentials).toString('base64');
109
- } else {
110
- const bytes = new TextEncoder().encode(credentials);
111
- const binString = Array.from(bytes, (x) =>
112
- String.fromCodePoint(x),
113
- ).join('');
114
- encoded = btoa(binString);
115
- }
116
-
117
- flatHeaders['Authorization'] = `Basic ${encoded}`;
118
- }
121
+ setBasicAuth(config, flatHeaders);
119
122
 
120
123
  const fetchOptions: RequestInit = {
121
124
  method: (config.method || 'GET').toUpperCase(),
@@ -135,39 +138,46 @@ export default function dispatchRequest(
135
138
  fetchOptions.credentials = 'include';
136
139
  }
137
140
 
141
+ if (config.dispatcher) {
142
+ (fetchOptions as any).dispatcher = config.dispatcher;
143
+ }
144
+ if (config.agent) {
145
+ (fetchOptions as any).agent = config.agent;
146
+ }
147
+
138
148
  let abortController: AbortController | null = null;
139
149
  let timeoutId: ReturnType<typeof setTimeout> | null = null;
140
150
  let isTimedOut = false;
141
151
  let onUserAbort: (() => void) | null = null;
142
152
 
143
- if (config.timeout && config.timeout > 0) {
153
+ const timeoutValue = Number(config.timeout);
154
+ if (!isNaN(timeoutValue) && timeoutValue > 0) {
144
155
  abortController = new AbortController();
145
156
 
146
157
  timeoutId = setTimeout(() => {
147
158
  isTimedOut = true;
148
159
  abortController!.abort(
149
160
  new AccessioError(
150
- `timeout of ${config.timeout}ms exceeded`,
161
+ `timeout of ${timeoutValue}ms exceeded`,
151
162
  AccessioError.ETIMEDOUT,
152
163
  config,
153
164
  null,
154
165
  null,
155
166
  ),
156
167
  );
157
- }, config.timeout);
168
+ }, timeoutValue);
158
169
 
159
170
  if (config.signal) {
160
171
  if (typeof AbortSignal.any === 'function') {
161
- fetchOptions.signal = AbortSignal.any([
162
- config.signal,
163
- abortController.signal,
164
- ]);
172
+ fetchOptions.signal = AbortSignal.any([config.signal, abortController.signal]);
165
173
  } else {
166
174
  if (config.signal.aborted) {
167
175
  abortController.abort(config.signal.reason);
168
176
  } else {
169
177
  onUserAbort = () => {
170
- abortController!.abort(config.signal!.reason);
178
+ if (!isTimedOut && abortController) {
179
+ abortController.abort(config.signal!.reason);
180
+ }
171
181
  };
172
182
  config.signal.addEventListener('abort', onUserAbort, {
173
183
  once: true,
@@ -189,25 +199,23 @@ export default function dispatchRequest(
189
199
  let responseData: unknown;
190
200
  const responseType = config.responseType || 'json';
191
201
 
202
+ const contentLength = fetchResponse.headers.get('content-length');
203
+ if (
204
+ contentLength &&
205
+ config.maxContentLength &&
206
+ parseInt(contentLength, 10) > config.maxContentLength
207
+ ) {
208
+ throw new AccessioError(
209
+ `maxContentLength size of ${config.maxContentLength} exceeded`,
210
+ AccessioError.ERR_BAD_RESPONSE,
211
+ config,
212
+ fetchResponse,
213
+ null,
214
+ );
215
+ }
216
+
192
217
  try {
193
- switch (responseType) {
194
- case 'arraybuffer':
195
- responseData = await fetchResponse.arrayBuffer();
196
- break;
197
- case 'blob':
198
- responseData = await fetchResponse.blob();
199
- break;
200
- case 'text':
201
- responseData = await fetchResponse.text();
202
- break;
203
- case 'stream':
204
- responseData = fetchResponse.body;
205
- break;
206
- case 'json':
207
- default:
208
- responseData = await fetchResponse.text();
209
- break;
210
- }
218
+ responseData = await readResponseData(fetchResponse, responseType);
211
219
  } catch (readError) {
212
220
  throw AccessioError.from(
213
221
  readError as Error,
@@ -222,12 +230,7 @@ export default function dispatchRequest(
222
230
 
223
231
  const responseTransforms = buildTransformArray(config.transformResponse);
224
232
 
225
- responseData = transformData(
226
- responseTransforms,
227
- responseData,
228
- responseHeaders,
229
- config,
230
- );
233
+ responseData = transformData(responseTransforms, responseData, responseHeaders, config);
231
234
 
232
235
  const response: AccessioResponse = {
233
236
  data: responseData,
@@ -240,7 +243,12 @@ export default function dispatchRequest(
240
243
  };
241
244
 
242
245
  return new Promise<AccessioResponse>((resolve, reject) => {
243
- settle(resolve as (value: AccessioResponse) => void, reject as (reason: AccessioError) => void, response, config);
246
+ settle(
247
+ resolve as (value: AccessioResponse) => void,
248
+ reject as (reason: AccessioError) => void,
249
+ response,
250
+ config,
251
+ );
244
252
  });
245
253
  })
246
254
  .catch((error) => {
@@ -258,9 +266,17 @@ export default function dispatchRequest(
258
266
  null,
259
267
  );
260
268
  }
269
+ throw new AccessioError('Request aborted', AccessioError.ERR_CANCELED, config, null, null);
270
+ }
271
+
272
+ if (
273
+ error instanceof TypeError &&
274
+ (error.message.toLowerCase().includes('url') ||
275
+ error.message.toLowerCase().includes('fetch'))
276
+ ) {
261
277
  throw new AccessioError(
262
- 'Request aborted',
263
- AccessioError.ERR_CANCELED,
278
+ `Invalid URL: ${fullURL}`,
279
+ AccessioError.ERR_INVALID_URL,
264
280
  config,
265
281
  null,
266
282
  null,
package/src/core/retry.ts CHANGED
@@ -1,8 +1,4 @@
1
- import {
2
- ERR_CANCELED,
3
- ERR_NETWORK,
4
- ETIMEDOUT,
5
- } from '../constants/errorCodes';
1
+ import { ERR_CANCELED, ERR_NETWORK, ETIMEDOUT } from '../constants/errorCodes';
6
2
  import type {
7
3
  AccessioRequestConfig,
8
4
  AccessioResponse,
@@ -20,10 +16,6 @@ function defaultRetryCondition(error: any): boolean {
20
16
  return true;
21
17
  }
22
18
 
23
- if (error.code === ETIMEDOUT) {
24
- return true;
25
- }
26
-
27
19
  if (error.response && error.response.status >= 500) {
28
20
  return true;
29
21
  }
@@ -51,9 +43,7 @@ function sleep(ms: number, options?: { signal?: AbortSignal }): Promise<void> {
51
43
  if (options?.signal) {
52
44
  if (options.signal.aborted) {
53
45
  clearTimeout(timeoutId);
54
- return reject(
55
- options.signal.reason || new Error('Sleep aborted'),
56
- );
46
+ return reject(options.signal.reason || new Error('Sleep aborted'));
57
47
  }
58
48
 
59
49
  onAbort = () => {
@@ -77,8 +67,7 @@ async function retryRequest(
77
67
  }
78
68
 
79
69
  const retryDelay = config.retryDelay ?? 1000;
80
- const retryCondition: RetryConditionFunction =
81
- config.retryCondition ?? defaultRetryCondition;
70
+ const retryCondition: RetryConditionFunction = config.retryCondition ?? defaultRetryCondition;
82
71
 
83
72
  let lastError: any;
84
73
 
@@ -99,11 +88,7 @@ async function retryRequest(
99
88
  const delay = calculateDelay(attempt, retryDelay);
100
89
 
101
90
  if (typeof config.onRetry === 'function') {
102
- (config.onRetry as OnRetryFunction)(
103
- attempt + 1,
104
- error as AccessioError,
105
- config,
106
- );
91
+ (config.onRetry as OnRetryFunction)(attempt + 1, error as AccessioError, config);
107
92
  }
108
93
 
109
94
  await sleep(delay, { signal: config.signal });
@@ -24,9 +24,7 @@ const defaults: AccessioRequestConfig = {
24
24
  },
25
25
  transformRequest: [defaultTransformRequest],
26
26
  transformResponse: [defaultTransformResponse],
27
- validateStatus: function defaultValidateStatus(
28
- status: number,
29
- ): boolean {
27
+ validateStatus: function defaultValidateStatus(status: number): boolean {
30
28
  return status >= 200 && status < 300;
31
29
  },
32
30
  responseType: 'json',
@@ -1,7 +1,4 @@
1
- export function defaultTransformRequest(
2
- data: unknown,
3
- headers: Record<string, string>,
4
- ): unknown {
1
+ export function defaultTransformRequest(data: unknown, headers: Record<string, string>): unknown {
5
2
  if (data === null || data === undefined) {
6
3
  return data;
7
4
  }
@@ -26,7 +23,14 @@ export function defaultTransformRequest(
26
23
  headers['Content-Type'] = 'application/json';
27
24
  }
28
25
  }
29
- return JSON.stringify(data);
26
+ try {
27
+ return JSON.stringify(data);
28
+ } catch (e: any) {
29
+ if (e instanceof TypeError && e.message.toLowerCase().includes('circular')) {
30
+ throw new Error('Accessio: Cannot stringify circular structure in request data');
31
+ }
32
+ throw e;
33
+ }
30
34
  }
31
35
 
32
36
  return data;
@@ -8,9 +8,11 @@ function formatBytes(bytes: number): string {
8
8
  return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${sizes[i]}`;
9
9
  }
10
10
 
11
- function sanitizeConfigForLog(
12
- config: AccessioRequestConfig,
13
- ): { params: Record<string, unknown> | undefined; timeout: number | undefined; retry: number | undefined } {
11
+ function sanitizeConfigForLog(config: AccessioRequestConfig): {
12
+ params: Record<string, unknown> | undefined;
13
+ timeout: number | undefined;
14
+ retry: number | undefined;
15
+ } {
14
16
  return {
15
17
  params: config.params,
16
18
  timeout: config.timeout,
@@ -18,10 +20,7 @@ function sanitizeConfigForLog(
18
20
  };
19
21
  }
20
22
 
21
- export function logRequest(
22
- config: AccessioRequestConfig,
23
- fullUrl: string,
24
- ): void {
23
+ export function logRequest(config: AccessioRequestConfig, fullUrl: string): void {
25
24
  if (!config.debug) return;
26
25
 
27
26
  const safe = sanitizeConfigForLog(config);
@@ -37,8 +36,7 @@ export function logRequest(
37
36
 
38
37
  if (config.data && typeof config.data === 'object') {
39
38
  const preview = JSON.stringify(config.data);
40
- const truncated =
41
- preview.length > 200 ? `${preview.substring(0, 200)}...` : preview;
39
+ const truncated = preview.length > 200 ? `${preview.substring(0, 200)}...` : preview;
42
40
  parts.push(` Body: ${truncated}`);
43
41
  }
44
42
 
@@ -57,19 +55,11 @@ export function logResponse(response: AccessioResponse): void {
57
55
  if (!response.config || !response.config.debug) return;
58
56
  const status = response.status;
59
57
  const statusText = response.statusText || '';
60
- const duration =
61
- response.duration != null ? `${response.duration}ms` : '??';
62
-
63
- const statusIcon =
64
- status >= 200 && status < 300
65
- ? '✅'
66
- : status >= 400
67
- ? '❌'
68
- : '⚠️';
69
-
70
- const parts: string[] = [
71
- `🐦‍⬛ [Accessio] ← ${statusIcon} ${status} ${statusText} (${duration})`,
72
- ];
58
+ const duration = response.duration != null ? `${response.duration}ms` : '??';
59
+
60
+ const statusIcon = status >= 200 && status < 300 ? '✅' : status >= 400 ? '❌' : '⚠️';
61
+
62
+ const parts: string[] = [`🐦‍⬛ [Accessio] ← ${statusIcon} ${status} ${statusText} (${duration})`];
73
63
 
74
64
  if (response.data) {
75
65
  try {
@@ -1,6 +1,4 @@
1
- export default function parseHeaders(
2
- headers: any,
3
- ): Record<string, string> {
1
+ export default function parseHeaders(headers: any): Record<string, string> {
4
2
  const parsed: Record<string, string> = {};
5
3
 
6
4
  if (!headers) return parsed;
@@ -1,32 +1,31 @@
1
- import type {
2
- RateLimiter,
3
- AccessioRequestConfig,
4
- AccessioResponse,
5
- } from '../types';
1
+ import type { RateLimiter, AccessioRequestConfig, AccessioResponse } from '../types';
6
2
 
7
3
  interface QueueItem {
8
4
  resolve: () => void;
9
5
  reject: (reason: Error) => void;
10
6
  }
11
7
 
12
- export function createRateLimiter(maxConcurrent: number = Infinity): RateLimiter {
13
- if (
14
- maxConcurrent !== Infinity &&
15
- (!Number.isInteger(maxConcurrent) || maxConcurrent < 1)
16
- ) {
8
+ export function createRateLimiter(
9
+ maxConcurrent: number = Infinity,
10
+ maxQueueSize: number = Infinity,
11
+ ): RateLimiter {
12
+ if (maxConcurrent !== Infinity && (!Number.isInteger(maxConcurrent) || maxConcurrent < 1)) {
17
13
  throw new RangeError(
18
14
  `[Accessio] maxConcurrent must be a positive integer or Infinity, got: ${maxConcurrent}`,
19
15
  );
20
16
  }
17
+ if (maxQueueSize !== Infinity && (!Number.isInteger(maxQueueSize) || maxQueueSize < 1)) {
18
+ throw new RangeError(
19
+ `[Accessio] maxQueueSize must be a positive integer or Infinity, got: ${maxQueueSize}`,
20
+ );
21
+ }
21
22
  let active = 0;
22
23
  let destroyed = false;
23
24
  const queue: QueueItem[] = [];
24
25
 
25
26
  function acquire(): Promise<void> {
26
27
  if (destroyed) {
27
- return Promise.reject(
28
- new Error('[Accessio] Rate limiter has been destroyed'),
29
- );
28
+ return Promise.reject(new Error('[Accessio] Rate limiter has been destroyed'));
30
29
  }
31
30
 
32
31
  if (active < maxConcurrent) {
@@ -34,6 +33,12 @@ export function createRateLimiter(maxConcurrent: number = Infinity): RateLimiter
34
33
  return Promise.resolve();
35
34
  }
36
35
 
36
+ if (queue.length >= maxQueueSize) {
37
+ return Promise.reject(
38
+ new Error(`[Accessio] Rate limiter queue size exceeded maxQueueSize (${maxQueueSize})`),
39
+ );
40
+ }
41
+
37
42
  return new Promise((resolve, reject) => {
38
43
  queue.push({ resolve, reject });
39
44
  });
@@ -55,9 +60,7 @@ export function createRateLimiter(maxConcurrent: number = Infinity): RateLimiter
55
60
 
56
61
  function destroy(): void {
57
62
  destroyed = true;
58
- const reason = new Error(
59
- '[Accessio] Rate limiter destroyed — pending request cancelled',
60
- );
63
+ const reason = new Error('[Accessio] Rate limiter destroyed — pending request cancelled');
61
64
  while (queue.length > 0) {
62
65
  const next = queue.shift();
63
66
  next?.reject(reason);
@@ -1,8 +1,5 @@
1
1
  import AccessioError from '../core/accessioError';
2
- import type {
3
- TransformFunction,
4
- AccessioRequestConfig,
5
- } from '../types';
2
+ import type { TransformFunction, AccessioRequestConfig } from '../types';
6
3
 
7
4
  export default function transformData(
8
5
  transforms: TransformFunction | TransformFunction[] | undefined,
package/src/index.ts CHANGED
@@ -46,23 +46,15 @@ function createInstance(defaultConfig: AccessioRequestConfig) {
46
46
  instance.all = function all(promises: any[]): Promise<any[]> {
47
47
  return Promise.all(promises);
48
48
  };
49
- instance.spread = function spread<T>(
50
- callback: (...args: any[]) => T,
51
- ): (arr: any[]) => T {
49
+ instance.spread = function spread<T>(callback: (...args: any[]) => T): (arr: any[]) => T {
52
50
  return function wrap(arr: any[]): T {
53
51
  return callback(...arr);
54
52
  };
55
53
  };
56
54
  instance.isCancel = function isCancel(value: any): boolean {
57
- return !!(
58
- value &&
59
- value.isAccessioError &&
60
- value.code === ERR_CANCELED
61
- );
55
+ return !!(value && value.isAccessioError && value.code === ERR_CANCELED);
62
56
  };
63
- instance.isAccessioError = function isAccessioError(
64
- value: any,
65
- ): boolean {
57
+ instance.isAccessioError = function isAccessioError(value: any): boolean {
66
58
  return (
67
59
  value instanceof AccessioError ||
68
60
  !!(value && typeof value === 'object' && value.isAccessioError === true)
@@ -1,5 +1,53 @@
1
- import { InterceptorManager } from '../types';
1
+ import type { TransformFunction, InterceptorHandler, InterceptorOptions } from '../types';
2
2
 
3
- export { InterceptorManager };
3
+ export class InterceptorManager {
4
+ handlers: Array<InterceptorHandler | null>;
5
+ private _activeCount: number;
6
+
7
+ constructor() {
8
+ this.handlers = [];
9
+ this._activeCount = 0;
10
+ }
11
+
12
+ use(
13
+ fulfilled: TransformFunction | null,
14
+ rejected?: ((error: unknown) => unknown) | null,
15
+ options: InterceptorOptions = {},
16
+ ): number {
17
+ this.handlers.push({
18
+ fulfilled: fulfilled || null,
19
+ rejected: rejected || null,
20
+ synchronous: options.synchronous || false,
21
+ runWhen: options.runWhen || null,
22
+ });
23
+
24
+ this._activeCount++;
25
+ return this.handlers.length - 1;
26
+ }
27
+
28
+ eject(id: number): void {
29
+ if (this.handlers[id]) {
30
+ this.handlers[id] = null;
31
+ this._activeCount--;
32
+ }
33
+ }
34
+
35
+ clear(): void {
36
+ this.handlers = [];
37
+ this._activeCount = 0;
38
+ }
39
+
40
+ forEach(fn: (handler: InterceptorHandler) => void): void {
41
+ for (const handler of this.handlers) {
42
+ if (handler !== null) {
43
+ fn(handler);
44
+ }
45
+ }
46
+ }
47
+
48
+ get size(): number {
49
+ return this._activeCount;
50
+ }
51
+ }
4
52
 
5
53
  export default InterceptorManager;
package/src/types.ts CHANGED
@@ -1,18 +1,8 @@
1
- export type Method =
2
- | 'get'
3
- | 'delete'
4
- | 'head'
5
- | 'options'
6
- | 'post'
7
- | 'put'
8
- | 'patch';
1
+ import type InterceptorManager from './interceptors/interceptorManager';
9
2
 
10
- export type ResponseType =
11
- | 'json'
12
- | 'text'
13
- | 'blob'
14
- | 'arraybuffer'
15
- | 'stream';
3
+ export type Method = 'get' | 'delete' | 'head' | 'options' | 'post' | 'put' | 'patch';
4
+
5
+ export type ResponseType = 'json' | 'text' | 'blob' | 'arraybuffer' | 'stream';
16
6
 
17
7
  export interface AuthConfig {
18
8
  username: string;
@@ -21,10 +11,7 @@ export interface AuthConfig {
21
11
 
22
12
  export type ParamsSerializer = (params: Record<string, unknown>) => string;
23
13
 
24
- export type TransformFunction = (
25
- data: unknown,
26
- headers: Record<string, string>,
27
- ) => unknown;
14
+ export type TransformFunction = (data: unknown, headers: Record<string, string>) => unknown;
28
15
 
29
16
  export type RetryConditionFunction = (error: AccessioError) => boolean;
30
17
 
@@ -76,6 +63,9 @@ export interface AccessioRequestConfig {
76
63
  debug?: boolean;
77
64
  rateLimiter?: RateLimiter;
78
65
  _builtUrl?: string;
66
+ maxContentLength?: number;
67
+ dispatcher?: unknown;
68
+ agent?: unknown;
79
69
  }
80
70
 
81
71
  export interface AccessioResponse<T = unknown> {
@@ -99,56 +89,6 @@ export interface AccessioError extends Error {
99
89
  toJSON(): Record<string, unknown>;
100
90
  }
101
91
 
102
- export class InterceptorManager {
103
- handlers: Array<InterceptorHandler | null>;
104
- private _activeCount: number;
105
-
106
- constructor() {
107
- this.handlers = [];
108
- this._activeCount = 0;
109
- }
110
-
111
- use(
112
- fulfilled: TransformFunction,
113
- rejected?: (error: unknown) => unknown,
114
- options: InterceptorOptions = {},
115
- ): number {
116
- this.handlers.push({
117
- fulfilled: fulfilled || null,
118
- rejected: rejected || null,
119
- synchronous: options.synchronous || false,
120
- runWhen: options.runWhen || null,
121
- });
122
-
123
- this._activeCount++;
124
- return this.handlers.length - 1;
125
- }
126
-
127
- eject(id: number): void {
128
- if (this.handlers[id]) {
129
- this.handlers[id] = null;
130
- this._activeCount--;
131
- }
132
- }
133
-
134
- clear(): void {
135
- this.handlers = [];
136
- this._activeCount = 0;
137
- }
138
-
139
- forEach(fn: (handler: InterceptorHandler) => void): void {
140
- for (const handler of this.handlers) {
141
- if (handler !== null) {
142
- fn(handler);
143
- }
144
- }
145
- }
146
-
147
- get size(): number {
148
- return this._activeCount;
149
- }
150
- }
151
-
152
92
  export interface RateLimiter {
153
93
  acquire: () => Promise<void>;
154
94
  release: () => void;