@keystrokehq/cli 0.0.31 → 0.0.37
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/README.md +25 -4
- package/dist/{accept.handler-DNfIXPSP.mjs → accept.handler-DCsud1s5.mjs} +4 -4
- package/dist/{admin-CJp8XksD.mjs → admin-BaOtHeZ2.mjs} +10 -10
- package/dist/{agent-manifest-De5TCxZq.mjs → agent-manifest-DfWD5tvv.mjs} +17 -27
- package/dist/{agents-G37PM35Z.mjs → agents-BVAVfMR_.mjs} +9 -9
- package/dist/{api-keys-4igNHJ_W.mjs → api-keys-BhEEsHUh.mjs} +6 -6
- package/dist/{api-BK3EhPvs.mjs → api-sWkB_Wta.mjs} +1 -1
- package/dist/{auth-CIOmmV4x.mjs → auth-BnsitjzT.mjs} +6 -6
- package/dist/{auth.handler-CznN_vfz.mjs → auth.handler-W_xk14TL.mjs} +3 -3
- package/dist/authored-workflow-ref-fkHEEVnd.mjs +113 -0
- package/dist/{build-agents-DseUtzd4-CSGpNXur.mjs → build-agents-CUzBnlAG-3ePFZiJ6.mjs} +12 -11
- package/dist/{build-progress-DLM1Bt4T.mjs → build-progress-CM-b6Bby.mjs} +2 -2
- package/dist/{build-tasks-C09SdfjC-BmAVLTtQ.mjs → build-tasks-5eOvI19S-tbN6CRx9.mjs} +4 -4
- package/dist/{build-workflows-BZ_m97Pr-BiyptCrn.mjs → build-workflows-C-gQM3l5-_zcBHE3M.mjs} +14 -9
- package/dist/{build.handler-zHimoO7c.mjs → build.handler-CpAsAsBc.mjs} +12 -9
- package/dist/{clear-cache.handler-BP0K1-uN.mjs → clear-cache.handler-gJpwslkK.mjs} +2 -2
- package/dist/{clear.handler-T27GpgSu.mjs → clear.handler-CDyG6-dk.mjs} +1 -1
- package/dist/{clear.handler-PsA5QKHx.mjs → clear.handler-_sR33Hp8.mjs} +2 -2
- package/dist/{commander-BlrSdFcu.mjs → commander-C6SSTQJ2.mjs} +22 -3
- package/dist/{connect-BbLJhlIA.mjs → connect-27EgnljZ.mjs} +3 -3
- package/dist/{connect.handler-BthE-7Wg.mjs → connect.handler-COM1LnNg.mjs} +5 -5
- package/dist/{context-sgKhRc5v.mjs → context-ebZssGCY.mjs} +4 -4
- package/dist/{create.handler-BovbO_g0.mjs → create.handler-CAWJAGzQ.mjs} +3 -3
- package/dist/{credential-env-map-CRs0llf0.mjs → credential-env-map-5a41jLwM.mjs} +1 -1
- package/dist/{credential-requirements-D0mavK8j-CFMf0Xwu.mjs → credential-requirements-B5Alhu1v-DanlSKnT.mjs} +3 -3
- package/dist/{credential-schema-mismatch-ClQgEVtO.mjs → credential-schema-mismatch-c17ktoNU.mjs} +1 -1
- package/dist/{credentials-CsncZ52a.mjs → credentials-C0ssbMlp.mjs} +10 -10
- package/dist/{credentials-DKrSaaLw.mjs → credentials-DtwLbee6.mjs} +1 -1
- package/dist/current-deployment-workflow-C6x65imE.mjs +20 -0
- package/dist/current.handler-DP1L_hm3.mjs +19 -0
- package/dist/{delete.handler-DkAK396w.mjs → delete.handler-C-5XFkgN.mjs} +2 -2
- package/dist/{deploy-DvPfR9fC.mjs → deploy-BcVQJza8.mjs} +2 -2
- package/dist/{deploy-progress-BsUH7fGE.mjs → deploy-progress-Bt86Yc1r.mjs} +2 -2
- package/dist/{deploy.handler-BW3f2N2G.mjs → deploy.handler-GPS9lxGk.mjs} +16 -16
- package/dist/{diff-utils-Bs--xmoV.mjs → diff-utils-YEUYtSRs.mjs} +1 -1
- package/dist/{diff.handler-BwhsoAg0.mjs → diff.handler-DkM5dhaN.mjs} +15 -9
- package/dist/{dist-Dw7gCE7y.mjs → dist-B5jy238v.mjs} +37 -11
- package/dist/{dist-CTEtWDW4.mjs → dist-BmbFJq8U.mjs} +8 -27
- package/dist/{env.handler-Dks6ZQh-.mjs → env.handler-V_isbSi2.mjs} +52 -29
- package/dist/{error-boundary-0veZ_RDS.mjs → error-boundary-BRxUsPi7.mjs} +3 -3
- package/dist/{iam-command-utils-CSZj4XlH.mjs → iam-command-utils-DNDN0wT6.mjs} +3 -13
- package/dist/{import-module-y0glInUe-DV_3dsU0.mjs → import-module-y0glInUe-EuAWaw9g.mjs} +506 -128
- package/dist/{init-DX08T87c.mjs → init-D1OmmclX.mjs} +8 -3
- package/dist/{init.handler-CzlmkNXi.mjs → init.handler-CUbYlUgP.mjs} +57 -14
- package/dist/{inspect.handler-v9snxDLi.mjs → inspect.handler-BE6coOuW.mjs} +24 -13
- package/dist/{integration-catalog-CiZ62hb_.mjs → integration-catalog-pSmWHFLQ.mjs} +3 -3
- package/dist/{integrations-MEExmqcg.mjs → integrations-DZD5t8n2.mjs} +7 -7
- package/dist/{invites-BuatfJmN.mjs → invites-BuR1H-tA.mjs} +5 -5
- package/dist/{invites.list.handler-CK6mL10z.mjs → invites.list.handler-Dj4a6XOg.mjs} +6 -5
- package/dist/{invites.resend.handler-CKZouK1Z.mjs → invites.resend.handler-DEGF4vlB.mjs} +6 -5
- package/dist/{invites.revoke.handler-H0VI-3sp.mjs → invites.revoke.handler-Dg4ZvlFS.mjs} +6 -5
- package/dist/keystroke.mjs +122 -77
- package/dist/{list-enrichment-DP1wEyBZ.mjs → list-enrichment-dqbkXJzy.mjs} +2 -2
- package/dist/{list.handler-LxZInip2.mjs → list.handler-2g1CZAvB.mjs} +4 -4
- package/dist/{list.handler-BKfGLkFu.mjs → list.handler-7MkJfkak.mjs} +5 -5
- package/dist/list.handler-BTYVIn6z.mjs +39 -0
- package/dist/{list.handler-BiY5NFWd.mjs → list.handler-Bchcr3-e.mjs} +3 -3
- package/dist/list.handler-Choc4SZz.mjs +64 -0
- package/dist/{list.handler-Jk_vK66s.mjs → list.handler-D47C1z3m.mjs} +4 -4
- package/dist/{list.handler-DVnFrlis.mjs → list.handler-DYE48apa.mjs} +7 -7
- package/dist/{list.handler-DIMWZx78.mjs → list.handler-KcCaG3PZ.mjs} +4 -4
- package/dist/list2.handler-BIaIyrQf.mjs +99 -0
- package/dist/{listen-C_7Rgwkb.mjs → listen-CVY-_F29.mjs} +3 -3
- package/dist/{listen.handler-dJgorIzr.mjs → listen.handler-D_nEvXRn.mjs} +4 -4
- package/dist/{logs-B9YMhUGt.mjs → logs-CZ2qnsSH.mjs} +3 -3
- package/dist/{logs.handler-BfjCsAyq.mjs → logs.handler-BRUzZC9Z.mjs} +26 -29
- package/dist/{logs.handler-DGGVPMOX.mjs → logs.handler-Wk6mYyAZ.mjs} +1 -1
- package/dist/{members.add.handler-DSRCRxsI.mjs → members.add.handler-BJ0wr6rP.mjs} +6 -5
- package/dist/{members.invite.handler-BNpHn1dY.mjs → members.invite.handler-DyveDMuq.mjs} +6 -5
- package/dist/{members.list.handler-Bn9LJEPG.mjs → members.list.handler-CyQxH_zS.mjs} +6 -5
- package/dist/{members.remove.handler-Dkr2t_tX.mjs → members.remove.handler-Dtv9PooY.mjs} +6 -5
- package/dist/{members.update.handler-DBtUYuAY.mjs → members.update.handler-CeK-tCjT.mjs} +6 -5
- package/dist/{operations-AWMLs6mE.mjs → operations-CxQlt0S0.mjs} +5 -5
- package/dist/{org-DOH7YHk2.mjs → org-B8MPHJJu.mjs} +35 -28
- package/dist/org-context-BI9OSpbb.mjs +112 -0
- package/dist/org-output-DffU7DKn.mjs +64 -0
- package/dist/{orgs.create.handler-BO70zIdp.mjs → orgs.create.handler-BKvSmkU3.mjs} +4 -4
- package/dist/{orgs.get.handler-BuGg5bc9.mjs → orgs.get.handler-BA-CexIY.mjs} +4 -4
- package/dist/{orgs.list.handler--5HutMkl.mjs → orgs.list.handler-eCEg5kC1.mjs} +4 -4
- package/dist/{output-BWcVRt-T.mjs → output-DnIFEmi5.mjs} +1 -1
- package/dist/package-manager-BP3-q8hh.mjs +162 -0
- package/dist/{paused.handler-DHvxz-cC.mjs → paused.handler-4wKMTKZ-.mjs} +20 -33
- package/dist/{projects-C5GZ5Jrf.mjs → projects-Wu_2fB_x.mjs} +11 -9
- package/dist/{register.handler-CePNU3sP.mjs → register.handler-BvAkXCwE.mjs} +2 -2
- package/dist/{render-credential-Bn15FEUC.mjs → render-credential-D-H1ECDt.mjs} +1 -1
- package/dist/{render-operation-Bc7Wu1sP.mjs → render-operation-VdEPhoII.mjs} +2 -2
- package/dist/{requirements.handler-B5rqCjMu.mjs → requirements.handler-Bab4kBtw.mjs} +7 -7
- package/dist/{resolve-cli-credentials-CAOSVMJP.mjs → resolve-cli-credentials-GVOOedoQ.mjs} +1 -1
- package/dist/{resolve-project-E9mrh_el.mjs → resolve-project-DLKlAy0z.mjs} +24 -8
- package/dist/{run-polling-DawiBus-.mjs → run-polling-C5fI7xTp.mjs} +97 -14
- package/dist/{run.handler-BG7xitEK.mjs → run.handler-BKD5Xu0A.mjs} +42 -30
- package/dist/{runs-swYYBT6C.mjs → runs-CT31dczt.mjs} +4 -4
- package/dist/{schema-display-FvI8QjOQ.mjs → schema-display-sZ6ConJd.mjs} +33 -26
- package/dist/schemas-ClAIoIrX.mjs +281 -0
- package/dist/{search-BEfy2fG9.mjs → search-BeQW_pf4.mjs} +3 -3
- package/dist/{search.handler-V7ObLGjN.mjs → search.handler-BJ-ZlDL4.mjs} +6 -6
- package/dist/{show.handler-C_VDYU91.mjs → show.handler-BrIHUH28.mjs} +4 -4
- package/dist/{show.handler-CsidInW8.mjs → show.handler-Cqe_hCqU.mjs} +5 -5
- package/dist/{show.handler-Wmv0tkxx.mjs → show.handler-DB8xl5FU.mjs} +6 -6
- package/dist/{skill-installer-D6j9IA3Z.mjs → skill-installer-DuMhavmM.mjs} +3 -1
- package/dist/{skills-sync.handler-BAATdT6N.mjs → skills-sync.handler-BGs-_YD9.mjs} +13 -7
- package/dist/{skills.command-0-E8mcYE.mjs → skills.command-DUWn6FbL.mjs} +5 -5
- package/dist/skills.handler-DqLXJepA.mjs +9 -0
- package/dist/{spinner-progress-lrKDs4YF.mjs → spinner-progress-BYxlr3lY.mjs} +1 -1
- package/dist/status.handler-DAId4bVU.mjs +72 -0
- package/dist/{switch.handler-BwYndsP-.mjs → switch.handler-Cd4Yg2n8.mjs} +17 -4
- package/dist/{sync-6fZkIUtn.mjs → sync-DgC4lcxh.mjs} +2 -2
- package/dist/{sync.handler-Ctr-cN9X.mjs → sync.handler-Cm_WtGmH.mjs} +8 -8
- package/dist/{task-BWuIKWh4.mjs → task-DTvLzUkA.mjs} +2 -88
- package/dist/{task-target-build-QllcCfoN.mjs → task-target-build-CtvRyVjH.mjs} +5 -5
- package/dist/task-target-deploy-runner.mjs +6 -6
- package/dist/{test-C8VIZe9V.mjs → test-4V7nh67i.mjs} +5 -5
- package/dist/{test.handler-BCW0YBPd.mjs → test.handler-BdCYcwR4.mjs} +2 -2
- package/dist/{test.handler-DLaxrJ9V.mjs → test.handler-Bo4YTs2Z.mjs} +19 -16
- package/dist/{tool.handler-8qNmgdRe.mjs → tool.handler-CPCrSDq2.mjs} +12 -12
- package/dist/{trigger-artifacts-BcRScRSp-BiD2h6do.mjs → trigger-artifacts-BcRScRSp-BRpU-He5.mjs} +2 -2
- package/dist/{trigger-manifest-C07EM-b2.mjs → trigger-manifest-BVqjDhxU.mjs} +1 -1
- package/dist/{upgrade-DgOcc8IT.mjs → upgrade-2qUOcjxb.mjs} +4 -8
- package/dist/upgrade.handler-PqlKSuUE.mjs +99 -0
- package/dist/{upload.handler-B7xle1oX.mjs → upload.handler-CS-vLpzC.mjs} +9 -9
- package/dist/{users.get.handler-C4t1vXwi.mjs → users.get.handler-CH1c6Lnj.mjs} +4 -4
- package/dist/{users.list.handler-Dvl90grq.mjs → users.list.handler-CxbZFgjO.mjs} +4 -4
- package/dist/{users.set-role.handler-Djw1_VGf.mjs → users.set-role.handler-CBRE-Ws6.mjs} +4 -4
- package/dist/{validate.handler-Drf_lssw.mjs → validate.handler-1d-UmtXB.mjs} +171 -26
- package/dist/{workflow-build-Begvjfq8.mjs → workflow-build-Bm8JoVv4.mjs} +234 -32
- package/dist/{workflow-build-manifest-1sC52TIG.mjs → workflow-build-manifest-CV6bBmDO.mjs} +1 -1
- package/dist/{workflow-bundler-BzHk73PM-muPv1yGG.mjs → workflow-bundler-Bs3zQNQv-Dy7lXxy3.mjs} +15 -4
- package/dist/{workflows-DjMlxuBX.mjs → workflows-ny7rOdeH.mjs} +34 -37
- package/dist/{writer-byNNUjRm-B-on1n6c.mjs → writer-BLg0RuZa-Y6ExdYH9.mjs} +6 -4
- package/package.json +11 -11
- package/dist/current-deployment-workflow-B1VQCYC-.mjs +0 -94
- package/dist/current.handler-BaGaCLzB.mjs +0 -21
- package/dist/list.handler-BEMj3FyH.mjs +0 -76
- package/dist/list.handler-Cq_oQY5B.mjs +0 -52
- package/dist/list.handler-htR9TeiS.mjs +0 -24
- package/dist/package-manager-DT1EhOkS.mjs +0 -61
- package/dist/schemas-D2zfmyC-.mjs +0 -671
- package/dist/skills.handler-DYIQK0Vu.mjs +0 -9
- package/dist/status.handler-Ch_DtyBp.mjs +0 -109
- package/dist/upgrade.handler-DSZuw7-9.mjs +0 -80
- /package/dist/{build-metadata-BB_L45ZS-DSJL7dTy.mjs → build-metadata-BB_L45ZS-DRQsV6JK.mjs} +0 -0
- /package/dist/{deploy-DhCbYFc7.mjs → deploy-BiKBH25R.mjs} +0 -0
- /package/dist/{detect-env-access-CwkOYeYM-COq4U-4Y.mjs → detect-env-access-CwkOYeYM-r4aynBU0.mjs} +0 -0
- /package/dist/{read-credential-keys-77a91T8M-DGK5XTQp.mjs → read-credential-keys-77a91T8M-I07NYwfH.mjs} +0 -0
- /package/dist/{run-polling-fBouPjJ2.mjs → run-polling-1c0ckC1A.mjs} +0 -0
- /package/dist/{schemas-4Mq_bxob.mjs → schemas-8nhXlXWh.mjs} +0 -0
- /package/dist/{task-target-deploy-B_3HPSo2.mjs → task-target-deploy-m9LfE488.mjs} +0 -0
- /package/dist/{types-AlA-ifK9.mjs → types-Cb0eWmUU.mjs} +0 -0
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { t as createTypedCommand } from "./commander-
|
|
3
|
+
import { t as createTypedCommand } from "./commander-C6SSTQJ2.mjs";
|
|
4
|
+
import { t as PackageManagerValues } from "./package-manager-BP3-q8hh.mjs";
|
|
4
5
|
import { z } from "zod";
|
|
5
6
|
//#region src/commands/upgrade/upgrade.command.ts
|
|
6
|
-
const PackageManagerSchema = z.enum(
|
|
7
|
-
"npm",
|
|
8
|
-
"pnpm",
|
|
9
|
-
"yarn",
|
|
10
|
-
"bun"
|
|
11
|
-
]);
|
|
7
|
+
const PackageManagerSchema = z.enum(PackageManagerValues);
|
|
12
8
|
const UpgradeOptionsSchema = z.object({
|
|
13
9
|
packageManager: PackageManagerSchema.default("npm").describe("Package manager to use"),
|
|
14
10
|
to: z.string().min(1).default("latest").describe("Package version or dist tag to install"),
|
|
@@ -34,7 +30,7 @@ function createUpgradeCommand() {
|
|
|
34
30
|
description: "Upgrade the Keystroke CLI to the latest published version",
|
|
35
31
|
schema: UpgradeOptionsSchema,
|
|
36
32
|
optionsConfig: UPGRADE_OPTIONS_CONFIG,
|
|
37
|
-
loadHandler: async () => (await import("./upgrade.handler-
|
|
33
|
+
loadHandler: async () => (await import("./upgrade.handler-PqlKSuUE.mjs")).handleUpgrade
|
|
38
34
|
});
|
|
39
35
|
}
|
|
40
36
|
//#endregion
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { N as throwReportedCliExit, a as CLI_PACKAGE_NAME, k as CliExitError, p as ui, x as toErrorMessage } from "./keystroke.mjs";
|
|
4
|
+
import { a as readYarnMajorVersion } from "./package-manager-BP3-q8hh.mjs";
|
|
5
|
+
import { spawn } from "node:child_process";
|
|
6
|
+
//#region src/commands/upgrade/upgrade.handler.ts
|
|
7
|
+
function buildUpgradeCommand(options) {
|
|
8
|
+
const { packageManager, to } = options;
|
|
9
|
+
const packageSpec = `${CLI_PACKAGE_NAME}@${to}`;
|
|
10
|
+
if (packageManager === "npm") return {
|
|
11
|
+
command: "npm",
|
|
12
|
+
args: [
|
|
13
|
+
"install",
|
|
14
|
+
"--global",
|
|
15
|
+
packageSpec
|
|
16
|
+
]
|
|
17
|
+
};
|
|
18
|
+
else if (packageManager === "pnpm") return {
|
|
19
|
+
command: "pnpm",
|
|
20
|
+
args: [
|
|
21
|
+
"add",
|
|
22
|
+
"--global",
|
|
23
|
+
packageSpec
|
|
24
|
+
]
|
|
25
|
+
};
|
|
26
|
+
else if (packageManager === "yarn") return {
|
|
27
|
+
command: "yarn",
|
|
28
|
+
args: [
|
|
29
|
+
"global",
|
|
30
|
+
"add",
|
|
31
|
+
packageSpec
|
|
32
|
+
]
|
|
33
|
+
};
|
|
34
|
+
else if (packageManager === "bun") return {
|
|
35
|
+
command: "bun",
|
|
36
|
+
args: [
|
|
37
|
+
"add",
|
|
38
|
+
"--global",
|
|
39
|
+
packageSpec
|
|
40
|
+
]
|
|
41
|
+
};
|
|
42
|
+
else return assertNever(packageManager);
|
|
43
|
+
}
|
|
44
|
+
function renderUpgradeCommand(upgradeCommand) {
|
|
45
|
+
return [upgradeCommand.command, ...upgradeCommand.args].map(shellToken).join(" ");
|
|
46
|
+
}
|
|
47
|
+
async function handleUpgrade(options, _ctx) {
|
|
48
|
+
const { packageManager, dryRun, to } = options;
|
|
49
|
+
await assertYarnClassicSupported(packageManager);
|
|
50
|
+
const upgradeCommand = buildUpgradeCommand({
|
|
51
|
+
packageManager,
|
|
52
|
+
to,
|
|
53
|
+
dryRun
|
|
54
|
+
});
|
|
55
|
+
const renderedCommand = renderUpgradeCommand(upgradeCommand);
|
|
56
|
+
if (dryRun) {
|
|
57
|
+
ui.text(renderedCommand);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
ui.header(`Upgrading Keystroke CLI with ${packageManager}...`);
|
|
61
|
+
ui.hint(renderedCommand);
|
|
62
|
+
const exitCode = await runCommand(upgradeCommand);
|
|
63
|
+
if (exitCode !== 0) throwReportedCliExit(`CLI upgrade failed with exit code ${exitCode}.`);
|
|
64
|
+
ui.success("Keystroke CLI upgrade complete.");
|
|
65
|
+
}
|
|
66
|
+
async function assertYarnClassicSupported(packageManager) {
|
|
67
|
+
if (packageManager === "npm") return;
|
|
68
|
+
if (packageManager === "pnpm") return;
|
|
69
|
+
if (packageManager === "bun") return;
|
|
70
|
+
if (packageManager === "yarn") {
|
|
71
|
+
const yarnMajor = await readYarnMajorVersion();
|
|
72
|
+
if (yarnMajor !== null && yarnMajor !== 1) throwReportedCliExit("Yarn 2+ does not support `yarn global add`. Use `--package-manager npm` or `--package-manager pnpm` instead.");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
return assertNever(packageManager);
|
|
76
|
+
}
|
|
77
|
+
function runCommand({ command, args }) {
|
|
78
|
+
return new Promise((resolve, reject) => {
|
|
79
|
+
const child = spawn(command, args, {
|
|
80
|
+
stdio: "inherit",
|
|
81
|
+
shell: process.platform === "win32"
|
|
82
|
+
});
|
|
83
|
+
child.on("error", (error) => {
|
|
84
|
+
reject(new CliExitError(`Failed to start upgrade command: ${toErrorMessage(error)}`, {
|
|
85
|
+
cause: error,
|
|
86
|
+
reported: true
|
|
87
|
+
}));
|
|
88
|
+
});
|
|
89
|
+
child.on("close", (code) => resolve(code ?? 1));
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function shellToken(value) {
|
|
93
|
+
return /^[A-Za-z0-9_./:@=-]+$/.test(value) ? value : `'${value.replaceAll("'", "'\\''")}'`;
|
|
94
|
+
}
|
|
95
|
+
function assertNever(value) {
|
|
96
|
+
throw new Error(`Unsupported package manager: ${String(value)}`);
|
|
97
|
+
}
|
|
98
|
+
//#endregion
|
|
99
|
+
export { handleUpgrade };
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { N as throwReportedCliExit, c as getProcessEnv, p as ui, x as toErrorMessage } from "./keystroke.mjs";
|
|
4
4
|
import { t as assertWorkflowProjectRoot } from "./project-config-DudGRFPO.mjs";
|
|
5
|
-
import { a as writeJsonError, i as writeJson } from "./output-
|
|
6
|
-
import { i as requireClient } from "./context-
|
|
7
|
-
import { a as readManifestsFromOutDir, t as collectCredentialFingerprintMapFromProjectDist } from "./dist-
|
|
8
|
-
import { t as requireWorkflowsDir } from "./resolve-project-
|
|
9
|
-
import { t as getIntegrationCatalog } from "./integration-catalog-
|
|
10
|
-
import { t as readCredentialEnvMap } from "./credential-env-map-
|
|
11
|
-
import { a as verifyCredentialResolvable, i as validateManualCredentialWithHook, n as resolveCredentialValuesFromEnv, r as uploadCredential, t as groupCredentialRequirements } from "./credentials-
|
|
12
|
-
import { n as renderCredentialSchemaMismatchText, r as writeCredentialSchemaMismatchJson, t as isCredentialSchemaMismatchErrorLike } from "./credential-schema-mismatch-
|
|
5
|
+
import { a as writeJsonError, i as writeJson } from "./output-DnIFEmi5.mjs";
|
|
6
|
+
import { i as requireClient } from "./context-ebZssGCY.mjs";
|
|
7
|
+
import { a as readManifestsFromOutDir, t as collectCredentialFingerprintMapFromProjectDist } from "./dist-BmbFJq8U.mjs";
|
|
8
|
+
import { t as requireWorkflowsDir } from "./resolve-project-DLKlAy0z.mjs";
|
|
9
|
+
import { t as getIntegrationCatalog } from "./integration-catalog-pSmWHFLQ.mjs";
|
|
10
|
+
import { t as readCredentialEnvMap } from "./credential-env-map-5a41jLwM.mjs";
|
|
11
|
+
import { a as verifyCredentialResolvable, i as validateManualCredentialWithHook, n as resolveCredentialValuesFromEnv, r as uploadCredential, t as groupCredentialRequirements } from "./credentials-DtwLbee6.mjs";
|
|
12
|
+
import { n as renderCredentialSchemaMismatchText, r as writeCredentialSchemaMismatchJson, t as isCredentialSchemaMismatchErrorLike } from "./credential-schema-mismatch-c17ktoNU.mjs";
|
|
13
13
|
import * as path$1 from "node:path";
|
|
14
14
|
import { confirm, isCancel } from "@clack/prompts";
|
|
15
15
|
//#region src/commands/credentials/upload/upload.handler.ts
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { i as writeJson } from "./output-
|
|
5
|
-
import { i as requireClient } from "./context-
|
|
6
|
-
import { n as isIamJsonMode, t as handleIamError } from "./iam-command-utils-
|
|
3
|
+
import { p as ui } from "./keystroke.mjs";
|
|
4
|
+
import { i as writeJson } from "./output-DnIFEmi5.mjs";
|
|
5
|
+
import { i as requireClient } from "./context-ebZssGCY.mjs";
|
|
6
|
+
import { n as isIamJsonMode, t as handleIamError } from "./iam-command-utils-DNDN0wT6.mjs";
|
|
7
7
|
//#region src/commands/admin/users.get.handler.ts
|
|
8
8
|
async function handleAdminUsersGet(options, ctx) {
|
|
9
9
|
const client = requireClient(ctx);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { i as writeJson } from "./output-
|
|
5
|
-
import { i as requireClient } from "./context-
|
|
6
|
-
import { n as isIamJsonMode, t as handleIamError } from "./iam-command-utils-
|
|
3
|
+
import { p as ui } from "./keystroke.mjs";
|
|
4
|
+
import { i as writeJson } from "./output-DnIFEmi5.mjs";
|
|
5
|
+
import { i as requireClient } from "./context-ebZssGCY.mjs";
|
|
6
|
+
import { n as isIamJsonMode, t as handleIamError } from "./iam-command-utils-DNDN0wT6.mjs";
|
|
7
7
|
import Table from "cli-table3";
|
|
8
8
|
//#region src/commands/admin/users.list.handler.ts
|
|
9
9
|
async function handleAdminUsersList(options, ctx) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { i as writeJson } from "./output-
|
|
5
|
-
import { i as requireClient } from "./context-
|
|
6
|
-
import { n as isIamJsonMode, r as requireConfirmation, t as handleIamError } from "./iam-command-utils-
|
|
3
|
+
import { p as ui } from "./keystroke.mjs";
|
|
4
|
+
import { i as writeJson } from "./output-DnIFEmi5.mjs";
|
|
5
|
+
import { i as requireClient } from "./context-ebZssGCY.mjs";
|
|
6
|
+
import { n as isIamJsonMode, r as requireConfirmation, t as handleIamError } from "./iam-command-utils-DNDN0wT6.mjs";
|
|
7
7
|
//#region src/commands/admin/users.set-role.handler.ts
|
|
8
8
|
async function handleAdminUsersSetRole(options, ctx) {
|
|
9
9
|
const client = requireClient(ctx);
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { i as projects } from "./dist-
|
|
5
|
-
import { i as writeJson } from "./output-
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { t as
|
|
3
|
+
import { N as throwReportedCliExit, p as ui, x as toErrorMessage } from "./keystroke.mjs";
|
|
4
|
+
import { i as projects } from "./dist-B5jy238v.mjs";
|
|
5
|
+
import { i as writeJson } from "./output-DnIFEmi5.mjs";
|
|
6
|
+
import { a as readManifestsFromOutDir } from "./dist-BmbFJq8U.mjs";
|
|
7
|
+
import { t as requireWorkflowsDir } from "./resolve-project-DLKlAy0z.mjs";
|
|
8
|
+
import { c as build, s as typecheckWorkflows, t as WorkflowNotFoundError } from "./workflow-build-Bm8JoVv4.mjs";
|
|
9
|
+
import { t as createBuildProgress } from "./build-progress-CM-b6Bby.mjs";
|
|
10
|
+
import { n as assertAuthoredWorkflowId, t as WORKFLOW_ID_COMMANDS } from "./authored-workflow-ref-fkHEEVnd.mjs";
|
|
9
11
|
import * as path$1 from "node:path";
|
|
10
12
|
import * as os from "node:os";
|
|
11
|
-
import { mkdtemp, rm } from "node:fs/promises";
|
|
13
|
+
import { mkdtemp, readFile, readdir, rm } from "node:fs/promises";
|
|
12
14
|
//#region src/commands/workflows/validate/workflow-validate.ts
|
|
13
|
-
/**
|
|
14
|
-
* workflow-validate.ts
|
|
15
|
-
*
|
|
16
|
-
* Validation-only build: runs analysis phases without
|
|
17
|
-
* writing any permanent output artifacts. Uses a temp dir cleaned up afterwards.
|
|
18
|
-
*/
|
|
19
15
|
var WorkflowValidationFailedError = class extends Error {
|
|
20
16
|
result;
|
|
21
17
|
constructor(result) {
|
|
@@ -42,12 +38,13 @@ async function runWorkflowValidate(options) {
|
|
|
42
38
|
});
|
|
43
39
|
}
|
|
44
40
|
const totalMs = Date.now() - startTime;
|
|
45
|
-
let result = mapBuildResultToValidateResult(buildResult, totalMs);
|
|
41
|
+
let result = await mapBuildResultToValidateResult(buildResult, totalMs);
|
|
42
|
+
if (options.typecheck !== false) result = await appendTypecheckToValidateResult(result, options.workflowsDir);
|
|
46
43
|
result = filterValidationResult(result, options.workflow);
|
|
47
44
|
if (!result.success) throw new WorkflowValidationFailedError(result);
|
|
48
45
|
return result;
|
|
49
46
|
}
|
|
50
|
-
function mapBuildResultToValidateResult(buildResult, totalMs) {
|
|
47
|
+
async function mapBuildResultToValidateResult(buildResult, totalMs) {
|
|
51
48
|
const workflowMap = /* @__PURE__ */ new Map();
|
|
52
49
|
for (const artifact of buildResult.artifacts) workflowMap.set(artifact.manifest.id, {
|
|
53
50
|
id: artifact.manifest.id,
|
|
@@ -56,6 +53,7 @@ function mapBuildResultToValidateResult(buildResult, totalMs) {
|
|
|
56
53
|
issues: []
|
|
57
54
|
});
|
|
58
55
|
for (const failure of buildResult.failures) appendFailureIssue(workflowMap, failure);
|
|
56
|
+
await enrichAuthoredWorkflowIds(workflowMap);
|
|
59
57
|
if (buildResult.warnings.length > 0) workflowMap.set("__project__", {
|
|
60
58
|
name: "project",
|
|
61
59
|
filePath: "",
|
|
@@ -79,11 +77,13 @@ function mapBuildResultToValidateResult(buildResult, totalMs) {
|
|
|
79
77
|
function appendFailureIssue(workflowMap, failure) {
|
|
80
78
|
if (failure.kind === "workflow" || failure.kind === "loader-protocol") {
|
|
81
79
|
const key = failure.workflow.resolvedFilePath;
|
|
82
|
-
const
|
|
83
|
-
|
|
80
|
+
const authoredId = failure.workflow.workflowId ?? resolveAuthoredIdFromWorkflowMap(workflowMap, failure.workflow.resolvedFilePath);
|
|
81
|
+
const existing = workflowMap.get(key) ?? workflowMap.get(authoredId ?? "") ?? createWorkflowValidateStats({
|
|
82
|
+
id: authoredId,
|
|
84
83
|
name: path$1.basename(failure.workflow.resolvedFilePath, path$1.extname(failure.workflow.resolvedFilePath)),
|
|
85
84
|
filePath: failure.workflow.resolvedFilePath
|
|
86
85
|
});
|
|
86
|
+
if (!existing.id && authoredId) existing.id = authoredId;
|
|
87
87
|
existing.issues.push({
|
|
88
88
|
severity: "error",
|
|
89
89
|
file: failure.workflow.resolvedFilePath,
|
|
@@ -142,6 +142,7 @@ function appendFailureIssue(workflowMap, failure) {
|
|
|
142
142
|
if (failure.kind === "trigger") {
|
|
143
143
|
const key = `trigger:${failure.workflowId}:${failure.triggerExportName}`;
|
|
144
144
|
const existing = workflowMap.get(key) ?? createWorkflowValidateStats({
|
|
145
|
+
id: failure.workflowId,
|
|
145
146
|
name: failure.triggerId,
|
|
146
147
|
filePath: ""
|
|
147
148
|
});
|
|
@@ -198,6 +199,136 @@ function appendFailureIssue(workflowMap, failure) {
|
|
|
198
199
|
});
|
|
199
200
|
workflowMap.set(key, existing);
|
|
200
201
|
}
|
|
202
|
+
function resolveAuthoredIdFromWorkflowMap(workflowMap, filePath) {
|
|
203
|
+
for (const stats of workflowMap.values()) if (stats.id && stats.filePath === filePath) return stats.id;
|
|
204
|
+
}
|
|
205
|
+
const AUTHORED_WORKFLOW_ID_PATTERN = /\bid:\s*['"]([^'"]+)['"]/;
|
|
206
|
+
async function readAuthoredWorkflowIdFromSource(filePath) {
|
|
207
|
+
const source = await readFile(filePath, "utf-8").catch(() => null);
|
|
208
|
+
if (!source) return;
|
|
209
|
+
return AUTHORED_WORKFLOW_ID_PATTERN.exec(source)?.[1];
|
|
210
|
+
}
|
|
211
|
+
async function collectWorkflowTypeScriptFiles(projectRoot) {
|
|
212
|
+
const workflowsRoot = path$1.join(projectRoot, "workflows");
|
|
213
|
+
const files = [];
|
|
214
|
+
async function walk(dir) {
|
|
215
|
+
let entries = [];
|
|
216
|
+
try {
|
|
217
|
+
entries = await readdir(dir, {
|
|
218
|
+
withFileTypes: true,
|
|
219
|
+
encoding: "utf8"
|
|
220
|
+
});
|
|
221
|
+
} catch {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
for (const entry of entries) {
|
|
225
|
+
if (entry.name === "node_modules" || entry.name === "dist") continue;
|
|
226
|
+
const fullPath = path$1.join(dir, entry.name);
|
|
227
|
+
if (entry.isDirectory()) await walk(fullPath);
|
|
228
|
+
else if (entry.isFile() && /\.tsx?$/.test(entry.name)) files.push(fullPath);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
await walk(workflowsRoot);
|
|
232
|
+
return files;
|
|
233
|
+
}
|
|
234
|
+
function findWorkflowStatsForDiagnosticFile(workflowMap, diagnosticFile) {
|
|
235
|
+
const resolvedFile = path$1.resolve(diagnosticFile);
|
|
236
|
+
for (const stats of workflowMap.values()) {
|
|
237
|
+
if (!stats.filePath) continue;
|
|
238
|
+
const workflowFile = path$1.resolve(stats.filePath);
|
|
239
|
+
const workflowDir = path$1.dirname(workflowFile);
|
|
240
|
+
if (resolvedFile === workflowFile || resolvedFile.startsWith(`${workflowDir}${path$1.sep}`)) return stats;
|
|
241
|
+
}
|
|
242
|
+
const fallback = createWorkflowValidateStats({
|
|
243
|
+
name: path$1.basename(resolvedFile, path$1.extname(resolvedFile)),
|
|
244
|
+
filePath: resolvedFile
|
|
245
|
+
});
|
|
246
|
+
workflowMap.set(resolvedFile, fallback);
|
|
247
|
+
return fallback;
|
|
248
|
+
}
|
|
249
|
+
function appendTypecheckDiagnostic(workflowMap, diagnostic) {
|
|
250
|
+
if (!diagnostic.file) {
|
|
251
|
+
const projectStats = workflowMap.get("__project__") ?? createWorkflowValidateStats({
|
|
252
|
+
name: "project",
|
|
253
|
+
filePath: ""
|
|
254
|
+
});
|
|
255
|
+
projectStats.issues.push({
|
|
256
|
+
severity: diagnostic.severity,
|
|
257
|
+
message: diagnostic.message,
|
|
258
|
+
type: "analysis"
|
|
259
|
+
});
|
|
260
|
+
workflowMap.set("__project__", projectStats);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
findWorkflowStatsForDiagnosticFile(workflowMap, diagnostic.file).issues.push({
|
|
264
|
+
severity: diagnostic.severity,
|
|
265
|
+
file: path$1.resolve(diagnostic.file),
|
|
266
|
+
line: diagnostic.line,
|
|
267
|
+
message: diagnostic.message,
|
|
268
|
+
type: "analysis"
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
async function appendTypecheckToValidateResult(result, projectRoot) {
|
|
272
|
+
const workflowMap = /* @__PURE__ */ new Map();
|
|
273
|
+
for (const workflow of result.workflows) {
|
|
274
|
+
const key = workflow.id ?? (workflow.filePath ? `file:${workflow.filePath}` : `name:${workflow.name}`);
|
|
275
|
+
workflowMap.set(key, workflow);
|
|
276
|
+
}
|
|
277
|
+
const files = await collectWorkflowTypeScriptFiles(projectRoot);
|
|
278
|
+
if (files.length === 0) return result;
|
|
279
|
+
try {
|
|
280
|
+
const typecheckResult = await typecheckWorkflows({
|
|
281
|
+
projectRoot,
|
|
282
|
+
files
|
|
283
|
+
});
|
|
284
|
+
if (typecheckResult.toolFailure) {
|
|
285
|
+
const projectStats = workflowMap.get("__project__") ?? createWorkflowValidateStats({
|
|
286
|
+
name: "project",
|
|
287
|
+
filePath: ""
|
|
288
|
+
});
|
|
289
|
+
projectStats.issues.push({
|
|
290
|
+
severity: "error",
|
|
291
|
+
message: typecheckResult.toolFailure.message,
|
|
292
|
+
type: "other"
|
|
293
|
+
});
|
|
294
|
+
workflowMap.set("__project__", projectStats);
|
|
295
|
+
}
|
|
296
|
+
for (const diagnostic of typecheckResult.diagnostics) appendTypecheckDiagnostic(workflowMap, diagnostic);
|
|
297
|
+
} catch (error) {
|
|
298
|
+
const projectStats = workflowMap.get("__project__") ?? createWorkflowValidateStats({
|
|
299
|
+
name: "project",
|
|
300
|
+
filePath: ""
|
|
301
|
+
});
|
|
302
|
+
projectStats.issues.push({
|
|
303
|
+
severity: "error",
|
|
304
|
+
message: toErrorMessage(error),
|
|
305
|
+
type: "other"
|
|
306
|
+
});
|
|
307
|
+
workflowMap.set("__project__", projectStats);
|
|
308
|
+
}
|
|
309
|
+
await enrichAuthoredWorkflowIds(workflowMap);
|
|
310
|
+
const workflows = [...workflowMap.values()];
|
|
311
|
+
const errorCount = workflows.reduce((count, workflow) => count + workflow.issues.filter((issue) => issue.severity === "error").length, 0);
|
|
312
|
+
const warningCount = workflows.reduce((count, workflow) => count + workflow.issues.filter((issue) => issue.severity === "warning").length, 0);
|
|
313
|
+
return {
|
|
314
|
+
...result,
|
|
315
|
+
success: errorCount === 0,
|
|
316
|
+
workflows,
|
|
317
|
+
errorCount,
|
|
318
|
+
warningCount
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
async function enrichAuthoredWorkflowIds(workflowMap) {
|
|
322
|
+
for (const stats of workflowMap.values()) {
|
|
323
|
+
if (stats.id || !stats.filePath) continue;
|
|
324
|
+
const fromArtifacts = resolveAuthoredIdFromWorkflowMap(workflowMap, stats.filePath);
|
|
325
|
+
if (fromArtifacts) {
|
|
326
|
+
stats.id = fromArtifacts;
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
stats.id = await readAuthoredWorkflowIdFromSource(stats.filePath);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
201
332
|
function createWorkflowValidateStats(stats) {
|
|
202
333
|
return {
|
|
203
334
|
id: stats.id,
|
|
@@ -206,14 +337,19 @@ function createWorkflowValidateStats(stats) {
|
|
|
206
337
|
issues: []
|
|
207
338
|
};
|
|
208
339
|
}
|
|
340
|
+
/** Matches an authored workflow id or failures scoped to that workflow's source tree. */
|
|
341
|
+
function workflowMatchesValidateRef(workflow, workflowRef) {
|
|
342
|
+
if (workflow.id === workflowRef) return true;
|
|
343
|
+
if (!workflow.filePath) return false;
|
|
344
|
+
const normalizedRef = workflowRef.replaceAll("\\", "/");
|
|
345
|
+
const normalizedPath = workflow.filePath.replaceAll("\\", "/");
|
|
346
|
+
if (normalizedPath.includes(`/${normalizedRef}/`) || normalizedPath.endsWith(`/${normalizedRef}.workflow.ts`)) return true;
|
|
347
|
+
return path$1.basename(normalizedPath, path$1.extname(normalizedPath)) === normalizedRef;
|
|
348
|
+
}
|
|
209
349
|
function filterValidationResult(result, workflowRef) {
|
|
210
350
|
if (!workflowRef) return result;
|
|
211
|
-
const matching = result.workflows.filter((workflow) =>
|
|
212
|
-
if (matching.length === 0)
|
|
213
|
-
const availableNames = result.workflows.map((workflow) => workflow.name).filter((name) => name !== "project");
|
|
214
|
-
const availableIds = result.workflows.map((workflow) => workflow.id).filter((id) => id !== void 0);
|
|
215
|
-
throw new WorkflowNotFoundError(workflowRef, availableNames.length > 0 ? availableNames : availableIds);
|
|
216
|
-
}
|
|
351
|
+
const matching = result.workflows.filter((workflow) => workflowMatchesValidateRef(workflow, workflowRef));
|
|
352
|
+
if (matching.length === 0) throw new WorkflowNotFoundError(workflowRef, [...new Set(result.workflows.map((workflow) => workflow.id).filter((id) => id !== void 0))]);
|
|
217
353
|
return {
|
|
218
354
|
...result,
|
|
219
355
|
success: matching.every((workflow) => workflow.issues.every((issue) => issue.severity !== "error")),
|
|
@@ -232,6 +368,10 @@ function renderValidateSummary(result) {
|
|
|
232
368
|
ui.success(`Validation passed — ${workflowLabel}, ${result.errorCount} errors, ${result.warningCount} warnings`);
|
|
233
369
|
}
|
|
234
370
|
}
|
|
371
|
+
function formatValidateWorkflowLabel(workflow) {
|
|
372
|
+
if (workflow.id) return `workflow id: ${workflow.id}`;
|
|
373
|
+
return `workflow: ${workflow.name}`;
|
|
374
|
+
}
|
|
235
375
|
function renderValidateFailure(error, asJson) {
|
|
236
376
|
if (error instanceof WorkflowValidationFailedError) {
|
|
237
377
|
if (!asJson) {
|
|
@@ -239,15 +379,15 @@ function renderValidateFailure(error, asJson) {
|
|
|
239
379
|
for (const workflow of error.result.workflows) for (const issue of workflow.issues.filter((i) => i.severity === "error")) {
|
|
240
380
|
const loc = issue.file ? issue.line !== void 0 ? `${issue.file}:${issue.line}` : issue.file : "";
|
|
241
381
|
ui.hint(` ${loc ? `${loc} — ` : ""}${issue.message}`);
|
|
242
|
-
ui.hint(`
|
|
382
|
+
ui.hint(` ${formatValidateWorkflowLabel(workflow)}`);
|
|
243
383
|
ui.hint(` type: ${issue.type}`);
|
|
244
384
|
}
|
|
245
385
|
} else writeJson(error.result);
|
|
246
386
|
return;
|
|
247
387
|
}
|
|
248
388
|
if (error instanceof WorkflowNotFoundError) {
|
|
249
|
-
ui.error(`Workflow "${error.
|
|
250
|
-
if (error.
|
|
389
|
+
ui.error(`Workflow "${error.workflowRef}" not found.`);
|
|
390
|
+
if (error.availableIds.length > 0) ui.hint(`Available workflow ids: ${error.availableIds.join(", ")}`);
|
|
251
391
|
return;
|
|
252
392
|
}
|
|
253
393
|
ui.error(`Validation error: ${toErrorMessage(error)}`);
|
|
@@ -257,6 +397,10 @@ function renderValidateFailure(error, asJson) {
|
|
|
257
397
|
async function handleWorkflowsValidate(options, ctx) {
|
|
258
398
|
const workflowsDir = await requireWorkflowsDir(options.path);
|
|
259
399
|
projects.track(workflowsDir);
|
|
400
|
+
if (options.workflow) {
|
|
401
|
+
const manifests = await readManifestsFromOutDir(workflowsDir);
|
|
402
|
+
await assertAuthoredWorkflowId(options.workflow, workflowsDir, WORKFLOW_ID_COMMANDS.validate, { refreshManifests: manifests.length === 0 });
|
|
403
|
+
}
|
|
260
404
|
const { jsonMode } = ctx;
|
|
261
405
|
renderValidateHeader(options.workflow);
|
|
262
406
|
const progress = createBuildProgress(options.workflow ?? "all workflows");
|
|
@@ -264,6 +408,7 @@ async function handleWorkflowsValidate(options, ctx) {
|
|
|
264
408
|
const result = await runWorkflowValidate({
|
|
265
409
|
workflowsDir,
|
|
266
410
|
verbose: options.verbose,
|
|
411
|
+
typecheck: options.typecheck,
|
|
267
412
|
workflow: options.workflow,
|
|
268
413
|
onProgressEvent: progress.handleEvent
|
|
269
414
|
});
|