@settlemint/sdk-utils 2.3.2-pr90f9d5ad → 2.3.2-pra0c7f3ba
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/dist/http.cjs +18 -0
- package/dist/http.cjs.map +1 -1
- package/dist/http.d.cts +6 -1
- package/dist/http.d.ts +6 -1
- package/dist/http.mjs +17 -0
- package/dist/http.mjs.map +1 -1
- package/package.json +1 -1
package/dist/http.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/http.ts
|
|
21
21
|
var http_exports = {};
|
|
22
22
|
__export(http_exports, {
|
|
23
|
+
appendHeaders: () => appendHeaders,
|
|
23
24
|
fetchWithRetry: () => fetchWithRetry,
|
|
24
25
|
graphqlFetchWithRetry: () => graphqlFetchWithRetry
|
|
25
26
|
});
|
|
@@ -83,8 +84,25 @@ async function graphqlFetchWithRetry(input, init, maxRetries = 5, initialSleepTi
|
|
|
83
84
|
initialSleepTime
|
|
84
85
|
);
|
|
85
86
|
}
|
|
87
|
+
|
|
88
|
+
// src/http/headers.ts
|
|
89
|
+
function appendHeaders(headers, additionalHeaders) {
|
|
90
|
+
const defaultHeaders = typeof headers === "function" ? headers() : headers;
|
|
91
|
+
const filteredAdditionalHeaders = Object.entries(additionalHeaders).filter(([_, value]) => value !== void 0);
|
|
92
|
+
if (Array.isArray(defaultHeaders)) {
|
|
93
|
+
return [...defaultHeaders, ...filteredAdditionalHeaders];
|
|
94
|
+
}
|
|
95
|
+
if (defaultHeaders instanceof Headers) {
|
|
96
|
+
return new Headers([...defaultHeaders, ...filteredAdditionalHeaders]);
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
...defaultHeaders,
|
|
100
|
+
...Object.fromEntries(filteredAdditionalHeaders)
|
|
101
|
+
};
|
|
102
|
+
}
|
|
86
103
|
// Annotate the CommonJS export names for ESM import in node:
|
|
87
104
|
0 && (module.exports = {
|
|
105
|
+
appendHeaders,
|
|
88
106
|
fetchWithRetry,
|
|
89
107
|
graphqlFetchWithRetry
|
|
90
108
|
});
|
package/dist/http.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/http.ts","../src/retry.ts","../src/http/fetch-with-retry.ts","../src/http/graphql-fetch-with-retry.ts"],"sourcesContent":["export { fetchWithRetry } from \"./http/fetch-with-retry.js\";\nexport { graphqlFetchWithRetry } from \"./http/graphql-fetch-with-retry.js\";\n","/**\n * Retry a function when it fails.\n * @param fn - The function to retry.\n * @param maxRetries - The maximum number of retries.\n * @param initialSleepTime - The initial time to sleep between exponential backoff retries.\n * @param stopOnError - The function to stop on error.\n * @returns The result of the function or undefined if it fails.\n * @example\n * import { retryWhenFailed } from \"@settlemint/sdk-utils\";\n * import { readFile } from \"node:fs/promises\";\n *\n * const result = await retryWhenFailed(() => readFile(\"/path/to/file.txt\"), 3, 1_000);\n */\nexport async function retryWhenFailed<T>(\n fn: () => Promise<T>,\n maxRetries = 5,\n initialSleepTime = 1_000,\n stopOnError?: (error: Error) => boolean,\n): Promise<T> {\n let attempt = 0;\n\n while (attempt < maxRetries) {\n try {\n return await fn();\n } catch (e) {\n if (typeof stopOnError === \"function\") {\n const error = e as Error;\n if (stopOnError(error)) {\n throw error;\n }\n }\n attempt += 1;\n if (attempt >= maxRetries) {\n throw e;\n }\n // Exponential backoff with full jitter to prevent thundering herd\n const jitter = Math.random();\n const delay = 2 ** attempt * initialSleepTime * jitter; // 0-1x of 1s, 2s, 4s base\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n\n throw new Error(\"Retry failed\");\n}\n","import { retryWhenFailed } from \"../retry.js\";\n\n/**\n * Retry an HTTP request with exponential backoff and jitter.\n * Only retries on server errors (5xx), rate limits (429), timeouts (408), and network errors.\n *\n * @param input - The URL or Request object to fetch\n * @param init - The fetch init options\n * @param maxRetries - Maximum number of retry attempts\n * @param initialSleepTime - Initial sleep time between retries in ms\n * @returns The fetch Response\n * @throws Error if all retries fail\n * @example\n * import { fetchWithRetry } from \"@settlemint/sdk-utils/http\";\n *\n * const response = await fetchWithRetry(\"https://api.example.com/data\");\n */\nexport async function fetchWithRetry(\n input: RequestInfo | URL,\n init?: RequestInit,\n maxRetries = 5,\n initialSleepTime = 3_000,\n): Promise<Response> {\n return retryWhenFailed(\n async () => {\n const response = await fetch(input, init);\n if (response.ok) {\n return response;\n }\n // Only retry on 5xx server errors, 429 rate limit, timeout, and network errors\n if (response.status < 500 && response.status !== 429 && response.status !== 408 && response.status !== 0) {\n return response;\n }\n throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);\n },\n maxRetries,\n initialSleepTime,\n );\n}\n","import { retryWhenFailed } from \"../retry.js\";\nimport { fetchWithRetry } from \"./fetch-with-retry.js\";\n\n/**\n * Executes a GraphQL request with automatic retries using exponential backoff and jitter.\n * Only retries on server errors (5xx), rate limits (429), timeouts (408), and network errors.\n * Will also retry if the GraphQL response contains errors.\n *\n * @param input - The URL or Request object for the GraphQL endpoint\n * @param init - Optional fetch configuration options\n * @param maxRetries - Maximum retry attempts before failing (default: 5)\n * @param initialSleepTime - Initial delay between retries in milliseconds (default: 3000)\n * @returns The parsed GraphQL response data\n * @throws Error if all retries fail or if GraphQL response contains errors\n * @example\n * import { graphqlFetchWithRetry } from \"@settlemint/sdk-utils/http\";\n *\n * const data = await graphqlFetchWithRetry<{ user: { id: string } }>(\n * \"https://api.example.com/graphql\",\n * {\n * method: \"POST\",\n * headers: { \"Content-Type\": \"application/json\" },\n * body: JSON.stringify({\n * query: `query GetUser($id: ID!) {\n * user(id: $id) {\n * id\n * }\n * }`,\n * variables: { id: \"123\" }\n * })\n * }\n * );\n */\nexport async function graphqlFetchWithRetry<Data>(\n input: RequestInfo | URL,\n init?: RequestInit,\n maxRetries = 5,\n initialSleepTime = 3_000,\n): Promise<Data> {\n return retryWhenFailed<Data>(\n async () => {\n const response = await fetchWithRetry(input, init);\n const json: { errors?: { message: string }[]; data: Data } = await response.json();\n if (json.errors) {\n throw new Error(`GraphQL errors in response: ${json.errors.map((error) => error.message).join(\", \")}`);\n }\n return json.data;\n },\n maxRetries,\n initialSleepTime,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACaA,eAAsB,gBACpB,IACA,aAAa,GACb,mBAAmB,KACnB,aACY;AACZ,MAAI,UAAU;AAEd,SAAO,UAAU,YAAY;AAC3B,QAAI;AACF,aAAO,MAAM,GAAG;AAAA,IAClB,SAAS,GAAG;AACV,UAAI,OAAO,gBAAgB,YAAY;AACrC,cAAM,QAAQ;AACd,YAAI,YAAY,KAAK,GAAG;AACtB,gBAAM;AAAA,QACR;AAAA,MACF;AACA,iBAAW;AACX,UAAI,WAAW,YAAY;AACzB,cAAM;AAAA,MACR;AAEA,YAAM,SAAS,KAAK,OAAO;AAC3B,YAAM,QAAQ,KAAK,UAAU,mBAAmB;AAChD,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,CAAC;AAAA,IAC3D;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,cAAc;AAChC;;;AC1BA,eAAsB,eACpB,OACA,MACA,aAAa,GACb,mBAAmB,KACA;AACnB,SAAO;AAAA,IACL,YAAY;AACV,YAAM,WAAW,MAAM,MAAM,OAAO,IAAI;AACxC,UAAI,SAAS,IAAI;AACf,eAAO;AAAA,MACT;AAEA,UAAI,SAAS,SAAS,OAAO,SAAS,WAAW,OAAO,SAAS,WAAW,OAAO,SAAS,WAAW,GAAG;AACxG,eAAO;AAAA,MACT;AACA,YAAM,IAAI,MAAM,uBAAuB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,IACjF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACLA,eAAsB,sBACpB,OACA,MACA,aAAa,GACb,mBAAmB,KACJ;AACf,SAAO;AAAA,IACL,YAAY;AACV,YAAM,WAAW,MAAM,eAAe,OAAO,IAAI;AACjD,YAAM,OAAuD,MAAM,SAAS,KAAK;AACjF,UAAI,KAAK,QAAQ;AACf,cAAM,IAAI,MAAM,+BAA+B,KAAK,OAAO,IAAI,CAAC,UAAU,MAAM,OAAO,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,MACvG;AACA,aAAO,KAAK;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/http.ts","../src/retry.ts","../src/http/fetch-with-retry.ts","../src/http/graphql-fetch-with-retry.ts","../src/http/headers.ts"],"sourcesContent":["export { fetchWithRetry } from \"./http/fetch-with-retry.js\";\nexport { graphqlFetchWithRetry } from \"./http/graphql-fetch-with-retry.js\";\nexport { appendHeaders } from \"./http/headers.js\";\n","/**\n * Retry a function when it fails.\n * @param fn - The function to retry.\n * @param maxRetries - The maximum number of retries.\n * @param initialSleepTime - The initial time to sleep between exponential backoff retries.\n * @param stopOnError - The function to stop on error.\n * @returns The result of the function or undefined if it fails.\n * @example\n * import { retryWhenFailed } from \"@settlemint/sdk-utils\";\n * import { readFile } from \"node:fs/promises\";\n *\n * const result = await retryWhenFailed(() => readFile(\"/path/to/file.txt\"), 3, 1_000);\n */\nexport async function retryWhenFailed<T>(\n fn: () => Promise<T>,\n maxRetries = 5,\n initialSleepTime = 1_000,\n stopOnError?: (error: Error) => boolean,\n): Promise<T> {\n let attempt = 0;\n\n while (attempt < maxRetries) {\n try {\n return await fn();\n } catch (e) {\n if (typeof stopOnError === \"function\") {\n const error = e as Error;\n if (stopOnError(error)) {\n throw error;\n }\n }\n attempt += 1;\n if (attempt >= maxRetries) {\n throw e;\n }\n // Exponential backoff with full jitter to prevent thundering herd\n const jitter = Math.random();\n const delay = 2 ** attempt * initialSleepTime * jitter; // 0-1x of 1s, 2s, 4s base\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n\n throw new Error(\"Retry failed\");\n}\n","import { retryWhenFailed } from \"../retry.js\";\n\n/**\n * Retry an HTTP request with exponential backoff and jitter.\n * Only retries on server errors (5xx), rate limits (429), timeouts (408), and network errors.\n *\n * @param input - The URL or Request object to fetch\n * @param init - The fetch init options\n * @param maxRetries - Maximum number of retry attempts\n * @param initialSleepTime - Initial sleep time between retries in ms\n * @returns The fetch Response\n * @throws Error if all retries fail\n * @example\n * import { fetchWithRetry } from \"@settlemint/sdk-utils/http\";\n *\n * const response = await fetchWithRetry(\"https://api.example.com/data\");\n */\nexport async function fetchWithRetry(\n input: RequestInfo | URL,\n init?: RequestInit,\n maxRetries = 5,\n initialSleepTime = 3_000,\n): Promise<Response> {\n return retryWhenFailed(\n async () => {\n const response = await fetch(input, init);\n if (response.ok) {\n return response;\n }\n // Only retry on 5xx server errors, 429 rate limit, timeout, and network errors\n if (response.status < 500 && response.status !== 429 && response.status !== 408 && response.status !== 0) {\n return response;\n }\n throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);\n },\n maxRetries,\n initialSleepTime,\n );\n}\n","import { retryWhenFailed } from \"../retry.js\";\nimport { fetchWithRetry } from \"./fetch-with-retry.js\";\n\n/**\n * Executes a GraphQL request with automatic retries using exponential backoff and jitter.\n * Only retries on server errors (5xx), rate limits (429), timeouts (408), and network errors.\n * Will also retry if the GraphQL response contains errors.\n *\n * @param input - The URL or Request object for the GraphQL endpoint\n * @param init - Optional fetch configuration options\n * @param maxRetries - Maximum retry attempts before failing (default: 5)\n * @param initialSleepTime - Initial delay between retries in milliseconds (default: 3000)\n * @returns The parsed GraphQL response data\n * @throws Error if all retries fail or if GraphQL response contains errors\n * @example\n * import { graphqlFetchWithRetry } from \"@settlemint/sdk-utils/http\";\n *\n * const data = await graphqlFetchWithRetry<{ user: { id: string } }>(\n * \"https://api.example.com/graphql\",\n * {\n * method: \"POST\",\n * headers: { \"Content-Type\": \"application/json\" },\n * body: JSON.stringify({\n * query: `query GetUser($id: ID!) {\n * user(id: $id) {\n * id\n * }\n * }`,\n * variables: { id: \"123\" }\n * })\n * }\n * );\n */\nexport async function graphqlFetchWithRetry<Data>(\n input: RequestInfo | URL,\n init?: RequestInit,\n maxRetries = 5,\n initialSleepTime = 3_000,\n): Promise<Data> {\n return retryWhenFailed<Data>(\n async () => {\n const response = await fetchWithRetry(input, init);\n const json: { errors?: { message: string }[]; data: Data } = await response.json();\n if (json.errors) {\n throw new Error(`GraphQL errors in response: ${json.errors.map((error) => error.message).join(\", \")}`);\n }\n return json.data;\n },\n maxRetries,\n initialSleepTime,\n );\n}\n","type MaybeLazy<T> = T | (() => T);\n\nexport function appendHeaders(\n headers: MaybeLazy<HeadersInit> | undefined,\n additionalHeaders: Record<string, string | undefined>,\n) {\n const defaultHeaders = typeof headers === \"function\" ? headers() : headers;\n const filteredAdditionalHeaders = Object.entries(additionalHeaders).filter(([_, value]) => value !== undefined) as [\n string,\n string,\n ][];\n if (Array.isArray(defaultHeaders)) {\n return [...defaultHeaders, ...filteredAdditionalHeaders];\n }\n if (defaultHeaders instanceof Headers) {\n return new Headers([...defaultHeaders, ...filteredAdditionalHeaders]);\n }\n return {\n ...defaultHeaders,\n ...Object.fromEntries(filteredAdditionalHeaders),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACaA,eAAsB,gBACpB,IACA,aAAa,GACb,mBAAmB,KACnB,aACY;AACZ,MAAI,UAAU;AAEd,SAAO,UAAU,YAAY;AAC3B,QAAI;AACF,aAAO,MAAM,GAAG;AAAA,IAClB,SAAS,GAAG;AACV,UAAI,OAAO,gBAAgB,YAAY;AACrC,cAAM,QAAQ;AACd,YAAI,YAAY,KAAK,GAAG;AACtB,gBAAM;AAAA,QACR;AAAA,MACF;AACA,iBAAW;AACX,UAAI,WAAW,YAAY;AACzB,cAAM;AAAA,MACR;AAEA,YAAM,SAAS,KAAK,OAAO;AAC3B,YAAM,QAAQ,KAAK,UAAU,mBAAmB;AAChD,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,CAAC;AAAA,IAC3D;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,cAAc;AAChC;;;AC1BA,eAAsB,eACpB,OACA,MACA,aAAa,GACb,mBAAmB,KACA;AACnB,SAAO;AAAA,IACL,YAAY;AACV,YAAM,WAAW,MAAM,MAAM,OAAO,IAAI;AACxC,UAAI,SAAS,IAAI;AACf,eAAO;AAAA,MACT;AAEA,UAAI,SAAS,SAAS,OAAO,SAAS,WAAW,OAAO,SAAS,WAAW,OAAO,SAAS,WAAW,GAAG;AACxG,eAAO;AAAA,MACT;AACA,YAAM,IAAI,MAAM,uBAAuB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,IACjF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACLA,eAAsB,sBACpB,OACA,MACA,aAAa,GACb,mBAAmB,KACJ;AACf,SAAO;AAAA,IACL,YAAY;AACV,YAAM,WAAW,MAAM,eAAe,OAAO,IAAI;AACjD,YAAM,OAAuD,MAAM,SAAS,KAAK;AACjF,UAAI,KAAK,QAAQ;AACf,cAAM,IAAI,MAAM,+BAA+B,KAAK,OAAO,IAAI,CAAC,UAAU,MAAM,OAAO,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,MACvG;AACA,aAAO,KAAK;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACjDO,SAAS,cACd,SACA,mBACA;AACA,QAAM,iBAAiB,OAAO,YAAY,aAAa,QAAQ,IAAI;AACnE,QAAM,4BAA4B,OAAO,QAAQ,iBAAiB,EAAE,OAAO,CAAC,CAAC,GAAG,KAAK,MAAM,UAAU,MAAS;AAI9G,MAAI,MAAM,QAAQ,cAAc,GAAG;AACjC,WAAO,CAAC,GAAG,gBAAgB,GAAG,yBAAyB;AAAA,EACzD;AACA,MAAI,0BAA0B,SAAS;AACrC,WAAO,IAAI,QAAQ,CAAC,GAAG,gBAAgB,GAAG,yBAAyB,CAAC;AAAA,EACtE;AACA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG,OAAO,YAAY,yBAAyB;AAAA,EACjD;AACF;","names":[]}
|
package/dist/http.d.cts
CHANGED
|
@@ -47,4 +47,9 @@ declare function fetchWithRetry(input: RequestInfo | URL, init?: RequestInit, ma
|
|
|
47
47
|
*/
|
|
48
48
|
declare function graphqlFetchWithRetry<Data>(input: RequestInfo | URL, init?: RequestInit, maxRetries?: number, initialSleepTime?: number): Promise<Data>;
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
type MaybeLazy<T> = T | (() => T);
|
|
51
|
+
declare function appendHeaders(headers: MaybeLazy<HeadersInit> | undefined, additionalHeaders: Record<string, string | undefined>): [string, string][] | Headers | {
|
|
52
|
+
[x: string]: string;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export { appendHeaders, fetchWithRetry, graphqlFetchWithRetry };
|
package/dist/http.d.ts
CHANGED
|
@@ -47,4 +47,9 @@ declare function fetchWithRetry(input: RequestInfo | URL, init?: RequestInit, ma
|
|
|
47
47
|
*/
|
|
48
48
|
declare function graphqlFetchWithRetry<Data>(input: RequestInfo | URL, init?: RequestInit, maxRetries?: number, initialSleepTime?: number): Promise<Data>;
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
type MaybeLazy<T> = T | (() => T);
|
|
51
|
+
declare function appendHeaders(headers: MaybeLazy<HeadersInit> | undefined, additionalHeaders: Record<string, string | undefined>): [string, string][] | Headers | {
|
|
52
|
+
[x: string]: string;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export { appendHeaders, fetchWithRetry, graphqlFetchWithRetry };
|
package/dist/http.mjs
CHANGED
|
@@ -56,7 +56,24 @@ async function graphqlFetchWithRetry(input, init, maxRetries = 5, initialSleepTi
|
|
|
56
56
|
initialSleepTime
|
|
57
57
|
);
|
|
58
58
|
}
|
|
59
|
+
|
|
60
|
+
// src/http/headers.ts
|
|
61
|
+
function appendHeaders(headers, additionalHeaders) {
|
|
62
|
+
const defaultHeaders = typeof headers === "function" ? headers() : headers;
|
|
63
|
+
const filteredAdditionalHeaders = Object.entries(additionalHeaders).filter(([_, value]) => value !== void 0);
|
|
64
|
+
if (Array.isArray(defaultHeaders)) {
|
|
65
|
+
return [...defaultHeaders, ...filteredAdditionalHeaders];
|
|
66
|
+
}
|
|
67
|
+
if (defaultHeaders instanceof Headers) {
|
|
68
|
+
return new Headers([...defaultHeaders, ...filteredAdditionalHeaders]);
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
...defaultHeaders,
|
|
72
|
+
...Object.fromEntries(filteredAdditionalHeaders)
|
|
73
|
+
};
|
|
74
|
+
}
|
|
59
75
|
export {
|
|
76
|
+
appendHeaders,
|
|
60
77
|
fetchWithRetry,
|
|
61
78
|
graphqlFetchWithRetry
|
|
62
79
|
};
|
package/dist/http.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/retry.ts","../src/http/fetch-with-retry.ts","../src/http/graphql-fetch-with-retry.ts"],"sourcesContent":["/**\n * Retry a function when it fails.\n * @param fn - The function to retry.\n * @param maxRetries - The maximum number of retries.\n * @param initialSleepTime - The initial time to sleep between exponential backoff retries.\n * @param stopOnError - The function to stop on error.\n * @returns The result of the function or undefined if it fails.\n * @example\n * import { retryWhenFailed } from \"@settlemint/sdk-utils\";\n * import { readFile } from \"node:fs/promises\";\n *\n * const result = await retryWhenFailed(() => readFile(\"/path/to/file.txt\"), 3, 1_000);\n */\nexport async function retryWhenFailed<T>(\n fn: () => Promise<T>,\n maxRetries = 5,\n initialSleepTime = 1_000,\n stopOnError?: (error: Error) => boolean,\n): Promise<T> {\n let attempt = 0;\n\n while (attempt < maxRetries) {\n try {\n return await fn();\n } catch (e) {\n if (typeof stopOnError === \"function\") {\n const error = e as Error;\n if (stopOnError(error)) {\n throw error;\n }\n }\n attempt += 1;\n if (attempt >= maxRetries) {\n throw e;\n }\n // Exponential backoff with full jitter to prevent thundering herd\n const jitter = Math.random();\n const delay = 2 ** attempt * initialSleepTime * jitter; // 0-1x of 1s, 2s, 4s base\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n\n throw new Error(\"Retry failed\");\n}\n","import { retryWhenFailed } from \"../retry.js\";\n\n/**\n * Retry an HTTP request with exponential backoff and jitter.\n * Only retries on server errors (5xx), rate limits (429), timeouts (408), and network errors.\n *\n * @param input - The URL or Request object to fetch\n * @param init - The fetch init options\n * @param maxRetries - Maximum number of retry attempts\n * @param initialSleepTime - Initial sleep time between retries in ms\n * @returns The fetch Response\n * @throws Error if all retries fail\n * @example\n * import { fetchWithRetry } from \"@settlemint/sdk-utils/http\";\n *\n * const response = await fetchWithRetry(\"https://api.example.com/data\");\n */\nexport async function fetchWithRetry(\n input: RequestInfo | URL,\n init?: RequestInit,\n maxRetries = 5,\n initialSleepTime = 3_000,\n): Promise<Response> {\n return retryWhenFailed(\n async () => {\n const response = await fetch(input, init);\n if (response.ok) {\n return response;\n }\n // Only retry on 5xx server errors, 429 rate limit, timeout, and network errors\n if (response.status < 500 && response.status !== 429 && response.status !== 408 && response.status !== 0) {\n return response;\n }\n throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);\n },\n maxRetries,\n initialSleepTime,\n );\n}\n","import { retryWhenFailed } from \"../retry.js\";\nimport { fetchWithRetry } from \"./fetch-with-retry.js\";\n\n/**\n * Executes a GraphQL request with automatic retries using exponential backoff and jitter.\n * Only retries on server errors (5xx), rate limits (429), timeouts (408), and network errors.\n * Will also retry if the GraphQL response contains errors.\n *\n * @param input - The URL or Request object for the GraphQL endpoint\n * @param init - Optional fetch configuration options\n * @param maxRetries - Maximum retry attempts before failing (default: 5)\n * @param initialSleepTime - Initial delay between retries in milliseconds (default: 3000)\n * @returns The parsed GraphQL response data\n * @throws Error if all retries fail or if GraphQL response contains errors\n * @example\n * import { graphqlFetchWithRetry } from \"@settlemint/sdk-utils/http\";\n *\n * const data = await graphqlFetchWithRetry<{ user: { id: string } }>(\n * \"https://api.example.com/graphql\",\n * {\n * method: \"POST\",\n * headers: { \"Content-Type\": \"application/json\" },\n * body: JSON.stringify({\n * query: `query GetUser($id: ID!) {\n * user(id: $id) {\n * id\n * }\n * }`,\n * variables: { id: \"123\" }\n * })\n * }\n * );\n */\nexport async function graphqlFetchWithRetry<Data>(\n input: RequestInfo | URL,\n init?: RequestInit,\n maxRetries = 5,\n initialSleepTime = 3_000,\n): Promise<Data> {\n return retryWhenFailed<Data>(\n async () => {\n const response = await fetchWithRetry(input, init);\n const json: { errors?: { message: string }[]; data: Data } = await response.json();\n if (json.errors) {\n throw new Error(`GraphQL errors in response: ${json.errors.map((error) => error.message).join(\", \")}`);\n }\n return json.data;\n },\n maxRetries,\n initialSleepTime,\n );\n}\n"],"mappings":";AAaA,eAAsB,gBACpB,IACA,aAAa,GACb,mBAAmB,KACnB,aACY;AACZ,MAAI,UAAU;AAEd,SAAO,UAAU,YAAY;AAC3B,QAAI;AACF,aAAO,MAAM,GAAG;AAAA,IAClB,SAAS,GAAG;AACV,UAAI,OAAO,gBAAgB,YAAY;AACrC,cAAM,QAAQ;AACd,YAAI,YAAY,KAAK,GAAG;AACtB,gBAAM;AAAA,QACR;AAAA,MACF;AACA,iBAAW;AACX,UAAI,WAAW,YAAY;AACzB,cAAM;AAAA,MACR;AAEA,YAAM,SAAS,KAAK,OAAO;AAC3B,YAAM,QAAQ,KAAK,UAAU,mBAAmB;AAChD,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,CAAC;AAAA,IAC3D;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,cAAc;AAChC;;;AC1BA,eAAsB,eACpB,OACA,MACA,aAAa,GACb,mBAAmB,KACA;AACnB,SAAO;AAAA,IACL,YAAY;AACV,YAAM,WAAW,MAAM,MAAM,OAAO,IAAI;AACxC,UAAI,SAAS,IAAI;AACf,eAAO;AAAA,MACT;AAEA,UAAI,SAAS,SAAS,OAAO,SAAS,WAAW,OAAO,SAAS,WAAW,OAAO,SAAS,WAAW,GAAG;AACxG,eAAO;AAAA,MACT;AACA,YAAM,IAAI,MAAM,uBAAuB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,IACjF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACLA,eAAsB,sBACpB,OACA,MACA,aAAa,GACb,mBAAmB,KACJ;AACf,SAAO;AAAA,IACL,YAAY;AACV,YAAM,WAAW,MAAM,eAAe,OAAO,IAAI;AACjD,YAAM,OAAuD,MAAM,SAAS,KAAK;AACjF,UAAI,KAAK,QAAQ;AACf,cAAM,IAAI,MAAM,+BAA+B,KAAK,OAAO,IAAI,CAAC,UAAU,MAAM,OAAO,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,MACvG;AACA,aAAO,KAAK;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/retry.ts","../src/http/fetch-with-retry.ts","../src/http/graphql-fetch-with-retry.ts","../src/http/headers.ts"],"sourcesContent":["/**\n * Retry a function when it fails.\n * @param fn - The function to retry.\n * @param maxRetries - The maximum number of retries.\n * @param initialSleepTime - The initial time to sleep between exponential backoff retries.\n * @param stopOnError - The function to stop on error.\n * @returns The result of the function or undefined if it fails.\n * @example\n * import { retryWhenFailed } from \"@settlemint/sdk-utils\";\n * import { readFile } from \"node:fs/promises\";\n *\n * const result = await retryWhenFailed(() => readFile(\"/path/to/file.txt\"), 3, 1_000);\n */\nexport async function retryWhenFailed<T>(\n fn: () => Promise<T>,\n maxRetries = 5,\n initialSleepTime = 1_000,\n stopOnError?: (error: Error) => boolean,\n): Promise<T> {\n let attempt = 0;\n\n while (attempt < maxRetries) {\n try {\n return await fn();\n } catch (e) {\n if (typeof stopOnError === \"function\") {\n const error = e as Error;\n if (stopOnError(error)) {\n throw error;\n }\n }\n attempt += 1;\n if (attempt >= maxRetries) {\n throw e;\n }\n // Exponential backoff with full jitter to prevent thundering herd\n const jitter = Math.random();\n const delay = 2 ** attempt * initialSleepTime * jitter; // 0-1x of 1s, 2s, 4s base\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n\n throw new Error(\"Retry failed\");\n}\n","import { retryWhenFailed } from \"../retry.js\";\n\n/**\n * Retry an HTTP request with exponential backoff and jitter.\n * Only retries on server errors (5xx), rate limits (429), timeouts (408), and network errors.\n *\n * @param input - The URL or Request object to fetch\n * @param init - The fetch init options\n * @param maxRetries - Maximum number of retry attempts\n * @param initialSleepTime - Initial sleep time between retries in ms\n * @returns The fetch Response\n * @throws Error if all retries fail\n * @example\n * import { fetchWithRetry } from \"@settlemint/sdk-utils/http\";\n *\n * const response = await fetchWithRetry(\"https://api.example.com/data\");\n */\nexport async function fetchWithRetry(\n input: RequestInfo | URL,\n init?: RequestInit,\n maxRetries = 5,\n initialSleepTime = 3_000,\n): Promise<Response> {\n return retryWhenFailed(\n async () => {\n const response = await fetch(input, init);\n if (response.ok) {\n return response;\n }\n // Only retry on 5xx server errors, 429 rate limit, timeout, and network errors\n if (response.status < 500 && response.status !== 429 && response.status !== 408 && response.status !== 0) {\n return response;\n }\n throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);\n },\n maxRetries,\n initialSleepTime,\n );\n}\n","import { retryWhenFailed } from \"../retry.js\";\nimport { fetchWithRetry } from \"./fetch-with-retry.js\";\n\n/**\n * Executes a GraphQL request with automatic retries using exponential backoff and jitter.\n * Only retries on server errors (5xx), rate limits (429), timeouts (408), and network errors.\n * Will also retry if the GraphQL response contains errors.\n *\n * @param input - The URL or Request object for the GraphQL endpoint\n * @param init - Optional fetch configuration options\n * @param maxRetries - Maximum retry attempts before failing (default: 5)\n * @param initialSleepTime - Initial delay between retries in milliseconds (default: 3000)\n * @returns The parsed GraphQL response data\n * @throws Error if all retries fail or if GraphQL response contains errors\n * @example\n * import { graphqlFetchWithRetry } from \"@settlemint/sdk-utils/http\";\n *\n * const data = await graphqlFetchWithRetry<{ user: { id: string } }>(\n * \"https://api.example.com/graphql\",\n * {\n * method: \"POST\",\n * headers: { \"Content-Type\": \"application/json\" },\n * body: JSON.stringify({\n * query: `query GetUser($id: ID!) {\n * user(id: $id) {\n * id\n * }\n * }`,\n * variables: { id: \"123\" }\n * })\n * }\n * );\n */\nexport async function graphqlFetchWithRetry<Data>(\n input: RequestInfo | URL,\n init?: RequestInit,\n maxRetries = 5,\n initialSleepTime = 3_000,\n): Promise<Data> {\n return retryWhenFailed<Data>(\n async () => {\n const response = await fetchWithRetry(input, init);\n const json: { errors?: { message: string }[]; data: Data } = await response.json();\n if (json.errors) {\n throw new Error(`GraphQL errors in response: ${json.errors.map((error) => error.message).join(\", \")}`);\n }\n return json.data;\n },\n maxRetries,\n initialSleepTime,\n );\n}\n","type MaybeLazy<T> = T | (() => T);\n\nexport function appendHeaders(\n headers: MaybeLazy<HeadersInit> | undefined,\n additionalHeaders: Record<string, string | undefined>,\n) {\n const defaultHeaders = typeof headers === \"function\" ? headers() : headers;\n const filteredAdditionalHeaders = Object.entries(additionalHeaders).filter(([_, value]) => value !== undefined) as [\n string,\n string,\n ][];\n if (Array.isArray(defaultHeaders)) {\n return [...defaultHeaders, ...filteredAdditionalHeaders];\n }\n if (defaultHeaders instanceof Headers) {\n return new Headers([...defaultHeaders, ...filteredAdditionalHeaders]);\n }\n return {\n ...defaultHeaders,\n ...Object.fromEntries(filteredAdditionalHeaders),\n };\n}\n"],"mappings":";AAaA,eAAsB,gBACpB,IACA,aAAa,GACb,mBAAmB,KACnB,aACY;AACZ,MAAI,UAAU;AAEd,SAAO,UAAU,YAAY;AAC3B,QAAI;AACF,aAAO,MAAM,GAAG;AAAA,IAClB,SAAS,GAAG;AACV,UAAI,OAAO,gBAAgB,YAAY;AACrC,cAAM,QAAQ;AACd,YAAI,YAAY,KAAK,GAAG;AACtB,gBAAM;AAAA,QACR;AAAA,MACF;AACA,iBAAW;AACX,UAAI,WAAW,YAAY;AACzB,cAAM;AAAA,MACR;AAEA,YAAM,SAAS,KAAK,OAAO;AAC3B,YAAM,QAAQ,KAAK,UAAU,mBAAmB;AAChD,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,CAAC;AAAA,IAC3D;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,cAAc;AAChC;;;AC1BA,eAAsB,eACpB,OACA,MACA,aAAa,GACb,mBAAmB,KACA;AACnB,SAAO;AAAA,IACL,YAAY;AACV,YAAM,WAAW,MAAM,MAAM,OAAO,IAAI;AACxC,UAAI,SAAS,IAAI;AACf,eAAO;AAAA,MACT;AAEA,UAAI,SAAS,SAAS,OAAO,SAAS,WAAW,OAAO,SAAS,WAAW,OAAO,SAAS,WAAW,GAAG;AACxG,eAAO;AAAA,MACT;AACA,YAAM,IAAI,MAAM,uBAAuB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,IACjF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACLA,eAAsB,sBACpB,OACA,MACA,aAAa,GACb,mBAAmB,KACJ;AACf,SAAO;AAAA,IACL,YAAY;AACV,YAAM,WAAW,MAAM,eAAe,OAAO,IAAI;AACjD,YAAM,OAAuD,MAAM,SAAS,KAAK;AACjF,UAAI,KAAK,QAAQ;AACf,cAAM,IAAI,MAAM,+BAA+B,KAAK,OAAO,IAAI,CAAC,UAAU,MAAM,OAAO,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,MACvG;AACA,aAAO,KAAK;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACjDO,SAAS,cACd,SACA,mBACA;AACA,QAAM,iBAAiB,OAAO,YAAY,aAAa,QAAQ,IAAI;AACnE,QAAM,4BAA4B,OAAO,QAAQ,iBAAiB,EAAE,OAAO,CAAC,CAAC,GAAG,KAAK,MAAM,UAAU,MAAS;AAI9G,MAAI,MAAM,QAAQ,cAAc,GAAG;AACjC,WAAO,CAAC,GAAG,gBAAgB,GAAG,yBAAyB;AAAA,EACzD;AACA,MAAI,0BAA0B,SAAS;AACrC,WAAO,IAAI,QAAQ,CAAC,GAAG,gBAAgB,GAAG,yBAAyB,CAAC;AAAA,EACtE;AACA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG,OAAO,YAAY,yBAAyB;AAAA,EACjD;AACF;","names":[]}
|
package/package.json
CHANGED