@zapier/zapier-sdk-cli 0.68.0 → 0.70.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/dist/index.cjs CHANGED
@@ -11,7 +11,7 @@ var zapierSdk = require('@zapier/zapier-sdk');
11
11
  var zod = require('zod');
12
12
  var chalk3 = require('chalk');
13
13
  var os = require('os');
14
- var inquirer = require('inquirer');
14
+ var inquirer3 = require('inquirer');
15
15
  var express = require('express');
16
16
  var promises$1 = require('readline/promises');
17
17
  var open = require('open');
@@ -25,8 +25,14 @@ require('is-installed-globally');
25
25
  var child_process = require('child_process');
26
26
  var Handlebars = require('handlebars');
27
27
  var url = require('url');
28
+ var core = require('@inquirer/core');
29
+ var packageJsonLib = require('package-json');
30
+ var semver = require('semver');
31
+ var crossSpawn = require('cross-spawn');
32
+ var wrapAnsi = require('wrap-ansi');
33
+ var Table = require('cli-table3');
28
34
  var experimental = require('@zapier/zapier-sdk/experimental');
29
- require('wrap-ansi');
35
+ require('commander');
30
36
 
31
37
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
32
38
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -56,13 +62,18 @@ var crypto__default = /*#__PURE__*/_interopDefault(crypto);
56
62
  var path__namespace = /*#__PURE__*/_interopNamespace(path);
57
63
  var lockfile__namespace = /*#__PURE__*/_interopNamespace(lockfile);
58
64
  var chalk3__default = /*#__PURE__*/_interopDefault(chalk3);
59
- var inquirer__default = /*#__PURE__*/_interopDefault(inquirer);
65
+ var inquirer3__default = /*#__PURE__*/_interopDefault(inquirer3);
60
66
  var express__default = /*#__PURE__*/_interopDefault(express);
61
67
  var open__default = /*#__PURE__*/_interopDefault(open);
62
68
  var ora__default = /*#__PURE__*/_interopDefault(ora);
63
69
  var pkceChallenge__default = /*#__PURE__*/_interopDefault(pkceChallenge);
64
70
  var ts__namespace = /*#__PURE__*/_interopNamespace(ts);
65
71
  var Handlebars__default = /*#__PURE__*/_interopDefault(Handlebars);
72
+ var packageJsonLib__default = /*#__PURE__*/_interopDefault(packageJsonLib);
73
+ var semver__default = /*#__PURE__*/_interopDefault(semver);
74
+ var crossSpawn__default = /*#__PURE__*/_interopDefault(crossSpawn);
75
+ var wrapAnsi__default = /*#__PURE__*/_interopDefault(wrapAnsi);
76
+ var Table__default = /*#__PURE__*/_interopDefault(Table);
66
77
 
67
78
  var __defProp = Object.defineProperty;
68
79
  var __export = (target, all) => {
@@ -2001,7 +2012,7 @@ async function promptCredentialsName({
2001
2012
  email,
2002
2013
  promptMessage
2003
2014
  }) {
2004
- const { credentialName } = await inquirer__default.default.prompt([
2015
+ const { credentialName } = await inquirer3__default.default.prompt([
2005
2016
  {
2006
2017
  type: "input",
2007
2018
  name: "credentialName",
@@ -2064,7 +2075,7 @@ async function promptConfirm({
2064
2075
  message,
2065
2076
  defaultValue
2066
2077
  }) {
2067
- const { confirmed } = await inquirer__default.default.prompt([
2078
+ const { confirmed } = await inquirer3__default.default.prompt([
2068
2079
  { type: "confirm", name: "confirmed", message, default: defaultValue }
2069
2080
  ]);
2070
2081
  return confirmed;
@@ -4140,26 +4151,57 @@ var InitSchema = zod.z.object({
4140
4151
  }).describe(
4141
4152
  "Create a new Zapier SDK project in a new directory with starter files"
4142
4153
  );
4154
+ var PACKAGE_MANAGERS = ["npm", "pnpm", "yarn", "bun"];
4155
+ var LOCKFILES = [
4156
+ ["pnpm-lock.yaml", "pnpm"],
4157
+ ["yarn.lock", "yarn"],
4158
+ ["bun.lock", "bun"],
4159
+ ["bun.lockb", "bun"],
4160
+ ["package-lock.json", "npm"]
4161
+ ];
4162
+ function readDeclaredPackageManager(cwd) {
4163
+ try {
4164
+ const manifest = JSON.parse(
4165
+ fs.readFileSync(path.join(cwd, "package.json"), "utf8")
4166
+ );
4167
+ if (typeof manifest !== "object" || manifest === null || !("packageManager" in manifest) || typeof manifest.packageManager !== "string") {
4168
+ return void 0;
4169
+ }
4170
+ const [name] = manifest.packageManager.split("@", 1);
4171
+ return PACKAGE_MANAGERS.find((packageManager) => packageManager === name);
4172
+ } catch {
4173
+ return void 0;
4174
+ }
4175
+ }
4143
4176
  function detectPackageManager(cwd = process.cwd()) {
4144
- const ua = process.env.npm_config_user_agent;
4145
- if (ua) {
4146
- if (ua.includes("yarn")) return { name: "yarn", source: "runtime" };
4147
- if (ua.includes("pnpm")) return { name: "pnpm", source: "runtime" };
4148
- if (ua.includes("bun")) return { name: "bun", source: "runtime" };
4149
- if (ua.includes("npm")) return { name: "npm", source: "runtime" };
4150
- }
4151
- const files = [
4152
- ["pnpm-lock.yaml", "pnpm"],
4153
- ["yarn.lock", "yarn"],
4154
- ["bun.lockb", "bun"],
4155
- ["package-lock.json", "npm"]
4156
- ];
4157
- for (const [file, name] of files) {
4158
- if (fs.existsSync(path.join(cwd, file))) {
4159
- return { name, source: "lockfile" };
4177
+ const lockfileManagers = new Set(
4178
+ LOCKFILES.filter(([file]) => fs.existsSync(path.join(cwd, file))).map(
4179
+ ([, packageManager]) => packageManager
4180
+ )
4181
+ );
4182
+ if (lockfileManagers.size === 1) {
4183
+ return { name: [...lockfileManagers][0], source: "lockfile" };
4184
+ }
4185
+ const declaredPackageManager = readDeclaredPackageManager(cwd);
4186
+ if (declaredPackageManager) {
4187
+ return { name: declaredPackageManager, source: "package-json" };
4188
+ }
4189
+ const userAgent = process.env.npm_config_user_agent;
4190
+ if (userAgent) {
4191
+ if (userAgent.includes("yarn")) {
4192
+ return { name: "yarn", source: "runtime" };
4193
+ }
4194
+ if (userAgent.includes("pnpm")) {
4195
+ return { name: "pnpm", source: "runtime" };
4196
+ }
4197
+ if (userAgent.includes("bun")) {
4198
+ return { name: "bun", source: "runtime" };
4199
+ }
4200
+ if (userAgent.includes("npm")) {
4201
+ return { name: "npm", source: "runtime" };
4160
4202
  }
4161
4203
  }
4162
- return { name: "unknown", source: "fallback" };
4204
+ return { name: "npm", source: "fallback" };
4163
4205
  }
4164
4206
  function getDirentParentPath(entry) {
4165
4207
  const e = entry;
@@ -4207,7 +4249,7 @@ async function promptYesNo({
4207
4249
  nonInteractive
4208
4250
  }) {
4209
4251
  if (nonInteractive) return defaultValue;
4210
- const { answer } = await inquirer__default.default.prompt([
4252
+ const { answer } = await inquirer3__default.default.prompt([
4211
4253
  { type: "confirm", name: "answer", message, default: defaultValue }
4212
4254
  ]);
4213
4255
  return answer;
@@ -4557,17 +4599,16 @@ var initPlugin = zapierSdk.defineMethod({
4557
4599
  const cwd = process.cwd();
4558
4600
  const { projectName, projectDir } = validateInitOptions({ rawName, cwd });
4559
4601
  const displayHooks = createConsoleDisplayHooks();
4560
- const packageManagerInfo = detectPackageManager(cwd);
4561
- if (packageManagerInfo.name === "unknown") {
4602
+ const packageManager = detectPackageManager(cwd);
4603
+ if (packageManager.source === "fallback") {
4562
4604
  displayHooks.onWarn(
4563
4605
  "Could not detect package manager, defaulting to npm."
4564
4606
  );
4565
4607
  }
4566
- const packageManager = packageManagerInfo.name === "unknown" ? "npm" : packageManagerInfo.name;
4567
4608
  const steps = getInitSteps({
4568
4609
  projectDir,
4569
4610
  projectName,
4570
- packageManager,
4611
+ packageManager: packageManager.name,
4571
4612
  displayHooks
4572
4613
  });
4573
4614
  const completedSetupStepIds = [];
@@ -4595,8 +4636,1729 @@ var initPlugin = zapierSdk.defineMethod({
4595
4636
  projectName,
4596
4637
  steps,
4597
4638
  completedSetupStepIds,
4598
- packageManager
4639
+ packageManager: packageManager.name
4640
+ });
4641
+ }
4642
+ });
4643
+ function isSelectable(item) {
4644
+ return !core.Separator.isSeparator(item) && !item.disabled;
4645
+ }
4646
+ function normalizeChoices(choices) {
4647
+ return choices.map((choice) => {
4648
+ if (core.Separator.isSeparator(choice)) return choice;
4649
+ const name = choice.name ?? String(choice.value);
4650
+ return {
4651
+ value: choice.value,
4652
+ name,
4653
+ short: choice.short ?? name,
4654
+ disabled: choice.disabled ?? false
4655
+ };
4656
+ });
4657
+ }
4658
+ var theme = core.makeTheme({
4659
+ icon: { cursor: "\u276F" },
4660
+ style: {
4661
+ disabled: (text) => chalk3__default.default.dim(`- ${text}`),
4662
+ searchTerm: (text) => chalk3__default.default.cyan(text),
4663
+ keysHelpTip: (keys) => keys.map(([key, action]) => `${chalk3__default.default.bold(key)} ${chalk3__default.default.dim(action)}`).join(chalk3__default.default.dim(" \u2022 "))
4664
+ }
4665
+ });
4666
+ var searchSelect = core.createPrompt(
4667
+ (config2, done) => {
4668
+ const { pageSize = 7 } = config2;
4669
+ const [status, setStatus] = core.useState(
4670
+ "loading"
4671
+ );
4672
+ const [searchTerm, setSearchTerm] = core.useState("");
4673
+ const [searchResults, setSearchResults] = core.useState([]);
4674
+ const [searchError, setSearchError] = core.useState();
4675
+ const prefix = core.usePrefix({ status, theme });
4676
+ const bounds = core.useMemo(() => {
4677
+ const first = searchResults.findIndex(isSelectable);
4678
+ let last = -1;
4679
+ for (let i = searchResults.length - 1; i >= 0; i--) {
4680
+ if (isSelectable(searchResults[i])) {
4681
+ last = i;
4682
+ break;
4683
+ }
4684
+ }
4685
+ return { first, last };
4686
+ }, [searchResults]);
4687
+ const defaultActive = core.useMemo(() => {
4688
+ const requested = config2.initialActive;
4689
+ if (searchTerm === "" && requested !== void 0 && requested >= 0 && requested < searchResults.length && isSelectable(searchResults[requested])) {
4690
+ return requested;
4691
+ }
4692
+ return bounds.first;
4693
+ }, [searchResults, searchTerm, bounds.first]);
4694
+ const [active = defaultActive, setActive] = core.useState();
4695
+ core.useEffect(() => {
4696
+ const controller = new AbortController();
4697
+ setStatus("loading");
4698
+ setSearchError(void 0);
4699
+ const fetchResults = async () => {
4700
+ try {
4701
+ const results = await config2.source(searchTerm || void 0);
4702
+ if (!controller.signal.aborted) {
4703
+ setActive(void 0);
4704
+ setSearchError(void 0);
4705
+ setSearchResults(normalizeChoices(results));
4706
+ setStatus("idle");
4707
+ }
4708
+ } catch (error2) {
4709
+ if (!controller.signal.aborted && error2 instanceof Error) {
4710
+ setSearchError(error2.message);
4711
+ }
4712
+ }
4713
+ };
4714
+ void fetchResults();
4715
+ return () => {
4716
+ controller.abort();
4717
+ };
4718
+ }, [searchTerm]);
4719
+ const selectedChoice = searchResults[active];
4720
+ core.useKeypress((key, rl) => {
4721
+ if (core.isEnterKey(key)) {
4722
+ if (selectedChoice && isSelectable(selectedChoice)) {
4723
+ setStatus("done");
4724
+ done(selectedChoice.value);
4725
+ } else {
4726
+ rl.write(searchTerm);
4727
+ }
4728
+ } else if (core.isTabKey(key) && selectedChoice && isSelectable(selectedChoice)) {
4729
+ rl.clearLine(0);
4730
+ rl.write(selectedChoice.name);
4731
+ setSearchTerm(selectedChoice.name);
4732
+ } else if (status !== "loading" && (core.isUpKey(key) || core.isDownKey(key))) {
4733
+ rl.clearLine(0);
4734
+ if (core.isUpKey(key) && active !== bounds.first || core.isDownKey(key) && active !== bounds.last) {
4735
+ const offset = core.isUpKey(key) ? -1 : 1;
4736
+ let next = active;
4737
+ do {
4738
+ next = (next + offset + searchResults.length) % searchResults.length;
4739
+ } while (!isSelectable(searchResults[next]));
4740
+ setActive(next);
4741
+ }
4742
+ } else {
4743
+ setSearchTerm(rl.line);
4744
+ }
4745
+ });
4746
+ const page = core.usePagination({
4747
+ items: searchResults,
4748
+ active,
4749
+ renderItem({ item, isActive }) {
4750
+ if (core.Separator.isSeparator(item)) {
4751
+ return ` ${item.separator}`;
4752
+ }
4753
+ if (item.disabled) {
4754
+ const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
4755
+ return theme.style.disabled(`${item.name} ${disabledLabel}`);
4756
+ }
4757
+ const color = isActive ? theme.style.highlight : (x) => x;
4758
+ const cursor = isActive ? theme.icon.cursor : ` `;
4759
+ return color(`${cursor} ${item.name}`);
4760
+ },
4761
+ pageSize,
4762
+ loop: false
4763
+ });
4764
+ const message = theme.style.message(config2.message, status);
4765
+ if (status === "done" && selectedChoice && isSelectable(selectedChoice)) {
4766
+ return [prefix, message, theme.style.answer(selectedChoice.short)].filter(Boolean).join(" ").trimEnd();
4767
+ }
4768
+ const searchStr = theme.style.searchTerm(searchTerm);
4769
+ const helpTip = theme.style.keysHelpTip([
4770
+ ["\u2191\u2193", "navigate"],
4771
+ ["\u23CE", "select"]
4772
+ ]);
4773
+ let error;
4774
+ if (searchError) {
4775
+ error = theme.style.error(searchError);
4776
+ } else if (searchResults.length === 0 && searchTerm !== "" && status === "idle") {
4777
+ error = theme.style.error("No results found");
4778
+ }
4779
+ const header = [prefix, message, searchStr].filter(Boolean).join(" ").trimEnd();
4780
+ const body = [error ?? page, " ", helpTip].filter(Boolean).join("\n").trimEnd();
4781
+ return [header, body];
4782
+ }
4783
+ );
4784
+
4785
+ // src/utils/controller-answer.ts
4786
+ function offers(question, action) {
4787
+ return question.actions.some((a) => a.action === action);
4788
+ }
4789
+ function isActionRow(value) {
4790
+ return typeof value === "object" && value !== null && "action" in value;
4791
+ }
4792
+ async function promptText({
4793
+ message,
4794
+ password
4795
+ }) {
4796
+ const { value } = await inquirer3__default.default.prompt([
4797
+ {
4798
+ type: password ? "password" : "input",
4799
+ name: "value",
4800
+ message,
4801
+ theme: HIGH_CONTRAST_PROMPT_THEME
4802
+ }
4803
+ ]);
4804
+ return value;
4805
+ }
4806
+ var display = (c) => c.hint ? `${c.label} ${chalk3__default.default.dim(`(${c.hint})`)}` : c.label;
4807
+ var HIGH_CONTRAST_PROMPT_THEME = {
4808
+ style: {
4809
+ answer: (text) => chalk3__default.default.inverse.bold(` ${text} `)
4810
+ }
4811
+ };
4812
+ function buildSelectRows(question, term) {
4813
+ const row = (name, action) => ({
4814
+ name,
4815
+ value: { action }
4816
+ });
4817
+ const t = term.trim().toLowerCase();
4818
+ const matched = t ? question.choices.filter(
4819
+ (c) => `${c.label} ${c.hint ?? ""}`.toLowerCase().includes(t)
4820
+ ) : question.choices;
4821
+ const matchRows = matched.map((c) => ({
4822
+ name: display(c),
4823
+ value: c.value
4824
+ }));
4825
+ const skipRow = offers(question, "skip") ? [row(chalk3__default.default.dim("Skip (optional)"), "skip")] : [];
4826
+ const customRow = offers(question, "custom") ? [row(chalk3__default.default.dim("Enter a value manually\u2026"), "custom")] : [];
4827
+ const committed = !!t || question.search !== void 0;
4828
+ let rows;
4829
+ if (!committed) {
4830
+ rows = [...skipRow, ...customRow, ...matchRows];
4831
+ } else if (matchRows.length > 0) {
4832
+ rows = [...matchRows, ...skipRow, ...customRow];
4833
+ } else {
4834
+ rows = [...customRow, ...skipRow];
4835
+ }
4836
+ if (offers(question, "search"))
4837
+ rows.push(row(chalk3__default.default.cyan("Search again\u2026"), "search"));
4838
+ if (offers(question, "next_page"))
4839
+ rows.push(row(chalk3__default.default.dim("Load more\u2026"), "next_page"));
4840
+ if (offers(question, "retry")) rows.push(row(chalk3__default.default.yellow("Retry"), "retry"));
4841
+ if (offers(question, "cancel")) rows.push(row(chalk3__default.default.dim("Cancel"), "cancel"));
4842
+ for (const note of question.notes ?? [])
4843
+ rows.push({ name: chalk3__default.default.dim(note), value: note, disabled: true });
4844
+ return rows;
4845
+ }
4846
+ function foldPage(acc, question, field) {
4847
+ const page = question.page;
4848
+ if (!page) {
4849
+ return {
4850
+ key: field,
4851
+ pageIndex: 0,
4852
+ choices: question.choices,
4853
+ newStart: 0,
4854
+ checked: []
4855
+ };
4856
+ }
4857
+ const key = `${field}#${page.generation}`;
4858
+ if (acc?.key === key && page.index === acc.pageIndex + 1) {
4859
+ return {
4860
+ key,
4861
+ pageIndex: page.index,
4862
+ choices: [...acc.choices, ...question.choices],
4863
+ newStart: acc.choices.length,
4864
+ checked: acc.checked
4865
+ };
4866
+ }
4867
+ if (acc?.key === key && page.index === acc.pageIndex) {
4868
+ return { ...acc, newStart: 0 };
4869
+ }
4870
+ return {
4871
+ key,
4872
+ pageIndex: page.index,
4873
+ choices: question.choices,
4874
+ newStart: 0,
4875
+ checked: []
4876
+ };
4877
+ }
4878
+ async function answerSelect(question, field, box, failed, mode) {
4879
+ const acc = failed ? void 0 : box.acc = foldPage(box.acc, question, field);
4880
+ const view = acc ? { ...question, choices: acc.choices } : question;
4881
+ const isClosedListPrompt = mode === "closed-list" && !failed && !view.multiple;
4882
+ const booleanValues = view.choices.map(({ value: value2 }) => value2);
4883
+ if (isClosedListPrompt && booleanValues.length === 2 && booleanValues.includes("true") && booleanValues.includes("false")) {
4884
+ const { value: value2 } = await inquirer3__default.default.prompt([
4885
+ {
4886
+ type: "confirm",
4887
+ name: "value",
4888
+ message: view.message,
4889
+ default: booleanValues[0] === "true",
4890
+ theme: HIGH_CONTRAST_PROMPT_THEME
4891
+ }
4892
+ ]);
4893
+ return { type: "choose", value: String(value2) };
4894
+ }
4895
+ if (isClosedListPrompt && view.choices.length > 0 && !offers(view, "search") && !offers(view, "next_page") && !offers(view, "retry")) {
4896
+ const choices = view.choices.map((choice) => ({
4897
+ name: display(choice),
4898
+ value: choice.value
4899
+ }));
4900
+ const { value: value2 } = await inquirer3__default.default.prompt([
4901
+ {
4902
+ type: "list",
4903
+ name: "value",
4904
+ message: view.message,
4905
+ choices,
4906
+ theme: HIGH_CONTRAST_PROMPT_THEME
4907
+ }
4908
+ ]);
4909
+ return { type: "choose", value: value2 };
4910
+ }
4911
+ if (question.multiple && acc) {
4912
+ if (acc.newStart > 0 && process.stdout.isTTY) {
4913
+ process.stdout.write("\x1B[1A\x1B[2K");
4914
+ }
4915
+ const choices = [
4916
+ ...acc.choices.map((c) => ({
4917
+ name: display(c),
4918
+ value: c.value,
4919
+ checked: acc.checked.includes(c.value)
4920
+ })),
4921
+ ...offers(question, "next_page") ? [
4922
+ {
4923
+ name: chalk3__default.default.dim("Load more\u2026"),
4924
+ value: { action: "next_page" }
4925
+ }
4926
+ ] : [],
4927
+ ...(question.notes ?? []).map((note) => ({
4928
+ name: chalk3__default.default.dim(note),
4929
+ value: note,
4930
+ disabled: true
4931
+ }))
4932
+ ];
4933
+ const { values } = await inquirer3__default.default.prompt([
4934
+ {
4935
+ type: "checkbox",
4936
+ name: "values",
4937
+ message: question.message,
4938
+ choices,
4939
+ theme: HIGH_CONTRAST_PROMPT_THEME
4940
+ }
4941
+ ]);
4942
+ const selected = values;
4943
+ const picked = selected.filter((v) => !isActionRow(v));
4944
+ if (selected.some(isActionRow)) {
4945
+ box.acc = { ...acc, checked: picked };
4946
+ return { type: "next_page" };
4947
+ }
4948
+ if (picked.length === 0 && offers(question, "skip")) {
4949
+ return { type: "skip" };
4950
+ }
4951
+ return { type: "choose", value: picked };
4952
+ }
4953
+ if (offers(question, "search") && question.search === void 0) {
4954
+ const optional = offers(question, "skip");
4955
+ const parts = [
4956
+ ...optional ? ["optional"] : [],
4957
+ ...question.placeholder ? [question.placeholder] : []
4958
+ ];
4959
+ const hint = parts.length ? ` (${parts.join(", ")})` : "";
4960
+ while (true) {
4961
+ const term = (await promptText({
4962
+ message: `Enter or search ${field}${hint}:`,
4963
+ password: false
4964
+ })).trim();
4965
+ if (term) return { type: "search", term };
4966
+ if (optional) return { type: "skip" };
4967
+ }
4968
+ }
4969
+ const newStart = acc?.newStart ?? 0;
4970
+ const firstFreshValue = newStart > 0 ? view.choices[newStart]?.value : void 0;
4971
+ const initialActive = firstFreshValue !== void 0 ? buildSelectRows(view, "").findIndex((r) => r.value === firstFreshValue) : -1;
4972
+ const value = await searchSelect(
4973
+ {
4974
+ message: view.message,
4975
+ source: (term) => buildSelectRows(view, term ?? ""),
4976
+ ...initialActive >= 0 ? { initialActive } : {}
4977
+ },
4978
+ { clearPromptOnDone: true }
4979
+ );
4980
+ if (!isActionRow(value)) {
4981
+ const picked = view.choices.find((c) => c.value === value);
4982
+ printAnswered(view.message, picked?.label ?? String(value));
4983
+ return { type: "choose", value };
4984
+ }
4985
+ switch (value.action) {
4986
+ case "search": {
4987
+ const term = await promptText({
4988
+ message: `Search ${field}:`,
4989
+ password: false
4990
+ });
4991
+ return { type: "search", term };
4992
+ }
4993
+ case "custom": {
4994
+ const custom = await promptText({
4995
+ message: `Enter ${field}:`,
4996
+ password: false
4997
+ });
4998
+ return { type: "custom", value: custom };
4999
+ }
5000
+ case "next_page":
5001
+ return { type: "next_page" };
5002
+ case "retry":
5003
+ return { type: "retry" };
5004
+ case "skip":
5005
+ printAnswered(view.message, chalk3__default.default.dim("(skipped)"));
5006
+ return { type: "skip" };
5007
+ case "cancel":
5008
+ return { type: "cancel" };
5009
+ }
5010
+ }
5011
+ function printAnswered(message, label) {
5012
+ console.log(`${chalk3__default.default.green("\u2714")} ${message} ${chalk3__default.default.cyan(label)}`);
5013
+ }
5014
+ async function answerInput(question) {
5015
+ const message = question.placeholder ? question.message.replace(/:?\s*$/, ` (${question.placeholder}):`) : question.message;
5016
+ const value = await promptText({
5017
+ message,
5018
+ password: question.inputType === "password"
5019
+ });
5020
+ if (value === "" && offers(question, "skip")) {
5021
+ return { type: "skip" };
5022
+ }
5023
+ return { type: "custom", value };
5024
+ }
5025
+ async function answerCollection(question) {
5026
+ if (!offers(question, "done")) {
5027
+ return { type: "add" };
5028
+ }
5029
+ if (question.description) console.log(question.description);
5030
+ const { again } = await inquirer3__default.default.prompt([
5031
+ {
5032
+ type: "confirm",
5033
+ name: "again",
5034
+ message: question.message,
5035
+ default: false,
5036
+ theme: HIGH_CONTRAST_PROMPT_THEME
5037
+ }
5038
+ ]);
5039
+ return again ? { type: "add" } : { type: "done" };
5040
+ }
5041
+ function createCliAnswer({
5042
+ mode = "search"
5043
+ } = {}) {
5044
+ const box = {};
5045
+ return async ({ result }) => {
5046
+ try {
5047
+ if (result.error !== void 0) {
5048
+ const message = typeof result.error === "string" ? result.error : result.error.message;
5049
+ console.log(chalk3__default.default.yellow(`! ${message}`));
5050
+ }
5051
+ const question = result.question;
5052
+ const field = question.path.length ? question.path.join(".") : "value";
5053
+ switch (question.type) {
5054
+ case "select":
5055
+ return await answerSelect(
5056
+ question,
5057
+ field,
5058
+ box,
5059
+ result.status === "failed",
5060
+ mode
5061
+ );
5062
+ case "input":
5063
+ return await answerInput(question);
5064
+ case "collection":
5065
+ return await answerCollection(question);
5066
+ }
5067
+ } catch (error) {
5068
+ if (error instanceof Error && error.name === "ExitPromptError") {
5069
+ return { type: "cancel" };
5070
+ }
5071
+ throw error;
5072
+ }
5073
+ };
5074
+ }
5075
+ var ONE_DAY_MILLISECONDS = 24 * 60 * 60 * 1e3;
5076
+ var CACHE_RESET_INTERVAL_MILLISECONDS = (() => {
5077
+ const {
5078
+ ZAPIER_SDK_UPDATE_CHECK_INTERVAL_SECONDS,
5079
+ ZAPIER_SDK_UPDATE_CHECK_INTERVAL_MS
5080
+ } = process.env;
5081
+ let intervalMs;
5082
+ if (ZAPIER_SDK_UPDATE_CHECK_INTERVAL_SECONDS !== void 0) {
5083
+ const seconds = parseInt(ZAPIER_SDK_UPDATE_CHECK_INTERVAL_SECONDS);
5084
+ intervalMs = isNaN(seconds) ? NaN : seconds * 1e3;
5085
+ } else if (ZAPIER_SDK_UPDATE_CHECK_INTERVAL_MS !== void 0) {
5086
+ intervalMs = parseInt(ZAPIER_SDK_UPDATE_CHECK_INTERVAL_MS);
5087
+ } else {
5088
+ intervalMs = ONE_DAY_MILLISECONDS;
5089
+ }
5090
+ if (isNaN(intervalMs) || intervalMs < 0) {
5091
+ return -1;
5092
+ }
5093
+ return intervalMs;
5094
+ })();
5095
+ function getVersionCache() {
5096
+ try {
5097
+ const cache = getConfig().get("version_cache");
5098
+ const now = Date.now();
5099
+ if (!cache || !cache.last_reset_timestamp || now - cache.last_reset_timestamp >= CACHE_RESET_INTERVAL_MILLISECONDS) {
5100
+ const newCache = {
5101
+ last_reset_timestamp: now,
5102
+ packages: {}
5103
+ };
5104
+ getConfig().set("version_cache", newCache);
5105
+ return newCache;
5106
+ }
5107
+ return cache;
5108
+ } catch (error) {
5109
+ log_default.debug(`Failed to read version cache: ${error}`);
5110
+ return {
5111
+ last_reset_timestamp: Date.now(),
5112
+ packages: {}
5113
+ };
5114
+ }
5115
+ }
5116
+ function setCachedPackageInfo(packageName, version, info) {
5117
+ try {
5118
+ const cache = getVersionCache();
5119
+ if (!cache.packages[packageName]) {
5120
+ cache.packages[packageName] = {};
5121
+ }
5122
+ cache.packages[packageName][version] = info;
5123
+ getConfig().set("version_cache", cache);
5124
+ } catch (error) {
5125
+ log_default.debug(`Failed to cache package info: ${error}`);
5126
+ }
5127
+ }
5128
+ function getCachedPackageInfo(packageName, version) {
5129
+ try {
5130
+ const cache = getVersionCache();
5131
+ return cache.packages[packageName]?.[version];
5132
+ } catch (error) {
5133
+ log_default.debug(`Failed to get cached package info: ${error}`);
5134
+ return void 0;
5135
+ }
5136
+ }
5137
+ async function fetchCachedPackageInfo(packageName, version) {
5138
+ const cacheKey = version || "latest";
5139
+ let cachedInfo = getCachedPackageInfo(packageName, cacheKey);
5140
+ if (cachedInfo) {
5141
+ return cachedInfo;
5142
+ }
5143
+ const packageInfo = await packageJsonLib__default.default(packageName, {
5144
+ version,
5145
+ fullMetadata: true
5146
+ });
5147
+ const info = {
5148
+ version: packageInfo.version,
5149
+ deprecated: packageInfo.deprecated,
5150
+ fetched_at: (/* @__PURE__ */ new Date()).toISOString()
5151
+ };
5152
+ setCachedPackageInfo(packageName, cacheKey, info);
5153
+ return info;
5154
+ }
5155
+ async function checkForUpdates({
5156
+ packageName,
5157
+ currentVersion
5158
+ }) {
5159
+ try {
5160
+ const latestPackageInfo = await fetchCachedPackageInfo(packageName);
5161
+ const latestVersion = latestPackageInfo.version;
5162
+ const hasUpdate = semver__default.default.gt(latestVersion, currentVersion);
5163
+ let currentPackageInfo;
5164
+ try {
5165
+ currentPackageInfo = await fetchCachedPackageInfo(
5166
+ packageName,
5167
+ currentVersion
5168
+ );
5169
+ } catch (error) {
5170
+ if (!(error instanceof packageJsonLib.VersionNotFoundError)) {
5171
+ log_default.debug(`Failed to check deprecation for current version: ${error}`);
5172
+ }
5173
+ currentPackageInfo = latestPackageInfo;
5174
+ }
5175
+ const isDeprecated = Boolean(currentPackageInfo.deprecated);
5176
+ const deprecationMessage = isDeprecated ? String(currentPackageInfo.deprecated) : void 0;
5177
+ return {
5178
+ hasUpdate,
5179
+ latestVersion,
5180
+ currentVersion,
5181
+ isDeprecated,
5182
+ deprecationMessage
5183
+ };
5184
+ } catch (error) {
5185
+ log_default.debug(`Failed to check for updates: ${error}`);
5186
+ return {
5187
+ hasUpdate: false,
5188
+ currentVersion,
5189
+ isDeprecated: false
5190
+ };
5191
+ }
5192
+ }
5193
+ var BRAILLE_BLANK = "\u2800";
5194
+ var LIGHTNING_INTERVAL_MILLISECONDS = 140;
5195
+ var boltRows = [
5196
+ "\u2800\u2800\u2880\u28FE\u2800\u2800\u2800\u2800",
5197
+ "\u2800\u2800\u28E0\u28FF\u28FF\u2800\u2800\u2800",
5198
+ "\u2800\u28FC\u28FF\u28FF\u28FF\u28C0\u28C0\u2840",
5199
+ "\u2808\u2809\u2809\u28FF\u28FF\u28FF\u285F\u2800",
5200
+ "\u2800\u2800\u2800\u28FF\u28FF\u280B\u2800\u2800",
5201
+ "\u2800\u2800\u2800\u287F\u2801\u2800\u2800\u2800"
5202
+ ];
5203
+ var boltFillOrder = boltRows.flatMap(
5204
+ (row, rowIndex) => [...row].flatMap(
5205
+ (cell, columnIndex) => cell === BRAILLE_BLANK ? [] : rowIndex * row.length + columnIndex
5206
+ )
5207
+ );
5208
+ var fillStages = [
5209
+ ...Array.from({ length: boltFillOrder.length + 1 }, (_, index) => index),
5210
+ boltFillOrder.length,
5211
+ 0
5212
+ ];
5213
+ var boltFillRanks = new Map(
5214
+ boltFillOrder.map((cellIndex, fillIndex) => [cellIndex, fillIndex])
5215
+ );
5216
+ var STATUS_ROW_INDEX = Math.floor(boltRows.length / 2);
5217
+ function formatPhase({ label, detail }) {
5218
+ return detail ? `${chalk3__default.default.bold(label)} ${chalk3__default.default.dim(detail)}` : chalk3__default.default.bold(label);
5219
+ }
5220
+ function formatLoaderFrame({
5221
+ phase,
5222
+ fillStage
5223
+ }) {
5224
+ return boltRows.map((row, rowIndex) => {
5225
+ const bolt = [...row].map((cell, columnIndex) => {
5226
+ if (cell === BRAILLE_BLANK) return cell;
5227
+ const cellIndex = rowIndex * row.length + columnIndex;
5228
+ const fillRank = boltFillRanks.get(cellIndex);
5229
+ const isFilled = fillRank !== void 0 && fillRank < fillStage;
5230
+ return isFilled ? chalk3__default.default.bold.yellow(cell) : chalk3__default.default.dim.yellow(cell);
5231
+ }).join("");
5232
+ const status = rowIndex === STATUS_ROW_INDEX ? ` ${formatPhase(phase)}` : "";
5233
+ return `${bolt}${status}`;
5234
+ }).join("\n");
5235
+ }
5236
+ async function runWithSetupLoader({
5237
+ promise,
5238
+ ...phase
5239
+ }) {
5240
+ const startedAt = Date.now();
5241
+ let fillFrameIndex = 0;
5242
+ const loader = ora__default.default({
5243
+ isEnabled: process.stderr.isTTY === true,
5244
+ spinner: { interval: 80, frames: [""] },
5245
+ text: formatLoaderFrame({
5246
+ phase,
5247
+ fillStage: fillStages[fillFrameIndex]
5248
+ })
5249
+ }).start();
5250
+ const animationTimer = setInterval(() => {
5251
+ fillFrameIndex = (fillFrameIndex + 1) % fillStages.length;
5252
+ loader.text = formatLoaderFrame({
5253
+ phase,
5254
+ fillStage: fillStages[fillFrameIndex]
5255
+ });
5256
+ }, LIGHTNING_INTERVAL_MILLISECONDS);
5257
+ animationTimer.unref?.();
5258
+ try {
5259
+ const result = await promise;
5260
+ clearInterval(animationTimer);
5261
+ const elapsedSeconds = ((Date.now() - startedAt) / 1e3).toFixed(1);
5262
+ loader.succeed(`${formatPhase(phase)} ${chalk3__default.default.dim(`${elapsedSeconds}s`)}`);
5263
+ return result;
5264
+ } catch (error) {
5265
+ clearInterval(animationTimer);
5266
+ const elapsedSeconds = ((Date.now() - startedAt) / 1e3).toFixed(1);
5267
+ loader.fail(`${formatPhase(phase)} ${chalk3__default.default.dim(`${elapsedSeconds}s`)}`);
5268
+ throw error;
5269
+ }
5270
+ }
5271
+ function isRecord(value) {
5272
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5273
+ }
5274
+ function readPackageJson({
5275
+ directory
5276
+ }) {
5277
+ try {
5278
+ const manifest = JSON.parse(
5279
+ fs.readFileSync(path.join(directory, "package.json"), "utf8")
5280
+ );
5281
+ return isRecord(manifest) ? manifest : void 0;
5282
+ } catch {
5283
+ return void 0;
5284
+ }
5285
+ }
5286
+ var SetupOptionSchema = zod.z.object({
5287
+ label: zod.z.string(),
5288
+ value: zod.z.string()
5289
+ });
5290
+ var SetupOptionsSchema = zod.z.array(SetupOptionSchema).min(1);
5291
+ var SetupDecisionSchema = zod.z.object({
5292
+ message: zod.z.string(),
5293
+ options: SetupOptionsSchema,
5294
+ answer: zod.z.string()
5295
+ });
5296
+ var SetupInputSchema = zod.z.object({
5297
+ message: zod.z.string(),
5298
+ answer: zod.z.string()
5299
+ });
5300
+ var setupDecisionResolver = zapierSdk.defineResolver({
5301
+ requireParameters: ["message", "options"],
5302
+ listItems: ({ input }) => ({ data: input.options }),
5303
+ prompt: ({ items, input }) => ({
5304
+ type: "list",
5305
+ message: input.message,
5306
+ choices: items
5307
+ }),
5308
+ validate: ({ input, value }) => {
5309
+ if (typeof value !== "string") return "Choose an available option.";
5310
+ return input.options.some((option) => option.value === value) || "Choose one of the available options.";
5311
+ }
5312
+ });
5313
+ var setupInputResolver = zapierSdk.defineResolver({
5314
+ type: "static",
5315
+ inputType: "text",
5316
+ requireParameters: ["message"]
5317
+ });
5318
+ var resolveSetupDecisionPlugin = zapierSdk.defineMethod({
5319
+ name: "resolveSetupDecision",
5320
+ description: "Resolve one setup wizard decision.",
5321
+ inputSchema: SetupDecisionSchema,
5322
+ resolvers: { answer: setupDecisionResolver },
5323
+ run: ({ input }) => input
5324
+ });
5325
+ var resolveSetupInputPlugin = zapierSdk.defineMethod({
5326
+ name: "resolveSetupInput",
5327
+ description: "Resolve one setup wizard text input.",
5328
+ inputSchema: SetupInputSchema,
5329
+ resolvers: { answer: setupInputResolver },
5330
+ run: ({ input }) => input
5331
+ });
5332
+ function createSetupController() {
5333
+ const setupResolutionSdk = zapierSdk.createSdk(
5334
+ zapierSdk.definePlugin({
5335
+ name: "setup-resolution",
5336
+ exports: [
5337
+ resolveSetupDecisionPlugin,
5338
+ resolveSetupInputPlugin,
5339
+ zapierSdk.getRegistryPlugin
5340
+ ]
5341
+ })
5342
+ );
5343
+ return zapierSdk.createController(setupResolutionSdk);
5344
+ }
5345
+ async function resolveWithCancellation({
5346
+ run
5347
+ }) {
5348
+ try {
5349
+ return await run();
5350
+ } catch (error) {
5351
+ if (zapierSdk.isCoreCancelledSignal(error)) {
5352
+ throw new ZapierCliUserCancellationError();
5353
+ }
5354
+ throw error;
5355
+ }
5356
+ }
5357
+ async function resolveSetupDecision({
5358
+ answer,
5359
+ controller,
5360
+ message,
5361
+ options
5362
+ }) {
5363
+ const parsedOptions = SetupOptionsSchema.parse(options);
5364
+ const resolved = await resolveWithCancellation({
5365
+ run: () => controller.resolve({
5366
+ method: "resolveSetupDecision",
5367
+ input: { message, options: parsedOptions },
5368
+ answer,
5369
+ interactive: true
5370
+ })
5371
+ });
5372
+ return SetupDecisionSchema.parse(resolved).answer;
5373
+ }
5374
+ async function resolveSetupConfirm({
5375
+ answer,
5376
+ controller,
5377
+ defaultValue,
5378
+ message
5379
+ }) {
5380
+ const values = defaultValue ? [true, false] : [false, true];
5381
+ const resolved = await resolveSetupDecision({
5382
+ answer,
5383
+ controller,
5384
+ message,
5385
+ options: values.map((value) => ({
5386
+ label: value ? "Yes" : "No",
5387
+ value: String(value)
5388
+ }))
5389
+ });
5390
+ return resolved === "true";
5391
+ }
5392
+ async function resolveSetupInput({
5393
+ answer,
5394
+ controller,
5395
+ message
5396
+ }) {
5397
+ const resolved = await resolveWithCancellation({
5398
+ run: () => controller.resolve({
5399
+ method: "resolveSetupInput",
5400
+ input: { message },
5401
+ answer: ({ result, state }) => answer({
5402
+ state,
5403
+ result: {
5404
+ ...result,
5405
+ question: { ...result.question, message }
5406
+ }
5407
+ }),
5408
+ interactive: true
5409
+ })
5410
+ });
5411
+ return SetupInputSchema.parse(resolved).answer.trim();
5412
+ }
5413
+ async function resolveSetupSelect({
5414
+ answer,
5415
+ controller,
5416
+ choices,
5417
+ message
5418
+ }) {
5419
+ const resolved = await resolveSetupDecision({
5420
+ answer,
5421
+ controller,
5422
+ message,
5423
+ options: choices
5424
+ });
5425
+ const selected = choices.find(({ value }) => value === resolved);
5426
+ if (!selected) {
5427
+ throw new Error("Resolved setup selection is not an available choice.");
5428
+ }
5429
+ return selected.value;
5430
+ }
5431
+
5432
+ // src/plugins/setup/dependencies.ts
5433
+ var REQUIRED_PACKAGES = [
5434
+ { name: "@zapier/zapier-sdk", dev: false, checkForUpdates: true },
5435
+ { name: "@zapier/zapier-sdk-cli", dev: true, checkForUpdates: true },
5436
+ {
5437
+ name: "@types/node",
5438
+ dev: true,
5439
+ checkForUpdates: false,
5440
+ typescriptOnly: true
5441
+ },
5442
+ {
5443
+ name: "typescript",
5444
+ dev: true,
5445
+ checkForUpdates: false,
5446
+ typescriptOnly: true
5447
+ },
5448
+ { name: "tsx", dev: true, checkForUpdates: false, typescriptOnly: true }
5449
+ ];
5450
+ function getInstallCommand({
5451
+ packageManager,
5452
+ packages,
5453
+ dev = false
5454
+ }) {
5455
+ const verb = packageManager === "npm" ? "install" : "add";
5456
+ const devFlag = packageManager === "bun" ? "-d" : "-D";
5457
+ return {
5458
+ command: packageManager,
5459
+ args: [verb, ...dev ? [devFlag] : [], ...packages]
5460
+ };
5461
+ }
5462
+ async function executeInstall(context, command) {
5463
+ try {
5464
+ await context.runCommand({ ...command, cwd: context.cwd });
5465
+ } catch (error) {
5466
+ const message = error instanceof Error ? error.message : String(error);
5467
+ if (message.includes("EPERM") && message.includes(".npm/_cacache")) {
5468
+ console.error(
5469
+ "This EPERM usually means the command sandbox blocked npm cache writes; it does not usually mean your file permissions are broken."
5470
+ );
5471
+ }
5472
+ throw error;
5473
+ }
5474
+ }
5475
+ function getDeclaredPackageNames(cwd) {
5476
+ const manifest = readPackageJson({ directory: cwd });
5477
+ if (!manifest) return /* @__PURE__ */ new Set();
5478
+ const names = /* @__PURE__ */ new Set();
5479
+ for (const section of ["dependencies", "devDependencies"]) {
5480
+ const dependencies = manifest[section];
5481
+ if (!isRecord(dependencies)) continue;
5482
+ for (const name of Object.keys(dependencies)) names.add(name);
5483
+ }
5484
+ return names;
5485
+ }
5486
+ function getInstalledPackageVersion({
5487
+ cwd,
5488
+ packageName
5489
+ }) {
5490
+ let directory = cwd;
5491
+ while (true) {
5492
+ const manifest = readPackageJson({
5493
+ directory: path.join(directory, "node_modules", ...packageName.split("/"))
5494
+ });
5495
+ if (manifest?.name === packageName && typeof manifest.version === "string") {
5496
+ return manifest.version;
5497
+ }
5498
+ const parent = path.dirname(directory);
5499
+ if (parent === directory) return void 0;
5500
+ directory = parent;
5501
+ }
5502
+ }
5503
+ async function installPackages({
5504
+ context,
5505
+ packages
5506
+ }) {
5507
+ const runtimePackages = packages.filter(({ dependency }) => !dependency.dev).map(({ dependency }) => dependency.name);
5508
+ if (runtimePackages.length > 0) {
5509
+ await executeInstall(
5510
+ context,
5511
+ getInstallCommand({
5512
+ packageManager: context.packageManager,
5513
+ packages: runtimePackages
5514
+ })
5515
+ );
5516
+ }
5517
+ const developmentPackages = packages.filter(({ dependency }) => dependency.dev).map(({ dependency }) => dependency.name);
5518
+ if (developmentPackages.length > 0) {
5519
+ await executeInstall(
5520
+ context,
5521
+ getInstallCommand({
5522
+ packageManager: context.packageManager,
5523
+ packages: developmentPackages,
5524
+ dev: true
5525
+ })
5526
+ );
5527
+ }
5528
+ }
5529
+ async function offerMissingPackageInstall({
5530
+ context,
5531
+ packages
5532
+ }) {
5533
+ if (packages.length === 0) return;
5534
+ const shouldInstall = await resolveSetupConfirm({
5535
+ answer: context.createAnswer(),
5536
+ controller: context.setupController,
5537
+ message: `These packages are required to continue. Install them now: ${packages.map(({ dependency }) => dependency.name).join(", ")}?`,
5538
+ defaultValue: true
5539
+ });
5540
+ if (!shouldInstall) {
5541
+ console.log(
5542
+ "The Zapier SDK packages are required to continue. Setup cancelled without installing dependencies."
5543
+ );
5544
+ throw new ZapierCliUserCancellationError(
5545
+ "Required Zapier SDK packages were not installed"
5546
+ );
5547
+ }
5548
+ await installPackages({ context, packages });
5549
+ }
5550
+ async function offerPackageUpdate({
5551
+ context,
5552
+ packageState
5553
+ }) {
5554
+ const { currentVersion, dependency } = packageState;
5555
+ if (!currentVersion || !dependency.checkForUpdates) return;
5556
+ const update = await runWithSetupLoader({
5557
+ promise: context.checkForUpdates({
5558
+ packageName: dependency.name,
5559
+ currentVersion
5560
+ }),
5561
+ label: "Checking for updates",
5562
+ detail: dependency.name
5563
+ });
5564
+ if (!update.hasUpdate || !update.latestVersion) return;
5565
+ const shouldUpdate = await resolveSetupConfirm({
5566
+ answer: context.createAnswer(),
5567
+ controller: context.setupController,
5568
+ message: `Update ${dependency.name} from ${currentVersion} to ${update.latestVersion}?`,
5569
+ defaultValue: true
5570
+ });
5571
+ if (!shouldUpdate) return;
5572
+ await executeInstall(
5573
+ context,
5574
+ getInstallCommand({
5575
+ packageManager: context.packageManager,
5576
+ packages: [`${dependency.name}@${update.latestVersion}`],
5577
+ dev: dependency.dev
5578
+ })
5579
+ );
5580
+ }
5581
+ async function prepareDependencies(context) {
5582
+ const declaredPackageNames = getDeclaredPackageNames(context.cwd);
5583
+ const requiredPackages = REQUIRED_PACKAGES.filter(
5584
+ ({ typescriptOnly }) => !typescriptOnly || context.projectLanguage === "typescript"
5585
+ );
5586
+ const packages = requiredPackages.map((dependency) => ({
5587
+ dependency,
5588
+ currentVersion: declaredPackageNames.has(dependency.name) ? getInstalledPackageVersion({
5589
+ cwd: context.cwd,
5590
+ packageName: dependency.name
5591
+ }) : void 0
5592
+ }));
5593
+ await offerMissingPackageInstall({
5594
+ context,
5595
+ packages: packages.filter(
5596
+ ({ dependency }) => !declaredPackageNames.has(dependency.name)
5597
+ )
5598
+ });
5599
+ for (const packageState of packages) {
5600
+ await offerPackageUpdate({ context, packageState });
5601
+ }
5602
+ }
5603
+
5604
+ // src/plugins/setup/package-commands.ts
5605
+ function createLocalPackageCommand({
5606
+ packageManager,
5607
+ binary,
5608
+ args = []
5609
+ }) {
5610
+ const runner = {
5611
+ npm: { command: "npx", args: ["--no-install"] },
5612
+ pnpm: { command: "pnpm", args: ["exec"] },
5613
+ yarn: { command: "yarn", args: ["exec"] },
5614
+ bun: { command: "bunx", args: ["--no-install"] }
5615
+ };
5616
+ return {
5617
+ command: runner[packageManager].command,
5618
+ args: [...runner[packageManager].args, binary, ...args]
5619
+ };
5620
+ }
5621
+ function createPackageRunnerCommand({
5622
+ packageManager,
5623
+ packageName,
5624
+ args = []
5625
+ }) {
5626
+ const runner = {
5627
+ npm: { command: "npx", args: ["--yes"] },
5628
+ pnpm: { command: "pnpm", args: ["dlx"] },
5629
+ yarn: { command: "yarn", args: ["dlx"] },
5630
+ bun: { command: "bunx", args: [] }
5631
+ };
5632
+ return {
5633
+ command: runner[packageManager].command,
5634
+ args: [...runner[packageManager].args, packageName, ...args]
5635
+ };
5636
+ }
5637
+ function formatPackageCommand({
5638
+ command,
5639
+ args
5640
+ }) {
5641
+ return [command, ...args].join(" ");
5642
+ }
5643
+
5644
+ // src/plugins/setup/project.ts
5645
+ var COMMAND_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
5646
+ var PROJECT_INIT_COMMANDS = {
5647
+ npm: { command: "npm", args: ["init", "-y"] },
5648
+ pnpm: { command: "pnpm", args: ["init"] },
5649
+ yarn: { command: "yarn", args: ["init", "-y"] },
5650
+ bun: { command: "bun", args: ["init", "-y"] }
5651
+ };
5652
+ var CapturedCommandError = class extends Error {
5653
+ constructor(error, stdout, stderr) {
5654
+ super(error.message);
5655
+ this.stdout = stdout;
5656
+ this.stderr = stderr;
5657
+ }
5658
+ };
5659
+ function commandError({
5660
+ command,
5661
+ code,
5662
+ signal
5663
+ }) {
5664
+ return new Error(
5665
+ signal ? `${command} was terminated by ${signal}` : `${command} exited with code ${code ?? "unknown"}`
5666
+ );
5667
+ }
5668
+ function executeCapturedCommand({
5669
+ command,
5670
+ args,
5671
+ cwd,
5672
+ input
5673
+ }) {
5674
+ return new Promise((resolve4, reject) => {
5675
+ const child = crossSpawn__default.default(command, args, {
5676
+ cwd,
5677
+ shell: false,
5678
+ stdio: ["pipe", "pipe", "pipe"]
5679
+ });
5680
+ let stdout = "";
5681
+ let stderr = "";
5682
+ const append = ({
5683
+ chunk,
5684
+ stream
5685
+ }) => {
5686
+ if (stream === "stdout") stdout += chunk.toString();
5687
+ else stderr += chunk.toString();
5688
+ if (Buffer.byteLength(stdout) + Buffer.byteLength(stderr) > COMMAND_MAX_BUFFER_BYTES) {
5689
+ child.kill();
5690
+ reject(new Error("Command output exceeded the capture limit."));
5691
+ }
5692
+ };
5693
+ child.stdout?.on(
5694
+ "data",
5695
+ (chunk) => append({ chunk, stream: "stdout" })
5696
+ );
5697
+ child.stderr?.on(
5698
+ "data",
5699
+ (chunk) => append({ chunk, stream: "stderr" })
5700
+ );
5701
+ child.once("error", reject);
5702
+ child.once("close", (code, signal) => {
5703
+ if (code === 0) {
5704
+ resolve4(stdout.trim());
5705
+ return;
5706
+ }
5707
+ reject(
5708
+ new CapturedCommandError(
5709
+ commandError({ command, code, signal }),
5710
+ stdout,
5711
+ stderr
5712
+ )
5713
+ );
5714
+ });
5715
+ child.stdin?.end(input);
5716
+ });
5717
+ }
5718
+ function executeStreamingCommand({
5719
+ command,
5720
+ args,
5721
+ cwd,
5722
+ input
5723
+ }) {
5724
+ return new Promise((resolve4, reject) => {
5725
+ const child = crossSpawn__default.default(command, args, {
5726
+ cwd,
5727
+ shell: false,
5728
+ stdio: [input === void 0 ? "inherit" : "pipe", "inherit", "inherit"]
5729
+ });
5730
+ child.once("error", reject);
5731
+ child.once("close", (code, signal) => {
5732
+ if (code === 0) {
5733
+ resolve4("");
5734
+ return;
5735
+ }
5736
+ reject(commandError({ command, code, signal }));
4599
5737
  });
5738
+ if (input !== void 0) child.stdin?.end(input);
5739
+ });
5740
+ }
5741
+ async function runCommand({
5742
+ command,
5743
+ args = [],
5744
+ cwd,
5745
+ capture = true,
5746
+ input
5747
+ }) {
5748
+ const commandLabel = `$ ${command} ${args.join(" ")}`.trim();
5749
+ const execute = capture ? executeCapturedCommand({ command, args, cwd, input }) : executeStreamingCommand({ command, args, cwd, input });
5750
+ try {
5751
+ if (capture) {
5752
+ return await runWithSetupLoader({
5753
+ promise: execute,
5754
+ label: "Running command",
5755
+ detail: commandLabel
5756
+ });
5757
+ }
5758
+ console.log(chalk3__default.default.dim(commandLabel));
5759
+ return await execute;
5760
+ } catch (error) {
5761
+ const message = error instanceof Error ? error.message : String(error);
5762
+ if (error instanceof CapturedCommandError) {
5763
+ if (error.stdout) process.stdout.write(error.stdout);
5764
+ if (error.stderr) process.stderr.write(error.stderr);
5765
+ if (!error.stdout && !error.stderr) console.error(message);
5766
+ } else {
5767
+ console.error(message);
5768
+ }
5769
+ throw new ZapierCliExitError(message);
5770
+ }
5771
+ }
5772
+ async function chooseDirectory(context) {
5773
+ const useCurrentDirectory = await resolveSetupConfirm({
5774
+ answer: context.createAnswer(),
5775
+ controller: context.setupController,
5776
+ message: `Set up the Zapier SDK in ${context.cwd}?`,
5777
+ defaultValue: true
5778
+ });
5779
+ if (useCurrentDirectory) return;
5780
+ const setupCommand = formatPackageCommand(
5781
+ createLocalPackageCommand({
5782
+ packageManager: context.packageManager,
5783
+ binary: "zapier-sdk",
5784
+ args: ["setup"]
5785
+ })
5786
+ );
5787
+ console.log(
5788
+ `Setup cancelled. Navigate to the intended directory and run \`${setupCommand}\` again.`
5789
+ );
5790
+ throw new ZapierCliUserCancellationError("Setup cancelled by user");
5791
+ }
5792
+ async function ensureSupportedNode(context) {
5793
+ let version;
5794
+ try {
5795
+ version = await context.runCommand({
5796
+ command: "node",
5797
+ args: ["-v"],
5798
+ cwd: context.cwd,
5799
+ capture: true
5800
+ });
5801
+ } catch {
5802
+ console.error(
5803
+ "Node.js 20 or higher is required. Install it from https://nodejs.org, then run setup again."
5804
+ );
5805
+ throw new ZapierCliExitError(
5806
+ "Setup could not continue without Node.js 20 or higher."
5807
+ );
5808
+ }
5809
+ const major = Number(version.replace(/^v/, "").split(".")[0]);
5810
+ if (!Number.isFinite(major) || major < 20) {
5811
+ console.error(
5812
+ `Node.js 20 or higher is required; found ${version}. Upgrade Node.js, then run setup again.`
5813
+ );
5814
+ throw new ZapierCliExitError(
5815
+ "Setup could not continue without Node.js 20 or higher."
5816
+ );
5817
+ }
5818
+ console.log(`Node.js ${version} is ready.`);
5819
+ }
5820
+ function detectProjectLanguage({
5821
+ cwd,
5822
+ hasExistingProject
5823
+ }) {
5824
+ if (!hasExistingProject || fs.existsSync(path.join(cwd, "tsconfig.json"))) {
5825
+ return "typescript";
5826
+ }
5827
+ const manifest = readPackageJson({ directory: cwd });
5828
+ const hasTypeScript = [
5829
+ manifest?.dependencies,
5830
+ manifest?.devDependencies
5831
+ ].some(
5832
+ (dependencies) => isRecord(dependencies) && "typescript" in dependencies
5833
+ );
5834
+ return hasTypeScript ? "typescript" : "javascript";
5835
+ }
5836
+ async function prepareProject(context) {
5837
+ context.packageManager = detectPackageManager(context.cwd).name;
5838
+ console.log(`Using ${context.packageManager} for dependency installs.`);
5839
+ const hasExistingProject = fs.existsSync(path.join(context.cwd, "package.json"));
5840
+ context.projectLanguage = detectProjectLanguage({
5841
+ cwd: context.cwd,
5842
+ hasExistingProject
5843
+ });
5844
+ if (hasExistingProject) {
5845
+ console.log("Found package.json; using this project as-is.");
5846
+ } else {
5847
+ await context.runCommand({
5848
+ ...PROJECT_INIT_COMMANDS[context.packageManager],
5849
+ cwd: context.cwd
5850
+ });
5851
+ }
5852
+ await prepareDependencies(context);
5853
+ }
5854
+
5855
+ // src/plugins/setup/context.ts
5856
+ function createWizardContext({
5857
+ imports
5858
+ }) {
5859
+ return {
5860
+ cwd: process.cwd(),
5861
+ imports,
5862
+ createAnswer: () => createCliAnswer({ mode: "closed-list" }),
5863
+ setupController: createSetupController(),
5864
+ checkForUpdates,
5865
+ openUrl: async (url) => {
5866
+ await open__default.default(url);
5867
+ },
5868
+ runCommand,
5869
+ packageManager: detectPackageManager(process.cwd()).name,
5870
+ projectLanguage: "typescript"
5871
+ };
5872
+ }
5873
+ var SetupSchema = zod.z.object({}).describe("Set up the Zapier SDK in an existing or new project");
5874
+ function printAuthCommand({
5875
+ context,
5876
+ flow,
5877
+ headless
5878
+ }) {
5879
+ const command = createLocalPackageCommand({
5880
+ packageManager: context.packageManager,
5881
+ binary: "zapier-sdk",
5882
+ args: [flow, ...headless ? ["--headless"] : []]
5883
+ });
5884
+ console.log(`$ ${formatPackageCommand(command)}`);
5885
+ if (headless) {
5886
+ console.log(
5887
+ "Open the printed URL in another browser, then paste the final OAuth callback URL when prompted."
5888
+ );
5889
+ }
5890
+ }
5891
+ function isCredentialWriteError(error) {
5892
+ const code = typeof error === "object" && error !== null && "code" in error && typeof error.code === "string" ? error.code : "";
5893
+ if (/^(eacces|eperm)$/i.test(code)) return true;
5894
+ const message = error instanceof Error ? error.message : String(error);
5895
+ return /permission|sandbox|eacces|eperm/i.test(message);
5896
+ }
5897
+ async function authenticate(context) {
5898
+ const activeProfile = await runWithSetupLoader({
5899
+ promise: context.imports.getProfile({}).then(({ data }) => data).catch((error) => {
5900
+ if (zapierSdk.isZapierAuthenticationError(error)) return void 0;
5901
+ throw error;
5902
+ }),
5903
+ label: "Checking Zapier authentication"
5904
+ });
5905
+ if (activeProfile) {
5906
+ const shouldLogout = await resolveSetupConfirm({
5907
+ answer: context.createAnswer(),
5908
+ controller: context.setupController,
5909
+ message: `You are already logged in as "${activeProfile.email}".
5910
+ Logging out will delete these credentials and may interrupt other Zapier SDK or CLI sessions using them.
5911
+ Log out and use a different account?`,
5912
+ defaultValue: false
5913
+ });
5914
+ if (!shouldLogout) {
5915
+ context.accountEmail = activeProfile.email;
5916
+ console.log(`Continuing as ${activeProfile.email}.`);
5917
+ return;
5918
+ }
5919
+ const logoutCommand = createLocalPackageCommand({
5920
+ packageManager: context.packageManager,
5921
+ binary: "zapier-sdk",
5922
+ args: ["logout"]
5923
+ });
5924
+ console.log(`$ ${formatPackageCommand(logoutCommand)}`);
5925
+ await context.imports.logout({});
5926
+ }
5927
+ const flow = await resolveSetupSelect({
5928
+ answer: context.createAnswer(),
5929
+ controller: context.setupController,
5930
+ message: "Zapier account:",
5931
+ choices: [
5932
+ { label: "Log in to an existing account", value: "login" },
5933
+ { label: "Create a new Zapier account", value: "signup" }
5934
+ ]
5935
+ });
5936
+ const environment = await resolveSetupSelect({
5937
+ answer: context.createAnswer(),
5938
+ controller: context.setupController,
5939
+ message: "Environment:",
5940
+ choices: [
5941
+ { label: "Local machine with a browser", value: "local" },
5942
+ { label: "Remote or headless", value: "headless" }
5943
+ ]
5944
+ });
5945
+ const headless = environment === "headless";
5946
+ const runAuth = flow === "login" ? context.imports.login : context.imports.signup;
5947
+ printAuthCommand({ context, flow, headless });
5948
+ try {
5949
+ await runAuth({ headless });
5950
+ } catch (error) {
5951
+ if (isCredentialWriteError(error)) {
5952
+ console.error(
5953
+ "Authentication could not write credentials. A permissions or sandbox restriction may be blocking disk access."
5954
+ );
5955
+ }
5956
+ throw error;
5957
+ }
5958
+ const { data: profile } = await runWithSetupLoader({
5959
+ promise: context.imports.getProfile({}),
5960
+ label: "Confirming Zapier account"
5961
+ });
5962
+ context.accountEmail = profile.email;
5963
+ console.log(`Authenticated as ${profile.email}.`);
5964
+ }
5965
+ var agentLabels = {
5966
+ claude: "Claude Code",
5967
+ codex: "Codex",
5968
+ cursor: "Cursor",
5969
+ "vscode-copilot": "VS Code Copilot"
5970
+ };
5971
+ function buildAgentPrompt({ context }) {
5972
+ const listConnectionsCommand = formatPackageCommand(
5973
+ createLocalPackageCommand({
5974
+ packageManager: context.packageManager,
5975
+ binary: "zapier-sdk",
5976
+ args: ["list-connections", "--owner", "me", "--json"]
5977
+ })
5978
+ );
5979
+ const listActionsCommand = formatPackageCommand(
5980
+ createLocalPackageCommand({
5981
+ packageManager: context.packageManager,
5982
+ binary: "zapier-sdk",
5983
+ args: ["list-actions", "APP_KEY"]
5984
+ })
5985
+ );
5986
+ return `Start by running this command to discover my active connected apps outside of your sandbox:
5987
+
5988
+ ${listConnectionsCommand}
5989
+
5990
+ Using the connected apps returned by that command:
5991
+
5992
+ - Pick 1-3 apps and show commands I can use to explore their actions, such as: ${listActionsCommand}
5993
+ - Do not run those list-actions commands.
5994
+ - Suggest 3 specific ideas based on my connected apps. Each idea should read from one app, optionally process data, and write to another.
5995
+ - Do not suggest event-driven workflows.
5996
+ - Keep each idea to one sentence. Example: "pull in-progress Jira issues and DM yourself a summary on Slack".
5997
+
5998
+ Do not inspect files or modify the project. If fewer than two distinct apps are listed, explain that cross-app ideas require another active connection instead of inventing apps.`;
5999
+ }
6000
+ function printAgentPrompt({
6001
+ context,
6002
+ message
6003
+ }) {
6004
+ console.log();
6005
+ console.log(chalk3__default.default.bgYellow.black.bold(message));
6006
+ console.log();
6007
+ console.log(buildAgentPrompt({ context }));
6008
+ }
6009
+ async function openAgentHandoff(context) {
6010
+ const agent = await resolveSetupSelect({
6011
+ answer: context.createAnswer(),
6012
+ controller: context.setupController,
6013
+ message: "Want to open your agent and have it give you suggestions to start?",
6014
+ choices: [
6015
+ { label: "No", value: "none" },
6016
+ { label: "Claude Code", value: "claude" },
6017
+ { label: "Cursor", value: "cursor" },
6018
+ { label: "Codex", value: "codex" },
6019
+ { label: "VS Code Copilot", value: "vscode-copilot" },
6020
+ { label: "Other", value: "other" }
6021
+ ]
6022
+ });
6023
+ if (agent === "none") return;
6024
+ if (agent === "other") {
6025
+ printAgentPrompt({
6026
+ context,
6027
+ message: "Paste this prompt into your AI agent:"
6028
+ });
6029
+ return;
6030
+ }
6031
+ const prompt = buildAgentPrompt({ context });
6032
+ const encodedPrompt = encodeURIComponent(prompt);
6033
+ const encodedPath = encodeURIComponent(context.cwd);
6034
+ try {
6035
+ switch (agent) {
6036
+ case "claude":
6037
+ await context.openUrl(
6038
+ `claude://code/new?q=${encodedPrompt}&folder=${encodedPath}`
6039
+ );
6040
+ break;
6041
+ case "codex":
6042
+ await context.openUrl(
6043
+ `codex://threads/new?prompt=${encodedPrompt}&path=${encodedPath}`
6044
+ );
6045
+ break;
6046
+ case "cursor":
6047
+ await context.runCommand({
6048
+ command: "cursor",
6049
+ args: ["."],
6050
+ cwd: context.cwd,
6051
+ capture: true
6052
+ });
6053
+ console.log(`Cursor opened in ${context.cwd}.`);
6054
+ break;
6055
+ case "vscode-copilot":
6056
+ await context.runCommand({
6057
+ command: "code",
6058
+ args: ["chat", "--mode", "agent", "-"],
6059
+ cwd: context.cwd,
6060
+ input: prompt
6061
+ });
6062
+ break;
6063
+ default: {
6064
+ const unsupportedAgent = agent;
6065
+ throw new Error(`Unsupported agent: ${unsupportedAgent}`);
6066
+ }
6067
+ }
6068
+ } catch {
6069
+ console.warn(
6070
+ `Could not open ${agentLabels[agent]}. Open it manually to continue.`
6071
+ );
6072
+ }
6073
+ printAgentPrompt({
6074
+ context,
6075
+ message: "If it didn't load correctly, paste this prompt into your agent:"
6076
+ });
6077
+ }
6078
+ var CONNECTIONS_URL = "https://zapier.com/app/assets/connections";
6079
+ var CONNECTION_DISPLAY_LIMIT = 10;
6080
+ async function ensureConnectionsAvailable(context) {
6081
+ const page = await runWithSetupLoader({
6082
+ promise: context.imports.listConnections({
6083
+ owner: "me",
6084
+ maxItems: CONNECTION_DISPLAY_LIMIT
6085
+ }),
6086
+ label: "Loading app connections"
6087
+ });
6088
+ if (page.data.length === 0) {
6089
+ console.log(
6090
+ `No active connections found. Connect or reconnect an app at ${CONNECTIONS_URL}, then come back and run setup again.`
6091
+ );
6092
+ throw new ZapierCliExitError(
6093
+ "Setup stopped before completion because no active connections are available."
6094
+ );
6095
+ }
6096
+ const table = new Table__default.default({
6097
+ head: ["App", "Connection"],
6098
+ style: { compact: true }
6099
+ });
6100
+ table.push(
6101
+ ...page.data.map((connection) => [
6102
+ connection.slug || connection.app_key,
6103
+ connection.title
6104
+ ])
6105
+ );
6106
+ console.log(
6107
+ `Active Zapier connections (showing up to ${CONNECTION_DISPLAY_LIMIT}):`
6108
+ );
6109
+ console.log(table.toString());
6110
+ }
6111
+ var CONNECTION_PLACEHOLDER = "__ZAPIER_SDK_SLACK_CONNECTION__";
6112
+ var EMAIL_PLACEHOLDER = "__ZAPIER_SDK_ACCOUNT_EMAIL__";
6113
+ var APP_PLACEHOLDER = "__ZAPIER_SDK_SLACK_APP__";
6114
+ var SLACK_SLUG = "slack";
6115
+ function getSlackTestPath(context) {
6116
+ const extension = context.projectLanguage === "typescript" ? "ts" : "mjs";
6117
+ return path.join("src", "sdk-demo", `zapier-slack-test.${extension}`);
6118
+ }
6119
+ function getSlackTestTemplatePath(context) {
6120
+ const extension = context.projectLanguage === "typescript" ? "ts" : "mjs";
6121
+ return path.join(TEMPLATES_DIR, "setup", `zapier-slack-test.${extension}`);
6122
+ }
6123
+ async function findSlackConnection(context) {
6124
+ const page = await runWithSetupLoader({
6125
+ promise: context.imports.listConnections({
6126
+ owner: "me",
6127
+ app: SLACK_SLUG,
6128
+ maxItems: 1
6129
+ }),
6130
+ label: "Looking for a Slack connection"
6131
+ });
6132
+ return page.data.find(({ slug }) => slug === SLACK_SLUG);
6133
+ }
6134
+ function toTemplateString(value) {
6135
+ return JSON.stringify(value).slice(1, -1);
6136
+ }
6137
+ function renderSlackTest({
6138
+ context,
6139
+ app,
6140
+ connection,
6141
+ email
6142
+ }) {
6143
+ return fs.readFileSync(getSlackTestTemplatePath(context), "utf8").replace(APP_PLACEHOLDER, () => toTemplateString(app)).replace(CONNECTION_PLACEHOLDER, () => toTemplateString(connection)).replace(EMAIL_PLACEHOLDER, () => toTemplateString(email));
6144
+ }
6145
+ function writeSlackTest({
6146
+ context,
6147
+ app,
6148
+ connection,
6149
+ email
6150
+ }) {
6151
+ const slackTestPath = getSlackTestPath(context);
6152
+ const path2 = path.join(context.cwd, slackTestPath);
6153
+ if (!fs.existsSync(path.dirname(path2))) fs.mkdirSync(path.dirname(path2), { recursive: true });
6154
+ fs.writeFileSync(path2, renderSlackTest({ context, app, connection, email }));
6155
+ console.log(`Created ${slackTestPath}.`);
6156
+ }
6157
+ async function executeSlackTest(context) {
6158
+ const slackTestPath = getSlackTestPath(context);
6159
+ if (context.projectLanguage === "javascript") {
6160
+ await context.runCommand({
6161
+ command: "node",
6162
+ args: [slackTestPath],
6163
+ cwd: context.cwd,
6164
+ capture: false
6165
+ });
6166
+ return;
6167
+ }
6168
+ const command = context.packageManager === "bun" ? { command: "bun", args: [] } : createLocalPackageCommand({
6169
+ packageManager: context.packageManager,
6170
+ binary: "tsx"
6171
+ });
6172
+ const args = [...command.args, slackTestPath];
6173
+ await context.runCommand({
6174
+ command: command.command,
6175
+ args,
6176
+ cwd: context.cwd,
6177
+ capture: false
6178
+ });
6179
+ }
6180
+ async function trySlackTest(context) {
6181
+ try {
6182
+ await executeSlackTest(context);
6183
+ return true;
6184
+ } catch (error) {
6185
+ const message = error instanceof Error ? error.message : String(error);
6186
+ console.warn(`Slack demo failed: ${message}. Setup will continue.`);
6187
+ return false;
6188
+ }
6189
+ }
6190
+ async function offerSlackTest(context) {
6191
+ if (!context.accountEmail) {
6192
+ console.log("No account email found; skipping the Slack demo.");
6193
+ return;
6194
+ }
6195
+ const slackConnection = await findSlackConnection(context);
6196
+ if (!slackConnection) {
6197
+ console.log("No active Slack connection found; skipping the Slack demo.");
6198
+ return;
6199
+ }
6200
+ const slackTestPath = getSlackTestPath(context);
6201
+ const shouldRun = await resolveSetupConfirm({
6202
+ answer: context.createAnswer(),
6203
+ controller: context.setupController,
6204
+ message: `Run the Slack self-DM test using ${context.accountEmail}?`,
6205
+ defaultValue: true
6206
+ });
6207
+ if (!shouldRun) return;
6208
+ const path2 = path.join(context.cwd, slackTestPath);
6209
+ if (fs.existsSync(path2)) {
6210
+ const shouldOverwrite = await resolveSetupConfirm({
6211
+ answer: context.createAnswer(),
6212
+ controller: context.setupController,
6213
+ message: `${slackTestPath} already exists. Is it okay to overwrite it?`,
6214
+ defaultValue: false
6215
+ });
6216
+ if (!shouldOverwrite) {
6217
+ console.log("Keeping the existing Slack test file.");
6218
+ const shouldRunExisting = await resolveSetupConfirm({
6219
+ answer: context.createAnswer(),
6220
+ controller: context.setupController,
6221
+ message: `Run the existing ${slackTestPath}?`,
6222
+ defaultValue: false
6223
+ });
6224
+ if (shouldRunExisting) await trySlackTest(context);
6225
+ return;
6226
+ }
6227
+ }
6228
+ let email = context.accountEmail;
6229
+ writeSlackTest({
6230
+ context,
6231
+ app: SLACK_SLUG,
6232
+ connection: slackConnection.id,
6233
+ email
6234
+ });
6235
+ if (await trySlackTest(context)) return;
6236
+ email = await resolveSetupInput({
6237
+ answer: context.createAnswer(),
6238
+ controller: context.setupController,
6239
+ message: "Slack email for one retry after the failed test:"
6240
+ });
6241
+ if (!email) {
6242
+ console.log("Skipping the Slack test.");
6243
+ return;
6244
+ }
6245
+ writeSlackTest({
6246
+ context,
6247
+ app: SLACK_SLUG,
6248
+ connection: slackConnection.id,
6249
+ email
6250
+ });
6251
+ await trySlackTest(context);
6252
+ }
6253
+
6254
+ // src/plugins/setup/skill.ts
6255
+ async function installOptionalSkill(context) {
6256
+ const shouldInstall = await resolveSetupConfirm({
6257
+ answer: context.createAnswer(),
6258
+ controller: context.setupController,
6259
+ message: "Install the optional Zapier SDK skill for extra agent context? This is not required for SDK setup.",
6260
+ defaultValue: true
6261
+ });
6262
+ if (!shouldInstall) {
6263
+ console.log("Skipping the optional Zapier SDK skill.");
6264
+ return;
6265
+ }
6266
+ const command = createPackageRunnerCommand({
6267
+ packageManager: context.packageManager,
6268
+ packageName: "skills",
6269
+ args: ["add", "zapier/sdk", "-y"]
6270
+ });
6271
+ try {
6272
+ await context.runCommand({
6273
+ ...command,
6274
+ cwd: context.cwd,
6275
+ capture: true
6276
+ });
6277
+ } catch {
6278
+ console.warn(
6279
+ `Could not install the optional Zapier SDK skill. To install it manually, run: ${formatPackageCommand(command)}`
6280
+ );
6281
+ }
6282
+ }
6283
+
6284
+ // src/plugins/setup/wizard.ts
6285
+ var PHASE_COUNT = 6;
6286
+ var MINIMUM_MESSAGE_WIDTH = 20;
6287
+ var MAXIMUM_MESSAGE_WIDTH = 88;
6288
+ function showPhase({ number, title }) {
6289
+ console.log();
6290
+ console.log(chalk3__default.default.bgCyan.black.bold(` ${number}/${PHASE_COUNT} ${title} `));
6291
+ }
6292
+ function printWrapped(text) {
6293
+ const width = Math.max(
6294
+ MINIMUM_MESSAGE_WIDTH,
6295
+ Math.min(
6296
+ process.stdout.columns ?? MAXIMUM_MESSAGE_WIDTH,
6297
+ MAXIMUM_MESSAGE_WIDTH
6298
+ )
6299
+ );
6300
+ console.log(wrapAnsi__default.default(text, width));
6301
+ }
6302
+ function showReadyMessage() {
6303
+ console.log();
6304
+ console.log(chalk3__default.default.bgGreen.black.bold(" \u2713 Zapier SDK setup complete "));
6305
+ console.log();
6306
+ printWrapped(
6307
+ "Use active Zapier connections to access 9,000+ app connectors without managing each app's OAuth, token refresh, or retries."
6308
+ );
6309
+ console.log();
6310
+ printWrapped(
6311
+ "To learn more about the Zapier SDK, visit https://docs.zapier.com/sdk"
6312
+ );
6313
+ console.log();
6314
+ }
6315
+ async function runWizard(context) {
6316
+ console.log(chalk3__default.default.bold("Zapier SDK setup"));
6317
+ showPhase({ number: 1, title: "Project directory" });
6318
+ await chooseDirectory(context);
6319
+ showPhase({ number: 2, title: "Node.js" });
6320
+ await ensureSupportedNode(context);
6321
+ showPhase({ number: 3, title: "Dependencies" });
6322
+ await prepareProject(context);
6323
+ await installOptionalSkill(context);
6324
+ showPhase({ number: 4, title: "Zapier account" });
6325
+ await authenticate(context);
6326
+ showPhase({ number: 5, title: "App connections" });
6327
+ await ensureConnectionsAvailable(context);
6328
+ showPhase({ number: 6, title: "Slack demo" });
6329
+ await offerSlackTest(context);
6330
+ showReadyMessage();
6331
+ console.log(chalk3__default.default.bgCyan.black.bold(" Next steps "));
6332
+ await openAgentHandoff(context);
6333
+ }
6334
+
6335
+ // src/plugins/setup/index.ts
6336
+ var getProfileRef = zapierSdk.declareMethod({ id: "getProfile" });
6337
+ var listConnectionsRef2 = zapierSdk.declareMethod({ id: "listConnections" });
6338
+ var loginRef = zapierSdk.declareMethod({ id: "login" });
6339
+ var logoutRef = zapierSdk.declareMethod({ id: "logout" });
6340
+ var signupRef = zapierSdk.declareMethod({ id: "signup" });
6341
+ var setupImports = [
6342
+ getProfileRef,
6343
+ listConnectionsRef2,
6344
+ loginRef,
6345
+ logoutRef,
6346
+ signupRef
6347
+ ];
6348
+ var setupPlugin = zapierSdk.defineMethod({
6349
+ name: "setup",
6350
+ imports: setupImports,
6351
+ categories: ["utility"],
6352
+ supportsJsonOutput: false,
6353
+ inputSchema: SetupSchema,
6354
+ output: "raw",
6355
+ run: async ({ imports }) => {
6356
+ if (process.stdin.isTTY !== true || process.stdout.isTTY !== true) {
6357
+ throw new ZapierCliExitError(
6358
+ "`zapier-sdk setup` requires an interactive terminal."
6359
+ );
6360
+ }
6361
+ await runWizard(createWizardContext({ imports }));
4600
6362
  }
4601
6363
  });
4602
6364
  function jsonReplacer(_key, value) {
@@ -4633,7 +6395,7 @@ ${chalk3__default.default.bold(`Message #${messageNumber}`)} ${chalk3__default.d
4633
6395
  while (true) {
4634
6396
  let action;
4635
6397
  try {
4636
- const answer = await inquirer__default.default.prompt([
6398
+ const answer = await inquirer3__default.default.prompt([
4637
6399
  {
4638
6400
  type: "list",
4639
6401
  name: "action",
@@ -5100,7 +6862,7 @@ function collectDeprecationNoticeAndForward(event, onEvent) {
5100
6862
  // package.json with { type: 'json' }
5101
6863
  var package_default = {
5102
6864
  name: "@zapier/zapier-sdk-cli",
5103
- version: "0.68.0"};
6865
+ version: "0.70.0"};
5104
6866
 
5105
6867
  // src/sdk.ts
5106
6868
  var warnedDeprecatedMethods = /* @__PURE__ */ new Set();
@@ -5140,6 +6902,7 @@ var cliSdkPlugin = zapierSdk.definePlugin({
5140
6902
  mcpPlugin,
5141
6903
  getLoginConfigPathPlugin,
5142
6904
  initPlugin,
6905
+ setupPlugin,
5143
6906
  bundleCodePlugin,
5144
6907
  feedbackPlugin,
5145
6908
  curlPlugin,
@@ -5183,7 +6946,7 @@ function createZapierCliSdk(options = {}) {
5183
6946
 
5184
6947
  // package.json
5185
6948
  var package_default2 = {
5186
- version: "0.68.0"};
6949
+ version: "0.70.0"};
5187
6950
 
5188
6951
  // src/telemetry/builders.ts
5189
6952
  function createCliBaseEvent(context = {}) {
@@ -5231,8 +6994,7 @@ function buildCliCommandExecutedEvent({
5231
6994
  ci_platform: zapierSdk.getCiPlatform(),
5232
6995
  ...zapierSdk.getTtyContext(),
5233
6996
  agent: zapierSdk.getAgent(),
5234
- package_manager: data.package_manager ?? "pnpm",
5235
- // Default based on project setup
6997
+ package_manager: data.package_manager ?? detectPackageManager(process.cwd()).name,
5236
6998
  made_network_requests: data.made_network_requests ?? null,
5237
6999
  files_modified_count: data.files_modified_count ?? null,
5238
7000
  files_created_count: data.files_created_count ?? null,
@@ -5276,6 +7038,14 @@ var SHARED_COMMAND_CLI_OPTIONS = [
5276
7038
  description: "Output raw JSON instead of formatted results"
5277
7039
  }
5278
7040
  ];
7041
+ function negationKebabName(param) {
7042
+ if (param.negatable === true) return `no-${toKebabCase(param.name)}`;
7043
+ if (typeof param.negatable === "string") return toKebabCase(param.negatable);
7044
+ return void 0;
7045
+ }
7046
+ ({
7047
+ [zapierSdk.getConnectionPlugin.name]: /* @__PURE__ */ new Set(["connection"])
7048
+ });
5279
7049
 
5280
7050
  exports.RESERVED_CLI_OPTIONS = RESERVED_CLI_OPTIONS;
5281
7051
  exports.ReservedCliParameter = ReservedCliParameter;
@@ -5283,3 +7053,4 @@ exports.SHARED_COMMAND_CLI_OPTIONS = SHARED_COMMAND_CLI_OPTIONS;
5283
7053
  exports.buildCliCommandExecutedEvent = buildCliCommandExecutedEvent;
5284
7054
  exports.createZapierCliSdk = createZapierCliSdk;
5285
7055
  exports.getReservedCliOption = getReservedCliOption;
7056
+ exports.negationKebabName = negationKebabName;