accessio 1.0.0

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 (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +487 -0
  3. package/cjs/accessio.cjs +208 -0
  4. package/cjs/accessio.cjs.map +1 -0
  5. package/cjs/constants/errorCodes.cjs +76 -0
  6. package/cjs/constants/errorCodes.cjs.map +1 -0
  7. package/cjs/core/accessioError.cjs +93 -0
  8. package/cjs/core/accessioError.cjs.map +1 -0
  9. package/cjs/core/buildURL.cjs +100 -0
  10. package/cjs/core/buildURL.cjs.map +1 -0
  11. package/cjs/core/mergeConfig.cjs +73 -0
  12. package/cjs/core/mergeConfig.cjs.map +1 -0
  13. package/cjs/core/request.cjs +259 -0
  14. package/cjs/core/request.cjs.map +1 -0
  15. package/cjs/core/retry.cjs +109 -0
  16. package/cjs/core/retry.cjs.map +1 -0
  17. package/cjs/defaults/index.cjs +55 -0
  18. package/cjs/defaults/index.cjs.map +1 -0
  19. package/cjs/defaults/transforms.cjs +59 -0
  20. package/cjs/defaults/transforms.cjs.map +1 -0
  21. package/cjs/helpers/debug.cjs +96 -0
  22. package/cjs/helpers/debug.cjs.map +1 -0
  23. package/cjs/helpers/parseHeaders.cjs +52 -0
  24. package/cjs/helpers/parseHeaders.cjs.map +1 -0
  25. package/cjs/helpers/rateLimiter.cjs +98 -0
  26. package/cjs/helpers/rateLimiter.cjs.map +1 -0
  27. package/cjs/helpers/settle.cjs +50 -0
  28. package/cjs/helpers/settle.cjs.map +1 -0
  29. package/cjs/helpers/transformData.cjs +57 -0
  30. package/cjs/helpers/transformData.cjs.map +1 -0
  31. package/cjs/index.cjs +121 -0
  32. package/cjs/index.cjs.map +1 -0
  33. package/cjs/interceptors/interceptorManager.cjs +31 -0
  34. package/cjs/interceptors/interceptorManager.cjs.map +1 -0
  35. package/index.d.ts +454 -0
  36. package/package.json +116 -0
  37. package/src/accessio.ts +251 -0
  38. package/src/constants/errorCodes.ts +29 -0
  39. package/src/core/accessioError.ts +74 -0
  40. package/src/core/buildURL.ts +99 -0
  41. package/src/core/mergeConfig.ts +78 -0
  42. package/src/core/request.ts +284 -0
  43. package/src/core/retry.ts +117 -0
  44. package/src/defaults/index.ts +36 -0
  45. package/src/defaults/transforms.ts +44 -0
  46. package/src/helpers/debug.ts +103 -0
  47. package/src/helpers/parseHeaders.ts +35 -0
  48. package/src/helpers/rateLimiter.ts +96 -0
  49. package/src/helpers/settle.ts +26 -0
  50. package/src/helpers/transformData.ts +36 -0
  51. package/src/index.ts +102 -0
  52. package/src/interceptors/interceptorManager.ts +5 -0
  53. package/src/types.ts +159 -0
@@ -0,0 +1,26 @@
1
+ import AccessioError from '../core/accessioError';
2
+ import type { AccessioResponse, AccessioRequestConfig } from '../types';
3
+
4
+ export default function settle(
5
+ resolve: (value: AccessioResponse) => void,
6
+ reject: (reason: AccessioError) => void,
7
+ response: AccessioResponse,
8
+ config: AccessioRequestConfig,
9
+ ): void {
10
+ const validateStatus = config.validateStatus;
11
+
12
+ if (!response.status || !validateStatus || validateStatus(response.status)) {
13
+ resolve(response);
14
+ } else {
15
+ const error = new AccessioError(
16
+ `Request failed with status code ${response.status}`,
17
+ response.status >= 400 && response.status < 500
18
+ ? AccessioError.ERR_BAD_REQUEST
19
+ : AccessioError.ERR_BAD_RESPONSE,
20
+ config,
21
+ response.request,
22
+ response,
23
+ );
24
+ reject(error);
25
+ }
26
+ }
@@ -0,0 +1,36 @@
1
+ import AccessioError from '../core/accessioError';
2
+ import type {
3
+ TransformFunction,
4
+ AccessioRequestConfig,
5
+ } from '../types';
6
+
7
+ export default function transformData(
8
+ transforms: TransformFunction | TransformFunction[] | undefined,
9
+ data: unknown,
10
+ headers: Record<string, string>,
11
+ config?: AccessioRequestConfig,
12
+ ): unknown {
13
+ if (!transforms || !Array.isArray(transforms)) {
14
+ return data;
15
+ }
16
+
17
+ let result = data;
18
+
19
+ for (const transform of transforms) {
20
+ if (typeof transform === 'function') {
21
+ try {
22
+ result = transform(result, headers);
23
+ } catch (err) {
24
+ throw AccessioError.from(
25
+ err instanceof Error ? err : new Error(String(err)),
26
+ AccessioError.ERR_BAD_REQUEST,
27
+ config ?? null,
28
+ null,
29
+ null,
30
+ );
31
+ }
32
+ }
33
+ }
34
+
35
+ return result;
36
+ }
package/src/index.ts ADDED
@@ -0,0 +1,102 @@
1
+ import Accessio from './accessio';
2
+ import defaults from './defaults';
3
+ import AccessioError from './core/accessioError';
4
+ import mergeConfig from './core/mergeConfig';
5
+ import buildURL from './core/buildURL';
6
+ import InterceptorManager from './interceptors/interceptorManager';
7
+ import { createRateLimiter } from './helpers/rateLimiter';
8
+ import { logRequest, logResponse, logError } from './helpers/debug';
9
+ import { ERR_CANCELED } from './constants/errorCodes';
10
+ import type { AccessioRequestConfig, AccessioResponse } from './types';
11
+
12
+ const PUBLIC_METHODS = [
13
+ 'request',
14
+ 'getUri',
15
+ 'get',
16
+ 'delete',
17
+ 'head',
18
+ 'options',
19
+ 'post',
20
+ 'put',
21
+ 'patch',
22
+ 'postForm',
23
+ 'putForm',
24
+ 'patchForm',
25
+ ];
26
+
27
+ function createInstance(defaultConfig: AccessioRequestConfig) {
28
+ const context = new Accessio(defaultConfig);
29
+
30
+ const instance: any = function accessio(
31
+ configOrUrl: string | AccessioRequestConfig,
32
+ config?: AccessioRequestConfig,
33
+ ) {
34
+ return context.request(configOrUrl, config);
35
+ };
36
+
37
+ for (const key of PUBLIC_METHODS) {
38
+ const method: any = (context as any)[key];
39
+ if (typeof method === 'function') {
40
+ instance[key] = method.bind(context);
41
+ }
42
+ }
43
+
44
+ instance.defaults = context.defaults;
45
+ instance.interceptors = context.interceptors;
46
+ instance.all = function all(promises: any[]): Promise<any[]> {
47
+ return Promise.all(promises);
48
+ };
49
+ instance.spread = function spread<T>(
50
+ callback: (...args: any[]) => T,
51
+ ): (arr: any[]) => T {
52
+ return function wrap(arr: any[]): T {
53
+ return callback(...arr);
54
+ };
55
+ };
56
+ instance.isCancel = function isCancel(value: any): boolean {
57
+ return !!(
58
+ value &&
59
+ value.isAccessioError &&
60
+ value.code === ERR_CANCELED
61
+ );
62
+ };
63
+ instance.isAccessioError = function isAccessioError(
64
+ value: any,
65
+ ): boolean {
66
+ return (
67
+ value instanceof AccessioError ||
68
+ !!(value && typeof value === 'object' && value.isAccessioError === true)
69
+ );
70
+ };
71
+ instance.AccessioError = AccessioError;
72
+ instance.Accessio = Accessio;
73
+ instance.mergeConfig = mergeConfig;
74
+ instance.buildURL = buildURL;
75
+ instance.InterceptorManager = InterceptorManager;
76
+ instance.createRateLimiter = createRateLimiter;
77
+
78
+ return instance;
79
+ }
80
+
81
+ const accessio = createInstance(defaults);
82
+
83
+ function create(instanceConfig?: AccessioRequestConfig) {
84
+ return createInstance(mergeConfig(defaults, instanceConfig));
85
+ }
86
+
87
+ accessio.create = create;
88
+
89
+ export default accessio;
90
+
91
+ export {
92
+ Accessio,
93
+ AccessioError,
94
+ mergeConfig,
95
+ buildURL,
96
+ InterceptorManager,
97
+ createInstance,
98
+ createRateLimiter,
99
+ logRequest,
100
+ logResponse,
101
+ logError,
102
+ };
@@ -0,0 +1,5 @@
1
+ import { InterceptorManager } from '../types';
2
+
3
+ export { InterceptorManager };
4
+
5
+ export default InterceptorManager;
package/src/types.ts ADDED
@@ -0,0 +1,159 @@
1
+ export type Method =
2
+ | 'get'
3
+ | 'delete'
4
+ | 'head'
5
+ | 'options'
6
+ | 'post'
7
+ | 'put'
8
+ | 'patch';
9
+
10
+ export type ResponseType =
11
+ | 'json'
12
+ | 'text'
13
+ | 'blob'
14
+ | 'arraybuffer'
15
+ | 'stream';
16
+
17
+ export interface AuthConfig {
18
+ username: string;
19
+ password: string;
20
+ }
21
+
22
+ export type ParamsSerializer = (params: Record<string, unknown>) => string;
23
+
24
+ export type TransformFunction = (
25
+ data: unknown,
26
+ headers: Record<string, string>,
27
+ ) => unknown;
28
+
29
+ export type RetryConditionFunction = (error: AccessioError) => boolean;
30
+
31
+ export type OnRetryFunction = (
32
+ attempt: number,
33
+ error: AccessioError,
34
+ config: AccessioRequestConfig,
35
+ ) => void;
36
+
37
+ export type RunWhenFunction = (config: AccessioRequestConfig) => boolean;
38
+
39
+ export interface InterceptorOptions {
40
+ synchronous?: boolean;
41
+ runWhen?: RunWhenFunction;
42
+ }
43
+
44
+ export interface InterceptorHandler {
45
+ fulfilled: TransformFunction | null;
46
+ rejected: ((error: unknown) => unknown) | null;
47
+ synchronous: boolean;
48
+ runWhen: RunWhenFunction | null;
49
+ }
50
+
51
+ export interface Interceptors {
52
+ request: InterceptorManager;
53
+ response: InterceptorManager;
54
+ }
55
+
56
+ export interface AccessioRequestConfig {
57
+ url?: string;
58
+ baseURL?: string;
59
+ method?: Method | string;
60
+ params?: Record<string, unknown>;
61
+ paramsSerializer?: ParamsSerializer;
62
+ data?: unknown;
63
+ headers?: Record<string, string> | Record<string, Record<string, string>>;
64
+ auth?: AuthConfig;
65
+ timeout?: number;
66
+ withCredentials?: boolean;
67
+ responseType?: ResponseType;
68
+ transformRequest?: TransformFunction | TransformFunction[];
69
+ transformResponse?: TransformFunction | TransformFunction[];
70
+ validateStatus?: ((status: number) => boolean) | null;
71
+ retry?: number;
72
+ retryDelay?: number;
73
+ retryCondition?: RetryConditionFunction;
74
+ onRetry?: OnRetryFunction;
75
+ signal?: AbortSignal;
76
+ debug?: boolean;
77
+ rateLimiter?: RateLimiter;
78
+ _builtUrl?: string;
79
+ }
80
+
81
+ export interface AccessioResponse<T = unknown> {
82
+ data: T;
83
+ status: number;
84
+ statusText: string;
85
+ headers: Record<string, string>;
86
+ config: AccessioRequestConfig;
87
+ request: Response;
88
+ duration: number;
89
+ }
90
+
91
+ export interface AccessioError extends Error {
92
+ name: 'AccessioError';
93
+ code: string | null;
94
+ config: AccessioRequestConfig | null;
95
+ request: unknown;
96
+ response: AccessioResponse | null;
97
+ isAccessioError: true;
98
+ cause?: Error;
99
+ toJSON(): Record<string, unknown>;
100
+ }
101
+
102
+ export class InterceptorManager {
103
+ handlers: Array<InterceptorHandler | null>;
104
+ private _activeCount: number;
105
+
106
+ constructor() {
107
+ this.handlers = [];
108
+ this._activeCount = 0;
109
+ }
110
+
111
+ use(
112
+ fulfilled: TransformFunction,
113
+ rejected?: (error: unknown) => unknown,
114
+ options: InterceptorOptions = {},
115
+ ): number {
116
+ this.handlers.push({
117
+ fulfilled: fulfilled || null,
118
+ rejected: rejected || null,
119
+ synchronous: options.synchronous || false,
120
+ runWhen: options.runWhen || null,
121
+ });
122
+
123
+ this._activeCount++;
124
+ return this.handlers.length - 1;
125
+ }
126
+
127
+ eject(id: number): void {
128
+ if (this.handlers[id]) {
129
+ this.handlers[id] = null;
130
+ this._activeCount--;
131
+ }
132
+ }
133
+
134
+ clear(): void {
135
+ this.handlers = [];
136
+ this._activeCount = 0;
137
+ }
138
+
139
+ forEach(fn: (handler: InterceptorHandler) => void): void {
140
+ for (const handler of this.handlers) {
141
+ if (handler !== null) {
142
+ fn(handler);
143
+ }
144
+ }
145
+ }
146
+
147
+ get size(): number {
148
+ return this._activeCount;
149
+ }
150
+ }
151
+
152
+ export interface RateLimiter {
153
+ acquire: () => Promise<void>;
154
+ release: () => void;
155
+ destroy: () => void;
156
+ pending: number;
157
+ active: number;
158
+ destroyed: boolean;
159
+ }