@keystrokehq/cli 0.0.1
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/AGENTS-blurb.md +123 -0
- package/LICENSE +42 -0
- package/README.md +177 -0
- package/THIRD_PARTY_NOTICES.md +16 -0
- package/bin/keystroke.mjs +107 -0
- package/dist/_manifest-JSRE3H8k.mjs +385 -0
- package/dist/agent-bundle-package-DWV6B_5q-BtV7Xycc.mjs +2344 -0
- package/dist/agent-manifest-CDnbkR2f.mjs +245 -0
- package/dist/agents-CZJGxVqV.mjs +228 -0
- package/dist/api-keys-D2lgguuY.mjs +40 -0
- package/dist/auth-DN2VusyU.mjs +59 -0
- package/dist/auth.handler-CT1BQUvu.mjs +340 -0
- package/dist/browser-qwFrUH82.mjs +24 -0
- package/dist/build-agents-BmM_AsSd-BGi9wtzt.mjs +514 -0
- package/dist/build-metadata-BWS7uhd_-DR8gJjTX.mjs +1422 -0
- package/dist/build-progress-DgYKb4hB.mjs +183 -0
- package/dist/build-tasks-CdihpudT-D5r5HUHe.mjs +91 -0
- package/dist/build-workflows-CfxBnIWh-CdYPv8w2.mjs +370 -0
- package/dist/build.handler-4799CjWH.mjs +36 -0
- package/dist/chunk-CH6r78ws.mjs +37 -0
- package/dist/clear-cache.handler-B9tqSoSM.mjs +11 -0
- package/dist/clear.handler-BTIXXPTJ.mjs +42 -0
- package/dist/clear.handler-BydlX-zE.mjs +11 -0
- package/dist/commander-DfTVqQ-3.mjs +133 -0
- package/dist/concurrency-gXn9Rw8x-DNl2YtrS.mjs +20 -0
- package/dist/connect-BUXkeH0F.mjs +43 -0
- package/dist/connect.handler-CYel9cy6.mjs +430 -0
- package/dist/constants-CPpPdSNg.mjs +8 -0
- package/dist/context-T7HZuB97.mjs +138 -0
- package/dist/credential-env-map-CI8yWHVy.mjs +28 -0
- package/dist/credential-schema-mismatch-BKo5PjcQ.mjs +76 -0
- package/dist/credentials-CvmjU0lK.mjs +171 -0
- package/dist/credentials-OfVHOtG3.mjs +151216 -0
- package/dist/current-deployment-workflow-poHt27i3.mjs +94 -0
- package/dist/current.handler-B8zKzfPp.mjs +21 -0
- package/dist/delete.handler-bAu1iXVQ.mjs +17 -0
- package/dist/deploy-7Jjls436.mjs +26 -0
- package/dist/deploy-BOPIpRWm.mjs +74 -0
- package/dist/deploy-progress-BmGUNFKg.mjs +70 -0
- package/dist/deploy.handler-BAzgiNhd.mjs +370 -0
- package/dist/detect-env-access-CwkOYeYM-D_BCZqV6.mjs +209 -0
- package/dist/diff-utils-NEfcjqxt.mjs +185 -0
- package/dist/diff.handler-Du7SY8K4.mjs +47 -0
- package/dist/dist-BkJUoBiG.mjs +1116 -0
- package/dist/dist-CUK7yBM0.mjs +308 -0
- package/dist/env-91KwMKov.mjs +140 -0
- package/dist/env.handler-BAzBuMzQ.mjs +277 -0
- package/dist/error-boundary-VL-JLfIa.mjs +34 -0
- package/dist/file-metadata-D1vm-XY2.mjs +191 -0
- package/dist/get-intrinsic-zLxwtrLK.mjs +658 -0
- package/dist/import-module-CV84H5fZ-B_CBCmb4.mjs +1747 -0
- package/dist/init-DpMCotSK.mjs +45 -0
- package/dist/init.handler-CPRnif52.mjs +585 -0
- package/dist/inspect.handler-DT_cD036.mjs +146 -0
- package/dist/integration-catalog-Bt-L3GjF.mjs +104 -0
- package/dist/integrations-DlatPK4W.mjs +79 -0
- package/dist/keystroke.d.mts +3 -0
- package/dist/keystroke.mjs +707 -0
- package/dist/layout-CbMtQ2tm.mjs +67 -0
- package/dist/list-enrichment-y-cwizLr.mjs +189 -0
- package/dist/list.handler-BTWvCyjA.mjs +52 -0
- package/dist/list.handler-CWF_Dj15.mjs +24 -0
- package/dist/list.handler-CZ6G2x_G.mjs +75 -0
- package/dist/list.handler-DWaQkJaR.mjs +51 -0
- package/dist/list.handler-DqbFcBW7.mjs +180 -0
- package/dist/list.handler-lq3ZGAn4.mjs +104 -0
- package/dist/logs-BEg9L5l8.mjs +28 -0
- package/dist/logs.handler-6hoMBzqw.mjs +35 -0
- package/dist/logs.handler-BD_dXiL1.mjs +231 -0
- package/dist/metadata-layout-GUYIUo0i-_aG2zjue.mjs +5877 -0
- package/dist/normalize-path-CojS-CgQ-DLCOvnD1.mjs +20 -0
- package/dist/options-CeaTcFxP.mjs +43 -0
- package/dist/org-xLzBtt2_.mjs +41 -0
- package/dist/output-DM4b7KgY.mjs +72 -0
- package/dist/oxc-B3KI3rf_-n9d1hKNq.mjs +119 -0
- package/dist/paused.handler-BMFm9Cff.mjs +94 -0
- package/dist/project-config-D1qsQlO7.mjs +107 -0
- package/dist/projects-CHkRE9rS.mjs +1574 -0
- package/dist/projects-Cjb7sovS.mjs +30 -0
- package/dist/read-credential-keys-77a91T8M-KA0Iw0Z1.mjs +9 -0
- package/dist/register.handler-BPCdor1_.mjs +86 -0
- package/dist/requirements.handler-DPXdSks3.mjs +201 -0
- package/dist/resolve-project-DDJ29sCF.mjs +35 -0
- package/dist/rolldown-runtime-twds-ZHy-BWWzu8VG.mjs +15 -0
- package/dist/run-polling-CAgFRdK3.mjs +20 -0
- package/dist/runs-D9hNLb9A.mjs +259 -0
- package/dist/schedule-BXx3uXwr.mjs +1142 -0
- package/dist/schema-17qMfNyI.mjs +18 -0
- package/dist/schema-display-CgmeKigW.mjs +130 -0
- package/dist/schemas-CDib1RhE.mjs +125 -0
- package/dist/skills-sync.handler-DIy8GR16.mjs +34 -0
- package/dist/skills.command-CrjI2dN9.mjs +35 -0
- package/dist/skills.handler-Bz8bJKql.mjs +9 -0
- package/dist/source-analysis-Cj-ADyu--BJQcFPCG.mjs +144 -0
- package/dist/spinner-progress-DMVwgqO9.mjs +173 -0
- package/dist/src-C0X6u_Mw.mjs +1340 -0
- package/dist/src-eHwu-Gfw.mjs +369 -0
- package/dist/status.handler-BO4nwvWn.mjs +101 -0
- package/dist/switch.handler-D_9213Vf.mjs +51 -0
- package/dist/sync-BL_Mo5st.mjs +39 -0
- package/dist/sync-keystroke-agent-skills-Kx_H7UTd.mjs +70 -0
- package/dist/sync.handler-BUFPdzWz.mjs +82 -0
- package/dist/task-B2sZMaZu.mjs +8 -0
- package/dist/task-target-build-CBeCKbu2.mjs +432 -0
- package/dist/task-target-deploy-C5X-USeR.mjs +4 -0
- package/dist/task-target-deploy-CA6elFpF-BEr4gkol.mjs +271 -0
- package/dist/task-target-deploy-runner.d.mts +3 -0
- package/dist/task-target-deploy-runner.mjs +202 -0
- package/dist/test-BHTgR3UA.mjs +698 -0
- package/dist/test.handler-BcPQ8b74.mjs +13 -0
- package/dist/trigger-artifacts-DQPbQNqC-B4yeeFBY.mjs +239 -0
- package/dist/trigger-manifest-CY7brZeg.mjs +30 -0
- package/dist/try-deploy.handler-DqybNhXx.mjs +490 -0
- package/dist/upload-CkU--iDC.mjs +207 -0
- package/dist/upload.handler-DCtiznQp.mjs +441 -0
- package/dist/utils-CywxCDM7.mjs +14 -0
- package/dist/validate.handler-DOcTaJL0.mjs +280 -0
- package/dist/workflow-build-DBQaBfnn.mjs +1819 -0
- package/dist/workflow-bundler-BPiqVscj-X1PFFAuP.mjs +167 -0
- package/dist/workflows-g9z87AJJ.mjs +799 -0
- package/dist/writer-BG8poUm3-BbXlU2kI.mjs +426 -0
- package/package.json +87 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { D as throwReportedCliExit, h as toErrorMessage, t as ui } from "./keystroke.mjs";
|
|
4
|
+
import { d as trackProject } from "./dist-CUK7yBM0.mjs";
|
|
5
|
+
import { i as writeJson } from "./output-DM4b7KgY.mjs";
|
|
6
|
+
import { t as requireWorkflowsDir } from "./resolve-project-DDJ29sCF.mjs";
|
|
7
|
+
import { s as build, t as WorkflowNotFoundError } from "./workflow-build-DBQaBfnn.mjs";
|
|
8
|
+
import { t as createBuildProgress } from "./build-progress-DgYKb4hB.mjs";
|
|
9
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
10
|
+
import * as os from "node:os";
|
|
11
|
+
import * as path$1 from "node:path";
|
|
12
|
+
//#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
|
+
var WorkflowValidationFailedError = class extends Error {
|
|
20
|
+
result;
|
|
21
|
+
constructor(result) {
|
|
22
|
+
super(`Validation failed with ${result.errorCount} error(s).`);
|
|
23
|
+
this.name = "WorkflowValidationFailedError";
|
|
24
|
+
this.result = result;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
async function runWorkflowValidate(options) {
|
|
28
|
+
const startTime = Date.now();
|
|
29
|
+
const tmpDir = await mkdtemp(path$1.join(os.tmpdir(), "keystroke-validate-"));
|
|
30
|
+
let buildResult;
|
|
31
|
+
try {
|
|
32
|
+
buildResult = await build({
|
|
33
|
+
projectRoot: options.workflowsDir,
|
|
34
|
+
outDir: tmpDir,
|
|
35
|
+
force: true,
|
|
36
|
+
onProgressEvent: options.onProgressEvent
|
|
37
|
+
});
|
|
38
|
+
} finally {
|
|
39
|
+
await rm(tmpDir, {
|
|
40
|
+
recursive: true,
|
|
41
|
+
force: true
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const totalMs = Date.now() - startTime;
|
|
45
|
+
let result = mapBuildResultToValidateResult(buildResult, totalMs);
|
|
46
|
+
result = filterValidationResult(result, options.workflow);
|
|
47
|
+
if (!result.success) throw new WorkflowValidationFailedError(result);
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
function mapBuildResultToValidateResult(buildResult, totalMs) {
|
|
51
|
+
const workflowMap = /* @__PURE__ */ new Map();
|
|
52
|
+
for (const artifact of buildResult.artifacts) workflowMap.set(artifact.manifest.id, {
|
|
53
|
+
id: artifact.manifest.id,
|
|
54
|
+
name: artifact.manifest.name,
|
|
55
|
+
filePath: artifact.workflow.resolvedFilePath,
|
|
56
|
+
issues: []
|
|
57
|
+
});
|
|
58
|
+
for (const failure of buildResult.failures) appendFailureIssue(workflowMap, failure);
|
|
59
|
+
if (buildResult.warnings.length > 0) workflowMap.set("__project__", {
|
|
60
|
+
name: "project",
|
|
61
|
+
filePath: "",
|
|
62
|
+
issues: buildResult.warnings.map((warning) => ({
|
|
63
|
+
severity: "warning",
|
|
64
|
+
message: warning,
|
|
65
|
+
type: "other"
|
|
66
|
+
}))
|
|
67
|
+
});
|
|
68
|
+
const workflows = [...workflowMap.values()];
|
|
69
|
+
const errorCount = workflows.reduce((count, workflow) => count + workflow.issues.filter((issue) => issue.severity === "error").length, 0);
|
|
70
|
+
const warningCount = workflows.reduce((count, workflow) => count + workflow.issues.filter((issue) => issue.severity === "warning").length, 0);
|
|
71
|
+
return {
|
|
72
|
+
success: errorCount === 0,
|
|
73
|
+
workflows,
|
|
74
|
+
errorCount,
|
|
75
|
+
warningCount,
|
|
76
|
+
totalMs
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function appendFailureIssue(workflowMap, failure) {
|
|
80
|
+
if (failure.kind === "workflow" || failure.kind === "loader-protocol") {
|
|
81
|
+
const key = failure.workflow.resolvedFilePath;
|
|
82
|
+
const existing = workflowMap.get(key) ?? workflowMap.get(failure.workflow.workflowId ?? "") ?? createWorkflowValidateStats({
|
|
83
|
+
id: failure.workflow.workflowId,
|
|
84
|
+
name: path$1.basename(failure.workflow.resolvedFilePath, path$1.extname(failure.workflow.resolvedFilePath)),
|
|
85
|
+
filePath: failure.workflow.resolvedFilePath
|
|
86
|
+
});
|
|
87
|
+
existing.issues.push({
|
|
88
|
+
severity: "error",
|
|
89
|
+
file: failure.workflow.resolvedFilePath,
|
|
90
|
+
message: failure.error,
|
|
91
|
+
type: "analysis"
|
|
92
|
+
});
|
|
93
|
+
workflowMap.set(key, existing);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (failure.kind === "duplicate-workflow-id") {
|
|
97
|
+
const key = `duplicate:${failure.workflowId}`;
|
|
98
|
+
const existing = workflowMap.get(key) ?? createWorkflowValidateStats({
|
|
99
|
+
id: failure.workflowId,
|
|
100
|
+
name: failure.workflowId,
|
|
101
|
+
filePath: failure.files[0] ?? ""
|
|
102
|
+
});
|
|
103
|
+
existing.issues.push({
|
|
104
|
+
severity: "error",
|
|
105
|
+
file: failure.files[0],
|
|
106
|
+
message: failure.error,
|
|
107
|
+
type: "analysis"
|
|
108
|
+
});
|
|
109
|
+
workflowMap.set(key, existing);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (failure.kind === "duplicate-agent-id") {
|
|
113
|
+
const key = `duplicate-agent:${failure.agentId}`;
|
|
114
|
+
const existing = workflowMap.get(key) ?? createWorkflowValidateStats({
|
|
115
|
+
name: failure.agentId,
|
|
116
|
+
filePath: failure.files[0] ?? ""
|
|
117
|
+
});
|
|
118
|
+
existing.issues.push({
|
|
119
|
+
severity: "error",
|
|
120
|
+
file: failure.files[0],
|
|
121
|
+
message: failure.error,
|
|
122
|
+
type: "analysis"
|
|
123
|
+
});
|
|
124
|
+
workflowMap.set(key, existing);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (failure.kind === "agent-cycle") {
|
|
128
|
+
const key = `agent-cycle:${failure.cyclePath.join(">")}`;
|
|
129
|
+
const existing = workflowMap.get(key) ?? createWorkflowValidateStats({
|
|
130
|
+
name: "Agent cycle",
|
|
131
|
+
filePath: ""
|
|
132
|
+
});
|
|
133
|
+
existing.issues.push({
|
|
134
|
+
severity: "error",
|
|
135
|
+
file: void 0,
|
|
136
|
+
message: failure.error,
|
|
137
|
+
type: "analysis"
|
|
138
|
+
});
|
|
139
|
+
workflowMap.set(key, existing);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (failure.kind === "trigger") {
|
|
143
|
+
const key = `trigger:${failure.workflowId}:${failure.triggerExportName}`;
|
|
144
|
+
const existing = workflowMap.get(key) ?? createWorkflowValidateStats({
|
|
145
|
+
name: failure.triggerName,
|
|
146
|
+
filePath: ""
|
|
147
|
+
});
|
|
148
|
+
existing.issues.push({
|
|
149
|
+
severity: "error",
|
|
150
|
+
file: void 0,
|
|
151
|
+
message: failure.error,
|
|
152
|
+
type: "analysis"
|
|
153
|
+
});
|
|
154
|
+
workflowMap.set(key, existing);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (failure.kind === "task") {
|
|
158
|
+
const key = `task:${failure.task.taskId}`;
|
|
159
|
+
const existing = workflowMap.get(key) ?? createWorkflowValidateStats({
|
|
160
|
+
name: failure.task.taskId,
|
|
161
|
+
filePath: failure.task.resolvedFilePath
|
|
162
|
+
});
|
|
163
|
+
existing.issues.push({
|
|
164
|
+
severity: "error",
|
|
165
|
+
file: failure.task.resolvedFilePath,
|
|
166
|
+
message: failure.error,
|
|
167
|
+
type: "analysis"
|
|
168
|
+
});
|
|
169
|
+
workflowMap.set(key, existing);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (failure.kind === "agent") {
|
|
173
|
+
const key = `agent:${failure.agent.agentId}`;
|
|
174
|
+
const existing = workflowMap.get(key) ?? createWorkflowValidateStats({
|
|
175
|
+
name: failure.agent.agentName,
|
|
176
|
+
filePath: failure.agent.resolvedFilePath
|
|
177
|
+
});
|
|
178
|
+
existing.issues.push({
|
|
179
|
+
severity: "error",
|
|
180
|
+
file: failure.agent.resolvedFilePath,
|
|
181
|
+
message: failure.error,
|
|
182
|
+
type: "analysis"
|
|
183
|
+
});
|
|
184
|
+
workflowMap.set(key, existing);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const filePath = "filePath" in failure ? failure.filePath : "";
|
|
188
|
+
const key = `discovery:${filePath}`;
|
|
189
|
+
const existing = workflowMap.get(key) ?? createWorkflowValidateStats({
|
|
190
|
+
name: path$1.basename(filePath, path$1.extname(filePath)),
|
|
191
|
+
filePath
|
|
192
|
+
});
|
|
193
|
+
existing.issues.push({
|
|
194
|
+
severity: "error",
|
|
195
|
+
file: filePath,
|
|
196
|
+
message: failure.error,
|
|
197
|
+
type: "analysis"
|
|
198
|
+
});
|
|
199
|
+
workflowMap.set(key, existing);
|
|
200
|
+
}
|
|
201
|
+
function createWorkflowValidateStats(stats) {
|
|
202
|
+
return {
|
|
203
|
+
id: stats.id,
|
|
204
|
+
name: stats.name,
|
|
205
|
+
filePath: stats.filePath,
|
|
206
|
+
issues: []
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function filterValidationResult(result, workflowRef) {
|
|
210
|
+
if (!workflowRef) return result;
|
|
211
|
+
const matching = result.workflows.filter((workflow) => workflow.id === workflowRef || workflow.name === workflowRef || path$1.basename(workflow.filePath, path$1.extname(workflow.filePath)) === workflowRef);
|
|
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
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
...result,
|
|
219
|
+
success: matching.every((workflow) => workflow.issues.every((issue) => issue.severity !== "error")),
|
|
220
|
+
workflows: matching,
|
|
221
|
+
errorCount: matching.reduce((count, workflow) => count + workflow.issues.filter((issue) => issue.severity === "error").length, 0),
|
|
222
|
+
warningCount: matching.reduce((count, workflow) => count + workflow.issues.filter((issue) => issue.severity === "warning").length, 0)
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function renderValidateHeader(name) {
|
|
226
|
+
if (name) ui.header(`Validating workflow "${name}"...`);
|
|
227
|
+
else ui.header("Validating workflows...");
|
|
228
|
+
}
|
|
229
|
+
function renderValidateSummary(result) {
|
|
230
|
+
if (result.success) {
|
|
231
|
+
const workflowLabel = result.workflows.length === 1 ? "1 workflow" : `${result.workflows.length} workflows`;
|
|
232
|
+
ui.success(`Validation passed — ${workflowLabel}, ${result.errorCount} errors, ${result.warningCount} warnings`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function renderValidateFailure(error, asJson) {
|
|
236
|
+
if (error instanceof WorkflowValidationFailedError) {
|
|
237
|
+
if (!asJson) {
|
|
238
|
+
ui.error(`Validation failed with ${error.result.errorCount} error(s):`);
|
|
239
|
+
for (const workflow of error.result.workflows) for (const issue of workflow.issues.filter((i) => i.severity === "error")) {
|
|
240
|
+
const loc = issue.file ? issue.line !== void 0 ? `${issue.file}:${issue.line}` : issue.file : "";
|
|
241
|
+
ui.hint(` ${loc ? `${loc} — ` : ""}${issue.message}`);
|
|
242
|
+
ui.hint(` workflow: ${workflow.name}`);
|
|
243
|
+
ui.hint(` type: ${issue.type}`);
|
|
244
|
+
}
|
|
245
|
+
} else writeJson(error.result);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (error instanceof WorkflowNotFoundError) {
|
|
249
|
+
ui.error(`Workflow "${error.workflowName}" not found.`);
|
|
250
|
+
if (error.availableNames.length > 0) ui.hint(`Available: ${error.availableNames.join(", ")}`);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
ui.error(`Validation error: ${toErrorMessage(error)}`);
|
|
254
|
+
}
|
|
255
|
+
//#endregion
|
|
256
|
+
//#region src/commands/workflows/validate/validate.handler.ts
|
|
257
|
+
async function handleWorkflowsValidate(options, ctx) {
|
|
258
|
+
const workflowsDir = await requireWorkflowsDir(options.path);
|
|
259
|
+
trackProject(workflowsDir);
|
|
260
|
+
const { jsonMode } = ctx;
|
|
261
|
+
renderValidateHeader(options.workflow);
|
|
262
|
+
const progress = createBuildProgress(options.workflow ?? "all workflows");
|
|
263
|
+
try {
|
|
264
|
+
const result = await runWorkflowValidate({
|
|
265
|
+
workflowsDir,
|
|
266
|
+
verbose: options.verbose,
|
|
267
|
+
workflow: options.workflow,
|
|
268
|
+
onProgressEvent: progress.handleEvent
|
|
269
|
+
});
|
|
270
|
+
if (jsonMode) writeJson(result);
|
|
271
|
+
else renderValidateSummary(result);
|
|
272
|
+
} catch (error) {
|
|
273
|
+
renderValidateFailure(error, jsonMode);
|
|
274
|
+
throwReportedCliExit("Workflow validation failed.", { cause: error });
|
|
275
|
+
} finally {
|
|
276
|
+
progress.stop();
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
//#endregion
|
|
280
|
+
export { handleWorkflowsValidate };
|