accessio 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +4 -2
  2. package/cjs/accessio.cjs +43 -7
  3. package/cjs/accessio.cjs.map +1 -1
  4. package/cjs/core/buildURL.cjs +2 -2
  5. package/cjs/core/buildURL.cjs.map +1 -1
  6. package/cjs/core/fetchAdapter.cjs +187 -0
  7. package/cjs/core/fetchAdapter.cjs.map +1 -0
  8. package/cjs/core/mergeConfig.cjs +2 -2
  9. package/cjs/core/mergeConfig.cjs.map +1 -1
  10. package/cjs/core/request.cjs +23 -171
  11. package/cjs/core/request.cjs.map +1 -1
  12. package/cjs/core/retry.cjs +0 -3
  13. package/cjs/core/retry.cjs.map +1 -1
  14. package/cjs/defaults/transforms.cjs +8 -1
  15. package/cjs/defaults/transforms.cjs.map +1 -1
  16. package/cjs/helpers/auth.cjs +45 -0
  17. package/cjs/helpers/auth.cjs.map +1 -0
  18. package/cjs/helpers/flattenHeaders.cjs +78 -0
  19. package/cjs/helpers/flattenHeaders.cjs.map +1 -0
  20. package/cjs/helpers/parseHeaders.cjs +16 -4
  21. package/cjs/helpers/parseHeaders.cjs.map +1 -1
  22. package/cjs/helpers/rateLimiter.cjs +20 -12
  23. package/cjs/helpers/rateLimiter.cjs.map +1 -1
  24. package/cjs/helpers/transformData.cjs +2 -2
  25. package/cjs/helpers/transformData.cjs.map +1 -1
  26. package/package.json +3 -3
  27. package/src/accessio.ts +46 -8
  28. package/src/core/buildURL.ts +2 -2
  29. package/src/core/fetchAdapter.ts +184 -0
  30. package/src/core/mergeConfig.ts +2 -2
  31. package/src/core/request.ts +28 -193
  32. package/src/core/retry.ts +0 -4
  33. package/src/defaults/transforms.ts +12 -2
  34. package/src/helpers/auth.ts +26 -0
  35. package/src/helpers/flattenHeaders.ts +59 -0
  36. package/src/helpers/parseHeaders.ts +19 -6
  37. package/src/helpers/rateLimiter.ts +20 -12
  38. package/src/helpers/transformData.ts +4 -4
  39. package/src/types.ts +9 -5
@@ -0,0 +1,59 @@
1
+ const METHOD_KEYS = new Set<string>([
2
+ 'common',
3
+ 'delete',
4
+ 'get',
5
+ 'head',
6
+ 'options',
7
+ 'post',
8
+ 'put',
9
+ 'patch',
10
+ ]);
11
+
12
+ type HeadersConfig = Record<string, Record<string, string | string[]>>;
13
+
14
+ export function flattenHeaders(
15
+ headers: HeadersConfig | undefined,
16
+ method?: string,
17
+ ): Record<string, string | string[]> {
18
+ if (!headers) return {};
19
+
20
+ const merged: Record<string, string | string[]> = {};
21
+ const methodLower = (method || 'get').toLowerCase();
22
+
23
+ if (headers['common']) {
24
+ Object.assign(merged, headers['common']);
25
+ }
26
+
27
+ if (headers[methodLower]) {
28
+ Object.assign(merged, headers[methodLower]);
29
+ }
30
+
31
+ for (const key in headers) {
32
+ if (Object.prototype.hasOwnProperty.call(headers, key) && !METHOD_KEYS.has(key)) {
33
+ merged[key] = headers[key] as unknown as string | string[];
34
+ }
35
+ }
36
+
37
+ return merged;
38
+ }
39
+
40
+ export function removeContentType(headers: Record<string, string | string[]>): void {
41
+ const keys = Object.keys(headers).filter((k) => k.toLowerCase() === 'content-type');
42
+ for (const key of keys) {
43
+ delete headers[key];
44
+ }
45
+ }
46
+
47
+ export function buildFetchHeaders(headers: Record<string, string | string[]>): Headers {
48
+ const fetchHeaders = new Headers();
49
+ for (const [key, value] of Object.entries(headers)) {
50
+ if (Array.isArray(value)) {
51
+ for (const v of value) {
52
+ fetchHeaders.append(key, v);
53
+ }
54
+ } else {
55
+ fetchHeaders.set(key, value);
56
+ }
57
+ }
58
+ return fetchHeaders;
59
+ }
@@ -1,11 +1,24 @@
1
- export default function parseHeaders(headers: any): Record<string, string> {
2
- const parsed: Record<string, string> = {};
1
+ export default function parseHeaders(headers: any): Record<string, string | string[]> {
2
+ const parsed: Record<string, string | string[]> = {};
3
3
 
4
4
  if (!headers) return parsed;
5
5
 
6
+ const addHeader = (key: string, value: string) => {
7
+ const k = key.toLowerCase();
8
+ if (parsed[k]) {
9
+ if (Array.isArray(parsed[k])) {
10
+ (parsed[k] as string[]).push(value);
11
+ } else {
12
+ parsed[k] = [parsed[k] as string, value];
13
+ }
14
+ } else {
15
+ parsed[k] = value;
16
+ }
17
+ };
18
+
6
19
  if (typeof headers.forEach === 'function') {
7
20
  headers.forEach((value: string, key: string) => {
8
- parsed[key.toLowerCase()] = value;
21
+ addHeader(key, value);
9
22
  });
10
23
  return parsed;
11
24
  }
@@ -14,9 +27,9 @@ export default function parseHeaders(headers: any): Record<string, string> {
14
27
  headers.split('\n').forEach((line: string) => {
15
28
  const index = line.indexOf(':');
16
29
  if (index > 0) {
17
- const key = line.substring(0, index).trim().toLowerCase();
30
+ const key = line.substring(0, index).trim();
18
31
  const value = line.substring(index + 1).trim();
19
- parsed[key] = value;
32
+ addHeader(key, value);
20
33
  }
21
34
  });
22
35
  return parsed;
@@ -24,7 +37,7 @@ export default function parseHeaders(headers: any): Record<string, string> {
24
37
 
25
38
  if (typeof headers === 'object') {
26
39
  Object.keys(headers).forEach((key) => {
27
- parsed[key.toLowerCase()] = headers[key];
40
+ addHeader(key, headers[key]);
28
41
  });
29
42
  return parsed;
30
43
  }
@@ -21,8 +21,9 @@ export function createRateLimiter(
21
21
  }
22
22
  let active = 0;
23
23
  let destroyed = false;
24
- let headIndex = 0;
25
- let tailIndex = 0;
24
+ let head = 0;
25
+ let tail = 0;
26
+ let pendingCount = 0;
26
27
  const queue: Record<number, QueueItem> = {};
27
28
 
28
29
  function acquire(): Promise<void> {
@@ -35,12 +36,15 @@ export function createRateLimiter(
35
36
  return Promise.resolve();
36
37
  }
37
38
 
38
- if (tailIndex - headIndex >= maxQueueSize) {
39
- return Promise.reject(new Error(`[Accessio] Rate limiter queue size exceeded maxQueueSize (${maxQueueSize})`));
39
+ if (pendingCount >= maxQueueSize) {
40
+ return Promise.reject(
41
+ new Error(`[Accessio] Rate limiter queue size exceeded maxQueueSize (${maxQueueSize})`),
42
+ );
40
43
  }
41
44
 
42
45
  return new Promise((resolve, reject) => {
43
- queue[tailIndex++] = { resolve, reject };
46
+ queue[tail++] = { resolve, reject };
47
+ pendingCount++;
44
48
  });
45
49
  }
46
50
 
@@ -51,10 +55,12 @@ export function createRateLimiter(
51
55
 
52
56
  active--;
53
57
 
54
- if (tailIndex - headIndex > 0 && active < maxConcurrent) {
58
+ if (pendingCount > 0 && active < maxConcurrent) {
55
59
  active++;
56
- const next = queue[headIndex];
57
- delete queue[headIndex++];
60
+ const next = queue[head];
61
+ delete queue[head];
62
+ head++;
63
+ pendingCount--;
58
64
  next?.resolve();
59
65
  }
60
66
  }
@@ -62,9 +68,11 @@ export function createRateLimiter(
62
68
  function destroy(): void {
63
69
  destroyed = true;
64
70
  const reason = new Error('[Accessio] Rate limiter destroyed — pending request cancelled');
65
- while (tailIndex - headIndex > 0) {
66
- const next = queue[headIndex];
67
- delete queue[headIndex++];
71
+ while (pendingCount > 0) {
72
+ const next = queue[head];
73
+ delete queue[head];
74
+ head++;
75
+ pendingCount--;
68
76
  next?.reject(reason);
69
77
  }
70
78
  }
@@ -74,7 +82,7 @@ export function createRateLimiter(
74
82
  release,
75
83
  destroy,
76
84
  get pending() {
77
- return tailIndex - headIndex;
85
+ return pendingCount;
78
86
  },
79
87
  get active() {
80
88
  return active;
@@ -1,12 +1,12 @@
1
1
  import AccessioError from '../core/accessioError';
2
2
  import type { TransformFunction, AccessioRequestConfig } from '../types';
3
3
 
4
- export default function transformData(
4
+ export default async function transformData(
5
5
  transforms: TransformFunction | TransformFunction[] | undefined,
6
6
  data: unknown,
7
- headers: Record<string, string>,
7
+ headers: Record<string, string | string[]>,
8
8
  config?: AccessioRequestConfig,
9
- ): unknown {
9
+ ): Promise<unknown> {
10
10
  if (!transforms || !Array.isArray(transforms)) {
11
11
  return data;
12
12
  }
@@ -16,7 +16,7 @@ export default function transformData(
16
16
  for (const transform of transforms) {
17
17
  if (typeof transform === 'function') {
18
18
  try {
19
- result = transform(result, headers);
19
+ result = await transform(result, headers);
20
20
  } catch (err) {
21
21
  throw AccessioError.from(
22
22
  err instanceof Error ? err : new Error(String(err)),
package/src/types.ts CHANGED
@@ -11,7 +11,10 @@ export interface AuthConfig {
11
11
 
12
12
  export type ParamsSerializer = (params: Record<string, unknown>) => string;
13
13
 
14
- export type TransformFunction = (data: unknown, headers: Record<string, string>) => unknown;
14
+ export type TransformFunction = (
15
+ data: unknown,
16
+ headers: Record<string, string | string[]>,
17
+ ) => unknown | Promise<unknown>;
15
18
 
16
19
  export type RetryConditionFunction = (error: AccessioError) => boolean;
17
20
 
@@ -47,7 +50,7 @@ export interface AccessioRequestConfig {
47
50
  params?: Record<string, unknown>;
48
51
  paramsSerializer?: ParamsSerializer;
49
52
  data?: unknown;
50
- headers?: Record<string, string> | Record<string, Record<string, string>>;
53
+ headers?: Record<string, string | string[]> | Record<string, Record<string, string | string[]>>;
51
54
  auth?: AuthConfig;
52
55
  timeout?: number;
53
56
  withCredentials?: boolean;
@@ -63,13 +66,16 @@ export interface AccessioRequestConfig {
63
66
  debug?: boolean;
64
67
  rateLimiter?: RateLimiter;
65
68
  _builtUrl?: string;
69
+ maxContentLength?: number;
70
+ dispatcher?: unknown;
71
+ agent?: unknown;
66
72
  }
67
73
 
68
74
  export interface AccessioResponse<T = unknown> {
69
75
  data: T;
70
76
  status: number;
71
77
  statusText: string;
72
- headers: Record<string, string>;
78
+ headers: Record<string, string | string[]>;
73
79
  config: AccessioRequestConfig;
74
80
  request: Response;
75
81
  duration: number;
@@ -86,8 +92,6 @@ export interface AccessioError extends Error {
86
92
  toJSON(): Record<string, unknown>;
87
93
  }
88
94
 
89
-
90
-
91
95
  export interface RateLimiter {
92
96
  acquire: () => Promise<void>;
93
97
  release: () => void;