@zapier/zapier-sdk-cli 0.44.1 → 0.46.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.
Files changed (45) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +381 -29
  3. package/bin/zapier-sdk-experimental.mjs +14 -0
  4. package/dist/cli.cjs +608 -38
  5. package/dist/cli.mjs +607 -37
  6. package/dist/experimental.cjs +3519 -0
  7. package/dist/experimental.d.mts +39 -0
  8. package/dist/experimental.d.ts +39 -0
  9. package/dist/experimental.mjs +3483 -0
  10. package/dist/index.cjs +507 -26
  11. package/dist/index.d.mts +3 -514
  12. package/dist/index.d.ts +3 -514
  13. package/dist/index.mjs +505 -24
  14. package/dist/package.json +14 -2
  15. package/dist/sdk-B3nKAZdN.d.mts +516 -0
  16. package/dist/sdk-B3nKAZdN.d.ts +516 -0
  17. package/dist/src/cli.js +26 -2
  18. package/dist/src/experimental.d.ts +33 -0
  19. package/dist/src/experimental.js +83 -0
  20. package/dist/src/generators/ast-generator.d.ts +2 -2
  21. package/dist/src/generators/ast-generator.js +1 -1
  22. package/dist/src/plugins/add/index.d.ts +2 -2
  23. package/dist/src/plugins/bundleCode/index.js +3 -12
  24. package/dist/src/plugins/curl/index.js +2 -2
  25. package/dist/src/plugins/curl/utils.d.ts +11 -1
  26. package/dist/src/plugins/curl/utils.js +14 -5
  27. package/dist/src/plugins/drainTriggerInbox/index.d.ts +46 -0
  28. package/dist/src/plugins/drainTriggerInbox/index.js +178 -0
  29. package/dist/src/plugins/generateAppTypes/index.d.ts +2 -2
  30. package/dist/src/plugins/index.d.ts +2 -0
  31. package/dist/src/plugins/index.js +2 -0
  32. package/dist/src/plugins/mcp/index.d.ts +1 -0
  33. package/dist/src/plugins/mcp/index.js +5 -1
  34. package/dist/src/plugins/watchTriggerInbox/index.d.ts +45 -0
  35. package/dist/src/plugins/watchTriggerInbox/index.js +157 -0
  36. package/dist/src/sdk.js +5 -1
  37. package/dist/src/utils/cli-generator.js +18 -1
  38. package/dist/src/utils/cli-renderer.d.ts +12 -0
  39. package/dist/src/utils/cli-renderer.js +22 -1
  40. package/dist/src/utils/parameter-resolver.d.ts +1 -0
  41. package/dist/src/utils/parameter-resolver.js +81 -10
  42. package/dist/src/utils/triggerDrain.d.ts +144 -0
  43. package/dist/src/utils/triggerDrain.js +351 -0
  44. package/dist/tsconfig.tsbuildinfo +1 -1
  45. package/package.json +16 -4
package/dist/cli.cjs CHANGED
@@ -27,6 +27,7 @@ var isInstalledGlobally = require('is-installed-globally');
27
27
  var child_process = require('child_process');
28
28
  var Handlebars = require('handlebars');
29
29
  var url = require('url');
30
+ var experimental = require('@zapier/zapier-sdk/experimental');
30
31
  var packageJsonLib = require('package-json');
31
32
  var semver = require('semver');
32
33
 
@@ -123,7 +124,7 @@ function formatZodError(error) {
123
124
  }
124
125
  function getLocalResolutionOrder(paramName, resolvers, resolved = /* @__PURE__ */ new Set()) {
125
126
  const resolver = resolvers[paramName];
126
- if (!resolver || resolver.type === "static") {
127
+ if (!resolver || resolver.type === "static" || resolver.type === "constant") {
127
128
  return [paramName];
128
129
  }
129
130
  const order = [];
@@ -206,7 +207,11 @@ var SchemaParameterResolver = class {
206
207
  }
207
208
  return parseResult.data;
208
209
  }
209
- const resolvedParams = { ...providedParams };
210
+ const resolverConstants = this.getResolverConstants(sdk, functionName);
211
+ const resolvedParams = {
212
+ ...resolverConstants,
213
+ ...providedParams
214
+ };
210
215
  const context = {
211
216
  sdk,
212
217
  currentParams: providedParams,
@@ -367,12 +372,22 @@ var SchemaParameterResolver = class {
367
372
  const missingParams = [];
368
373
  for (const param of params) {
369
374
  const resolver = this.getResolver(param.name, context.sdk, functionName);
370
- const autoResolution = resolver?.type === "dynamic" ? await this.tryAutoResolve(resolver, context) : null;
371
- if (autoResolution != null) {
375
+ let autoResolved = null;
376
+ if (resolver?.type === "constant") {
377
+ autoResolved = {
378
+ resolvedValue: resolver.value
379
+ };
380
+ } else if (resolver?.type === "dynamic") {
381
+ autoResolved = await this.tryAutoResolve(
382
+ resolver,
383
+ context
384
+ );
385
+ }
386
+ if (autoResolved != null) {
372
387
  this.setNestedValue(
373
388
  resolvedParams,
374
389
  param.path,
375
- autoResolution.resolvedValue
390
+ autoResolved.resolvedValue
376
391
  );
377
392
  context.resolvedParams = resolvedParams;
378
393
  } else {
@@ -406,7 +421,11 @@ var SchemaParameterResolver = class {
406
421
  const promptLabel = inArrayContext ? `${param.name}[${arrayIndex}]` : param.name;
407
422
  const promptName = inArrayContext ? "value" : param.name;
408
423
  this.debugLog(`Resolving ${promptLabel}${isOptional ? " (optional)" : ""}`);
409
- if (resolver.type === "static") {
424
+ if (resolver.type === "constant") {
425
+ const constantResolver = resolver;
426
+ this.stopSpinner();
427
+ return constantResolver.value;
428
+ } else if (resolver.type === "static") {
410
429
  const staticResolver = resolver;
411
430
  const promptConfig = {
412
431
  type: staticResolver.inputType === "password" ? "password" : "input",
@@ -466,6 +485,7 @@ var SchemaParameterResolver = class {
466
485
  }
467
486
  const LOAD_MORE_SENTINEL = Symbol("LOAD_MORE");
468
487
  const SKIP_SENTINEL = Symbol("SKIP");
488
+ const CUSTOM_VALUE_SENTINEL = Symbol("CUSTOM_VALUE");
469
489
  let newItemsStartIndex = -1;
470
490
  this.stopSpinner();
471
491
  while (true) {
@@ -474,12 +494,27 @@ var SchemaParameterResolver = class {
474
494
  context.resolvedParams
475
495
  );
476
496
  promptConfig.name = promptName;
497
+ const hasSelectableChoice = promptConfig.choices?.some(
498
+ (c) => !c.disabled
499
+ );
500
+ if (!hasSelectableChoice && !hasMore) {
501
+ throw new ZapierCliValidationError(
502
+ `No ${promptLabel} available to select.`
503
+ );
504
+ }
477
505
  if (isOptional && promptConfig.choices) {
478
506
  promptConfig.choices.unshift({
479
507
  name: chalk7__default.default.dim("(Skip)"),
480
508
  value: SKIP_SENTINEL
481
509
  });
482
510
  }
511
+ if (promptConfig.choices && promptConfig.type === "list") {
512
+ const insertAt = isOptional ? 1 : 0;
513
+ promptConfig.choices.splice(insertAt, 0, {
514
+ name: chalk7__default.default.dim("(Enter custom value)"),
515
+ value: CUSTOM_VALUE_SENTINEL
516
+ });
517
+ }
483
518
  if (hasMore && pageIterator && promptConfig.choices) {
484
519
  promptConfig.choices.push({
485
520
  name: chalk7__default.default.dim("(Load more...)"),
@@ -502,7 +537,7 @@ var SchemaParameterResolver = class {
502
537
  }
503
538
  }
504
539
  if (newItemsStartIndex >= 0 && promptConfig.choices) {
505
- const injectedBefore = isOptional ? 1 : 0;
540
+ const injectedBefore = (isOptional ? 1 : 0) + (promptConfig.type === "list" ? 1 : 0);
506
541
  const adjustedIndex = newItemsStartIndex + injectedBefore;
507
542
  if (promptConfig.choices[adjustedIndex]) {
508
543
  promptConfig.default = promptConfig.choices[adjustedIndex].value;
@@ -514,6 +549,20 @@ var SchemaParameterResolver = class {
514
549
  if (selected === SKIP_SENTINEL) {
515
550
  return void 0;
516
551
  }
552
+ if (selected === CUSTOM_VALUE_SENTINEL) {
553
+ const customAnswer = await inquirer__default.default.prompt([
554
+ {
555
+ type: "input",
556
+ name: promptName,
557
+ message: `Enter ${promptLabel}${isOptional ? " (optional)" : ""}:`
558
+ }
559
+ ]);
560
+ const value = customAnswer[promptName];
561
+ if (isOptional && (value === void 0 || value === "")) {
562
+ return void 0;
563
+ }
564
+ return value;
565
+ }
517
566
  const wantsMore = Array.isArray(selected) ? selected.includes(LOAD_MORE_SENTINEL) : selected === LOAD_MORE_SENTINEL;
518
567
  if (wantsMore && pageIterator) {
519
568
  if (Array.isArray(selected)) {
@@ -844,7 +893,7 @@ Optional fields${pathContext}:`));
844
893
  cursor ? `Fetching more choices for ${fieldMeta.title}` : `Fetching choices for ${fieldMeta.title}`
845
894
  );
846
895
  this.startSpinner();
847
- const page = await context.sdk.listInputFieldChoices({
896
+ const page = await context.sdk.listActionInputFieldChoices({
848
897
  app: context.resolvedParams.app,
849
898
  action: context.resolvedParams.action,
850
899
  actionType: context.resolvedParams.actionType,
@@ -1081,6 +1130,23 @@ Optional fields${pathContext}:`));
1081
1130
  );
1082
1131
  return functionInfo?.resolvers || {};
1083
1132
  }
1133
+ getResolverConstants(sdk, functionName) {
1134
+ if (!functionName || typeof sdk.getRegistry !== "function") {
1135
+ return {};
1136
+ }
1137
+ const registry = sdk.getRegistry();
1138
+ const functionInfo = registry.functions.find(
1139
+ (f) => f.name === functionName
1140
+ );
1141
+ const resolvers = functionInfo?.resolvers ?? {};
1142
+ const constants = {};
1143
+ for (const [key, resolver] of Object.entries(resolvers)) {
1144
+ if (resolver && typeof resolver === "object" && resolver.type === "constant") {
1145
+ constants[key] = resolver.value;
1146
+ }
1147
+ }
1148
+ return constants;
1149
+ }
1084
1150
  };
1085
1151
 
1086
1152
  // src/utils/cli-options.ts
@@ -1113,7 +1179,7 @@ var SHARED_COMMAND_CLI_OPTIONS = [
1113
1179
 
1114
1180
  // package.json
1115
1181
  var package_default = {
1116
- version: "0.44.1"};
1182
+ version: "0.46.0"};
1117
1183
 
1118
1184
  // src/telemetry/builders.ts
1119
1185
  function createCliBaseEvent(context = {}) {
@@ -1324,8 +1390,18 @@ async function unwrapHttpResponse(response) {
1324
1390
  );
1325
1391
  }
1326
1392
  }
1393
+ function jsonReplacer(_key, value) {
1394
+ if (value instanceof Error) {
1395
+ return {
1396
+ name: value.name,
1397
+ message: value.message,
1398
+ ...value.stack ? { stack: value.stack } : {}
1399
+ };
1400
+ }
1401
+ return value;
1402
+ }
1327
1403
  function outputJson(envelope) {
1328
- console.log(JSON.stringify(envelope, null, 2));
1404
+ console.log(JSON.stringify(envelope, jsonReplacer, 2));
1329
1405
  }
1330
1406
  function createJsonRenderer() {
1331
1407
  return {
@@ -1726,6 +1802,10 @@ function analyzeZodField(name, schema, functionInfo) {
1726
1802
  break;
1727
1803
  }
1728
1804
  }
1805
+ const baseSchemaDef = baseSchema._zod?.def;
1806
+ if (baseSchema instanceof zod.z.ZodFunction || baseSchemaDef?.type === "custom") {
1807
+ return null;
1808
+ }
1729
1809
  let paramType = "string";
1730
1810
  let elementType;
1731
1811
  let choices;
@@ -1920,7 +2000,8 @@ function createCommandConfig(cliCommandName, functionInfo, sdk) {
1920
2000
  }
1921
2001
  }
1922
2002
  }
1923
- const description = functionInfo.description || schema?.description || `${cliCommandName} command`;
2003
+ const baseDescription = functionInfo.description || schema?.description || `${cliCommandName} command`;
2004
+ const description = functionInfo.experimental ? `${baseDescription} (experimental)` : baseDescription;
1924
2005
  const handler = async (...args) => {
1925
2006
  const startTime = Date.now();
1926
2007
  let success = true;
@@ -3156,7 +3237,8 @@ var mcpPlugin = zapierSdk.definePlugin(
3156
3237
  await zapierSdkMcp.startMcpServer({
3157
3238
  ...options,
3158
3239
  debug: sdk2.context.options?.debug,
3159
- extensions: sdk2.context.extensions
3240
+ extensions: sdk2.context.extensions,
3241
+ experimental: sdk2.context.experimental
3160
3242
  });
3161
3243
  }
3162
3244
  })
@@ -3179,15 +3261,6 @@ var bundleCodePlugin = zapierSdk.definePlugin(
3179
3261
  handler: async ({ options }) => bundleCode(options)
3180
3262
  })
3181
3263
  );
3182
- var ZapierBundleError = class extends Error {
3183
- constructor(message, details, originalError) {
3184
- super(message);
3185
- this.code = "ZAPIER_BUNDLE_ERROR";
3186
- this.name = "ZapierBundleError";
3187
- this.details = details;
3188
- this.originalError = originalError;
3189
- }
3190
- };
3191
3264
  async function bundleCode(options) {
3192
3265
  const {
3193
3266
  input,
@@ -3215,14 +3288,14 @@ async function bundleCode(options) {
3215
3288
  });
3216
3289
  if (result.errors.length > 0) {
3217
3290
  const errorMessages = result.errors.map((e) => e.text);
3218
- throw new ZapierBundleError(
3291
+ throw new zapierSdk.ZapierBundleError(
3219
3292
  `Bundle failed: ${errorMessages.join(", ")}`,
3220
- errorMessages
3293
+ { buildErrors: errorMessages }
3221
3294
  );
3222
3295
  }
3223
3296
  const bundledCode = result.outputFiles?.[0]?.text;
3224
3297
  if (!bundledCode) {
3225
- throw new ZapierBundleError("No output generated");
3298
+ throw new zapierSdk.ZapierBundleError("No output generated");
3226
3299
  }
3227
3300
  let finalOutput = bundledCode;
3228
3301
  if (returnString) {
@@ -3234,13 +3307,12 @@ async function bundleCode(options) {
3234
3307
  }
3235
3308
  return finalOutput;
3236
3309
  } catch (error) {
3237
- if (error instanceof ZapierBundleError) {
3310
+ if (error instanceof zapierSdk.ZapierBundleError) {
3238
3311
  throw error;
3239
3312
  }
3240
- throw new ZapierBundleError(
3313
+ throw new zapierSdk.ZapierBundleError(
3241
3314
  `Bundle failed: ${error instanceof Error ? error.message : "Unknown error"}`,
3242
- void 0,
3243
- error instanceof Error ? error : void 0
3315
+ { cause: error instanceof Error ? error : void 0 }
3244
3316
  );
3245
3317
  }
3246
3318
  }
@@ -3415,7 +3487,7 @@ var AstTypeGenerator = class {
3415
3487
  const actions = actionsResult.data;
3416
3488
  const actionsWithFields = [];
3417
3489
  const inputFieldsTasks = actions.map(
3418
- (action) => () => sdk.listInputFields({
3490
+ (action) => () => sdk.listActionInputFields({
3419
3491
  appKey: app.implementation_id,
3420
3492
  actionKey: action.key,
3421
3493
  actionType: action.action_type,
@@ -4292,11 +4364,12 @@ var CurlSchema = zod.z.object({
4292
4364
  /** @deprecated Use `connection` instead. */
4293
4365
  connectionId: zod.z.union([zod.z.string(), zod.z.number()]).optional().meta({ deprecated: true })
4294
4366
  }).describe("Make HTTP requests through Zapier Relay with curl-like options");
4295
- var CurlExitError = class extends Error {
4367
+ var ZapierCurlExitError = class extends zapierSdk.ZapierError {
4296
4368
  constructor(message, exitCode) {
4297
4369
  super(message);
4370
+ this.name = "ZapierCurlExitError";
4371
+ this.code = "ZAPIER_CURL_EXIT_ERROR";
4298
4372
  this.exitCode = exitCode;
4299
- this.name = "CurlExitError";
4300
4373
  }
4301
4374
  };
4302
4375
  function parseHeaderLine(input) {
@@ -4388,7 +4461,7 @@ async function resolveDataArgBinary(raw) {
4388
4461
  }
4389
4462
  async function buildFormData(formArgs, formStringArgs) {
4390
4463
  if (typeof FormData === "undefined") {
4391
- throw new CurlExitError(
4464
+ throw new ZapierCurlExitError(
4392
4465
  "FormData is not available in this runtime; cannot use --form.",
4393
4466
  2
4394
4467
  );
@@ -4397,7 +4470,7 @@ async function buildFormData(formArgs, formStringArgs) {
4397
4470
  const addField = async (item, forceString) => {
4398
4471
  const idx = item.indexOf("=");
4399
4472
  if (idx === -1) {
4400
- throw new CurlExitError(
4473
+ throw new ZapierCurlExitError(
4401
4474
  `Invalid form field: '${item}'. Expected 'name=value' or 'name=@file'.`,
4402
4475
  2
4403
4476
  );
@@ -4405,7 +4478,7 @@ async function buildFormData(formArgs, formStringArgs) {
4405
4478
  const name = item.slice(0, idx);
4406
4479
  const value = item.slice(idx + 1);
4407
4480
  if (!name) {
4408
- throw new CurlExitError(
4481
+ throw new ZapierCurlExitError(
4409
4482
  `Invalid form field: '${item}'. Field name cannot be empty.`,
4410
4483
  2
4411
4484
  );
@@ -4642,7 +4715,7 @@ ${Array.from(
4642
4715
  `
4643
4716
  );
4644
4717
  }
4645
- throw new CurlExitError("HTTP request failed", 22);
4718
+ throw new ZapierCurlExitError("HTTP request failed", 22);
4646
4719
  }
4647
4720
  return void 0;
4648
4721
  }
@@ -5188,11 +5261,481 @@ var initPlugin = zapierSdk.definePlugin(
5188
5261
  }
5189
5262
  })
5190
5263
  );
5264
+ var CliSkipLeaseExpireError = class extends Error {
5265
+ constructor() {
5266
+ super("user skipped (let lease expire)");
5267
+ this.name = "CliSkipLeaseExpireError";
5268
+ }
5269
+ };
5270
+ function createInteractiveCallback() {
5271
+ let messageNumber = 0;
5272
+ return async (message) => {
5273
+ messageNumber++;
5274
+ const attrs = message.message_attributes;
5275
+ console.log(
5276
+ `
5277
+ ${chalk7__default.default.bold(`Message #${messageNumber}`)} ${chalk7__default.default.dim(message.id)} ${chalk7__default.default.dim(`(lease #${attrs.lease_count})`)}`
5278
+ );
5279
+ if (attrs.error_message) {
5280
+ console.log(chalk7__default.default.yellow(` upstream error: ${attrs.error_message}`));
5281
+ }
5282
+ if (attrs.possible_duplicate_data) {
5283
+ console.log(chalk7__default.default.yellow(" possible duplicate data"));
5284
+ }
5285
+ while (true) {
5286
+ let action;
5287
+ try {
5288
+ const answer = await inquirer__default.default.prompt([
5289
+ {
5290
+ type: "list",
5291
+ name: "action",
5292
+ message: "Action?",
5293
+ choices: [
5294
+ { name: "Ack (remove from inbox)", value: "ack" },
5295
+ {
5296
+ name: "Skip (release after draining)",
5297
+ value: "skip-release"
5298
+ },
5299
+ { name: "Skip (let lease expire)", value: "skip-expire" },
5300
+ { name: "View payload", value: "view" },
5301
+ { name: "Quit", value: "quit" }
5302
+ ]
5303
+ }
5304
+ ]);
5305
+ action = answer.action;
5306
+ } catch (error) {
5307
+ if (error instanceof Error && error.name === "ExitPromptError") {
5308
+ throw new zapierSdk.ZapierAbortDrainSignal("user pressed Ctrl-C");
5309
+ }
5310
+ throw error;
5311
+ }
5312
+ if (action === "view") {
5313
+ console.log(chalk7__default.default.dim(JSON.stringify(message.payload, null, 2)));
5314
+ continue;
5315
+ }
5316
+ if (action === "ack") {
5317
+ return;
5318
+ }
5319
+ if (action === "skip-release") {
5320
+ throw new zapierSdk.ZapierReleaseTriggerMessageSignal("user skipped (release)");
5321
+ }
5322
+ if (action === "skip-expire") {
5323
+ throw new CliSkipLeaseExpireError();
5324
+ }
5325
+ if (action === "quit") {
5326
+ throw new zapierSdk.ZapierAbortDrainSignal("user requested quit");
5327
+ }
5328
+ }
5329
+ };
5330
+ }
5331
+ function createNdjsonCallback() {
5332
+ return (message) => new Promise((resolve4, reject) => {
5333
+ process.stdout.write(JSON.stringify(message) + "\n", (err) => {
5334
+ if (err) reject(err);
5335
+ else resolve4();
5336
+ });
5337
+ });
5338
+ }
5339
+ function runSubprocess(options) {
5340
+ const { command, args, shell, label, message, signal } = options;
5341
+ return new Promise((resolve4, reject) => {
5342
+ const child = child_process.spawn(command, args, {
5343
+ shell,
5344
+ stdio: ["pipe", "inherit", "inherit"]
5345
+ });
5346
+ let abortListener;
5347
+ if (signal) {
5348
+ if (signal.aborted) {
5349
+ child.kill();
5350
+ } else {
5351
+ abortListener = () => {
5352
+ child.kill();
5353
+ };
5354
+ signal.addEventListener("abort", abortListener, { once: true });
5355
+ }
5356
+ }
5357
+ child.on("error", (err) => {
5358
+ if (signal && abortListener) {
5359
+ signal.removeEventListener("abort", abortListener);
5360
+ }
5361
+ reject(err);
5362
+ });
5363
+ child.on("close", (code) => {
5364
+ if (signal && abortListener) {
5365
+ signal.removeEventListener("abort", abortListener);
5366
+ }
5367
+ if (signal?.aborted) {
5368
+ reject(new zapierSdk.ZapierAbortDrainSignal(`${label} aborted`));
5369
+ return;
5370
+ }
5371
+ if (code === 0) resolve4();
5372
+ else
5373
+ reject(
5374
+ new Error(
5375
+ `${label} exited with code ${code} for message ${message.id}`
5376
+ )
5377
+ );
5378
+ });
5379
+ child.stdin.on("error", (err) => {
5380
+ if (err.code !== "EPIPE") reject(err);
5381
+ });
5382
+ child.stdin.end(JSON.stringify(message) + "\n");
5383
+ });
5384
+ }
5385
+ function runShellCommand(command, message, signal) {
5386
+ return runSubprocess({
5387
+ command,
5388
+ args: [],
5389
+ shell: true,
5390
+ label: "exec-shell",
5391
+ message,
5392
+ signal
5393
+ });
5394
+ }
5395
+ function runExecCommand(argv, message, signal) {
5396
+ if (argv.length === 0) {
5397
+ return Promise.reject(
5398
+ new Error("exec requires at least one element (the binary)")
5399
+ );
5400
+ }
5401
+ const [command, ...args] = argv;
5402
+ return runSubprocess({
5403
+ command,
5404
+ args,
5405
+ shell: false,
5406
+ label: "exec",
5407
+ message,
5408
+ signal
5409
+ });
5410
+ }
5411
+ function describeReason(reason) {
5412
+ return reason instanceof Error ? reason.message : String(reason);
5413
+ }
5414
+ function printDrainError(reason, message) {
5415
+ console.error(
5416
+ chalk7__default.default.red(`Error processing ${message.id}: ${describeReason(reason)}`)
5417
+ );
5418
+ }
5419
+ function printDrainSummary(counts) {
5420
+ const skipped = counts.skipped ?? 0;
5421
+ const total = counts.fulfilled + counts.rejected + skipped;
5422
+ const parts = [`${counts.fulfilled} fulfilled`];
5423
+ if (skipped > 0) parts.push(`${skipped} skipped`);
5424
+ parts.push(`${counts.rejected} rejected`);
5425
+ console.log(
5426
+ chalk7__default.default.dim(
5427
+ `
5428
+ Processed ${total} message${total === 1 ? "" : "s"} (${parts.join(", ")}).`
5429
+ )
5430
+ );
5431
+ }
5432
+ function warnInteractiveContinueOnErrorOverride() {
5433
+ console.warn(
5434
+ chalk7__default.default.yellow(
5435
+ 'Note: continueOnError=false is overridden to true in interactive mode (the "Skip (let lease expire)" choice would otherwise terminate the drain).'
5436
+ )
5437
+ );
5438
+ }
5439
+ function requireInteractiveTty(commandName) {
5440
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
5441
+ throw new ZapierCliValidationError(
5442
+ `${commandName} needs an interactive terminal by default. Pass --exec '<bin>' (with optional \`-- args...\`) or --exec-shell '<cmd>' to run a script per message, or --json for non-interactive output.`
5443
+ );
5444
+ }
5445
+ }
5446
+ function rejectExecJsonMutex(opts) {
5447
+ const picked = [
5448
+ opts.exec ? "--exec" : null,
5449
+ opts.execShell ? "--exec-shell" : null,
5450
+ opts.json ? "--json" : null
5451
+ ].filter((x) => x !== null);
5452
+ if (picked.length > 1) {
5453
+ throw new ZapierCliValidationError(
5454
+ `${picked.join(", ")} are mutually exclusive. Pick one.`
5455
+ );
5456
+ }
5457
+ }
5458
+ function getPostDashArgs(argv = process.argv) {
5459
+ const idx = argv.indexOf("--");
5460
+ if (idx === -1) return [];
5461
+ return argv.slice(idx + 1);
5462
+ }
5463
+ function combineSignals(a, b) {
5464
+ if (!a) {
5465
+ return { signal: b, dispose: () => void 0 };
5466
+ }
5467
+ const controller = new AbortController();
5468
+ const onAbort = () => controller.abort();
5469
+ if (a.aborted || b.aborted) controller.abort();
5470
+ else {
5471
+ a.addEventListener("abort", onAbort, { once: true });
5472
+ b.addEventListener("abort", onAbort, { once: true });
5473
+ }
5474
+ return {
5475
+ signal: controller.signal,
5476
+ dispose: () => {
5477
+ a.removeEventListener("abort", onAbort);
5478
+ b.removeEventListener("abort", onAbort);
5479
+ }
5480
+ };
5481
+ }
5482
+
5483
+ // src/plugins/drainTriggerInbox/index.ts
5484
+ var JsonProperty = zod.z.boolean().optional().describe(
5485
+ "Format the drained result as a JSON object on stdout: { data, errors }. Use for scripts or piping. Mutually exclusive with --exec / --exec-shell and the interactive default."
5486
+ );
5487
+ var ExecCliProperty = zod.z.string().optional().describe(
5488
+ "Run a binary per message with no shell interpretation. Message JSON is piped to stdin; exit code 0 acks, non-zero records the error per the same rules as a thrown handler. Pass extra argv after `--` (e.g. `--exec ./handler -- --verbose`). Mutually exclusive with --exec-shell and --json."
5489
+ );
5490
+ var ExecShellCliProperty = zod.z.string().optional().describe(
5491
+ "Run a shell command per message. Message JSON is piped to the subprocess on stdin; exit code 0 acks, non-zero records the error per the same rules as a thrown handler. Interpreted by the platform's default shell (sh on POSIX, cmd.exe on Windows). Mutually exclusive with --exec and --json."
5492
+ );
5493
+ var drainTriggerInboxCliPlugin = zapierSdk.definePlugin(
5494
+ (sdk) => {
5495
+ const original = sdk.drainTriggerInbox;
5496
+ const existingMeta = sdk.context.meta.drainTriggerInbox;
5497
+ const baseInputSchema = existingMeta.inputSchema;
5498
+ const extendedInputSchema = baseInputSchema ? baseInputSchema.extend({
5499
+ exec: ExecCliProperty,
5500
+ execShell: ExecShellCliProperty,
5501
+ json: JsonProperty
5502
+ }) : zod.z.object({
5503
+ exec: ExecCliProperty,
5504
+ execShell: ExecShellCliProperty,
5505
+ json: JsonProperty
5506
+ });
5507
+ return {
5508
+ drainTriggerInbox: async (options) => {
5509
+ const { json, exec, execShell, ...sdkArgs } = options;
5510
+ rejectExecJsonMutex({ exec, execShell, json });
5511
+ if (!exec && !execShell && !json) {
5512
+ requireInteractiveTty("drain-trigger-inbox");
5513
+ }
5514
+ const sigintController = new AbortController();
5515
+ const onSigint = () => sigintController.abort();
5516
+ process.on("SIGINT", onSigint);
5517
+ const combined = combineSignals(
5518
+ sdkArgs.signal,
5519
+ sigintController.signal
5520
+ );
5521
+ let fulfilled = 0;
5522
+ let rejected = 0;
5523
+ let skipped = 0;
5524
+ const liveOnError = (reason, message) => {
5525
+ rejected++;
5526
+ printDrainError(reason, message);
5527
+ };
5528
+ try {
5529
+ if (exec) {
5530
+ const execArgv = [exec, ...getPostDashArgs()];
5531
+ await original({
5532
+ ...sdkArgs,
5533
+ signal: combined.signal,
5534
+ onMessage: async (message) => {
5535
+ await runExecCommand(execArgv, message, combined.signal);
5536
+ fulfilled++;
5537
+ },
5538
+ onError: liveOnError
5539
+ });
5540
+ return;
5541
+ }
5542
+ if (execShell) {
5543
+ await original({
5544
+ ...sdkArgs,
5545
+ signal: combined.signal,
5546
+ onMessage: async (message) => {
5547
+ await runShellCommand(execShell, message, combined.signal);
5548
+ fulfilled++;
5549
+ },
5550
+ onError: liveOnError
5551
+ });
5552
+ return;
5553
+ }
5554
+ if (json) {
5555
+ const data = [];
5556
+ const errors = [];
5557
+ await original({
5558
+ ...sdkArgs,
5559
+ signal: combined.signal,
5560
+ continueOnError: true,
5561
+ onMessage: (message) => {
5562
+ data.push(message);
5563
+ },
5564
+ onError: (reason, message) => {
5565
+ errors.push({ reason, message });
5566
+ }
5567
+ });
5568
+ process.stdout.write(
5569
+ JSON.stringify({ data, errors }, jsonReplacer, 2) + "\n"
5570
+ );
5571
+ return;
5572
+ }
5573
+ if (sdkArgs.continueOnError === false) {
5574
+ warnInteractiveContinueOnErrorOverride();
5575
+ }
5576
+ const interactive = createInteractiveCallback();
5577
+ await original({
5578
+ ...sdkArgs,
5579
+ signal: combined.signal,
5580
+ concurrency: 1,
5581
+ continueOnError: true,
5582
+ onMessage: async (message) => {
5583
+ try {
5584
+ await interactive(message);
5585
+ fulfilled++;
5586
+ } catch (err) {
5587
+ if (err instanceof zapierSdk.ZapierReleaseTriggerMessageSignal || err instanceof CliSkipLeaseExpireError) {
5588
+ skipped++;
5589
+ }
5590
+ throw err;
5591
+ }
5592
+ }
5593
+ });
5594
+ } finally {
5595
+ process.off("SIGINT", onSigint);
5596
+ combined.dispose();
5597
+ if (!json) {
5598
+ printDrainSummary({ fulfilled, rejected, skipped });
5599
+ }
5600
+ }
5601
+ },
5602
+ context: {
5603
+ meta: {
5604
+ drainTriggerInbox: {
5605
+ ...existingMeta,
5606
+ inputSchema: extendedInputSchema,
5607
+ packages: void 0
5608
+ }
5609
+ }
5610
+ }
5611
+ };
5612
+ }
5613
+ );
5614
+ var JsonProperty2 = zod.z.boolean().optional().describe(
5615
+ "Stream each message as JSON to stdout (one record per line, NDJSON), acking as each write completes. Use for piping to other tools. Mutually exclusive with --exec / --exec-shell and the interactive default."
5616
+ );
5617
+ var ExecCliProperty2 = zod.z.string().optional().describe(
5618
+ "Run a binary per message with no shell interpretation. Message JSON is piped to stdin; exit code 0 acks, non-zero records the error per the same rules as a thrown handler. Pass extra argv after `--` (e.g. `--exec ./handler -- --verbose`). Mutually exclusive with --exec-shell and --json."
5619
+ );
5620
+ var ExecShellCliProperty2 = zod.z.string().optional().describe(
5621
+ "Run a shell command per message. Message JSON is piped to the subprocess on stdin; exit code 0 acks, non-zero records the error per the same rules as a thrown handler. Interpreted by the platform's default shell (sh on POSIX, cmd.exe on Windows). Mutually exclusive with --exec and --json."
5622
+ );
5623
+ var watchTriggerInboxCliPlugin = zapierSdk.definePlugin(
5624
+ (sdk) => {
5625
+ const original = sdk.watchTriggerInbox;
5626
+ const existingMeta = sdk.context.meta.watchTriggerInbox;
5627
+ const baseInputSchema = existingMeta.inputSchema;
5628
+ const extendedInputSchema = baseInputSchema ? baseInputSchema.extend({
5629
+ exec: ExecCliProperty2,
5630
+ execShell: ExecShellCliProperty2,
5631
+ json: JsonProperty2
5632
+ }) : zod.z.object({
5633
+ exec: ExecCliProperty2,
5634
+ execShell: ExecShellCliProperty2,
5635
+ json: JsonProperty2
5636
+ });
5637
+ return {
5638
+ watchTriggerInbox: async (options) => {
5639
+ const { json, exec, execShell, ...sdkArgs } = options;
5640
+ rejectExecJsonMutex({ exec, execShell, json });
5641
+ if (!exec && !execShell && !json) {
5642
+ requireInteractiveTty("watch-trigger-inbox");
5643
+ }
5644
+ const sigintController = new AbortController();
5645
+ const onSigint = () => sigintController.abort();
5646
+ process.on("SIGINT", onSigint);
5647
+ const combined = combineSignals(
5648
+ sdkArgs.signal,
5649
+ sigintController.signal
5650
+ );
5651
+ let fulfilled = 0;
5652
+ let rejected = 0;
5653
+ let skipped = 0;
5654
+ const liveOnError = (reason, message) => {
5655
+ rejected++;
5656
+ printDrainError(reason, message);
5657
+ };
5658
+ try {
5659
+ if (exec) {
5660
+ const execArgv = [exec, ...getPostDashArgs()];
5661
+ await original({
5662
+ ...sdkArgs,
5663
+ signal: combined.signal,
5664
+ onMessage: async (message) => {
5665
+ await runExecCommand(execArgv, message, combined.signal);
5666
+ fulfilled++;
5667
+ },
5668
+ onError: liveOnError
5669
+ });
5670
+ } else if (execShell) {
5671
+ await original({
5672
+ ...sdkArgs,
5673
+ signal: combined.signal,
5674
+ onMessage: async (message) => {
5675
+ await runShellCommand(execShell, message, combined.signal);
5676
+ fulfilled++;
5677
+ },
5678
+ onError: liveOnError
5679
+ });
5680
+ } else if (json) {
5681
+ const ndjson = createNdjsonCallback();
5682
+ await original({
5683
+ ...sdkArgs,
5684
+ signal: combined.signal,
5685
+ onMessage: async (message) => {
5686
+ await ndjson(message);
5687
+ fulfilled++;
5688
+ },
5689
+ onError: liveOnError
5690
+ });
5691
+ } else {
5692
+ if (sdkArgs.continueOnError === false) {
5693
+ warnInteractiveContinueOnErrorOverride();
5694
+ }
5695
+ const interactive = createInteractiveCallback();
5696
+ await original({
5697
+ ...sdkArgs,
5698
+ signal: combined.signal,
5699
+ concurrency: 1,
5700
+ continueOnError: true,
5701
+ onMessage: async (message) => {
5702
+ try {
5703
+ await interactive(message);
5704
+ fulfilled++;
5705
+ } catch (err) {
5706
+ if (err instanceof zapierSdk.ZapierReleaseTriggerMessageSignal || err instanceof CliSkipLeaseExpireError) {
5707
+ skipped++;
5708
+ }
5709
+ throw err;
5710
+ }
5711
+ }
5712
+ });
5713
+ }
5714
+ } finally {
5715
+ process.off("SIGINT", onSigint);
5716
+ combined.dispose();
5717
+ if (!json) {
5718
+ printDrainSummary({ fulfilled, rejected, skipped });
5719
+ }
5720
+ }
5721
+ },
5722
+ context: {
5723
+ meta: {
5724
+ watchTriggerInbox: {
5725
+ ...existingMeta,
5726
+ inputSchema: extendedInputSchema,
5727
+ packages: void 0
5728
+ }
5729
+ }
5730
+ }
5731
+ };
5732
+ }
5733
+ );
5191
5734
 
5192
5735
  // package.json with { type: 'json' }
5193
5736
  var package_default2 = {
5194
5737
  name: "@zapier/zapier-sdk-cli",
5195
- version: "0.44.1"};
5738
+ version: "0.46.0"};
5196
5739
 
5197
5740
  // src/sdk.ts
5198
5741
  zapierSdk.injectCliLogin(login_exports);
@@ -5217,6 +5760,31 @@ function createZapierCliSdk(options = {}) {
5217
5760
  }
5218
5761
  return chain;
5219
5762
  }
5763
+ experimental.injectCliLogin(login_exports);
5764
+ function createZapierCliSdk2(options = {}) {
5765
+ const { extensions = [], ...sdkOptions } = options;
5766
+ const extensionsContextPlugin = () => ({
5767
+ context: { extensions }
5768
+ });
5769
+ const experimentalContextPlugin = () => ({
5770
+ context: { experimental: true }
5771
+ });
5772
+ let chain = experimental.createZapierSdk({
5773
+ ...sdkOptions,
5774
+ eventEmission: { ...sdkOptions.eventEmission, callContext: "cli" },
5775
+ callerPackage: { name: package_default2.name, version: package_default2.version }
5776
+ }).addPlugin(extensionsContextPlugin).addPlugin(experimentalContextPlugin).addPlugin(generateAppTypesPlugin).addPlugin(buildManifestPlugin).addPlugin(bundleCodePlugin).addPlugin(getLoginConfigPathPlugin).addPlugin(addPlugin).addPlugin(feedbackPlugin).addPlugin(curlPlugin).addPlugin(initPlugin).addPlugin(drainTriggerInboxCliPlugin, { override: true }).addPlugin(watchTriggerInboxCliPlugin, { override: true }).addPlugin(mcpPlugin).addPlugin(loginPlugin).addPlugin(logoutPlugin).addPlugin(cliOverridesPlugin);
5777
+ for (const ext of extensions) {
5778
+ try {
5779
+ chain = chain.addPlugin(ext);
5780
+ } catch (err) {
5781
+ console.warn(
5782
+ `Extension plugin failed to construct: ${err.message}; skipping.`
5783
+ );
5784
+ }
5785
+ }
5786
+ return chain;
5787
+ }
5220
5788
 
5221
5789
  // src/utils/extensions.ts
5222
5790
  var ENV_VAR = "ZAPIER_SDK_EXTENSIONS";
@@ -5429,7 +5997,7 @@ program.name("zapier-sdk").description("CLI for Zapier SDK").version(
5429
5997
  ).option(
5430
5998
  "--max-network-retry-delay-ms <ms>",
5431
5999
  "Max delay in ms to wait for rate limit retry (default: 60000)"
5432
- );
6000
+ ).option("--experimental", "Use the experimental SDK / CLI surface");
5433
6001
  var booleanFlags = [];
5434
6002
  for (const [key, fieldSchema] of Object.entries(
5435
6003
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -5494,11 +6062,13 @@ for (const { camelName, kebabFlag } of booleanFlags) {
5494
6062
  flagOverrides[camelName] = true;
5495
6063
  }
5496
6064
  }
6065
+ var useExperimental = process.argv.includes("--experimental") || process.env.ZAPIER_EXPERIMENTAL === "1" || process.env.ZAPIER_EXPERIMENTAL === "true";
6066
+ var createZapierCliSdk3 = useExperimental ? createZapierCliSdk2 : createZapierCliSdk;
5497
6067
  program.exitOverride();
5498
6068
  (async () => {
5499
6069
  let exitCode = 0;
5500
6070
  const extensions = await resolveExtensions();
5501
- const sdk = createZapierCliSdk({
6071
+ const sdk = createZapierCliSdk3({
5502
6072
  debug: isDebugMode,
5503
6073
  credentials,
5504
6074
  baseUrl,