@zapier/zapier-sdk 0.102.0 → 0.102.2
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 +17 -0
- package/README.md +45 -45
- package/dist/{chunk-V4FAEYKU.cjs → chunk-J5ELTMEQ.cjs} +26 -10
- package/dist/{chunk-SAKWJ4RS.mjs → chunk-WWJRIDEW.mjs} +26 -10
- package/dist/experimental.cjs +367 -361
- package/dist/experimental.mjs +14 -8
- package/dist/index.cjs +277 -277
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @zapier/zapier-sdk
|
|
2
2
|
|
|
3
|
+
## 0.102.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b6dfdf9: `runDurable`, `publishWorkflowVersion` and `updateWorkflowDraft` document that `"latest"` is accepted for the durable runtime version and, in `dependencies`, for `@zapier/zapier-durable` and `@zapier/zapier-sdk`. The server resolves those to the newest release old enough to install — not npm's `"latest"` tag, which can point at a release too new to install. A `"latest"` on any other package is passed to the install unchanged. On a draft the value is stored verbatim and resolved when the draft is published.
|
|
8
|
+
|
|
9
|
+
## 0.102.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 173df80: `ZapierRateLimitError` now surfaces the server's explanatory message — quota used, when the window resets, and how to request a higher limit — instead of the bare string "Rate limited". When the response body is empty or unreadable, the message falls back to "Rate limited" as before.
|
|
14
|
+
|
|
15
|
+
`rateLimit.resetMs` on the error is now a real epoch timestamp when the server sends `X-RateLimit-Reset` as seconds-until-reset (the IETF draft convention) instead of a date in 1970. This also fixes the retry delay computed from that header when `Retry-After` is absent, which previously collapsed to zero and retried immediately.
|
|
16
|
+
|
|
17
|
+
- Updated dependencies [173df80]
|
|
18
|
+
- @zapier/kitcore@0.17.2
|
|
19
|
+
|
|
3
20
|
## 0.102.0
|
|
4
21
|
|
|
5
22
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -2088,23 +2088,23 @@ Publish a new version of a durable workflow. Enables the workflow by default.
|
|
|
2088
2088
|
|
|
2089
2089
|
**Parameters:**
|
|
2090
2090
|
|
|
2091
|
-
| Name | Type | Required | Default | Possible Values | Description
|
|
2092
|
-
| -------------------------- | --------- | -------- | ------- | --------------- |
|
|
2093
|
-
| `options` | `object` | ✅ | — | — |
|
|
2094
|
-
| ↳ `workflow` | `string` | ✅ | — | — | Durable workflow ID
|
|
2095
|
-
| ↳ `sourceFiles` | `object` | ✅ | — | — | Source files keyed by filename → contents
|
|
2096
|
-
| ↳ `dependencies` | `object` | ❌ | — | — | Optional npm package dependencies
|
|
2097
|
-
| ↳ `zapierDurableVersion` | `string` | ❌ | — | — | Exact semver of @zapier/zapier-durable to use (e.g. "1.2.3"). Defaults to server-configured version if omitted.
|
|
2098
|
-
| ↳ `enabled` | `boolean` | ❌ | — | — | Enable the workflow after publishing. Defaults to true if omitted; pass false to publish without enabling.
|
|
2099
|
-
| ↳ `ignoreOpenDrafts` | `boolean` | ❌ | — | — | Publish even though the workflow has open draft(s). Without this, the API rejects a direct publish with a 409 while any draft is open, since publishing the draft later would ship its stale content over this version.
|
|
2100
|
-
| ↳ `connections` | `object` | ❌ | — | — | Map of connection aliases to Zapier connections used by the workflow. Pass `null` to clear an existing binding.
|
|
2101
|
-
| ↳ `appVersions` | `object` | ❌ | — | — | Map of app keys to pinned app implementation/version used by the workflow. Pass `null` to clear an existing binding.
|
|
2102
|
-
| ↳ `trigger` | `object` | ❌ | — | — | Trigger configuration. When provided, the workflow subscribes to a Zapier trigger; for an on-demand, triggerless workflow, omit this and pass `manual: true` instead.
|
|
2103
|
-
| ↳ `selectedApi` | `string` | ❌ | — | — | Zapier app/API identifier (e.g. 'GoogleSheetsAPI'). Required when a trigger is configured.
|
|
2104
|
-
| ↳ `action` | `string` | ✅ | — | — | Trigger action key (e.g. 'new_row')
|
|
2105
|
-
| ↳ `authenticationId` | `string` | ❌ | — | — | Connection ID for the trigger source. Omit or pass null for no-auth triggers (e.g. Schedule by Zapier).
|
|
2106
|
-
| ↳ `params` | `object` | ❌ | — | — | Trigger parameters as a JSON object
|
|
2107
|
-
| ↳ `manual` | `boolean` | ❌ | — | — | Declare this an on-demand, triggerless workflow version. Pass `manual: true` only when omitting `trigger`; passing both is a contradiction the API rejects with a 400.
|
|
2091
|
+
| Name | Type | Required | Default | Possible Values | Description |
|
|
2092
|
+
| -------------------------- | --------- | -------- | ------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
2093
|
+
| `options` | `object` | ✅ | — | — | |
|
|
2094
|
+
| ↳ `workflow` | `string` | ✅ | — | — | Durable workflow ID |
|
|
2095
|
+
| ↳ `sourceFiles` | `object` | ✅ | — | — | Source files keyed by filename → contents |
|
|
2096
|
+
| ↳ `dependencies` | `object` | ❌ | — | — | Optional npm package dependencies. A version of "latest" is resolved by the server for @zapier/zapier-durable and @zapier/zapier-sdk only; every other value, including a "latest" on any other package, is passed to the install as written. |
|
|
2097
|
+
| ↳ `zapierDurableVersion` | `string` | ❌ | — | — | Exact semver of @zapier/zapier-durable to use (e.g. "1.2.3"), or "latest". Defaults to the server-configured version if omitted. "latest" is resolved by the server to the newest release old enough to clear the sandbox install age gate (24h) -- this is not npm's "latest" tag, which can point at a release too new to install. Ranges (^1.2.3, ~1.2) are rejected. |
|
|
2098
|
+
| ↳ `enabled` | `boolean` | ❌ | — | — | Enable the workflow after publishing. Defaults to true if omitted; pass false to publish without enabling. |
|
|
2099
|
+
| ↳ `ignoreOpenDrafts` | `boolean` | ❌ | — | — | Publish even though the workflow has open draft(s). Without this, the API rejects a direct publish with a 409 while any draft is open, since publishing the draft later would ship its stale content over this version. |
|
|
2100
|
+
| ↳ `connections` | `object` | ❌ | — | — | Map of connection aliases to Zapier connections used by the workflow. Pass `null` to clear an existing binding. |
|
|
2101
|
+
| ↳ `appVersions` | `object` | ❌ | — | — | Map of app keys to pinned app implementation/version used by the workflow. Pass `null` to clear an existing binding. |
|
|
2102
|
+
| ↳ `trigger` | `object` | ❌ | — | — | Trigger configuration. When provided, the workflow subscribes to a Zapier trigger; for an on-demand, triggerless workflow, omit this and pass `manual: true` instead. |
|
|
2103
|
+
| ↳ `selectedApi` | `string` | ❌ | — | — | Zapier app/API identifier (e.g. 'GoogleSheetsAPI'). Required when a trigger is configured. |
|
|
2104
|
+
| ↳ `action` | `string` | ✅ | — | — | Trigger action key (e.g. 'new_row') |
|
|
2105
|
+
| ↳ `authenticationId` | `string` | ❌ | — | — | Connection ID for the trigger source. Omit or pass null for no-auth triggers (e.g. Schedule by Zapier). |
|
|
2106
|
+
| ↳ `params` | `object` | ❌ | — | — | Trigger parameters as a JSON object |
|
|
2107
|
+
| ↳ `manual` | `boolean` | ❌ | — | — | Declare this an on-demand, triggerless workflow version. Pass `manual: true` only when omitting `trigger`; passing both is a contradiction the API rejects with a 400. |
|
|
2108
2108
|
|
|
2109
2109
|
**Returns:** `Promise<WorkflowVersionItem>`
|
|
2110
2110
|
|
|
@@ -2137,21 +2137,21 @@ Run a workflow source file as a run-once durable run on code-substrate-runner (n
|
|
|
2137
2137
|
|
|
2138
2138
|
**Parameters:**
|
|
2139
2139
|
|
|
2140
|
-
| Name | Type | Required | Default | Possible Values | Description
|
|
2141
|
-
| -------------------------- | ---------- | -------- | ------- | --------------- |
|
|
2142
|
-
| `options` | `object` | ✅ | — | — |
|
|
2143
|
-
| ↳ `sourceFiles` | `object` | ✅ | — | — | Source files keyed by filename → contents
|
|
2144
|
-
| ↳ `input` | `unknown` | ❌ | — | — | Input data passed to the run. Accepts any JSON value, or its JSON-string encoding.
|
|
2145
|
-
| ↳ `dependencies` | `object` | ❌ | — | — | Optional npm package dependencies
|
|
2146
|
-
| ↳ `zapierDurableVersion` | `string` | ❌ | — | — | Exact semver of @zapier/zapier-durable to use (e.g. "1.2.3"). Defaults to server-configured version if omitted.
|
|
2147
|
-
| ↳ `connections` | `object` | ❌ | — | — | Named connection aliases. Maps each alias to an object holding its Zapier connection ID, e.g. `{ "slack": { "connectionId": "123" } }`.
|
|
2148
|
-
| ↳ `appVersions` | `object` | ❌ | — | — | Pinned app versions. Maps app keys (slugs) to implementation names and versions.
|
|
2149
|
-
| ↳ `private` | `boolean` | ❌ | — | — | Only the creating user can see the run (default false)
|
|
2150
|
-
| ↳ `notifications[]` | `object[]` | ❌ | — | — | Webhook subscribers for run lifecycle events. Each entry specifies a URL and the events it subscribes to.
|
|
2151
|
-
| ↳ `type` | `string` | ❌ | — | `webhook` | Notification transport. Webhook is the only supported type.
|
|
2152
|
-
| ↳ `url` | `string` | ✅ | — | — | URL to POST event notifications to. Payload is `{run_id, event}`.
|
|
2153
|
-
| ↳ `max_retries` | `number` | ❌ | — | — | Max delivery attempts with exponential backoff. Defaults to 3 server-side.
|
|
2154
|
-
| ↳ `events` | `array` | ✅ | — | — | One or more lifecycle events to subscribe this URL to.
|
|
2140
|
+
| Name | Type | Required | Default | Possible Values | Description |
|
|
2141
|
+
| -------------------------- | ---------- | -------- | ------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
2142
|
+
| `options` | `object` | ✅ | — | — | |
|
|
2143
|
+
| ↳ `sourceFiles` | `object` | ✅ | — | — | Source files keyed by filename → contents |
|
|
2144
|
+
| ↳ `input` | `unknown` | ❌ | — | — | Input data passed to the run. Accepts any JSON value, or its JSON-string encoding. |
|
|
2145
|
+
| ↳ `dependencies` | `object` | ❌ | — | — | Optional npm package dependencies. A version of "latest" is resolved by the server for @zapier/zapier-durable and @zapier/zapier-sdk only; every other value, including a "latest" on any other package, is passed to the install as written. |
|
|
2146
|
+
| ↳ `zapierDurableVersion` | `string` | ❌ | — | — | Exact semver of @zapier/zapier-durable to use (e.g. "1.2.3"), or "latest". Defaults to the server-configured version if omitted. "latest" is resolved by the server to the newest release old enough to clear the sandbox install age gate (24h) -- this is not npm's "latest" tag, which can point at a release too new to install. Ranges (^1.2.3, ~1.2) are rejected. |
|
|
2147
|
+
| ↳ `connections` | `object` | ❌ | — | — | Named connection aliases. Maps each alias to an object holding its Zapier connection ID, e.g. `{ "slack": { "connectionId": "123" } }`. |
|
|
2148
|
+
| ↳ `appVersions` | `object` | ❌ | — | — | Pinned app versions. Maps app keys (slugs) to implementation names and versions. |
|
|
2149
|
+
| ↳ `private` | `boolean` | ❌ | — | — | Only the creating user can see the run (default false) |
|
|
2150
|
+
| ↳ `notifications[]` | `object[]` | ❌ | — | — | Webhook subscribers for run lifecycle events. Each entry specifies a URL and the events it subscribes to. |
|
|
2151
|
+
| ↳ `type` | `string` | ❌ | — | `webhook` | Notification transport. Webhook is the only supported type. |
|
|
2152
|
+
| ↳ `url` | `string` | ✅ | — | — | URL to POST event notifications to. Payload is `{run_id, event}`. |
|
|
2153
|
+
| ↳ `max_retries` | `number` | ❌ | — | — | Max delivery attempts with exponential backoff. Defaults to 3 server-side. |
|
|
2154
|
+
| ↳ `events` | `array` | ✅ | — | — | One or more lifecycle events to subscribe this URL to. |
|
|
2155
2155
|
|
|
2156
2156
|
**Returns:** `Promise<DurableRunItem>`
|
|
2157
2157
|
|
|
@@ -2242,19 +2242,19 @@ Update (autosave) an open workflow draft
|
|
|
2242
2242
|
|
|
2243
2243
|
**Parameters:**
|
|
2244
2244
|
|
|
2245
|
-
| Name | Type | Required | Default | Possible Values | Description
|
|
2246
|
-
| -------------------------- | --------- | -------- | ------- | --------------- |
|
|
2247
|
-
| `options` | `object` | ✅ | — | — |
|
|
2248
|
-
| ↳ `workflow` | `string` | ✅ | — | — | Durable workflow ID
|
|
2249
|
-
| ↳ `draft` | `string` | ✅ | — | — | Workflow draft ID
|
|
2250
|
-
| ↳ `sourceFiles` | `object` | ✅ | — | — | Source files keyed by filename → contents
|
|
2251
|
-
| ↳ `zapierDurableVersion` | `string` | ❌ | — | — | Exact semver of @zapier/zapier-durable to use (e.g. "1.2.3"). Leaves the stored pin unchanged if omitted.
|
|
2252
|
-
| ↳ `dependencies` | `object` | ❌ | — | — | Optional npm package dependencies
|
|
2253
|
-
| ↳ `draftRevision` | `number` | ❌ | — | — | Expected draft revision for optimistic concurrency. Pass the revision from the last read; the server rejects the save with a conflict if the draft has changed since. Omit to skip the check.
|
|
2254
|
-
| ↳ `trigger` | `object` | ❌ | — | — | Trigger configuration. Omit to leave the stored trigger unchanged, pass null to clear it, or pass an object to replace it; for an on-demand, triggerless workflow, clear this and pass `manual: true` instead.
|
|
2255
|
-
| ↳ `connections` | `object` | ❌ | — | — | Map of connection aliases to Zapier connections used by the workflow. Pass `null` to clear an existing binding.
|
|
2256
|
-
| ↳ `appVersions` | `object` | ❌ | — | — | Map of app keys to pinned app implementation/version used by the workflow. Pass `null` to clear an existing binding.
|
|
2257
|
-
| ↳ `manual` | `boolean` | ❌ | — | — | Declare this draft on-demand and triggerless. Pass `manual: true` only when omitting `trigger` (or clearing it with `trigger: null`); passing both is a contradiction the API rejects with a 400. Setting a `trigger` later clears a previously stored `manual: true`.
|
|
2245
|
+
| Name | Type | Required | Default | Possible Values | Description |
|
|
2246
|
+
| -------------------------- | --------- | -------- | ------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
2247
|
+
| `options` | `object` | ✅ | — | — | |
|
|
2248
|
+
| ↳ `workflow` | `string` | ✅ | — | — | Durable workflow ID |
|
|
2249
|
+
| ↳ `draft` | `string` | ✅ | — | — | Workflow draft ID |
|
|
2250
|
+
| ↳ `sourceFiles` | `object` | ✅ | — | — | Source files keyed by filename → contents |
|
|
2251
|
+
| ↳ `zapierDurableVersion` | `string` | ❌ | — | — | Exact semver of @zapier/zapier-durable to use (e.g. "1.2.3"), or "latest". Leaves the stored pin unchanged if omitted. A draft stores what you pass verbatim, so "latest" is recorded as-is and resolved to an exact version when the draft is published -- reading the draft back shows "latest", not a version. Ranges (^1.2.3, ~1.2) are rejected at publish. |
|
|
2252
|
+
| ↳ `dependencies` | `object` | ❌ | — | — | Optional npm package dependencies. A version of "latest" is resolved by the server for @zapier/zapier-durable and @zapier/zapier-sdk only; every other value, including a "latest" on any other package, is passed to the install as written. |
|
|
2253
|
+
| ↳ `draftRevision` | `number` | ❌ | — | — | Expected draft revision for optimistic concurrency. Pass the revision from the last read; the server rejects the save with a conflict if the draft has changed since. Omit to skip the check. |
|
|
2254
|
+
| ↳ `trigger` | `object` | ❌ | — | — | Trigger configuration. Omit to leave the stored trigger unchanged, pass null to clear it, or pass an object to replace it; for an on-demand, triggerless workflow, clear this and pass `manual: true` instead. |
|
|
2255
|
+
| ↳ `connections` | `object` | ❌ | — | — | Map of connection aliases to Zapier connections used by the workflow. Pass `null` to clear an existing binding. |
|
|
2256
|
+
| ↳ `appVersions` | `object` | ❌ | — | — | Map of app keys to pinned app implementation/version used by the workflow. Pass `null` to clear an existing binding. |
|
|
2257
|
+
| ↳ `manual` | `boolean` | ❌ | — | — | Declare this draft on-demand and triggerless. Pass `manual: true` only when omitting `trigger` (or clearing it with `trigger: null`); passing both is a contradiction the API rejects with a 400. Setting a `trigger` later clears a previously stored `manual: true`. |
|
|
2258
2258
|
|
|
2259
2259
|
**Returns:** `Promise<WorkflowDraftItem>`
|
|
2260
2260
|
|
|
@@ -1988,7 +1988,7 @@ function parseDeprecationDate(value) {
|
|
|
1988
1988
|
}
|
|
1989
1989
|
|
|
1990
1990
|
// src/sdk-version.ts
|
|
1991
|
-
var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.102.
|
|
1991
|
+
var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.102.2" : void 0) || "unknown";
|
|
1992
1992
|
|
|
1993
1993
|
// src/utils/open-url.ts
|
|
1994
1994
|
var nodePrefix = "node:";
|
|
@@ -2104,6 +2104,7 @@ var PollApprovalResponseSchema = zod.z.object({
|
|
|
2104
2104
|
approval_url: zod.z.string().optional()
|
|
2105
2105
|
});
|
|
2106
2106
|
var APPROVAL_MAX_POLLING_INTERVAL_MILLISECONDS = 5e3;
|
|
2107
|
+
var EPOCH_THRESHOLD_SECONDS = 1e9;
|
|
2107
2108
|
function validateSdkPath(path) {
|
|
2108
2109
|
if (!path.startsWith("/") || path.startsWith("//")) {
|
|
2109
2110
|
throw new ZapierValidationError(
|
|
@@ -2144,11 +2145,12 @@ function parseRateLimitHeaders(response) {
|
|
|
2144
2145
|
}
|
|
2145
2146
|
const reset = response.headers.get("x-ratelimit-reset");
|
|
2146
2147
|
if (reset) {
|
|
2147
|
-
const
|
|
2148
|
-
if (!isNaN(
|
|
2149
|
-
|
|
2148
|
+
const resetValue = parseInt(reset, 10);
|
|
2149
|
+
if (!isNaN(resetValue)) {
|
|
2150
|
+
const isEpoch = resetValue >= EPOCH_THRESHOLD_SECONDS;
|
|
2151
|
+
info.resetMs = isEpoch ? resetValue * 1e3 : Date.now() + resetValue * 1e3;
|
|
2150
2152
|
if (info.retryAfterMs === void 0) {
|
|
2151
|
-
info.retryAfterMs = Math.max(0, info.resetMs - Date.now());
|
|
2153
|
+
info.retryAfterMs = isEpoch ? Math.max(0, info.resetMs - Date.now()) : Math.max(0, resetValue * 1e3);
|
|
2152
2154
|
}
|
|
2153
2155
|
}
|
|
2154
2156
|
}
|
|
@@ -2286,11 +2288,14 @@ var ZapierApiClient = class {
|
|
|
2286
2288
|
const rateLimitInfo = parseRateLimitHeaders(response);
|
|
2287
2289
|
const delayMs = rateLimitInfo.retryAfterMs ?? calculateExponentialBackoffMs(retries + 1);
|
|
2288
2290
|
if (delayMs > this.maxNetworkRetryDelayMilliseconds || retries >= this.maxNetworkRetries) {
|
|
2289
|
-
throw new ZapierRateLimitError(
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2291
|
+
throw new ZapierRateLimitError(
|
|
2292
|
+
await this.readRateLimitErrorMessage(response),
|
|
2293
|
+
{
|
|
2294
|
+
statusCode: 429,
|
|
2295
|
+
rateLimit: rateLimitInfo,
|
|
2296
|
+
retries
|
|
2297
|
+
}
|
|
2298
|
+
);
|
|
2294
2299
|
}
|
|
2295
2300
|
retries++;
|
|
2296
2301
|
this.emitEvent("api:rate_limit_retry", {
|
|
@@ -2725,6 +2730,17 @@ var ZapierApiClient = class {
|
|
|
2725
2730
|
}
|
|
2726
2731
|
return void 0;
|
|
2727
2732
|
}
|
|
2733
|
+
// Surface the server's explanatory 429 body (e.g. quota details and how
|
|
2734
|
+
// to get a higher limit) instead of a bare "Rate limited". The body is
|
|
2735
|
+
// only consumed on the terminal throw path, never on retries.
|
|
2736
|
+
async readRateLimitErrorMessage(response) {
|
|
2737
|
+
try {
|
|
2738
|
+
const { data } = await this.parseResult(response);
|
|
2739
|
+
return this.extractErrorMessage(data)?.trim() || "Rate limited";
|
|
2740
|
+
} catch {
|
|
2741
|
+
return "Rate limited";
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2728
2744
|
// Helper to parse API error response
|
|
2729
2745
|
parseErrorResponse(errorInfo) {
|
|
2730
2746
|
const fallbackMessage = `HTTP ${errorInfo.status}: ${errorInfo.statusText}`;
|
|
@@ -1987,7 +1987,7 @@ function parseDeprecationDate(value) {
|
|
|
1987
1987
|
}
|
|
1988
1988
|
|
|
1989
1989
|
// src/sdk-version.ts
|
|
1990
|
-
var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.102.
|
|
1990
|
+
var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.102.2" : void 0) || "unknown";
|
|
1991
1991
|
|
|
1992
1992
|
// src/utils/open-url.ts
|
|
1993
1993
|
var nodePrefix = "node:";
|
|
@@ -2103,6 +2103,7 @@ var PollApprovalResponseSchema = z.object({
|
|
|
2103
2103
|
approval_url: z.string().optional()
|
|
2104
2104
|
});
|
|
2105
2105
|
var APPROVAL_MAX_POLLING_INTERVAL_MILLISECONDS = 5e3;
|
|
2106
|
+
var EPOCH_THRESHOLD_SECONDS = 1e9;
|
|
2106
2107
|
function validateSdkPath(path) {
|
|
2107
2108
|
if (!path.startsWith("/") || path.startsWith("//")) {
|
|
2108
2109
|
throw new ZapierValidationError(
|
|
@@ -2143,11 +2144,12 @@ function parseRateLimitHeaders(response) {
|
|
|
2143
2144
|
}
|
|
2144
2145
|
const reset = response.headers.get("x-ratelimit-reset");
|
|
2145
2146
|
if (reset) {
|
|
2146
|
-
const
|
|
2147
|
-
if (!isNaN(
|
|
2148
|
-
|
|
2147
|
+
const resetValue = parseInt(reset, 10);
|
|
2148
|
+
if (!isNaN(resetValue)) {
|
|
2149
|
+
const isEpoch = resetValue >= EPOCH_THRESHOLD_SECONDS;
|
|
2150
|
+
info.resetMs = isEpoch ? resetValue * 1e3 : Date.now() + resetValue * 1e3;
|
|
2149
2151
|
if (info.retryAfterMs === void 0) {
|
|
2150
|
-
info.retryAfterMs = Math.max(0, info.resetMs - Date.now());
|
|
2152
|
+
info.retryAfterMs = isEpoch ? Math.max(0, info.resetMs - Date.now()) : Math.max(0, resetValue * 1e3);
|
|
2151
2153
|
}
|
|
2152
2154
|
}
|
|
2153
2155
|
}
|
|
@@ -2285,11 +2287,14 @@ var ZapierApiClient = class {
|
|
|
2285
2287
|
const rateLimitInfo = parseRateLimitHeaders(response);
|
|
2286
2288
|
const delayMs = rateLimitInfo.retryAfterMs ?? calculateExponentialBackoffMs(retries + 1);
|
|
2287
2289
|
if (delayMs > this.maxNetworkRetryDelayMilliseconds || retries >= this.maxNetworkRetries) {
|
|
2288
|
-
throw new ZapierRateLimitError(
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2290
|
+
throw new ZapierRateLimitError(
|
|
2291
|
+
await this.readRateLimitErrorMessage(response),
|
|
2292
|
+
{
|
|
2293
|
+
statusCode: 429,
|
|
2294
|
+
rateLimit: rateLimitInfo,
|
|
2295
|
+
retries
|
|
2296
|
+
}
|
|
2297
|
+
);
|
|
2293
2298
|
}
|
|
2294
2299
|
retries++;
|
|
2295
2300
|
this.emitEvent("api:rate_limit_retry", {
|
|
@@ -2724,6 +2729,17 @@ var ZapierApiClient = class {
|
|
|
2724
2729
|
}
|
|
2725
2730
|
return void 0;
|
|
2726
2731
|
}
|
|
2732
|
+
// Surface the server's explanatory 429 body (e.g. quota details and how
|
|
2733
|
+
// to get a higher limit) instead of a bare "Rate limited". The body is
|
|
2734
|
+
// only consumed on the terminal throw path, never on retries.
|
|
2735
|
+
async readRateLimitErrorMessage(response) {
|
|
2736
|
+
try {
|
|
2737
|
+
const { data } = await this.parseResult(response);
|
|
2738
|
+
return this.extractErrorMessage(data)?.trim() || "Rate limited";
|
|
2739
|
+
} catch {
|
|
2740
|
+
return "Rate limited";
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2727
2743
|
// Helper to parse API error response
|
|
2728
2744
|
parseErrorResponse(errorInfo) {
|
|
2729
2745
|
const fallbackMessage = `HTTP ${errorInfo.status}: ${errorInfo.statusText}`;
|