@ehrenkind/shopify-lib 0.8.2 → 0.8.3

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/index.mjs CHANGED
@@ -143,13 +143,21 @@ var RETRYABLE_ERROR_CODES = /* @__PURE__ */ new Set([
143
143
  "UND_ERR_SOCKET",
144
144
  "UND_ERR_CONNECT_TIMEOUT",
145
145
  "UND_ERR_HEADERS_TIMEOUT",
146
- "UND_ERR_BODY_TIMEOUT"
146
+ "UND_ERR_BODY_TIMEOUT",
147
+ // Shopify GraphQL rate limiting — backoff lets the leaky bucket refill
148
+ "THROTTLED"
147
149
  ]);
148
150
  function hasRetryableCode(value) {
149
151
  if (!value || typeof value !== "object") return false;
150
152
  const code = value.code;
151
153
  return typeof code === "string" && RETRYABLE_ERROR_CODES.has(code);
152
154
  }
155
+ function isThrottledErrors(errors) {
156
+ const list = Array.isArray(errors) ? errors : [errors];
157
+ return list.some(
158
+ (e) => e?.extensions?.code === "THROTTLED"
159
+ );
160
+ }
153
161
  function isRetryableError(error) {
154
162
  if (!(error instanceof Error)) return false;
155
163
  if (hasRetryableCode(error)) return true;
@@ -237,7 +245,12 @@ async function makeRequest(query, variables, retries = 0) {
237
245
  errorMessages = JSON.stringify(errors);
238
246
  }
239
247
  logger.error("GraphQL query failed:", errorMessages);
240
- throw new Error(`GraphQL errors: ${errorMessages}`);
248
+ const graphqlError = new Error(`GraphQL errors: ${errorMessages}`);
249
+ if (isThrottledErrors(errors)) {
250
+ ;
251
+ graphqlError.code = "THROTTLED";
252
+ }
253
+ throw graphqlError;
241
254
  }
242
255
  if (!response.data) {
243
256
  throw new Error("No data in Shopify API response");