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.
- package/README.md +121 -391
- package/cjs/accessio.cjs +23 -52
- package/cjs/accessio.cjs.map +1 -1
- package/cjs/core/accessioError.cjs +1 -7
- package/cjs/core/accessioError.cjs.map +1 -1
- package/cjs/core/buildURL.cjs +3 -7
- package/cjs/core/buildURL.cjs.map +1 -1
- package/cjs/core/mergeConfig.cjs +2 -4
- package/cjs/core/mergeConfig.cjs.map +1 -1
- package/cjs/core/request.cjs +74 -66
- package/cjs/core/request.cjs.map +1 -1
- package/cjs/core/retry.cjs +2 -11
- package/cjs/core/retry.cjs.map +1 -1
- package/cjs/defaults/index.cjs.map +1 -1
- package/cjs/defaults/transforms.cjs +8 -1
- package/cjs/defaults/transforms.cjs.map +1 -1
- package/cjs/helpers/debug.cjs +1 -3
- package/cjs/helpers/debug.cjs.map +1 -1
- package/cjs/helpers/parseHeaders.cjs.map +1 -1
- package/cjs/helpers/rateLimiter.cjs +13 -7
- package/cjs/helpers/rateLimiter.cjs.map +1 -1
- package/cjs/helpers/transformData.cjs.map +1 -1
- package/cjs/index.cjs.map +1 -1
- package/cjs/interceptors/interceptorManager.cjs +40 -3
- package/cjs/interceptors/interceptorManager.cjs.map +1 -1
- package/package.json +7 -15
- package/src/accessio.ts +28 -72
- package/src/core/accessioError.ts +1 -7
- package/src/core/buildURL.ts +6 -15
- package/src/core/mergeConfig.ts +6 -16
- package/src/core/request.ts +90 -74
- package/src/core/retry.ts +4 -19
- package/src/defaults/index.ts +1 -3
- package/src/defaults/transforms.ts +9 -5
- package/src/helpers/debug.ts +12 -22
- package/src/helpers/parseHeaders.ts +1 -3
- package/src/helpers/rateLimiter.ts +19 -16
- package/src/helpers/transformData.ts +1 -4
- package/src/index.ts +3 -11
- package/src/interceptors/interceptorManager.ts +50 -2
- package/src/types.ts +8 -68
package/cjs/core/retry.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/retry.ts"],"sourcesContent":["import {
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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":[]}
|
package/cjs/helpers/debug.cjs
CHANGED
|
@@ -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(
|
|
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(
|
|
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 {
|
|
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 {
|
|
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>(
|
|
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: () =>
|
|
21
|
+
InterceptorManager: () => InterceptorManager,
|
|
22
22
|
default: () => interceptorManager_default
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(interceptorManager_exports);
|
|
25
|
-
|
|
26
|
-
|
|
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 {
|
|
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.
|
|
4
|
-
"description": "Fast, flexible HTTP client
|
|
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
|
|
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
|
-
(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
(
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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;
|
package/src/core/buildURL.ts
CHANGED
|
@@ -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(
|
|
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;
|
package/src/core/mergeConfig.ts
CHANGED
|
@@ -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];
|