accessio 1.7.0 → 1.7.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/cjs/accessio.cjs +76 -10
- package/cjs/accessio.cjs.map +1 -1
- package/cjs/core/buildURL.cjs +24 -26
- package/cjs/core/buildURL.cjs.map +1 -1
- package/cjs/core/mergeConfig.cjs +14 -9
- package/cjs/core/mergeConfig.cjs.map +1 -1
- package/cjs/core/request.cjs +1 -1
- package/cjs/core/request.cjs.map +1 -1
- package/cjs/helpers/flattenHeaders.cjs +34 -22
- package/cjs/helpers/flattenHeaders.cjs.map +1 -1
- package/cjs/helpers/memoryCache.cjs +8 -3
- package/cjs/helpers/memoryCache.cjs.map +1 -1
- package/package.json +4 -1
- package/src/accessio.ts +78 -14
- package/src/core/buildURL.ts +28 -30
- package/src/core/mergeConfig.ts +14 -10
- package/src/core/request.ts +1 -1
- package/src/helpers/flattenHeaders.ts +34 -22
- package/src/helpers/memoryCache.ts +8 -3
package/cjs/accessio.cjs
CHANGED
|
@@ -66,7 +66,10 @@ function runRequestInterceptorsSync(startConfig, interceptors) {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
-
|
|
69
|
+
if (isRejected) {
|
|
70
|
+
throw rejectReason;
|
|
71
|
+
}
|
|
72
|
+
return cfg;
|
|
70
73
|
}
|
|
71
74
|
function runRequestInterceptorsAsync(startConfig, interceptors) {
|
|
72
75
|
let promise = Promise.resolve(startConfig);
|
|
@@ -81,7 +84,7 @@ function runRequestInterceptorsAsync(startConfig, interceptors) {
|
|
|
81
84
|
function dispatchAndRetry(cfg) {
|
|
82
85
|
const fullUrl = (0, import_buildURL.default)(cfg.url ?? "", cfg.baseURL, cfg.params, cfg.paramsSerializer);
|
|
83
86
|
(0, import_debug.logRequest)(cfg, fullUrl);
|
|
84
|
-
const enrichedCfg =
|
|
87
|
+
const enrichedCfg = { ...cfg, _builtUrl: fullUrl };
|
|
85
88
|
const dispatchFn = cfg.rateLimiter ? (config) => (0, import_rateLimiter.rateLimitedRequest)(import_request.default, config.rateLimiter, config) : import_request.default;
|
|
86
89
|
return (0, import_retry.default)(dispatchFn, enrichedCfg);
|
|
87
90
|
}
|
|
@@ -113,8 +116,19 @@ class Accessio {
|
|
|
113
116
|
);
|
|
114
117
|
}
|
|
115
118
|
const { requestInterceptors, responseInterceptors, synchronous } = this.collectInterceptors(mergedConfig);
|
|
116
|
-
let promise
|
|
117
|
-
|
|
119
|
+
let promise;
|
|
120
|
+
if (synchronous) {
|
|
121
|
+
try {
|
|
122
|
+
const finalCfg = runRequestInterceptorsSync(mergedConfig, requestInterceptors);
|
|
123
|
+
promise = dispatchAndRetry(finalCfg);
|
|
124
|
+
} catch (err) {
|
|
125
|
+
promise = Promise.reject(err);
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
promise = runRequestInterceptorsAsync(mergedConfig, requestInterceptors).then(
|
|
129
|
+
(cfg) => dispatchAndRetry(cfg)
|
|
130
|
+
);
|
|
131
|
+
}
|
|
118
132
|
promise = promise.then(
|
|
119
133
|
(value) => {
|
|
120
134
|
(0, import_debug.logResponse)(value);
|
|
@@ -125,13 +139,65 @@ class Accessio {
|
|
|
125
139
|
throw error;
|
|
126
140
|
}
|
|
127
141
|
);
|
|
128
|
-
|
|
129
|
-
promise = promise.then(
|
|
130
|
-
|
|
131
|
-
|
|
142
|
+
if (responseInterceptors.length > 0) {
|
|
143
|
+
promise = promise.then(
|
|
144
|
+
async (value) => {
|
|
145
|
+
let current = value;
|
|
146
|
+
let isRejected = false;
|
|
147
|
+
for (const interceptor of responseInterceptors) {
|
|
148
|
+
if (!isRejected) {
|
|
149
|
+
try {
|
|
150
|
+
if (interceptor.fulfilled) {
|
|
151
|
+
current = await interceptor.fulfilled(current);
|
|
152
|
+
}
|
|
153
|
+
} catch (err) {
|
|
154
|
+
current = err;
|
|
155
|
+
isRejected = true;
|
|
156
|
+
}
|
|
157
|
+
} else if (interceptor.rejected) {
|
|
158
|
+
try {
|
|
159
|
+
current = await interceptor.rejected(current);
|
|
160
|
+
isRejected = false;
|
|
161
|
+
} catch (err) {
|
|
162
|
+
current = err;
|
|
163
|
+
isRejected = true;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (isRejected) {
|
|
168
|
+
throw current;
|
|
169
|
+
}
|
|
170
|
+
return current;
|
|
171
|
+
},
|
|
172
|
+
async (error) => {
|
|
173
|
+
let current = error;
|
|
174
|
+
let isRejected = true;
|
|
175
|
+
for (const interceptor of responseInterceptors) {
|
|
176
|
+
if (!isRejected) {
|
|
177
|
+
try {
|
|
178
|
+
if (interceptor.fulfilled) {
|
|
179
|
+
current = await interceptor.fulfilled(current);
|
|
180
|
+
}
|
|
181
|
+
} catch (err) {
|
|
182
|
+
current = err;
|
|
183
|
+
isRejected = true;
|
|
184
|
+
}
|
|
185
|
+
} else if (interceptor.rejected) {
|
|
186
|
+
try {
|
|
187
|
+
current = await interceptor.rejected(current);
|
|
188
|
+
isRejected = false;
|
|
189
|
+
} catch (err) {
|
|
190
|
+
current = err;
|
|
191
|
+
isRejected = true;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (isRejected) {
|
|
196
|
+
throw current;
|
|
197
|
+
}
|
|
198
|
+
return current;
|
|
132
199
|
}
|
|
133
|
-
|
|
134
|
-
}, interceptor.rejected ?? void 0);
|
|
200
|
+
);
|
|
135
201
|
}
|
|
136
202
|
return promise;
|
|
137
203
|
}
|
package/cjs/accessio.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/accessio.ts"],"sourcesContent":["import InterceptorManager from './interceptors/interceptorManager';\nimport AccessioError from './core/accessioError';\nimport mergeConfig from './core/mergeConfig';\nimport dispatchRequest from './core/request';\nimport buildURL from './core/buildURL';\nimport retryRequest from './core/retry';\nimport { logRequest, logResponse, logError } from './helpers/debug';\nimport { rateLimitedRequest } from './helpers/rateLimiter';\nimport { toFormData } from './helpers/toFormData';\nimport type {\n AccessioRequestConfig,\n AccessioResponse,\n Interceptors,\n InterceptorHandler,\n} from './types';\nimport defaultsConfig from './defaults/index';\n\nfunction runRequestInterceptorsSync(\n startConfig: AccessioRequestConfig,\n interceptors: InterceptorHandler[],\n): Promise<AccessioRequestConfig> {\n let cfg = startConfig;\n let rejectReason: any = null;\n let isRejected = false;\n\n for (const interceptor of interceptors) {\n if (!isRejected) {\n try {\n if (interceptor.fulfilled) {\n cfg = (interceptor.fulfilled as any)(cfg) as AccessioRequestConfig;\n }\n } catch (err) {\n rejectReason = err;\n isRejected = true;\n }\n } else if (interceptor.rejected) {\n try {\n cfg = interceptor.rejected(rejectReason) as AccessioRequestConfig;\n isRejected = false;\n } catch (err) {\n rejectReason = err;\n isRejected = true;\n }\n }\n }\n\n return isRejected ? Promise.reject(rejectReason) : Promise.resolve(cfg);\n}\n\nfunction runRequestInterceptorsAsync(\n startConfig: AccessioRequestConfig,\n interceptors: InterceptorHandler[],\n): Promise<AccessioRequestConfig> {\n let promise: Promise<any> = Promise.resolve(startConfig);\n for (const interceptor of interceptors) {\n promise = promise.then(\n (value: any) => (interceptor.fulfilled ? (interceptor.fulfilled as any)(value) : value),\n interceptor.rejected ?? undefined,\n );\n }\n return promise as Promise<AccessioRequestConfig>;\n}\n\nfunction dispatchAndRetry(cfg: AccessioRequestConfig): Promise<AccessioResponse> {\n const fullUrl = buildURL(cfg.url ?? '', cfg.baseURL, cfg.params, cfg.paramsSerializer);\n logRequest(cfg, fullUrl);\n\n const enrichedCfg = fullUrl !== (cfg.url || '') ? { ...cfg, _builtUrl: fullUrl } : cfg;\n\n const dispatchFn = cfg.rateLimiter\n ? (config: AccessioRequestConfig) =>\n rateLimitedRequest(dispatchRequest, config.rateLimiter!, config)\n : dispatchRequest;\n\n return retryRequest(dispatchFn, enrichedCfg);\n}\n\nexport class Accessio {\n defaults: AccessioRequestConfig;\n interceptors: Interceptors;\n\n constructor(instanceConfig: AccessioRequestConfig = {}) {\n this.defaults = mergeConfig(defaultsConfig, instanceConfig);\n this.interceptors = {\n request: new InterceptorManager(),\n response: new InterceptorManager(),\n };\n }\n\n request<T = any>(\n configOrUrl: string | AccessioRequestConfig,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n if (typeof configOrUrl === 'string') {\n config = { ...config, url: configOrUrl };\n } else {\n config = configOrUrl ? { ...configOrUrl } : {};\n }\n\n const mergedConfig = mergeConfig(this.defaults, config);\n\n mergedConfig.method = (mergedConfig.method || 'get').toLowerCase();\n\n if (!mergedConfig.url && !mergedConfig.baseURL) {\n throw new AccessioError(\n 'Request URL is required. Provide a `url` or `baseURL` in the config.',\n AccessioError.ERR_BAD_OPTION,\n mergedConfig,\n null,\n null,\n );\n }\n\n const { requestInterceptors, responseInterceptors, synchronous } =\n this.collectInterceptors(mergedConfig);\n\n let promise: Promise<any> = synchronous\n ? runRequestInterceptorsSync(mergedConfig, requestInterceptors)\n : runRequestInterceptorsAsync(mergedConfig, requestInterceptors);\n\n promise = promise.then((cfg: AccessioRequestConfig) => dispatchAndRetry(cfg));\n\n promise = promise.then(\n (value: AccessioResponse) => {\n logResponse(value);\n return value;\n },\n (error: any) => {\n logError(error, mergedConfig);\n throw error;\n },\n );\n\n for (const interceptor of responseInterceptors) {\n promise = promise.then((value: any) => {\n if (interceptor.fulfilled) {\n return (interceptor.fulfilled as any)(value);\n }\n return value;\n }, interceptor.rejected ?? undefined);\n }\n\n return promise;\n }\n\n private collectInterceptors(mergedConfig: AccessioRequestConfig): {\n requestInterceptors: InterceptorHandler[];\n responseInterceptors: InterceptorHandler[];\n synchronous: boolean;\n } {\n const requestInterceptors: InterceptorHandler[] = [];\n const responseInterceptors: InterceptorHandler[] = [];\n let synchronous = true;\n\n this.interceptors.request.forEach((interceptor: InterceptorHandler) => {\n if (interceptor.runWhen && !interceptor.runWhen(mergedConfig)) return;\n synchronous = synchronous && interceptor.synchronous;\n requestInterceptors.unshift(interceptor);\n });\n\n this.interceptors.response.forEach((interceptor: InterceptorHandler) => {\n responseInterceptors.push(interceptor);\n });\n\n return { requestInterceptors, responseInterceptors, synchronous };\n }\n\n getUri(config?: AccessioRequestConfig): string {\n const merged = mergeConfig(this.defaults, config);\n return buildURL(merged.url ?? '', merged.baseURL, merged.params, merged.paramsSerializer);\n }\n\n get<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'get', url }));\n }\n\n delete<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'delete', url }));\n }\n\n head<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'head', url }));\n }\n\n options<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'options', url }));\n }\n\n post<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'post', url, data }));\n }\n\n put<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'put', url, data }));\n }\n\n patch<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'patch', url, data }));\n }\n\n private formRequest<T = any>(\n method: 'post' | 'put' | 'patch',\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n const formData = data && !(data instanceof FormData) ? toFormData(data) : data;\n return this.request<T>(\n mergeConfig(config || {}, {\n method,\n url,\n data: formData,\n headers: { 'Content-Type': 'multipart/form-data' },\n }),\n );\n }\n\n postForm<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.formRequest<T>('post', url, data, config);\n }\n\n putForm<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.formRequest<T>('put', url, data, config);\n }\n\n patchForm<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.formRequest<T>('patch', url, data, config);\n }\n\n async *stream<T = any>(\n url: string,\n config?: AccessioRequestConfig,\n ): AsyncGenerator<T, void, unknown> {\n const response = await this.request<ReadableStream<Uint8Array>>(\n mergeConfig(config || {}, { method: 'get', url, responseType: 'stream' }),\n );\n if (!response.data) return;\n\n const reader = response.data.getReader();\n try {\n const decoder = new TextDecoder();\n let buffer = '';\n\n const processLine = function* (line: string) {\n const trimmed = line.trim();\n if (trimmed.startsWith('data:')) {\n const dataStr = line.replace(/^data:\\s*/, '');\n if (dataStr === '[DONE]') return;\n try {\n yield JSON.parse(dataStr);\n } catch (e) {\n yield dataStr as any;\n }\n } else if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n try {\n yield JSON.parse(line);\n } catch (e) {\n // ignore partial json\n }\n }\n };\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n yield* processLine(line);\n }\n }\n\n buffer += decoder.decode(new Uint8Array(), { stream: false });\n if (buffer.trim()) {\n yield* processLine(buffer);\n }\n } finally {\n try {\n await reader.cancel();\n } catch {\n // ignore errors on cancel\n }\n reader.releaseLock();\n }\n }\n\n async *autoPaginate<T = any>(\n url: string,\n config?: AccessioRequestConfig,\n ): AsyncGenerator<T, void, unknown> {\n let nextUrl: string | null = url;\n let currentConfig = config || {};\n\n while (nextUrl) {\n const response: AccessioResponse<any> = await this.get(nextUrl, currentConfig);\n\n const data = response.data;\n const items = Array.isArray(data)\n ? data\n : data && typeof data === 'object'\n ? (data as any).data\n : null;\n\n if (Array.isArray(items)) {\n for (const item of items) {\n yield item;\n }\n }\n\n nextUrl =\n data && typeof data === 'object'\n ? (data as any).next || (data as any).links?.next || null\n : null;\n\n if (nextUrl) {\n currentConfig = mergeConfig(currentConfig, { url: nextUrl, params: {} });\n }\n }\n }\n\n gql<T = any>(\n url: string,\n query: string,\n variables?: Record<string, any>,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.post<T>(url, { query, variables }, config);\n }\n}\n\nexport default Accessio;\n"],"mappings":"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","names":["buildURL","dispatchRequest","retryRequest","mergeConfig","defaultsConfig","InterceptorManager","AccessioError"]}
|
|
1
|
+
{"version":3,"sources":["../src/accessio.ts"],"sourcesContent":["import InterceptorManager from './interceptors/interceptorManager';\nimport AccessioError from './core/accessioError';\nimport mergeConfig from './core/mergeConfig';\nimport dispatchRequest from './core/request';\nimport buildURL from './core/buildURL';\nimport retryRequest from './core/retry';\nimport { logRequest, logResponse, logError } from './helpers/debug';\nimport { rateLimitedRequest } from './helpers/rateLimiter';\nimport { toFormData } from './helpers/toFormData';\nimport type {\n AccessioRequestConfig,\n AccessioResponse,\n Interceptors,\n InterceptorHandler,\n} from './types';\nimport defaultsConfig from './defaults/index';\n\nfunction runRequestInterceptorsSync(\n startConfig: AccessioRequestConfig,\n interceptors: InterceptorHandler[],\n): AccessioRequestConfig {\n let cfg = startConfig;\n let rejectReason: any = null;\n let isRejected = false;\n\n for (const interceptor of interceptors) {\n if (!isRejected) {\n try {\n if (interceptor.fulfilled) {\n cfg = (interceptor.fulfilled as any)(cfg) as AccessioRequestConfig;\n }\n } catch (err) {\n rejectReason = err;\n isRejected = true;\n }\n } else if (interceptor.rejected) {\n try {\n cfg = interceptor.rejected(rejectReason) as AccessioRequestConfig;\n isRejected = false;\n } catch (err) {\n rejectReason = err;\n isRejected = true;\n }\n }\n }\n\n if (isRejected) {\n throw rejectReason;\n }\n return cfg;\n}\n\nfunction runRequestInterceptorsAsync(\n startConfig: AccessioRequestConfig,\n interceptors: InterceptorHandler[],\n): Promise<AccessioRequestConfig> {\n let promise: Promise<any> = Promise.resolve(startConfig);\n for (const interceptor of interceptors) {\n promise = promise.then(\n (value: any) => (interceptor.fulfilled ? (interceptor.fulfilled as any)(value) : value),\n interceptor.rejected ?? undefined,\n );\n }\n return promise as Promise<AccessioRequestConfig>;\n}\n\nfunction dispatchAndRetry(cfg: AccessioRequestConfig): Promise<AccessioResponse> {\n const fullUrl = buildURL(cfg.url ?? '', cfg.baseURL, cfg.params, cfg.paramsSerializer);\n logRequest(cfg, fullUrl);\n\n const enrichedCfg = { ...cfg, _builtUrl: fullUrl };\n\n const dispatchFn = cfg.rateLimiter\n ? (config: AccessioRequestConfig) =>\n rateLimitedRequest(dispatchRequest, config.rateLimiter!, config)\n : dispatchRequest;\n\n return retryRequest(dispatchFn, enrichedCfg);\n}\n\nexport class Accessio {\n defaults: AccessioRequestConfig;\n interceptors: Interceptors;\n\n constructor(instanceConfig: AccessioRequestConfig = {}) {\n this.defaults = mergeConfig(defaultsConfig, instanceConfig);\n this.interceptors = {\n request: new InterceptorManager(),\n response: new InterceptorManager(),\n };\n }\n\n request<T = any>(\n configOrUrl: string | AccessioRequestConfig,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n if (typeof configOrUrl === 'string') {\n config = { ...config, url: configOrUrl };\n } else {\n config = configOrUrl ? { ...configOrUrl } : {};\n }\n\n const mergedConfig = mergeConfig(this.defaults, config);\n\n mergedConfig.method = (mergedConfig.method || 'get').toLowerCase();\n\n if (!mergedConfig.url && !mergedConfig.baseURL) {\n throw new AccessioError(\n 'Request URL is required. Provide a `url` or `baseURL` in the config.',\n AccessioError.ERR_BAD_OPTION,\n mergedConfig,\n null,\n null,\n );\n }\n\n const { requestInterceptors, responseInterceptors, synchronous } =\n this.collectInterceptors(mergedConfig);\n\n let promise: Promise<any>;\n\n if (synchronous) {\n try {\n const finalCfg = runRequestInterceptorsSync(mergedConfig, requestInterceptors);\n promise = dispatchAndRetry(finalCfg);\n } catch (err) {\n promise = Promise.reject(err);\n }\n } else {\n promise = runRequestInterceptorsAsync(mergedConfig, requestInterceptors).then(\n (cfg: AccessioRequestConfig) => dispatchAndRetry(cfg),\n );\n }\n\n promise = promise.then(\n (value: AccessioResponse) => {\n logResponse(value);\n return value;\n },\n (error: any) => {\n logError(error, mergedConfig);\n throw error;\n },\n );\n\n if (responseInterceptors.length > 0) {\n promise = promise.then(\n async (value: AccessioResponse) => {\n let current: any = value;\n let isRejected = false;\n for (const interceptor of responseInterceptors) {\n if (!isRejected) {\n try {\n if (interceptor.fulfilled) {\n current = await (interceptor.fulfilled as any)(current);\n }\n } catch (err) {\n current = err;\n isRejected = true;\n }\n } else if (interceptor.rejected) {\n try {\n current = await interceptor.rejected(current);\n isRejected = false;\n } catch (err) {\n current = err;\n isRejected = true;\n }\n }\n }\n if (isRejected) {\n throw current;\n }\n return current;\n },\n async (error: any) => {\n let current: any = error;\n let isRejected = true;\n for (const interceptor of responseInterceptors) {\n if (!isRejected) {\n try {\n if (interceptor.fulfilled) {\n current = await (interceptor.fulfilled as any)(current);\n }\n } catch (err) {\n current = err;\n isRejected = true;\n }\n } else if (interceptor.rejected) {\n try {\n current = await interceptor.rejected(current);\n isRejected = false;\n } catch (err) {\n current = err;\n isRejected = true;\n }\n }\n }\n if (isRejected) {\n throw current;\n }\n return current;\n },\n );\n }\n\n return promise;\n }\n\n private collectInterceptors(mergedConfig: AccessioRequestConfig): {\n requestInterceptors: InterceptorHandler[];\n responseInterceptors: InterceptorHandler[];\n synchronous: boolean;\n } {\n const requestInterceptors: InterceptorHandler[] = [];\n const responseInterceptors: InterceptorHandler[] = [];\n let synchronous = true;\n\n this.interceptors.request.forEach((interceptor: InterceptorHandler) => {\n if (interceptor.runWhen && !interceptor.runWhen(mergedConfig)) return;\n synchronous = synchronous && interceptor.synchronous;\n requestInterceptors.unshift(interceptor);\n });\n\n this.interceptors.response.forEach((interceptor: InterceptorHandler) => {\n responseInterceptors.push(interceptor);\n });\n\n return { requestInterceptors, responseInterceptors, synchronous };\n }\n\n getUri(config?: AccessioRequestConfig): string {\n const merged = mergeConfig(this.defaults, config);\n return buildURL(merged.url ?? '', merged.baseURL, merged.params, merged.paramsSerializer);\n }\n\n get<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'get', url }));\n }\n\n delete<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'delete', url }));\n }\n\n head<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'head', url }));\n }\n\n options<T = any>(url: string, config?: AccessioRequestConfig): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'options', url }));\n }\n\n post<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'post', url, data }));\n }\n\n put<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'put', url, data }));\n }\n\n patch<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.request<T>(mergeConfig(config || {}, { method: 'patch', url, data }));\n }\n\n private formRequest<T = any>(\n method: 'post' | 'put' | 'patch',\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n const formData = data && !(data instanceof FormData) ? toFormData(data) : data;\n return this.request<T>(\n mergeConfig(config || {}, {\n method,\n url,\n data: formData,\n headers: { 'Content-Type': 'multipart/form-data' },\n }),\n );\n }\n\n postForm<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.formRequest<T>('post', url, data, config);\n }\n\n putForm<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.formRequest<T>('put', url, data, config);\n }\n\n patchForm<T = any>(\n url: string,\n data?: any,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.formRequest<T>('patch', url, data, config);\n }\n\n async *stream<T = any>(\n url: string,\n config?: AccessioRequestConfig,\n ): AsyncGenerator<T, void, unknown> {\n const response = await this.request<ReadableStream<Uint8Array>>(\n mergeConfig(config || {}, { method: 'get', url, responseType: 'stream' }),\n );\n if (!response.data) return;\n\n const reader = response.data.getReader();\n try {\n const decoder = new TextDecoder();\n let buffer = '';\n\n const processLine = function* (line: string) {\n const trimmed = line.trim();\n if (trimmed.startsWith('data:')) {\n const dataStr = line.replace(/^data:\\s*/, '');\n if (dataStr === '[DONE]') return;\n try {\n yield JSON.parse(dataStr);\n } catch (e) {\n yield dataStr as any;\n }\n } else if (trimmed.startsWith('{') || trimmed.startsWith('[')) {\n try {\n yield JSON.parse(line);\n } catch (e) {\n // ignore partial json\n }\n }\n };\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n yield* processLine(line);\n }\n }\n\n buffer += decoder.decode(new Uint8Array(), { stream: false });\n if (buffer.trim()) {\n yield* processLine(buffer);\n }\n } finally {\n try {\n await reader.cancel();\n } catch {\n // ignore errors on cancel\n }\n reader.releaseLock();\n }\n }\n\n async *autoPaginate<T = any>(\n url: string,\n config?: AccessioRequestConfig,\n ): AsyncGenerator<T, void, unknown> {\n let nextUrl: string | null = url;\n let currentConfig = config || {};\n\n while (nextUrl) {\n const response: AccessioResponse<any> = await this.get(nextUrl, currentConfig);\n\n const data = response.data;\n const items = Array.isArray(data)\n ? data\n : data && typeof data === 'object'\n ? (data as any).data\n : null;\n\n if (Array.isArray(items)) {\n for (const item of items) {\n yield item;\n }\n }\n\n nextUrl =\n data && typeof data === 'object'\n ? (data as any).next || (data as any).links?.next || null\n : null;\n\n if (nextUrl) {\n currentConfig = mergeConfig(currentConfig, { url: nextUrl, params: {} });\n }\n }\n }\n\n gql<T = any>(\n url: string,\n query: string,\n variables?: Record<string, any>,\n config?: AccessioRequestConfig,\n ): Promise<AccessioResponse<T>> {\n return this.post<T>(url, { query, variables }, config);\n }\n}\n\nexport default Accessio;\n"],"mappings":"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","names":["buildURL","dispatchRequest","retryRequest","mergeConfig","defaultsConfig","InterceptorManager","AccessioError"]}
|
package/cjs/core/buildURL.cjs
CHANGED
|
@@ -62,15 +62,11 @@ function serializeParams(params, paramsSerializer) {
|
|
|
62
62
|
function combineURLs(baseURL, relativeURL) {
|
|
63
63
|
if (!baseURL) return relativeURL || "";
|
|
64
64
|
if (!relativeURL) return baseURL;
|
|
65
|
-
let
|
|
66
|
-
while (
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
while (relative.startsWith("/")) {
|
|
71
|
-
relative = relative.slice(1);
|
|
72
|
-
}
|
|
73
|
-
return `${base}/${relative}`;
|
|
65
|
+
let baseEnd = baseURL.length;
|
|
66
|
+
while (baseEnd > 0 && baseURL[baseEnd - 1] === "/") baseEnd--;
|
|
67
|
+
let relStart = 0;
|
|
68
|
+
while (relStart < relativeURL.length && relativeURL[relStart] === "/") relStart++;
|
|
69
|
+
return baseURL.slice(0, baseEnd) + "/" + relativeURL.slice(relStart);
|
|
74
70
|
}
|
|
75
71
|
function isAbsoluteURL(url) {
|
|
76
72
|
return /^([a-z][a-z\d+\-.]*:)/i.test(url);
|
|
@@ -79,24 +75,26 @@ function buildURL(url, baseURL, params, paramsSerializer) {
|
|
|
79
75
|
let fullURL = baseURL && !isAbsoluteURL(url) ? combineURLs(baseURL, url) : url || "";
|
|
80
76
|
let finalParams = params;
|
|
81
77
|
if (params && typeof params === "object" && !(params instanceof URLSearchParams)) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
fullURL = fullURL.replace(
|
|
88
|
-
/(?::([a-zA-Z_][a-zA-Z0-9_]*))|(?:{([a-zA-Z_][a-zA-Z0-9_]*)})/g,
|
|
89
|
-
(match, p1, p2) => {
|
|
90
|
-
const key = p1 || p2;
|
|
91
|
-
if (key && Object.prototype.hasOwnProperty.call(unusedParams, key) && unusedParams[key] !== void 0) {
|
|
92
|
-
const val = unusedParams[key];
|
|
93
|
-
delete unusedParams[key];
|
|
94
|
-
return encodeURIComponent(String(val));
|
|
95
|
-
}
|
|
96
|
-
return match;
|
|
78
|
+
if (fullURL.includes("{") || /:[a-zA-Z_]/.test(fullURL)) {
|
|
79
|
+
const unusedParams = {};
|
|
80
|
+
for (const key of Object.keys(params)) {
|
|
81
|
+
if (key === "__proto__" || key === "prototype" || key === "constructor") continue;
|
|
82
|
+
unusedParams[key] = params[key];
|
|
97
83
|
}
|
|
98
|
-
|
|
99
|
-
|
|
84
|
+
fullURL = fullURL.replace(
|
|
85
|
+
/(?::([a-zA-Z_][a-zA-Z0-9_]*))|(?:{([a-zA-Z_][a-zA-Z0-9_]*)})/g,
|
|
86
|
+
(match, p1, p2) => {
|
|
87
|
+
const key = p1 || p2;
|
|
88
|
+
if (key && Object.prototype.hasOwnProperty.call(unusedParams, key) && unusedParams[key] !== void 0) {
|
|
89
|
+
const val = unusedParams[key];
|
|
90
|
+
delete unusedParams[key];
|
|
91
|
+
return encodeURIComponent(String(val));
|
|
92
|
+
}
|
|
93
|
+
return match;
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
finalParams = unusedParams;
|
|
97
|
+
}
|
|
100
98
|
}
|
|
101
99
|
const serialized = serializeParams(finalParams, paramsSerializer);
|
|
102
100
|
if (serialized) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/buildURL.ts"],"sourcesContent":["import type { ParamsSerializer } from '../types';\n\nfunction serializeParams(\n params: Record<string, unknown>,\n paramsSerializer?: ParamsSerializer,\n): string {\n if (!params) return '';\n\n if (typeof paramsSerializer === 'function') {\n return paramsSerializer(params);\n }\n\n if (typeof URLSearchParams !== 'undefined' && params instanceof URLSearchParams) {\n return params.toString();\n }\n\n const parts: string[] = [];\n\n function encode(prefix: string, value: unknown): void {\n if (value === null || value === undefined) {\n return;\n }\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n if (typeof item === 'object' && item !== null) {\n encode(`${prefix}[${index}]`, item);\n } else {\n encode(prefix, item);\n }\n });\n } else if (typeof value === 'object' && !(value instanceof Date)) {\n Object.keys(value as Record<string, unknown>).forEach((key) => {\n encode(`${prefix}[${key}]`, (value as Record<string, unknown>)[key]);\n });\n } else {\n const encodedValue = value instanceof Date ? value.toISOString() : value;\n parts.push(`${encodeURIComponent(prefix)}=${encodeURIComponent(encodedValue as string)}`);\n }\n }\n\n Object.keys(params).forEach((key) => {\n encode(key, params[key]);\n });\n\n return parts.join('&');\n}\n\nfunction combineURLs(baseURL: string, relativeURL: string): string {\n if (!baseURL) return relativeURL || '';\n if (!relativeURL) return baseURL;\n\n let
|
|
1
|
+
{"version":3,"sources":["../../src/core/buildURL.ts"],"sourcesContent":["import type { ParamsSerializer } from '../types';\n\nfunction serializeParams(\n params: Record<string, unknown>,\n paramsSerializer?: ParamsSerializer,\n): string {\n if (!params) return '';\n\n if (typeof paramsSerializer === 'function') {\n return paramsSerializer(params);\n }\n\n if (typeof URLSearchParams !== 'undefined' && params instanceof URLSearchParams) {\n return params.toString();\n }\n\n const parts: string[] = [];\n\n function encode(prefix: string, value: unknown): void {\n if (value === null || value === undefined) {\n return;\n }\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n if (typeof item === 'object' && item !== null) {\n encode(`${prefix}[${index}]`, item);\n } else {\n encode(prefix, item);\n }\n });\n } else if (typeof value === 'object' && !(value instanceof Date)) {\n Object.keys(value as Record<string, unknown>).forEach((key) => {\n encode(`${prefix}[${key}]`, (value as Record<string, unknown>)[key]);\n });\n } else {\n const encodedValue = value instanceof Date ? value.toISOString() : value;\n parts.push(`${encodeURIComponent(prefix)}=${encodeURIComponent(encodedValue as string)}`);\n }\n }\n\n Object.keys(params).forEach((key) => {\n encode(key, params[key]);\n });\n\n return parts.join('&');\n}\n\nfunction combineURLs(baseURL: string, relativeURL: string): string {\n if (!baseURL) return relativeURL || '';\n if (!relativeURL) return baseURL;\n\n let baseEnd = baseURL.length;\n while (baseEnd > 0 && baseURL[baseEnd - 1] === '/') baseEnd--;\n\n let relStart = 0;\n while (relStart < relativeURL.length && relativeURL[relStart] === '/') relStart++;\n\n return baseURL.slice(0, baseEnd) + '/' + relativeURL.slice(relStart);\n}\n\nfunction isAbsoluteURL(url: string): boolean {\n return /^([a-z][a-z\\d+\\-.]*:)/i.test(url);\n}\n\nexport default function buildURL(\n url: string,\n baseURL?: string,\n params?: Record<string, unknown>,\n paramsSerializer?: ParamsSerializer,\n): string {\n let fullURL = baseURL && !isAbsoluteURL(url) ? combineURLs(baseURL, url) : url || '';\n\n let finalParams = params;\n if (params && typeof params === 'object' && !(params instanceof URLSearchParams)) {\n if (fullURL.includes('{') || /:[a-zA-Z_]/.test(fullURL)) {\n const unusedParams: Record<string, unknown> = {};\n for (const key of Object.keys(params)) {\n if (key === '__proto__' || key === 'prototype' || key === 'constructor') continue;\n unusedParams[key] = (params as Record<string, unknown>)[key];\n }\n fullURL = fullURL.replace(\n /(?::([a-zA-Z_][a-zA-Z0-9_]*))|(?:{([a-zA-Z_][a-zA-Z0-9_]*)})/g,\n (match, p1, p2) => {\n const key = p1 || p2;\n if (\n key &&\n Object.prototype.hasOwnProperty.call(unusedParams, key) &&\n unusedParams[key] !== undefined\n ) {\n const val = unusedParams[key];\n delete unusedParams[key];\n return encodeURIComponent(String(val));\n }\n return match;\n },\n );\n finalParams = unusedParams;\n }\n }\n\n const serialized = serializeParams(finalParams as Record<string, unknown>, paramsSerializer);\n if (serialized) {\n const hashIndex = fullURL.indexOf('#');\n let fragment = '';\n if (hashIndex !== -1) {\n fragment = fullURL.slice(hashIndex);\n fullURL = fullURL.slice(0, hashIndex);\n }\n fullURL += (fullURL.indexOf('?') === -1 ? '?' : '&') + serialized + fragment;\n }\n\n return fullURL;\n}\n\nexport { serializeParams, combineURLs, isAbsoluteURL };\n"],"mappings":"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","names":[]}
|
package/cjs/core/mergeConfig.cjs
CHANGED
|
@@ -48,18 +48,23 @@ const requestOnlyKeys = /* @__PURE__ */ new Set(["url", "data", "signal"]);
|
|
|
48
48
|
const deepMergeKeys = /* @__PURE__ */ new Set(["headers", "params", "hooks"]);
|
|
49
49
|
function mergeConfig(config1 = {}, config2 = {}) {
|
|
50
50
|
const merged = /* @__PURE__ */ Object.create(null);
|
|
51
|
-
const
|
|
52
|
-
for (
|
|
53
|
-
const
|
|
51
|
+
const keys1 = Object.keys(config1);
|
|
52
|
+
for (let i = 0; i < keys1.length; i++) {
|
|
53
|
+
const key = keys1[i];
|
|
54
|
+
if (requestOnlyKeys.has(key)) continue;
|
|
55
|
+
merged[key] = config1[key];
|
|
56
|
+
}
|
|
57
|
+
const keys2 = Object.keys(config2);
|
|
58
|
+
for (let i = 0; i < keys2.length; i++) {
|
|
59
|
+
const key = keys2[i];
|
|
54
60
|
const val2 = config2[key];
|
|
55
|
-
if (
|
|
56
|
-
if (
|
|
61
|
+
if (val2 !== void 0) {
|
|
62
|
+
if (deepMergeKeys.has(key)) {
|
|
63
|
+
const val1 = config1[key];
|
|
64
|
+
merged[key] = deepMerge(val1 || {}, val2);
|
|
65
|
+
} else {
|
|
57
66
|
merged[key] = val2;
|
|
58
67
|
}
|
|
59
|
-
} else if (deepMergeKeys.has(key)) {
|
|
60
|
-
merged[key] = deepMerge(val1 || {}, val2 || {});
|
|
61
|
-
} else {
|
|
62
|
-
merged[key] = val2 !== void 0 ? val2 : val1;
|
|
63
68
|
}
|
|
64
69
|
}
|
|
65
70
|
return merged;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/mergeConfig.ts"],"sourcesContent":["import type { AccessioRequestConfig } from '../types';\n\nfunction deepMerge(...sources: any[]): Record<string, any> {\n const result: Record<string, any> = Object.create(null);\n\n for (const source of sources) {\n if (!source || typeof source !== 'object') continue;\n\n for (const key of Object.keys(source)) {\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;\n\n const value = source[key];\n\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n if (\n value instanceof Date ||\n value instanceof RegExp ||\n value instanceof Map ||\n value instanceof Set ||\n value instanceof Error ||\n (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) ||\n (typeof Blob !== 'undefined' && value instanceof Blob)\n ) {\n result[key] = value;\n } else if (result[key] && typeof result[key] === 'object' && !Array.isArray(result[key])) {\n result[key] = deepMerge(result[key], value);\n } else {\n result[key] = deepMerge(value);\n }\n } else if (value !== undefined) {\n result[key] = value;\n }\n }\n }\n\n return result;\n}\n\nconst requestOnlyKeys = new Set<string>(['url', 'data', 'signal']);\nconst deepMergeKeys = new Set<string>(['headers', 'params', 'hooks']);\n\nexport default function mergeConfig(\n config1: AccessioRequestConfig = {},\n config2: AccessioRequestConfig = {},\n): AccessioRequestConfig {\n const merged: any = Object.create(null);\n\n const
|
|
1
|
+
{"version":3,"sources":["../../src/core/mergeConfig.ts"],"sourcesContent":["import type { AccessioRequestConfig } from '../types';\n\nfunction deepMerge(...sources: any[]): Record<string, any> {\n const result: Record<string, any> = Object.create(null);\n\n for (const source of sources) {\n if (!source || typeof source !== 'object') continue;\n\n for (const key of Object.keys(source)) {\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;\n\n const value = source[key];\n\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n if (\n value instanceof Date ||\n value instanceof RegExp ||\n value instanceof Map ||\n value instanceof Set ||\n value instanceof Error ||\n (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) ||\n (typeof Blob !== 'undefined' && value instanceof Blob)\n ) {\n result[key] = value;\n } else if (result[key] && typeof result[key] === 'object' && !Array.isArray(result[key])) {\n result[key] = deepMerge(result[key], value);\n } else {\n result[key] = deepMerge(value);\n }\n } else if (value !== undefined) {\n result[key] = value;\n }\n }\n }\n\n return result;\n}\n\nconst requestOnlyKeys = new Set<string>(['url', 'data', 'signal']);\nconst deepMergeKeys = new Set<string>(['headers', 'params', 'hooks']);\n\nexport default function mergeConfig(\n config1: AccessioRequestConfig = {},\n config2: AccessioRequestConfig = {},\n): AccessioRequestConfig {\n const merged: any = Object.create(null);\n\n const keys1 = Object.keys(config1);\n for (let i = 0; i < keys1.length; i++) {\n const key = keys1[i];\n if (requestOnlyKeys.has(key)) continue;\n merged[key] = config1[key as keyof AccessioRequestConfig];\n }\n\n const keys2 = Object.keys(config2);\n for (let i = 0; i < keys2.length; i++) {\n const key = keys2[i];\n const val2 = config2[key as keyof AccessioRequestConfig];\n if (val2 !== undefined) {\n if (deepMergeKeys.has(key)) {\n const val1 = config1[key as keyof AccessioRequestConfig];\n merged[key] = deepMerge(val1 || {}, val2);\n } else {\n merged[key] = val2;\n }\n }\n }\n\n return merged;\n}\n\nexport { deepMerge };\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,SAAS,aAAa,SAAqC;AACzD,QAAM,SAA8B,uBAAO,OAAO,IAAI;AAEtD,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,UAAU,OAAO,WAAW,SAAU;AAE3C,eAAW,OAAO,OAAO,KAAK,MAAM,GAAG;AACrC,UAAI,QAAQ,eAAe,QAAQ,iBAAiB,QAAQ,YAAa;AAEzE,YAAM,QAAQ,OAAO,GAAG;AAExB,UAAI,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GAAG;AAC/D,YACE,iBAAiB,QACjB,iBAAiB,UACjB,iBAAiB,OACjB,iBAAiB,OACjB,iBAAiB,SAChB,OAAO,gBAAgB,eAAe,iBAAiB,eACvD,OAAO,SAAS,eAAe,iBAAiB,MACjD;AACA,iBAAO,GAAG,IAAI;AAAA,QAChB,WAAW,OAAO,GAAG,KAAK,OAAO,OAAO,GAAG,MAAM,YAAY,CAAC,MAAM,QAAQ,OAAO,GAAG,CAAC,GAAG;AACxF,iBAAO,GAAG,IAAI,UAAU,OAAO,GAAG,GAAG,KAAK;AAAA,QAC5C,OAAO;AACL,iBAAO,GAAG,IAAI,UAAU,KAAK;AAAA,QAC/B;AAAA,MACF,WAAW,UAAU,QAAW;AAC9B,eAAO,GAAG,IAAI;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,MAAM,kBAAkB,oBAAI,IAAY,CAAC,OAAO,QAAQ,QAAQ,CAAC;AACjE,MAAM,gBAAgB,oBAAI,IAAY,CAAC,WAAW,UAAU,OAAO,CAAC;AAErD,SAAR,YACL,UAAiC,CAAC,GAClC,UAAiC,CAAC,GACX;AACvB,QAAM,SAAc,uBAAO,OAAO,IAAI;AAEtC,QAAM,QAAQ,OAAO,KAAK,OAAO;AACjC,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,MAAM,MAAM,CAAC;AACnB,QAAI,gBAAgB,IAAI,GAAG,EAAG;AAC9B,WAAO,GAAG,IAAI,QAAQ,GAAkC;AAAA,EAC1D;AAEA,QAAM,QAAQ,OAAO,KAAK,OAAO;AACjC,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,MAAM,MAAM,CAAC;AACnB,UAAM,OAAO,QAAQ,GAAkC;AACvD,QAAI,SAAS,QAAW;AACtB,UAAI,cAAc,IAAI,GAAG,GAAG;AAC1B,cAAM,OAAO,QAAQ,GAAkC;AACvD,eAAO,GAAG,IAAI,UAAU,QAAQ,CAAC,GAAG,IAAI;AAAA,MAC1C,OAAO;AACL,eAAO,GAAG,IAAI;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;","names":[]}
|
package/cjs/core/request.cjs
CHANGED
|
@@ -108,7 +108,7 @@ async function dispatchRequest(config) {
|
|
|
108
108
|
const flatHeaders = (0, import_flattenHeaders.flattenHeaders)(config.headers, config.method);
|
|
109
109
|
(0, import_auth.setBasicAuth)(config, flatHeaders);
|
|
110
110
|
const isGet = (config.method || "GET").toUpperCase() === "GET";
|
|
111
|
-
const cacheKey = isGet ? buildCacheKey(config, fullURL, flatHeaders) : "";
|
|
111
|
+
const cacheKey = isGet && (config.cache || config.dedupe) ? buildCacheKey(config, fullURL, flatHeaders) : "";
|
|
112
112
|
if (isGet && config.cache) {
|
|
113
113
|
const cacheProvider = typeof config.cache === "object" ? config.cache : import_memoryCache.defaultMemoryCache;
|
|
114
114
|
const cached = await cacheProvider.get(cacheKey);
|
package/cjs/core/request.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/request.ts"],"sourcesContent":["import buildURL from './buildURL';\nimport AccessioError, { redactConfig } from './accessioError';\nimport { ERR_BAD_OPTION } from '../constants/errorCodes';\nimport transformData from '../helpers/transformData';\nimport settle from '../helpers/settle';\nimport { flattenHeaders, removeContentType, buildFetchHeaders } from '../helpers/flattenHeaders';\nimport { setBasicAuth } from '../helpers/auth';\nimport fetchAdapter from './fetchAdapter';\nimport { defaultMemoryCache } from '../helpers/memoryCache';\nimport type { AccessioRequestConfig, AccessioResponse, TransformFunction } from '../types';\n\ntype HeadersConfig = Record<string, Record<string, string | string[]>>;\ntype FlatHeaders = Record<string, string | string[]>;\n\nfunction buildCacheKey(\n config: AccessioRequestConfig,\n fullURL: string,\n flatHeaders: FlatHeaders,\n): string {\n if (typeof config.cacheKeySerializer === 'function') {\n return config.cacheKeySerializer(config, fullURL, flatHeaders);\n }\n const method = (config.method || 'GET').toUpperCase();\n const withCreds = config.withCredentials ? '1' : '0';\n const respType = config.responseType || 'json';\n\n // Sort and serialize headers dynamically to prevent collisions,\n // excluding environment-specific transient headers.\n const serializedHeaders = Object.keys(flatHeaders)\n .sort()\n .filter(\n (k) =>\n !['user-agent', 'connection', 'host', 'content-length', 'accept-encoding'].includes(\n k.toLowerCase(),\n ),\n )\n .map((k) => {\n const val = flatHeaders[k];\n return `${k.toLowerCase()}=${Array.isArray(val) ? val.join(',') : val}`;\n })\n .join('&');\n\n return `${method}:${fullURL}|h:${serializedHeaders}|c=${withCreds}|t=${respType}`;\n}\n\nfunction buildTransformArray(\n transform: TransformFunction | TransformFunction[] | undefined,\n): TransformFunction[] {\n if (!transform) return [];\n if (Array.isArray(transform)) return transform;\n return [transform];\n}\n\nconst DEFAULT_ALLOWED_PROTOCOLS = ['http:', 'https:'];\n\nfunction assertAllowedProtocol(fullURL: string, config: AccessioRequestConfig): void {\n if (config.allowedProtocols === null) return;\n const allowed = config.allowedProtocols ?? DEFAULT_ALLOWED_PROTOCOLS;\n\n let scheme: string | null = null;\n const match = /^([a-z][a-z\\d+\\-.]*):/i.exec(fullURL);\n if (match) scheme = `${match[1].toLowerCase()}:`;\n if (!scheme) return;\n\n if (!allowed.includes(scheme)) {\n throw new AccessioError(\n `URL protocol \"${scheme}\" is not allowed. Allowed: ${allowed.join(', ')}. ` +\n 'Set config.allowedProtocols to extend, or null to disable the check.',\n ERR_BAD_OPTION,\n config,\n null,\n null,\n );\n }\n}\n\nconst activeRequests = new Map<string, Promise<AccessioResponse>>();\nconst MAX_ACTIVE_REQUESTS = 1024;\n\nexport function __activeRequestsSize(): number {\n return activeRequests.size;\n}\n\nfunction trackActiveRequest(key: string, promise: Promise<AccessioResponse>): void {\n activeRequests.set(key, promise);\n // Evict the oldest entry if we've grown past the cap. Map preserves insertion order.\n while (activeRequests.size > MAX_ACTIVE_REQUESTS) {\n const oldest = activeRequests.keys().next().value;\n if (oldest === undefined || oldest === key) break;\n activeRequests.delete(oldest);\n }\n}\n\nexport default async function dispatchRequest(\n config: AccessioRequestConfig,\n): Promise<AccessioResponse> {\n const fullURL =\n config._builtUrl ||\n buildURL(\n config.url ?? '',\n config.baseURL,\n config.params as Record<string, unknown> | undefined,\n config.paramsSerializer,\n );\n\n assertAllowedProtocol(fullURL, config);\n\n if (config.hooks?.onBeforeRequest) {\n await config.hooks.onBeforeRequest(config);\n }\n\n const flatHeaders = flattenHeaders(config.headers as HeadersConfig | undefined, config.method);\n setBasicAuth(config, flatHeaders);\n\n const isGet = (config.method || 'GET').toUpperCase() === 'GET';\n const cacheKey = isGet ? buildCacheKey(config, fullURL, flatHeaders) : '';\n\n if (isGet && config.cache) {\n const cacheProvider = typeof config.cache === 'object' ? config.cache : defaultMemoryCache;\n const cached = await cacheProvider.get(cacheKey);\n if (cached) {\n const cachedView: AccessioResponse = {\n ...cached,\n config: redactConfig(config) as typeof cached.config,\n };\n if (config.hooks?.onRequestResponse) {\n await config.hooks.onRequestResponse(cachedView);\n }\n return cachedView;\n }\n }\n\n if (isGet && config.dedupe) {\n const inflight = activeRequests.get(cacheKey);\n if (inflight) {\n try {\n const shared = await inflight;\n const response = finalizeResponse(shared, config);\n const settled = await new Promise<AccessioResponse>((resolve, reject) => {\n settle(\n resolve as (value: AccessioResponse) => void,\n reject as (reason: AccessioError) => void,\n response,\n config,\n );\n });\n\n if (config.hooks?.onRequestResponse) {\n await config.hooks.onRequestResponse(settled);\n }\n\n return settled;\n } catch (error) {\n let finalError = error;\n if (error instanceof AccessioError) {\n finalError = AccessioError.from(\n error,\n error.code || 'ERR_DEDUPE',\n config,\n error.request,\n error.response,\n );\n }\n if (config.hooks?.onRequestError && finalError instanceof AccessioError) {\n await config.hooks.onRequestError(finalError);\n }\n throw finalError;\n }\n }\n }\n\n const performRequest = async (): Promise<AccessioResponse> => {\n const requestTransforms = buildTransformArray(config.transformRequest);\n const requestData = await transformData(requestTransforms, config.data, flatHeaders, config);\n\n if (\n requestData === null ||\n requestData === undefined ||\n (typeof FormData !== 'undefined' && requestData instanceof FormData)\n ) {\n removeContentType(flatHeaders);\n }\n\n const fetchOptions: RequestInit = {\n method: (config.method || 'GET').toUpperCase(),\n headers: buildFetchHeaders(flatHeaders),\n };\n\n const methodsWithBody = ['POST', 'PUT', 'PATCH', 'DELETE'];\n if (\n methodsWithBody.includes(fetchOptions.method!) &&\n requestData !== undefined &&\n requestData !== null\n ) {\n fetchOptions.body = requestData as BodyInit;\n }\n\n if (config.withCredentials) {\n fetchOptions.credentials = 'include';\n }\n\n if (config.dispatcher) {\n (fetchOptions as any).dispatcher = config.dispatcher;\n }\n if (config.agent) {\n (fetchOptions as any).agent = config.agent;\n }\n\n const requestStartTime = Date.now();\n const response = await fetchAdapter(config, fullURL, fetchOptions, requestStartTime);\n\n const responseTransforms = buildTransformArray(config.transformResponse);\n response.data = await transformData(\n responseTransforms,\n response.data,\n response.headers,\n config,\n 'response',\n );\n\n return response;\n };\n\n const promise = performRequest();\n\n if (isGet && config.dedupe) {\n trackActiveRequest(cacheKey, promise);\n const cleanup = () => {\n if (activeRequests.get(cacheKey) === promise) {\n activeRequests.delete(cacheKey);\n }\n };\n promise.then(cleanup, cleanup);\n }\n\n try {\n const shared = await promise;\n const response = finalizeResponse(shared, config);\n\n if (isGet && config.cache) {\n const cacheProvider = typeof config.cache === 'object' ? config.cache : defaultMemoryCache;\n await cacheProvider.set(cacheKey, shared, config.cacheTTL);\n }\n\n const settled = await new Promise<AccessioResponse>((resolve, reject) => {\n settle(\n resolve as (value: AccessioResponse) => void,\n reject as (reason: AccessioError) => void,\n response,\n config,\n );\n });\n\n if (config.hooks?.onRequestResponse) {\n await config.hooks.onRequestResponse(settled);\n }\n\n return settled;\n } catch (error) {\n if (config.hooks?.onRequestError && error instanceof AccessioError) {\n await config.hooks.onRequestError(error);\n }\n throw error;\n }\n}\n\nfunction finalizeResponse(\n shared: AccessioResponse,\n config: AccessioRequestConfig,\n): AccessioResponse {\n return {\n ...shared,\n config: redactConfig(config) as typeof shared.config,\n };\n}\n"],"mappings":"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","names":["AccessioError","buildURL","settle","transformData","fetchAdapter"]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/request.ts"],"sourcesContent":["import buildURL from './buildURL';\nimport AccessioError, { redactConfig } from './accessioError';\nimport { ERR_BAD_OPTION } from '../constants/errorCodes';\nimport transformData from '../helpers/transformData';\nimport settle from '../helpers/settle';\nimport { flattenHeaders, removeContentType, buildFetchHeaders } from '../helpers/flattenHeaders';\nimport { setBasicAuth } from '../helpers/auth';\nimport fetchAdapter from './fetchAdapter';\nimport { defaultMemoryCache } from '../helpers/memoryCache';\nimport type { AccessioRequestConfig, AccessioResponse, TransformFunction } from '../types';\n\ntype HeadersConfig = Record<string, Record<string, string | string[]>>;\ntype FlatHeaders = Record<string, string | string[]>;\n\nfunction buildCacheKey(\n config: AccessioRequestConfig,\n fullURL: string,\n flatHeaders: FlatHeaders,\n): string {\n if (typeof config.cacheKeySerializer === 'function') {\n return config.cacheKeySerializer(config, fullURL, flatHeaders);\n }\n const method = (config.method || 'GET').toUpperCase();\n const withCreds = config.withCredentials ? '1' : '0';\n const respType = config.responseType || 'json';\n\n // Sort and serialize headers dynamically to prevent collisions,\n // excluding environment-specific transient headers.\n const serializedHeaders = Object.keys(flatHeaders)\n .sort()\n .filter(\n (k) =>\n !['user-agent', 'connection', 'host', 'content-length', 'accept-encoding'].includes(\n k.toLowerCase(),\n ),\n )\n .map((k) => {\n const val = flatHeaders[k];\n return `${k.toLowerCase()}=${Array.isArray(val) ? val.join(',') : val}`;\n })\n .join('&');\n\n return `${method}:${fullURL}|h:${serializedHeaders}|c=${withCreds}|t=${respType}`;\n}\n\nfunction buildTransformArray(\n transform: TransformFunction | TransformFunction[] | undefined,\n): TransformFunction[] {\n if (!transform) return [];\n if (Array.isArray(transform)) return transform;\n return [transform];\n}\n\nconst DEFAULT_ALLOWED_PROTOCOLS = ['http:', 'https:'];\n\nfunction assertAllowedProtocol(fullURL: string, config: AccessioRequestConfig): void {\n if (config.allowedProtocols === null) return;\n const allowed = config.allowedProtocols ?? DEFAULT_ALLOWED_PROTOCOLS;\n\n let scheme: string | null = null;\n const match = /^([a-z][a-z\\d+\\-.]*):/i.exec(fullURL);\n if (match) scheme = `${match[1].toLowerCase()}:`;\n if (!scheme) return;\n\n if (!allowed.includes(scheme)) {\n throw new AccessioError(\n `URL protocol \"${scheme}\" is not allowed. Allowed: ${allowed.join(', ')}. ` +\n 'Set config.allowedProtocols to extend, or null to disable the check.',\n ERR_BAD_OPTION,\n config,\n null,\n null,\n );\n }\n}\n\nconst activeRequests = new Map<string, Promise<AccessioResponse>>();\nconst MAX_ACTIVE_REQUESTS = 1024;\n\nexport function __activeRequestsSize(): number {\n return activeRequests.size;\n}\n\nfunction trackActiveRequest(key: string, promise: Promise<AccessioResponse>): void {\n activeRequests.set(key, promise);\n // Evict the oldest entry if we've grown past the cap. Map preserves insertion order.\n while (activeRequests.size > MAX_ACTIVE_REQUESTS) {\n const oldest = activeRequests.keys().next().value;\n if (oldest === undefined || oldest === key) break;\n activeRequests.delete(oldest);\n }\n}\n\nexport default async function dispatchRequest(\n config: AccessioRequestConfig,\n): Promise<AccessioResponse> {\n const fullURL =\n config._builtUrl ||\n buildURL(\n config.url ?? '',\n config.baseURL,\n config.params as Record<string, unknown> | undefined,\n config.paramsSerializer,\n );\n\n assertAllowedProtocol(fullURL, config);\n\n if (config.hooks?.onBeforeRequest) {\n await config.hooks.onBeforeRequest(config);\n }\n\n const flatHeaders = flattenHeaders(config.headers as HeadersConfig | undefined, config.method);\n setBasicAuth(config, flatHeaders);\n\n const isGet = (config.method || 'GET').toUpperCase() === 'GET';\n const cacheKey = isGet && (config.cache || config.dedupe) ? buildCacheKey(config, fullURL, flatHeaders) : '';\n\n if (isGet && config.cache) {\n const cacheProvider = typeof config.cache === 'object' ? config.cache : defaultMemoryCache;\n const cached = await cacheProvider.get(cacheKey);\n if (cached) {\n const cachedView: AccessioResponse = {\n ...cached,\n config: redactConfig(config) as typeof cached.config,\n };\n if (config.hooks?.onRequestResponse) {\n await config.hooks.onRequestResponse(cachedView);\n }\n return cachedView;\n }\n }\n\n if (isGet && config.dedupe) {\n const inflight = activeRequests.get(cacheKey);\n if (inflight) {\n try {\n const shared = await inflight;\n const response = finalizeResponse(shared, config);\n const settled = await new Promise<AccessioResponse>((resolve, reject) => {\n settle(\n resolve as (value: AccessioResponse) => void,\n reject as (reason: AccessioError) => void,\n response,\n config,\n );\n });\n\n if (config.hooks?.onRequestResponse) {\n await config.hooks.onRequestResponse(settled);\n }\n\n return settled;\n } catch (error) {\n let finalError = error;\n if (error instanceof AccessioError) {\n finalError = AccessioError.from(\n error,\n error.code || 'ERR_DEDUPE',\n config,\n error.request,\n error.response,\n );\n }\n if (config.hooks?.onRequestError && finalError instanceof AccessioError) {\n await config.hooks.onRequestError(finalError);\n }\n throw finalError;\n }\n }\n }\n\n const performRequest = async (): Promise<AccessioResponse> => {\n const requestTransforms = buildTransformArray(config.transformRequest);\n const requestData = await transformData(requestTransforms, config.data, flatHeaders, config);\n\n if (\n requestData === null ||\n requestData === undefined ||\n (typeof FormData !== 'undefined' && requestData instanceof FormData)\n ) {\n removeContentType(flatHeaders);\n }\n\n const fetchOptions: RequestInit = {\n method: (config.method || 'GET').toUpperCase(),\n headers: buildFetchHeaders(flatHeaders),\n };\n\n const methodsWithBody = ['POST', 'PUT', 'PATCH', 'DELETE'];\n if (\n methodsWithBody.includes(fetchOptions.method!) &&\n requestData !== undefined &&\n requestData !== null\n ) {\n fetchOptions.body = requestData as BodyInit;\n }\n\n if (config.withCredentials) {\n fetchOptions.credentials = 'include';\n }\n\n if (config.dispatcher) {\n (fetchOptions as any).dispatcher = config.dispatcher;\n }\n if (config.agent) {\n (fetchOptions as any).agent = config.agent;\n }\n\n const requestStartTime = Date.now();\n const response = await fetchAdapter(config, fullURL, fetchOptions, requestStartTime);\n\n const responseTransforms = buildTransformArray(config.transformResponse);\n response.data = await transformData(\n responseTransforms,\n response.data,\n response.headers,\n config,\n 'response',\n );\n\n return response;\n };\n\n const promise = performRequest();\n\n if (isGet && config.dedupe) {\n trackActiveRequest(cacheKey, promise);\n const cleanup = () => {\n if (activeRequests.get(cacheKey) === promise) {\n activeRequests.delete(cacheKey);\n }\n };\n promise.then(cleanup, cleanup);\n }\n\n try {\n const shared = await promise;\n const response = finalizeResponse(shared, config);\n\n if (isGet && config.cache) {\n const cacheProvider = typeof config.cache === 'object' ? config.cache : defaultMemoryCache;\n await cacheProvider.set(cacheKey, shared, config.cacheTTL);\n }\n\n const settled = await new Promise<AccessioResponse>((resolve, reject) => {\n settle(\n resolve as (value: AccessioResponse) => void,\n reject as (reason: AccessioError) => void,\n response,\n config,\n );\n });\n\n if (config.hooks?.onRequestResponse) {\n await config.hooks.onRequestResponse(settled);\n }\n\n return settled;\n } catch (error) {\n if (config.hooks?.onRequestError && error instanceof AccessioError) {\n await config.hooks.onRequestError(error);\n }\n throw error;\n }\n}\n\nfunction finalizeResponse(\n shared: AccessioResponse,\n config: AccessioRequestConfig,\n): AccessioResponse {\n return {\n ...shared,\n config: redactConfig(config) as typeof shared.config,\n };\n}\n"],"mappings":"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","names":["AccessioError","buildURL","settle","transformData","fetchAdapter"]}
|
|
@@ -72,25 +72,30 @@ const METHOD_KEYS = /* @__PURE__ */ new Set([
|
|
|
72
72
|
function flattenHeaders(headers, method) {
|
|
73
73
|
if (!headers) return {};
|
|
74
74
|
const merged = {};
|
|
75
|
+
const lowerKeys = {};
|
|
75
76
|
const methodLower = (method || "get").toLowerCase();
|
|
76
77
|
const setHeader = (target, key, value) => {
|
|
77
78
|
const keyLower = key.toLowerCase();
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
79
|
+
const existingKey = lowerKeys[keyLower];
|
|
80
|
+
if (existingKey !== void 0) {
|
|
81
|
+
delete target[existingKey];
|
|
82
82
|
}
|
|
83
83
|
target[key] = value;
|
|
84
|
+
lowerKeys[keyLower] = key;
|
|
84
85
|
};
|
|
85
86
|
if (headers["common"]) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
for (const key in headers["common"]) {
|
|
88
|
+
if (Object.prototype.hasOwnProperty.call(headers["common"], key)) {
|
|
89
|
+
setHeader(merged, key, headers["common"][key]);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
89
92
|
}
|
|
90
93
|
if (headers[methodLower]) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
for (const key in headers[methodLower]) {
|
|
95
|
+
if (Object.prototype.hasOwnProperty.call(headers[methodLower], key)) {
|
|
96
|
+
setHeader(merged, key, headers[methodLower][key]);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
94
99
|
}
|
|
95
100
|
for (const key in headers) {
|
|
96
101
|
if (Object.prototype.hasOwnProperty.call(headers, key) && !METHOD_KEYS.has(key)) {
|
|
@@ -100,24 +105,31 @@ function flattenHeaders(headers, method) {
|
|
|
100
105
|
return merged;
|
|
101
106
|
}
|
|
102
107
|
function removeContentType(headers) {
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
for (const key in headers) {
|
|
109
|
+
if (Object.prototype.hasOwnProperty.call(headers, key)) {
|
|
110
|
+
if (key.toLowerCase() === "content-type") {
|
|
111
|
+
delete headers[key];
|
|
112
|
+
}
|
|
113
|
+
}
|
|
106
114
|
}
|
|
107
115
|
}
|
|
108
116
|
function buildFetchHeaders(headers) {
|
|
109
117
|
const fetchHeaders = new Headers();
|
|
110
|
-
for (const
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
118
|
+
for (const key in headers) {
|
|
119
|
+
if (Object.prototype.hasOwnProperty.call(headers, key)) {
|
|
120
|
+
const value = headers[key];
|
|
121
|
+
if (value === void 0 || value === null) continue;
|
|
122
|
+
assertSafeHeader(key, value);
|
|
123
|
+
if (Array.isArray(value)) {
|
|
124
|
+
for (let i = 0; i < value.length; i++) {
|
|
125
|
+
const v = value[i];
|
|
126
|
+
if (v !== void 0 && v !== null) {
|
|
127
|
+
fetchHeaders.append(key, v);
|
|
128
|
+
}
|
|
117
129
|
}
|
|
130
|
+
} else {
|
|
131
|
+
fetchHeaders.set(key, value);
|
|
118
132
|
}
|
|
119
|
-
} else {
|
|
120
|
-
fetchHeaders.set(key, value);
|
|
121
133
|
}
|
|
122
134
|
}
|
|
123
135
|
return fetchHeaders;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/helpers/flattenHeaders.ts"],"sourcesContent":["import AccessioError from '../core/accessioError';\nimport { ERR_BAD_OPTION } from '../constants/errorCodes';\n\nconst HEADER_FORBIDDEN_CHAR = /[\\r\\n\\0]/;\n\nfunction assertSafeHeader(name: string, value: string | string[]): void {\n if (typeof name !== 'string' || HEADER_FORBIDDEN_CHAR.test(name)) {\n throw new AccessioError(\n `Invalid header name \"${String(name)}\": CR, LF and NUL are not allowed`,\n ERR_BAD_OPTION,\n null,\n null,\n null,\n );\n }\n const values = Array.isArray(value) ? value : [value];\n for (const v of values) {\n if (typeof v === 'string' && HEADER_FORBIDDEN_CHAR.test(v)) {\n throw new AccessioError(\n `Invalid value for header \"${name}\": CR, LF and NUL are not allowed`,\n ERR_BAD_OPTION,\n null,\n null,\n null,\n );\n }\n }\n}\n\nconst METHOD_KEYS = new Set<string>([\n 'common',\n 'delete',\n 'get',\n 'head',\n 'options',\n 'post',\n 'put',\n 'patch',\n]);\n\ntype HeadersConfig = Record<string, Record<string, string | string[]>>;\n\nexport function flattenHeaders(\n headers: HeadersConfig | undefined,\n method?: string,\n): Record<string, string | string[]> {\n if (!headers) return {};\n\n const merged: Record<string, string | string[]> = {};\n const methodLower = (method || 'get').toLowerCase();\n\n const setHeader = (target: Record<string, string | string[]>, key: string, value: any) => {\n const keyLower = key.toLowerCase();\n
|
|
1
|
+
{"version":3,"sources":["../../src/helpers/flattenHeaders.ts"],"sourcesContent":["import AccessioError from '../core/accessioError';\nimport { ERR_BAD_OPTION } from '../constants/errorCodes';\n\nconst HEADER_FORBIDDEN_CHAR = /[\\r\\n\\0]/;\n\nfunction assertSafeHeader(name: string, value: string | string[]): void {\n if (typeof name !== 'string' || HEADER_FORBIDDEN_CHAR.test(name)) {\n throw new AccessioError(\n `Invalid header name \"${String(name)}\": CR, LF and NUL are not allowed`,\n ERR_BAD_OPTION,\n null,\n null,\n null,\n );\n }\n const values = Array.isArray(value) ? value : [value];\n for (const v of values) {\n if (typeof v === 'string' && HEADER_FORBIDDEN_CHAR.test(v)) {\n throw new AccessioError(\n `Invalid value for header \"${name}\": CR, LF and NUL are not allowed`,\n ERR_BAD_OPTION,\n null,\n null,\n null,\n );\n }\n }\n}\n\nconst METHOD_KEYS = new Set<string>([\n 'common',\n 'delete',\n 'get',\n 'head',\n 'options',\n 'post',\n 'put',\n 'patch',\n]);\n\ntype HeadersConfig = Record<string, Record<string, string | string[]>>;\n\nexport function flattenHeaders(\n headers: HeadersConfig | undefined,\n method?: string,\n): Record<string, string | string[]> {\n if (!headers) return {};\n\n const merged: Record<string, string | string[]> = {};\n const lowerKeys: Record<string, string> = {};\n const methodLower = (method || 'get').toLowerCase();\n\n const setHeader = (target: Record<string, string | string[]>, key: string, value: any) => {\n const keyLower = key.toLowerCase();\n const existingKey = lowerKeys[keyLower];\n if (existingKey !== undefined) {\n delete target[existingKey];\n }\n target[key] = value;\n lowerKeys[keyLower] = key;\n };\n\n if (headers['common']) {\n for (const key in headers['common']) {\n if (Object.prototype.hasOwnProperty.call(headers['common'], key)) {\n setHeader(merged, key, headers['common'][key]);\n }\n }\n }\n\n if (headers[methodLower]) {\n for (const key in headers[methodLower]) {\n if (Object.prototype.hasOwnProperty.call(headers[methodLower], key)) {\n setHeader(merged, key, headers[methodLower][key]);\n }\n }\n }\n\n for (const key in headers) {\n if (Object.prototype.hasOwnProperty.call(headers, key) && !METHOD_KEYS.has(key)) {\n setHeader(merged, key, headers[key]);\n }\n }\n\n return merged;\n}\n\nexport function removeContentType(headers: Record<string, string | string[]>): void {\n for (const key in headers) {\n if (Object.prototype.hasOwnProperty.call(headers, key)) {\n if (key.toLowerCase() === 'content-type') {\n delete headers[key];\n }\n }\n }\n}\n\nexport function buildFetchHeaders(headers: Record<string, string | string[]>): Headers {\n const fetchHeaders = new Headers();\n for (const key in headers) {\n if (Object.prototype.hasOwnProperty.call(headers, key)) {\n const value = headers[key];\n if (value === undefined || value === null) continue;\n assertSafeHeader(key, value);\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n const v = value[i];\n if (v !== undefined && v !== null) {\n fetchHeaders.append(key, v);\n }\n }\n } else {\n fetchHeaders.set(key, value);\n }\n }\n }\n return fetchHeaders;\n}\n"],"mappings":"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","names":["AccessioError"]}
|
|
@@ -45,11 +45,16 @@ class MemoryCache {
|
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
let count = 0;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
const keys = this.cache.keys();
|
|
49
|
+
while (count < 5) {
|
|
50
|
+
const next = keys.next();
|
|
51
|
+
if (next.done) break;
|
|
52
|
+
const k = next.value;
|
|
53
|
+
const item = this.cache.get(k);
|
|
54
|
+
if (item && item.expiry && now > item.expiry) {
|
|
51
55
|
this.cache.delete(k);
|
|
52
56
|
}
|
|
57
|
+
count++;
|
|
53
58
|
}
|
|
54
59
|
if (this.cache.size >= this.maxItems) {
|
|
55
60
|
const oldest = this.cache.keys().next().value;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/helpers/memoryCache.ts"],"sourcesContent":["import type { CacheProvider } from '../types';\n\nclass MemoryCache implements CacheProvider {\n private cache = new Map<string, { value: any; expiry: number | null }>();\n private maxItems: number;\n\n constructor(maxItems: number = 1000) {\n this.maxItems = maxItems;\n }\n\n get(key: string) {\n const item = this.cache.get(key);\n if (!item) return null;\n if (item.expiry && Date.now() > item.expiry) {\n this.cache.delete(key);\n return null;\n }\n return item.value;\n }\n\n set(key: string, value: any, ttl?: number) {\n const now = Date.now();\n\n if (this.cache.has(key)) {\n const expiry = ttl ? now + ttl : null;\n this.cache.set(key, { value, expiry });\n return;\n }\n\n // Proactively evict up to 5 of the oldest items to prevent memory build-up without O(N) cost.\n // Map entries are ordered by insertion, so the oldest are checked first.\n let count = 0;\n
|
|
1
|
+
{"version":3,"sources":["../../src/helpers/memoryCache.ts"],"sourcesContent":["import type { CacheProvider } from '../types';\n\nclass MemoryCache implements CacheProvider {\n private cache = new Map<string, { value: any; expiry: number | null }>();\n private maxItems: number;\n\n constructor(maxItems: number = 1000) {\n this.maxItems = maxItems;\n }\n\n get(key: string) {\n const item = this.cache.get(key);\n if (!item) return null;\n if (item.expiry && Date.now() > item.expiry) {\n this.cache.delete(key);\n return null;\n }\n return item.value;\n }\n\n set(key: string, value: any, ttl?: number) {\n const now = Date.now();\n\n if (this.cache.has(key)) {\n const expiry = ttl ? now + ttl : null;\n this.cache.set(key, { value, expiry });\n return;\n }\n\n // Proactively evict up to 5 of the oldest items to prevent memory build-up without O(N) cost.\n // Map entries are ordered by insertion, so the oldest are checked first.\n let count = 0;\n const keys = this.cache.keys();\n while (count < 5) {\n const next = keys.next();\n if (next.done) break;\n const k = next.value;\n const item = this.cache.get(k);\n if (item && item.expiry && now > item.expiry) {\n this.cache.delete(k);\n }\n count++;\n }\n\n // Evict the oldest item if we are still at limit\n if (this.cache.size >= this.maxItems) {\n const oldest = this.cache.keys().next().value;\n if (oldest !== undefined) {\n this.cache.delete(oldest);\n }\n }\n\n const expiry = ttl ? now + ttl : null;\n this.cache.set(key, { value, expiry });\n }\n\n delete(key: string) {\n this.cache.delete(key);\n }\n\n clear() {\n this.cache.clear();\n }\n}\n\nexport const defaultMemoryCache = new MemoryCache();\nexport { MemoryCache };\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,MAAM,YAAqC;AAAA,EACjC,QAAQ,oBAAI,IAAmD;AAAA,EAC/D;AAAA,EAER,YAAY,WAAmB,KAAM;AACnC,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,IAAI,KAAa;AACf,UAAM,OAAO,KAAK,MAAM,IAAI,GAAG;AAC/B,QAAI,CAAC,KAAM,QAAO;AAClB,QAAI,KAAK,UAAU,KAAK,IAAI,IAAI,KAAK,QAAQ;AAC3C,WAAK,MAAM,OAAO,GAAG;AACrB,aAAO;AAAA,IACT;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,KAAa,OAAY,KAAc;AACzC,UAAM,MAAM,KAAK,IAAI;AAErB,QAAI,KAAK,MAAM,IAAI,GAAG,GAAG;AACvB,YAAMA,UAAS,MAAM,MAAM,MAAM;AACjC,WAAK,MAAM,IAAI,KAAK,EAAE,OAAO,QAAAA,QAAO,CAAC;AACrC;AAAA,IACF;AAIA,QAAI,QAAQ;AACZ,UAAM,OAAO,KAAK,MAAM,KAAK;AAC7B,WAAO,QAAQ,GAAG;AAChB,YAAM,OAAO,KAAK,KAAK;AACvB,UAAI,KAAK,KAAM;AACf,YAAM,IAAI,KAAK;AACf,YAAM,OAAO,KAAK,MAAM,IAAI,CAAC;AAC7B,UAAI,QAAQ,KAAK,UAAU,MAAM,KAAK,QAAQ;AAC5C,aAAK,MAAM,OAAO,CAAC;AAAA,MACrB;AACA;AAAA,IACF;AAGA,QAAI,KAAK,MAAM,QAAQ,KAAK,UAAU;AACpC,YAAM,SAAS,KAAK,MAAM,KAAK,EAAE,KAAK,EAAE;AACxC,UAAI,WAAW,QAAW;AACxB,aAAK,MAAM,OAAO,MAAM;AAAA,MAC1B;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,MAAM,MAAM;AACjC,SAAK,MAAM,IAAI,KAAK,EAAE,OAAO,OAAO,CAAC;AAAA,EACvC;AAAA,EAEA,OAAO,KAAa;AAClB,SAAK,MAAM,OAAO,GAAG;AAAA,EACvB;AAAA,EAEA,QAAQ;AACN,SAAK,MAAM,MAAM;AAAA,EACnB;AACF;AAEO,MAAM,qBAAqB,IAAI,YAAY;","names":["expiry"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "accessio",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "Fast, flexible HTTP client — simple, modular, and dependency-free",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./cjs/index.cjs",
|
|
@@ -106,5 +106,8 @@
|
|
|
106
106
|
"typescript": "^5.0.0",
|
|
107
107
|
"typescript-eslint": "^8.59.3",
|
|
108
108
|
"vitest": "^4.1.8"
|
|
109
|
+
},
|
|
110
|
+
"overrides": {
|
|
111
|
+
"esbuild": "^0.28.1"
|
|
109
112
|
}
|
|
110
113
|
}
|
package/src/accessio.ts
CHANGED
|
@@ -18,7 +18,7 @@ import defaultsConfig from './defaults/index';
|
|
|
18
18
|
function runRequestInterceptorsSync(
|
|
19
19
|
startConfig: AccessioRequestConfig,
|
|
20
20
|
interceptors: InterceptorHandler[],
|
|
21
|
-
):
|
|
21
|
+
): AccessioRequestConfig {
|
|
22
22
|
let cfg = startConfig;
|
|
23
23
|
let rejectReason: any = null;
|
|
24
24
|
let isRejected = false;
|
|
@@ -44,7 +44,10 @@ function runRequestInterceptorsSync(
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
if (isRejected) {
|
|
48
|
+
throw rejectReason;
|
|
49
|
+
}
|
|
50
|
+
return cfg;
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
function runRequestInterceptorsAsync(
|
|
@@ -65,7 +68,7 @@ function dispatchAndRetry(cfg: AccessioRequestConfig): Promise<AccessioResponse>
|
|
|
65
68
|
const fullUrl = buildURL(cfg.url ?? '', cfg.baseURL, cfg.params, cfg.paramsSerializer);
|
|
66
69
|
logRequest(cfg, fullUrl);
|
|
67
70
|
|
|
68
|
-
const enrichedCfg =
|
|
71
|
+
const enrichedCfg = { ...cfg, _builtUrl: fullUrl };
|
|
69
72
|
|
|
70
73
|
const dispatchFn = cfg.rateLimiter
|
|
71
74
|
? (config: AccessioRequestConfig) =>
|
|
@@ -114,11 +117,20 @@ export class Accessio {
|
|
|
114
117
|
const { requestInterceptors, responseInterceptors, synchronous } =
|
|
115
118
|
this.collectInterceptors(mergedConfig);
|
|
116
119
|
|
|
117
|
-
let promise: Promise<any
|
|
118
|
-
? runRequestInterceptorsSync(mergedConfig, requestInterceptors)
|
|
119
|
-
: runRequestInterceptorsAsync(mergedConfig, requestInterceptors);
|
|
120
|
+
let promise: Promise<any>;
|
|
120
121
|
|
|
121
|
-
|
|
122
|
+
if (synchronous) {
|
|
123
|
+
try {
|
|
124
|
+
const finalCfg = runRequestInterceptorsSync(mergedConfig, requestInterceptors);
|
|
125
|
+
promise = dispatchAndRetry(finalCfg);
|
|
126
|
+
} catch (err) {
|
|
127
|
+
promise = Promise.reject(err);
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
promise = runRequestInterceptorsAsync(mergedConfig, requestInterceptors).then(
|
|
131
|
+
(cfg: AccessioRequestConfig) => dispatchAndRetry(cfg),
|
|
132
|
+
);
|
|
133
|
+
}
|
|
122
134
|
|
|
123
135
|
promise = promise.then(
|
|
124
136
|
(value: AccessioResponse) => {
|
|
@@ -131,13 +143,65 @@ export class Accessio {
|
|
|
131
143
|
},
|
|
132
144
|
);
|
|
133
145
|
|
|
134
|
-
|
|
135
|
-
promise = promise.then(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
146
|
+
if (responseInterceptors.length > 0) {
|
|
147
|
+
promise = promise.then(
|
|
148
|
+
async (value: AccessioResponse) => {
|
|
149
|
+
let current: any = value;
|
|
150
|
+
let isRejected = false;
|
|
151
|
+
for (const interceptor of responseInterceptors) {
|
|
152
|
+
if (!isRejected) {
|
|
153
|
+
try {
|
|
154
|
+
if (interceptor.fulfilled) {
|
|
155
|
+
current = await (interceptor.fulfilled as any)(current);
|
|
156
|
+
}
|
|
157
|
+
} catch (err) {
|
|
158
|
+
current = err;
|
|
159
|
+
isRejected = true;
|
|
160
|
+
}
|
|
161
|
+
} else if (interceptor.rejected) {
|
|
162
|
+
try {
|
|
163
|
+
current = await interceptor.rejected(current);
|
|
164
|
+
isRejected = false;
|
|
165
|
+
} catch (err) {
|
|
166
|
+
current = err;
|
|
167
|
+
isRejected = true;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (isRejected) {
|
|
172
|
+
throw current;
|
|
173
|
+
}
|
|
174
|
+
return current;
|
|
175
|
+
},
|
|
176
|
+
async (error: any) => {
|
|
177
|
+
let current: any = error;
|
|
178
|
+
let isRejected = true;
|
|
179
|
+
for (const interceptor of responseInterceptors) {
|
|
180
|
+
if (!isRejected) {
|
|
181
|
+
try {
|
|
182
|
+
if (interceptor.fulfilled) {
|
|
183
|
+
current = await (interceptor.fulfilled as any)(current);
|
|
184
|
+
}
|
|
185
|
+
} catch (err) {
|
|
186
|
+
current = err;
|
|
187
|
+
isRejected = true;
|
|
188
|
+
}
|
|
189
|
+
} else if (interceptor.rejected) {
|
|
190
|
+
try {
|
|
191
|
+
current = await interceptor.rejected(current);
|
|
192
|
+
isRejected = false;
|
|
193
|
+
} catch (err) {
|
|
194
|
+
current = err;
|
|
195
|
+
isRejected = true;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (isRejected) {
|
|
200
|
+
throw current;
|
|
201
|
+
}
|
|
202
|
+
return current;
|
|
203
|
+
},
|
|
204
|
+
);
|
|
141
205
|
}
|
|
142
206
|
|
|
143
207
|
return promise;
|
package/src/core/buildURL.ts
CHANGED
|
@@ -50,17 +50,13 @@ function combineURLs(baseURL: string, relativeURL: string): string {
|
|
|
50
50
|
if (!baseURL) return relativeURL || '';
|
|
51
51
|
if (!relativeURL) return baseURL;
|
|
52
52
|
|
|
53
|
-
let
|
|
54
|
-
while (
|
|
55
|
-
base = base.slice(0, -1);
|
|
56
|
-
}
|
|
53
|
+
let baseEnd = baseURL.length;
|
|
54
|
+
while (baseEnd > 0 && baseURL[baseEnd - 1] === '/') baseEnd--;
|
|
57
55
|
|
|
58
|
-
let
|
|
59
|
-
while (
|
|
60
|
-
relative = relative.slice(1);
|
|
61
|
-
}
|
|
56
|
+
let relStart = 0;
|
|
57
|
+
while (relStart < relativeURL.length && relativeURL[relStart] === '/') relStart++;
|
|
62
58
|
|
|
63
|
-
return
|
|
59
|
+
return baseURL.slice(0, baseEnd) + '/' + relativeURL.slice(relStart);
|
|
64
60
|
}
|
|
65
61
|
|
|
66
62
|
function isAbsoluteURL(url: string): boolean {
|
|
@@ -77,28 +73,30 @@ export default function buildURL(
|
|
|
77
73
|
|
|
78
74
|
let finalParams = params;
|
|
79
75
|
if (params && typeof params === 'object' && !(params instanceof URLSearchParams)) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
76
|
+
if (fullURL.includes('{') || /:[a-zA-Z_]/.test(fullURL)) {
|
|
77
|
+
const unusedParams: Record<string, unknown> = {};
|
|
78
|
+
for (const key of Object.keys(params)) {
|
|
79
|
+
if (key === '__proto__' || key === 'prototype' || key === 'constructor') continue;
|
|
80
|
+
unusedParams[key] = (params as Record<string, unknown>)[key];
|
|
81
|
+
}
|
|
82
|
+
fullURL = fullURL.replace(
|
|
83
|
+
/(?::([a-zA-Z_][a-zA-Z0-9_]*))|(?:{([a-zA-Z_][a-zA-Z0-9_]*)})/g,
|
|
84
|
+
(match, p1, p2) => {
|
|
85
|
+
const key = p1 || p2;
|
|
86
|
+
if (
|
|
87
|
+
key &&
|
|
88
|
+
Object.prototype.hasOwnProperty.call(unusedParams, key) &&
|
|
89
|
+
unusedParams[key] !== undefined
|
|
90
|
+
) {
|
|
91
|
+
const val = unusedParams[key];
|
|
92
|
+
delete unusedParams[key];
|
|
93
|
+
return encodeURIComponent(String(val));
|
|
94
|
+
}
|
|
95
|
+
return match;
|
|
96
|
+
},
|
|
97
|
+
);
|
|
98
|
+
finalParams = unusedParams;
|
|
84
99
|
}
|
|
85
|
-
fullURL = fullURL.replace(
|
|
86
|
-
/(?::([a-zA-Z_][a-zA-Z0-9_]*))|(?:{([a-zA-Z_][a-zA-Z0-9_]*)})/g,
|
|
87
|
-
(match, p1, p2) => {
|
|
88
|
-
const key = p1 || p2;
|
|
89
|
-
if (
|
|
90
|
-
key &&
|
|
91
|
-
Object.prototype.hasOwnProperty.call(unusedParams, key) &&
|
|
92
|
-
unusedParams[key] !== undefined
|
|
93
|
-
) {
|
|
94
|
-
const val = unusedParams[key];
|
|
95
|
-
delete unusedParams[key];
|
|
96
|
-
return encodeURIComponent(String(val));
|
|
97
|
-
}
|
|
98
|
-
return match;
|
|
99
|
-
},
|
|
100
|
-
);
|
|
101
|
-
finalParams = unusedParams;
|
|
102
100
|
}
|
|
103
101
|
|
|
104
102
|
const serialized = serializeParams(finalParams as Record<string, unknown>, paramsSerializer);
|
package/src/core/mergeConfig.ts
CHANGED
|
@@ -45,20 +45,24 @@ export default function mergeConfig(
|
|
|
45
45
|
): AccessioRequestConfig {
|
|
46
46
|
const merged: any = Object.create(null);
|
|
47
47
|
|
|
48
|
-
const
|
|
48
|
+
const keys1 = Object.keys(config1);
|
|
49
|
+
for (let i = 0; i < keys1.length; i++) {
|
|
50
|
+
const key = keys1[i];
|
|
51
|
+
if (requestOnlyKeys.has(key)) continue;
|
|
52
|
+
merged[key] = config1[key as keyof AccessioRequestConfig];
|
|
53
|
+
}
|
|
49
54
|
|
|
50
|
-
|
|
51
|
-
|
|
55
|
+
const keys2 = Object.keys(config2);
|
|
56
|
+
for (let i = 0; i < keys2.length; i++) {
|
|
57
|
+
const key = keys2[i];
|
|
52
58
|
const val2 = config2[key as keyof AccessioRequestConfig];
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
if (val2 !== undefined) {
|
|
60
|
+
if (deepMergeKeys.has(key)) {
|
|
61
|
+
const val1 = config1[key as keyof AccessioRequestConfig];
|
|
62
|
+
merged[key] = deepMerge(val1 || {}, val2);
|
|
63
|
+
} else {
|
|
56
64
|
merged[key] = val2;
|
|
57
65
|
}
|
|
58
|
-
} else if (deepMergeKeys.has(key)) {
|
|
59
|
-
merged[key] = deepMerge(val1 || {}, val2 || {});
|
|
60
|
-
} else {
|
|
61
|
-
merged[key] = val2 !== undefined ? val2 : val1;
|
|
62
66
|
}
|
|
63
67
|
}
|
|
64
68
|
|
package/src/core/request.ts
CHANGED
|
@@ -113,7 +113,7 @@ export default async function dispatchRequest(
|
|
|
113
113
|
setBasicAuth(config, flatHeaders);
|
|
114
114
|
|
|
115
115
|
const isGet = (config.method || 'GET').toUpperCase() === 'GET';
|
|
116
|
-
const cacheKey = isGet ? buildCacheKey(config, fullURL, flatHeaders) : '';
|
|
116
|
+
const cacheKey = isGet && (config.cache || config.dedupe) ? buildCacheKey(config, fullURL, flatHeaders) : '';
|
|
117
117
|
|
|
118
118
|
if (isGet && config.cache) {
|
|
119
119
|
const cacheProvider = typeof config.cache === 'object' ? config.cache : defaultMemoryCache;
|
|
@@ -47,28 +47,33 @@ export function flattenHeaders(
|
|
|
47
47
|
if (!headers) return {};
|
|
48
48
|
|
|
49
49
|
const merged: Record<string, string | string[]> = {};
|
|
50
|
+
const lowerKeys: Record<string, string> = {};
|
|
50
51
|
const methodLower = (method || 'get').toLowerCase();
|
|
51
52
|
|
|
52
53
|
const setHeader = (target: Record<string, string | string[]>, key: string, value: any) => {
|
|
53
54
|
const keyLower = key.toLowerCase();
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
55
|
+
const existingKey = lowerKeys[keyLower];
|
|
56
|
+
if (existingKey !== undefined) {
|
|
57
|
+
delete target[existingKey];
|
|
58
58
|
}
|
|
59
59
|
target[key] = value;
|
|
60
|
+
lowerKeys[keyLower] = key;
|
|
60
61
|
};
|
|
61
62
|
|
|
62
63
|
if (headers['common']) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
for (const key in headers['common']) {
|
|
65
|
+
if (Object.prototype.hasOwnProperty.call(headers['common'], key)) {
|
|
66
|
+
setHeader(merged, key, headers['common'][key]);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
66
69
|
}
|
|
67
70
|
|
|
68
71
|
if (headers[methodLower]) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
for (const key in headers[methodLower]) {
|
|
73
|
+
if (Object.prototype.hasOwnProperty.call(headers[methodLower], key)) {
|
|
74
|
+
setHeader(merged, key, headers[methodLower][key]);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
72
77
|
}
|
|
73
78
|
|
|
74
79
|
for (const key in headers) {
|
|
@@ -81,25 +86,32 @@ export function flattenHeaders(
|
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
export function removeContentType(headers: Record<string, string | string[]>): void {
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
89
|
+
for (const key in headers) {
|
|
90
|
+
if (Object.prototype.hasOwnProperty.call(headers, key)) {
|
|
91
|
+
if (key.toLowerCase() === 'content-type') {
|
|
92
|
+
delete headers[key];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
87
95
|
}
|
|
88
96
|
}
|
|
89
97
|
|
|
90
98
|
export function buildFetchHeaders(headers: Record<string, string | string[]>): Headers {
|
|
91
99
|
const fetchHeaders = new Headers();
|
|
92
|
-
for (const
|
|
93
|
-
if (
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
for (const key in headers) {
|
|
101
|
+
if (Object.prototype.hasOwnProperty.call(headers, key)) {
|
|
102
|
+
const value = headers[key];
|
|
103
|
+
if (value === undefined || value === null) continue;
|
|
104
|
+
assertSafeHeader(key, value);
|
|
105
|
+
if (Array.isArray(value)) {
|
|
106
|
+
for (let i = 0; i < value.length; i++) {
|
|
107
|
+
const v = value[i];
|
|
108
|
+
if (v !== undefined && v !== null) {
|
|
109
|
+
fetchHeaders.append(key, v);
|
|
110
|
+
}
|
|
99
111
|
}
|
|
112
|
+
} else {
|
|
113
|
+
fetchHeaders.set(key, value);
|
|
100
114
|
}
|
|
101
|
-
} else {
|
|
102
|
-
fetchHeaders.set(key, value);
|
|
103
115
|
}
|
|
104
116
|
}
|
|
105
117
|
return fetchHeaders;
|
|
@@ -30,11 +30,16 @@ class MemoryCache implements CacheProvider {
|
|
|
30
30
|
// Proactively evict up to 5 of the oldest items to prevent memory build-up without O(N) cost.
|
|
31
31
|
// Map entries are ordered by insertion, so the oldest are checked first.
|
|
32
32
|
let count = 0;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
const keys = this.cache.keys();
|
|
34
|
+
while (count < 5) {
|
|
35
|
+
const next = keys.next();
|
|
36
|
+
if (next.done) break;
|
|
37
|
+
const k = next.value;
|
|
38
|
+
const item = this.cache.get(k);
|
|
39
|
+
if (item && item.expiry && now > item.expiry) {
|
|
36
40
|
this.cache.delete(k);
|
|
37
41
|
}
|
|
42
|
+
count++;
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
// Evict the oldest item if we are still at limit
|