@zapier/zapier-sdk-cli 0.44.0 → 0.45.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 +20 -0
  2. package/README.md +392 -40
  3. package/bin/zapier-sdk-experimental.mjs +14 -0
  4. package/dist/cli.cjs +585 -37
  5. package/dist/cli.mjs +584 -36
  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 +55 -9
  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.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command, CommanderError, Option } from 'commander';
3
3
  import { z } from 'zod';
4
- import { definePlugin, createPluginMethod, buildApplicationLifecycleEvent, OutputPropertySchema, DEFAULT_CONFIG_PATH, ZapierValidationError, ZapierUnknownError, injectCliLogin, BaseSdkOptionsSchema, isCredentialsObject, batch, toSnakeCase, createZapierSdk, ZapierError, isPositional, runWithTelemetryContext, buildCapabilityMessage, formatErrorMessage, getOsInfo, getPlatformVersions, getCiPlatform, isCi, getReleaseId, getCurrentTimestamp, generateEventId } from '@zapier/zapier-sdk';
4
+ import { definePlugin, createPluginMethod, buildApplicationLifecycleEvent, OutputPropertySchema, ZapierBundleError, DEFAULT_CONFIG_PATH, ZapierValidationError, ZapierUnknownError, ZapierReleaseTriggerMessageSignal, injectCliLogin, BaseSdkOptionsSchema, isCredentialsObject, batch, toSnakeCase, ZapierAbortDrainSignal, createZapierSdk as createZapierSdk$1, ZapierError, isPositional, runWithTelemetryContext, buildCapabilityMessage, formatErrorMessage, getOsInfo, getPlatformVersions, getCiPlatform, isCi, getReleaseId, getCurrentTimestamp, generateEventId } from '@zapier/zapier-sdk';
5
5
  import inquirer from 'inquirer';
6
6
  import chalk7 from 'chalk';
7
7
  import ora from 'ora';
@@ -24,9 +24,10 @@ import { buildSync } from 'esbuild';
24
24
  import { mkdir, writeFile, access } from 'fs/promises';
25
25
  import * as ts from 'typescript';
26
26
  import isInstalledGlobally from 'is-installed-globally';
27
- import { execSync } from 'child_process';
27
+ import { execSync, spawn } from 'child_process';
28
28
  import Handlebars from 'handlebars';
29
29
  import { fileURLToPath } from 'url';
30
+ import { injectCliLogin as injectCliLogin$1, createZapierSdk } from '@zapier/zapier-sdk/experimental';
30
31
  import packageJsonLib from 'package-json';
31
32
  import semver from 'semver';
32
33
 
@@ -82,7 +83,7 @@ function formatZodError(error) {
82
83
  }
83
84
  function getLocalResolutionOrder(paramName, resolvers, resolved = /* @__PURE__ */ new Set()) {
84
85
  const resolver = resolvers[paramName];
85
- if (!resolver || resolver.type === "static") {
86
+ if (!resolver || resolver.type === "static" || resolver.type === "constant") {
86
87
  return [paramName];
87
88
  }
88
89
  const order = [];
@@ -165,7 +166,11 @@ var SchemaParameterResolver = class {
165
166
  }
166
167
  return parseResult.data;
167
168
  }
168
- const resolvedParams = { ...providedParams };
169
+ const resolverConstants = this.getResolverConstants(sdk, functionName);
170
+ const resolvedParams = {
171
+ ...resolverConstants,
172
+ ...providedParams
173
+ };
169
174
  const context = {
170
175
  sdk,
171
176
  currentParams: providedParams,
@@ -326,12 +331,22 @@ var SchemaParameterResolver = class {
326
331
  const missingParams = [];
327
332
  for (const param of params) {
328
333
  const resolver = this.getResolver(param.name, context.sdk, functionName);
329
- const autoResolution = resolver?.type === "dynamic" ? await this.tryAutoResolve(resolver, context) : null;
330
- if (autoResolution != null) {
334
+ let autoResolved = null;
335
+ if (resolver?.type === "constant") {
336
+ autoResolved = {
337
+ resolvedValue: resolver.value
338
+ };
339
+ } else if (resolver?.type === "dynamic") {
340
+ autoResolved = await this.tryAutoResolve(
341
+ resolver,
342
+ context
343
+ );
344
+ }
345
+ if (autoResolved != null) {
331
346
  this.setNestedValue(
332
347
  resolvedParams,
333
348
  param.path,
334
- autoResolution.resolvedValue
349
+ autoResolved.resolvedValue
335
350
  );
336
351
  context.resolvedParams = resolvedParams;
337
352
  } else {
@@ -365,7 +380,11 @@ var SchemaParameterResolver = class {
365
380
  const promptLabel = inArrayContext ? `${param.name}[${arrayIndex}]` : param.name;
366
381
  const promptName = inArrayContext ? "value" : param.name;
367
382
  this.debugLog(`Resolving ${promptLabel}${isOptional ? " (optional)" : ""}`);
368
- if (resolver.type === "static") {
383
+ if (resolver.type === "constant") {
384
+ const constantResolver = resolver;
385
+ this.stopSpinner();
386
+ return constantResolver.value;
387
+ } else if (resolver.type === "static") {
369
388
  const staticResolver = resolver;
370
389
  const promptConfig = {
371
390
  type: staticResolver.inputType === "password" ? "password" : "input",
@@ -433,6 +452,14 @@ var SchemaParameterResolver = class {
433
452
  context.resolvedParams
434
453
  );
435
454
  promptConfig.name = promptName;
455
+ const hasSelectableChoice = promptConfig.choices?.some(
456
+ (c) => !c.disabled
457
+ );
458
+ if (!hasSelectableChoice && !hasMore) {
459
+ throw new ZapierCliValidationError(
460
+ `No ${promptLabel} available to select.`
461
+ );
462
+ }
436
463
  if (isOptional && promptConfig.choices) {
437
464
  promptConfig.choices.unshift({
438
465
  name: chalk7.dim("(Skip)"),
@@ -803,7 +830,7 @@ Optional fields${pathContext}:`));
803
830
  cursor ? `Fetching more choices for ${fieldMeta.title}` : `Fetching choices for ${fieldMeta.title}`
804
831
  );
805
832
  this.startSpinner();
806
- const page = await context.sdk.listInputFieldChoices({
833
+ const page = await context.sdk.listActionInputFieldChoices({
807
834
  app: context.resolvedParams.app,
808
835
  action: context.resolvedParams.action,
809
836
  actionType: context.resolvedParams.actionType,
@@ -1040,6 +1067,23 @@ Optional fields${pathContext}:`));
1040
1067
  );
1041
1068
  return functionInfo?.resolvers || {};
1042
1069
  }
1070
+ getResolverConstants(sdk, functionName) {
1071
+ if (!functionName || typeof sdk.getRegistry !== "function") {
1072
+ return {};
1073
+ }
1074
+ const registry = sdk.getRegistry();
1075
+ const functionInfo = registry.functions.find(
1076
+ (f) => f.name === functionName
1077
+ );
1078
+ const resolvers = functionInfo?.resolvers ?? {};
1079
+ const constants = {};
1080
+ for (const [key, resolver] of Object.entries(resolvers)) {
1081
+ if (resolver && typeof resolver === "object" && resolver.type === "constant") {
1082
+ constants[key] = resolver.value;
1083
+ }
1084
+ }
1085
+ return constants;
1086
+ }
1043
1087
  };
1044
1088
 
1045
1089
  // src/utils/cli-options.ts
@@ -1072,7 +1116,7 @@ var SHARED_COMMAND_CLI_OPTIONS = [
1072
1116
 
1073
1117
  // package.json
1074
1118
  var package_default = {
1075
- version: "0.44.0"};
1119
+ version: "0.45.0"};
1076
1120
 
1077
1121
  // src/telemetry/builders.ts
1078
1122
  function createCliBaseEvent(context = {}) {
@@ -1283,8 +1327,18 @@ async function unwrapHttpResponse(response) {
1283
1327
  );
1284
1328
  }
1285
1329
  }
1330
+ function jsonReplacer(_key, value) {
1331
+ if (value instanceof Error) {
1332
+ return {
1333
+ name: value.name,
1334
+ message: value.message,
1335
+ ...value.stack ? { stack: value.stack } : {}
1336
+ };
1337
+ }
1338
+ return value;
1339
+ }
1286
1340
  function outputJson(envelope) {
1287
- console.log(JSON.stringify(envelope, null, 2));
1341
+ console.log(JSON.stringify(envelope, jsonReplacer, 2));
1288
1342
  }
1289
1343
  function createJsonRenderer() {
1290
1344
  return {
@@ -1685,6 +1739,10 @@ function analyzeZodField(name, schema, functionInfo) {
1685
1739
  break;
1686
1740
  }
1687
1741
  }
1742
+ const baseSchemaDef = baseSchema._zod?.def;
1743
+ if (baseSchema instanceof z.ZodFunction || baseSchemaDef?.type === "custom") {
1744
+ return null;
1745
+ }
1688
1746
  let paramType = "string";
1689
1747
  let elementType;
1690
1748
  let choices;
@@ -1879,7 +1937,8 @@ function createCommandConfig(cliCommandName, functionInfo, sdk) {
1879
1937
  }
1880
1938
  }
1881
1939
  }
1882
- const description = functionInfo.description || schema?.description || `${cliCommandName} command`;
1940
+ const baseDescription = functionInfo.description || schema?.description || `${cliCommandName} command`;
1941
+ const description = functionInfo.experimental ? `${baseDescription} (experimental)` : baseDescription;
1883
1942
  const handler = async (...args) => {
1884
1943
  const startTime = Date.now();
1885
1944
  let success = true;
@@ -3115,7 +3174,8 @@ var mcpPlugin = definePlugin(
3115
3174
  await startMcpServer({
3116
3175
  ...options,
3117
3176
  debug: sdk2.context.options?.debug,
3118
- extensions: sdk2.context.extensions
3177
+ extensions: sdk2.context.extensions,
3178
+ experimental: sdk2.context.experimental
3119
3179
  });
3120
3180
  }
3121
3181
  })
@@ -3138,15 +3198,6 @@ var bundleCodePlugin = definePlugin(
3138
3198
  handler: async ({ options }) => bundleCode(options)
3139
3199
  })
3140
3200
  );
3141
- var ZapierBundleError = class extends Error {
3142
- constructor(message, details, originalError) {
3143
- super(message);
3144
- this.code = "ZAPIER_BUNDLE_ERROR";
3145
- this.name = "ZapierBundleError";
3146
- this.details = details;
3147
- this.originalError = originalError;
3148
- }
3149
- };
3150
3201
  async function bundleCode(options) {
3151
3202
  const {
3152
3203
  input,
@@ -3176,7 +3227,7 @@ async function bundleCode(options) {
3176
3227
  const errorMessages = result.errors.map((e) => e.text);
3177
3228
  throw new ZapierBundleError(
3178
3229
  `Bundle failed: ${errorMessages.join(", ")}`,
3179
- errorMessages
3230
+ { buildErrors: errorMessages }
3180
3231
  );
3181
3232
  }
3182
3233
  const bundledCode = result.outputFiles?.[0]?.text;
@@ -3198,8 +3249,7 @@ async function bundleCode(options) {
3198
3249
  }
3199
3250
  throw new ZapierBundleError(
3200
3251
  `Bundle failed: ${error instanceof Error ? error.message : "Unknown error"}`,
3201
- void 0,
3202
- error instanceof Error ? error : void 0
3252
+ { cause: error instanceof Error ? error : void 0 }
3203
3253
  );
3204
3254
  }
3205
3255
  }
@@ -3374,7 +3424,7 @@ var AstTypeGenerator = class {
3374
3424
  const actions = actionsResult.data;
3375
3425
  const actionsWithFields = [];
3376
3426
  const inputFieldsTasks = actions.map(
3377
- (action) => () => sdk.listInputFields({
3427
+ (action) => () => sdk.listActionInputFields({
3378
3428
  appKey: app.implementation_id,
3379
3429
  actionKey: action.key,
3380
3430
  actionType: action.action_type,
@@ -4251,11 +4301,12 @@ var CurlSchema = z.object({
4251
4301
  /** @deprecated Use `connection` instead. */
4252
4302
  connectionId: z.union([z.string(), z.number()]).optional().meta({ deprecated: true })
4253
4303
  }).describe("Make HTTP requests through Zapier Relay with curl-like options");
4254
- var CurlExitError = class extends Error {
4304
+ var ZapierCurlExitError = class extends ZapierError {
4255
4305
  constructor(message, exitCode) {
4256
4306
  super(message);
4307
+ this.name = "ZapierCurlExitError";
4308
+ this.code = "ZAPIER_CURL_EXIT_ERROR";
4257
4309
  this.exitCode = exitCode;
4258
- this.name = "CurlExitError";
4259
4310
  }
4260
4311
  };
4261
4312
  function parseHeaderLine(input) {
@@ -4347,7 +4398,7 @@ async function resolveDataArgBinary(raw) {
4347
4398
  }
4348
4399
  async function buildFormData(formArgs, formStringArgs) {
4349
4400
  if (typeof FormData === "undefined") {
4350
- throw new CurlExitError(
4401
+ throw new ZapierCurlExitError(
4351
4402
  "FormData is not available in this runtime; cannot use --form.",
4352
4403
  2
4353
4404
  );
@@ -4356,7 +4407,7 @@ async function buildFormData(formArgs, formStringArgs) {
4356
4407
  const addField = async (item, forceString) => {
4357
4408
  const idx = item.indexOf("=");
4358
4409
  if (idx === -1) {
4359
- throw new CurlExitError(
4410
+ throw new ZapierCurlExitError(
4360
4411
  `Invalid form field: '${item}'. Expected 'name=value' or 'name=@file'.`,
4361
4412
  2
4362
4413
  );
@@ -4364,7 +4415,7 @@ async function buildFormData(formArgs, formStringArgs) {
4364
4415
  const name = item.slice(0, idx);
4365
4416
  const value = item.slice(idx + 1);
4366
4417
  if (!name) {
4367
- throw new CurlExitError(
4418
+ throw new ZapierCurlExitError(
4368
4419
  `Invalid form field: '${item}'. Field name cannot be empty.`,
4369
4420
  2
4370
4421
  );
@@ -4601,7 +4652,7 @@ ${Array.from(
4601
4652
  `
4602
4653
  );
4603
4654
  }
4604
- throw new CurlExitError("HTTP request failed", 22);
4655
+ throw new ZapierCurlExitError("HTTP request failed", 22);
4605
4656
  }
4606
4657
  return void 0;
4607
4658
  }
@@ -5147,11 +5198,481 @@ var initPlugin = definePlugin(
5147
5198
  }
5148
5199
  })
5149
5200
  );
5201
+ var CliSkipLeaseExpireError = class extends Error {
5202
+ constructor() {
5203
+ super("user skipped (let lease expire)");
5204
+ this.name = "CliSkipLeaseExpireError";
5205
+ }
5206
+ };
5207
+ function createInteractiveCallback() {
5208
+ let messageNumber = 0;
5209
+ return async (message) => {
5210
+ messageNumber++;
5211
+ const attrs = message.message_attributes;
5212
+ console.log(
5213
+ `
5214
+ ${chalk7.bold(`Message #${messageNumber}`)} ${chalk7.dim(message.id)} ${chalk7.dim(`(lease #${attrs.lease_count})`)}`
5215
+ );
5216
+ if (attrs.error_message) {
5217
+ console.log(chalk7.yellow(` upstream error: ${attrs.error_message}`));
5218
+ }
5219
+ if (attrs.possible_duplicate_data) {
5220
+ console.log(chalk7.yellow(" possible duplicate data"));
5221
+ }
5222
+ while (true) {
5223
+ let action;
5224
+ try {
5225
+ const answer = await inquirer.prompt([
5226
+ {
5227
+ type: "list",
5228
+ name: "action",
5229
+ message: "Action?",
5230
+ choices: [
5231
+ { name: "Ack (remove from inbox)", value: "ack" },
5232
+ {
5233
+ name: "Skip (release after draining)",
5234
+ value: "skip-release"
5235
+ },
5236
+ { name: "Skip (let lease expire)", value: "skip-expire" },
5237
+ { name: "View payload", value: "view" },
5238
+ { name: "Quit", value: "quit" }
5239
+ ]
5240
+ }
5241
+ ]);
5242
+ action = answer.action;
5243
+ } catch (error) {
5244
+ if (error instanceof Error && error.name === "ExitPromptError") {
5245
+ throw new ZapierAbortDrainSignal("user pressed Ctrl-C");
5246
+ }
5247
+ throw error;
5248
+ }
5249
+ if (action === "view") {
5250
+ console.log(chalk7.dim(JSON.stringify(message.payload, null, 2)));
5251
+ continue;
5252
+ }
5253
+ if (action === "ack") {
5254
+ return;
5255
+ }
5256
+ if (action === "skip-release") {
5257
+ throw new ZapierReleaseTriggerMessageSignal("user skipped (release)");
5258
+ }
5259
+ if (action === "skip-expire") {
5260
+ throw new CliSkipLeaseExpireError();
5261
+ }
5262
+ if (action === "quit") {
5263
+ throw new ZapierAbortDrainSignal("user requested quit");
5264
+ }
5265
+ }
5266
+ };
5267
+ }
5268
+ function createNdjsonCallback() {
5269
+ return (message) => new Promise((resolve4, reject) => {
5270
+ process.stdout.write(JSON.stringify(message) + "\n", (err) => {
5271
+ if (err) reject(err);
5272
+ else resolve4();
5273
+ });
5274
+ });
5275
+ }
5276
+ function runSubprocess(options) {
5277
+ const { command, args, shell, label, message, signal } = options;
5278
+ return new Promise((resolve4, reject) => {
5279
+ const child = spawn(command, args, {
5280
+ shell,
5281
+ stdio: ["pipe", "inherit", "inherit"]
5282
+ });
5283
+ let abortListener;
5284
+ if (signal) {
5285
+ if (signal.aborted) {
5286
+ child.kill();
5287
+ } else {
5288
+ abortListener = () => {
5289
+ child.kill();
5290
+ };
5291
+ signal.addEventListener("abort", abortListener, { once: true });
5292
+ }
5293
+ }
5294
+ child.on("error", (err) => {
5295
+ if (signal && abortListener) {
5296
+ signal.removeEventListener("abort", abortListener);
5297
+ }
5298
+ reject(err);
5299
+ });
5300
+ child.on("close", (code) => {
5301
+ if (signal && abortListener) {
5302
+ signal.removeEventListener("abort", abortListener);
5303
+ }
5304
+ if (signal?.aborted) {
5305
+ reject(new ZapierAbortDrainSignal(`${label} aborted`));
5306
+ return;
5307
+ }
5308
+ if (code === 0) resolve4();
5309
+ else
5310
+ reject(
5311
+ new Error(
5312
+ `${label} exited with code ${code} for message ${message.id}`
5313
+ )
5314
+ );
5315
+ });
5316
+ child.stdin.on("error", (err) => {
5317
+ if (err.code !== "EPIPE") reject(err);
5318
+ });
5319
+ child.stdin.end(JSON.stringify(message) + "\n");
5320
+ });
5321
+ }
5322
+ function runShellCommand(command, message, signal) {
5323
+ return runSubprocess({
5324
+ command,
5325
+ args: [],
5326
+ shell: true,
5327
+ label: "exec-shell",
5328
+ message,
5329
+ signal
5330
+ });
5331
+ }
5332
+ function runExecCommand(argv, message, signal) {
5333
+ if (argv.length === 0) {
5334
+ return Promise.reject(
5335
+ new Error("exec requires at least one element (the binary)")
5336
+ );
5337
+ }
5338
+ const [command, ...args] = argv;
5339
+ return runSubprocess({
5340
+ command,
5341
+ args,
5342
+ shell: false,
5343
+ label: "exec",
5344
+ message,
5345
+ signal
5346
+ });
5347
+ }
5348
+ function describeReason(reason) {
5349
+ return reason instanceof Error ? reason.message : String(reason);
5350
+ }
5351
+ function printDrainError(reason, message) {
5352
+ console.error(
5353
+ chalk7.red(`Error processing ${message.id}: ${describeReason(reason)}`)
5354
+ );
5355
+ }
5356
+ function printDrainSummary(counts) {
5357
+ const skipped = counts.skipped ?? 0;
5358
+ const total = counts.fulfilled + counts.rejected + skipped;
5359
+ const parts = [`${counts.fulfilled} fulfilled`];
5360
+ if (skipped > 0) parts.push(`${skipped} skipped`);
5361
+ parts.push(`${counts.rejected} rejected`);
5362
+ console.log(
5363
+ chalk7.dim(
5364
+ `
5365
+ Processed ${total} message${total === 1 ? "" : "s"} (${parts.join(", ")}).`
5366
+ )
5367
+ );
5368
+ }
5369
+ function warnInteractiveContinueOnErrorOverride() {
5370
+ console.warn(
5371
+ chalk7.yellow(
5372
+ 'Note: continueOnError=false is overridden to true in interactive mode (the "Skip (let lease expire)" choice would otherwise terminate the drain).'
5373
+ )
5374
+ );
5375
+ }
5376
+ function requireInteractiveTty(commandName) {
5377
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
5378
+ throw new ZapierCliValidationError(
5379
+ `${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.`
5380
+ );
5381
+ }
5382
+ }
5383
+ function rejectExecJsonMutex(opts) {
5384
+ const picked = [
5385
+ opts.exec ? "--exec" : null,
5386
+ opts.execShell ? "--exec-shell" : null,
5387
+ opts.json ? "--json" : null
5388
+ ].filter((x) => x !== null);
5389
+ if (picked.length > 1) {
5390
+ throw new ZapierCliValidationError(
5391
+ `${picked.join(", ")} are mutually exclusive. Pick one.`
5392
+ );
5393
+ }
5394
+ }
5395
+ function getPostDashArgs(argv = process.argv) {
5396
+ const idx = argv.indexOf("--");
5397
+ if (idx === -1) return [];
5398
+ return argv.slice(idx + 1);
5399
+ }
5400
+ function combineSignals(a, b) {
5401
+ if (!a) {
5402
+ return { signal: b, dispose: () => void 0 };
5403
+ }
5404
+ const controller = new AbortController();
5405
+ const onAbort = () => controller.abort();
5406
+ if (a.aborted || b.aborted) controller.abort();
5407
+ else {
5408
+ a.addEventListener("abort", onAbort, { once: true });
5409
+ b.addEventListener("abort", onAbort, { once: true });
5410
+ }
5411
+ return {
5412
+ signal: controller.signal,
5413
+ dispose: () => {
5414
+ a.removeEventListener("abort", onAbort);
5415
+ b.removeEventListener("abort", onAbort);
5416
+ }
5417
+ };
5418
+ }
5419
+
5420
+ // src/plugins/drainTriggerInbox/index.ts
5421
+ var JsonProperty = z.boolean().optional().describe(
5422
+ "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."
5423
+ );
5424
+ var ExecCliProperty = z.string().optional().describe(
5425
+ "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."
5426
+ );
5427
+ var ExecShellCliProperty = z.string().optional().describe(
5428
+ "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."
5429
+ );
5430
+ var drainTriggerInboxCliPlugin = definePlugin(
5431
+ (sdk) => {
5432
+ const original = sdk.drainTriggerInbox;
5433
+ const existingMeta = sdk.context.meta.drainTriggerInbox;
5434
+ const baseInputSchema = existingMeta.inputSchema;
5435
+ const extendedInputSchema = baseInputSchema ? baseInputSchema.extend({
5436
+ exec: ExecCliProperty,
5437
+ execShell: ExecShellCliProperty,
5438
+ json: JsonProperty
5439
+ }) : z.object({
5440
+ exec: ExecCliProperty,
5441
+ execShell: ExecShellCliProperty,
5442
+ json: JsonProperty
5443
+ });
5444
+ return {
5445
+ drainTriggerInbox: async (options) => {
5446
+ const { json, exec, execShell, ...sdkArgs } = options;
5447
+ rejectExecJsonMutex({ exec, execShell, json });
5448
+ if (!exec && !execShell && !json) {
5449
+ requireInteractiveTty("drain-trigger-inbox");
5450
+ }
5451
+ const sigintController = new AbortController();
5452
+ const onSigint = () => sigintController.abort();
5453
+ process.on("SIGINT", onSigint);
5454
+ const combined = combineSignals(
5455
+ sdkArgs.signal,
5456
+ sigintController.signal
5457
+ );
5458
+ let fulfilled = 0;
5459
+ let rejected = 0;
5460
+ let skipped = 0;
5461
+ const liveOnError = (reason, message) => {
5462
+ rejected++;
5463
+ printDrainError(reason, message);
5464
+ };
5465
+ try {
5466
+ if (exec) {
5467
+ const execArgv = [exec, ...getPostDashArgs()];
5468
+ await original({
5469
+ ...sdkArgs,
5470
+ signal: combined.signal,
5471
+ onMessage: async (message) => {
5472
+ await runExecCommand(execArgv, message, combined.signal);
5473
+ fulfilled++;
5474
+ },
5475
+ onError: liveOnError
5476
+ });
5477
+ return;
5478
+ }
5479
+ if (execShell) {
5480
+ await original({
5481
+ ...sdkArgs,
5482
+ signal: combined.signal,
5483
+ onMessage: async (message) => {
5484
+ await runShellCommand(execShell, message, combined.signal);
5485
+ fulfilled++;
5486
+ },
5487
+ onError: liveOnError
5488
+ });
5489
+ return;
5490
+ }
5491
+ if (json) {
5492
+ const data = [];
5493
+ const errors = [];
5494
+ await original({
5495
+ ...sdkArgs,
5496
+ signal: combined.signal,
5497
+ continueOnError: true,
5498
+ onMessage: (message) => {
5499
+ data.push(message);
5500
+ },
5501
+ onError: (reason, message) => {
5502
+ errors.push({ reason, message });
5503
+ }
5504
+ });
5505
+ process.stdout.write(
5506
+ JSON.stringify({ data, errors }, jsonReplacer, 2) + "\n"
5507
+ );
5508
+ return;
5509
+ }
5510
+ if (sdkArgs.continueOnError === false) {
5511
+ warnInteractiveContinueOnErrorOverride();
5512
+ }
5513
+ const interactive = createInteractiveCallback();
5514
+ await original({
5515
+ ...sdkArgs,
5516
+ signal: combined.signal,
5517
+ concurrency: 1,
5518
+ continueOnError: true,
5519
+ onMessage: async (message) => {
5520
+ try {
5521
+ await interactive(message);
5522
+ fulfilled++;
5523
+ } catch (err) {
5524
+ if (err instanceof ZapierReleaseTriggerMessageSignal || err instanceof CliSkipLeaseExpireError) {
5525
+ skipped++;
5526
+ }
5527
+ throw err;
5528
+ }
5529
+ }
5530
+ });
5531
+ } finally {
5532
+ process.off("SIGINT", onSigint);
5533
+ combined.dispose();
5534
+ if (!json) {
5535
+ printDrainSummary({ fulfilled, rejected, skipped });
5536
+ }
5537
+ }
5538
+ },
5539
+ context: {
5540
+ meta: {
5541
+ drainTriggerInbox: {
5542
+ ...existingMeta,
5543
+ inputSchema: extendedInputSchema,
5544
+ packages: void 0
5545
+ }
5546
+ }
5547
+ }
5548
+ };
5549
+ }
5550
+ );
5551
+ var JsonProperty2 = z.boolean().optional().describe(
5552
+ "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."
5553
+ );
5554
+ var ExecCliProperty2 = z.string().optional().describe(
5555
+ "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."
5556
+ );
5557
+ var ExecShellCliProperty2 = z.string().optional().describe(
5558
+ "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."
5559
+ );
5560
+ var watchTriggerInboxCliPlugin = definePlugin(
5561
+ (sdk) => {
5562
+ const original = sdk.watchTriggerInbox;
5563
+ const existingMeta = sdk.context.meta.watchTriggerInbox;
5564
+ const baseInputSchema = existingMeta.inputSchema;
5565
+ const extendedInputSchema = baseInputSchema ? baseInputSchema.extend({
5566
+ exec: ExecCliProperty2,
5567
+ execShell: ExecShellCliProperty2,
5568
+ json: JsonProperty2
5569
+ }) : z.object({
5570
+ exec: ExecCliProperty2,
5571
+ execShell: ExecShellCliProperty2,
5572
+ json: JsonProperty2
5573
+ });
5574
+ return {
5575
+ watchTriggerInbox: async (options) => {
5576
+ const { json, exec, execShell, ...sdkArgs } = options;
5577
+ rejectExecJsonMutex({ exec, execShell, json });
5578
+ if (!exec && !execShell && !json) {
5579
+ requireInteractiveTty("watch-trigger-inbox");
5580
+ }
5581
+ const sigintController = new AbortController();
5582
+ const onSigint = () => sigintController.abort();
5583
+ process.on("SIGINT", onSigint);
5584
+ const combined = combineSignals(
5585
+ sdkArgs.signal,
5586
+ sigintController.signal
5587
+ );
5588
+ let fulfilled = 0;
5589
+ let rejected = 0;
5590
+ let skipped = 0;
5591
+ const liveOnError = (reason, message) => {
5592
+ rejected++;
5593
+ printDrainError(reason, message);
5594
+ };
5595
+ try {
5596
+ if (exec) {
5597
+ const execArgv = [exec, ...getPostDashArgs()];
5598
+ await original({
5599
+ ...sdkArgs,
5600
+ signal: combined.signal,
5601
+ onMessage: async (message) => {
5602
+ await runExecCommand(execArgv, message, combined.signal);
5603
+ fulfilled++;
5604
+ },
5605
+ onError: liveOnError
5606
+ });
5607
+ } else if (execShell) {
5608
+ await original({
5609
+ ...sdkArgs,
5610
+ signal: combined.signal,
5611
+ onMessage: async (message) => {
5612
+ await runShellCommand(execShell, message, combined.signal);
5613
+ fulfilled++;
5614
+ },
5615
+ onError: liveOnError
5616
+ });
5617
+ } else if (json) {
5618
+ const ndjson = createNdjsonCallback();
5619
+ await original({
5620
+ ...sdkArgs,
5621
+ signal: combined.signal,
5622
+ onMessage: async (message) => {
5623
+ await ndjson(message);
5624
+ fulfilled++;
5625
+ },
5626
+ onError: liveOnError
5627
+ });
5628
+ } else {
5629
+ if (sdkArgs.continueOnError === false) {
5630
+ warnInteractiveContinueOnErrorOverride();
5631
+ }
5632
+ const interactive = createInteractiveCallback();
5633
+ await original({
5634
+ ...sdkArgs,
5635
+ signal: combined.signal,
5636
+ concurrency: 1,
5637
+ continueOnError: true,
5638
+ onMessage: async (message) => {
5639
+ try {
5640
+ await interactive(message);
5641
+ fulfilled++;
5642
+ } catch (err) {
5643
+ if (err instanceof ZapierReleaseTriggerMessageSignal || err instanceof CliSkipLeaseExpireError) {
5644
+ skipped++;
5645
+ }
5646
+ throw err;
5647
+ }
5648
+ }
5649
+ });
5650
+ }
5651
+ } finally {
5652
+ process.off("SIGINT", onSigint);
5653
+ combined.dispose();
5654
+ if (!json) {
5655
+ printDrainSummary({ fulfilled, rejected, skipped });
5656
+ }
5657
+ }
5658
+ },
5659
+ context: {
5660
+ meta: {
5661
+ watchTriggerInbox: {
5662
+ ...existingMeta,
5663
+ inputSchema: extendedInputSchema,
5664
+ packages: void 0
5665
+ }
5666
+ }
5667
+ }
5668
+ };
5669
+ }
5670
+ );
5150
5671
 
5151
5672
  // package.json with { type: 'json' }
5152
5673
  var package_default2 = {
5153
5674
  name: "@zapier/zapier-sdk-cli",
5154
- version: "0.44.0"};
5675
+ version: "0.45.0"};
5155
5676
 
5156
5677
  // src/sdk.ts
5157
5678
  injectCliLogin(login_exports);
@@ -5160,7 +5681,7 @@ function createZapierCliSdk(options = {}) {
5160
5681
  const extensionsContextPlugin = () => ({
5161
5682
  context: { extensions }
5162
5683
  });
5163
- let chain = createZapierSdk({
5684
+ let chain = createZapierSdk$1({
5164
5685
  ...sdkOptions,
5165
5686
  eventEmission: { ...sdkOptions.eventEmission, callContext: "cli" },
5166
5687
  callerPackage: { name: package_default2.name, version: package_default2.version }
@@ -5176,6 +5697,31 @@ function createZapierCliSdk(options = {}) {
5176
5697
  }
5177
5698
  return chain;
5178
5699
  }
5700
+ injectCliLogin$1(login_exports);
5701
+ function createZapierCliSdk2(options = {}) {
5702
+ const { extensions = [], ...sdkOptions } = options;
5703
+ const extensionsContextPlugin = () => ({
5704
+ context: { extensions }
5705
+ });
5706
+ const experimentalContextPlugin = () => ({
5707
+ context: { experimental: true }
5708
+ });
5709
+ let chain = createZapierSdk({
5710
+ ...sdkOptions,
5711
+ eventEmission: { ...sdkOptions.eventEmission, callContext: "cli" },
5712
+ callerPackage: { name: package_default2.name, version: package_default2.version }
5713
+ }).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);
5714
+ for (const ext of extensions) {
5715
+ try {
5716
+ chain = chain.addPlugin(ext);
5717
+ } catch (err) {
5718
+ console.warn(
5719
+ `Extension plugin failed to construct: ${err.message}; skipping.`
5720
+ );
5721
+ }
5722
+ }
5723
+ return chain;
5724
+ }
5179
5725
 
5180
5726
  // src/utils/extensions.ts
5181
5727
  var ENV_VAR = "ZAPIER_SDK_EXTENSIONS";
@@ -5388,7 +5934,7 @@ program.name("zapier-sdk").description("CLI for Zapier SDK").version(
5388
5934
  ).option(
5389
5935
  "--max-network-retry-delay-ms <ms>",
5390
5936
  "Max delay in ms to wait for rate limit retry (default: 60000)"
5391
- );
5937
+ ).option("--experimental", "Use the experimental SDK / CLI surface");
5392
5938
  var booleanFlags = [];
5393
5939
  for (const [key, fieldSchema] of Object.entries(
5394
5940
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -5453,11 +5999,13 @@ for (const { camelName, kebabFlag } of booleanFlags) {
5453
5999
  flagOverrides[camelName] = true;
5454
6000
  }
5455
6001
  }
6002
+ var useExperimental = process.argv.includes("--experimental") || process.env.ZAPIER_EXPERIMENTAL === "1" || process.env.ZAPIER_EXPERIMENTAL === "true";
6003
+ var createZapierCliSdk3 = useExperimental ? createZapierCliSdk2 : createZapierCliSdk;
5456
6004
  program.exitOverride();
5457
6005
  (async () => {
5458
6006
  let exitCode = 0;
5459
6007
  const extensions = await resolveExtensions();
5460
- const sdk = createZapierCliSdk({
6008
+ const sdk = createZapierCliSdk3({
5461
6009
  debug: isDebugMode,
5462
6010
  credentials,
5463
6011
  baseUrl,