@zapier/zapier-sdk 0.68.0 → 0.69.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/AGENTS.md +321 -0
- package/CHANGELOG.md +15 -0
- package/CLAUDE.md +3 -319
- package/README.md +17 -17
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +108 -3
- package/dist/api/error-classification.d.ts +12 -0
- package/dist/api/error-classification.d.ts.map +1 -0
- package/dist/api/error-classification.js +18 -0
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +3 -0
- package/dist/api/sse-parser.d.ts +17 -0
- package/dist/api/sse-parser.d.ts.map +1 -0
- package/dist/api/sse-parser.js +67 -0
- package/dist/api/types.d.ts +16 -0
- package/dist/api/types.d.ts.map +1 -1
- package/dist/experimental.cjs +356 -67
- package/dist/experimental.d.mts +2 -2
- package/dist/experimental.mjs +356 -67
- package/dist/{index-oRnHsPn5.d.mts → index-DC31DAP2.d.mts} +20 -1
- package/dist/{index-oRnHsPn5.d.ts → index-DC31DAP2.d.ts} +20 -1
- package/dist/index.cjs +131 -7
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +131 -7
- package/dist/plugins/triggers/drainTriggerInbox/schemas.js +2 -2
- package/dist/plugins/triggers/watchTriggerInbox/index.d.ts +31 -6
- package/dist/plugins/triggers/watchTriggerInbox/index.d.ts.map +1 -1
- package/dist/plugins/triggers/watchTriggerInbox/index.js +272 -65
- package/dist/plugins/triggers/watchTriggerInbox/sse.d.ts +30 -0
- package/dist/plugins/triggers/watchTriggerInbox/sse.d.ts.map +1 -0
- package/dist/plugins/triggers/watchTriggerInbox/sse.js +38 -0
- package/package.json +2 -1
package/dist/experimental.cjs
CHANGED
|
@@ -3124,8 +3124,55 @@ async function invalidateCredentialsToken(options) {
|
|
|
3124
3124
|
}
|
|
3125
3125
|
}
|
|
3126
3126
|
|
|
3127
|
+
// src/api/sse-parser.ts
|
|
3128
|
+
function createSseParserStream() {
|
|
3129
|
+
let buffer = "";
|
|
3130
|
+
let data = "";
|
|
3131
|
+
let hasData = false;
|
|
3132
|
+
function processLine(line, controller) {
|
|
3133
|
+
if (line === "") {
|
|
3134
|
+
if (hasData) {
|
|
3135
|
+
controller.enqueue({
|
|
3136
|
+
data: data.endsWith("\n") ? data.slice(0, -1) : data
|
|
3137
|
+
});
|
|
3138
|
+
}
|
|
3139
|
+
data = "";
|
|
3140
|
+
hasData = false;
|
|
3141
|
+
return;
|
|
3142
|
+
}
|
|
3143
|
+
if (line.startsWith(":")) return;
|
|
3144
|
+
const colon = line.indexOf(":");
|
|
3145
|
+
const field = colon === -1 ? line : line.slice(0, colon);
|
|
3146
|
+
let value = colon === -1 ? "" : line.slice(colon + 1);
|
|
3147
|
+
if (value.startsWith(" ")) value = value.slice(1);
|
|
3148
|
+
if (field === "data") {
|
|
3149
|
+
data += value + "\n";
|
|
3150
|
+
hasData = true;
|
|
3151
|
+
}
|
|
3152
|
+
}
|
|
3153
|
+
return new TransformStream({
|
|
3154
|
+
transform(chunk, controller) {
|
|
3155
|
+
buffer += chunk;
|
|
3156
|
+
const newline = /\r\n|\r|\n/g;
|
|
3157
|
+
let start = 0;
|
|
3158
|
+
let match;
|
|
3159
|
+
while ((match = newline.exec(buffer)) !== null) {
|
|
3160
|
+
if (match[0] === "\r" && match.index === buffer.length - 1) break;
|
|
3161
|
+
processLine(buffer.slice(start, match.index), controller);
|
|
3162
|
+
start = match.index + match[0].length;
|
|
3163
|
+
}
|
|
3164
|
+
buffer = buffer.slice(start);
|
|
3165
|
+
},
|
|
3166
|
+
flush(controller) {
|
|
3167
|
+
if (buffer.endsWith("\r")) {
|
|
3168
|
+
processLine(buffer.slice(0, -1), controller);
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
3171
|
+
});
|
|
3172
|
+
}
|
|
3173
|
+
|
|
3127
3174
|
// src/sdk-version.ts
|
|
3128
|
-
var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.
|
|
3175
|
+
var SDK_VERSION = (typeof process !== "undefined" && process.env ? "0.69.0" : void 0) || "unknown";
|
|
3129
3176
|
|
|
3130
3177
|
// src/utils/open-url.ts
|
|
3131
3178
|
var nodePrefix = "node:";
|
|
@@ -3488,6 +3535,18 @@ var ZapierApiClient = class {
|
|
|
3488
3535
|
{ status: "max_retries_exceeded" }
|
|
3489
3536
|
);
|
|
3490
3537
|
};
|
|
3538
|
+
/**
|
|
3539
|
+
* Streaming counterpart to `fetch`. Opens a Server-Sent Events connection
|
|
3540
|
+
* through the same pipeline (auth, base URL, 429 retry, approval flow,
|
|
3541
|
+
* concurrency) and yields parsed `{ data }` frames. On a non-ok response it
|
|
3542
|
+
* throws the same `ZapierError` subclasses as the JSON path — callers
|
|
3543
|
+
* classify errors off `statusCode` instead of hand-rolling the mapping.
|
|
3544
|
+
*
|
|
3545
|
+
* The concurrency permit is released when the underlying `fetch` resolves
|
|
3546
|
+
* (headers received), not when the body finishes, so a long-lived stream
|
|
3547
|
+
* never pins a slot — see `withSemaphore`.
|
|
3548
|
+
*/
|
|
3549
|
+
this.fetchStream = (path, init) => this.streamSse(path, init);
|
|
3491
3550
|
this.get = async (path, options = {}) => {
|
|
3492
3551
|
return this.fetchJson("GET", path, void 0, options);
|
|
3493
3552
|
};
|
|
@@ -3562,17 +3621,30 @@ var ZapierApiClient = class {
|
|
|
3562
3621
|
}
|
|
3563
3622
|
// Helper to handle responses
|
|
3564
3623
|
async handleResponse(params) {
|
|
3624
|
+
const { data: responseData } = await this.parseResult(
|
|
3625
|
+
params.response
|
|
3626
|
+
);
|
|
3627
|
+
if (params.response.ok) {
|
|
3628
|
+
return responseData;
|
|
3629
|
+
}
|
|
3630
|
+
return this.throwForErrorResponse({ ...params, responseData });
|
|
3631
|
+
}
|
|
3632
|
+
/**
|
|
3633
|
+
* Maps a non-ok response to the appropriate ZapierError subclass and throws.
|
|
3634
|
+
* Takes the already-parsed body so a streaming caller (`fetchStream`) gets
|
|
3635
|
+
* the exact same status→error classification as the JSON path without
|
|
3636
|
+
* re-reading — or reading on the success path, which would consume the
|
|
3637
|
+
* stream — the response body.
|
|
3638
|
+
*/
|
|
3639
|
+
async throwForErrorResponse(params) {
|
|
3565
3640
|
const {
|
|
3566
3641
|
response,
|
|
3642
|
+
responseData,
|
|
3567
3643
|
customErrorHandler,
|
|
3568
3644
|
resource,
|
|
3569
3645
|
wasMissingAuthToken,
|
|
3570
3646
|
requiredScopes
|
|
3571
3647
|
} = params;
|
|
3572
|
-
const { data: responseData } = await this.parseResult(response);
|
|
3573
|
-
if (response.ok) {
|
|
3574
|
-
return responseData;
|
|
3575
|
-
}
|
|
3576
3648
|
const errorInfo = {
|
|
3577
3649
|
status: response.status,
|
|
3578
3650
|
statusText: response.statusText,
|
|
@@ -3809,6 +3881,58 @@ var ZapierApiClient = class {
|
|
|
3809
3881
|
}
|
|
3810
3882
|
return result;
|
|
3811
3883
|
}
|
|
3884
|
+
// The generator body for `fetchStream`. Kept as a prototype method (not an
|
|
3885
|
+
// arrow class field, which can't be a generator) and exposed through the
|
|
3886
|
+
// bound `fetchStream` arrow above for parity with the other client methods.
|
|
3887
|
+
async *streamSse(path, init) {
|
|
3888
|
+
const { onOpen, headers: initHeaders, ...fetchInit } = init ?? {};
|
|
3889
|
+
const signal = fetchInit.signal;
|
|
3890
|
+
if (signal?.aborted) return;
|
|
3891
|
+
const wasMissingAuthToken = fetchInit.authRequired === true && await this.getAuthToken({
|
|
3892
|
+
requiredScopes: fetchInit.requiredScopes
|
|
3893
|
+
}) == null;
|
|
3894
|
+
const headers = new Headers(initHeaders);
|
|
3895
|
+
if (!headers.has("Accept")) headers.set("Accept", "text/event-stream");
|
|
3896
|
+
let response;
|
|
3897
|
+
try {
|
|
3898
|
+
response = await this.fetch(path, {
|
|
3899
|
+
...fetchInit,
|
|
3900
|
+
method: fetchInit.method ?? "GET",
|
|
3901
|
+
headers
|
|
3902
|
+
});
|
|
3903
|
+
} catch (err) {
|
|
3904
|
+
if (signal?.aborted || isAbortError(err)) return;
|
|
3905
|
+
throw err;
|
|
3906
|
+
}
|
|
3907
|
+
if (!response.ok) {
|
|
3908
|
+
const { data } = await this.parseResult(response);
|
|
3909
|
+
await this.throwForErrorResponse({
|
|
3910
|
+
response,
|
|
3911
|
+
responseData: data,
|
|
3912
|
+
wasMissingAuthToken,
|
|
3913
|
+
requiredScopes: fetchInit.requiredScopes
|
|
3914
|
+
});
|
|
3915
|
+
}
|
|
3916
|
+
if (!response.body) return;
|
|
3917
|
+
const reader = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(createSseParserStream()).getReader();
|
|
3918
|
+
const onAbort = () => {
|
|
3919
|
+
reader.cancel().catch(() => {
|
|
3920
|
+
});
|
|
3921
|
+
};
|
|
3922
|
+
try {
|
|
3923
|
+
onOpen?.();
|
|
3924
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
3925
|
+
while (!signal?.aborted) {
|
|
3926
|
+
const { done, value } = await reader.read();
|
|
3927
|
+
if (done || signal?.aborted) return;
|
|
3928
|
+
yield value;
|
|
3929
|
+
}
|
|
3930
|
+
} finally {
|
|
3931
|
+
signal?.removeEventListener("abort", onAbort);
|
|
3932
|
+
await reader.cancel().catch(() => {
|
|
3933
|
+
});
|
|
3934
|
+
}
|
|
3935
|
+
}
|
|
3812
3936
|
/**
|
|
3813
3937
|
* Run a single approval round: create the approval, open the URL (poll mode)
|
|
3814
3938
|
* or throw (throw mode), poll until resolved, and emit events. Throws on
|
|
@@ -3986,6 +4110,12 @@ var createZapierApi = (options) => {
|
|
|
3986
4110
|
});
|
|
3987
4111
|
};
|
|
3988
4112
|
|
|
4113
|
+
// src/api/error-classification.ts
|
|
4114
|
+
function isPermanentHttpError(err) {
|
|
4115
|
+
const statusCode = err instanceof ZapierError ? err.statusCode : void 0;
|
|
4116
|
+
return statusCode !== void 0 && statusCode >= 400 && statusCode < 500 && statusCode !== 429;
|
|
4117
|
+
}
|
|
4118
|
+
|
|
3989
4119
|
// src/api/index.ts
|
|
3990
4120
|
function getOrCreateApiClient(config) {
|
|
3991
4121
|
const {
|
|
@@ -10158,10 +10288,10 @@ var DrainTriggerInboxSchema = TriggerInboxCommandBaseSchema.extend({
|
|
|
10158
10288
|
);
|
|
10159
10289
|
var WatchTriggerInboxSchema = TriggerInboxCommandBaseSchema.extend({
|
|
10160
10290
|
maxDrainIntervalSeconds: zod.z.number().int().min(1).optional().describe(
|
|
10161
|
-
"Maximum seconds between
|
|
10291
|
+
"Maximum seconds between safety drain attempts (default: 300). The watcher subscribes to SSE notifications for near-real-time wake-ups; this interval is the backstop that guarantees forward progress if SSE events are missed or the connection drops undetected."
|
|
10162
10292
|
)
|
|
10163
10293
|
}).describe(
|
|
10164
|
-
"Continuously consume a trigger inbox: drain currently-available messages, then
|
|
10294
|
+
"Continuously consume a trigger inbox: drain currently-available messages, then subscribe to SSE notifications for new arrivals, until aborted. Stop via the `signal` AbortSignal or by throwing `ZapierAbortDrainSignal` from a handler. Resolves cleanly on abort; rejects on a fatal error or a fail-fast handler error."
|
|
10165
10295
|
);
|
|
10166
10296
|
|
|
10167
10297
|
// src/plugins/triggers/drainTriggerInbox/pipeline.ts
|
|
@@ -10516,36 +10646,170 @@ var drainTriggerInboxPlugin = definePlugin(
|
|
|
10516
10646
|
}
|
|
10517
10647
|
);
|
|
10518
10648
|
|
|
10649
|
+
// src/plugins/triggers/watchTriggerInbox/sse.ts
|
|
10650
|
+
async function* readInboxEvents({
|
|
10651
|
+
api,
|
|
10652
|
+
inboxId,
|
|
10653
|
+
signal,
|
|
10654
|
+
onOpen
|
|
10655
|
+
}) {
|
|
10656
|
+
for await (const message of api.fetchStream(
|
|
10657
|
+
`/trigger-inbox/api/v1/inboxes/${encodeURIComponent(inboxId)}/events`,
|
|
10658
|
+
{ method: "GET", signal, authRequired: true, onOpen }
|
|
10659
|
+
)) {
|
|
10660
|
+
let parsed;
|
|
10661
|
+
try {
|
|
10662
|
+
parsed = JSON.parse(message.data);
|
|
10663
|
+
} catch {
|
|
10664
|
+
continue;
|
|
10665
|
+
}
|
|
10666
|
+
if (typeof parsed === "object" && parsed !== null && typeof parsed.inbox_id === "string" && // Only wake on a frame for this inbox. Case-insensitive: the endpoint
|
|
10667
|
+
// echoes the canonical lowercase UUID, but resolveTriggerInboxId passes
|
|
10668
|
+
// a UUID-shaped `inbox` through unchanged, so its casing may differ.
|
|
10669
|
+
parsed.inbox_id.toLowerCase() === inboxId.toLowerCase()) {
|
|
10670
|
+
yield parsed;
|
|
10671
|
+
}
|
|
10672
|
+
}
|
|
10673
|
+
}
|
|
10674
|
+
|
|
10519
10675
|
// src/plugins/triggers/watchTriggerInbox/index.ts
|
|
10520
|
-
var
|
|
10521
|
-
|
|
10522
|
-
|
|
10523
|
-
|
|
10524
|
-
|
|
10525
|
-
|
|
10526
|
-
|
|
10527
|
-
|
|
10528
|
-
|
|
10529
|
-
|
|
10530
|
-
|
|
10531
|
-
|
|
10532
|
-
|
|
10533
|
-
return
|
|
10534
|
-
|
|
10535
|
-
|
|
10536
|
-
|
|
10537
|
-
|
|
10538
|
-
|
|
10539
|
-
|
|
10540
|
-
|
|
10541
|
-
|
|
10542
|
-
|
|
10543
|
-
|
|
10544
|
-
|
|
10545
|
-
|
|
10546
|
-
|
|
10547
|
-
|
|
10548
|
-
}
|
|
10676
|
+
var SSE_RECONNECT_BACKOFF_MS = [500, 1e3, 2e3, 5e3];
|
|
10677
|
+
var DEFAULT_SAFETY_DRAIN_INTERVAL_MS = 3e5;
|
|
10678
|
+
var SSE_HEALTHY_CONNECTION_MS = 5e3;
|
|
10679
|
+
function createDrainLatch() {
|
|
10680
|
+
let pending = false;
|
|
10681
|
+
const make = () => {
|
|
10682
|
+
let resolve2;
|
|
10683
|
+
const promise = new Promise((r) => {
|
|
10684
|
+
resolve2 = r;
|
|
10685
|
+
});
|
|
10686
|
+
return { promise, resolve: resolve2 };
|
|
10687
|
+
};
|
|
10688
|
+
let current = make();
|
|
10689
|
+
return {
|
|
10690
|
+
request() {
|
|
10691
|
+
pending = true;
|
|
10692
|
+
const prev = current;
|
|
10693
|
+
current = make();
|
|
10694
|
+
prev.resolve();
|
|
10695
|
+
},
|
|
10696
|
+
async waitForRequest() {
|
|
10697
|
+
if (pending) {
|
|
10698
|
+
pending = false;
|
|
10699
|
+
return;
|
|
10700
|
+
}
|
|
10701
|
+
await current.promise;
|
|
10702
|
+
pending = false;
|
|
10703
|
+
}
|
|
10704
|
+
};
|
|
10705
|
+
}
|
|
10706
|
+
async function drainRunner({
|
|
10707
|
+
drainOptions,
|
|
10708
|
+
drainRequest,
|
|
10709
|
+
signal
|
|
10710
|
+
}) {
|
|
10711
|
+
let firstFetch = true;
|
|
10712
|
+
while (!signal.aborted) {
|
|
10713
|
+
await drainRequest.waitForRequest();
|
|
10714
|
+
if (signal.aborted) return { kind: "aborted" };
|
|
10715
|
+
let abortedFromCallback = false;
|
|
10716
|
+
try {
|
|
10717
|
+
({ abortedFromCallback } = await runDrainPass({
|
|
10718
|
+
...drainOptions,
|
|
10719
|
+
firstFetch
|
|
10720
|
+
}));
|
|
10721
|
+
} catch (error) {
|
|
10722
|
+
return { kind: "error", error };
|
|
10723
|
+
}
|
|
10724
|
+
firstFetch = false;
|
|
10725
|
+
if (abortedFromCallback) return { kind: "abortedFromCallback" };
|
|
10726
|
+
}
|
|
10727
|
+
return { kind: "aborted" };
|
|
10728
|
+
}
|
|
10729
|
+
function sseErrorStatusCode(err) {
|
|
10730
|
+
return err instanceof ZapierError ? err.statusCode : void 0;
|
|
10731
|
+
}
|
|
10732
|
+
function sseErrorMessage(err) {
|
|
10733
|
+
return err instanceof Error ? err.message : String(err);
|
|
10734
|
+
}
|
|
10735
|
+
async function sseLoop({
|
|
10736
|
+
api,
|
|
10737
|
+
inboxId,
|
|
10738
|
+
drainRequest,
|
|
10739
|
+
safetyDrainMs,
|
|
10740
|
+
signal,
|
|
10741
|
+
debug
|
|
10742
|
+
}) {
|
|
10743
|
+
let attempt = 0;
|
|
10744
|
+
let degraded = false;
|
|
10745
|
+
while (!signal.aborted) {
|
|
10746
|
+
let connected = false;
|
|
10747
|
+
let connectedAt = 0;
|
|
10748
|
+
let transientError;
|
|
10749
|
+
try {
|
|
10750
|
+
for await (const _event of readInboxEvents({
|
|
10751
|
+
api,
|
|
10752
|
+
inboxId,
|
|
10753
|
+
signal,
|
|
10754
|
+
// SSE is edge-triggered with no replay, so draining on connect is the
|
|
10755
|
+
// only way to pick up messages that arrived before this connection —
|
|
10756
|
+
// including the window left by a prior disconnect.
|
|
10757
|
+
onOpen: () => {
|
|
10758
|
+
connected = true;
|
|
10759
|
+
connectedAt = Date.now();
|
|
10760
|
+
degraded = false;
|
|
10761
|
+
drainRequest.request();
|
|
10762
|
+
}
|
|
10763
|
+
})) {
|
|
10764
|
+
drainRequest.request();
|
|
10765
|
+
}
|
|
10766
|
+
if (connected && Date.now() - connectedAt >= SSE_HEALTHY_CONNECTION_MS) {
|
|
10767
|
+
attempt = 0;
|
|
10768
|
+
}
|
|
10769
|
+
} catch (err) {
|
|
10770
|
+
if (signal.aborted || isAbortError(err)) return;
|
|
10771
|
+
if (isPermanentHttpError(err)) {
|
|
10772
|
+
if (!degraded) {
|
|
10773
|
+
const statusCode = sseErrorStatusCode(err);
|
|
10774
|
+
const errorMsg = sseErrorMessage(err);
|
|
10775
|
+
const httpPart = statusCode !== void 0 ? ` (HTTP ${statusCode})` : "";
|
|
10776
|
+
console.warn(
|
|
10777
|
+
`[zapier-sdk] Real-time wake-ups for inbox ${inboxId}${httpPart} paused: ${errorMsg}. Falling back to the periodic safety drain.`
|
|
10778
|
+
);
|
|
10779
|
+
degraded = true;
|
|
10780
|
+
}
|
|
10781
|
+
attempt = 0;
|
|
10782
|
+
if (signal.aborted) return;
|
|
10783
|
+
await sleep(safetyDrainMs, signal);
|
|
10784
|
+
continue;
|
|
10785
|
+
}
|
|
10786
|
+
if (connected) attempt = 0;
|
|
10787
|
+
transientError = err;
|
|
10788
|
+
}
|
|
10789
|
+
if (signal.aborted) return;
|
|
10790
|
+
const delay = SSE_RECONNECT_BACKOFF_MS[Math.min(attempt, SSE_RECONNECT_BACKOFF_MS.length - 1)];
|
|
10791
|
+
attempt = Math.min(attempt + 1, SSE_RECONNECT_BACKOFF_MS.length - 1);
|
|
10792
|
+
if (transientError !== void 0 && debug) {
|
|
10793
|
+
const statusCode = sseErrorStatusCode(transientError);
|
|
10794
|
+
const errorMsg = sseErrorMessage(transientError);
|
|
10795
|
+
const httpPart = statusCode !== void 0 ? ` (HTTP ${statusCode})` : "";
|
|
10796
|
+
console.error(
|
|
10797
|
+
`[zapier-sdk] Reconnecting real-time wake-ups for inbox ${inboxId} (attempt ${attempt}, retry in ${delay}ms)${httpPart}: ${errorMsg}`
|
|
10798
|
+
);
|
|
10799
|
+
}
|
|
10800
|
+
await sleep(delay, signal);
|
|
10801
|
+
}
|
|
10802
|
+
}
|
|
10803
|
+
async function safetyTimerLoop({
|
|
10804
|
+
safetyDrainMs,
|
|
10805
|
+
drainRequest,
|
|
10806
|
+
signal
|
|
10807
|
+
}) {
|
|
10808
|
+
while (!signal.aborted) {
|
|
10809
|
+
await sleep(safetyDrainMs, signal);
|
|
10810
|
+
if (signal.aborted) return;
|
|
10811
|
+
drainRequest.request();
|
|
10812
|
+
}
|
|
10549
10813
|
}
|
|
10550
10814
|
var watchTriggerInboxPlugin = definePlugin(
|
|
10551
10815
|
(sdk) => {
|
|
@@ -10556,37 +10820,62 @@ var watchTriggerInboxPlugin = definePlugin(
|
|
|
10556
10820
|
api: sdk.context.api,
|
|
10557
10821
|
inbox: options.inbox
|
|
10558
10822
|
});
|
|
10559
|
-
|
|
10560
|
-
|
|
10561
|
-
|
|
10562
|
-
|
|
10563
|
-
|
|
10564
|
-
|
|
10565
|
-
|
|
10566
|
-
|
|
10567
|
-
|
|
10568
|
-
|
|
10569
|
-
|
|
10570
|
-
|
|
10571
|
-
|
|
10572
|
-
|
|
10573
|
-
|
|
10574
|
-
|
|
10575
|
-
|
|
10576
|
-
|
|
10577
|
-
|
|
10578
|
-
|
|
10579
|
-
|
|
10580
|
-
|
|
10581
|
-
|
|
10582
|
-
|
|
10583
|
-
|
|
10584
|
-
|
|
10585
|
-
|
|
10586
|
-
|
|
10587
|
-
|
|
10588
|
-
|
|
10823
|
+
if (options.signal?.aborted) return;
|
|
10824
|
+
const safetyDrainMs = options.maxDrainIntervalSeconds !== void 0 ? options.maxDrainIntervalSeconds * 1e3 : DEFAULT_SAFETY_DRAIN_INTERVAL_MS;
|
|
10825
|
+
const stop = new AbortController();
|
|
10826
|
+
const combined = combineAbortSignals({
|
|
10827
|
+
handles: [
|
|
10828
|
+
...options.signal ? [{ signal: options.signal, dispose: () => {
|
|
10829
|
+
} }] : [],
|
|
10830
|
+
{ signal: stop.signal, dispose: () => {
|
|
10831
|
+
} }
|
|
10832
|
+
]
|
|
10833
|
+
});
|
|
10834
|
+
const signal = combined?.signal ?? stop.signal;
|
|
10835
|
+
const drainRequest = createDrainLatch();
|
|
10836
|
+
signal.addEventListener("abort", () => drainRequest.request(), {
|
|
10837
|
+
once: true
|
|
10838
|
+
});
|
|
10839
|
+
const debug = sdk.context.options.debug === true;
|
|
10840
|
+
const drainOptions = {
|
|
10841
|
+
sdk,
|
|
10842
|
+
inboxId,
|
|
10843
|
+
onMessage,
|
|
10844
|
+
concurrency,
|
|
10845
|
+
leaseLimit,
|
|
10846
|
+
leaseSeconds: options.leaseSeconds,
|
|
10847
|
+
maxMessages: void 0,
|
|
10848
|
+
releaseOnError: options.releaseOnError ?? false,
|
|
10849
|
+
continueOnError: options.continueOnError ?? false,
|
|
10850
|
+
onError: options.onError,
|
|
10851
|
+
signal
|
|
10852
|
+
};
|
|
10853
|
+
drainRequest.request();
|
|
10854
|
+
const runnerDone = drainRunner({ drainOptions, drainRequest, signal });
|
|
10855
|
+
const sseDone = sseLoop({
|
|
10856
|
+
api: sdk.context.api,
|
|
10857
|
+
inboxId,
|
|
10858
|
+
drainRequest,
|
|
10859
|
+
safetyDrainMs,
|
|
10860
|
+
signal,
|
|
10861
|
+
debug
|
|
10862
|
+
}).catch(() => {
|
|
10863
|
+
});
|
|
10864
|
+
const safetyDone = safetyTimerLoop({
|
|
10865
|
+
safetyDrainMs,
|
|
10866
|
+
drainRequest,
|
|
10867
|
+
signal
|
|
10868
|
+
}).catch(() => {
|
|
10869
|
+
});
|
|
10870
|
+
let end;
|
|
10871
|
+
try {
|
|
10872
|
+
end = await runnerDone;
|
|
10873
|
+
} finally {
|
|
10874
|
+
stop.abort();
|
|
10875
|
+
await Promise.all([sseDone, safetyDone]);
|
|
10876
|
+
combined?.dispose();
|
|
10589
10877
|
}
|
|
10878
|
+
if (end.kind === "error") throw end.error;
|
|
10590
10879
|
}
|
|
10591
10880
|
return {
|
|
10592
10881
|
watchTriggerInbox,
|
|
@@ -10595,7 +10884,7 @@ var watchTriggerInboxPlugin = definePlugin(
|
|
|
10595
10884
|
watchTriggerInbox: {
|
|
10596
10885
|
...triggersDefaults,
|
|
10597
10886
|
type: "create",
|
|
10598
|
-
description: "Continuously consume a trigger inbox: drain currently-available messages via onMessage, then
|
|
10887
|
+
description: "Continuously consume a trigger inbox: drain currently-available messages via onMessage, then subscribe to SSE notifications for new arrivals until aborted. A periodic safety drain runs every maxDrainIntervalSeconds (default: 300) to guarantee forward progress if SSE events are missed. Resolves cleanly on signal abort or ZapierAbortDrainSignal from a handler; rejects on fatal SDK errors or fail-fast handler errors. Real-time wake-up health is reported on stderr: a warning when wake-ups pause and the watch falls back to the safety drain, plus (with debug) transient reconnect notices.",
|
|
10599
10888
|
itemType: "void",
|
|
10600
10889
|
// See drainTriggerInbox: override the doc generator's default
|
|
10601
10890
|
// suffix so the rendered return type is Promise<void>, not
|
package/dist/experimental.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { B as BaseSdkOptions, P as PluginStack, a as PluginMeta, M as MethodHooks, C as CoreOptions, Z as ZapierSdkOptions$1, E as EventEmissionContext, A as ApiClient, b as Manifest, R as ResolvedAppLocator, U as UpdateManifestEntryOptions, c as UpdateManifestEntryResult, d as AddActionEntryOptions, e as AddActionEntryResult, f as ActionEntry, g as findManifestEntry, r as readManifestFromFile, h as CapabilitiesContext, i as PaginatedSdkResult, F as FieldsetItem, j as PositionalMetadata, O as OutputFormatter, k as ZapierFetchInitOptions, D as DrainTriggerInboxOptions, l as DynamicResolver, W as WatchTriggerInboxOptions, m as ActionProxy, n as ZapierSdkApps, o as WithAddPlugin } from './index-
|
|
2
|
-
export { x as Action,
|
|
1
|
+
import { B as BaseSdkOptions, P as PluginStack, a as PluginMeta, M as MethodHooks, C as CoreOptions, Z as ZapierSdkOptions$1, E as EventEmissionContext, A as ApiClient, b as Manifest, R as ResolvedAppLocator, U as UpdateManifestEntryOptions, c as UpdateManifestEntryResult, d as AddActionEntryOptions, e as AddActionEntryResult, f as ActionEntry, g as findManifestEntry, r as readManifestFromFile, h as CapabilitiesContext, i as PaginatedSdkResult, F as FieldsetItem, j as PositionalMetadata, O as OutputFormatter, k as ZapierFetchInitOptions, D as DrainTriggerInboxOptions, l as DynamicResolver, W as WatchTriggerInboxOptions, m as ActionProxy, n as ZapierSdkApps, o as WithAddPlugin } from './index-DC31DAP2.mjs';
|
|
2
|
+
export { x as Action, ca as ActionExecutionOptions, I as ActionExecutionResult, J as ActionField, K as ActionFieldChoice, aO as ActionItem, bo as ActionKeyProperty, aY as ActionKeyPropertySchema, bp as ActionProperty, aZ as ActionPropertySchema, aE as ActionResolverItem, bA as ActionTimeoutMsProperty, b8 as ActionTimeoutMsPropertySchema, aF as ActionTypeItem, bn as ActionTypeProperty, aX as ActionTypePropertySchema, c6 as ApiError, dA as ApiEvent, cU as ApiPluginOptions, cW as ApiPluginProvides, y as App, cb as AppFactoryInput, aM as AppItem, bl as AppKeyProperty, aV as AppKeyPropertySchema, bm as AppProperty, aW as AppPropertySchema, eJ as ApplicationLifecycleEventData, c2 as ApprovalStatus, c9 as AppsPluginProvides, bF as AppsProperty, bd as AppsPropertySchema, a5 as ArrayResolver, dz as AuthEvent, bt as AuthenticationIdProperty, b0 as AuthenticationIdPropertySchema, eR as BaseEvent, as as BaseSdkOptionsSchema, ag as BatchOptions, cH as CONTEXT_CACHE_MAX_SIZE, cG as CONTEXT_CACHE_TTL_MS, aw as CORE_ERROR_SYMBOL, H as Choice, dG as ClientCredentialsObject, dR as ClientCredentialsObjectSchema, V as Connection, dZ as ConnectionEntry, dY as ConnectionEntrySchema, br as ConnectionIdProperty, a$ as ConnectionIdPropertySchema, aN as ConnectionItem, bs as ConnectionProperty, b1 as ConnectionPropertySchema, d$ as ConnectionsMap, d_ as ConnectionsMapSchema, e1 as ConnectionsPluginProvides, bH as ConnectionsProperty, bf as ConnectionsPropertySchema, X as ConnectionsResponse, ax as CoreErrorCode, ct as CreateClientCredentialsPluginProvides, er as CreateTableFieldsPluginProvides, el as CreateTablePluginProvides, ez as CreateTableRecordsPluginProvides, dD as Credentials, dW as CredentialsFunction, dV as CredentialsFunctionSchema, dF as CredentialsObject, dT as CredentialsObjectSchema, dX as CredentialsSchema, e6 as DEFAULT_ACTION_TIMEOUT_MS, ee as DEFAULT_APPROVAL_TIMEOUT_MS, cQ as DEFAULT_CONFIG_PATH, ef as DEFAULT_MAX_APPROVAL_RETRIES, e5 as DEFAULT_PAGE_SIZE, by as DebugProperty, b6 as DebugPropertySchema, cv as DeleteClientCredentialsPluginProvides, et as DeleteTableFieldsPluginProvides, en as DeleteTablePluginProvides, eB as DeleteTableRecordsPluginProvides, s as DrainTriggerInboxCallback, t as DrainTriggerInboxErrorObserver, a8 as DynamicListResolver, a9 as DynamicSearchResolver, eK as EnhancedErrorEventData, bN as ErrorOptions, dC as EventCallback, eI as EventContext, eF as EventEmissionConfig, eH as EventEmissionProvides, cd as FetchPluginProvides, z as Field, bE as FieldsProperty, bc as FieldsPropertySchema, aa as FieldsResolver, v as FindFirstAuthenticationPluginProvides, cD as FindFirstConnectionPluginProvides, w as FindUniqueAuthenticationPluginProvides, cF as FindUniqueConnectionPluginProvides, a3 as FormattedItem, ar as FunctionDeprecation, aq as FunctionRegistryEntry, cn as GetActionInputFieldsSchemaPluginProvides, cz as GetActionPluginProvides, cx as GetAppPluginProvides, G as GetAuthenticationPluginProvides, cB as GetConnectionPluginProvides, cT as GetProfilePluginProvides, ej as GetTablePluginProvides, ev as GetTableRecordPluginProvides, aQ as InfoFieldItem, aP as InputFieldItem, bq as InputFieldProperty, a_ as InputFieldPropertySchema, bu as InputsProperty, b2 as InputsPropertySchema, bM as LeaseLimitProperty, bk as LeaseLimitPropertySchema, bK as LeaseProperty, bi as LeasePropertySchema, bL as LeaseSecondsProperty, bj as LeaseSecondsPropertySchema, L as LeasedTriggerMessageItem, bv as LimitProperty, b3 as LimitPropertySchema, cl as ListActionInputFieldChoicesPluginProvides, cj as ListActionInputFieldsPluginProvides, ch as ListActionsPluginProvides, cf as ListAppsPluginProvides, u as ListAuthenticationsPluginProvides, cr as ListClientCredentialsPluginProvides, cp as ListConnectionsPluginProvides, ep as ListTableFieldsPluginProvides, ex as ListTableRecordsPluginProvides, eh as ListTablesPluginProvides, dB as LoadingEvent, e9 as MAX_CONCURRENCY_LIMIT, e4 as MAX_PAGE_LIMIT, cR as ManifestEntry, cM as ManifestPluginOptions, cP as ManifestPluginProvides, eS as MethodCalledEvent, eL as MethodCalledEventData, N as Need, Q as NeedsRequest, S as NeedsResponse, bw as OffsetProperty, b4 as OffsetPropertySchema, bx as OutputProperty, b5 as OutputPropertySchema, aU as PaginatedSdkFunction, bz as ParamsProperty, b7 as ParamsPropertySchema, dH as PkceCredentialsObject, dS as PkceCredentialsObjectSchema, ay as Plugin, az as PluginProvides, aI as PollOptions, c0 as RateLimitInfo, bC as RecordProperty, ba as RecordPropertySchema, bD as RecordsProperty, bb as RecordsPropertySchema, al as RelayFetchSchema, ak as RelayRequestSchema, aH as RequestOptions, cL as RequestPluginProvides, dl as ResolveAuthTokenOptions, dM as ResolveCredentialsOptions, dE as ResolvedCredentials, dU as ResolvedCredentialsSchema, a4 as Resolver, a6 as ResolverMetadata, aR as RootFieldItem, cJ as RunActionPluginProvides, dy as SdkEvent, aT as SdkPage, aL as SseMessage, a7 as StaticResolver, bB as TableProperty, b9 as TablePropertySchema, bG as TablesProperty, be as TablesPropertySchema, bJ as TriggerInboxNameProperty, bh as TriggerInboxNamePropertySchema, bI as TriggerInboxProperty, bg as TriggerInboxPropertySchema, T as TriggerMessageStatus, eD as UpdateTableRecordsPluginProvides, Y as UserProfile, aS as UserProfileItem, e2 as ZAPIER_BASE_URL, eb as ZAPIER_MAX_CONCURRENT_REQUESTS, e7 as ZAPIER_MAX_NETWORK_RETRIES, e8 as ZAPIER_MAX_NETWORK_RETRY_DELAY_MS, p as ZapierAbortDrainSignal, b_ as ZapierActionError, bT as ZapierApiError, bU as ZapierAppNotFoundError, c3 as ZapierApprovalError, bR as ZapierAuthenticationError, bY as ZapierBundleError, du as ZapierCache, dv as ZapierCacheEntry, dw as ZapierCacheSetOptions, bX as ZapierConfigurationError, b$ as ZapierConflictError, bO as ZapierError, bV as ZapierNotFoundError, c1 as ZapierRateLimitError, c4 as ZapierRelayError, q as ZapierReleaseTriggerMessageSignal, bW as ZapierResourceNotFoundError, c7 as ZapierSignal, bZ as ZapierTimeoutError, bQ as ZapierUnknownError, bP as ZapierValidationError, cZ as actionKeyResolver, cY as actionTypeResolver, a2 as addPlugin, cV as apiPlugin, cX as appKeyResolver, c8 as appsPlugin, c$ as authenticationIdGenericResolver, c_ as authenticationIdResolver, af as batch, eM as buildApplicationLifecycleEvent, ah as buildCapabilityMessage, eO as buildErrorEvent, eN as buildErrorEventWithContext, eQ as buildMethodCalledEvent, eE as cleanupEventListeners, dm as clearTokenCache, d3 as clientCredentialsNameResolver, d4 as clientIdResolver, aD as composePlugins, c$ as connectionIdGenericResolver, c_ as connectionIdResolver, e0 as connectionsPlugin, eP as createBaseEvent, cs as createClientCredentialsPlugin, a1 as createCorePlugin, $ as createFunction, dx as createMemoryCache, ao as createOptionsPlugin, aC as createPaginatedPluginMethod, aB as createPluginMethod, a0 as createPluginStack, an as createSdk, eq as createTableFieldsPlugin, ek as createTablePlugin, ey as createTableRecordsPlugin, aJ as createZapierApi, ap as createZapierCoreStack, am as createZapierSdkWithoutRegistry, aA as definePlugin, cu as deleteClientCredentialsPlugin, es as deleteTableFieldsPlugin, em as deleteTablePlugin, eA as deleteTableRecordsPlugin, d8 as durableRunIdResolver, eG as eventEmissionPlugin, cc as fetchPlugin, cC as findFirstConnectionPlugin, cE as findUniqueConnectionPlugin, c5 as formatErrorMessage, eT as generateEventId, cm as getActionInputFieldsSchemaPlugin, cy as getActionPlugin, cw as getAppPlugin, dP as getBaseUrlFromCredentials, eZ as getCiPlatform, dQ as getClientIdFromCredentials, cA as getConnectionPlugin, av as getCoreErrorCause, au as getCoreErrorCode, e$ as getCpuTime, eU as getCurrentTimestamp, e_ as getMemoryUsage, aK as getOrCreateApiClient, eW as getOsInfo, eX as getPlatformVersions, cN as getPreferredManifestEntryKey, cS as getProfilePlugin, eV as getReleaseId, ei as getTablePlugin, eu as getTableRecordPlugin, dr as getTokenFromCliLogin, ec as getZapierApprovalMode, ed as getZapierDefaultApprovalMode, e3 as getZapierSdkService, dp as injectCliLogin, d2 as inputFieldKeyResolver, d1 as inputsAllOptionalResolver, d0 as inputsResolver, dn as invalidateCachedToken, dt as invalidateCredentialsToken, eY as isCi, dq as isCliLoginAvailable, dI as isClientCredentials, at as isCoreError, dL as isCredentialsFunction, dK as isCredentialsObject, dJ as isPkceCredentials, _ as isPositional, ck as listActionInputFieldChoicesPlugin, ci as listActionInputFieldsPlugin, cg as listActionsPlugin, ce as listAppsPlugin, cq as listClientCredentialsPlugin, co as listConnectionsPlugin, eo as listTableFieldsPlugin, ew as listTableRecordsPlugin, eg as listTablesPlugin, ai as logDeprecation, cO as manifestPlugin, ea as parseConcurrencyEnvVar, aG as registryPlugin, cK as requestPlugin, aj as resetDeprecationWarnings, ds as resolveAuthToken, dO as resolveCredentials, dN as resolveCredentialsFromEnv, cI as runActionPlugin, ab as runInMethodScope, ac as runWithTelemetryContext, de as tableFieldIdsResolver, dg as tableFieldsResolver, dj as tableFiltersResolver, d5 as tableIdResolver, df as tableNameResolver, dc as tableRecordIdResolver, dd as tableRecordIdsResolver, dh as tableRecordsResolver, dk as tableSortResolver, di as tableUpdateRecordsResolver, ad as toSnakeCase, ae as toTitleCase, d6 as triggerInboxResolver, db as triggerMessagesResolver, eC as updateTableRecordsPlugin, d7 as workflowIdResolver, da as workflowRunIdResolver, d9 as workflowVersionIdResolver, bS as zapierAdaptError } from './index-DC31DAP2.mjs';
|
|
3
3
|
import * as zod_v4_core from 'zod/v4/core';
|
|
4
4
|
import * as zod from 'zod';
|
|
5
5
|
import '@zapier/zapier-sdk-core/v0/schemas/connections';
|