@zapier/zapier-sdk 0.48.1 → 0.50.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 +21 -0
- package/README.md +832 -81
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +27 -16
- package/dist/api/polling.d.ts +7 -0
- package/dist/api/polling.d.ts.map +1 -1
- package/dist/api/polling.js +29 -4
- package/dist/api/types.d.ts +15 -7
- package/dist/api/types.d.ts.map +1 -1
- package/dist/constants.d.ts +8 -9
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +8 -11
- package/dist/experimental.cjs +10383 -0
- package/dist/experimental.d.mts +2292 -0
- package/dist/experimental.d.ts +2308 -0
- package/dist/experimental.d.ts.map +1 -0
- package/dist/experimental.js +155 -0
- package/dist/experimental.mjs +10202 -0
- package/dist/index-BQ2ii0Bs.d.mts +9538 -0
- package/dist/index-BQ2ii0Bs.d.ts +9538 -0
- package/dist/index.cjs +718 -513
- package/dist/index.d.mts +6 -8562
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.mjs +706 -512
- package/dist/plugins/api/index.d.ts.map +1 -1
- package/dist/plugins/api/index.js +1 -2
- package/dist/plugins/apps/index.d.ts +1 -1
- package/dist/plugins/deprecated/inputFields.d.ts +468 -0
- package/dist/plugins/deprecated/inputFields.d.ts.map +1 -0
- package/dist/plugins/deprecated/inputFields.js +73 -0
- package/dist/plugins/fetch/index.d.ts +1 -1
- package/dist/plugins/fetch/schemas.d.ts +1 -1
- package/dist/plugins/{getInputFieldsSchema → getActionInputFieldsSchema}/index.d.ts +4 -4
- package/dist/plugins/getActionInputFieldsSchema/index.d.ts.map +1 -0
- package/dist/plugins/{getInputFieldsSchema → getActionInputFieldsSchema}/index.js +4 -4
- package/dist/plugins/{getInputFieldsSchema → getActionInputFieldsSchema}/schemas.d.ts +8 -8
- package/dist/plugins/getActionInputFieldsSchema/schemas.d.ts.map +1 -0
- package/dist/plugins/{getInputFieldsSchema → getActionInputFieldsSchema}/schemas.js +13 -10
- package/dist/plugins/{listInputFieldChoices → listActionInputFieldChoices}/index.d.ts +4 -4
- package/dist/plugins/listActionInputFieldChoices/index.d.ts.map +1 -0
- package/dist/plugins/{listInputFieldChoices → listActionInputFieldChoices}/index.js +4 -4
- package/dist/plugins/{listInputFieldChoices → listActionInputFieldChoices}/schemas.d.ts +10 -10
- package/dist/plugins/listActionInputFieldChoices/schemas.d.ts.map +1 -0
- package/dist/plugins/{listInputFieldChoices → listActionInputFieldChoices}/schemas.js +13 -10
- package/dist/plugins/{listInputFields → listActionInputFields}/index.d.ts +4 -4
- package/dist/plugins/listActionInputFields/index.d.ts.map +1 -0
- package/dist/plugins/{listInputFields → listActionInputFields}/index.js +4 -4
- package/dist/plugins/{listInputFields → listActionInputFields}/schemas.d.ts +9 -9
- package/dist/plugins/listActionInputFields/schemas.d.ts.map +1 -0
- package/dist/plugins/{listInputFields → listActionInputFields}/schemas.js +7 -7
- package/dist/plugins/request/index.d.ts +2 -2
- package/dist/plugins/request/schemas.d.ts +2 -2
- package/dist/plugins/triggers/ackTriggerInboxMessages/index.d.ts +51 -0
- package/dist/plugins/triggers/ackTriggerInboxMessages/index.d.ts.map +1 -0
- package/dist/plugins/triggers/ackTriggerInboxMessages/index.js +35 -0
- package/dist/plugins/triggers/ackTriggerInboxMessages/schemas.d.ts +34 -0
- package/dist/plugins/triggers/ackTriggerInboxMessages/schemas.d.ts.map +1 -0
- package/dist/plugins/triggers/ackTriggerInboxMessages/schemas.js +17 -0
- package/dist/plugins/triggers/createTriggerInbox/index.d.ts +62 -0
- package/dist/plugins/triggers/createTriggerInbox/index.d.ts.map +1 -0
- package/dist/plugins/triggers/createTriggerInbox/index.js +54 -0
- package/dist/plugins/triggers/createTriggerInbox/schemas.d.ts +20 -0
- package/dist/plugins/triggers/createTriggerInbox/schemas.d.ts.map +1 -0
- package/dist/plugins/triggers/createTriggerInbox/schemas.js +20 -0
- package/dist/plugins/triggers/deleteTriggerInbox/index.d.ts +50 -0
- package/dist/plugins/triggers/deleteTriggerInbox/index.d.ts.map +1 -0
- package/dist/plugins/triggers/deleteTriggerInbox/index.js +27 -0
- package/dist/plugins/triggers/deleteTriggerInbox/schemas.d.ts +14 -0
- package/dist/plugins/triggers/deleteTriggerInbox/schemas.d.ts.map +1 -0
- package/dist/plugins/triggers/deleteTriggerInbox/schemas.js +9 -0
- package/dist/plugins/triggers/drainTriggerInbox/index.d.ts +213 -0
- package/dist/plugins/triggers/drainTriggerInbox/index.d.ts.map +1 -0
- package/dist/plugins/triggers/drainTriggerInbox/index.js +227 -0
- package/dist/plugins/triggers/drainTriggerInbox/pipeline.d.ts +56 -0
- package/dist/plugins/triggers/drainTriggerInbox/pipeline.d.ts.map +1 -0
- package/dist/plugins/triggers/drainTriggerInbox/pipeline.js +225 -0
- package/dist/plugins/triggers/drainTriggerInbox/schemas.d.ts +104 -0
- package/dist/plugins/triggers/drainTriggerInbox/schemas.d.ts.map +1 -0
- package/dist/plugins/triggers/drainTriggerInbox/schemas.js +102 -0
- package/dist/plugins/triggers/ensureTriggerInbox/index.d.ts +63 -0
- package/dist/plugins/triggers/ensureTriggerInbox/index.d.ts.map +1 -0
- package/dist/plugins/triggers/ensureTriggerInbox/index.js +77 -0
- package/dist/plugins/triggers/ensureTriggerInbox/schemas.d.ts +21 -0
- package/dist/plugins/triggers/ensureTriggerInbox/schemas.d.ts.map +1 -0
- package/dist/plugins/triggers/ensureTriggerInbox/schemas.js +21 -0
- package/dist/plugins/triggers/getTriggerInbox/index.d.ts +50 -0
- package/dist/plugins/triggers/getTriggerInbox/index.d.ts.map +1 -0
- package/dist/plugins/triggers/getTriggerInbox/index.js +26 -0
- package/dist/plugins/triggers/getTriggerInbox/schemas.d.ts +14 -0
- package/dist/plugins/triggers/getTriggerInbox/schemas.d.ts.map +1 -0
- package/dist/plugins/triggers/getTriggerInbox/schemas.js +9 -0
- package/dist/plugins/triggers/getTriggerInputFieldsSchema/index.d.ts +48 -0
- package/dist/plugins/triggers/getTriggerInputFieldsSchema/index.d.ts.map +1 -0
- package/dist/plugins/triggers/getTriggerInputFieldsSchema/index.js +23 -0
- package/dist/plugins/triggers/getTriggerInputFieldsSchema/schemas.d.ts +13 -0
- package/dist/plugins/triggers/getTriggerInputFieldsSchema/schemas.d.ts.map +1 -0
- package/dist/plugins/triggers/getTriggerInputFieldsSchema/schemas.js +10 -0
- package/dist/plugins/triggers/leaseTriggerInboxMessages/index.d.ts +58 -0
- package/dist/plugins/triggers/leaseTriggerInboxMessages/index.d.ts.map +1 -0
- package/dist/plugins/triggers/leaseTriggerInboxMessages/index.js +70 -0
- package/dist/plugins/triggers/leaseTriggerInboxMessages/schemas.d.ts +57 -0
- package/dist/plugins/triggers/leaseTriggerInboxMessages/schemas.d.ts.map +1 -0
- package/dist/plugins/triggers/leaseTriggerInboxMessages/schemas.js +25 -0
- package/dist/plugins/triggers/listTriggerInboxMessages/index.d.ts +51 -0
- package/dist/plugins/triggers/listTriggerInboxMessages/index.d.ts.map +1 -0
- package/dist/plugins/triggers/listTriggerInboxMessages/index.js +48 -0
- package/dist/plugins/triggers/listTriggerInboxMessages/schemas.d.ts +37 -0
- package/dist/plugins/triggers/listTriggerInboxMessages/schemas.d.ts.map +1 -0
- package/dist/plugins/triggers/listTriggerInboxMessages/schemas.js +27 -0
- package/dist/plugins/triggers/listTriggerInboxes/index.d.ts +56 -0
- package/dist/plugins/triggers/listTriggerInboxes/index.d.ts.map +1 -0
- package/dist/plugins/triggers/listTriggerInboxes/index.js +51 -0
- package/dist/plugins/triggers/listTriggerInboxes/schemas.d.ts +58 -0
- package/dist/plugins/triggers/listTriggerInboxes/schemas.d.ts.map +1 -0
- package/dist/plugins/triggers/listTriggerInboxes/schemas.js +35 -0
- package/dist/plugins/triggers/listTriggerInputFieldChoices/index.d.ts +77 -0
- package/dist/plugins/triggers/listTriggerInputFieldChoices/index.d.ts.map +1 -0
- package/dist/plugins/triggers/listTriggerInputFieldChoices/index.js +30 -0
- package/dist/plugins/triggers/listTriggerInputFieldChoices/schemas.d.ts +20 -0
- package/dist/plugins/triggers/listTriggerInputFieldChoices/schemas.d.ts.map +1 -0
- package/dist/plugins/triggers/listTriggerInputFieldChoices/schemas.js +28 -0
- package/dist/plugins/triggers/listTriggerInputFields/index.d.ts +101 -0
- package/dist/plugins/triggers/listTriggerInputFields/index.d.ts.map +1 -0
- package/dist/plugins/triggers/listTriggerInputFields/index.js +33 -0
- package/dist/plugins/triggers/listTriggerInputFields/schemas.d.ts +16 -0
- package/dist/plugins/triggers/listTriggerInputFields/schemas.d.ts.map +1 -0
- package/dist/plugins/triggers/listTriggerInputFields/schemas.js +21 -0
- package/dist/plugins/triggers/pauseTriggerInbox/index.d.ts +50 -0
- package/dist/plugins/triggers/pauseTriggerInbox/index.d.ts.map +1 -0
- package/dist/plugins/triggers/pauseTriggerInbox/index.js +26 -0
- package/dist/plugins/triggers/pauseTriggerInbox/schemas.d.ts +14 -0
- package/dist/plugins/triggers/pauseTriggerInbox/schemas.d.ts.map +1 -0
- package/dist/plugins/triggers/pauseTriggerInbox/schemas.js +9 -0
- package/dist/plugins/triggers/releaseTriggerInboxMessages/index.d.ts +51 -0
- package/dist/plugins/triggers/releaseTriggerInboxMessages/index.d.ts.map +1 -0
- package/dist/plugins/triggers/releaseTriggerInboxMessages/index.js +37 -0
- package/dist/plugins/triggers/releaseTriggerInboxMessages/schemas.d.ts +34 -0
- package/dist/plugins/triggers/releaseTriggerInboxMessages/schemas.d.ts.map +1 -0
- package/dist/plugins/triggers/releaseTriggerInboxMessages/schemas.js +17 -0
- package/dist/plugins/triggers/resumeTriggerInbox/index.d.ts +50 -0
- package/dist/plugins/triggers/resumeTriggerInbox/index.d.ts.map +1 -0
- package/dist/plugins/triggers/resumeTriggerInbox/index.js +26 -0
- package/dist/plugins/triggers/resumeTriggerInbox/schemas.d.ts +14 -0
- package/dist/plugins/triggers/resumeTriggerInbox/schemas.d.ts.map +1 -0
- package/dist/plugins/triggers/resumeTriggerInbox/schemas.js +9 -0
- package/dist/plugins/triggers/shared.d.ts +17 -0
- package/dist/plugins/triggers/shared.d.ts.map +1 -0
- package/dist/plugins/triggers/shared.js +16 -0
- package/dist/plugins/triggers/updateTriggerInbox/index.d.ts +51 -0
- package/dist/plugins/triggers/updateTriggerInbox/index.d.ts.map +1 -0
- package/dist/plugins/triggers/updateTriggerInbox/index.js +30 -0
- package/dist/plugins/triggers/updateTriggerInbox/schemas.d.ts +15 -0
- package/dist/plugins/triggers/updateTriggerInbox/schemas.d.ts.map +1 -0
- package/dist/plugins/triggers/updateTriggerInbox/schemas.js +15 -0
- package/dist/plugins/triggers/utils.d.ts +17 -0
- package/dist/plugins/triggers/utils.d.ts.map +1 -0
- package/dist/plugins/triggers/utils.js +28 -0
- package/dist/plugins/triggers/watchTriggerInbox/index.d.ts +163 -0
- package/dist/plugins/triggers/watchTriggerInbox/index.d.ts.map +1 -0
- package/dist/plugins/triggers/watchTriggerInbox/index.js +111 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +2 -0
- package/dist/resolvers/actionKey.d.ts +1 -0
- package/dist/resolvers/actionKey.d.ts.map +1 -1
- package/dist/resolvers/actionKey.js +1 -1
- package/dist/resolvers/index.d.ts +2 -2
- package/dist/resolvers/index.d.ts.map +1 -1
- package/dist/resolvers/index.js +2 -2
- package/dist/resolvers/triggerInbox.d.ts +4 -0
- package/dist/resolvers/triggerInbox.d.ts.map +1 -0
- package/dist/resolvers/triggerInbox.js +18 -0
- package/dist/schemas/TriggerInbox.d.ts +59 -0
- package/dist/schemas/TriggerInbox.d.ts.map +1 -0
- package/dist/schemas/TriggerInbox.js +81 -0
- package/dist/schemas/TriggerMessage.d.ts +48 -0
- package/dist/schemas/TriggerMessage.d.ts.map +1 -0
- package/dist/schemas/TriggerMessage.js +79 -0
- package/dist/sdk.d.ts +621 -17
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +26 -9
- package/dist/types/errors.d.ts +18 -5
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/errors.js +16 -0
- package/dist/types/plugin.d.ts +12 -1
- package/dist/types/plugin.d.ts.map +1 -1
- package/dist/types/properties.d.ts +12 -0
- package/dist/types/properties.d.ts.map +1 -1
- package/dist/types/properties.js +25 -0
- package/dist/types/registry.d.ts +5 -0
- package/dist/types/registry.d.ts.map +1 -1
- package/dist/types/sdk.d.ts +4 -4
- package/dist/types/sdk.d.ts.map +1 -1
- package/dist/types/sdk.js +4 -11
- package/dist/types/signals.d.ts +20 -0
- package/dist/types/signals.d.ts.map +1 -0
- package/dist/types/signals.js +21 -0
- package/dist/utils/abort-utils.d.ts +13 -0
- package/dist/utils/abort-utils.d.ts.map +1 -1
- package/dist/utils/abort-utils.js +15 -0
- package/dist/utils/retry-utils.d.ts +6 -2
- package/dist/utils/retry-utils.d.ts.map +1 -1
- package/dist/utils/retry-utils.js +22 -3
- package/dist/utils/schema-utils.d.ts +19 -1
- package/dist/utils/schema-utils.d.ts.map +1 -1
- package/package.json +12 -1
- package/dist/plugins/getInputFieldsSchema/index.d.ts.map +0 -1
- package/dist/plugins/getInputFieldsSchema/schemas.d.ts.map +0 -1
- package/dist/plugins/listInputFieldChoices/index.d.ts.map +0 -1
- package/dist/plugins/listInputFieldChoices/schemas.d.ts.map +0 -1
- package/dist/plugins/listInputFields/index.d.ts.map +0 -1
- package/dist/plugins/listInputFields/schemas.d.ts.map +0 -1
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { definePlugin } from "../../../utils/plugin-utils";
|
|
2
|
+
import { DrainTriggerInboxSchema, ZapierAbortDrainSignal, ZapierReleaseTriggerMessageSignal, } from "./schemas";
|
|
3
|
+
import { runBatchedDrainPipeline } from "./pipeline";
|
|
4
|
+
import { ZapierApiError, ZapierValidationError } from "../../../types/errors";
|
|
5
|
+
import { ZapierSignal } from "../../../types/signals";
|
|
6
|
+
import { triggerInboxResolver } from "../../../resolvers";
|
|
7
|
+
import { resolveTriggerInboxId } from "../utils";
|
|
8
|
+
import { triggersDefaults } from "../shared";
|
|
9
|
+
import { isAbortError } from "../../../utils/abort-utils";
|
|
10
|
+
export { ZapierAbortDrainSignal, ZapierReleaseTriggerMessageSignal, } from "./schemas";
|
|
11
|
+
/**
|
|
12
|
+
* Server returns 400 lease_expired when a UUIDv7 timestamp is in the
|
|
13
|
+
* past. The API atomically quarantines messages that have hit
|
|
14
|
+
* MESSAGE_LEASE_MAX before raising — work has been done server-side
|
|
15
|
+
* already, so failing the drain on a clock-skew race would be a poor
|
|
16
|
+
* UX.
|
|
17
|
+
*/
|
|
18
|
+
function isLeaseExpiredError(err) {
|
|
19
|
+
if (!(err instanceof ZapierValidationError))
|
|
20
|
+
return false;
|
|
21
|
+
return err.errors?.some((e) => e.code === "lease_expired") ?? false;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* One drain pass through `runBatchedDrainPipeline`. Used directly by
|
|
25
|
+
* `drainTriggerInbox` (single pass) and as the inner loop body of
|
|
26
|
+
* `watchTriggerInbox` (called repeatedly with poll backoff between
|
|
27
|
+
* empty passes).
|
|
28
|
+
*/
|
|
29
|
+
export async function runDrainPass(options) {
|
|
30
|
+
const { sdk, inboxId, onMessage, concurrency, leaseLimit, leaseSeconds, maxMessages, releaseOnError, continueOnError, onError, signal, } = options;
|
|
31
|
+
let firstFetch = options.firstFetch;
|
|
32
|
+
let abortedFromCallback = false;
|
|
33
|
+
let firstHandlerError = undefined;
|
|
34
|
+
const outcomes = await runBatchedDrainPipeline({
|
|
35
|
+
concurrency,
|
|
36
|
+
maxItems: maxMessages,
|
|
37
|
+
leaseSize: leaseLimit,
|
|
38
|
+
fetchBatch: async (requestedSize) => {
|
|
39
|
+
if (signal?.aborted)
|
|
40
|
+
return "exhausted";
|
|
41
|
+
let lease;
|
|
42
|
+
try {
|
|
43
|
+
({ data: lease } = await sdk.leaseTriggerInboxMessages({
|
|
44
|
+
inbox: inboxId,
|
|
45
|
+
leaseLimit: requestedSize,
|
|
46
|
+
leaseSeconds,
|
|
47
|
+
signal,
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
// Only swallow abort-shaped failures. A real auth / validation
|
|
52
|
+
// / transport error that races with cancellation must still
|
|
53
|
+
// reject — checking `signal?.aborted` alone would silently hide
|
|
54
|
+
// a 401 that landed in the same tick the user pressed Ctrl-C.
|
|
55
|
+
if (signal?.aborted && isAbortError(err))
|
|
56
|
+
return "exhausted";
|
|
57
|
+
throw err;
|
|
58
|
+
}
|
|
59
|
+
if (lease.results.length === 0) {
|
|
60
|
+
if (firstFetch &&
|
|
61
|
+
lease.inbox_attributes.status === "initialization_failure") {
|
|
62
|
+
throw new ZapierApiError(`Trigger inbox ${inboxId} is in initialization_failure state — inspect via getTriggerInbox.`);
|
|
63
|
+
}
|
|
64
|
+
firstFetch = false;
|
|
65
|
+
return "exhausted";
|
|
66
|
+
}
|
|
67
|
+
firstFetch = false;
|
|
68
|
+
if (!lease.lease_id)
|
|
69
|
+
return "exhausted";
|
|
70
|
+
return { id: lease.lease_id, items: lease.results };
|
|
71
|
+
},
|
|
72
|
+
processItem: async (message) => {
|
|
73
|
+
if (signal?.aborted) {
|
|
74
|
+
return {
|
|
75
|
+
value: message,
|
|
76
|
+
action: "release",
|
|
77
|
+
abort: true,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
await onMessage(message);
|
|
82
|
+
return { value: message, action: "ack" };
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
let action = "ignore";
|
|
86
|
+
let abort = false;
|
|
87
|
+
if (err instanceof ZapierAbortDrainSignal) {
|
|
88
|
+
abort = true;
|
|
89
|
+
abortedFromCallback = true;
|
|
90
|
+
if (releaseOnError)
|
|
91
|
+
action = "release";
|
|
92
|
+
}
|
|
93
|
+
else if (err instanceof ZapierReleaseTriggerMessageSignal) {
|
|
94
|
+
action = "release";
|
|
95
|
+
}
|
|
96
|
+
else if (releaseOnError) {
|
|
97
|
+
action = "release";
|
|
98
|
+
}
|
|
99
|
+
// Observe (signals filtered — they're control-flow, not failures).
|
|
100
|
+
if (onError && !(err instanceof ZapierSignal)) {
|
|
101
|
+
try {
|
|
102
|
+
await onError(err, message);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// observer's own error is intentionally swallowed.
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Fail-fast: capture the first real error and tell the
|
|
109
|
+
// pipeline to abort. continueOnError keeps it running.
|
|
110
|
+
if (!continueOnError && !(err instanceof ZapierSignal)) {
|
|
111
|
+
if (firstHandlerError === undefined)
|
|
112
|
+
firstHandlerError = err;
|
|
113
|
+
abort = true;
|
|
114
|
+
}
|
|
115
|
+
return { value: message, action, abort };
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
ackItem: async (leaseId, messageId) => {
|
|
119
|
+
try {
|
|
120
|
+
await sdk.ackTriggerInboxMessages({
|
|
121
|
+
inbox: inboxId,
|
|
122
|
+
lease: leaseId,
|
|
123
|
+
messages: [messageId],
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
if (!isLeaseExpiredError(err))
|
|
128
|
+
throw err;
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
releaseItems: async (leaseId, messageIds) => {
|
|
132
|
+
try {
|
|
133
|
+
await sdk.releaseTriggerInboxMessages({
|
|
134
|
+
inbox: inboxId,
|
|
135
|
+
lease: leaseId,
|
|
136
|
+
messages: messageIds,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
if (!isLeaseExpiredError(err))
|
|
141
|
+
throw err;
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
if (firstHandlerError !== undefined)
|
|
146
|
+
throw firstHandlerError;
|
|
147
|
+
return { abortedFromCallback, processed: outcomes.length };
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Validate the per-message callback. `onMessage` is required — no
|
|
151
|
+
* identity default, since "lease and ack everything in this inbox"
|
|
152
|
+
* is a footgun on a casual call. JS callers that skip onMessage hit
|
|
153
|
+
* this guard at runtime; TS callers are rejected at the call site.
|
|
154
|
+
*/
|
|
155
|
+
export function requireOnMessage(onMessage) {
|
|
156
|
+
if (typeof onMessage !== "function") {
|
|
157
|
+
throw new ZapierValidationError("onMessage is required.");
|
|
158
|
+
}
|
|
159
|
+
return onMessage;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Compute concurrency and lease size with symmetric defaulting:
|
|
163
|
+
*
|
|
164
|
+
* both unset -> concurrency=1, leaseLimit=1
|
|
165
|
+
* concurrency=N -> concurrency=N, leaseLimit=N
|
|
166
|
+
* leaseLimit=L -> concurrency=L, leaseLimit=L
|
|
167
|
+
* both set -> use both as given
|
|
168
|
+
*
|
|
169
|
+
* The symmetry kills the "set leaseLimit alone, get prefetch
|
|
170
|
+
* pathology" footgun: a leased message buffer is never larger than
|
|
171
|
+
* the worker pool that can immediately work it.
|
|
172
|
+
*/
|
|
173
|
+
export function resolveConcurrencyAndLease(options) {
|
|
174
|
+
const concurrency = options.concurrency ?? options.leaseLimit ?? 1;
|
|
175
|
+
const leaseLimit = options.leaseLimit ?? concurrency;
|
|
176
|
+
return { concurrency, leaseLimit };
|
|
177
|
+
}
|
|
178
|
+
export const drainTriggerInboxPlugin = definePlugin((sdk) => {
|
|
179
|
+
async function drainTriggerInbox(options) {
|
|
180
|
+
const onMessage = requireOnMessage(options.onMessage);
|
|
181
|
+
const { concurrency, leaseLimit } = resolveConcurrencyAndLease(options);
|
|
182
|
+
const inboxId = await resolveTriggerInboxId({
|
|
183
|
+
api: sdk.context.api,
|
|
184
|
+
inbox: options.inbox,
|
|
185
|
+
});
|
|
186
|
+
await runDrainPass({
|
|
187
|
+
sdk,
|
|
188
|
+
inboxId,
|
|
189
|
+
onMessage,
|
|
190
|
+
concurrency,
|
|
191
|
+
leaseLimit,
|
|
192
|
+
leaseSeconds: options.leaseSeconds,
|
|
193
|
+
maxMessages: options.maxMessages,
|
|
194
|
+
releaseOnError: options.releaseOnError ?? false,
|
|
195
|
+
continueOnError: options.continueOnError ?? false,
|
|
196
|
+
onError: options.onError,
|
|
197
|
+
signal: options.signal,
|
|
198
|
+
firstFetch: true,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
drainTriggerInbox,
|
|
203
|
+
context: {
|
|
204
|
+
meta: {
|
|
205
|
+
drainTriggerInbox: {
|
|
206
|
+
...triggersDefaults,
|
|
207
|
+
type: "create",
|
|
208
|
+
description: "Drain an existing trigger inbox: lease currently-available messages, process each via onMessage, return when the inbox is empty, maxMessages is reached, or the abort signal fires.",
|
|
209
|
+
itemType: "void",
|
|
210
|
+
// The doc generator's default for type="create" + itemType
|
|
211
|
+
// appends "Item" (e.g. "RecordItem"), which would render
|
|
212
|
+
// "voidItem" here. drainTriggerInbox returns Promise<void>,
|
|
213
|
+
// so we override.
|
|
214
|
+
returnType: "void",
|
|
215
|
+
inputSchema: DrainTriggerInboxSchema,
|
|
216
|
+
resolvers: {
|
|
217
|
+
inbox: triggerInboxResolver,
|
|
218
|
+
},
|
|
219
|
+
// Returns Promise<void>; the CLI ships a hand-written
|
|
220
|
+
// drain-trigger-inbox plugin that adds presentation flags
|
|
221
|
+
// (interactive, --json, etc.) around this command.
|
|
222
|
+
packages: ["sdk"],
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic worker-pool drain over a batched fetch source. The pipeline
|
|
3
|
+
* owns mechanism: concurrent workers, low-watermark refill,
|
|
4
|
+
* batch-completion detection, deferred-release accumulation, and
|
|
5
|
+
* end-of-drain cleanup. Plugin-specific policy (signal interpretation,
|
|
6
|
+
* error swallowing, locator resolution) lives in the caller's hooks.
|
|
7
|
+
*/
|
|
8
|
+
export type ItemAction = "ack" | "release" | "ignore";
|
|
9
|
+
export interface ProcessItemResult<TValue> {
|
|
10
|
+
/** Pushed onto the drain's results array. */
|
|
11
|
+
value: TValue;
|
|
12
|
+
/** What the pipeline does with the item: ack, release, or ignore (lease timeout returns it). */
|
|
13
|
+
action: ItemAction;
|
|
14
|
+
/** Stop the drain after current in-flight items finish. */
|
|
15
|
+
abort?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface BatchedDrainPipelineOptions<TItem extends {
|
|
18
|
+
id: string;
|
|
19
|
+
}, TValue> {
|
|
20
|
+
concurrency: number;
|
|
21
|
+
maxItems?: number;
|
|
22
|
+
leaseSize: number;
|
|
23
|
+
/**
|
|
24
|
+
* Fetch the next batch. `"exhausted"` signals no more items will arrive.
|
|
25
|
+
* Errors thrown after the initial fetch surface only after in-flight
|
|
26
|
+
* workers wind down.
|
|
27
|
+
*/
|
|
28
|
+
fetchBatch(requestedSize: number): Promise<{
|
|
29
|
+
id: string;
|
|
30
|
+
items: TItem[];
|
|
31
|
+
} | "exhausted">;
|
|
32
|
+
/**
|
|
33
|
+
* Run the per-item callback. The returned `action` controls
|
|
34
|
+
* ack/release; `abort: true` short-circuits the drain after current
|
|
35
|
+
* in-flight items finish.
|
|
36
|
+
*/
|
|
37
|
+
processItem(item: TItem): Promise<ProcessItemResult<TValue>>;
|
|
38
|
+
/**
|
|
39
|
+
* Called once per item the callback marked `"ack"`, immediately after
|
|
40
|
+
* processItem returns. Per-item rather than per-batch so a crash
|
|
41
|
+
* mid-drain can't roll back already-committed items. The hook is on
|
|
42
|
+
* the hot path; in drainTriggerInbox it issues one
|
|
43
|
+
* sdk.ackTriggerInboxMessages call per acked message.
|
|
44
|
+
*/
|
|
45
|
+
ackItem(batchId: string, itemId: string): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Called once at drain end per batch with items the callback marked
|
|
48
|
+
* `"release"`. Stays batched (vs ackItem's per-item) because an
|
|
49
|
+
* unreleased item just waits for the lease timeout — no work is lost.
|
|
50
|
+
*/
|
|
51
|
+
releaseItems(batchId: string, itemIds: string[]): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
export declare function runBatchedDrainPipeline<TItem extends {
|
|
54
|
+
id: string;
|
|
55
|
+
}, TValue>(options: BatchedDrainPipelineOptions<TItem, TValue>): Promise<TValue[]>;
|
|
56
|
+
//# sourceMappingURL=pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../../../src/plugins/triggers/drainTriggerInbox/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEtD,MAAM,WAAW,iBAAiB,CAAC,MAAM;IACvC,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,MAAM,EAAE,UAAU,CAAC;IACnB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,2BAA2B,CAC1C,KAAK,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAC5B,MAAM;IAEN,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,UAAU,CACR,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,EAAE,CAAA;KAAE,GAAG,WAAW,CAAC,CAAC;IACzD;;;;OAIG;IACH,WAAW,CAAC,IAAI,EAAE,KAAK,GAAG,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7D;;;;;;OAMG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD;;;;OAIG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjE;AA4ED,wBAAsB,uBAAuB,CAC3C,KAAK,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAC5B,MAAM,EACN,OAAO,EAAE,2BAA2B,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAyKxE"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic worker-pool drain over a batched fetch source. The pipeline
|
|
3
|
+
* owns mechanism: concurrent workers, low-watermark refill,
|
|
4
|
+
* batch-completion detection, deferred-release accumulation, and
|
|
5
|
+
* end-of-drain cleanup. Plugin-specific policy (signal interpretation,
|
|
6
|
+
* error swallowing, locator resolution) lives in the caller's hooks.
|
|
7
|
+
*/
|
|
8
|
+
// With per-item ack the tracker is purely a counter for refill math and
|
|
9
|
+
// the worker exit condition. It used to also accumulate fulfilled item
|
|
10
|
+
// ids for a per-batch ack call.
|
|
11
|
+
function createBatchTracker() {
|
|
12
|
+
const batches = new Map();
|
|
13
|
+
return {
|
|
14
|
+
addBatch(id, total) {
|
|
15
|
+
batches.set(id, { total, inFlight: 0, completed: 0 });
|
|
16
|
+
},
|
|
17
|
+
markInFlight(id) {
|
|
18
|
+
const e = batches.get(id);
|
|
19
|
+
if (e)
|
|
20
|
+
e.inFlight++;
|
|
21
|
+
},
|
|
22
|
+
/** Decrement inFlight and increment completed. Paired with markInFlight. */
|
|
23
|
+
markCompleted(id) {
|
|
24
|
+
const e = batches.get(id);
|
|
25
|
+
if (!e)
|
|
26
|
+
return;
|
|
27
|
+
e.inFlight--;
|
|
28
|
+
e.completed++;
|
|
29
|
+
},
|
|
30
|
+
/** Drop the batch once all items completed; tracker stays small over long drains. */
|
|
31
|
+
finalizeIfDone(id) {
|
|
32
|
+
const e = batches.get(id);
|
|
33
|
+
if (e && e.completed === e.total)
|
|
34
|
+
batches.delete(id);
|
|
35
|
+
},
|
|
36
|
+
inFlightTotal() {
|
|
37
|
+
let n = 0;
|
|
38
|
+
for (const e of batches.values())
|
|
39
|
+
n += e.inFlight;
|
|
40
|
+
return n;
|
|
41
|
+
},
|
|
42
|
+
/** Items leased but not yet completed (queued + in-flight). */
|
|
43
|
+
pipelineSize() {
|
|
44
|
+
let n = 0;
|
|
45
|
+
for (const e of batches.values())
|
|
46
|
+
n += e.total - e.completed;
|
|
47
|
+
return n;
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* One-shot waiter. Workers `wait()` when the queue is empty; producers
|
|
53
|
+
* `notifyAll()` to wake them. Each `notifyAll` swaps in a fresh waiter
|
|
54
|
+
* so already-woken workers don't re-fire on the next notify.
|
|
55
|
+
*/
|
|
56
|
+
function createWaiter() {
|
|
57
|
+
const make = () => {
|
|
58
|
+
let signal;
|
|
59
|
+
const promise = new Promise((r) => {
|
|
60
|
+
signal = r;
|
|
61
|
+
});
|
|
62
|
+
return { promise, signal };
|
|
63
|
+
};
|
|
64
|
+
let current = make();
|
|
65
|
+
return {
|
|
66
|
+
wait: () => current.promise,
|
|
67
|
+
notifyAll: () => {
|
|
68
|
+
const prev = current;
|
|
69
|
+
current = make();
|
|
70
|
+
prev.signal();
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function addToMap(m, key, value) {
|
|
75
|
+
const existing = m.get(key) ?? [];
|
|
76
|
+
m.set(key, [...existing, value]);
|
|
77
|
+
}
|
|
78
|
+
export async function runBatchedDrainPipeline(options) {
|
|
79
|
+
const { concurrency, maxItems, leaseSize, fetchBatch, processItem, ackItem, releaseItems, } = options;
|
|
80
|
+
const tracker = createBatchTracker();
|
|
81
|
+
const waiter = createWaiter();
|
|
82
|
+
const accumulated = [];
|
|
83
|
+
const pendingReleases = new Map();
|
|
84
|
+
const queue = [];
|
|
85
|
+
let totalProcessed = 0;
|
|
86
|
+
let aborted = false;
|
|
87
|
+
let exhausted = false;
|
|
88
|
+
let fetchInProgress = false;
|
|
89
|
+
let fetchError = undefined;
|
|
90
|
+
async function tryFetch() {
|
|
91
|
+
if (fetchInProgress || exhausted || aborted)
|
|
92
|
+
return;
|
|
93
|
+
const remainingCap = maxItems !== undefined
|
|
94
|
+
? maxItems - totalProcessed - tracker.pipelineSize()
|
|
95
|
+
: Number.POSITIVE_INFINITY;
|
|
96
|
+
if (remainingCap <= 0)
|
|
97
|
+
return;
|
|
98
|
+
const requestedSize = Math.min(remainingCap, leaseSize);
|
|
99
|
+
fetchInProgress = true;
|
|
100
|
+
try {
|
|
101
|
+
const result = await fetchBatch(requestedSize);
|
|
102
|
+
if (result === "exhausted") {
|
|
103
|
+
exhausted = true;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
tracker.addBatch(result.id, result.items.length);
|
|
107
|
+
for (const item of result.items) {
|
|
108
|
+
queue.push({ item, batchId: result.id });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
fetchError = err;
|
|
113
|
+
exhausted = true;
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
fetchInProgress = false;
|
|
117
|
+
waiter.notifyAll();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async function processQueueEntry(entry) {
|
|
121
|
+
tracker.markInFlight(entry.batchId);
|
|
122
|
+
// markCompleted / finalizeIfDone / notifyAll all run in finally so a
|
|
123
|
+
// throw from processItem or ackItem still decrements inFlight and
|
|
124
|
+
// wakes peer workers. Skipping markCompleted on a processItem throw
|
|
125
|
+
// wedges sibling workers: they wake on notifyAll, check
|
|
126
|
+
// `inFlightTotal === 0` for exit, see the never-decremented count,
|
|
127
|
+
// and block again — permanently with concurrency > 1.
|
|
128
|
+
try {
|
|
129
|
+
const result = await processItem(entry.item);
|
|
130
|
+
accumulated.push(result.value);
|
|
131
|
+
totalProcessed++;
|
|
132
|
+
if (result.action === "release") {
|
|
133
|
+
addToMap(pendingReleases, entry.batchId, entry.item.id);
|
|
134
|
+
}
|
|
135
|
+
if (result.abort)
|
|
136
|
+
aborted = true;
|
|
137
|
+
if (result.action === "ack") {
|
|
138
|
+
await ackItem(entry.batchId, entry.item.id);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
finally {
|
|
142
|
+
tracker.markCompleted(entry.batchId);
|
|
143
|
+
tracker.finalizeIfDone(entry.batchId);
|
|
144
|
+
waiter.notifyAll();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async function worker() {
|
|
148
|
+
while (true) {
|
|
149
|
+
if (aborted)
|
|
150
|
+
return;
|
|
151
|
+
if (maxItems !== undefined && totalProcessed >= maxItems)
|
|
152
|
+
return;
|
|
153
|
+
const entry = queue.shift();
|
|
154
|
+
if (entry !== undefined) {
|
|
155
|
+
// Low-watermark refill: keep the pipeline at ~concurrency so a
|
|
156
|
+
// freed worker has work queued. Fire-and-forget so the worker
|
|
157
|
+
// doesn't block on the lease HTTP.
|
|
158
|
+
if (tracker.pipelineSize() < concurrency &&
|
|
159
|
+
!fetchInProgress &&
|
|
160
|
+
!exhausted) {
|
|
161
|
+
void tryFetch();
|
|
162
|
+
}
|
|
163
|
+
await processQueueEntry(entry);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (!exhausted && !fetchInProgress)
|
|
167
|
+
void tryFetch();
|
|
168
|
+
if (queue.length === 0 &&
|
|
169
|
+
!fetchInProgress &&
|
|
170
|
+
(exhausted || aborted) &&
|
|
171
|
+
tracker.inFlightTotal() === 0) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
await waiter.wait();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// Initial fetch primes the queue. Errors here surface directly without
|
|
178
|
+
// ever spinning up workers.
|
|
179
|
+
await tryFetch();
|
|
180
|
+
if (fetchError !== undefined)
|
|
181
|
+
throw fetchError;
|
|
182
|
+
// Cleanup runs in finally so a thrown lease-boundary ack or a captured
|
|
183
|
+
// mid-drain fetchError still flushes deferred releases.
|
|
184
|
+
let cleanupError = undefined;
|
|
185
|
+
try {
|
|
186
|
+
if (!exhausted || queue.length > 0) {
|
|
187
|
+
// Catch-and-track on each worker so all settle before we surface
|
|
188
|
+
// the first error. With Promise.all, a failing worker rejects
|
|
189
|
+
// immediately and sibling workers continue running on the next
|
|
190
|
+
// tick, firing API calls after the caller has received the
|
|
191
|
+
// rejection.
|
|
192
|
+
let firstWorkerError = undefined;
|
|
193
|
+
const workers = Array.from({ length: concurrency }, () => worker().catch((err) => {
|
|
194
|
+
if (firstWorkerError === undefined)
|
|
195
|
+
firstWorkerError = err;
|
|
196
|
+
}));
|
|
197
|
+
await Promise.all(workers);
|
|
198
|
+
if (firstWorkerError !== undefined)
|
|
199
|
+
throw firstWorkerError;
|
|
200
|
+
}
|
|
201
|
+
if (fetchError !== undefined)
|
|
202
|
+
throw fetchError;
|
|
203
|
+
}
|
|
204
|
+
finally {
|
|
205
|
+
// Aborted-but-unstarted items are still leased to us but were never
|
|
206
|
+
// offered to the callback — release them. With per-item ack there's
|
|
207
|
+
// nothing else to flush at cleanup; successful items were acked
|
|
208
|
+
// immediately as they completed.
|
|
209
|
+
while (queue.length > 0) {
|
|
210
|
+
const entry = queue.shift();
|
|
211
|
+
addToMap(pendingReleases, entry.batchId, entry.item.id);
|
|
212
|
+
}
|
|
213
|
+
for (const [batchId, itemIds] of pendingReleases) {
|
|
214
|
+
try {
|
|
215
|
+
await releaseItems(batchId, itemIds);
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
cleanupError ?? (cleanupError = err);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (cleanupError !== undefined)
|
|
223
|
+
throw cleanupError;
|
|
224
|
+
return accumulated;
|
|
225
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { LeasedTriggerMessageItem } from "../../../schemas/TriggerMessage";
|
|
3
|
+
import { ZapierSignal } from "../../../types/signals";
|
|
4
|
+
/**
|
|
5
|
+
* Signal an `onMessage` callback can throw to release the current
|
|
6
|
+
* message back to the inbox immediately (status returns to
|
|
7
|
+
* `available`) rather than leaving it leased until the lease
|
|
8
|
+
* timeout. The actual release call is deferred to the end of the
|
|
9
|
+
* drain so the same drain doesn't immediately re-lease it.
|
|
10
|
+
*
|
|
11
|
+
* Always triggers release regardless of `releaseOnError`.
|
|
12
|
+
*/
|
|
13
|
+
export declare class ZapierReleaseTriggerMessageSignal extends ZapierSignal {
|
|
14
|
+
readonly name = "ZapierReleaseTriggerMessageSignal";
|
|
15
|
+
readonly code: "ZAPIER_RELEASE_TRIGGER_MESSAGE_SIGNAL";
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Signal an `onMessage` callback can throw to stop the drain after
|
|
19
|
+
* the current batch — no further leases, no further callbacks. The
|
|
20
|
+
* triggering message gets the same release-or-leave treatment as any
|
|
21
|
+
* thrown error (per `releaseOnError`). Other in-flight messages in
|
|
22
|
+
* the same batch finish normally before the command returns.
|
|
23
|
+
* Already-leased-but-not-yet-started messages are released so
|
|
24
|
+
* they're available for re-lease.
|
|
25
|
+
*/
|
|
26
|
+
export declare class ZapierAbortDrainSignal extends ZapierSignal {
|
|
27
|
+
readonly name = "ZapierAbortDrainSignal";
|
|
28
|
+
readonly code: "ZAPIER_ABORT_DRAIN_SIGNAL";
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Per-message handler. Resolves to ack the message; rejects to
|
|
32
|
+
* release-or-leave per `releaseOnError`. Throw a
|
|
33
|
+
* `ZapierReleaseTriggerMessageSignal` for explicit release; throw a
|
|
34
|
+
* `ZapierAbortDrainSignal` to stop the drain after the current
|
|
35
|
+
* batch.
|
|
36
|
+
*/
|
|
37
|
+
export type DrainTriggerInboxCallback = (message: LeasedTriggerMessageItem) => void | Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Per-message error observer for `continueOnError: true` mode.
|
|
40
|
+
* Called with the failure reason and the message; signals
|
|
41
|
+
* (`ZapierSignal` subclasses) are filtered out — they're
|
|
42
|
+
* control-flow throws, not failures to observe. Synchronous from
|
|
43
|
+
* the loop's perspective; throwing from `onError` is swallowed,
|
|
44
|
+
* since it's an observer not a flow controller.
|
|
45
|
+
*/
|
|
46
|
+
export type DrainTriggerInboxErrorObserver = (error: unknown, message: LeasedTriggerMessageItem) => void | Promise<void>;
|
|
47
|
+
export declare const DrainTriggerInboxSchema: z.ZodObject<{
|
|
48
|
+
inbox: z.ZodString & {
|
|
49
|
+
_def: z.core.$ZodStringDef & import("../../..").PositionalMetadata;
|
|
50
|
+
};
|
|
51
|
+
onMessage: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
52
|
+
concurrency: z.ZodOptional<z.ZodNumber>;
|
|
53
|
+
leaseLimit: z.ZodOptional<z.ZodNumber>;
|
|
54
|
+
leaseSeconds: z.ZodOptional<z.ZodNumber>;
|
|
55
|
+
releaseOnError: z.ZodOptional<z.ZodBoolean>;
|
|
56
|
+
continueOnError: z.ZodOptional<z.ZodBoolean>;
|
|
57
|
+
onError: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
58
|
+
signal: z.ZodOptional<z.ZodCustom<AbortSignal, AbortSignal>>;
|
|
59
|
+
maxMessages: z.ZodOptional<z.ZodNumber>;
|
|
60
|
+
}, z.core.$strip>;
|
|
61
|
+
export declare const WatchTriggerInboxSchema: z.ZodObject<{
|
|
62
|
+
inbox: z.ZodString & {
|
|
63
|
+
_def: z.core.$ZodStringDef & import("../../..").PositionalMetadata;
|
|
64
|
+
};
|
|
65
|
+
onMessage: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
66
|
+
concurrency: z.ZodOptional<z.ZodNumber>;
|
|
67
|
+
leaseLimit: z.ZodOptional<z.ZodNumber>;
|
|
68
|
+
leaseSeconds: z.ZodOptional<z.ZodNumber>;
|
|
69
|
+
releaseOnError: z.ZodOptional<z.ZodBoolean>;
|
|
70
|
+
continueOnError: z.ZodOptional<z.ZodBoolean>;
|
|
71
|
+
onError: z.ZodOptional<z.ZodFunction<z.core.$ZodFunctionArgs, z.core.$ZodFunctionOut>>;
|
|
72
|
+
signal: z.ZodOptional<z.ZodCustom<AbortSignal, AbortSignal>>;
|
|
73
|
+
maxDrainIntervalSeconds: z.ZodOptional<z.ZodNumber>;
|
|
74
|
+
}, z.core.$strip>;
|
|
75
|
+
/**
|
|
76
|
+
* Fields shared by both `drainTriggerInbox` and `watchTriggerInbox`.
|
|
77
|
+
* `onMessage` is required at the type level; runtime validation in
|
|
78
|
+
* the handler covers JS callers who bypass TS.
|
|
79
|
+
*/
|
|
80
|
+
interface TriggerInboxCommandSharedFields {
|
|
81
|
+
inbox: string;
|
|
82
|
+
onMessage: DrainTriggerInboxCallback;
|
|
83
|
+
concurrency?: number;
|
|
84
|
+
leaseLimit?: number;
|
|
85
|
+
leaseSeconds?: number;
|
|
86
|
+
releaseOnError?: boolean;
|
|
87
|
+
continueOnError?: boolean;
|
|
88
|
+
onError?: DrainTriggerInboxErrorObserver;
|
|
89
|
+
signal?: AbortSignal;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Hand-typed options for `drainTriggerInbox`. The Zod schema above is
|
|
93
|
+
* for docs and registry; this type is what the SDK function accepts,
|
|
94
|
+
* with `onMessage` / `onError` typed as proper callbacks instead of
|
|
95
|
+
* opaque `z.function()`.
|
|
96
|
+
*/
|
|
97
|
+
export type DrainTriggerInboxOptions = TriggerInboxCommandSharedFields & {
|
|
98
|
+
maxMessages?: number;
|
|
99
|
+
};
|
|
100
|
+
export type WatchTriggerInboxOptions = TriggerInboxCommandSharedFields & {
|
|
101
|
+
maxDrainIntervalSeconds?: number;
|
|
102
|
+
};
|
|
103
|
+
export type { LeasedTriggerMessageItem };
|
|
104
|
+
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../../src/plugins/triggers/drainTriggerInbox/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD;;;;;;;;GAQG;AACH,qBAAa,iCAAkC,SAAQ,YAAY;IACjE,QAAQ,CAAC,IAAI,uCAAuC;IACpD,QAAQ,CAAC,IAAI,EAAG,uCAAuC,CAAU;CAClE;AAED;;;;;;;;GAQG;AACH,qBAAa,sBAAuB,SAAQ,YAAY;IACtD,QAAQ,CAAC,IAAI,4BAA4B;IACzC,QAAQ,CAAC,IAAI,EAAG,2BAA2B,CAAU;CACtD;AAED;;;;;;GAMG;AACH,MAAM,MAAM,yBAAyB,GAAG,CACtC,OAAO,EAAE,wBAAwB,KAC9B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B;;;;;;;GAOG;AACH,MAAM,MAAM,8BAA8B,GAAG,CAC3C,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,wBAAwB,KAC9B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAoE1B,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;iBAWnC,CAAC;AAEF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;iBAWnC,CAAC;AAEF;;;;GAIG;AACH,UAAU,+BAA+B;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,yBAAyB,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,8BAA8B,CAAC;IACzC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;GAKG;AACH,MAAM,MAAM,wBAAwB,GAAG,+BAA+B,GAAG;IACvE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,+BAA+B,GAAG;IACvE,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC,CAAC;AAEF,YAAY,EAAE,wBAAwB,EAAE,CAAC"}
|