@zapier/zapier-sdk 0.103.0 → 0.104.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @zapier/zapier-sdk
2
2
 
3
+ ## 0.104.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 1ec9410: SDK HTTP requests now automatically retry HTTP 500, 502, 503, and 504 responses for idempotent methods; HTTP 429 responses continue to retry for any method. All retryable responses share the budget set by `maxNetworkRetries`, with exponential backoff capped by `maxNetworkRetryDelaySeconds`; set `maxNetworkRetries: 0` to disable retries. Callers that pass a custom `sendHttpRequest` transport to `createZapierApi` remain responsible for its retry behavior.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [1ec9410]
12
+ - Updated dependencies [1ec9410]
13
+ - @zapier/kitcore@0.19.0
14
+
3
15
  ## 0.103.0
4
16
 
5
17
  ### Minor Changes
package/README.md CHANGED
@@ -376,8 +376,8 @@ The `createZapierSdk(...)` factory function is the main entry point for the SDK.
376
376
  | `debug` | `boolean` | ❌ | — | — | Enable debug logging. |
377
377
  | `baseUrl` | `string` | ❌ | — | — | Base URL for Zapier API endpoints. |
378
378
  | `trackingBaseUrl` | `string` | ❌ | — | — | Base URL for Zapier tracking endpoints. |
379
- | `maxNetworkRetries` | `number` | ❌ | — | — | Max retries for rate-limited requests (default: 3). |
380
- | `maxNetworkRetryDelaySeconds` | `number` | ❌ | — | — | Max delay in seconds to wait for a rate-limit retry (default: 60). |
379
+ | `maxNetworkRetries` | `number` | ❌ | — | — | Max retries for rate-limited and server-error responses (default: 3). |
380
+ | `maxNetworkRetryDelaySeconds` | `number` | ❌ | — | — | Max delay in seconds to wait between network retries (default: 60). |
381
381
  | `maxConcurrentRequests` | `number, literal` | ❌ | — | — | Max concurrent in-flight HTTP requests (default: 200, max: 10000). |
382
382
  | `approvalTimeoutSeconds` | `number` | ❌ | — | — | Timeout in seconds for approval polling. Default: 600 (10 min). |
383
383
  | `maxApprovalRetries` | `number` | ❌ | — | — | Maximum number of sequential approval rounds per request (one per gating policy) before giving up. Default: 2. |
@@ -1,6 +1,6 @@
1
1
  import { __require } from './chunk-Y6FXYEAI.mjs';
2
2
  import { z } from 'zod';
3
- import { withPositional, declareOptionalProperty, defineProperty, createDeprecationLogger, createAsyncContext, definePlugin, sendHttpRequestPlugin, declareProperty, defineMethod, coreOptionsPluginRef, createValidator, defineFormatter, declareMethod, defineResolver, concatLists, openEnum, defineHook, getRegistryPlugin, paginate, toSnakeCase, isCoreError, toTitleCase, createSdk, CORE_ERROR_SYMBOL, CoreErrorCode, CORE_SIGNAL_SYMBOL, isCoreSignal, CORE_OPTIONS_ID } from '@zapier/kitcore';
3
+ import { withPositional, declareOptionalProperty, defineProperty, createDeprecationLogger, createAsyncContext, definePlugin, sendHttpRequestPlugin, retryHttpRequestPlugin, declareProperty, defineMethod, coreOptionsPluginRef, createValidator, defineFormatter, declareMethod, defineResolver, concatLists, openEnum, defineHook, getRegistryPlugin, paginate, toSnakeCase, isCoreError, toTitleCase, createSdk, RETRY_HTTP_REQUEST_OPTIONS_ID, CORE_ERROR_SYMBOL, CoreErrorCode, CORE_SIGNAL_SYMBOL, isCoreSignal, CORE_OPTIONS_ID } from '@zapier/kitcore';
4
4
  export { CONTEXT, CORE_ERROR_SYMBOL, CORE_OPTIONS_ID, CORE_SIGNAL_SYMBOL, CoreCancelledSignal, CoreDisposeError, CoreErrorCode, CoreSignal, addPlugin, composePlugins, createController, createCorePlugin, createFunction, createPaginatedFunction, createPaginatedPluginMethod, createPluginMethod, createPluginStack, createSdk, declareMethod, declareOptionalProperty, declarePlugin, declareProperty, defineFormatter, defineLegacyMerge, defineMethod, defineMethodOverride, defineOverride, definePlugin, defineProperty, defineResolver, disposeSdk, fromFunctionPlugin, getContext, getCoreErrorCause, getCoreErrorCode, getNegatable, getRegistryPlugin, isCoreCancelledSignal, isCoreError, isCoreSignal, isPositional, omitExports, resolvePlugin, runInMethodScope, runWithTelemetryContext, selectExports, toSnakeCase, toTitleCase } from '@zapier/kitcore';
5
5
  import { buildHttpRequestContext, buildActionRunContext } from '@zapier/policy-context';
6
6
  import { ListAppsQuerySchema, AppItemSchema as AppItemSchema$1 } from '@zapier/zapier-sdk-core/v0/schemas/apps';
@@ -705,7 +705,6 @@ function createDebugFetch(options) {
705
705
  // src/utils/retry-utils.ts
706
706
  var MAX_CONSECUTIVE_ERRORS = 3;
707
707
  var BASE_ERROR_BACKOFF_MILLISECONDS = 1e3;
708
- var BASE_EXPONENTIAL_BACKOFF_MILLISECONDS = 1e3;
709
708
  var JITTER_FACTOR = 0.5;
710
709
  function calculateErrorBackoffMs(baseInterval, errorCount) {
711
710
  const jitter = Math.random() * JITTER_FACTOR * baseInterval;
@@ -716,11 +715,6 @@ function calculateErrorBackoffMs(baseInterval, errorCount) {
716
715
  );
717
716
  return Math.floor(baseInterval + jitter + errorBackoff);
718
717
  }
719
- function calculateExponentialBackoffMs(attempt, baseDelayMs = BASE_EXPONENTIAL_BACKOFF_MILLISECONDS) {
720
- const baseDelay = baseDelayMs * Math.pow(2, attempt - 1);
721
- const jitter = Math.random() * JITTER_FACTOR * baseDelay;
722
- return Math.floor(baseDelay + jitter);
723
- }
724
718
  function sleep(ms, signal) {
725
719
  if (!signal) {
726
720
  return new Promise((resolve2) => setTimeout(resolve2, ms));
@@ -1075,7 +1069,114 @@ var sdkOptionsPluginRef = declareOptionalProperty({
1075
1069
  id: SDK_OPTIONS_ID
1076
1070
  });
1077
1071
 
1072
+ // src/api/rate-limit.ts
1073
+ var EPOCH_THRESHOLD_SECONDS = 1e9;
1074
+ function parseRateLimitHeaders(response) {
1075
+ const info = {};
1076
+ const retryAfter = response.headers.get("retry-after");
1077
+ if (retryAfter) {
1078
+ const seconds = parseInt(retryAfter, 10);
1079
+ if (!isNaN(seconds)) {
1080
+ info.retryAfterMs = Math.max(0, seconds * 1e3);
1081
+ } else {
1082
+ const date = Date.parse(retryAfter);
1083
+ if (!isNaN(date)) {
1084
+ info.retryAfterMs = Math.max(0, date - Date.now());
1085
+ }
1086
+ }
1087
+ }
1088
+ const reset = response.headers.get("x-ratelimit-reset");
1089
+ if (reset) {
1090
+ const resetValue = parseInt(reset, 10);
1091
+ if (!isNaN(resetValue)) {
1092
+ const isEpoch = resetValue >= EPOCH_THRESHOLD_SECONDS;
1093
+ info.resetMs = isEpoch ? resetValue * 1e3 : Date.now() + resetValue * 1e3;
1094
+ if (info.retryAfterMs === void 0) {
1095
+ info.retryAfterMs = isEpoch ? Math.max(0, info.resetMs - Date.now()) : Math.max(0, resetValue * 1e3);
1096
+ }
1097
+ }
1098
+ }
1099
+ const limit = response.headers.get("x-ratelimit-limit");
1100
+ if (limit) {
1101
+ const limitNum = parseInt(limit, 10);
1102
+ if (!isNaN(limitNum)) {
1103
+ info.limit = limitNum;
1104
+ }
1105
+ }
1106
+ const remaining = response.headers.get("x-ratelimit-remaining");
1107
+ if (remaining) {
1108
+ const remainingNum = parseInt(remaining, 10);
1109
+ if (!isNaN(remainingNum)) {
1110
+ info.remaining = remainingNum;
1111
+ }
1112
+ }
1113
+ return info;
1114
+ }
1115
+
1116
+ // src/utils/type-guard-utils.ts
1117
+ function isPlainObject(value) {
1118
+ if (typeof value !== "object" || value === null) return false;
1119
+ const proto = Object.getPrototypeOf(value);
1120
+ return proto === Object.prototype || proto === null;
1121
+ }
1122
+ function isPromiseLike(value) {
1123
+ return (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
1124
+ }
1125
+
1126
+ // src/plugins/transport/retry-events.ts
1127
+ var retryCounts = /* @__PURE__ */ new WeakMap();
1128
+ function retriesFor(request) {
1129
+ return retryCounts.get(request) ?? 0;
1130
+ }
1131
+ function createRetryObserver({
1132
+ onEvent,
1133
+ maxNetworkRetries
1134
+ }) {
1135
+ return ({ request, attemptNumber, delayMilliseconds, response }) => {
1136
+ retryCounts.set(request, attemptNumber);
1137
+ if (!onEvent || response?.status !== 429) return;
1138
+ const observed = onEvent({
1139
+ type: "api:rate_limit_retry",
1140
+ payload: {
1141
+ retry: attemptNumber,
1142
+ maxNetworkRetries,
1143
+ delayMs: delayMilliseconds,
1144
+ path: request.url,
1145
+ method: request.method ?? "GET",
1146
+ rateLimit: parseRateLimitHeaders(response)
1147
+ },
1148
+ timestamp: Date.now()
1149
+ });
1150
+ if (isPromiseLike(observed)) {
1151
+ void Promise.resolve(observed).catch(() => {
1152
+ });
1153
+ }
1154
+ };
1155
+ }
1156
+
1078
1157
  // src/plugins/transport/options.ts
1158
+ var RETRYABLE_STATUSES = [429, 500, 502, 503, 504];
1159
+ var NON_IDEMPOTENT_RETRYABLE_STATUSES = [429];
1160
+ function resolveRetryHttpRequestOptions({
1161
+ maxNetworkRetries,
1162
+ maxNetworkRetryDelayMilliseconds,
1163
+ onEvent
1164
+ }) {
1165
+ const retries = maxNetworkRetries ?? ZAPIER_MAX_NETWORK_RETRIES;
1166
+ return {
1167
+ maxAttempts: retries + 1,
1168
+ maxDelayMilliseconds: maxNetworkRetryDelayMilliseconds ?? ZAPIER_MAX_NETWORK_RETRY_DELAY_MILLISECONDS,
1169
+ retryStatuses: RETRYABLE_STATUSES,
1170
+ nonIdempotentRetryStatuses: NON_IDEMPOTENT_RETRYABLE_STATUSES,
1171
+ onRetry: createRetryObserver({ onEvent, maxNetworkRetries: retries })
1172
+ };
1173
+ }
1174
+ function resolveNetworkRetryDelayMilliseconds({
1175
+ maxNetworkRetryDelaySeconds,
1176
+ maxNetworkRetryDelayMs
1177
+ }) {
1178
+ return maxNetworkRetryDelaySeconds != null ? maxNetworkRetryDelaySeconds * 1e3 : maxNetworkRetryDelayMs;
1179
+ }
1079
1180
  function resolveTransportFetch({
1080
1181
  fetch: customFetch,
1081
1182
  debug = false
@@ -1103,15 +1204,29 @@ var httpFetchPlugin = defineProperty({
1103
1204
  // src/plugins/transport/standalone.ts
1104
1205
  function createZapierSendHttpRequest({
1105
1206
  fetch: customFetch,
1106
- debug
1207
+ debug,
1208
+ maxNetworkRetries,
1209
+ maxNetworkRetryDelayMilliseconds,
1210
+ onEvent
1107
1211
  }) {
1108
1212
  const sdk = createSdk(
1109
1213
  definePlugin({
1110
1214
  name: "zapierStandaloneHttpTransport",
1111
- imports: [sendHttpRequestPlugin, httpFetchPlugin],
1215
+ imports: [sendHttpRequestPlugin, retryHttpRequestPlugin, httpFetchPlugin],
1112
1216
  exports: [sendHttpRequestPlugin]
1113
1217
  }),
1114
- { configuration: { [SDK_OPTIONS_ID]: { fetch: customFetch, debug } } }
1218
+ {
1219
+ configuration: {
1220
+ [SDK_OPTIONS_ID]: { fetch: customFetch, debug },
1221
+ // Filled by configuration rather than the graph's property plugin: the
1222
+ // caller here holds client-shaped ms options, not SDK options.
1223
+ [RETRY_HTTP_REQUEST_OPTIONS_ID]: resolveRetryHttpRequestOptions({
1224
+ maxNetworkRetries,
1225
+ maxNetworkRetryDelayMilliseconds,
1226
+ onEvent
1227
+ })
1228
+ }
1229
+ }
1115
1230
  );
1116
1231
  return sdk.sendHttpRequest;
1117
1232
  }
@@ -1769,13 +1884,6 @@ async function invalidateCredentialsToken(options) {
1769
1884
  });
1770
1885
  }
1771
1886
  }
1772
-
1773
- // src/utils/type-guard-utils.ts
1774
- function isPlainObject(value) {
1775
- if (typeof value !== "object" || value === null) return false;
1776
- const proto = Object.getPrototypeOf(value);
1777
- return proto === Object.prototype || proto === null;
1778
- }
1779
1887
  var callerContext = createAsyncContext();
1780
1888
  function runWithCallerContext(context, fn) {
1781
1889
  let parent;
@@ -2021,9 +2129,6 @@ function sniffDeprecationNotice({
2021
2129
  }
2022
2130
  }
2023
2131
  }
2024
- function isPromiseLike(value) {
2025
- return (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
2026
- }
2027
2132
  function parseDeprecationDate(value) {
2028
2133
  if (!value) return void 0;
2029
2134
  const match = /^@(-?\d+)$/.exec(value.trim());
@@ -2552,7 +2657,7 @@ function logRouteOverride({
2552
2657
  }
2553
2658
 
2554
2659
  // src/sdk-version.ts
2555
- var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.103.0" : void 0) || "unknown";
2660
+ var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.104.0" : void 0) || "unknown";
2556
2661
 
2557
2662
  // src/utils/open-url.ts
2558
2663
  var nodePrefix = "node:";
@@ -2668,7 +2773,6 @@ var PollApprovalResponseSchema = z.object({
2668
2773
  approval_url: z.string().optional()
2669
2774
  });
2670
2775
  var APPROVAL_MAX_POLLING_INTERVAL_MILLISECONDS = 5e3;
2671
- var EPOCH_THRESHOLD_SECONDS = 1e9;
2672
2776
  function validateSdkPath(path) {
2673
2777
  if (!path.startsWith("/") || path.startsWith("//")) {
2674
2778
  throw new ZapierValidationError(
@@ -2676,57 +2780,17 @@ function validateSdkPath(path) {
2676
2780
  );
2677
2781
  }
2678
2782
  }
2679
- function parseRateLimitHeaders(response) {
2680
- const info = {};
2681
- const retryAfter = response.headers.get("retry-after");
2682
- if (retryAfter) {
2683
- const seconds = parseInt(retryAfter, 10);
2684
- if (!isNaN(seconds)) {
2685
- info.retryAfterMs = seconds * 1e3;
2686
- } else {
2687
- const date = Date.parse(retryAfter);
2688
- if (!isNaN(date)) {
2689
- info.retryAfterMs = Math.max(0, date - Date.now());
2690
- }
2691
- }
2692
- }
2693
- const reset = response.headers.get("x-ratelimit-reset");
2694
- if (reset) {
2695
- const resetValue = parseInt(reset, 10);
2696
- if (!isNaN(resetValue)) {
2697
- const isEpoch = resetValue >= EPOCH_THRESHOLD_SECONDS;
2698
- info.resetMs = isEpoch ? resetValue * 1e3 : Date.now() + resetValue * 1e3;
2699
- if (info.retryAfterMs === void 0) {
2700
- info.retryAfterMs = isEpoch ? Math.max(0, info.resetMs - Date.now()) : Math.max(0, resetValue * 1e3);
2701
- }
2702
- }
2703
- }
2704
- const limit = response.headers.get("x-ratelimit-limit");
2705
- if (limit) {
2706
- const limitNum = parseInt(limit, 10);
2707
- if (!isNaN(limitNum)) {
2708
- info.limit = limitNum;
2709
- }
2710
- }
2711
- const remaining = response.headers.get("x-ratelimit-remaining");
2712
- if (remaining) {
2713
- const remainingNum = parseInt(remaining, 10);
2714
- if (!isNaN(remainingNum)) {
2715
- info.remaining = remainingNum;
2716
- }
2717
- }
2718
- return info;
2719
- }
2720
2783
  var ZapierApiClient = class {
2721
2784
  constructor(options) {
2722
2785
  this.options = options;
2723
2786
  /**
2724
2787
  * Perform a request against an already-resolved URL.
2725
2788
  *
2726
- * Does auth, header merging, and 429 retry all the cross-cutting
2727
- * concerns that every Zapier-bound HTTP call needs. Callers that have a
2728
- * path (e.g. `/relay/...`) should use `rawFetch` instead, which does
2729
- * path URL resolution and delegates here.
2789
+ * Does auth and header merging, and converts a terminal 429 into
2790
+ * `ZapierRateLimitError` the cross-cutting concerns that every
2791
+ * Zapier-bound HTTP call needs and that the transport does not own. Callers
2792
+ * that have a path (e.g. `/relay/...`) should use `rawFetch` instead, which
2793
+ * does path → URL resolution and delegates here.
2730
2794
  *
2731
2795
  * Exposed as a separate helper so call sites with a server-supplied
2732
2796
  * absolute URL (e.g. an approval poll URL) can still share the same
@@ -2760,47 +2824,30 @@ var ZapierApiClient = class {
2760
2824
  resource: _resource,
2761
2825
  ...wireInit
2762
2826
  } = fetchInit;
2763
- let retries = 0;
2764
- while (true) {
2765
- const response = await this.options.sendHttpRequest({
2766
- ...wireInit,
2767
- // Set the resolved URL and merged headers after the spread so caller
2768
- // values cannot override them.
2769
- url,
2770
- headers: Object.fromEntries(mergedHeaders)
2771
- });
2772
- if (response.status !== 429) {
2773
- return response;
2774
- }
2775
- const rateLimitInfo = parseRateLimitHeaders(response);
2776
- const delayMs = rateLimitInfo.retryAfterMs ?? calculateExponentialBackoffMs(retries + 1);
2777
- if (delayMs > this.maxNetworkRetryDelayMilliseconds || retries >= this.maxNetworkRetries) {
2778
- throw new ZapierRateLimitError(
2779
- await this.readRateLimitErrorMessage(response),
2780
- {
2781
- statusCode: 429,
2782
- rateLimit: rateLimitInfo,
2783
- retries
2784
- }
2785
- );
2786
- }
2787
- retries++;
2788
- this.emitEvent("api:rate_limit_retry", {
2789
- retry: retries,
2790
- maxNetworkRetries: this.maxNetworkRetries,
2791
- delayMs,
2792
- path: url,
2793
- method: init?.method ?? "GET",
2794
- rateLimit: rateLimitInfo
2795
- });
2796
- await sleep(delayMs, init?.signal ?? void 0);
2827
+ const request = {
2828
+ ...wireInit,
2829
+ url,
2830
+ headers: Object.fromEntries(mergedHeaders)
2831
+ };
2832
+ const response = await this.options.sendHttpRequest(request);
2833
+ if (response.status !== 429) {
2834
+ return response;
2797
2835
  }
2836
+ throw new ZapierRateLimitError(
2837
+ await this.readRateLimitErrorMessage(response),
2838
+ {
2839
+ statusCode: 429,
2840
+ rateLimit: parseRateLimitHeaders(response),
2841
+ retries: retriesFor(request)
2842
+ }
2843
+ );
2798
2844
  };
2799
2845
  /**
2800
2846
  * Wrap an outbound HTTP call with the concurrency semaphore. Used by both
2801
2847
  * `rawFetch` (path-based) and the approval-poll path (absolute URL); each
2802
- * caller acquires per-attempt, so 429 retry sleep is held but the gap
2803
- * between approval polls and the human-approval wait are not.
2848
+ * caller acquires per request, so the transport's retry sleeps are held
2849
+ * inside the permit but the gap between approval polls and the
2850
+ * human-approval wait are not.
2804
2851
  *
2805
2852
  * The release is registered in a finally that wraps the entire post-
2806
2853
  * acquire flow — including the `wait_end` event emission — so a throwing
@@ -3050,8 +3097,6 @@ var ZapierApiClient = class {
3050
3097
  signal: options.signal
3051
3098
  });
3052
3099
  };
3053
- this.maxNetworkRetries = options.maxNetworkRetries ?? ZAPIER_MAX_NETWORK_RETRIES;
3054
- this.maxNetworkRetryDelayMilliseconds = options.maxNetworkRetryDelayMilliseconds ?? options.maxNetworkRetryDelayMs ?? ZAPIER_MAX_NETWORK_RETRY_DELAY_MILLISECONDS;
3055
3100
  const requested = options.maxConcurrentRequests;
3056
3101
  const limit = requested === void 0 || Number.isNaN(requested) ? ZAPIER_MAX_CONCURRENT_REQUESTS : requested;
3057
3102
  if (limit !== Infinity && (!Number.isInteger(limit) || limit < 1 || limit > MAX_CONCURRENCY_LIMIT)) {
@@ -3807,7 +3852,13 @@ var createZapierApi = (options) => {
3807
3852
  fetch: debugFetch,
3808
3853
  // Built from the caller's own `fetch`, not `debugFetch`: the pipeline wraps
3809
3854
  // for debug itself, and passing the wrapped one would log twice.
3810
- sendHttpRequest: options.sendHttpRequest ?? createZapierSendHttpRequest({ fetch: options.fetch, debug }),
3855
+ sendHttpRequest: options.sendHttpRequest ?? createZapierSendHttpRequest({
3856
+ fetch: options.fetch,
3857
+ debug,
3858
+ onEvent: options.onEvent,
3859
+ maxNetworkRetries: options.maxNetworkRetries,
3860
+ maxNetworkRetryDelayMilliseconds: options.maxNetworkRetryDelayMilliseconds ?? options.maxNetworkRetryDelayMs
3861
+ }),
3811
3862
  debugLog,
3812
3863
  routingOptions
3813
3864
  });
@@ -3846,10 +3897,30 @@ function getOrCreateApiClient(config) {
3846
3897
  callerPackage
3847
3898
  });
3848
3899
  }
3900
+ var retryHttpRequestOptionsPlugin = defineProperty({
3901
+ namespace: "kitcore",
3902
+ name: "retryHttpRequestOptions",
3903
+ imports: [sdkOptionsPluginRef],
3904
+ setup: ({ imports }) => resolveRetryHttpRequestOptions({
3905
+ maxNetworkRetries: imports.sdkOptions?.maxNetworkRetries,
3906
+ maxNetworkRetryDelayMilliseconds: resolveNetworkRetryDelayMilliseconds(
3907
+ imports.sdkOptions ?? {}
3908
+ ),
3909
+ onEvent: imports.sdkOptions?.onEvent
3910
+ }),
3911
+ get: ({ state }) => state
3912
+ });
3913
+
3914
+ // src/plugins/transport/index.ts
3849
3915
  var zapierHttpTransportPlugin = definePlugin({
3850
3916
  namespace: "zapier",
3851
3917
  name: "httpTransport",
3852
- imports: [sendHttpRequestPlugin, httpFetchPlugin],
3918
+ imports: [
3919
+ sendHttpRequestPlugin,
3920
+ retryHttpRequestPlugin,
3921
+ retryHttpRequestOptionsPlugin,
3922
+ httpFetchPlugin
3923
+ ],
3853
3924
  exports: [sendHttpRequestPlugin]
3854
3925
  });
3855
3926
 
@@ -3909,7 +3980,10 @@ var apiPlugin = defineProperty({
3909
3980
  fetch: customFetch,
3910
3981
  onEvent,
3911
3982
  maxNetworkRetries,
3912
- maxNetworkRetryDelayMilliseconds: (maxNetworkRetryDelaySeconds != null ? maxNetworkRetryDelaySeconds * 1e3 : maxNetworkRetryDelayMs) ?? ZAPIER_MAX_NETWORK_RETRY_DELAY_MILLISECONDS,
3983
+ maxNetworkRetryDelayMilliseconds: resolveNetworkRetryDelayMilliseconds({
3984
+ maxNetworkRetryDelaySeconds,
3985
+ maxNetworkRetryDelayMs
3986
+ }) ?? ZAPIER_MAX_NETWORK_RETRY_DELAY_MILLISECONDS,
3913
3987
  maxConcurrentRequests,
3914
3988
  approvalTimeoutMilliseconds: approvalTimeoutSeconds != null ? approvalTimeoutSeconds * 1e3 : approvalTimeoutMs,
3915
3989
  maxApprovalRetries,
@@ -12314,17 +12388,20 @@ var BaseSdkOptionsSchema = z.object({
12314
12388
  routeOverrides: z.record(z.string(), z.string()).optional().describe("Maps SDK route prefixes to direct origins.").meta({ internal: true }),
12315
12389
  trackingBaseUrl: z.string().optional().describe("Base URL for Zapier tracking endpoints.").meta({ valueHint: "url" }),
12316
12390
  /**
12317
- * Maximum number of retries for rate-limited requests (429 responses).
12391
+ * Maximum number of retries for rate-limited requests (429 responses) and,
12392
+ * on idempotent methods, retryable server errors (500, 502, 503, 504).
12318
12393
  * Set to 0 to disable retries. Default is 3.
12319
12394
  */
12320
- maxNetworkRetries: z.number().optional().describe("Max retries for rate-limited requests (default: 3).").meta({ valueHint: "count" }),
12395
+ maxNetworkRetries: z.number().optional().describe(
12396
+ "Max retries for rate-limited and server-error responses (default: 3)."
12397
+ ).meta({ valueHint: "count" }),
12321
12398
  /**
12322
- * Maximum delay in seconds to wait for a rate-limit retry.
12399
+ * Maximum delay in seconds to wait between network retries.
12323
12400
  * If the server requests a longer delay, the request fails immediately.
12324
12401
  * Default is 60 (60 seconds).
12325
12402
  */
12326
12403
  maxNetworkRetryDelaySeconds: z.number().optional().describe(
12327
- "Max delay in seconds to wait for a rate-limit retry (default: 60)."
12404
+ "Max delay in seconds to wait between network retries (default: 60)."
12328
12405
  ).meta({ valueHint: "seconds" }),
12329
12406
  /** @deprecated Use `maxNetworkRetryDelaySeconds` instead. */
12330
12407
  maxNetworkRetryDelayMs: z.number().optional().describe("Max delay in ms to wait for retry (default: 60000).").meta({ valueHint: "ms", deprecated: true }),