@settlemint/sdk-utils 2.3.2 → 2.3.3-main6f8f814c

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/README.md +121 -77
  2. package/dist/environment.cjs +17708 -383
  3. package/dist/environment.cjs.map +1 -1
  4. package/dist/environment.d.cts +263 -98
  5. package/dist/environment.d.ts +263 -98
  6. package/dist/environment.js +17746 -0
  7. package/dist/environment.js.map +1 -0
  8. package/dist/filesystem.cjs +6746 -113
  9. package/dist/filesystem.cjs.map +1 -1
  10. package/dist/filesystem.d.cts +22 -1
  11. package/dist/filesystem.d.ts +22 -1
  12. package/dist/filesystem.js +6766 -0
  13. package/dist/filesystem.js.map +1 -0
  14. package/dist/http.cjs +217 -79
  15. package/dist/http.cjs.map +1 -1
  16. package/dist/http.d.cts +14 -1
  17. package/dist/http.d.ts +14 -1
  18. package/dist/http.js +226 -0
  19. package/dist/http.js.map +1 -0
  20. package/dist/index.cjs +295 -104
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +26 -1
  23. package/dist/index.d.ts +26 -1
  24. package/dist/index.js +306 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/json.cjs +83 -0
  27. package/dist/json.cjs.map +1 -0
  28. package/dist/json.d.cts +56 -0
  29. package/dist/json.d.ts +56 -0
  30. package/dist/json.js +80 -0
  31. package/dist/json.js.map +1 -0
  32. package/dist/logging.cjs +209 -137
  33. package/dist/logging.cjs.map +1 -1
  34. package/dist/logging.d.cts +23 -14
  35. package/dist/logging.d.ts +23 -14
  36. package/dist/logging.js +221 -0
  37. package/dist/logging.js.map +1 -0
  38. package/dist/package-manager.cjs +7353 -173
  39. package/dist/package-manager.cjs.map +1 -1
  40. package/dist/package-manager.d.cts +26 -3
  41. package/dist/package-manager.d.ts +26 -3
  42. package/dist/package-manager.js +7385 -0
  43. package/dist/package-manager.js.map +1 -0
  44. package/dist/retry.cjs +137 -0
  45. package/dist/retry.cjs.map +1 -0
  46. package/dist/retry.d.cts +19 -0
  47. package/dist/retry.d.ts +19 -0
  48. package/dist/retry.js +136 -0
  49. package/dist/retry.js.map +1 -0
  50. package/dist/runtime.cjs +58 -40
  51. package/dist/runtime.cjs.map +1 -1
  52. package/dist/runtime.d.cts +3 -0
  53. package/dist/runtime.d.ts +3 -0
  54. package/dist/runtime.js +45 -0
  55. package/dist/runtime.js.map +1 -0
  56. package/dist/string.cjs +76 -0
  57. package/dist/string.cjs.map +1 -0
  58. package/dist/string.d.cts +58 -0
  59. package/dist/string.d.ts +58 -0
  60. package/dist/string.js +72 -0
  61. package/dist/string.js.map +1 -0
  62. package/dist/terminal.cjs +426 -229
  63. package/dist/terminal.cjs.map +1 -1
  64. package/dist/terminal.d.cts +54 -24
  65. package/dist/terminal.d.ts +54 -24
  66. package/dist/terminal.js +441 -0
  67. package/dist/terminal.js.map +1 -0
  68. package/dist/url.cjs +25 -0
  69. package/dist/url.cjs.map +1 -0
  70. package/dist/url.d.cts +20 -0
  71. package/dist/url.d.ts +20 -0
  72. package/dist/url.js +24 -0
  73. package/dist/url.js.map +1 -0
  74. package/dist/validation.cjs +10486 -190
  75. package/dist/validation.cjs.map +1 -1
  76. package/dist/validation.d.cts +128 -94
  77. package/dist/validation.d.ts +128 -94
  78. package/dist/validation.js +10482 -0
  79. package/dist/validation.js.map +1 -0
  80. package/package.json +6 -6
  81. package/dist/environment.mjs +0 -383
  82. package/dist/environment.mjs.map +0 -1
  83. package/dist/filesystem.mjs +0 -105
  84. package/dist/filesystem.mjs.map +0 -1
  85. package/dist/http.mjs +0 -63
  86. package/dist/http.mjs.map +0 -1
  87. package/dist/index.mjs +0 -90
  88. package/dist/index.mjs.map +0 -1
  89. package/dist/logging.mjs +0 -123
  90. package/dist/logging.mjs.map +0 -1
  91. package/dist/package-manager.mjs +0 -167
  92. package/dist/package-manager.mjs.map +0 -1
  93. package/dist/runtime.mjs +0 -23
  94. package/dist/runtime.mjs.map +0 -1
  95. package/dist/terminal.mjs +0 -230
  96. package/dist/terminal.mjs.map +0 -1
  97. package/dist/validation.mjs +0 -159
  98. package/dist/validation.mjs.map +0 -1
package/dist/http.cjs CHANGED
@@ -1,91 +1,229 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
1
+
2
+ //#region src/logging/mask-tokens.ts
3
+ /**
4
+ * Masks sensitive SettleMint tokens in output text by replacing them with asterisks.
5
+ * Handles personal access tokens (PAT), application access tokens (AAT), and service account tokens (SAT).
6
+ *
7
+ * @param output - The text string that may contain sensitive tokens
8
+ * @returns The text with any sensitive tokens masked with asterisks
9
+ * @example
10
+ * import { maskTokens } from "@settlemint/sdk-utils/terminal";
11
+ *
12
+ * // Masks a token in text
13
+ * const masked = maskTokens("Token: sm_pat_****"); // "Token: ***"
14
+ */
15
+ const maskTokens = (output) => {
16
+ return output.replace(/sm_(pat|aat|sat)_[0-9a-zA-Z]+/g, "***");
17
17
  };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
18
 
20
- // src/http.ts
21
- var http_exports = {};
22
- __export(http_exports, {
23
- fetchWithRetry: () => fetchWithRetry,
24
- graphqlFetchWithRetry: () => graphqlFetchWithRetry
25
- });
26
- module.exports = __toCommonJS(http_exports);
19
+ //#endregion
20
+ //#region src/logging/logger.ts
21
+ /**
22
+ * Creates a simple logger with configurable log level
23
+ *
24
+ * @param options - Configuration options for the logger
25
+ * @param options.level - The minimum log level to output (default: warn)
26
+ * @param options.prefix - The prefix to add to the log message (default: "")
27
+ * @returns A logger instance with debug, info, warn, and error methods
28
+ *
29
+ * @example
30
+ * import { createLogger } from "@/utils/logging/logger";
31
+ *
32
+ * const logger = createLogger({ level: 'info' });
33
+ *
34
+ * logger.info('User logged in', { userId: '123' });
35
+ * logger.error('Operation failed', new Error('Connection timeout'));
36
+ */
37
+ function createLogger(options = {}) {
38
+ const { level = "warn", prefix = "" } = options;
39
+ const logLevels = {
40
+ debug: 0,
41
+ info: 1,
42
+ warn: 2,
43
+ error: 3,
44
+ none: 4
45
+ };
46
+ const currentLevelValue = logLevels[level];
47
+ const formatArgs = (args) => {
48
+ if (args.length === 0 || args.every((arg) => arg === undefined || arg === null)) {
49
+ return "";
50
+ }
51
+ const formatted = args.map((arg) => {
52
+ if (arg instanceof Error) {
53
+ return `\n${arg.stack || arg.message}`;
54
+ }
55
+ if (typeof arg === "object" && arg !== null) {
56
+ return `\n${JSON.stringify(arg, null, 2)}`;
57
+ }
58
+ return ` ${String(arg)}`;
59
+ }).join("");
60
+ return `, args:${formatted}`;
61
+ };
62
+ const shouldLog = (level$1) => {
63
+ return logLevels[level$1] >= currentLevelValue;
64
+ };
65
+ return {
66
+ debug: (message, ...args) => {
67
+ if (shouldLog("debug")) {
68
+ console.debug(`\x1b[32m${prefix}[DEBUG] ${maskTokens(message)}${maskTokens(formatArgs(args))}\x1b[0m`);
69
+ }
70
+ },
71
+ info: (message, ...args) => {
72
+ if (shouldLog("info")) {
73
+ console.info(`\x1b[34m${prefix}[INFO] ${maskTokens(message)}${maskTokens(formatArgs(args))}\x1b[0m`);
74
+ }
75
+ },
76
+ warn: (message, ...args) => {
77
+ if (shouldLog("warn")) {
78
+ console.warn(`\x1b[33m${prefix}[WARN] ${maskTokens(message)}${maskTokens(formatArgs(args))}\x1b[0m`);
79
+ }
80
+ },
81
+ error: (message, ...args) => {
82
+ if (shouldLog("error")) {
83
+ console.error(`\x1b[31m${prefix}[ERROR] ${maskTokens(message)}${maskTokens(formatArgs(args))}\x1b[0m`);
84
+ }
85
+ }
86
+ };
87
+ }
88
+ /**
89
+ * Default logger instance with standard configuration
90
+ */
91
+ const logger = createLogger();
27
92
 
28
- // src/retry.ts
93
+ //#endregion
94
+ //#region src/retry.ts
95
+ /**
96
+ * Retry a function when it fails.
97
+ * @param fn - The function to retry.
98
+ * @param maxRetries - The maximum number of retries.
99
+ * @param initialSleepTime - The initial time to sleep between exponential backoff retries.
100
+ * @param stopOnError - The function to stop on error.
101
+ * @returns The result of the function or undefined if it fails.
102
+ * @example
103
+ * import { retryWhenFailed } from "@settlemint/sdk-utils";
104
+ * import { readFile } from "node:fs/promises";
105
+ *
106
+ * const result = await retryWhenFailed(() => readFile("/path/to/file.txt"), 3, 1_000);
107
+ */
29
108
  async function retryWhenFailed(fn, maxRetries = 5, initialSleepTime = 1e3, stopOnError) {
30
- let attempt = 0;
31
- while (attempt < maxRetries) {
32
- try {
33
- return await fn();
34
- } catch (e) {
35
- if (typeof stopOnError === "function") {
36
- const error = e;
37
- if (stopOnError(error)) {
38
- throw error;
39
- }
40
- }
41
- attempt += 1;
42
- if (attempt >= maxRetries) {
43
- throw e;
44
- }
45
- const jitter = Math.random();
46
- const delay = 2 ** attempt * initialSleepTime * jitter;
47
- await new Promise((resolve) => setTimeout(resolve, delay));
48
- }
49
- }
50
- throw new Error("Retry failed");
109
+ let retries = 0;
110
+ const maxAttempts = maxRetries + 1;
111
+ while (retries < maxAttempts) {
112
+ try {
113
+ return await fn();
114
+ } catch (e) {
115
+ const error = e;
116
+ if (typeof stopOnError === "function") {
117
+ if (stopOnError(error)) {
118
+ throw error;
119
+ }
120
+ }
121
+ if (retries >= maxRetries) {
122
+ throw e;
123
+ }
124
+ const baseDelay = 2 ** retries * initialSleepTime;
125
+ const jitterAmount = initialSleepTime * (Math.random() / 10);
126
+ const delay = baseDelay + jitterAmount;
127
+ retries += 1;
128
+ logger.warn(`An error occurred ${error.message}, retrying in ${delay.toFixed(0)}ms (retry ${retries} of ${maxRetries})...`);
129
+ await new Promise((resolve) => setTimeout(resolve, delay));
130
+ }
131
+ }
132
+ throw new Error("Retry failed");
51
133
  }
52
134
 
53
- // src/http/fetch-with-retry.ts
135
+ //#endregion
136
+ //#region src/http/fetch-with-retry.ts
137
+ /**
138
+ * Retry an HTTP request with exponential backoff and jitter.
139
+ * Only retries on server errors (5xx), rate limits (429), timeouts (408), and network errors.
140
+ *
141
+ * @param input - The URL or Request object to fetch
142
+ * @param init - The fetch init options
143
+ * @param maxRetries - Maximum number of retry attempts
144
+ * @param initialSleepTime - Initial sleep time between retries in ms
145
+ * @returns The fetch Response
146
+ * @throws Error if all retries fail
147
+ * @example
148
+ * import { fetchWithRetry } from "@settlemint/sdk-utils/http";
149
+ *
150
+ * const response = await fetchWithRetry("https://api.example.com/data");
151
+ */
54
152
  async function fetchWithRetry(input, init, maxRetries = 5, initialSleepTime = 3e3) {
55
- return retryWhenFailed(
56
- async () => {
57
- const response = await fetch(input, init);
58
- if (response.ok) {
59
- return response;
60
- }
61
- if (response.status < 500 && response.status !== 429 && response.status !== 408 && response.status !== 0) {
62
- return response;
63
- }
64
- throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);
65
- },
66
- maxRetries,
67
- initialSleepTime
68
- );
153
+ return retryWhenFailed(async () => {
154
+ const response = await fetch(input, init);
155
+ if (response.ok) {
156
+ return response;
157
+ }
158
+ if (response.status < 500 && response.status !== 429 && response.status !== 408 && response.status !== 0) {
159
+ return response;
160
+ }
161
+ throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);
162
+ }, maxRetries, initialSleepTime);
69
163
  }
70
164
 
71
- // src/http/graphql-fetch-with-retry.ts
165
+ //#endregion
166
+ //#region src/http/graphql-fetch-with-retry.ts
167
+ /**
168
+ * Executes a GraphQL request with automatic retries using exponential backoff and jitter.
169
+ * Only retries on server errors (5xx), rate limits (429), timeouts (408), and network errors.
170
+ * Will also retry if the GraphQL response contains errors.
171
+ *
172
+ * @param input - The URL or Request object for the GraphQL endpoint
173
+ * @param init - Optional fetch configuration options
174
+ * @param maxRetries - Maximum retry attempts before failing (default: 5)
175
+ * @param initialSleepTime - Initial delay between retries in milliseconds (default: 3000)
176
+ * @returns The parsed GraphQL response data
177
+ * @throws Error if all retries fail or if GraphQL response contains errors
178
+ * @example
179
+ * import { graphqlFetchWithRetry } from "@settlemint/sdk-utils/http";
180
+ *
181
+ * const data = await graphqlFetchWithRetry<{ user: { id: string } }>(
182
+ * "https://api.example.com/graphql",
183
+ * {
184
+ * method: "POST",
185
+ * headers: { "Content-Type": "application/json" },
186
+ * body: JSON.stringify({
187
+ * query: `query GetUser($id: ID!) {
188
+ * user(id: $id) {
189
+ * id
190
+ * }
191
+ * }`,
192
+ * variables: { id: "123" }
193
+ * })
194
+ * }
195
+ * );
196
+ */
72
197
  async function graphqlFetchWithRetry(input, init, maxRetries = 5, initialSleepTime = 3e3) {
73
- return retryWhenFailed(
74
- async () => {
75
- const response = await fetchWithRetry(input, init);
76
- const json = await response.json();
77
- if (json.errors) {
78
- throw new Error(`GraphQL errors in response: ${json.errors.map((error) => error.message).join(", ")}`);
79
- }
80
- return json.data;
81
- },
82
- maxRetries,
83
- initialSleepTime
84
- );
198
+ return retryWhenFailed(async () => {
199
+ const response = await fetchWithRetry(input, init);
200
+ const json = await response.json();
201
+ if (json.errors) {
202
+ throw new Error(`GraphQL errors in response: ${json.errors.map((error) => error.message).join(", ")}`);
203
+ }
204
+ return json.data;
205
+ }, maxRetries, initialSleepTime);
85
206
  }
86
- // Annotate the CommonJS export names for ESM import in node:
87
- 0 && (module.exports = {
88
- fetchWithRetry,
89
- graphqlFetchWithRetry
90
- });
207
+
208
+ //#endregion
209
+ //#region src/http/headers.ts
210
+ function appendHeaders(headers, additionalHeaders) {
211
+ const defaultHeaders = typeof headers === "function" ? headers() : headers;
212
+ const filteredAdditionalHeaders = Object.entries(additionalHeaders).filter(([_, value]) => value !== undefined);
213
+ if (Array.isArray(defaultHeaders)) {
214
+ return [...defaultHeaders, ...filteredAdditionalHeaders];
215
+ }
216
+ if (defaultHeaders instanceof Headers) {
217
+ return new Headers([...defaultHeaders, ...filteredAdditionalHeaders]);
218
+ }
219
+ return {
220
+ ...defaultHeaders,
221
+ ...Object.fromEntries(filteredAdditionalHeaders)
222
+ };
223
+ }
224
+
225
+ //#endregion
226
+ exports.appendHeaders = appendHeaders;
227
+ exports.fetchWithRetry = fetchWithRetry;
228
+ exports.graphqlFetchWithRetry = graphqlFetchWithRetry;
91
229
  //# sourceMappingURL=http.cjs.map
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,"file":"http.cjs","names":["output: string","options: LoggerOptions","logLevels: Record<LogLevel, number>","args: unknown[]","level: LogLevel","level","message: string","fn: () => Promise<T>","stopOnError?: (error: Error) => boolean","input: RequestInfo | URL","init?: RequestInit","input: RequestInfo | URL","init?: RequestInit","json: { errors?: { message: string }[]; data: Data }","headers: MaybeLazy<HeadersInit> | undefined","additionalHeaders: Record<string, string | undefined>"],"sources":["../src/logging/mask-tokens.ts","../src/logging/logger.ts","../src/retry.ts","../src/http/fetch-with-retry.ts","../src/http/graphql-fetch-with-retry.ts","../src/http/headers.ts"],"sourcesContent":["/**\n * Masks sensitive SettleMint tokens in output text by replacing them with asterisks.\n * Handles personal access tokens (PAT), application access tokens (AAT), and service account tokens (SAT).\n *\n * @param output - The text string that may contain sensitive tokens\n * @returns The text with any sensitive tokens masked with asterisks\n * @example\n * import { maskTokens } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Masks a token in text\n * const masked = maskTokens(\"Token: sm_pat_****\"); // \"Token: ***\"\n */\nexport const maskTokens = (output: string): string => {\n return output.replace(/sm_(pat|aat|sat)_[0-9a-zA-Z]+/g, \"***\");\n};\n","import { maskTokens } from \"./mask-tokens.js\";\n\n/**\n * Log levels supported by the logger\n */\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\" | \"none\";\n\n/**\n * Configuration options for the logger\n * @interface LoggerOptions\n */\nexport interface LoggerOptions {\n /** The minimum log level to output */\n level?: LogLevel;\n /** The prefix to add to the log message */\n prefix?: string;\n}\n\n/**\n * Simple logger interface with basic logging methods\n * @interface Logger\n */\nexport interface Logger {\n /** Log debug information */\n debug: (message: string, ...args: unknown[]) => void;\n /** Log general information */\n info: (message: string, ...args: unknown[]) => void;\n /** Log warnings */\n warn: (message: string, ...args: unknown[]) => void;\n /** Log errors */\n error: (message: string, ...args: unknown[]) => void;\n}\n\n/**\n * Creates a simple logger with configurable log level\n *\n * @param options - Configuration options for the logger\n * @param options.level - The minimum log level to output (default: warn)\n * @param options.prefix - The prefix to add to the log message (default: \"\")\n * @returns A logger instance with debug, info, warn, and error methods\n *\n * @example\n * import { createLogger } from \"@/utils/logging/logger\";\n *\n * const logger = createLogger({ level: 'info' });\n *\n * logger.info('User logged in', { userId: '123' });\n * logger.error('Operation failed', new Error('Connection timeout'));\n */\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const { level = \"warn\", prefix = \"\" } = options;\n\n const logLevels: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n none: 4,\n };\n\n const currentLevelValue = logLevels[level];\n\n const formatArgs = (args: unknown[]): string => {\n if (args.length === 0 || args.every((arg) => arg === undefined || arg === null)) {\n return \"\";\n }\n\n const formatted = args\n .map((arg) => {\n if (arg instanceof Error) {\n return `\\n${arg.stack || arg.message}`;\n }\n if (typeof arg === \"object\" && arg !== null) {\n return `\\n${JSON.stringify(arg, null, 2)}`;\n }\n return ` ${String(arg)}`;\n })\n .join(\"\");\n\n return `, args:${formatted}`;\n };\n\n const shouldLog = (level: LogLevel): boolean => {\n return logLevels[level] >= currentLevelValue;\n };\n\n return {\n debug: (message: string, ...args: unknown[]) => {\n if (shouldLog(\"debug\")) {\n console.debug(`\\x1b[32m${prefix}[DEBUG] ${maskTokens(message)}${maskTokens(formatArgs(args))}\\x1b[0m`);\n }\n },\n info: (message: string, ...args: unknown[]) => {\n if (shouldLog(\"info\")) {\n console.info(`\\x1b[34m${prefix}[INFO] ${maskTokens(message)}${maskTokens(formatArgs(args))}\\x1b[0m`);\n }\n },\n warn: (message: string, ...args: unknown[]) => {\n if (shouldLog(\"warn\")) {\n console.warn(`\\x1b[33m${prefix}[WARN] ${maskTokens(message)}${maskTokens(formatArgs(args))}\\x1b[0m`);\n }\n },\n error: (message: string, ...args: unknown[]) => {\n if (shouldLog(\"error\")) {\n console.error(`\\x1b[31m${prefix}[ERROR] ${maskTokens(message)}${maskTokens(formatArgs(args))}\\x1b[0m`);\n }\n },\n };\n}\n\n/**\n * Default logger instance with standard configuration\n */\nexport const logger = createLogger();\n","import { logger } from \"./logging/logger.js\";\n\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 retries = 0;\n const maxAttempts = maxRetries + 1;\n\n while (retries < maxAttempts) {\n try {\n return await fn();\n } catch (e) {\n const error = e as Error;\n if (typeof stopOnError === \"function\") {\n if (stopOnError(error)) {\n throw error;\n }\n }\n if (retries >= maxRetries) {\n throw e;\n }\n // Exponential backoff with jitter to prevent thundering herd\n // Jitter: Random value between 0-10% of initialSleepTime\n const baseDelay = 2 ** retries * initialSleepTime;\n const jitterAmount = initialSleepTime * (Math.random() / 10);\n const delay = baseDelay + jitterAmount;\n retries += 1;\n logger.warn(\n `An error occurred ${error.message}, retrying in ${delay.toFixed(0)}ms (retry ${retries} of ${maxRetries})...`,\n );\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":"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"}
package/dist/http.d.cts CHANGED
@@ -1,3 +1,4 @@
1
+ //#region src/http/fetch-with-retry.d.ts
1
2
  /**
2
3
  * Retry an HTTP request with exponential backoff and jitter.
3
4
  * Only retries on server errors (5xx), rate limits (429), timeouts (408), and network errors.
@@ -15,6 +16,9 @@
15
16
  */
16
17
  declare function fetchWithRetry(input: RequestInfo | URL, init?: RequestInit, maxRetries?: number, initialSleepTime?: number): Promise<Response>;
17
18
 
19
+ //#endregion
20
+ //#region src/http/graphql-fetch-with-retry.d.ts
21
+
18
22
  /**
19
23
  * Executes a GraphQL request with automatic retries using exponential backoff and jitter.
20
24
  * Only retries on server errors (5xx), rate limits (429), timeouts (408), and network errors.
@@ -47,4 +51,13 @@ declare function fetchWithRetry(input: RequestInfo | URL, init?: RequestInit, ma
47
51
  */
48
52
  declare function graphqlFetchWithRetry<Data>(input: RequestInfo | URL, init?: RequestInit, maxRetries?: number, initialSleepTime?: number): Promise<Data>;
49
53
 
50
- export { fetchWithRetry, graphqlFetchWithRetry };
54
+ //#endregion
55
+ //#region src/http/headers.d.ts
56
+ type MaybeLazy<T> = T | (() => T);
57
+ declare function appendHeaders(headers: MaybeLazy<HeadersInit> | undefined, additionalHeaders: Record<string, string | undefined>): [string, string][] | Headers | {
58
+ [x: string]: string;
59
+ };
60
+
61
+ //#endregion
62
+ export { appendHeaders, fetchWithRetry, graphqlFetchWithRetry };
63
+ //# sourceMappingURL=http.d.cts.map
package/dist/http.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ //#region src/http/fetch-with-retry.d.ts
1
2
  /**
2
3
  * Retry an HTTP request with exponential backoff and jitter.
3
4
  * Only retries on server errors (5xx), rate limits (429), timeouts (408), and network errors.
@@ -15,6 +16,9 @@
15
16
  */
16
17
  declare function fetchWithRetry(input: RequestInfo | URL, init?: RequestInit, maxRetries?: number, initialSleepTime?: number): Promise<Response>;
17
18
 
19
+ //#endregion
20
+ //#region src/http/graphql-fetch-with-retry.d.ts
21
+
18
22
  /**
19
23
  * Executes a GraphQL request with automatic retries using exponential backoff and jitter.
20
24
  * Only retries on server errors (5xx), rate limits (429), timeouts (408), and network errors.
@@ -47,4 +51,13 @@ declare function fetchWithRetry(input: RequestInfo | URL, init?: RequestInit, ma
47
51
  */
48
52
  declare function graphqlFetchWithRetry<Data>(input: RequestInfo | URL, init?: RequestInit, maxRetries?: number, initialSleepTime?: number): Promise<Data>;
49
53
 
50
- export { fetchWithRetry, graphqlFetchWithRetry };
54
+ //#endregion
55
+ //#region src/http/headers.d.ts
56
+ type MaybeLazy<T> = T | (() => T);
57
+ declare function appendHeaders(headers: MaybeLazy<HeadersInit> | undefined, additionalHeaders: Record<string, string | undefined>): [string, string][] | Headers | {
58
+ [x: string]: string;
59
+ };
60
+
61
+ //#endregion
62
+ export { appendHeaders, fetchWithRetry, graphqlFetchWithRetry };
63
+ //# sourceMappingURL=http.d.ts.map
package/dist/http.js ADDED
@@ -0,0 +1,226 @@
1
+ //#region src/logging/mask-tokens.ts
2
+ /**
3
+ * Masks sensitive SettleMint tokens in output text by replacing them with asterisks.
4
+ * Handles personal access tokens (PAT), application access tokens (AAT), and service account tokens (SAT).
5
+ *
6
+ * @param output - The text string that may contain sensitive tokens
7
+ * @returns The text with any sensitive tokens masked with asterisks
8
+ * @example
9
+ * import { maskTokens } from "@settlemint/sdk-utils/terminal";
10
+ *
11
+ * // Masks a token in text
12
+ * const masked = maskTokens("Token: sm_pat_****"); // "Token: ***"
13
+ */
14
+ const maskTokens = (output) => {
15
+ return output.replace(/sm_(pat|aat|sat)_[0-9a-zA-Z]+/g, "***");
16
+ };
17
+
18
+ //#endregion
19
+ //#region src/logging/logger.ts
20
+ /**
21
+ * Creates a simple logger with configurable log level
22
+ *
23
+ * @param options - Configuration options for the logger
24
+ * @param options.level - The minimum log level to output (default: warn)
25
+ * @param options.prefix - The prefix to add to the log message (default: "")
26
+ * @returns A logger instance with debug, info, warn, and error methods
27
+ *
28
+ * @example
29
+ * import { createLogger } from "@/utils/logging/logger";
30
+ *
31
+ * const logger = createLogger({ level: 'info' });
32
+ *
33
+ * logger.info('User logged in', { userId: '123' });
34
+ * logger.error('Operation failed', new Error('Connection timeout'));
35
+ */
36
+ function createLogger(options = {}) {
37
+ const { level = "warn", prefix = "" } = options;
38
+ const logLevels = {
39
+ debug: 0,
40
+ info: 1,
41
+ warn: 2,
42
+ error: 3,
43
+ none: 4
44
+ };
45
+ const currentLevelValue = logLevels[level];
46
+ const formatArgs = (args) => {
47
+ if (args.length === 0 || args.every((arg) => arg === undefined || arg === null)) {
48
+ return "";
49
+ }
50
+ const formatted = args.map((arg) => {
51
+ if (arg instanceof Error) {
52
+ return `\n${arg.stack || arg.message}`;
53
+ }
54
+ if (typeof arg === "object" && arg !== null) {
55
+ return `\n${JSON.stringify(arg, null, 2)}`;
56
+ }
57
+ return ` ${String(arg)}`;
58
+ }).join("");
59
+ return `, args:${formatted}`;
60
+ };
61
+ const shouldLog = (level$1) => {
62
+ return logLevels[level$1] >= currentLevelValue;
63
+ };
64
+ return {
65
+ debug: (message, ...args) => {
66
+ if (shouldLog("debug")) {
67
+ console.debug(`\x1b[32m${prefix}[DEBUG] ${maskTokens(message)}${maskTokens(formatArgs(args))}\x1b[0m`);
68
+ }
69
+ },
70
+ info: (message, ...args) => {
71
+ if (shouldLog("info")) {
72
+ console.info(`\x1b[34m${prefix}[INFO] ${maskTokens(message)}${maskTokens(formatArgs(args))}\x1b[0m`);
73
+ }
74
+ },
75
+ warn: (message, ...args) => {
76
+ if (shouldLog("warn")) {
77
+ console.warn(`\x1b[33m${prefix}[WARN] ${maskTokens(message)}${maskTokens(formatArgs(args))}\x1b[0m`);
78
+ }
79
+ },
80
+ error: (message, ...args) => {
81
+ if (shouldLog("error")) {
82
+ console.error(`\x1b[31m${prefix}[ERROR] ${maskTokens(message)}${maskTokens(formatArgs(args))}\x1b[0m`);
83
+ }
84
+ }
85
+ };
86
+ }
87
+ /**
88
+ * Default logger instance with standard configuration
89
+ */
90
+ const logger = createLogger();
91
+
92
+ //#endregion
93
+ //#region src/retry.ts
94
+ /**
95
+ * Retry a function when it fails.
96
+ * @param fn - The function to retry.
97
+ * @param maxRetries - The maximum number of retries.
98
+ * @param initialSleepTime - The initial time to sleep between exponential backoff retries.
99
+ * @param stopOnError - The function to stop on error.
100
+ * @returns The result of the function or undefined if it fails.
101
+ * @example
102
+ * import { retryWhenFailed } from "@settlemint/sdk-utils";
103
+ * import { readFile } from "node:fs/promises";
104
+ *
105
+ * const result = await retryWhenFailed(() => readFile("/path/to/file.txt"), 3, 1_000);
106
+ */
107
+ async function retryWhenFailed(fn, maxRetries = 5, initialSleepTime = 1e3, stopOnError) {
108
+ let retries = 0;
109
+ const maxAttempts = maxRetries + 1;
110
+ while (retries < maxAttempts) {
111
+ try {
112
+ return await fn();
113
+ } catch (e) {
114
+ const error = e;
115
+ if (typeof stopOnError === "function") {
116
+ if (stopOnError(error)) {
117
+ throw error;
118
+ }
119
+ }
120
+ if (retries >= maxRetries) {
121
+ throw e;
122
+ }
123
+ const baseDelay = 2 ** retries * initialSleepTime;
124
+ const jitterAmount = initialSleepTime * (Math.random() / 10);
125
+ const delay = baseDelay + jitterAmount;
126
+ retries += 1;
127
+ logger.warn(`An error occurred ${error.message}, retrying in ${delay.toFixed(0)}ms (retry ${retries} of ${maxRetries})...`);
128
+ await new Promise((resolve) => setTimeout(resolve, delay));
129
+ }
130
+ }
131
+ throw new Error("Retry failed");
132
+ }
133
+
134
+ //#endregion
135
+ //#region src/http/fetch-with-retry.ts
136
+ /**
137
+ * Retry an HTTP request with exponential backoff and jitter.
138
+ * Only retries on server errors (5xx), rate limits (429), timeouts (408), and network errors.
139
+ *
140
+ * @param input - The URL or Request object to fetch
141
+ * @param init - The fetch init options
142
+ * @param maxRetries - Maximum number of retry attempts
143
+ * @param initialSleepTime - Initial sleep time between retries in ms
144
+ * @returns The fetch Response
145
+ * @throws Error if all retries fail
146
+ * @example
147
+ * import { fetchWithRetry } from "@settlemint/sdk-utils/http";
148
+ *
149
+ * const response = await fetchWithRetry("https://api.example.com/data");
150
+ */
151
+ async function fetchWithRetry(input, init, maxRetries = 5, initialSleepTime = 3e3) {
152
+ return retryWhenFailed(async () => {
153
+ const response = await fetch(input, init);
154
+ if (response.ok) {
155
+ return response;
156
+ }
157
+ if (response.status < 500 && response.status !== 429 && response.status !== 408 && response.status !== 0) {
158
+ return response;
159
+ }
160
+ throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);
161
+ }, maxRetries, initialSleepTime);
162
+ }
163
+
164
+ //#endregion
165
+ //#region src/http/graphql-fetch-with-retry.ts
166
+ /**
167
+ * Executes a GraphQL request with automatic retries using exponential backoff and jitter.
168
+ * Only retries on server errors (5xx), rate limits (429), timeouts (408), and network errors.
169
+ * Will also retry if the GraphQL response contains errors.
170
+ *
171
+ * @param input - The URL or Request object for the GraphQL endpoint
172
+ * @param init - Optional fetch configuration options
173
+ * @param maxRetries - Maximum retry attempts before failing (default: 5)
174
+ * @param initialSleepTime - Initial delay between retries in milliseconds (default: 3000)
175
+ * @returns The parsed GraphQL response data
176
+ * @throws Error if all retries fail or if GraphQL response contains errors
177
+ * @example
178
+ * import { graphqlFetchWithRetry } from "@settlemint/sdk-utils/http";
179
+ *
180
+ * const data = await graphqlFetchWithRetry<{ user: { id: string } }>(
181
+ * "https://api.example.com/graphql",
182
+ * {
183
+ * method: "POST",
184
+ * headers: { "Content-Type": "application/json" },
185
+ * body: JSON.stringify({
186
+ * query: `query GetUser($id: ID!) {
187
+ * user(id: $id) {
188
+ * id
189
+ * }
190
+ * }`,
191
+ * variables: { id: "123" }
192
+ * })
193
+ * }
194
+ * );
195
+ */
196
+ async function graphqlFetchWithRetry(input, init, maxRetries = 5, initialSleepTime = 3e3) {
197
+ return retryWhenFailed(async () => {
198
+ const response = await fetchWithRetry(input, init);
199
+ const json = await response.json();
200
+ if (json.errors) {
201
+ throw new Error(`GraphQL errors in response: ${json.errors.map((error) => error.message).join(", ")}`);
202
+ }
203
+ return json.data;
204
+ }, maxRetries, initialSleepTime);
205
+ }
206
+
207
+ //#endregion
208
+ //#region src/http/headers.ts
209
+ function appendHeaders(headers, additionalHeaders) {
210
+ const defaultHeaders = typeof headers === "function" ? headers() : headers;
211
+ const filteredAdditionalHeaders = Object.entries(additionalHeaders).filter(([_, value]) => value !== undefined);
212
+ if (Array.isArray(defaultHeaders)) {
213
+ return [...defaultHeaders, ...filteredAdditionalHeaders];
214
+ }
215
+ if (defaultHeaders instanceof Headers) {
216
+ return new Headers([...defaultHeaders, ...filteredAdditionalHeaders]);
217
+ }
218
+ return {
219
+ ...defaultHeaders,
220
+ ...Object.fromEntries(filteredAdditionalHeaders)
221
+ };
222
+ }
223
+
224
+ //#endregion
225
+ export { appendHeaders, fetchWithRetry, graphqlFetchWithRetry };
226
+ //# sourceMappingURL=http.js.map