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