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
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/retry.ts"],"sourcesContent":["import {\n ERR_CANCELED,\n ERR_NETWORK,\n ETIMEDOUT,\n} from '../constants/errorCodes';\nimport type {\n AccessioRequestConfig,\n AccessioResponse,\n AccessioError,\n RetryConditionFunction,\n OnRetryFunction,\n} from '../types';\n\nfunction defaultRetryCondition(error: any): boolean {\n if (error.code === ERR_CANCELED) {\n return false;\n }\n\n if (error.code === ERR_NETWORK) {\n return true;\n }\n\n if (error.code === ETIMEDOUT) {\n return true;\n }\n\n if (error.response && error.response.status >= 500) {\n return true;\n }\n\n return false;\n}\n\nfunction calculateDelay(attempt: number, baseDelay: number): number {\n const exponentialDelay = baseDelay * Math.pow(2, attempt);\n const jitter = exponentialDelay * 0.25 * (Math.random() * 2 - 1);\n return Math.round(exponentialDelay + jitter);\n}\n\nfunction sleep(ms: number, options?: { signal?: AbortSignal }): Promise<void> {\n return new Promise((resolve, reject) => {\n let onAbort: (() => void) | undefined;\n\n const timeoutId = setTimeout(() => {\n if (options?.signal && onAbort) {\n options.signal.removeEventListener('abort', onAbort);\n }\n resolve();\n }, ms);\n\n if (options?.signal) {\n if (options.signal.aborted) {\n clearTimeout(timeoutId);\n return reject(\n options.signal.reason || new Error('Sleep aborted'),\n );\n }\n\n onAbort = () => {\n clearTimeout(timeoutId);\n reject(options.signal!.reason || new Error('Sleep aborted'));\n };\n\n options.signal.addEventListener('abort', onAbort, { once: true });\n }\n });\n}\n\nasync function retryRequest(\n dispatchFn: (config: AccessioRequestConfig) => Promise<any>,\n config: AccessioRequestConfig,\n): Promise<any> {\n const maxRetries = config.retry ?? 0;\n\n if (maxRetries <= 0) {\n return dispatchFn(config);\n }\n\n const retryDelay = config.retryDelay ?? 1000;\n const retryCondition: RetryConditionFunction =\n config.retryCondition ?? defaultRetryCondition;\n\n let lastError: any;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const response = await dispatchFn(config);\n return response;\n } catch (error) {\n lastError = error;\n\n const isLastAttempt = attempt >= maxRetries;\n const shouldRetry = !isLastAttempt && retryCondition(error as AccessioError);\n\n if (!shouldRetry) {\n throw error;\n }\n\n const delay = calculateDelay(attempt, retryDelay);\n\n if (typeof config.onRetry === 'function') {\n (config.onRetry as OnRetryFunction)(\n attempt + 1,\n error as AccessioError,\n config,\n );\n }\n\n await sleep(delay, { signal: config.signal });\n }\n }\n\n throw lastError;\n}\n\nexport { defaultRetryCondition, calculateDelay };\nexport default retryRequest;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAIO;AASP,SAAS,sBAAsB,OAAqB;AAClD,MAAI,MAAM,SAAS,gCAAc;AAC/B,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,SAAS,+BAAa;AAC9B,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,SAAS,6BAAW;AAC5B,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,YAAY,MAAM,SAAS,UAAU,KAAK;AAClD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,eAAe,SAAiB,WAA2B;AAClE,QAAM,mBAAmB,YAAY,KAAK,IAAI,GAAG,OAAO;AACxD,QAAM,SAAS,mBAAmB,QAAQ,KAAK,OAAO,IAAI,IAAI;AAC9D,SAAO,KAAK,MAAM,mBAAmB,MAAM;AAC7C;AAEA,SAAS,MAAM,IAAY,SAAmD;AAC5E,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,QAAI;AAEJ,UAAM,YAAY,WAAW,MAAM;AACjC,UAAI,SAAS,UAAU,SAAS;AAC9B,gBAAQ,OAAO,oBAAoB,SAAS,OAAO;AAAA,MACrD;AACA,cAAQ;AAAA,IACV,GAAG,EAAE;AAEL,QAAI,SAAS,QAAQ;AACnB,UAAI,QAAQ,OAAO,SAAS;AAC1B,qBAAa,SAAS;AACtB,eAAO;AAAA,UACL,QAAQ,OAAO,UAAU,IAAI,MAAM,eAAe;AAAA,QACpD;AAAA,MACF;AAEA,gBAAU,MAAM;AACd,qBAAa,SAAS;AACtB,eAAO,QAAQ,OAAQ,UAAU,IAAI,MAAM,eAAe,CAAC;AAAA,MAC7D;AAEA,cAAQ,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,IAClE;AAAA,EACF,CAAC;AACH;AAEA,eAAe,aACb,YACA,QACc;AACd,QAAM,aAAa,OAAO,SAAS;AAEnC,MAAI,cAAc,GAAG;AACnB,WAAO,WAAW,MAAM;AAAA,EAC1B;AAEA,QAAM,aAAa,OAAO,cAAc;AACxC,QAAM,iBACJ,OAAO,kBAAkB;AAE3B,MAAI;AAEJ,WAAS,UAAU,GAAG,WAAW,YAAY,WAAW;AACtD,QAAI;AACF,YAAM,WAAW,MAAM,WAAW,MAAM;AACxC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,kBAAY;AAEZ,YAAM,gBAAgB,WAAW;AACjC,YAAM,cAAc,CAAC,iBAAiB,eAAe,KAAsB;AAE3E,UAAI,CAAC,aAAa;AAChB,cAAM;AAAA,MACR;AAEA,YAAM,QAAQ,eAAe,SAAS,UAAU;AAEhD,UAAI,OAAO,OAAO,YAAY,YAAY;AACxC,QAAC,OAAO;AAAA,UACN,UAAU;AAAA,UACV;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,YAAM,MAAM,OAAO,EAAE,QAAQ,OAAO,OAAO,CAAC;AAAA,IAC9C;AAAA,EACF;AAEA,QAAM;AACR;AAGA,IAAO,gBAAQ;","names":[]}
1
+ {"version":3,"sources":["../../src/core/retry.ts"],"sourcesContent":["import { ERR_CANCELED, ERR_NETWORK, ETIMEDOUT } from '../constants/errorCodes';\nimport type {\n AccessioRequestConfig,\n AccessioResponse,\n AccessioError,\n RetryConditionFunction,\n OnRetryFunction,\n} from '../types';\n\nfunction defaultRetryCondition(error: any): boolean {\n if (error.code === ERR_CANCELED) {\n return false;\n }\n\n if (error.code === ERR_NETWORK) {\n return true;\n }\n\n if (error.response && error.response.status >= 500) {\n return true;\n }\n\n return false;\n}\n\nfunction calculateDelay(attempt: number, baseDelay: number): number {\n const exponentialDelay = baseDelay * Math.pow(2, attempt);\n const jitter = exponentialDelay * 0.25 * (Math.random() * 2 - 1);\n return Math.round(exponentialDelay + jitter);\n}\n\nfunction sleep(ms: number, options?: { signal?: AbortSignal }): Promise<void> {\n return new Promise((resolve, reject) => {\n let onAbort: (() => void) | undefined;\n\n const timeoutId = setTimeout(() => {\n if (options?.signal && onAbort) {\n options.signal.removeEventListener('abort', onAbort);\n }\n resolve();\n }, ms);\n\n if (options?.signal) {\n if (options.signal.aborted) {\n clearTimeout(timeoutId);\n return reject(options.signal.reason || new Error('Sleep aborted'));\n }\n\n onAbort = () => {\n clearTimeout(timeoutId);\n reject(options.signal!.reason || new Error('Sleep aborted'));\n };\n\n options.signal.addEventListener('abort', onAbort, { once: true });\n }\n });\n}\n\nasync function retryRequest(\n dispatchFn: (config: AccessioRequestConfig) => Promise<any>,\n config: AccessioRequestConfig,\n): Promise<any> {\n const maxRetries = config.retry ?? 0;\n\n if (maxRetries <= 0) {\n return dispatchFn(config);\n }\n\n const retryDelay = config.retryDelay ?? 1000;\n const retryCondition: RetryConditionFunction = config.retryCondition ?? defaultRetryCondition;\n\n let lastError: any;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const response = await dispatchFn(config);\n return response;\n } catch (error) {\n lastError = error;\n\n const isLastAttempt = attempt >= maxRetries;\n const shouldRetry = !isLastAttempt && retryCondition(error as AccessioError);\n\n if (!shouldRetry) {\n throw error;\n }\n\n const delay = calculateDelay(attempt, retryDelay);\n\n if (typeof config.onRetry === 'function') {\n (config.onRetry as OnRetryFunction)(attempt + 1, error as AccessioError, config);\n }\n\n await sleep(delay, { signal: config.signal });\n }\n }\n\n throw lastError;\n}\n\nexport { defaultRetryCondition, calculateDelay };\nexport default retryRequest;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAqD;AASrD,SAAS,sBAAsB,OAAqB;AAClD,MAAI,MAAM,SAAS,gCAAc;AAC/B,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,SAAS,+BAAa;AAC9B,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,YAAY,MAAM,SAAS,UAAU,KAAK;AAClD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,eAAe,SAAiB,WAA2B;AAClE,QAAM,mBAAmB,YAAY,KAAK,IAAI,GAAG,OAAO;AACxD,QAAM,SAAS,mBAAmB,QAAQ,KAAK,OAAO,IAAI,IAAI;AAC9D,SAAO,KAAK,MAAM,mBAAmB,MAAM;AAC7C;AAEA,SAAS,MAAM,IAAY,SAAmD;AAC5E,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,QAAI;AAEJ,UAAM,YAAY,WAAW,MAAM;AACjC,UAAI,SAAS,UAAU,SAAS;AAC9B,gBAAQ,OAAO,oBAAoB,SAAS,OAAO;AAAA,MACrD;AACA,cAAQ;AAAA,IACV,GAAG,EAAE;AAEL,QAAI,SAAS,QAAQ;AACnB,UAAI,QAAQ,OAAO,SAAS;AAC1B,qBAAa,SAAS;AACtB,eAAO,OAAO,QAAQ,OAAO,UAAU,IAAI,MAAM,eAAe,CAAC;AAAA,MACnE;AAEA,gBAAU,MAAM;AACd,qBAAa,SAAS;AACtB,eAAO,QAAQ,OAAQ,UAAU,IAAI,MAAM,eAAe,CAAC;AAAA,MAC7D;AAEA,cAAQ,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,IAClE;AAAA,EACF,CAAC;AACH;AAEA,eAAe,aACb,YACA,QACc;AACd,QAAM,aAAa,OAAO,SAAS;AAEnC,MAAI,cAAc,GAAG;AACnB,WAAO,WAAW,MAAM;AAAA,EAC1B;AAEA,QAAM,aAAa,OAAO,cAAc;AACxC,QAAM,iBAAyC,OAAO,kBAAkB;AAExE,MAAI;AAEJ,WAAS,UAAU,GAAG,WAAW,YAAY,WAAW;AACtD,QAAI;AACF,YAAM,WAAW,MAAM,WAAW,MAAM;AACxC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,kBAAY;AAEZ,YAAM,gBAAgB,WAAW;AACjC,YAAM,cAAc,CAAC,iBAAiB,eAAe,KAAsB;AAE3E,UAAI,CAAC,aAAa;AAChB,cAAM;AAAA,MACR;AAEA,YAAM,QAAQ,eAAe,SAAS,UAAU;AAEhD,UAAI,OAAO,OAAO,YAAY,YAAY;AACxC,QAAC,OAAO,QAA4B,UAAU,GAAG,OAAwB,MAAM;AAAA,MACjF;AAEA,YAAM,MAAM,OAAO,EAAE,QAAQ,OAAO,OAAO,CAAC;AAAA,IAC9C;AAAA,EACF;AAEA,QAAM;AACR;AAGA,IAAO,gBAAQ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/defaults/index.ts"],"sourcesContent":["import { defaultTransformRequest, defaultTransformResponse } from './transforms';\nimport type { AccessioRequestConfig } from '../types';\n\nconst defaults: AccessioRequestConfig = {\n method: 'get',\n timeout: 0,\n headers: {\n common: {\n Accept: 'application/json, text/plain, */*',\n },\n delete: {},\n get: {},\n head: {},\n options: {},\n post: {\n 'Content-Type': 'application/json',\n },\n put: {\n 'Content-Type': 'application/json',\n },\n patch: {\n 'Content-Type': 'application/json',\n },\n },\n transformRequest: [defaultTransformRequest],\n transformResponse: [defaultTransformResponse],\n validateStatus: function defaultValidateStatus(\n status: number,\n ): boolean {\n return status >= 200 && status < 300;\n },\n responseType: 'json',\n withCredentials: false,\n};\n\nexport default defaults;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAkE;AAGlE,MAAM,WAAkC;AAAA,EACtC,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AAAA,IACP,QAAQ;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,IACA,QAAQ,CAAC;AAAA,IACT,KAAK,CAAC;AAAA,IACN,MAAM,CAAC;AAAA,IACP,SAAS,CAAC;AAAA,IACV,MAAM;AAAA,MACJ,gBAAgB;AAAA,IAClB;AAAA,IACA,KAAK;AAAA,MACH,gBAAgB;AAAA,IAClB;AAAA,IACA,OAAO;AAAA,MACL,gBAAgB;AAAA,IAClB;AAAA,EACF;AAAA,EACA,kBAAkB,CAAC,yCAAuB;AAAA,EAC1C,mBAAmB,CAAC,0CAAwB;AAAA,EAC5C,gBAAgB,SAAS,sBACvB,QACS;AACT,WAAO,UAAU,OAAO,SAAS;AAAA,EACnC;AAAA,EACA,cAAc;AAAA,EACd,iBAAiB;AACnB;AAEA,IAAO,mBAAQ;","names":[]}
1
+ {"version":3,"sources":["../../src/defaults/index.ts"],"sourcesContent":["import { defaultTransformRequest, defaultTransformResponse } from './transforms';\nimport type { AccessioRequestConfig } from '../types';\n\nconst defaults: AccessioRequestConfig = {\n method: 'get',\n timeout: 0,\n headers: {\n common: {\n Accept: 'application/json, text/plain, */*',\n },\n delete: {},\n get: {},\n head: {},\n options: {},\n post: {\n 'Content-Type': 'application/json',\n },\n put: {\n 'Content-Type': 'application/json',\n },\n patch: {\n 'Content-Type': 'application/json',\n },\n },\n transformRequest: [defaultTransformRequest],\n transformResponse: [defaultTransformResponse],\n validateStatus: function defaultValidateStatus(status: number): boolean {\n return status >= 200 && status < 300;\n },\n responseType: 'json',\n withCredentials: false,\n};\n\nexport default defaults;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAkE;AAGlE,MAAM,WAAkC;AAAA,EACtC,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AAAA,IACP,QAAQ;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,IACA,QAAQ,CAAC;AAAA,IACT,KAAK,CAAC;AAAA,IACN,MAAM,CAAC;AAAA,IACP,SAAS,CAAC;AAAA,IACV,MAAM;AAAA,MACJ,gBAAgB;AAAA,IAClB;AAAA,IACA,KAAK;AAAA,MACH,gBAAgB;AAAA,IAClB;AAAA,IACA,OAAO;AAAA,MACL,gBAAgB;AAAA,IAClB;AAAA,EACF;AAAA,EACA,kBAAkB,CAAC,yCAAuB;AAAA,EAC1C,mBAAmB,CAAC,0CAAwB;AAAA,EAC5C,gBAAgB,SAAS,sBAAsB,QAAyB;AACtE,WAAO,UAAU,OAAO,SAAS;AAAA,EACnC;AAAA,EACA,cAAc;AAAA,EACd,iBAAiB;AACnB;AAEA,IAAO,mBAAQ;","names":[]}
@@ -38,7 +38,14 @@ function defaultTransformRequest(data, headers) {
38
38
  headers["Content-Type"] = "application/json";
39
39
  }
40
40
  }
41
- return JSON.stringify(data);
41
+ try {
42
+ return JSON.stringify(data);
43
+ } catch (e) {
44
+ if (e instanceof TypeError && e.message.toLowerCase().includes("circular")) {
45
+ throw new Error("Accessio: Cannot stringify circular structure in request data");
46
+ }
47
+ throw e;
48
+ }
42
49
  }
43
50
  return data;
44
51
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/defaults/transforms.ts"],"sourcesContent":["export function defaultTransformRequest(\n data: unknown,\n headers: Record<string, string>,\n): unknown {\n if (data === null || data === undefined) {\n return data;\n }\n\n if (\n typeof data === 'string' ||\n data instanceof ArrayBuffer ||\n (typeof Blob !== 'undefined' && data instanceof Blob) ||\n (typeof FormData !== 'undefined' && data instanceof FormData) ||\n (typeof URLSearchParams !== 'undefined' && data instanceof URLSearchParams) ||\n (typeof ReadableStream !== 'undefined' && data instanceof ReadableStream)\n ) {\n return data;\n }\n\n if (typeof data === 'object') {\n if (headers && typeof headers === 'object') {\n const hasContentType = Object.keys(headers).some(\n (key) => key.toLowerCase() === 'content-type',\n );\n if (!hasContentType) {\n headers['Content-Type'] = 'application/json';\n }\n }\n return JSON.stringify(data);\n }\n\n return data;\n}\n\nexport function defaultTransformResponse(data: unknown): unknown {\n if (typeof data === 'string') {\n try {\n return JSON.parse(data);\n } catch {\n // Not JSON — return as-is\n }\n }\n return data;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,SAAS,wBACd,MACA,SACS;AACT,MAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,WAAO;AAAA,EACT;AAEA,MACE,OAAO,SAAS,YAChB,gBAAgB,eACf,OAAO,SAAS,eAAe,gBAAgB,QAC/C,OAAO,aAAa,eAAe,gBAAgB,YACnD,OAAO,oBAAoB,eAAe,gBAAgB,mBAC1D,OAAO,mBAAmB,eAAe,gBAAgB,gBAC1D;AACA,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,SAAS,UAAU;AAC5B,QAAI,WAAW,OAAO,YAAY,UAAU;AAC1C,YAAM,iBAAiB,OAAO,KAAK,OAAO,EAAE;AAAA,QAC1C,CAAC,QAAQ,IAAI,YAAY,MAAM;AAAA,MACjC;AACA,UAAI,CAAC,gBAAgB;AACnB,gBAAQ,cAAc,IAAI;AAAA,MAC5B;AAAA,IACF;AACA,WAAO,KAAK,UAAU,IAAI;AAAA,EAC5B;AAEA,SAAO;AACT;AAEO,SAAS,yBAAyB,MAAwB;AAC/D,MAAI,OAAO,SAAS,UAAU;AAC5B,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/defaults/transforms.ts"],"sourcesContent":["export function defaultTransformRequest(data: unknown, headers: Record<string, string>): unknown {\n if (data === null || data === undefined) {\n return data;\n }\n\n if (\n typeof data === 'string' ||\n data instanceof ArrayBuffer ||\n (typeof Blob !== 'undefined' && data instanceof Blob) ||\n (typeof FormData !== 'undefined' && data instanceof FormData) ||\n (typeof URLSearchParams !== 'undefined' && data instanceof URLSearchParams) ||\n (typeof ReadableStream !== 'undefined' && data instanceof ReadableStream)\n ) {\n return data;\n }\n\n if (typeof data === 'object') {\n if (headers && typeof headers === 'object') {\n const hasContentType = Object.keys(headers).some(\n (key) => key.toLowerCase() === 'content-type',\n );\n if (!hasContentType) {\n headers['Content-Type'] = 'application/json';\n }\n }\n try {\n return JSON.stringify(data);\n } catch (e: any) {\n if (e instanceof TypeError && e.message.toLowerCase().includes('circular')) {\n throw new Error('Accessio: Cannot stringify circular structure in request data');\n }\n throw e;\n }\n }\n\n return data;\n}\n\nexport function defaultTransformResponse(data: unknown): unknown {\n if (typeof data === 'string') {\n try {\n return JSON.parse(data);\n } catch {\n // Not JSON — return as-is\n }\n }\n return data;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,SAAS,wBAAwB,MAAe,SAA0C;AAC/F,MAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,WAAO;AAAA,EACT;AAEA,MACE,OAAO,SAAS,YAChB,gBAAgB,eACf,OAAO,SAAS,eAAe,gBAAgB,QAC/C,OAAO,aAAa,eAAe,gBAAgB,YACnD,OAAO,oBAAoB,eAAe,gBAAgB,mBAC1D,OAAO,mBAAmB,eAAe,gBAAgB,gBAC1D;AACA,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,SAAS,UAAU;AAC5B,QAAI,WAAW,OAAO,YAAY,UAAU;AAC1C,YAAM,iBAAiB,OAAO,KAAK,OAAO,EAAE;AAAA,QAC1C,CAAC,QAAQ,IAAI,YAAY,MAAM;AAAA,MACjC;AACA,UAAI,CAAC,gBAAgB;AACnB,gBAAQ,cAAc,IAAI;AAAA,MAC5B;AAAA,IACF;AACA,QAAI;AACF,aAAO,KAAK,UAAU,IAAI;AAAA,IAC5B,SAAS,GAAQ;AACf,UAAI,aAAa,aAAa,EAAE,QAAQ,YAAY,EAAE,SAAS,UAAU,GAAG;AAC1E,cAAM,IAAI,MAAM,+DAA+D;AAAA,MACjF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,yBAAyB,MAAwB;AAC/D,MAAI,OAAO,SAAS,UAAU;AAC5B,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
@@ -64,9 +64,7 @@ function logResponse(response) {
64
64
  const statusText = response.statusText || "";
65
65
  const duration = response.duration != null ? `${response.duration}ms` : "??";
66
66
  const statusIcon = status >= 200 && status < 300 ? "\u2705" : status >= 400 ? "\u274C" : "\u26A0\uFE0F";
67
- const parts = [
68
- `\u{1F426}\u200D\u2B1B [Accessio] \u2190 ${statusIcon} ${status} ${statusText} (${duration})`
69
- ];
67
+ const parts = [`\u{1F426}\u200D\u2B1B [Accessio] \u2190 ${statusIcon} ${status} ${statusText} (${duration})`];
70
68
  if (response.data) {
71
69
  try {
72
70
  const size = typeof response.data === "string" ? response.data.length : JSON.stringify(response.data).length;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/helpers/debug.ts"],"sourcesContent":["import type { AccessioRequestConfig, AccessioResponse } from '../types';\nimport AccessioError from '../core/accessioError';\n\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${sizes[i]}`;\n}\n\nfunction sanitizeConfigForLog(\n config: AccessioRequestConfig,\n): { params: Record<string, unknown> | undefined; timeout: number | undefined; retry: number | undefined } {\n return {\n params: config.params,\n timeout: config.timeout,\n retry: config.retry,\n };\n}\n\nexport function logRequest(\n config: AccessioRequestConfig,\n fullUrl: string,\n): void {\n if (!config.debug) return;\n\n const safe = sanitizeConfigForLog(config);\n\n const method = (config.method || 'GET').toUpperCase();\n const url = fullUrl || config.url || '';\n\n const parts: string[] = [`🐦‍⬛ [Accessio] → ${method} ${url}`];\n\n if (safe.params && Object.keys(safe.params).length > 0) {\n parts.push(` Params: ${JSON.stringify(safe.params)}`);\n }\n\n if (config.data && typeof config.data === 'object') {\n const preview = JSON.stringify(config.data);\n const truncated =\n preview.length > 200 ? `${preview.substring(0, 200)}...` : preview;\n parts.push(` Body: ${truncated}`);\n }\n\n if (safe.timeout) {\n parts.push(` Timeout: ${safe.timeout}ms`);\n }\n\n if (safe.retry) {\n parts.push(` Retry: ${safe.retry}x`);\n }\n\n console.log(parts.join('\\n'));\n}\n\nexport function logResponse(response: AccessioResponse): void {\n if (!response.config || !response.config.debug) return;\n const status = response.status;\n const statusText = response.statusText || '';\n const duration =\n response.duration != null ? `${response.duration}ms` : '??';\n\n const statusIcon =\n status >= 200 && status < 300\n ? '✅'\n : status >= 400\n ? '❌'\n : '⚠️';\n\n const parts: string[] = [\n `🐦‍⬛ [Accessio] ← ${statusIcon} ${status} ${statusText} (${duration})`,\n ];\n\n if (response.data) {\n try {\n const size =\n typeof response.data === 'string'\n ? response.data.length\n : JSON.stringify(response.data).length;\n parts.push(` Size: ~${formatBytes(size)}`);\n } catch {\n // ignore\n }\n }\n\n console.log(parts.join('\\n'));\n}\n\nexport function logError(error: AccessioError, config?: AccessioRequestConfig): void {\n if (!config || !config.debug) return;\n\n const parts: string[] = [`🐦‍⬛ [Accessio] ← ❌ ERROR: ${error.message}`];\n\n if (error.code) {\n parts.push(` Code: ${error.code}`);\n }\n\n if (error.response) {\n parts.push(` Status: ${error.response.status}`);\n }\n\n console.log(parts.join('\\n'));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,SAAS,YAAY,OAAuB;AAC1C,MAAI,UAAU,EAAG,QAAO;AACxB,QAAM,QAAQ,CAAC,KAAK,MAAM,MAAM,IAAI;AACpC,QAAM,IAAI,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,CAAC;AACrD,SAAO,IAAI,QAAQ,KAAK,IAAI,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC;AAC9D;AAEA,SAAS,qBACP,QACyG;AACzG,SAAO;AAAA,IACL,QAAQ,OAAO;AAAA,IACf,SAAS,OAAO;AAAA,IAChB,OAAO,OAAO;AAAA,EAChB;AACF;AAEO,SAAS,WACd,QACA,SACM;AACN,MAAI,CAAC,OAAO,MAAO;AAEnB,QAAM,OAAO,qBAAqB,MAAM;AAExC,QAAM,UAAU,OAAO,UAAU,OAAO,YAAY;AACpD,QAAM,MAAM,WAAW,OAAO,OAAO;AAErC,QAAM,QAAkB,CAAC,2CAAqB,MAAM,IAAI,GAAG,EAAE;AAE7D,MAAI,KAAK,UAAU,OAAO,KAAK,KAAK,MAAM,EAAE,SAAS,GAAG;AACtD,UAAM,KAAK,cAAc,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE;AAAA,EACxD;AAEA,MAAI,OAAO,QAAQ,OAAO,OAAO,SAAS,UAAU;AAClD,UAAM,UAAU,KAAK,UAAU,OAAO,IAAI;AAC1C,UAAM,YACJ,QAAQ,SAAS,MAAM,GAAG,QAAQ,UAAU,GAAG,GAAG,CAAC,QAAQ;AAC7D,UAAM,KAAK,YAAY,SAAS,EAAE;AAAA,EACpC;AAEA,MAAI,KAAK,SAAS;AAChB,UAAM,KAAK,eAAe,KAAK,OAAO,IAAI;AAAA,EAC5C;AAEA,MAAI,KAAK,OAAO;AACd,UAAM,KAAK,aAAa,KAAK,KAAK,GAAG;AAAA,EACvC;AAEA,UAAQ,IAAI,MAAM,KAAK,IAAI,CAAC;AAC9B;AAEO,SAAS,YAAY,UAAkC;AAC5D,MAAI,CAAC,SAAS,UAAU,CAAC,SAAS,OAAO,MAAO;AAChD,QAAM,SAAS,SAAS;AACxB,QAAM,aAAa,SAAS,cAAc;AAC1C,QAAM,WACJ,SAAS,YAAY,OAAO,GAAG,SAAS,QAAQ,OAAO;AAEzD,QAAM,aACJ,UAAU,OAAO,SAAS,MACtB,WACA,UAAU,MACR,WACA;AAER,QAAM,QAAkB;AAAA,IACtB,2CAAqB,UAAU,IAAI,MAAM,IAAI,UAAU,KAAK,QAAQ;AAAA,EACtE;AAEA,MAAI,SAAS,MAAM;AACjB,QAAI;AACF,YAAM,OACJ,OAAO,SAAS,SAAS,WACrB,SAAS,KAAK,SACd,KAAK,UAAU,SAAS,IAAI,EAAE;AACpC,YAAM,KAAK,aAAa,YAAY,IAAI,CAAC,EAAE;AAAA,IAC7C,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,UAAQ,IAAI,MAAM,KAAK,IAAI,CAAC;AAC9B;AAEO,SAAS,SAAS,OAAsB,QAAsC;AACnF,MAAI,CAAC,UAAU,CAAC,OAAO,MAAO;AAE9B,QAAM,QAAkB,CAAC,yDAA8B,MAAM,OAAO,EAAE;AAEtE,MAAI,MAAM,MAAM;AACd,UAAM,KAAK,YAAY,MAAM,IAAI,EAAE;AAAA,EACrC;AAEA,MAAI,MAAM,UAAU;AAClB,UAAM,KAAK,cAAc,MAAM,SAAS,MAAM,EAAE;AAAA,EAClD;AAEA,UAAQ,IAAI,MAAM,KAAK,IAAI,CAAC;AAC9B;","names":[]}
1
+ {"version":3,"sources":["../../src/helpers/debug.ts"],"sourcesContent":["import type { AccessioRequestConfig, AccessioResponse } from '../types';\nimport AccessioError from '../core/accessioError';\n\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${sizes[i]}`;\n}\n\nfunction sanitizeConfigForLog(config: AccessioRequestConfig): {\n params: Record<string, unknown> | undefined;\n timeout: number | undefined;\n retry: number | undefined;\n} {\n return {\n params: config.params,\n timeout: config.timeout,\n retry: config.retry,\n };\n}\n\nexport function logRequest(config: AccessioRequestConfig, fullUrl: string): void {\n if (!config.debug) return;\n\n const safe = sanitizeConfigForLog(config);\n\n const method = (config.method || 'GET').toUpperCase();\n const url = fullUrl || config.url || '';\n\n const parts: string[] = [`🐦‍⬛ [Accessio] → ${method} ${url}`];\n\n if (safe.params && Object.keys(safe.params).length > 0) {\n parts.push(` Params: ${JSON.stringify(safe.params)}`);\n }\n\n if (config.data && typeof config.data === 'object') {\n const preview = JSON.stringify(config.data);\n const truncated = preview.length > 200 ? `${preview.substring(0, 200)}...` : preview;\n parts.push(` Body: ${truncated}`);\n }\n\n if (safe.timeout) {\n parts.push(` Timeout: ${safe.timeout}ms`);\n }\n\n if (safe.retry) {\n parts.push(` Retry: ${safe.retry}x`);\n }\n\n console.log(parts.join('\\n'));\n}\n\nexport function logResponse(response: AccessioResponse): void {\n if (!response.config || !response.config.debug) return;\n const status = response.status;\n const statusText = response.statusText || '';\n const duration = response.duration != null ? `${response.duration}ms` : '??';\n\n const statusIcon = status >= 200 && status < 300 ? '✅' : status >= 400 ? '❌' : '⚠️';\n\n const parts: string[] = [`🐦‍⬛ [Accessio] ← ${statusIcon} ${status} ${statusText} (${duration})`];\n\n if (response.data) {\n try {\n const size =\n typeof response.data === 'string'\n ? response.data.length\n : JSON.stringify(response.data).length;\n parts.push(` Size: ~${formatBytes(size)}`);\n } catch {\n // ignore\n }\n }\n\n console.log(parts.join('\\n'));\n}\n\nexport function logError(error: AccessioError, config?: AccessioRequestConfig): void {\n if (!config || !config.debug) return;\n\n const parts: string[] = [`🐦‍⬛ [Accessio] ← ❌ ERROR: ${error.message}`];\n\n if (error.code) {\n parts.push(` Code: ${error.code}`);\n }\n\n if (error.response) {\n parts.push(` Status: ${error.response.status}`);\n }\n\n console.log(parts.join('\\n'));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,SAAS,YAAY,OAAuB;AAC1C,MAAI,UAAU,EAAG,QAAO;AACxB,QAAM,QAAQ,CAAC,KAAK,MAAM,MAAM,IAAI;AACpC,QAAM,IAAI,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,CAAC;AACrD,SAAO,IAAI,QAAQ,KAAK,IAAI,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC;AAC9D;AAEA,SAAS,qBAAqB,QAI5B;AACA,SAAO;AAAA,IACL,QAAQ,OAAO;AAAA,IACf,SAAS,OAAO;AAAA,IAChB,OAAO,OAAO;AAAA,EAChB;AACF;AAEO,SAAS,WAAW,QAA+B,SAAuB;AAC/E,MAAI,CAAC,OAAO,MAAO;AAEnB,QAAM,OAAO,qBAAqB,MAAM;AAExC,QAAM,UAAU,OAAO,UAAU,OAAO,YAAY;AACpD,QAAM,MAAM,WAAW,OAAO,OAAO;AAErC,QAAM,QAAkB,CAAC,2CAAqB,MAAM,IAAI,GAAG,EAAE;AAE7D,MAAI,KAAK,UAAU,OAAO,KAAK,KAAK,MAAM,EAAE,SAAS,GAAG;AACtD,UAAM,KAAK,cAAc,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE;AAAA,EACxD;AAEA,MAAI,OAAO,QAAQ,OAAO,OAAO,SAAS,UAAU;AAClD,UAAM,UAAU,KAAK,UAAU,OAAO,IAAI;AAC1C,UAAM,YAAY,QAAQ,SAAS,MAAM,GAAG,QAAQ,UAAU,GAAG,GAAG,CAAC,QAAQ;AAC7E,UAAM,KAAK,YAAY,SAAS,EAAE;AAAA,EACpC;AAEA,MAAI,KAAK,SAAS;AAChB,UAAM,KAAK,eAAe,KAAK,OAAO,IAAI;AAAA,EAC5C;AAEA,MAAI,KAAK,OAAO;AACd,UAAM,KAAK,aAAa,KAAK,KAAK,GAAG;AAAA,EACvC;AAEA,UAAQ,IAAI,MAAM,KAAK,IAAI,CAAC;AAC9B;AAEO,SAAS,YAAY,UAAkC;AAC5D,MAAI,CAAC,SAAS,UAAU,CAAC,SAAS,OAAO,MAAO;AAChD,QAAM,SAAS,SAAS;AACxB,QAAM,aAAa,SAAS,cAAc;AAC1C,QAAM,WAAW,SAAS,YAAY,OAAO,GAAG,SAAS,QAAQ,OAAO;AAExE,QAAM,aAAa,UAAU,OAAO,SAAS,MAAM,WAAM,UAAU,MAAM,WAAM;AAE/E,QAAM,QAAkB,CAAC,2CAAqB,UAAU,IAAI,MAAM,IAAI,UAAU,KAAK,QAAQ,GAAG;AAEhG,MAAI,SAAS,MAAM;AACjB,QAAI;AACF,YAAM,OACJ,OAAO,SAAS,SAAS,WACrB,SAAS,KAAK,SACd,KAAK,UAAU,SAAS,IAAI,EAAE;AACpC,YAAM,KAAK,aAAa,YAAY,IAAI,CAAC,EAAE;AAAA,IAC7C,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,UAAQ,IAAI,MAAM,KAAK,IAAI,CAAC;AAC9B;AAEO,SAAS,SAAS,OAAsB,QAAsC;AACnF,MAAI,CAAC,UAAU,CAAC,OAAO,MAAO;AAE9B,QAAM,QAAkB,CAAC,yDAA8B,MAAM,OAAO,EAAE;AAEtE,MAAI,MAAM,MAAM;AACd,UAAM,KAAK,YAAY,MAAM,IAAI,EAAE;AAAA,EACrC;AAEA,MAAI,MAAM,UAAU;AAClB,UAAM,KAAK,cAAc,MAAM,SAAS,MAAM,EAAE;AAAA,EAClD;AAEA,UAAQ,IAAI,MAAM,KAAK,IAAI,CAAC;AAC9B;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/helpers/parseHeaders.ts"],"sourcesContent":["export default function parseHeaders(\n headers: any,\n): Record<string, string> {\n const parsed: Record<string, string> = {};\n\n if (!headers) return parsed;\n\n if (typeof headers.forEach === 'function') {\n headers.forEach((value: string, key: string) => {\n parsed[key.toLowerCase()] = value;\n });\n return parsed;\n }\n\n if (typeof headers === 'string') {\n headers.split('\\n').forEach((line: string) => {\n const index = line.indexOf(':');\n if (index > 0) {\n const key = line.substring(0, index).trim().toLowerCase();\n const value = line.substring(index + 1).trim();\n parsed[key] = value;\n }\n });\n return parsed;\n }\n\n if (typeof headers === 'object') {\n Object.keys(headers).forEach((key) => {\n parsed[key.toLowerCase()] = headers[key];\n });\n return parsed;\n }\n\n return parsed;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAe,SAAR,aACL,SACwB;AACxB,QAAM,SAAiC,CAAC;AAExC,MAAI,CAAC,QAAS,QAAO;AAErB,MAAI,OAAO,QAAQ,YAAY,YAAY;AACzC,YAAQ,QAAQ,CAAC,OAAe,QAAgB;AAC9C,aAAO,IAAI,YAAY,CAAC,IAAI;AAAA,IAC9B,CAAC;AACD,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,YAAY,UAAU;AAC/B,YAAQ,MAAM,IAAI,EAAE,QAAQ,CAAC,SAAiB;AAC5C,YAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,UAAI,QAAQ,GAAG;AACb,cAAM,MAAM,KAAK,UAAU,GAAG,KAAK,EAAE,KAAK,EAAE,YAAY;AACxD,cAAM,QAAQ,KAAK,UAAU,QAAQ,CAAC,EAAE,KAAK;AAC7C,eAAO,GAAG,IAAI;AAAA,MAChB;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO,KAAK,OAAO,EAAE,QAAQ,CAAC,QAAQ;AACpC,aAAO,IAAI,YAAY,CAAC,IAAI,QAAQ,GAAG;AAAA,IACzC,CAAC;AACD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/helpers/parseHeaders.ts"],"sourcesContent":["export default function parseHeaders(headers: any): Record<string, string> {\n const parsed: Record<string, string> = {};\n\n if (!headers) return parsed;\n\n if (typeof headers.forEach === 'function') {\n headers.forEach((value: string, key: string) => {\n parsed[key.toLowerCase()] = value;\n });\n return parsed;\n }\n\n if (typeof headers === 'string') {\n headers.split('\\n').forEach((line: string) => {\n const index = line.indexOf(':');\n if (index > 0) {\n const key = line.substring(0, index).trim().toLowerCase();\n const value = line.substring(index + 1).trim();\n parsed[key] = value;\n }\n });\n return parsed;\n }\n\n if (typeof headers === 'object') {\n Object.keys(headers).forEach((key) => {\n parsed[key.toLowerCase()] = headers[key];\n });\n return parsed;\n }\n\n return parsed;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAe,SAAR,aAA8B,SAAsC;AACzE,QAAM,SAAiC,CAAC;AAExC,MAAI,CAAC,QAAS,QAAO;AAErB,MAAI,OAAO,QAAQ,YAAY,YAAY;AACzC,YAAQ,QAAQ,CAAC,OAAe,QAAgB;AAC9C,aAAO,IAAI,YAAY,CAAC,IAAI;AAAA,IAC9B,CAAC;AACD,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,YAAY,UAAU;AAC/B,YAAQ,MAAM,IAAI,EAAE,QAAQ,CAAC,SAAiB;AAC5C,YAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,UAAI,QAAQ,GAAG;AACb,cAAM,MAAM,KAAK,UAAU,GAAG,KAAK,EAAE,KAAK,EAAE,YAAY;AACxD,cAAM,QAAQ,KAAK,UAAU,QAAQ,CAAC,EAAE,KAAK;AAC7C,eAAO,GAAG,IAAI;AAAA,MAChB;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO,KAAK,OAAO,EAAE,QAAQ,CAAC,QAAQ;AACpC,aAAO,IAAI,YAAY,CAAC,IAAI,QAAQ,GAAG;AAAA,IACzC,CAAC;AACD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;","names":[]}
@@ -23,25 +23,33 @@ __export(rateLimiter_exports, {
23
23
  rateLimitedRequest: () => rateLimitedRequest
24
24
  });
25
25
  module.exports = __toCommonJS(rateLimiter_exports);
26
- function createRateLimiter(maxConcurrent = Infinity) {
26
+ function createRateLimiter(maxConcurrent = Infinity, maxQueueSize = Infinity) {
27
27
  if (maxConcurrent !== Infinity && (!Number.isInteger(maxConcurrent) || maxConcurrent < 1)) {
28
28
  throw new RangeError(
29
29
  `[Accessio] maxConcurrent must be a positive integer or Infinity, got: ${maxConcurrent}`
30
30
  );
31
31
  }
32
+ if (maxQueueSize !== Infinity && (!Number.isInteger(maxQueueSize) || maxQueueSize < 1)) {
33
+ throw new RangeError(
34
+ `[Accessio] maxQueueSize must be a positive integer or Infinity, got: ${maxQueueSize}`
35
+ );
36
+ }
32
37
  let active = 0;
33
38
  let destroyed = false;
34
39
  const queue = [];
35
40
  function acquire() {
36
41
  if (destroyed) {
37
- return Promise.reject(
38
- new Error("[Accessio] Rate limiter has been destroyed")
39
- );
42
+ return Promise.reject(new Error("[Accessio] Rate limiter has been destroyed"));
40
43
  }
41
44
  if (active < maxConcurrent) {
42
45
  active++;
43
46
  return Promise.resolve();
44
47
  }
48
+ if (queue.length >= maxQueueSize) {
49
+ return Promise.reject(
50
+ new Error(`[Accessio] Rate limiter queue size exceeded maxQueueSize (${maxQueueSize})`)
51
+ );
52
+ }
45
53
  return new Promise((resolve, reject) => {
46
54
  queue.push({ resolve, reject });
47
55
  });
@@ -58,9 +66,7 @@ function createRateLimiter(maxConcurrent = Infinity) {
58
66
  }
59
67
  function destroy() {
60
68
  destroyed = true;
61
- const reason = new Error(
62
- "[Accessio] Rate limiter destroyed \u2014 pending request cancelled"
63
- );
69
+ const reason = new Error("[Accessio] Rate limiter destroyed \u2014 pending request cancelled");
64
70
  while (queue.length > 0) {
65
71
  const next = queue.shift();
66
72
  next?.reject(reason);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/helpers/rateLimiter.ts"],"sourcesContent":["import type {\n RateLimiter,\n AccessioRequestConfig,\n AccessioResponse,\n} from '../types';\n\ninterface QueueItem {\n resolve: () => void;\n reject: (reason: Error) => void;\n}\n\nexport function createRateLimiter(maxConcurrent: number = Infinity): RateLimiter {\n if (\n maxConcurrent !== Infinity &&\n (!Number.isInteger(maxConcurrent) || maxConcurrent < 1)\n ) {\n throw new RangeError(\n `[Accessio] maxConcurrent must be a positive integer or Infinity, got: ${maxConcurrent}`,\n );\n }\n let active = 0;\n let destroyed = false;\n const queue: QueueItem[] = [];\n\n function acquire(): Promise<void> {\n if (destroyed) {\n return Promise.reject(\n new Error('[Accessio] Rate limiter has been destroyed'),\n );\n }\n\n if (active < maxConcurrent) {\n active++;\n return Promise.resolve();\n }\n\n return new Promise((resolve, reject) => {\n queue.push({ resolve, reject });\n });\n }\n\n function release(): void {\n if (destroyed) return;\n\n if (active <= 0) return;\n\n active--;\n\n if (queue.length > 0 && active < maxConcurrent) {\n active++;\n const next = queue.shift();\n next?.resolve();\n }\n }\n\n function destroy(): void {\n destroyed = true;\n const reason = new Error(\n '[Accessio] Rate limiter destroyed — pending request cancelled',\n );\n while (queue.length > 0) {\n const next = queue.shift();\n next?.reject(reason);\n }\n }\n\n return {\n acquire,\n release,\n destroy,\n get pending() {\n return queue.length;\n },\n get active() {\n return active;\n },\n get destroyed() {\n return destroyed;\n },\n };\n}\n\nexport async function rateLimitedRequest<T = unknown>(\n dispatchFn: (config: AccessioRequestConfig) => Promise<AccessioResponse<T>>,\n limiter: RateLimiter,\n config: AccessioRequestConfig,\n): Promise<AccessioResponse<T>> {\n await limiter.acquire();\n try {\n return await dispatchFn(config);\n } finally {\n limiter.release();\n }\n}\n\nexport default createRateLimiter;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWO,SAAS,kBAAkB,gBAAwB,UAAuB;AAC/E,MACE,kBAAkB,aACjB,CAAC,OAAO,UAAU,aAAa,KAAK,gBAAgB,IACrD;AACA,UAAM,IAAI;AAAA,MACR,yEAAyE,aAAa;AAAA,IACxF;AAAA,EACF;AACA,MAAI,SAAS;AACb,MAAI,YAAY;AAChB,QAAM,QAAqB,CAAC;AAE5B,WAAS,UAAyB;AAChC,QAAI,WAAW;AACb,aAAO,QAAQ;AAAA,QACb,IAAI,MAAM,4CAA4C;AAAA,MACxD;AAAA,IACF;AAEA,QAAI,SAAS,eAAe;AAC1B;AACA,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAEA,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,KAAK,EAAE,SAAS,OAAO,CAAC;AAAA,IAChC,CAAC;AAAA,EACH;AAEA,WAAS,UAAgB;AACvB,QAAI,UAAW;AAEf,QAAI,UAAU,EAAG;AAEjB;AAEA,QAAI,MAAM,SAAS,KAAK,SAAS,eAAe;AAC9C;AACA,YAAM,OAAO,MAAM,MAAM;AACzB,YAAM,QAAQ;AAAA,IAChB;AAAA,EACF;AAEA,WAAS,UAAgB;AACvB,gBAAY;AACZ,UAAM,SAAS,IAAI;AAAA,MACjB;AAAA,IACF;AACA,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,OAAO,MAAM,MAAM;AACzB,YAAM,OAAO,MAAM;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,IAAI,UAAU;AACZ,aAAO,MAAM;AAAA,IACf;AAAA,IACA,IAAI,SAAS;AACX,aAAO;AAAA,IACT;AAAA,IACA,IAAI,YAAY;AACd,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,eAAsB,mBACpB,YACA,SACA,QAC8B;AAC9B,QAAM,QAAQ,QAAQ;AACtB,MAAI;AACF,WAAO,MAAM,WAAW,MAAM;AAAA,EAChC,UAAE;AACA,YAAQ,QAAQ;AAAA,EAClB;AACF;AAEA,IAAO,sBAAQ;","names":[]}
1
+ {"version":3,"sources":["../../src/helpers/rateLimiter.ts"],"sourcesContent":["import type { RateLimiter, AccessioRequestConfig, AccessioResponse } from '../types';\n\ninterface QueueItem {\n resolve: () => void;\n reject: (reason: Error) => void;\n}\n\nexport function createRateLimiter(\n maxConcurrent: number = Infinity,\n maxQueueSize: number = Infinity,\n): RateLimiter {\n if (maxConcurrent !== Infinity && (!Number.isInteger(maxConcurrent) || maxConcurrent < 1)) {\n throw new RangeError(\n `[Accessio] maxConcurrent must be a positive integer or Infinity, got: ${maxConcurrent}`,\n );\n }\n if (maxQueueSize !== Infinity && (!Number.isInteger(maxQueueSize) || maxQueueSize < 1)) {\n throw new RangeError(\n `[Accessio] maxQueueSize must be a positive integer or Infinity, got: ${maxQueueSize}`,\n );\n }\n let active = 0;\n let destroyed = false;\n const queue: QueueItem[] = [];\n\n function acquire(): Promise<void> {\n if (destroyed) {\n return Promise.reject(new Error('[Accessio] Rate limiter has been destroyed'));\n }\n\n if (active < maxConcurrent) {\n active++;\n return Promise.resolve();\n }\n\n if (queue.length >= maxQueueSize) {\n return Promise.reject(\n new Error(`[Accessio] Rate limiter queue size exceeded maxQueueSize (${maxQueueSize})`),\n );\n }\n\n return new Promise((resolve, reject) => {\n queue.push({ resolve, reject });\n });\n }\n\n function release(): void {\n if (destroyed) return;\n\n if (active <= 0) return;\n\n active--;\n\n if (queue.length > 0 && active < maxConcurrent) {\n active++;\n const next = queue.shift();\n next?.resolve();\n }\n }\n\n function destroy(): void {\n destroyed = true;\n const reason = new Error('[Accessio] Rate limiter destroyed — pending request cancelled');\n while (queue.length > 0) {\n const next = queue.shift();\n next?.reject(reason);\n }\n }\n\n return {\n acquire,\n release,\n destroy,\n get pending() {\n return queue.length;\n },\n get active() {\n return active;\n },\n get destroyed() {\n return destroyed;\n },\n };\n}\n\nexport async function rateLimitedRequest<T = unknown>(\n dispatchFn: (config: AccessioRequestConfig) => Promise<AccessioResponse<T>>,\n limiter: RateLimiter,\n config: AccessioRequestConfig,\n): Promise<AccessioResponse<T>> {\n await limiter.acquire();\n try {\n return await dispatchFn(config);\n } finally {\n limiter.release();\n }\n}\n\nexport default createRateLimiter;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOO,SAAS,kBACd,gBAAwB,UACxB,eAAuB,UACV;AACb,MAAI,kBAAkB,aAAa,CAAC,OAAO,UAAU,aAAa,KAAK,gBAAgB,IAAI;AACzF,UAAM,IAAI;AAAA,MACR,yEAAyE,aAAa;AAAA,IACxF;AAAA,EACF;AACA,MAAI,iBAAiB,aAAa,CAAC,OAAO,UAAU,YAAY,KAAK,eAAe,IAAI;AACtF,UAAM,IAAI;AAAA,MACR,wEAAwE,YAAY;AAAA,IACtF;AAAA,EACF;AACA,MAAI,SAAS;AACb,MAAI,YAAY;AAChB,QAAM,QAAqB,CAAC;AAE5B,WAAS,UAAyB;AAChC,QAAI,WAAW;AACb,aAAO,QAAQ,OAAO,IAAI,MAAM,4CAA4C,CAAC;AAAA,IAC/E;AAEA,QAAI,SAAS,eAAe;AAC1B;AACA,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAEA,QAAI,MAAM,UAAU,cAAc;AAChC,aAAO,QAAQ;AAAA,QACb,IAAI,MAAM,6DAA6D,YAAY,GAAG;AAAA,MACxF;AAAA,IACF;AAEA,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,KAAK,EAAE,SAAS,OAAO,CAAC;AAAA,IAChC,CAAC;AAAA,EACH;AAEA,WAAS,UAAgB;AACvB,QAAI,UAAW;AAEf,QAAI,UAAU,EAAG;AAEjB;AAEA,QAAI,MAAM,SAAS,KAAK,SAAS,eAAe;AAC9C;AACA,YAAM,OAAO,MAAM,MAAM;AACzB,YAAM,QAAQ;AAAA,IAChB;AAAA,EACF;AAEA,WAAS,UAAgB;AACvB,gBAAY;AACZ,UAAM,SAAS,IAAI,MAAM,oEAA+D;AACxF,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,OAAO,MAAM,MAAM;AACzB,YAAM,OAAO,MAAM;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,IAAI,UAAU;AACZ,aAAO,MAAM;AAAA,IACf;AAAA,IACA,IAAI,SAAS;AACX,aAAO;AAAA,IACT;AAAA,IACA,IAAI,YAAY;AACd,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,eAAsB,mBACpB,YACA,SACA,QAC8B;AAC9B,QAAM,QAAQ,QAAQ;AACtB,MAAI;AACF,WAAO,MAAM,WAAW,MAAM;AAAA,EAChC,UAAE;AACA,YAAQ,QAAQ;AAAA,EAClB;AACF;AAEA,IAAO,sBAAQ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/helpers/transformData.ts"],"sourcesContent":["import AccessioError from '../core/accessioError';\nimport type {\n TransformFunction,\n AccessioRequestConfig,\n} from '../types';\n\nexport default function transformData(\n transforms: TransformFunction | TransformFunction[] | undefined,\n data: unknown,\n headers: Record<string, string>,\n config?: AccessioRequestConfig,\n): unknown {\n if (!transforms || !Array.isArray(transforms)) {\n return data;\n }\n\n let result = data;\n\n for (const transform of transforms) {\n if (typeof transform === 'function') {\n try {\n result = transform(result, headers);\n } catch (err) {\n throw AccessioError.from(\n err instanceof Error ? err : new Error(String(err)),\n AccessioError.ERR_BAD_REQUEST,\n config ?? null,\n null,\n null,\n );\n }\n }\n }\n\n return result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAA0B;AAMX,SAAR,cACL,YACA,MACA,SACA,QACS;AACT,MAAI,CAAC,cAAc,CAAC,MAAM,QAAQ,UAAU,GAAG;AAC7C,WAAO;AAAA,EACT;AAEA,MAAI,SAAS;AAEb,aAAW,aAAa,YAAY;AAClC,QAAI,OAAO,cAAc,YAAY;AACnC,UAAI;AACF,iBAAS,UAAU,QAAQ,OAAO;AAAA,MACpC,SAAS,KAAK;AACZ,cAAM,qBAAAA,QAAc;AAAA,UAClB,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAAA,UAClD,qBAAAA,QAAc;AAAA,UACd,UAAU;AAAA,UACV;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;","names":["AccessioError"]}
1
+ {"version":3,"sources":["../../src/helpers/transformData.ts"],"sourcesContent":["import AccessioError from '../core/accessioError';\nimport type { TransformFunction, AccessioRequestConfig } from '../types';\n\nexport default function transformData(\n transforms: TransformFunction | TransformFunction[] | undefined,\n data: unknown,\n headers: Record<string, string>,\n config?: AccessioRequestConfig,\n): unknown {\n if (!transforms || !Array.isArray(transforms)) {\n return data;\n }\n\n let result = data;\n\n for (const transform of transforms) {\n if (typeof transform === 'function') {\n try {\n result = transform(result, headers);\n } catch (err) {\n throw AccessioError.from(\n err instanceof Error ? err : new Error(String(err)),\n AccessioError.ERR_BAD_REQUEST,\n config ?? null,\n null,\n null,\n );\n }\n }\n }\n\n return result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAA0B;AAGX,SAAR,cACL,YACA,MACA,SACA,QACS;AACT,MAAI,CAAC,cAAc,CAAC,MAAM,QAAQ,UAAU,GAAG;AAC7C,WAAO;AAAA,EACT;AAEA,MAAI,SAAS;AAEb,aAAW,aAAa,YAAY;AAClC,QAAI,OAAO,cAAc,YAAY;AACnC,UAAI;AACF,iBAAS,UAAU,QAAQ,OAAO;AAAA,MACpC,SAAS,KAAK;AACZ,cAAM,qBAAAA,QAAc;AAAA,UAClB,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC;AAAA,UAClD,qBAAAA,QAAc;AAAA,UACd,UAAU;AAAA,UACV;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;","names":["AccessioError"]}
package/cjs/index.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import Accessio from './accessio';\nimport defaults from './defaults';\nimport AccessioError from './core/accessioError';\nimport mergeConfig from './core/mergeConfig';\nimport buildURL from './core/buildURL';\nimport InterceptorManager from './interceptors/interceptorManager';\nimport { createRateLimiter } from './helpers/rateLimiter';\nimport { logRequest, logResponse, logError } from './helpers/debug';\nimport { ERR_CANCELED } from './constants/errorCodes';\nimport type { AccessioRequestConfig, AccessioResponse } from './types';\n\nconst PUBLIC_METHODS = [\n 'request',\n 'getUri',\n 'get',\n 'delete',\n 'head',\n 'options',\n 'post',\n 'put',\n 'patch',\n 'postForm',\n 'putForm',\n 'patchForm',\n];\n\nfunction createInstance(defaultConfig: AccessioRequestConfig) {\n const context = new Accessio(defaultConfig);\n\n const instance: any = function accessio(\n configOrUrl: string | AccessioRequestConfig,\n config?: AccessioRequestConfig,\n ) {\n return context.request(configOrUrl, config);\n };\n\n for (const key of PUBLIC_METHODS) {\n const method: any = (context as any)[key];\n if (typeof method === 'function') {\n instance[key] = method.bind(context);\n }\n }\n\n instance.defaults = context.defaults;\n instance.interceptors = context.interceptors;\n instance.all = function all(promises: any[]): Promise<any[]> {\n return Promise.all(promises);\n };\n instance.spread = function spread<T>(\n callback: (...args: any[]) => T,\n ): (arr: any[]) => T {\n return function wrap(arr: any[]): T {\n return callback(...arr);\n };\n };\n instance.isCancel = function isCancel(value: any): boolean {\n return !!(\n value &&\n value.isAccessioError &&\n value.code === ERR_CANCELED\n );\n };\n instance.isAccessioError = function isAccessioError(\n value: any,\n ): boolean {\n return (\n value instanceof AccessioError ||\n !!(value && typeof value === 'object' && value.isAccessioError === true)\n );\n };\n instance.AccessioError = AccessioError;\n instance.Accessio = Accessio;\n instance.mergeConfig = mergeConfig;\n instance.buildURL = buildURL;\n instance.InterceptorManager = InterceptorManager;\n instance.createRateLimiter = createRateLimiter;\n\n return instance;\n}\n\nconst accessio = createInstance(defaults);\n\nfunction create(instanceConfig?: AccessioRequestConfig) {\n return createInstance(mergeConfig(defaults, instanceConfig));\n}\n\naccessio.create = create;\n\nexport default accessio;\n\nexport {\n Accessio,\n AccessioError,\n mergeConfig,\n buildURL,\n InterceptorManager,\n createInstance,\n createRateLimiter,\n logRequest,\n logResponse,\n logError,\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA,kCAAAA;AAAA,EAAA,0CAAAC;AAAA,EAAA,oDAAAC;AAAA,EAAA,gCAAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wCAAAC;AAAA;AAAA;AAAA,sBAAqB;AACrB,sBAAqB;AACrB,2BAA0B;AAC1B,yBAAwB;AACxB,sBAAqB;AACrB,gCAA+B;AAC/B,yBAAkC;AAClC,mBAAkD;AAClD,wBAA6B;AAG7B,MAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,eAAe,eAAsC;AAC5D,QAAM,UAAU,IAAI,gBAAAJ,QAAS,aAAa;AAE1C,QAAM,WAAgB,SAASK,UAC7B,aACA,QACA;AACA,WAAO,QAAQ,QAAQ,aAAa,MAAM;AAAA,EAC5C;AAEA,aAAW,OAAO,gBAAgB;AAChC,UAAM,SAAe,QAAgB,GAAG;AACxC,QAAI,OAAO,WAAW,YAAY;AAChC,eAAS,GAAG,IAAI,OAAO,KAAK,OAAO;AAAA,IACrC;AAAA,EACF;AAEA,WAAS,WAAW,QAAQ;AAC5B,WAAS,eAAe,QAAQ;AAChC,WAAS,MAAM,SAAS,IAAI,UAAiC;AAC3D,WAAO,QAAQ,IAAI,QAAQ;AAAA,EAC7B;AACA,WAAS,SAAS,SAAS,OACzB,UACmB;AACnB,WAAO,SAAS,KAAK,KAAe;AAClC,aAAO,SAAS,GAAG,GAAG;AAAA,IACxB;AAAA,EACF;AACA,WAAS,WAAW,SAAS,SAAS,OAAqB;AACzD,WAAO,CAAC,EACN,SACA,MAAM,mBACN,MAAM,SAAS;AAAA,EAEnB;AACA,WAAS,kBAAkB,SAAS,gBAClC,OACS;AACT,WACE,iBAAiB,qBAAAJ,WACjB,CAAC,EAAE,SAAS,OAAO,UAAU,YAAY,MAAM,oBAAoB;AAAA,EAEvE;AACA,WAAS,gBAAgB,qBAAAA;AACzB,WAAS,WAAW,gBAAAD;AACpB,WAAS,cAAc,mBAAAI;AACvB,WAAS,WAAW,gBAAAD;AACpB,WAAS,qBAAqB,0BAAAD;AAC9B,WAAS,oBAAoB;AAE7B,SAAO;AACT;AAEA,MAAM,WAAW,eAAe,gBAAAI,OAAQ;AAExC,SAAS,OAAO,gBAAwC;AACtD,SAAO,mBAAe,mBAAAF,SAAY,gBAAAE,SAAU,cAAc,CAAC;AAC7D;AAEA,SAAS,SAAS;AAElB,IAAO,cAAQ;","names":["Accessio","AccessioError","InterceptorManager","buildURL","mergeConfig","accessio","defaults"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import Accessio from './accessio';\nimport defaults from './defaults';\nimport AccessioError from './core/accessioError';\nimport mergeConfig from './core/mergeConfig';\nimport buildURL from './core/buildURL';\nimport InterceptorManager from './interceptors/interceptorManager';\nimport { createRateLimiter } from './helpers/rateLimiter';\nimport { logRequest, logResponse, logError } from './helpers/debug';\nimport { ERR_CANCELED } from './constants/errorCodes';\nimport type { AccessioRequestConfig, AccessioResponse } from './types';\n\nconst PUBLIC_METHODS = [\n 'request',\n 'getUri',\n 'get',\n 'delete',\n 'head',\n 'options',\n 'post',\n 'put',\n 'patch',\n 'postForm',\n 'putForm',\n 'patchForm',\n];\n\nfunction createInstance(defaultConfig: AccessioRequestConfig) {\n const context = new Accessio(defaultConfig);\n\n const instance: any = function accessio(\n configOrUrl: string | AccessioRequestConfig,\n config?: AccessioRequestConfig,\n ) {\n return context.request(configOrUrl, config);\n };\n\n for (const key of PUBLIC_METHODS) {\n const method: any = (context as any)[key];\n if (typeof method === 'function') {\n instance[key] = method.bind(context);\n }\n }\n\n instance.defaults = context.defaults;\n instance.interceptors = context.interceptors;\n instance.all = function all(promises: any[]): Promise<any[]> {\n return Promise.all(promises);\n };\n instance.spread = function spread<T>(callback: (...args: any[]) => T): (arr: any[]) => T {\n return function wrap(arr: any[]): T {\n return callback(...arr);\n };\n };\n instance.isCancel = function isCancel(value: any): boolean {\n return !!(value && value.isAccessioError && value.code === ERR_CANCELED);\n };\n instance.isAccessioError = function isAccessioError(value: any): boolean {\n return (\n value instanceof AccessioError ||\n !!(value && typeof value === 'object' && value.isAccessioError === true)\n );\n };\n instance.AccessioError = AccessioError;\n instance.Accessio = Accessio;\n instance.mergeConfig = mergeConfig;\n instance.buildURL = buildURL;\n instance.InterceptorManager = InterceptorManager;\n instance.createRateLimiter = createRateLimiter;\n\n return instance;\n}\n\nconst accessio = createInstance(defaults);\n\nfunction create(instanceConfig?: AccessioRequestConfig) {\n return createInstance(mergeConfig(defaults, instanceConfig));\n}\n\naccessio.create = create;\n\nexport default accessio;\n\nexport {\n Accessio,\n AccessioError,\n mergeConfig,\n buildURL,\n InterceptorManager,\n createInstance,\n createRateLimiter,\n logRequest,\n logResponse,\n logError,\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA,kCAAAA;AAAA,EAAA,0CAAAC;AAAA,EAAA,oDAAAC;AAAA,EAAA,gCAAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wCAAAC;AAAA;AAAA;AAAA,sBAAqB;AACrB,sBAAqB;AACrB,2BAA0B;AAC1B,yBAAwB;AACxB,sBAAqB;AACrB,gCAA+B;AAC/B,yBAAkC;AAClC,mBAAkD;AAClD,wBAA6B;AAG7B,MAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,eAAe,eAAsC;AAC5D,QAAM,UAAU,IAAI,gBAAAJ,QAAS,aAAa;AAE1C,QAAM,WAAgB,SAASK,UAC7B,aACA,QACA;AACA,WAAO,QAAQ,QAAQ,aAAa,MAAM;AAAA,EAC5C;AAEA,aAAW,OAAO,gBAAgB;AAChC,UAAM,SAAe,QAAgB,GAAG;AACxC,QAAI,OAAO,WAAW,YAAY;AAChC,eAAS,GAAG,IAAI,OAAO,KAAK,OAAO;AAAA,IACrC;AAAA,EACF;AAEA,WAAS,WAAW,QAAQ;AAC5B,WAAS,eAAe,QAAQ;AAChC,WAAS,MAAM,SAAS,IAAI,UAAiC;AAC3D,WAAO,QAAQ,IAAI,QAAQ;AAAA,EAC7B;AACA,WAAS,SAAS,SAAS,OAAU,UAAoD;AACvF,WAAO,SAAS,KAAK,KAAe;AAClC,aAAO,SAAS,GAAG,GAAG;AAAA,IACxB;AAAA,EACF;AACA,WAAS,WAAW,SAAS,SAAS,OAAqB;AACzD,WAAO,CAAC,EAAE,SAAS,MAAM,mBAAmB,MAAM,SAAS;AAAA,EAC7D;AACA,WAAS,kBAAkB,SAAS,gBAAgB,OAAqB;AACvE,WACE,iBAAiB,qBAAAJ,WACjB,CAAC,EAAE,SAAS,OAAO,UAAU,YAAY,MAAM,oBAAoB;AAAA,EAEvE;AACA,WAAS,gBAAgB,qBAAAA;AACzB,WAAS,WAAW,gBAAAD;AACpB,WAAS,cAAc,mBAAAI;AACvB,WAAS,WAAW,gBAAAD;AACpB,WAAS,qBAAqB,0BAAAD;AAC9B,WAAS,oBAAoB;AAE7B,SAAO;AACT;AAEA,MAAM,WAAW,eAAe,gBAAAI,OAAQ;AAExC,SAAS,OAAO,gBAAwC;AACtD,SAAO,mBAAe,mBAAAF,SAAY,gBAAAE,SAAU,cAAc,CAAC;AAC7D;AAEA,SAAS,SAAS;AAElB,IAAO,cAAQ;","names":["Accessio","AccessioError","InterceptorManager","buildURL","mergeConfig","accessio","defaults"]}
@@ -18,12 +18,49 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var interceptorManager_exports = {};
20
20
  __export(interceptorManager_exports, {
21
- InterceptorManager: () => import_types.InterceptorManager,
21
+ InterceptorManager: () => InterceptorManager,
22
22
  default: () => interceptorManager_default
23
23
  });
24
24
  module.exports = __toCommonJS(interceptorManager_exports);
25
- var import_types = require("../types");
26
- var interceptorManager_default = import_types.InterceptorManager;
25
+ class InterceptorManager {
26
+ handlers;
27
+ _activeCount;
28
+ constructor() {
29
+ this.handlers = [];
30
+ this._activeCount = 0;
31
+ }
32
+ use(fulfilled, rejected, options = {}) {
33
+ this.handlers.push({
34
+ fulfilled: fulfilled || null,
35
+ rejected: rejected || null,
36
+ synchronous: options.synchronous || false,
37
+ runWhen: options.runWhen || null
38
+ });
39
+ this._activeCount++;
40
+ return this.handlers.length - 1;
41
+ }
42
+ eject(id) {
43
+ if (this.handlers[id]) {
44
+ this.handlers[id] = null;
45
+ this._activeCount--;
46
+ }
47
+ }
48
+ clear() {
49
+ this.handlers = [];
50
+ this._activeCount = 0;
51
+ }
52
+ forEach(fn) {
53
+ for (const handler of this.handlers) {
54
+ if (handler !== null) {
55
+ fn(handler);
56
+ }
57
+ }
58
+ }
59
+ get size() {
60
+ return this._activeCount;
61
+ }
62
+ }
63
+ var interceptorManager_default = InterceptorManager;
27
64
  // Annotate the CommonJS export names for ESM import in node:
28
65
  0 && (module.exports = {
29
66
  InterceptorManager
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/interceptors/interceptorManager.ts"],"sourcesContent":["import { InterceptorManager } from '../types';\n\nexport { InterceptorManager };\n\nexport default InterceptorManager;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAmC;AAInC,IAAO,6BAAQ;","names":[]}
1
+ {"version":3,"sources":["../../src/interceptors/interceptorManager.ts"],"sourcesContent":["import type { TransformFunction, InterceptorHandler, InterceptorOptions } from '../types';\n\nexport class InterceptorManager {\n handlers: Array<InterceptorHandler | null>;\n private _activeCount: number;\n\n constructor() {\n this.handlers = [];\n this._activeCount = 0;\n }\n\n use(\n fulfilled: TransformFunction | null,\n rejected?: ((error: unknown) => unknown) | null,\n options: InterceptorOptions = {},\n ): number {\n this.handlers.push({\n fulfilled: fulfilled || null,\n rejected: rejected || null,\n synchronous: options.synchronous || false,\n runWhen: options.runWhen || null,\n });\n\n this._activeCount++;\n return this.handlers.length - 1;\n }\n\n eject(id: number): void {\n if (this.handlers[id]) {\n this.handlers[id] = null;\n this._activeCount--;\n }\n }\n\n clear(): void {\n this.handlers = [];\n this._activeCount = 0;\n }\n\n forEach(fn: (handler: InterceptorHandler) => void): void {\n for (const handler of this.handlers) {\n if (handler !== null) {\n fn(handler);\n }\n }\n }\n\n get size(): number {\n return this._activeCount;\n }\n}\n\nexport default InterceptorManager;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEO,MAAM,mBAAmB;AAAA,EAC9B;AAAA,EACQ;AAAA,EAER,cAAc;AACZ,SAAK,WAAW,CAAC;AACjB,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,IACE,WACA,UACA,UAA8B,CAAC,GACvB;AACR,SAAK,SAAS,KAAK;AAAA,MACjB,WAAW,aAAa;AAAA,MACxB,UAAU,YAAY;AAAA,MACtB,aAAa,QAAQ,eAAe;AAAA,MACpC,SAAS,QAAQ,WAAW;AAAA,IAC9B,CAAC;AAED,SAAK;AACL,WAAO,KAAK,SAAS,SAAS;AAAA,EAChC;AAAA,EAEA,MAAM,IAAkB;AACtB,QAAI,KAAK,SAAS,EAAE,GAAG;AACrB,WAAK,SAAS,EAAE,IAAI;AACpB,WAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEA,QAAc;AACZ,SAAK,WAAW,CAAC;AACjB,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,QAAQ,IAAiD;AACvD,eAAW,WAAW,KAAK,UAAU;AACnC,UAAI,YAAY,MAAM;AACpB,WAAG,OAAO;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAAA,EAEA,IAAI,OAAe;AACjB,WAAO,KAAK;AAAA,EACd;AACF;AAEA,IAAO,6BAAQ;","names":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "accessio",
3
- "version": "1.0.0",
4
- "description": "Fast, flexible HTTP client for Node.js and browsers — simple, modular, and dependency-free",
3
+ "version": "1.1.1",
4
+ "description": "Fast, flexible HTTP client — simple, modular, and dependency-free",
5
5
  "type": "module",
6
6
  "main": "./cjs/index.cjs",
7
7
  "module": "./src/index.ts",
@@ -65,9 +65,7 @@
65
65
  "files": [
66
66
  "src/",
67
67
  "cjs/",
68
- "index.d.ts",
69
- "README.md",
70
- "LICENSE"
68
+ "index.d.ts"
71
69
  ],
72
70
  "scripts": {
73
71
  "build:cjs": "tsup",
@@ -75,6 +73,7 @@
75
73
  "prepublishOnly": "npm run build",
76
74
  "lint": "eslint .",
77
75
  "lint:fix": "eslint . --fix",
76
+ "format": "prettier --write .",
78
77
  "test": "vitest run",
79
78
  "test:watch": "vitest",
80
79
  "test:coverage": "vitest run --coverage",
@@ -82,15 +81,6 @@
82
81
  "release:npm": "gh workflow run publish-npm.yml -f publish_tag=$(git describe --tags --abbrev=0)",
83
82
  "typecheck": "tsc --noEmit"
84
83
  },
85
- "keywords": [
86
- "http",
87
- "client",
88
- "ajax",
89
- "fetch",
90
- "promise",
91
- "request",
92
- "accessio"
93
- ],
94
84
  "author": "salvatorecorvaglia",
95
85
  "license": "MIT",
96
86
  "repository": {
@@ -100,7 +90,7 @@
100
90
  "bugs": {
101
91
  "url": "https://github.com/salvatorecorvaglia/accessio/issues"
102
92
  },
103
- "homepage": "https://github.com/salvatorecorvaglia/accessio#readme",
93
+ "homepage": "https://github.com/salvatorecorvaglia/accessio",
104
94
  "sideEffects": false,
105
95
  "engines": {
106
96
  "node": ">=18.0.0"
@@ -108,7 +98,9 @@
108
98
  "devDependencies": {
109
99
  "@vitest/coverage-v8": "^3.1.0",
110
100
  "eslint": "^9.0.0",
101
+ "eslint-config-prettier": "^10.1.8",
111
102
  "jsdom": "^29.0.2",
103
+ "prettier": "^3.8.3",
112
104
  "tsup": "^8.0.0",
113
105
  "typescript": "^5.0.0",
114
106
  "vitest": "^3.1.0"
package/src/accessio.ts CHANGED
@@ -12,13 +12,14 @@ import type {
12
12
  Interceptors,
13
13
  InterceptorHandler,
14
14
  } from './types';
15
+ import defaultsConfig from './defaults/index';
15
16
 
16
17
  export class Accessio {
17
18
  defaults: AccessioRequestConfig;
18
19
  interceptors: Interceptors;
19
20
 
20
21
  constructor(instanceConfig: AccessioRequestConfig = {}) {
21
- this.defaults = instanceConfig;
22
+ this.defaults = mergeConfig(defaultsConfig, instanceConfig);
22
23
  this.interceptors = {
23
24
  request: new InterceptorManager(),
24
25
  response: new InterceptorManager(),
@@ -66,31 +67,20 @@ export class Accessio {
66
67
  let promise: Promise<any> = Promise.resolve(mergedConfig);
67
68
 
68
69
  for (const interceptor of requestInterceptors) {
69
- promise = promise.then(
70
- (value: any) => {
71
- if (interceptor.fulfilled) {
72
- return interceptor.fulfilled(value);
73
- }
74
- return value;
75
- },
76
- interceptor.rejected,
77
- );
70
+ promise = promise.then((value: any) => {
71
+ if (interceptor.fulfilled) {
72
+ return interceptor.fulfilled(value);
73
+ }
74
+ return value;
75
+ }, interceptor.rejected);
78
76
  }
79
77
 
80
78
  promise = promise.then((cfg: any) => {
81
- const fullUrl = buildURL(
82
- cfg.url ?? '',
83
- cfg.baseURL,
84
- cfg.params,
85
- cfg.paramsSerializer,
86
- );
79
+ const fullUrl = buildURL(cfg.url ?? '', cfg.baseURL, cfg.params, cfg.paramsSerializer);
87
80
 
88
81
  logRequest(cfg, fullUrl);
89
82
 
90
- const enrichedCfg =
91
- fullUrl !== (cfg.url || '')
92
- ? { ...cfg, _builtUrl: fullUrl }
93
- : cfg;
83
+ const enrichedCfg = fullUrl !== (cfg.url || '') ? { ...cfg, _builtUrl: fullUrl } : cfg;
94
84
 
95
85
  const dispatchFn = cfg.rateLimiter
96
86
  ? (config: AccessioRequestConfig) =>
@@ -112,15 +102,12 @@ export class Accessio {
112
102
  );
113
103
 
114
104
  for (const interceptor of responseInterceptors) {
115
- promise = promise.then(
116
- (value: any) => {
117
- if (interceptor.fulfilled) {
118
- return interceptor.fulfilled(value);
119
- }
120
- return value;
121
- },
122
- interceptor.rejected,
123
- );
105
+ promise = promise.then((value: any) => {
106
+ if (interceptor.fulfilled) {
107
+ return interceptor.fulfilled(value);
108
+ }
109
+ return value;
110
+ }, interceptor.rejected);
124
111
  }
125
112
 
126
113
  return promise;
@@ -128,48 +115,23 @@ export class Accessio {
128
115
 
129
116
  getUri(config?: AccessioRequestConfig): string {
130
117
  const merged = mergeConfig(this.defaults, config);
131
- return buildURL(
132
- merged.url ?? '',
133
- merged.baseURL,
134
- merged.params,
135
- merged.paramsSerializer,
136
- );
118
+ return buildURL(merged.url ?? '', merged.baseURL, merged.params, merged.paramsSerializer);
137
119
  }
138
120
 
139
- get<T = any>(
140
- url: string,
141
- config?: AccessioRequestConfig,
142
- ): Promise<AccessioResponse<T>> {
143
- return this.request<T>(
144
- mergeConfig(config || {}, { method: 'get', url }),
145
- );
121
+ get<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {
122
+ return this.request<T>(mergeConfig(config || {}, { method: 'get', url }));
146
123
  }
147
124
 
148
- delete<T = any>(
149
- url: string,
150
- config?: AccessioRequestConfig,
151
- ): Promise<AccessioResponse<T>> {
152
- return this.request<T>(
153
- mergeConfig(config || {}, { method: 'delete', url }),
154
- );
125
+ delete<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {
126
+ return this.request<T>(mergeConfig(config || {}, { method: 'delete', url }));
155
127
  }
156
128
 
157
- head<T = any>(
158
- url: string,
159
- config?: AccessioRequestConfig,
160
- ): Promise<AccessioResponse<T>> {
161
- return this.request<T>(
162
- mergeConfig(config || {}, { method: 'head', url }),
163
- );
129
+ head<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {
130
+ return this.request<T>(mergeConfig(config || {}, { method: 'head', url }));
164
131
  }
165
132
 
166
- options<T = any>(
167
- url: string,
168
- config?: AccessioRequestConfig,
169
- ): Promise<AccessioResponse<T>> {
170
- return this.request<T>(
171
- mergeConfig(config || {}, { method: 'options', url }),
172
- );
133
+ options<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {
134
+ return this.request<T>(mergeConfig(config || {}, { method: 'options', url }));
173
135
  }
174
136
 
175
137
  post<T = any>(
@@ -177,9 +139,7 @@ export class Accessio {
177
139
  data?: any,
178
140
  config?: AccessioRequestConfig,
179
141
  ): Promise<AccessioResponse<T>> {
180
- return this.request<T>(
181
- mergeConfig(config || {}, { method: 'post', url, data }),
182
- );
142
+ return this.request<T>(mergeConfig(config || {}, { method: 'post', url, data }));
183
143
  }
184
144
 
185
145
  put<T = any>(
@@ -187,9 +147,7 @@ export class Accessio {
187
147
  data?: any,
188
148
  config?: AccessioRequestConfig,
189
149
  ): Promise<AccessioResponse<T>> {
190
- return this.request<T>(
191
- mergeConfig(config || {}, { method: 'put', url, data }),
192
- );
150
+ return this.request<T>(mergeConfig(config || {}, { method: 'put', url, data }));
193
151
  }
194
152
 
195
153
  patch<T = any>(
@@ -197,9 +155,7 @@ export class Accessio {
197
155
  data?: any,
198
156
  config?: AccessioRequestConfig,
199
157
  ): Promise<AccessioResponse<T>> {
200
- return this.request<T>(
201
- mergeConfig(config || {}, { method: 'patch', url, data }),
202
- );
158
+ return this.request<T>(mergeConfig(config || {}, { method: 'patch', url, data }));
203
159
  }
204
160
 
205
161
  postForm<T = any>(
@@ -58,13 +58,7 @@ export class AccessioError extends Error {
58
58
  request: unknown,
59
59
  response: AccessioResponse | null,
60
60
  ): AccessioError {
61
- const accessioError = new AccessioError(
62
- error.message,
63
- code,
64
- config,
65
- request,
66
- response,
67
- );
61
+ const accessioError = new AccessioError(error.message, code, config, request, response);
68
62
  accessioError.cause = error;
69
63
  accessioError.stack = error.stack;
70
64
  return accessioError;
@@ -10,10 +10,7 @@ function serializeParams(
10
10
  return paramsSerializer(params);
11
11
  }
12
12
 
13
- if (
14
- typeof URLSearchParams !== 'undefined' &&
15
- params instanceof URLSearchParams
16
- ) {
13
+ if (typeof URLSearchParams !== 'undefined' && params instanceof URLSearchParams) {
17
14
  return params.toString();
18
15
  }
19
16
 
@@ -29,7 +26,7 @@ function serializeParams(
29
26
  if (typeof item === 'object' && item !== null) {
30
27
  encode(`${prefix}[${index}]`, item);
31
28
  } else {
32
- encode(`${prefix}[]`, item);
29
+ encode(prefix, item);
33
30
  }
34
31
  });
35
32
  } else if (typeof value === 'object' && !(value instanceof Date)) {
@@ -38,11 +35,7 @@ function serializeParams(
38
35
  });
39
36
  } else {
40
37
  const encodedValue = value instanceof Date ? value.toISOString() : value;
41
- parts.push(
42
- `${encodeURIComponent(prefix)}=${encodeURIComponent(
43
- encodedValue as string,
44
- )}`,
45
- );
38
+ parts.push(`${encodeURIComponent(prefix)}=${encodeURIComponent(encodedValue as string)}`);
46
39
  }
47
40
  }
48
41
 
@@ -71,7 +64,7 @@ function combineURLs(baseURL: string, relativeURL: string): string {
71
64
  }
72
65
 
73
66
  function isAbsoluteURL(url: string): boolean {
74
- return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url);
67
+ return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url) || /^([a-z][a-z\d+\-.]*:)/i.test(url);
75
68
  }
76
69
 
77
70
  export default function buildURL(
@@ -80,8 +73,7 @@ export default function buildURL(
80
73
  params?: Record<string, unknown>,
81
74
  paramsSerializer?: ParamsSerializer,
82
75
  ): string {
83
- let fullURL =
84
- baseURL && !isAbsoluteURL(url) ? combineURLs(baseURL, url) : url || '';
76
+ let fullURL = baseURL && !isAbsoluteURL(url) ? combineURLs(baseURL, url) : url || '';
85
77
 
86
78
  const serialized = serializeParams(params as Record<string, unknown>, paramsSerializer);
87
79
  if (serialized) {
@@ -89,8 +81,7 @@ export default function buildURL(
89
81
  if (hashIndex !== -1) {
90
82
  fullURL = fullURL.slice(0, hashIndex);
91
83
  }
92
- fullURL +=
93
- (fullURL.indexOf('?') === -1 ? '?' : '&') + serialized;
84
+ fullURL += (fullURL.indexOf('?') === -1 ? '?' : '&') + serialized;
94
85
  }
95
86
 
96
87
  return fullURL;
@@ -7,29 +7,22 @@ function deepMerge(...sources: any[]): Record<string, any> {
7
7
  if (!source || typeof source !== 'object') continue;
8
8
 
9
9
  for (const key of Object.keys(source)) {
10
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;
11
+
10
12
  const value = source[key];
11
13
 
12
- if (
13
- value &&
14
- typeof value === 'object' &&
15
- !Array.isArray(value)
16
- ) {
14
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
17
15
  if (
18
16
  value instanceof Date ||
19
17
  value instanceof RegExp ||
20
18
  value instanceof Map ||
21
19
  value instanceof Set ||
22
20
  value instanceof Error ||
23
- (typeof ArrayBuffer !== 'undefined' &&
24
- value instanceof ArrayBuffer) ||
21
+ (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) ||
25
22
  (typeof Blob !== 'undefined' && value instanceof Blob)
26
23
  ) {
27
24
  result[key] = value;
28
- } else if (
29
- result[key] &&
30
- typeof result[key] === 'object' &&
31
- !Array.isArray(result[key])
32
- ) {
25
+ } else if (result[key] && typeof result[key] === 'object' && !Array.isArray(result[key])) {
33
26
  result[key] = deepMerge(result[key], value);
34
27
  } else {
35
28
  result[key] = deepMerge(value);
@@ -52,10 +45,7 @@ export default function mergeConfig(
52
45
  ): AccessioRequestConfig {
53
46
  const merged: any = {};
54
47
 
55
- const allKeys = new Set<string>([
56
- ...Object.keys(config1),
57
- ...Object.keys(config2),
58
- ]);
48
+ const allKeys = new Set<string>([...Object.keys(config1), ...Object.keys(config2)]);
59
49
 
60
50
  for (const key of allKeys) {
61
51
  const val1 = config1[key as keyof AccessioRequestConfig];