@zayne-labs/callapi 0.0.6 → 0.1.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.
@@ -0,0 +1,241 @@
1
+ type AnyString = string & {
2
+ placeholder?: never;
3
+ };
4
+ type AnyNumber = number & {
5
+ placeholder?: never;
6
+ };
7
+
8
+ type ToQueryStringFn = {
9
+ (params: Required<ExtraOptions>["query"]): string;
10
+ (params: ExtraOptions["query"]): string | null;
11
+ };
12
+ declare const toQueryString: ToQueryStringFn;
13
+ declare const mergeUrlWithParams: (url: string, params: ExtraOptions["query"]) => string;
14
+ declare const objectifyHeaders: (headers: RequestInit["headers"]) => Record<string, string> | undefined;
15
+ declare const defaultRetryCodes: Required<BaseConfig>["retryCodes"];
16
+ declare const defaultRetryMethods: Required<BaseConfig>["retryMethods"];
17
+ declare const fetchSpecificKeys: ("body" | "method" | "headers" | "cache" | "credentials" | "integrity" | "keepalive" | "mode" | "priority" | "redirect" | "referrer" | "referrerPolicy" | "signal" | "window")[];
18
+ declare const splitConfig: <TObject extends object>(config: TObject) => ["body" extends keyof TObject ? $RequestOptions : $BaseRequestOptions, ExtraOptions];
19
+ declare const handleResponseType: <TResponse>(response: Response, parser?: Required<ExtraOptions>["responseParser"]) => {
20
+ json: () => Promise<Record<string, unknown> | TResponse>;
21
+ arrayBuffer: () => Promise<TResponse>;
22
+ blob: () => Promise<TResponse>;
23
+ formData: () => Promise<TResponse>;
24
+ text: () => Promise<TResponse>;
25
+ };
26
+ declare const getResponseData: <TResponse>(response: Response, responseType: keyof ReturnType<typeof handleResponseType>, parser: ExtraOptions["responseParser"]) => Promise<Record<string, unknown> | TResponse>;
27
+ type data = {
28
+ successData: unknown;
29
+ options: ExtraOptions;
30
+ response: Response;
31
+ };
32
+ declare const resolveSuccessResult: <CallApiResult>(info: data) => CallApiResult;
33
+ declare const $resolveErrorResult: <CallApiResult>($info: {
34
+ error?: unknown;
35
+ options: ExtraOptions;
36
+ }) => (info?: {
37
+ response?: Response;
38
+ errorData?: unknown;
39
+ message?: string;
40
+ }) => CallApiResult;
41
+ declare const isHTTPError: <TErrorData>(error: ApiErrorVariant<TErrorData>["error"] | null) => error is {
42
+ errorName: "HTTPError";
43
+ errorData: TErrorData;
44
+ message: string;
45
+ };
46
+ type ErrorDetails<TErrorResponse> = {
47
+ response: Response & {
48
+ errorData: TErrorResponse;
49
+ };
50
+ defaultErrorMessage: string;
51
+ };
52
+ type ErrorOptions = {
53
+ cause?: unknown;
54
+ };
55
+ declare class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {
56
+ response: ErrorDetails<TErrorResponse>["response"];
57
+ name: "HTTPError";
58
+ isHTTPError: boolean;
59
+ constructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions);
60
+ }
61
+ declare const isHTTPErrorInstance: <TErrorResponse>(error: unknown) => error is HTTPError<TErrorResponse>;
62
+ declare const waitUntil: (delay: number) => Promise<unknown> | undefined;
63
+
64
+ type $RequestOptions = Pick<FetchConfig, (typeof fetchSpecificKeys)[number]>;
65
+ type $BaseRequestOptions = Omit<$RequestOptions, "body">;
66
+ type ExtraOptions<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultModeUnion = ResultModeUnion> = {
67
+ /** Optional body of the request, can be a object or any other supported body type. */
68
+ body?: Record<string, unknown> | RequestInit["body"];
69
+ /**
70
+ * @description HTTP method for the request.
71
+ * @default "GET"
72
+ */
73
+ method?: "GET" | "POST" | "PATCH" | "PUT" | "DELETE" | AnyString;
74
+ /**
75
+ * @description Query parameters to append to the URL.
76
+ */
77
+ query?: Record<string, string | number | boolean>;
78
+ /**
79
+ * @description Authorization header value.
80
+ */
81
+ auth?: string;
82
+ /**
83
+ * @description Custom function to serialize the body object into a string.
84
+ */
85
+ bodySerializer?: (bodyData: Record<string, unknown>) => string;
86
+ /**
87
+ * @description Custom function to parse the response string into a object.
88
+ */
89
+ responseParser?: (responseString: string) => Record<string, unknown>;
90
+ /**
91
+ * @description Mode of the result, can influence how results are handled or returned.
92
+ * Can be set to "all" | "onlySuccess" | "onlyError" | "onlyResponse".
93
+ * @default "all"
94
+ */
95
+ resultMode?: TBaseResultMode;
96
+ /**
97
+ * @description If true, cancels previous unfinished requests to the same URL.
98
+ * @default true
99
+ */
100
+ cancelRedundantRequests?: boolean;
101
+ /**
102
+ * @description Base URL to be prepended to all request URLs
103
+ */
104
+ baseURL?: string;
105
+ /**
106
+ * @description Request timeout in milliseconds
107
+ */
108
+ timeout?: number;
109
+ /**
110
+ * @description Default error message to use if none is provided from a response.
111
+ * @default "Failed to fetch data from server!"
112
+ */
113
+ defaultErrorMessage?: string;
114
+ /**
115
+ * If true or the function returns true, throws errors instead of returning them
116
+ * The function is passed the error object and can be used to conditionally throw the error
117
+ * @default false
118
+ */
119
+ throwOnError?: boolean | ((error?: Error | HTTPError<TBaseErrorData>) => boolean);
120
+ /**
121
+ * @description Expected response type, affects how response is parsed
122
+ * @default "json"
123
+ */
124
+ responseType?: keyof ReturnType<typeof handleResponseType>;
125
+ /**
126
+ * @description Number of retry attempts for failed requests
127
+ * @default 0
128
+ */
129
+ retries?: number;
130
+ /**
131
+ * @description Delay between retries in milliseconds
132
+ * @default 500
133
+ */
134
+ retryDelay?: number;
135
+ /**
136
+ * @description HTTP status codes that trigger a retry
137
+ * @default [409, 425, 429, 500, 502, 503, 504]
138
+ */
139
+ retryCodes?: Array<409 | 425 | 429 | 500 | 502 | 503 | 504 | AnyNumber>;
140
+ /**
141
+ * HTTP methods that are allowed to retry
142
+ * @default ["GET", "POST"]
143
+ */
144
+ retryMethods?: Array<"GET" | "POST" | AnyString>;
145
+ /**
146
+ * @description an optional field you can fill with additional information,
147
+ * to associate with the request, typically used for logging or tracing.
148
+ *
149
+ * A good use case for this, would be to use the info to handle specific cases in any of the shared interceptors.
150
+ * @example
151
+ * ```ts
152
+ * const callMainApi = callApi.create({
153
+ * baseURL: "https://main-api.com",
154
+ * onResponseError: ({ response, options }) => {
155
+ * if (options.meta?.userId) {
156
+ * console.error(`User ${options.meta.userId} made an error`);
157
+ * }
158
+ * },
159
+ * });
160
+ *
161
+ * const response = await callMainApi({
162
+ * url: "https://example.com/api/data",
163
+ * meta: { userId: "123" },
164
+ * });
165
+ * ```
166
+ */
167
+ meta?: Record<string, unknown>;
168
+ /** @description Interceptor to be called just before the request is made, allowing for modifications or additional operations. */
169
+ onRequest?: (requestContext: {
170
+ request: $RequestOptions;
171
+ options: ExtraOptions;
172
+ }) => void | Promise<void>;
173
+ /** @description Interceptor to be called when an error occurs during the fetch request. */
174
+ onRequestError?: (requestErrorContext: {
175
+ error: Error;
176
+ request: $RequestOptions;
177
+ options: ExtraOptions;
178
+ }) => void | Promise<void>;
179
+ /** @description Interceptor to be called when a successful response is received from the api. */
180
+ onResponse?: (responseContext: ResponseContext<TBaseData>) => void | Promise<void>;
181
+ /** @description Interceptor to be called when an error response is received from the api. */
182
+ onResponseError?: (responseErrorContext: ResponseErrorContext<TBaseErrorData>) => void | Promise<void>;
183
+ };
184
+ type ResponseContext<TData> = {
185
+ _: {
186
+ response: Response & {
187
+ data: TData;
188
+ };
189
+ request: $RequestOptions;
190
+ options: ExtraOptions;
191
+ };
192
+ }["_"];
193
+ type ResponseErrorContext<TErrorData> = {
194
+ _: {
195
+ response: Response & {
196
+ errorData: TErrorData;
197
+ };
198
+ request: $RequestOptions;
199
+ options: ExtraOptions;
200
+ };
201
+ }["_"];
202
+ interface FetchConfig<TData = unknown, TErrorData = unknown, TResultMode extends ResultModeUnion = undefined> extends Omit<RequestInit, "method" | "body">, ExtraOptions<TData, TErrorData, TResultMode> {
203
+ }
204
+ interface BaseConfig<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultModeUnion = undefined> extends FetchConfig<TBaseData, TBaseErrorData, TBaseResultMode> {
205
+ }
206
+ type ApiSuccessVariant<TData> = {
207
+ data: TData;
208
+ error: null;
209
+ response: Response;
210
+ };
211
+ type PossibleErrors = "AbortError" | "TimeoutError" | "SyntaxError" | "TypeError" | "Error" | "UnknownError";
212
+ type ApiErrorVariant<TErrorData> = {
213
+ data: null;
214
+ error: {
215
+ errorName: "HTTPError";
216
+ errorData: TErrorData;
217
+ message: string;
218
+ };
219
+ response: Response;
220
+ } | {
221
+ data: null;
222
+ error: {
223
+ errorName: PossibleErrors;
224
+ message: string;
225
+ };
226
+ response: null;
227
+ };
228
+ type ResultModeMap<TData = unknown, TErrorData = unknown> = {
229
+ all: ApiSuccessVariant<TData> | ApiErrorVariant<TErrorData>;
230
+ onlySuccess: ApiSuccessVariant<TData>["data"];
231
+ onlyError: ApiErrorVariant<TErrorData>["error"];
232
+ onlyResponse: Response;
233
+ };
234
+ type ResultModeUnion = {
235
+ _: {
236
+ [Key in keyof ResultModeMap]: Key;
237
+ }[keyof ResultModeMap] | undefined;
238
+ }["_"];
239
+ type GetCallApiResult<TData, TErrorData, TResultMode> = TResultMode extends NonNullable<ResultModeUnion> ? ResultModeMap<TData, TErrorData>[TResultMode] : ResultModeMap<TData, TErrorData>["all"];
240
+
241
+ export { type $RequestOptions as $, type BaseConfig as B, type ExtraOptions as E, type FetchConfig as F, type GetCallApiResult as G, HTTPError as H, type ResultModeUnion as R, type ResponseContext as a, type ResponseErrorContext as b, isHTTPErrorInstance as c, defaultRetryCodes as d, defaultRetryMethods as e, fetchSpecificKeys as f, getResponseData as g, handleResponseType as h, isHTTPError as i, $resolveErrorResult as j, mergeUrlWithParams as m, objectifyHeaders as o, resolveSuccessResult as r, splitConfig as s, toQueryString as t, waitUntil as w };
package/dist/utils.cjs CHANGED
@@ -1,23 +1,23 @@
1
1
  'use strict';
2
2
 
3
- const m=(e,r)=>{if(!r)return e;const o=new URLSearchParams(r).toString();return e.includes("?")&&!e.endsWith("?")?`${e}&${o}`:e.endsWith("?")?`${e}${o}`:`${e}?${o}`},b=e=>!e||i(e)?e:Object.fromEntries(d(e)?e:e.entries()),p={408:"Request Timeout",409:"Conflict",425:"Too Early",429:"Too Many Requests",500:"Internal Server Error",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout"},g=Object.keys(p).map(Number),j=["GET"],c=["body","integrity","method","headers","signal","cache","redirect","window","credentials","keepalive","referrer","priority","mode","referrerPolicy"],l=(e,r)=>{const o=Object.entries(e).filter(([s])=>!r.includes(s));return Object.fromEntries(o)},T=(e,r)=>{const o=new Set(r),s=Object.entries(e).filter(([a])=>o.has(a));return Object.fromEntries(s)},x=e=>[T(e,c),l(e,c)],f=(e,r)=>({json:async()=>r?r(await e.text()):e.json(),arrayBuffer:()=>e.arrayBuffer(),blob:()=>e.blob(),formData:()=>e.formData(),text:()=>e.text()}),w=(e,r,o)=>{const t=f(e,o);if(!Object.hasOwn(t,r))throw new Error(`Invalid response type: ${r}`);return t[r]()},k=e=>{const{options:r,response:o,successData:t}=e,s={dataInfo:t,errorInfo:null,response:o};return r.resultMode===void 0||r.resultMode==="all"?s:{onlySuccess:s.dataInfo,onlyError:s.errorInfo,onlyResponse:s.response}[r.resultMode]},P=e=>{const{error:r,options:o}=e;return (s={})=>{const{errorData:n,message:a,response:u}=s;if(E(o.throwOnError)?o.throwOnError(r):o.throwOnError)throw r;return {dataInfo:null,errorInfo:{errorName:r?.name??"UnknownError",message:a??r?.message??o.defaultErrorMessage,...!!n&&{errorData:n}},response:u??null}}},A=e=>i(e)&&e.errorName==="HTTPError";class y extends Error{response;name="HTTPError";isHTTPError=!0;constructor(r,o){const{defaultErrorMessage:t,response:s}=r;super(s.errorData.message??t,o),this.response=s;}}const h=e=>e instanceof y||i(e)&&e.name==="HTTPError"&&e.isHTTPError===!0,C=e=>{if(e===0)return;const{promise:r,resolve:o}=Promise.withResolvers();return setTimeout(o,e),r},d=e=>Array.isArray(e),R=e=>e instanceof FormData,i=e=>typeof e=="object"&&e!==null&&!R(e)&&!Array.isArray(e),E=e=>typeof e=="function";
3
+ var _typeof = require('./typeof');
4
4
 
5
- exports.$resolveErrorResult = P;
6
- exports.HTTPError = y;
7
- exports.defaultRetryCodes = g;
5
+ const d=r=>r?new URLSearchParams(r).toString():(console.error("No query params provided"),null),b=(r,e)=>{if(!e)return r;const t=d(e);return r.includes("?")&&!r.endsWith("?")?`${r}&${t}`:r.endsWith("?")?`${r}${t}`:`${r}?${t}`},g=r=>!r||_typeof.isObject(r)?r:Object.fromEntries(_typeof.isArray(r)?r:r.entries()),T={408:"Request Timeout",409:"Conflict",425:"Too Early",429:"Too Many Requests",500:"Internal Server Error",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout"},x=Object.keys(T).map(Number),j=["GET"],c=["body","integrity","method","headers","signal","cache","redirect","window","credentials","keepalive","referrer","priority","mode","referrerPolicy"],E=(r,e)=>{const t=Object.entries(r).filter(([s])=>!e.includes(s));return Object.fromEntries(t)},y=(r,e)=>{const t=new Set(e),s=Object.entries(r).filter(([n])=>t.has(n));return Object.fromEntries(s)},P=r=>[y(r,c),E(r,c)],R=(r,e)=>({json:async()=>e?e(await r.text()):r.json(),arrayBuffer:()=>r.arrayBuffer(),blob:()=>r.blob(),formData:()=>r.formData(),text:()=>r.text()}),w=(r,e,t)=>{const o=R(r,t);if(!Object.hasOwn(o,e))throw new Error(`Invalid response type: ${e}`);return o[e]()},k=r=>{const{options:e,response:t,successData:o}=r,s={data:o,errorInfo:null,response:t};return e.resultMode===void 0||e.resultMode==="all"?s:{onlySuccess:s.data,onlyError:s.errorInfo,onlyResponse:s.response}[e.resultMode]},h=r=>{const{error:e,options:t}=r;return (s={})=>{const{errorData:i,message:n,response:p}=s;if(_typeof.isFunction(t.throwOnError)?t.throwOnError(e):t.throwOnError)throw e;return {data:null,error:{errorName:e?.name??"UnknownError",errorData:i??null,message:n??e?.message??t.defaultErrorMessage},response:p??null}}},A=r=>_typeof.isObject(r)&&r.errorName==="HTTPError";class O extends Error{response;name="HTTPError";isHTTPError=!0;constructor(e,t){const{defaultErrorMessage:o,response:s}=e;super(s.errorData.message??o,t),this.response=s;}}const C=r=>r instanceof O||_typeof.isObject(r)&&r.name==="HTTPError"&&r.isHTTPError===!0,v=r=>{if(r===0)return;const{promise:e,resolve:t}=Promise.withResolvers();return setTimeout(t,r),e};
6
+
7
+ exports.$resolveErrorResult = h;
8
+ exports.HTTPError = O;
9
+ exports.defaultRetryCodes = x;
8
10
  exports.defaultRetryMethods = j;
9
11
  exports.fetchSpecificKeys = c;
10
12
  exports.getResponseData = w;
11
- exports.handleResponseType = f;
12
- exports.isFormData = R;
13
- exports.isFunction = E;
14
- exports.isHTTPErrorInfo = A;
15
- exports.isHTTPErrorInstance = h;
16
- exports.isObject = i;
17
- exports.mergeUrlWithParams = m;
18
- exports.objectifyHeaders = b;
13
+ exports.handleResponseType = R;
14
+ exports.isHTTPError = A;
15
+ exports.isHTTPErrorInstance = C;
16
+ exports.mergeUrlWithParams = b;
17
+ exports.objectifyHeaders = g;
19
18
  exports.resolveSuccessResult = k;
20
- exports.splitConfig = x;
21
- exports.wait = C;
19
+ exports.splitConfig = P;
20
+ exports.toQueryString = d;
21
+ exports.waitUntil = v;
22
22
  //# sourceMappingURL=out.js.map
23
23
  //# sourceMappingURL=utils.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts"],"names":["mergeUrlWithParams","url","params","paramsString","objectifyHeaders","headers","isObject","isArray","retryCodesLookup","defaultRetryCodes","defaultRetryMethods","fetchSpecificKeys","omitKeys","initialObject","keysToOmit","arrayFromFilteredObject","key","pickKeys","keysToPick","keysToPickSet","filteredArray","objectKey","splitConfig","config","handleResponseType","response","parser","getResponseData","responseType","RESPONSE_TYPE_LOOKUP","resolveSuccessResult","info","options","successData","apiDetails","$resolveErrorResult","$info","error","errorData","message","isFunction","isHTTPErrorInfo","errorInfo","HTTPError","errorDetails","errorOptions","defaultErrorMessage","isHTTPErrorInstance","wait","delay","promise","resolve","value","isFormData"],"mappings":"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","sourcesContent":["import type { AnyFunction } from \"./type-helpers\";\nimport type {\n\t$BaseRequestConfig,\n\t$RequestConfig,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tPossibleErrorObject,\n} from \"./types\";\n\nexport const mergeUrlWithParams = (url: string, params: ExtraOptions[\"query\"]): string => {\n\tif (!params) {\n\t\treturn url;\n\t}\n\n\tconst paramsString = new URLSearchParams(params as Record<string, string>).toString();\n\n\tif (url.includes(\"?\") && !url.endsWith(\"?\")) {\n\t\treturn `${url}&${paramsString}`;\n\t}\n\n\tif (url.endsWith(\"?\")) {\n\t\treturn `${url}${paramsString}`;\n\t}\n\n\treturn `${url}?${paramsString}`;\n};\n\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\n\tif (!headers || isObject(headers)) {\n\t\treturn headers;\n\t}\n\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\n};\n\nconst retryCodesLookup = {\n\t408: \"Request Timeout\",\n\t409: \"Conflict\",\n\t425: \"Too Early\",\n\t429: \"Too Many Requests\",\n\t500: \"Internal Server Error\",\n\t502: \"Bad Gateway\",\n\t503: \"Service Unavailable\",\n\t504: \"Gateway Timeout\",\n};\n\nexport const defaultRetryCodes: Required<BaseConfig>[\"retryCodes\"] =\n\tObject.keys(retryCodesLookup).map(Number);\n\nexport const defaultRetryMethods: Required<BaseConfig>[\"retryMethods\"] = [\"GET\"];\n\nexport const fetchSpecificKeys = [\n\t\"body\",\n\t\"integrity\",\n\t\"method\",\n\t\"headers\",\n\t\"signal\",\n\t\"cache\",\n\t\"redirect\",\n\t\"window\",\n\t\"credentials\",\n\t\"keepalive\",\n\t\"referrer\",\n\t\"priority\",\n\t\"mode\",\n\t\"referrerPolicy\",\n] satisfies Array<keyof FetchConfig>;\n\nconst omitKeys = <TObject extends Record<string, unknown>, const TOmitArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToOmit: TOmitArray\n) => {\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\n\t\t([key]) => !keysToOmit.includes(key)\n\t);\n\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\n\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\n};\n\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToPick: TPickArray\n) => {\n\tconst keysToPickSet = new Set(keysToPick);\n\n\tconst arrayFromInitObject = Object.entries(initialObject);\n\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\n\n\tconst updatedObject = Object.fromEntries(filteredArray);\n\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\n};\n\nexport const splitConfig = <TObject extends object>(\n\tconfig: TObject\n): [\"body\" extends keyof TObject ? $RequestConfig : $BaseRequestConfig, ExtraOptions] => [\n\tpickKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n\tomitKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n];\n\nexport const handleResponseType = <TResponse>(\n\tresponse: Response,\n\tparser?: Required<ExtraOptions>[\"responseParser\"]\n) => ({\n\tjson: async () => {\n\t\tif (parser) {\n\t\t\treturn parser<TResponse>(await response.text());\n\t\t}\n\n\t\treturn response.json() as Promise<TResponse>;\n\t},\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\n\tblob: () => response.blob() as Promise<TResponse>,\n\tformData: () => response.formData() as Promise<TResponse>,\n\ttext: () => response.text() as Promise<TResponse>,\n});\n\nexport const getResponseData = <TResponse>(\n\tresponse: Response,\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\n\tparser: ExtraOptions[\"responseParser\"]\n) => {\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\n\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\n\t}\n\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\n};\n\ntype DataInfo = {\n\tsuccessData: unknown;\n\toptions: ExtraOptions;\n\tresponse: Response;\n};\n\n// == The CallApiResult type is used to cast all return statements due to a design limitation in ts.\n// LINK - See https://www.zhenghao.io/posts/type-functions for more info\nexport const resolveSuccessResult = <CallApiResult>(info: DataInfo): CallApiResult => {\n\tconst { options, response, successData } = info;\n\n\tconst apiDetails = { dataInfo: successData, errorInfo: null, response };\n\n\tif (options.resultMode === undefined || options.resultMode === \"all\") {\n\t\treturn apiDetails as CallApiResult;\n\t}\n\n\treturn {\n\t\tonlySuccess: apiDetails.dataInfo,\n\t\tonlyError: apiDetails.errorInfo,\n\t\tonlyResponse: apiDetails.response,\n\t}[options.resultMode] as CallApiResult;\n};\n\n// == Using curring here so error and options are not required to be passed every time, instead to be captured once by way of closure\nexport const $resolveErrorResult = <CallApiResult>($info: { error?: unknown; options: ExtraOptions }) => {\n\tconst { error, options } = $info;\n\n\ttype ErrorInfo = {\n\t\tresponse?: Response;\n\t\terrorData?: unknown;\n\t\tmessage?: string;\n\t};\n\n\tconst resolveErrorResult = (info: ErrorInfo = {}): CallApiResult => {\n\t\tconst { errorData, message, response } = info;\n\n\t\tconst shouldThrowOnError = isFunction(options.throwOnError)\n\t\t\t? options.throwOnError(error as Error)\n\t\t\t: options.throwOnError;\n\n\t\tif (shouldThrowOnError) {\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn {\n\t\t\tdataInfo: null,\n\t\t\terrorInfo: {\n\t\t\t\terrorName: (error as PossibleErrorObject)?.name ?? \"UnknownError\",\n\t\t\t\tmessage: message ?? (error as PossibleErrorObject)?.message ?? options.defaultErrorMessage,\n\t\t\t\t...(Boolean(errorData) && { errorData }),\n\t\t\t},\n\t\t\tresponse: response ?? null,\n\t\t} as CallApiResult;\n\t};\n\n\treturn resolveErrorResult;\n};\nexport const isHTTPErrorInfo = (\n\terrorInfo: Record<string, unknown> | null\n): errorInfo is { errorName: \"HTTPError\" } => isObject(errorInfo) && errorInfo.errorName === \"HTTPError\";\n\ntype ErrorDetails<TErrorResponse> = {\n\tresponse: Response & { errorData: TErrorResponse };\n\tdefaultErrorMessage: string;\n};\n\ntype ErrorOptions = {\n\tcause?: unknown;\n};\n\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\n\n\toverride name = \"HTTPError\" as const;\n\n\tisHTTPError = true;\n\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\n\t\tconst { defaultErrorMessage, response } = errorDetails;\n\n\t\tsuper((response.errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\n\n\t\tthis.response = response;\n\t}\n}\n\nexport const isHTTPErrorInstance = <TErrorResponse>(\n\terror: unknown\n): error is HTTPError<TErrorResponse> => {\n\treturn (\n\t\terror instanceof HTTPError ||\n\t\t(isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\n\t);\n};\n\nexport const wait = (delay: number) => {\n\tif (delay === 0) return;\n\n\tconst { promise, resolve } = Promise.withResolvers();\n\n\tsetTimeout(resolve, delay);\n\n\treturn promise;\n};\n\nconst isArray = <TArray>(value: unknown): value is TArray[] => Array.isArray(value);\n\nexport const isFormData = (value: unknown) => value instanceof FormData;\n\nexport const isObject = <TObject extends Record<string, unknown>>(value: unknown): value is TObject => {\n\treturn typeof value === \"object\" && value !== null && !isFormData(value) && !Array.isArray(value);\n};\n\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\n\ttypeof value === \"function\";\n"]}
1
+ {"version":3,"sources":["../src/utils.ts"],"names":["isArray","isFunction","isObject","toQueryString","params","mergeUrlWithParams","url","paramsString","objectifyHeaders","headers","retryCodesLookup","defaultRetryCodes","defaultRetryMethods","fetchSpecificKeys","omitKeys","initialObject","keysToOmit","arrayFromFilteredObject","key","pickKeys","keysToPick","keysToPickSet","filteredArray","objectKey","splitConfig","config","handleResponseType","response","parser","getResponseData","responseType","RESPONSE_TYPE_LOOKUP","resolveSuccessResult","info","options","successData","apiDetails","$resolveErrorResult","$info","error","errorData","message","isHTTPError","HTTPError","errorDetails","errorOptions","defaultErrorMessage","isHTTPErrorInstance","waitUntil","delay","promise","resolve"],"mappings":"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","sourcesContent":["import { isArray, isFunction, isObject } from \"./typeof\";\nimport type {\n\t$BaseRequestOptions,\n\t$RequestOptions,\n\tApiErrorVariant,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tPossibleErrorObject,\n} from \"./types\";\n\ntype ToQueryStringFn = {\n\t(params: Required<ExtraOptions>[\"query\"]): string;\n\t(params: ExtraOptions[\"query\"]): string | null;\n};\n\nexport const toQueryString: ToQueryStringFn = (params) => {\n\tif (!params) {\n\t\tconsole.error(\"No query params provided\");\n\t\treturn null as never;\n\t}\n\n\treturn new URLSearchParams(params as Record<string, string>).toString();\n};\n\nexport const mergeUrlWithParams = (url: string, params: ExtraOptions[\"query\"]): string => {\n\tif (!params) {\n\t\treturn url;\n\t}\n\n\tconst paramsString = toQueryString(params);\n\n\tif (url.includes(\"?\") && !url.endsWith(\"?\")) {\n\t\treturn `${url}&${paramsString}`;\n\t}\n\n\tif (url.endsWith(\"?\")) {\n\t\treturn `${url}${paramsString}`;\n\t}\n\n\treturn `${url}?${paramsString}`;\n};\n\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\n\tif (!headers || isObject(headers)) {\n\t\treturn headers;\n\t}\n\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\n};\n\nconst retryCodesLookup = {\n\t408: \"Request Timeout\",\n\t409: \"Conflict\",\n\t425: \"Too Early\",\n\t429: \"Too Many Requests\",\n\t500: \"Internal Server Error\",\n\t502: \"Bad Gateway\",\n\t503: \"Service Unavailable\",\n\t504: \"Gateway Timeout\",\n};\n\nexport const defaultRetryCodes: Required<BaseConfig>[\"retryCodes\"] =\n\tObject.keys(retryCodesLookup).map(Number);\n\nexport const defaultRetryMethods: Required<BaseConfig>[\"retryMethods\"] = [\"GET\"];\n\nexport const fetchSpecificKeys = [\n\t\"body\",\n\t\"integrity\",\n\t\"method\",\n\t\"headers\",\n\t\"signal\",\n\t\"cache\",\n\t\"redirect\",\n\t\"window\",\n\t\"credentials\",\n\t\"keepalive\",\n\t\"referrer\",\n\t\"priority\",\n\t\"mode\",\n\t\"referrerPolicy\",\n] satisfies Array<keyof FetchConfig>;\n\nconst omitKeys = <TObject extends Record<string, unknown>, const TOmitArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToOmit: TOmitArray\n) => {\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\n\t\t([key]) => !keysToOmit.includes(key)\n\t);\n\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\n\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\n};\n\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToPick: TPickArray\n) => {\n\tconst keysToPickSet = new Set(keysToPick);\n\n\tconst arrayFromInitObject = Object.entries(initialObject);\n\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\n\n\tconst updatedObject = Object.fromEntries(filteredArray);\n\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\n};\n\nexport const splitConfig = <TObject extends object>(\n\tconfig: TObject\n): [\"body\" extends keyof TObject ? $RequestOptions : $BaseRequestOptions, ExtraOptions] => [\n\tpickKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n\tomitKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n];\n\nexport const handleResponseType = <TResponse>(\n\tresponse: Response,\n\tparser?: Required<ExtraOptions>[\"responseParser\"]\n) => ({\n\tjson: async () => {\n\t\tif (parser) {\n\t\t\treturn parser(await response.text());\n\t\t}\n\n\t\treturn response.json() as Promise<TResponse>;\n\t},\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\n\tblob: () => response.blob() as Promise<TResponse>,\n\tformData: () => response.formData() as Promise<TResponse>,\n\ttext: () => response.text() as Promise<TResponse>,\n});\n\nexport const getResponseData = <TResponse>(\n\tresponse: Response,\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\n\tparser: ExtraOptions[\"responseParser\"]\n) => {\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\n\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\n\t}\n\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\n};\n\ntype data = {\n\tsuccessData: unknown;\n\toptions: ExtraOptions;\n\tresponse: Response;\n};\n\n// == The CallApiResult type is used to cast all return statements due to a design limitation in ts.\n// LINK - See https://www.zhenghao.io/posts/type-functions for more info\nexport const resolveSuccessResult = <CallApiResult>(info: data): CallApiResult => {\n\tconst { options, response, successData } = info;\n\n\tconst apiDetails = {\n\t\tdata: successData,\n\t\terrorInfo: null,\n\t\tresponse,\n\t};\n\n\tif (options.resultMode === undefined || options.resultMode === \"all\") {\n\t\treturn apiDetails as CallApiResult;\n\t}\n\n\treturn {\n\t\tonlySuccess: apiDetails.data,\n\t\tonlyError: apiDetails.errorInfo,\n\t\tonlyResponse: apiDetails.response,\n\t}[options.resultMode] as CallApiResult;\n};\n\n// == Using curring here so error and options are not required to be passed every time, instead to be captured once by way of closure\nexport const $resolveErrorResult = <CallApiResult>($info: { error?: unknown; options: ExtraOptions }) => {\n\tconst { error, options } = $info;\n\n\ttype ErrorInfo = {\n\t\tresponse?: Response;\n\t\terrorData?: unknown;\n\t\tmessage?: string;\n\t};\n\n\tconst resolveErrorResult = (info: ErrorInfo = {}): CallApiResult => {\n\t\tconst { errorData, message, response } = info;\n\n\t\tconst shouldThrowOnError = isFunction(options.throwOnError)\n\t\t\t? options.throwOnError(error as Error)\n\t\t\t: options.throwOnError;\n\n\t\tif (shouldThrowOnError) {\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn {\n\t\t\tdata: null,\n\t\t\terror: {\n\t\t\t\terrorName: (error as PossibleErrorObject)?.name ?? \"UnknownError\",\n\t\t\t\terrorData: errorData ?? null,\n\t\t\t\tmessage: message ?? (error as PossibleErrorObject)?.message ?? options.defaultErrorMessage,\n\t\t\t},\n\t\t\tresponse: response ?? null,\n\t\t} as CallApiResult;\n\t};\n\n\treturn resolveErrorResult;\n};\n\nexport const isHTTPError = <TErrorData>(error: ApiErrorVariant<TErrorData>[\"error\"] | null) => {\n\treturn isObject(error) && error.errorName === \"HTTPError\";\n};\n\ntype ErrorDetails<TErrorResponse> = {\n\tresponse: Response & { errorData: TErrorResponse };\n\tdefaultErrorMessage: string;\n};\n\ntype ErrorOptions = {\n\tcause?: unknown;\n};\n\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\n\n\toverride name = \"HTTPError\" as const;\n\n\tisHTTPError = true;\n\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\n\t\tconst { defaultErrorMessage, response } = errorDetails;\n\n\t\tsuper((response.errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\n\n\t\tthis.response = response;\n\t}\n}\n\n// prettier-ignore\nexport const isHTTPErrorInstance = <TErrorResponse>(\n\terror: unknown\n): error is HTTPError<TErrorResponse> => {\n\treturn (\n\t\terror instanceof HTTPError || (isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\n\t);\n};\n\nexport const waitUntil = (delay: number) => {\n\tif (delay === 0) return;\n\n\tconst { promise, resolve } = Promise.withResolvers();\n\n\tsetTimeout(resolve, delay);\n\n\treturn promise;\n};\n"]}
package/dist/utils.d.cts CHANGED
@@ -1 +1 @@
1
- export { $ as $resolveErrorResult, H as HTTPError, d as defaultRetryCodes, b as defaultRetryMethods, f as fetchSpecificKeys, g as getResponseData, h as handleResponseType, c as isFormData, j as isFunction, i as isHTTPErrorInfo, a as isHTTPErrorInstance, e as isObject, m as mergeUrlWithParams, o as objectifyHeaders, r as resolveSuccessResult, s as splitConfig, w as wait } from './types-B8arQl4O.cjs';
1
+ export { j as $resolveErrorResult, H as HTTPError, d as defaultRetryCodes, e as defaultRetryMethods, f as fetchSpecificKeys, g as getResponseData, h as handleResponseType, i as isHTTPError, c as isHTTPErrorInstance, m as mergeUrlWithParams, o as objectifyHeaders, r as resolveSuccessResult, s as splitConfig, t as toQueryString, w as waitUntil } from './types-CGXvcfe9.cjs';
package/dist/utils.d.ts CHANGED
@@ -1 +1 @@
1
- export { $ as $resolveErrorResult, H as HTTPError, d as defaultRetryCodes, b as defaultRetryMethods, f as fetchSpecificKeys, g as getResponseData, h as handleResponseType, c as isFormData, j as isFunction, i as isHTTPErrorInfo, a as isHTTPErrorInstance, e as isObject, m as mergeUrlWithParams, o as objectifyHeaders, r as resolveSuccessResult, s as splitConfig, w as wait } from './types-B8arQl4O.js';
1
+ export { j as $resolveErrorResult, H as HTTPError, d as defaultRetryCodes, e as defaultRetryMethods, f as fetchSpecificKeys, g as getResponseData, h as handleResponseType, i as isHTTPError, c as isHTTPErrorInstance, m as mergeUrlWithParams, o as objectifyHeaders, r as resolveSuccessResult, s as splitConfig, t as toQueryString, w as waitUntil } from './types-CGXvcfe9.js';
package/dist/utils.js CHANGED
@@ -1,5 +1,7 @@
1
- const m=(e,r)=>{if(!r)return e;const o=new URLSearchParams(r).toString();return e.includes("?")&&!e.endsWith("?")?`${e}&${o}`:e.endsWith("?")?`${e}${o}`:`${e}?${o}`},b=e=>!e||i(e)?e:Object.fromEntries(d(e)?e:e.entries()),p={408:"Request Timeout",409:"Conflict",425:"Too Early",429:"Too Many Requests",500:"Internal Server Error",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout"},g=Object.keys(p).map(Number),j=["GET"],c=["body","integrity","method","headers","signal","cache","redirect","window","credentials","keepalive","referrer","priority","mode","referrerPolicy"],l=(e,r)=>{const o=Object.entries(e).filter(([s])=>!r.includes(s));return Object.fromEntries(o)},T=(e,r)=>{const o=new Set(r),s=Object.entries(e).filter(([a])=>o.has(a));return Object.fromEntries(s)},x=e=>[T(e,c),l(e,c)],f=(e,r)=>({json:async()=>r?r(await e.text()):e.json(),arrayBuffer:()=>e.arrayBuffer(),blob:()=>e.blob(),formData:()=>e.formData(),text:()=>e.text()}),w=(e,r,o)=>{const t=f(e,o);if(!Object.hasOwn(t,r))throw new Error(`Invalid response type: ${r}`);return t[r]()},k=e=>{const{options:r,response:o,successData:t}=e,s={dataInfo:t,errorInfo:null,response:o};return r.resultMode===void 0||r.resultMode==="all"?s:{onlySuccess:s.dataInfo,onlyError:s.errorInfo,onlyResponse:s.response}[r.resultMode]},P=e=>{const{error:r,options:o}=e;return (s={})=>{const{errorData:n,message:a,response:u}=s;if(E(o.throwOnError)?o.throwOnError(r):o.throwOnError)throw r;return {dataInfo:null,errorInfo:{errorName:r?.name??"UnknownError",message:a??r?.message??o.defaultErrorMessage,...!!n&&{errorData:n}},response:u??null}}},A=e=>i(e)&&e.errorName==="HTTPError";class y extends Error{response;name="HTTPError";isHTTPError=!0;constructor(r,o){const{defaultErrorMessage:t,response:s}=r;super(s.errorData.message??t,o),this.response=s;}}const h=e=>e instanceof y||i(e)&&e.name==="HTTPError"&&e.isHTTPError===!0,C=e=>{if(e===0)return;const{promise:r,resolve:o}=Promise.withResolvers();return setTimeout(o,e),r},d=e=>Array.isArray(e),R=e=>e instanceof FormData,i=e=>typeof e=="object"&&e!==null&&!R(e)&&!Array.isArray(e),E=e=>typeof e=="function";
1
+ import { isObject, isArray, isFunction } from './typeof';
2
2
 
3
- export { P as $resolveErrorResult, y as HTTPError, g as defaultRetryCodes, j as defaultRetryMethods, c as fetchSpecificKeys, w as getResponseData, f as handleResponseType, R as isFormData, E as isFunction, A as isHTTPErrorInfo, h as isHTTPErrorInstance, i as isObject, m as mergeUrlWithParams, b as objectifyHeaders, k as resolveSuccessResult, x as splitConfig, C as wait };
3
+ const d=r=>r?new URLSearchParams(r).toString():(console.error("No query params provided"),null),b=(r,e)=>{if(!e)return r;const t=d(e);return r.includes("?")&&!r.endsWith("?")?`${r}&${t}`:r.endsWith("?")?`${r}${t}`:`${r}?${t}`},g=r=>!r||isObject(r)?r:Object.fromEntries(isArray(r)?r:r.entries()),T={408:"Request Timeout",409:"Conflict",425:"Too Early",429:"Too Many Requests",500:"Internal Server Error",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout"},x=Object.keys(T).map(Number),j=["GET"],c=["body","integrity","method","headers","signal","cache","redirect","window","credentials","keepalive","referrer","priority","mode","referrerPolicy"],E=(r,e)=>{const t=Object.entries(r).filter(([s])=>!e.includes(s));return Object.fromEntries(t)},y=(r,e)=>{const t=new Set(e),s=Object.entries(r).filter(([n])=>t.has(n));return Object.fromEntries(s)},P=r=>[y(r,c),E(r,c)],R=(r,e)=>({json:async()=>e?e(await r.text()):r.json(),arrayBuffer:()=>r.arrayBuffer(),blob:()=>r.blob(),formData:()=>r.formData(),text:()=>r.text()}),w=(r,e,t)=>{const o=R(r,t);if(!Object.hasOwn(o,e))throw new Error(`Invalid response type: ${e}`);return o[e]()},k=r=>{const{options:e,response:t,successData:o}=r,s={data:o,errorInfo:null,response:t};return e.resultMode===void 0||e.resultMode==="all"?s:{onlySuccess:s.data,onlyError:s.errorInfo,onlyResponse:s.response}[e.resultMode]},h=r=>{const{error:e,options:t}=r;return (s={})=>{const{errorData:i,message:n,response:p}=s;if(isFunction(t.throwOnError)?t.throwOnError(e):t.throwOnError)throw e;return {data:null,error:{errorName:e?.name??"UnknownError",errorData:i??null,message:n??e?.message??t.defaultErrorMessage},response:p??null}}},A=r=>isObject(r)&&r.errorName==="HTTPError";class O extends Error{response;name="HTTPError";isHTTPError=!0;constructor(e,t){const{defaultErrorMessage:o,response:s}=e;super(s.errorData.message??o,t),this.response=s;}}const C=r=>r instanceof O||isObject(r)&&r.name==="HTTPError"&&r.isHTTPError===!0,v=r=>{if(r===0)return;const{promise:e,resolve:t}=Promise.withResolvers();return setTimeout(t,r),e};
4
+
5
+ export { h as $resolveErrorResult, O as HTTPError, x as defaultRetryCodes, j as defaultRetryMethods, c as fetchSpecificKeys, w as getResponseData, R as handleResponseType, A as isHTTPError, C as isHTTPErrorInstance, b as mergeUrlWithParams, g as objectifyHeaders, k as resolveSuccessResult, P as splitConfig, d as toQueryString, v as waitUntil };
4
6
  //# sourceMappingURL=out.js.map
5
7
  //# sourceMappingURL=utils.js.map
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts"],"names":["mergeUrlWithParams","url","params","paramsString","objectifyHeaders","headers","isObject","isArray","retryCodesLookup","defaultRetryCodes","defaultRetryMethods","fetchSpecificKeys","omitKeys","initialObject","keysToOmit","arrayFromFilteredObject","key","pickKeys","keysToPick","keysToPickSet","filteredArray","objectKey","splitConfig","config","handleResponseType","response","parser","getResponseData","responseType","RESPONSE_TYPE_LOOKUP","resolveSuccessResult","info","options","successData","apiDetails","$resolveErrorResult","$info","error","errorData","message","isFunction","isHTTPErrorInfo","errorInfo","HTTPError","errorDetails","errorOptions","defaultErrorMessage","isHTTPErrorInstance","wait","delay","promise","resolve","value","isFormData"],"mappings":"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","sourcesContent":["import type { AnyFunction } from \"./type-helpers\";\nimport type {\n\t$BaseRequestConfig,\n\t$RequestConfig,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tPossibleErrorObject,\n} from \"./types\";\n\nexport const mergeUrlWithParams = (url: string, params: ExtraOptions[\"query\"]): string => {\n\tif (!params) {\n\t\treturn url;\n\t}\n\n\tconst paramsString = new URLSearchParams(params as Record<string, string>).toString();\n\n\tif (url.includes(\"?\") && !url.endsWith(\"?\")) {\n\t\treturn `${url}&${paramsString}`;\n\t}\n\n\tif (url.endsWith(\"?\")) {\n\t\treturn `${url}${paramsString}`;\n\t}\n\n\treturn `${url}?${paramsString}`;\n};\n\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\n\tif (!headers || isObject(headers)) {\n\t\treturn headers;\n\t}\n\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\n};\n\nconst retryCodesLookup = {\n\t408: \"Request Timeout\",\n\t409: \"Conflict\",\n\t425: \"Too Early\",\n\t429: \"Too Many Requests\",\n\t500: \"Internal Server Error\",\n\t502: \"Bad Gateway\",\n\t503: \"Service Unavailable\",\n\t504: \"Gateway Timeout\",\n};\n\nexport const defaultRetryCodes: Required<BaseConfig>[\"retryCodes\"] =\n\tObject.keys(retryCodesLookup).map(Number);\n\nexport const defaultRetryMethods: Required<BaseConfig>[\"retryMethods\"] = [\"GET\"];\n\nexport const fetchSpecificKeys = [\n\t\"body\",\n\t\"integrity\",\n\t\"method\",\n\t\"headers\",\n\t\"signal\",\n\t\"cache\",\n\t\"redirect\",\n\t\"window\",\n\t\"credentials\",\n\t\"keepalive\",\n\t\"referrer\",\n\t\"priority\",\n\t\"mode\",\n\t\"referrerPolicy\",\n] satisfies Array<keyof FetchConfig>;\n\nconst omitKeys = <TObject extends Record<string, unknown>, const TOmitArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToOmit: TOmitArray\n) => {\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\n\t\t([key]) => !keysToOmit.includes(key)\n\t);\n\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\n\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\n};\n\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToPick: TPickArray\n) => {\n\tconst keysToPickSet = new Set(keysToPick);\n\n\tconst arrayFromInitObject = Object.entries(initialObject);\n\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\n\n\tconst updatedObject = Object.fromEntries(filteredArray);\n\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\n};\n\nexport const splitConfig = <TObject extends object>(\n\tconfig: TObject\n): [\"body\" extends keyof TObject ? $RequestConfig : $BaseRequestConfig, ExtraOptions] => [\n\tpickKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n\tomitKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n];\n\nexport const handleResponseType = <TResponse>(\n\tresponse: Response,\n\tparser?: Required<ExtraOptions>[\"responseParser\"]\n) => ({\n\tjson: async () => {\n\t\tif (parser) {\n\t\t\treturn parser<TResponse>(await response.text());\n\t\t}\n\n\t\treturn response.json() as Promise<TResponse>;\n\t},\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\n\tblob: () => response.blob() as Promise<TResponse>,\n\tformData: () => response.formData() as Promise<TResponse>,\n\ttext: () => response.text() as Promise<TResponse>,\n});\n\nexport const getResponseData = <TResponse>(\n\tresponse: Response,\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\n\tparser: ExtraOptions[\"responseParser\"]\n) => {\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\n\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\n\t}\n\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\n};\n\ntype DataInfo = {\n\tsuccessData: unknown;\n\toptions: ExtraOptions;\n\tresponse: Response;\n};\n\n// == The CallApiResult type is used to cast all return statements due to a design limitation in ts.\n// LINK - See https://www.zhenghao.io/posts/type-functions for more info\nexport const resolveSuccessResult = <CallApiResult>(info: DataInfo): CallApiResult => {\n\tconst { options, response, successData } = info;\n\n\tconst apiDetails = { dataInfo: successData, errorInfo: null, response };\n\n\tif (options.resultMode === undefined || options.resultMode === \"all\") {\n\t\treturn apiDetails as CallApiResult;\n\t}\n\n\treturn {\n\t\tonlySuccess: apiDetails.dataInfo,\n\t\tonlyError: apiDetails.errorInfo,\n\t\tonlyResponse: apiDetails.response,\n\t}[options.resultMode] as CallApiResult;\n};\n\n// == Using curring here so error and options are not required to be passed every time, instead to be captured once by way of closure\nexport const $resolveErrorResult = <CallApiResult>($info: { error?: unknown; options: ExtraOptions }) => {\n\tconst { error, options } = $info;\n\n\ttype ErrorInfo = {\n\t\tresponse?: Response;\n\t\terrorData?: unknown;\n\t\tmessage?: string;\n\t};\n\n\tconst resolveErrorResult = (info: ErrorInfo = {}): CallApiResult => {\n\t\tconst { errorData, message, response } = info;\n\n\t\tconst shouldThrowOnError = isFunction(options.throwOnError)\n\t\t\t? options.throwOnError(error as Error)\n\t\t\t: options.throwOnError;\n\n\t\tif (shouldThrowOnError) {\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn {\n\t\t\tdataInfo: null,\n\t\t\terrorInfo: {\n\t\t\t\terrorName: (error as PossibleErrorObject)?.name ?? \"UnknownError\",\n\t\t\t\tmessage: message ?? (error as PossibleErrorObject)?.message ?? options.defaultErrorMessage,\n\t\t\t\t...(Boolean(errorData) && { errorData }),\n\t\t\t},\n\t\t\tresponse: response ?? null,\n\t\t} as CallApiResult;\n\t};\n\n\treturn resolveErrorResult;\n};\nexport const isHTTPErrorInfo = (\n\terrorInfo: Record<string, unknown> | null\n): errorInfo is { errorName: \"HTTPError\" } => isObject(errorInfo) && errorInfo.errorName === \"HTTPError\";\n\ntype ErrorDetails<TErrorResponse> = {\n\tresponse: Response & { errorData: TErrorResponse };\n\tdefaultErrorMessage: string;\n};\n\ntype ErrorOptions = {\n\tcause?: unknown;\n};\n\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\n\n\toverride name = \"HTTPError\" as const;\n\n\tisHTTPError = true;\n\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\n\t\tconst { defaultErrorMessage, response } = errorDetails;\n\n\t\tsuper((response.errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\n\n\t\tthis.response = response;\n\t}\n}\n\nexport const isHTTPErrorInstance = <TErrorResponse>(\n\terror: unknown\n): error is HTTPError<TErrorResponse> => {\n\treturn (\n\t\terror instanceof HTTPError ||\n\t\t(isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\n\t);\n};\n\nexport const wait = (delay: number) => {\n\tif (delay === 0) return;\n\n\tconst { promise, resolve } = Promise.withResolvers();\n\n\tsetTimeout(resolve, delay);\n\n\treturn promise;\n};\n\nconst isArray = <TArray>(value: unknown): value is TArray[] => Array.isArray(value);\n\nexport const isFormData = (value: unknown) => value instanceof FormData;\n\nexport const isObject = <TObject extends Record<string, unknown>>(value: unknown): value is TObject => {\n\treturn typeof value === \"object\" && value !== null && !isFormData(value) && !Array.isArray(value);\n};\n\nexport const isFunction = <TFunction extends AnyFunction>(value: unknown): value is TFunction =>\n\ttypeof value === \"function\";\n"]}
1
+ {"version":3,"sources":["../src/utils.ts"],"names":["isArray","isFunction","isObject","toQueryString","params","mergeUrlWithParams","url","paramsString","objectifyHeaders","headers","retryCodesLookup","defaultRetryCodes","defaultRetryMethods","fetchSpecificKeys","omitKeys","initialObject","keysToOmit","arrayFromFilteredObject","key","pickKeys","keysToPick","keysToPickSet","filteredArray","objectKey","splitConfig","config","handleResponseType","response","parser","getResponseData","responseType","RESPONSE_TYPE_LOOKUP","resolveSuccessResult","info","options","successData","apiDetails","$resolveErrorResult","$info","error","errorData","message","isHTTPError","HTTPError","errorDetails","errorOptions","defaultErrorMessage","isHTTPErrorInstance","waitUntil","delay","promise","resolve"],"mappings":"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","sourcesContent":["import { isArray, isFunction, isObject } from \"./typeof\";\nimport type {\n\t$BaseRequestOptions,\n\t$RequestOptions,\n\tApiErrorVariant,\n\tBaseConfig,\n\tExtraOptions,\n\tFetchConfig,\n\tPossibleErrorObject,\n} from \"./types\";\n\ntype ToQueryStringFn = {\n\t(params: Required<ExtraOptions>[\"query\"]): string;\n\t(params: ExtraOptions[\"query\"]): string | null;\n};\n\nexport const toQueryString: ToQueryStringFn = (params) => {\n\tif (!params) {\n\t\tconsole.error(\"No query params provided\");\n\t\treturn null as never;\n\t}\n\n\treturn new URLSearchParams(params as Record<string, string>).toString();\n};\n\nexport const mergeUrlWithParams = (url: string, params: ExtraOptions[\"query\"]): string => {\n\tif (!params) {\n\t\treturn url;\n\t}\n\n\tconst paramsString = toQueryString(params);\n\n\tif (url.includes(\"?\") && !url.endsWith(\"?\")) {\n\t\treturn `${url}&${paramsString}`;\n\t}\n\n\tif (url.endsWith(\"?\")) {\n\t\treturn `${url}${paramsString}`;\n\t}\n\n\treturn `${url}?${paramsString}`;\n};\n\nexport const objectifyHeaders = (headers: RequestInit[\"headers\"]): Record<string, string> | undefined => {\n\tif (!headers || isObject(headers)) {\n\t\treturn headers;\n\t}\n\n\treturn Object.fromEntries(isArray(headers) ? headers : headers.entries());\n};\n\nconst retryCodesLookup = {\n\t408: \"Request Timeout\",\n\t409: \"Conflict\",\n\t425: \"Too Early\",\n\t429: \"Too Many Requests\",\n\t500: \"Internal Server Error\",\n\t502: \"Bad Gateway\",\n\t503: \"Service Unavailable\",\n\t504: \"Gateway Timeout\",\n};\n\nexport const defaultRetryCodes: Required<BaseConfig>[\"retryCodes\"] =\n\tObject.keys(retryCodesLookup).map(Number);\n\nexport const defaultRetryMethods: Required<BaseConfig>[\"retryMethods\"] = [\"GET\"];\n\nexport const fetchSpecificKeys = [\n\t\"body\",\n\t\"integrity\",\n\t\"method\",\n\t\"headers\",\n\t\"signal\",\n\t\"cache\",\n\t\"redirect\",\n\t\"window\",\n\t\"credentials\",\n\t\"keepalive\",\n\t\"referrer\",\n\t\"priority\",\n\t\"mode\",\n\t\"referrerPolicy\",\n] satisfies Array<keyof FetchConfig>;\n\nconst omitKeys = <TObject extends Record<string, unknown>, const TOmitArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToOmit: TOmitArray\n) => {\n\tconst arrayFromFilteredObject = Object.entries(initialObject).filter(\n\t\t([key]) => !keysToOmit.includes(key)\n\t);\n\n\tconst updatedObject = Object.fromEntries(arrayFromFilteredObject);\n\n\treturn updatedObject as Omit<TObject, keyof TOmitArray>;\n};\n\nconst pickKeys = <TObject extends Record<string, unknown>, const TPickArray extends Array<keyof TObject>>(\n\tinitialObject: TObject,\n\tkeysToPick: TPickArray\n) => {\n\tconst keysToPickSet = new Set(keysToPick);\n\n\tconst arrayFromInitObject = Object.entries(initialObject);\n\n\tconst filteredArray = arrayFromInitObject.filter(([objectKey]) => keysToPickSet.has(objectKey));\n\n\tconst updatedObject = Object.fromEntries(filteredArray);\n\n\treturn updatedObject as Pick<TObject, TPickArray[number]>;\n};\n\nexport const splitConfig = <TObject extends object>(\n\tconfig: TObject\n): [\"body\" extends keyof TObject ? $RequestOptions : $BaseRequestOptions, ExtraOptions] => [\n\tpickKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n\tomitKeys(config as Record<string, unknown>, fetchSpecificKeys) as never,\n];\n\nexport const handleResponseType = <TResponse>(\n\tresponse: Response,\n\tparser?: Required<ExtraOptions>[\"responseParser\"]\n) => ({\n\tjson: async () => {\n\t\tif (parser) {\n\t\t\treturn parser(await response.text());\n\t\t}\n\n\t\treturn response.json() as Promise<TResponse>;\n\t},\n\tarrayBuffer: () => response.arrayBuffer() as Promise<TResponse>,\n\tblob: () => response.blob() as Promise<TResponse>,\n\tformData: () => response.formData() as Promise<TResponse>,\n\ttext: () => response.text() as Promise<TResponse>,\n});\n\nexport const getResponseData = <TResponse>(\n\tresponse: Response,\n\tresponseType: keyof ReturnType<typeof handleResponseType>,\n\tparser: ExtraOptions[\"responseParser\"]\n) => {\n\tconst RESPONSE_TYPE_LOOKUP = handleResponseType<TResponse>(response, parser);\n\n\tif (!Object.hasOwn(RESPONSE_TYPE_LOOKUP, responseType)) {\n\t\tthrow new Error(`Invalid response type: ${responseType}`);\n\t}\n\n\treturn RESPONSE_TYPE_LOOKUP[responseType]();\n};\n\ntype data = {\n\tsuccessData: unknown;\n\toptions: ExtraOptions;\n\tresponse: Response;\n};\n\n// == The CallApiResult type is used to cast all return statements due to a design limitation in ts.\n// LINK - See https://www.zhenghao.io/posts/type-functions for more info\nexport const resolveSuccessResult = <CallApiResult>(info: data): CallApiResult => {\n\tconst { options, response, successData } = info;\n\n\tconst apiDetails = {\n\t\tdata: successData,\n\t\terrorInfo: null,\n\t\tresponse,\n\t};\n\n\tif (options.resultMode === undefined || options.resultMode === \"all\") {\n\t\treturn apiDetails as CallApiResult;\n\t}\n\n\treturn {\n\t\tonlySuccess: apiDetails.data,\n\t\tonlyError: apiDetails.errorInfo,\n\t\tonlyResponse: apiDetails.response,\n\t}[options.resultMode] as CallApiResult;\n};\n\n// == Using curring here so error and options are not required to be passed every time, instead to be captured once by way of closure\nexport const $resolveErrorResult = <CallApiResult>($info: { error?: unknown; options: ExtraOptions }) => {\n\tconst { error, options } = $info;\n\n\ttype ErrorInfo = {\n\t\tresponse?: Response;\n\t\terrorData?: unknown;\n\t\tmessage?: string;\n\t};\n\n\tconst resolveErrorResult = (info: ErrorInfo = {}): CallApiResult => {\n\t\tconst { errorData, message, response } = info;\n\n\t\tconst shouldThrowOnError = isFunction(options.throwOnError)\n\t\t\t? options.throwOnError(error as Error)\n\t\t\t: options.throwOnError;\n\n\t\tif (shouldThrowOnError) {\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn {\n\t\t\tdata: null,\n\t\t\terror: {\n\t\t\t\terrorName: (error as PossibleErrorObject)?.name ?? \"UnknownError\",\n\t\t\t\terrorData: errorData ?? null,\n\t\t\t\tmessage: message ?? (error as PossibleErrorObject)?.message ?? options.defaultErrorMessage,\n\t\t\t},\n\t\t\tresponse: response ?? null,\n\t\t} as CallApiResult;\n\t};\n\n\treturn resolveErrorResult;\n};\n\nexport const isHTTPError = <TErrorData>(error: ApiErrorVariant<TErrorData>[\"error\"] | null) => {\n\treturn isObject(error) && error.errorName === \"HTTPError\";\n};\n\ntype ErrorDetails<TErrorResponse> = {\n\tresponse: Response & { errorData: TErrorResponse };\n\tdefaultErrorMessage: string;\n};\n\ntype ErrorOptions = {\n\tcause?: unknown;\n};\n\nexport class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {\n\tresponse: ErrorDetails<TErrorResponse>[\"response\"];\n\n\toverride name = \"HTTPError\" as const;\n\n\tisHTTPError = true;\n\n\tconstructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions) {\n\t\tconst { defaultErrorMessage, response } = errorDetails;\n\n\t\tsuper((response.errorData as { message?: string }).message ?? defaultErrorMessage, errorOptions);\n\n\t\tthis.response = response;\n\t}\n}\n\n// prettier-ignore\nexport const isHTTPErrorInstance = <TErrorResponse>(\n\terror: unknown\n): error is HTTPError<TErrorResponse> => {\n\treturn (\n\t\terror instanceof HTTPError || (isObject(error) && error.name === \"HTTPError\" && error.isHTTPError === true)\n\t);\n};\n\nexport const waitUntil = (delay: number) => {\n\tif (delay === 0) return;\n\n\tconst { promise, resolve } = Promise.withResolvers();\n\n\tsetTimeout(resolve, delay);\n\n\treturn promise;\n};\n"]}
package/package.json CHANGED
@@ -1,10 +1,9 @@
1
1
  {
2
2
  "name": "@zayne-labs/callapi",
3
- "version": "0.0.6",
3
+ "version": "0.1.0",
4
4
  "type": "module",
5
5
  "description": "A lightweight wrapper over fetch with quality of life improvements like built-in request cancellation, retries, interceptors and more",
6
- "main": "dist/index.cjs",
7
- "module": "dist/index.js",
6
+ "main": "dist/index.js",
8
7
  "types": "./dist/index.d.ts",
9
8
  "exports": {
10
9
  ".": {
@@ -1,147 +0,0 @@
1
- type AnyString = string & {
2
- placeholder?: never;
3
- };
4
- type AnyNumber = number & {
5
- placeholder?: never;
6
- };
7
- type AnyFunction = (...args: any[]) => any;
8
-
9
- declare const mergeUrlWithParams: (url: string, params: ExtraOptions["query"]) => string;
10
- declare const objectifyHeaders: (headers: RequestInit["headers"]) => Record<string, string> | undefined;
11
- declare const defaultRetryCodes: Required<BaseConfig>["retryCodes"];
12
- declare const defaultRetryMethods: Required<BaseConfig>["retryMethods"];
13
- declare const fetchSpecificKeys: ("headers" | "body" | "method" | "cache" | "credentials" | "integrity" | "keepalive" | "mode" | "priority" | "redirect" | "referrer" | "referrerPolicy" | "signal" | "window")[];
14
- declare const splitConfig: <TObject extends object>(config: TObject) => ["body" extends keyof TObject ? $RequestConfig : $BaseRequestConfig, ExtraOptions];
15
- declare const handleResponseType: <TResponse>(response: Response, parser?: Required<ExtraOptions>["responseParser"]) => {
16
- json: () => Promise<TResponse>;
17
- arrayBuffer: () => Promise<TResponse>;
18
- blob: () => Promise<TResponse>;
19
- formData: () => Promise<TResponse>;
20
- text: () => Promise<TResponse>;
21
- };
22
- declare const getResponseData: <TResponse>(response: Response, responseType: keyof ReturnType<typeof handleResponseType>, parser: ExtraOptions["responseParser"]) => Promise<TResponse>;
23
- type DataInfo = {
24
- successData: unknown;
25
- options: ExtraOptions;
26
- response: Response;
27
- };
28
- declare const resolveSuccessResult: <CallApiResult>(info: DataInfo) => CallApiResult;
29
- declare const $resolveErrorResult: <CallApiResult>($info: {
30
- error?: unknown;
31
- options: ExtraOptions;
32
- }) => (info?: {
33
- response?: Response;
34
- errorData?: unknown;
35
- message?: string;
36
- }) => CallApiResult;
37
- declare const isHTTPErrorInfo: (errorInfo: Record<string, unknown> | null) => errorInfo is {
38
- errorName: "HTTPError";
39
- };
40
- type ErrorDetails<TErrorResponse> = {
41
- response: Response & {
42
- errorData: TErrorResponse;
43
- };
44
- defaultErrorMessage: string;
45
- };
46
- type ErrorOptions = {
47
- cause?: unknown;
48
- };
49
- declare class HTTPError<TErrorResponse = Record<string, unknown>> extends Error {
50
- response: ErrorDetails<TErrorResponse>["response"];
51
- name: "HTTPError";
52
- isHTTPError: boolean;
53
- constructor(errorDetails: ErrorDetails<TErrorResponse>, errorOptions?: ErrorOptions);
54
- }
55
- declare const isHTTPErrorInstance: <TErrorResponse>(error: unknown) => error is HTTPError<TErrorResponse>;
56
- declare const wait: (delay: number) => Promise<unknown> | undefined;
57
- declare const isFormData: (value: unknown) => value is FormData;
58
- declare const isObject: <TObject extends Record<string, unknown>>(value: unknown) => value is TObject;
59
- declare const isFunction: <TFunction extends AnyFunction>(value: unknown) => value is TFunction;
60
-
61
- type $RequestConfig = Pick<FetchConfig, (typeof fetchSpecificKeys)[number]>;
62
- type $BaseRequestConfig = Omit<$RequestConfig, "body">;
63
- type ExtraOptions<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultStyleUnion = ResultStyleUnion> = {
64
- body?: Record<string, unknown> | RequestInit["body"];
65
- method?: "GET" | "POST" | "PATCH" | "PUT" | "DELETE" | AnyString;
66
- query?: Record<string, string | number | boolean>;
67
- bodySerializer?: (bodyData: Record<string, unknown>) => string;
68
- responseParser?: {
69
- (data: string): unknown;
70
- <TData>(data: string): TData;
71
- };
72
- resultMode?: TBaseResultMode;
73
- cancelRedundantRequests?: boolean;
74
- baseURL?: string;
75
- timeout?: number;
76
- defaultErrorMessage?: string;
77
- throwOnError?: boolean | ((error?: Error | HTTPError<TBaseErrorData>) => boolean);
78
- responseType?: keyof ReturnType<typeof handleResponseType>;
79
- retries?: number;
80
- retryDelay?: number;
81
- retryCodes?: Array<409 | 425 | 429 | 500 | 502 | 503 | 504 | AnyNumber>;
82
- retryMethods?: Array<"GET" | "POST" | "PATCH" | "DELETE" | AnyString>;
83
- meta?: Record<string, unknown>;
84
- onRequest?: (requestContext: {
85
- request: $RequestConfig;
86
- options: ExtraOptions;
87
- }) => void | Promise<void>;
88
- onRequestError?: (requestContext: {
89
- request: $RequestConfig;
90
- error: Error;
91
- options: ExtraOptions;
92
- }) => void | Promise<void>;
93
- onResponse?: (successContext: {
94
- request: $RequestConfig;
95
- response: Response & {
96
- data: TBaseData;
97
- };
98
- options: ExtraOptions;
99
- }) => void | Promise<void>;
100
- onResponseError?: (errorContext: {
101
- request: $RequestConfig;
102
- response: Response & {
103
- errorData: TBaseErrorData;
104
- };
105
- options: ExtraOptions;
106
- }) => void | Promise<void>;
107
- };
108
- interface FetchConfig<TData = unknown, TErrorData = unknown, TResultMode extends ResultStyleUnion = undefined> extends Omit<RequestInit, "method" | "body">, ExtraOptions<TData, TErrorData, TResultMode> {
109
- }
110
- interface BaseConfig<TBaseData = unknown, TBaseErrorData = unknown, TBaseResultMode extends ResultStyleUnion = undefined> extends Omit<FetchConfig<TBaseData, TBaseErrorData, TBaseResultMode>, "body"> {
111
- }
112
- type ApiSuccessVariant<TData> = {
113
- dataInfo: TData;
114
- errorInfo: null;
115
- response: Response;
116
- };
117
- type PossibleErrors = "AbortError" | "TimeoutError" | "SyntaxError" | "TypeError" | "Error" | "UnknownError";
118
- type ApiErrorVariant<TErrorData> = {
119
- dataInfo: null;
120
- errorInfo: {
121
- errorName: "HTTPError";
122
- errorData: TErrorData;
123
- message: string;
124
- };
125
- response: Response;
126
- } | {
127
- dataInfo: null;
128
- errorInfo: {
129
- errorName: PossibleErrors;
130
- message: string;
131
- };
132
- response: null;
133
- };
134
- type ResultStyleMap<TData = unknown, TErrorData = unknown> = {
135
- all: ApiSuccessVariant<TData> | ApiErrorVariant<TErrorData>;
136
- onlySuccess: TData;
137
- onlyError: TErrorData;
138
- onlyResponse: Response;
139
- };
140
- type ResultStyleUnion = {
141
- _: {
142
- [Key in keyof ResultStyleMap]: Key;
143
- }[keyof ResultStyleMap] | undefined;
144
- }["_"];
145
- type GetCallApiResult<TData, TErrorData, TResultMode> = TResultMode extends NonNullable<ResultStyleUnion> ? ResultStyleMap<TData, TErrorData>[TResultMode] : ResultStyleMap<TData, TErrorData>["all"];
146
-
147
- export { $resolveErrorResult as $, type BaseConfig as B, type FetchConfig as F, type GetCallApiResult as G, HTTPError as H, type ResultStyleUnion as R, isHTTPErrorInstance as a, defaultRetryMethods as b, isFormData as c, defaultRetryCodes as d, isObject as e, fetchSpecificKeys as f, getResponseData as g, handleResponseType as h, isHTTPErrorInfo as i, isFunction as j, mergeUrlWithParams as m, objectifyHeaders as o, resolveSuccessResult as r, splitConfig as s, wait as w };