@decantr/cli 1.10.0 → 2.1.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/README.md +4 -1
- package/dist/bin.js +3 -3
- package/dist/{chunk-FLZVSNB5.js → chunk-5QM6XDZU.js} +3230 -3077
- package/dist/{chunk-K5KCZSEI.js → chunk-KGEEYXSU.js} +87 -9
- package/dist/{chunk-USOO77A5.js → chunk-WDA4SHIQ.js} +190 -283
- package/dist/{chunk-RSDCWAHD.js → chunk-X2HIXQAY.js} +9 -6
- package/dist/{chunk-DI2PLOJ6.js → chunk-ZUUJ24YU.js} +418 -180
- package/dist/{heal-5JHGCLDX.js → heal-MQ56WYX4.js} +2 -2
- package/dist/{health-SIKAOE2Z.js → health-DCT625XN.js} +3 -3
- package/dist/index.js +3 -3
- package/dist/{studio-EQSSNA6D.js → studio-CI7OOGHV.js} +21 -4
- package/dist/{upgrade-4NRDVD5N.js → upgrade-PL755AF7.js} +21 -41
- package/package.json +7 -7
- package/src/templates/decantr-health.workflow.yml.template +5 -5
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
collectCheckIssues
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-X2HIXQAY.js";
|
|
4
|
+
import {
|
|
5
|
+
sendProjectHealthCiFailedTelemetry,
|
|
6
|
+
sendProjectHealthPromptTelemetry,
|
|
7
|
+
sendProjectHealthReportTelemetry
|
|
8
|
+
} from "./chunk-ZUUJ24YU.js";
|
|
4
9
|
|
|
5
10
|
// src/commands/health.ts
|
|
6
11
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -62,7 +67,7 @@ function normalizeCliPackageSpecifier(version) {
|
|
|
62
67
|
const versionToken = value.startsWith("@decantr/cli@") ? value.slice("@decantr/cli@".length) : value;
|
|
63
68
|
if (!/^[A-Za-z0-9._~^*-]+$/.test(versionToken)) {
|
|
64
69
|
throw new Error(
|
|
65
|
-
"Invalid --cli-version value. Use a package version or dist-tag such as latest,
|
|
70
|
+
"Invalid --cli-version value. Use a package version or dist-tag such as latest, 2.0.0, or next."
|
|
66
71
|
);
|
|
67
72
|
}
|
|
68
73
|
return `@decantr/cli@${versionToken}`;
|
|
@@ -92,17 +97,45 @@ function validateArtifactPath(value, flag) {
|
|
|
92
97
|
}
|
|
93
98
|
return normalized;
|
|
94
99
|
}
|
|
100
|
+
function validateProjectPath(value) {
|
|
101
|
+
if (value === void 0) return void 0;
|
|
102
|
+
const raw = value.trim();
|
|
103
|
+
if (!raw || raw === ".") return void 0;
|
|
104
|
+
const normalized = raw.replace(/^\.\/+/, "").replace(/\/+$/, "");
|
|
105
|
+
if (!normalized || normalized.startsWith("/") || normalized.startsWith("-") || normalized.includes("..") || normalized.includes("\\") || /\s/.test(normalized) || !/^[A-Za-z0-9._@/-]+$/.test(normalized)) {
|
|
106
|
+
throw new Error(
|
|
107
|
+
"Invalid --project value. Use a relative project path without spaces or parent-directory segments."
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
const segments = normalized.split("/");
|
|
111
|
+
if (segments.some((segment) => !segment || segment === "." || segment === "..")) {
|
|
112
|
+
throw new Error(
|
|
113
|
+
"Invalid --project value. Use a relative project path without empty or parent-directory segments."
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
return normalized;
|
|
117
|
+
}
|
|
118
|
+
function prefixArtifactPath(projectPath, artifactPath) {
|
|
119
|
+
return projectPath ? `${projectPath}/${artifactPath}` : artifactPath;
|
|
120
|
+
}
|
|
95
121
|
function renderProjectHealthCiWorkflow(options = {}) {
|
|
96
122
|
const failOn = normalizeHealthFailOn(options.failOn);
|
|
123
|
+
const projectPath = validateProjectPath(options.projectPath);
|
|
124
|
+
const reportPath = validateArtifactPath(
|
|
125
|
+
options.reportPath || DEFAULT_HEALTH_CI_REPORT_PATH,
|
|
126
|
+
"--report-path"
|
|
127
|
+
);
|
|
128
|
+
const jsonPath = validateArtifactPath(options.jsonPath || DEFAULT_HEALTH_CI_JSON_PATH, "--json-path");
|
|
97
129
|
const template = loadHealthTemplate("decantr-health.workflow.yml.template");
|
|
98
130
|
return renderTemplate(template, {
|
|
99
131
|
CLI_PACKAGE: normalizeCliPackageSpecifier(options.cliVersion),
|
|
100
132
|
FAIL_ON: failOn,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
133
|
+
PROJECT_WORKING_DIRECTORY: projectPath ? ` working-directory: ${projectPath}
|
|
134
|
+
` : "",
|
|
135
|
+
REPORT_PATH: reportPath,
|
|
136
|
+
JSON_PATH: jsonPath,
|
|
137
|
+
REPORT_ARTIFACT_PATH: prefixArtifactPath(projectPath, reportPath),
|
|
138
|
+
JSON_ARTIFACT_PATH: prefixArtifactPath(projectPath, jsonPath)
|
|
106
139
|
});
|
|
107
140
|
}
|
|
108
141
|
function writeProjectHealthCiWorkflow(projectRoot, options = {}) {
|
|
@@ -118,12 +151,15 @@ function writeProjectHealthCiWorkflow(projectRoot, options = {}) {
|
|
|
118
151
|
}
|
|
119
152
|
mkdirSync(dirname(workflowPath), { recursive: true });
|
|
120
153
|
writeFileSync(workflowPath, renderProjectHealthCiWorkflow(options), "utf-8");
|
|
121
|
-
|
|
154
|
+
const projectPath = validateProjectPath(options.projectPath);
|
|
155
|
+
const result = {
|
|
122
156
|
path: workflowRelativePath,
|
|
123
157
|
created: !alreadyExists,
|
|
124
158
|
cliPackage: normalizeCliPackageSpecifier(options.cliVersion),
|
|
125
159
|
failOn: normalizeHealthFailOn(options.failOn)
|
|
126
160
|
};
|
|
161
|
+
if (projectPath) result.projectPath = projectPath;
|
|
162
|
+
return result;
|
|
127
163
|
}
|
|
128
164
|
function collectDeclaredRoutes(essence) {
|
|
129
165
|
if (!essence || typeof essence !== "object") return [];
|
|
@@ -490,6 +526,9 @@ async function cmdHealth(projectRoot = process.cwd(), options = {}) {
|
|
|
490
526
|
const action = result.created ? "Created" : "Updated";
|
|
491
527
|
console.log(`${GREEN}${action} Decantr Project Health workflow:${RESET} ${result.path}`);
|
|
492
528
|
console.log(`${DIM}CLI package: ${result.cliPackage}${RESET}`);
|
|
529
|
+
if (result.projectPath) {
|
|
530
|
+
console.log(`${DIM}Project: ${result.projectPath}${RESET}`);
|
|
531
|
+
}
|
|
493
532
|
console.log(`${DIM}CI gate: decantr health --ci --fail-on ${result.failOn}${RESET}`);
|
|
494
533
|
} catch (e) {
|
|
495
534
|
console.error(`${RED}${e.message}${RESET}`);
|
|
@@ -497,9 +536,22 @@ async function cmdHealth(projectRoot = process.cwd(), options = {}) {
|
|
|
497
536
|
}
|
|
498
537
|
return;
|
|
499
538
|
}
|
|
539
|
+
const startedAt = Date.now();
|
|
500
540
|
const report = await createProjectHealthReport(projectRoot);
|
|
501
541
|
if (options.promptId) {
|
|
502
542
|
const finding = report.findings.find((entry) => entry.id === options.promptId);
|
|
543
|
+
await sendProjectHealthReportTelemetry({
|
|
544
|
+
ci: options.ci ?? false,
|
|
545
|
+
durationMs: Date.now() - startedAt,
|
|
546
|
+
projectRoot,
|
|
547
|
+
report
|
|
548
|
+
});
|
|
549
|
+
await sendProjectHealthPromptTelemetry({
|
|
550
|
+
ci: options.ci ?? false,
|
|
551
|
+
finding,
|
|
552
|
+
projectRoot,
|
|
553
|
+
report
|
|
554
|
+
});
|
|
503
555
|
if (!finding) {
|
|
504
556
|
console.error(`${RED}No health finding found for id: ${options.promptId}${RESET}`);
|
|
505
557
|
process.exitCode = 1;
|
|
@@ -509,6 +561,7 @@ async function cmdHealth(projectRoot = process.cwd(), options = {}) {
|
|
|
509
561
|
return;
|
|
510
562
|
}
|
|
511
563
|
const format = resolveFormat(options);
|
|
564
|
+
const failOn = options.failOn ?? "error";
|
|
512
565
|
const payload = format === "json" ? formatProjectHealthJson(report) : format === "markdown" ? formatProjectHealthMarkdown(report) : formatProjectHealthText(report);
|
|
513
566
|
if (options.output) {
|
|
514
567
|
writeFileSync(options.output, payload, "utf-8");
|
|
@@ -518,7 +571,27 @@ async function cmdHealth(projectRoot = process.cwd(), options = {}) {
|
|
|
518
571
|
} else {
|
|
519
572
|
process.stdout.write(payload);
|
|
520
573
|
}
|
|
521
|
-
|
|
574
|
+
await sendProjectHealthReportTelemetry({
|
|
575
|
+
ci: options.ci ?? false,
|
|
576
|
+
durationMs: Date.now() - startedAt,
|
|
577
|
+
failOn,
|
|
578
|
+
format,
|
|
579
|
+
outputWritten: Boolean(options.output),
|
|
580
|
+
projectRoot,
|
|
581
|
+
report
|
|
582
|
+
});
|
|
583
|
+
if (options.ci && shouldFailHealth(report, failOn)) {
|
|
584
|
+
if (failOn !== "none") {
|
|
585
|
+
await sendProjectHealthCiFailedTelemetry({
|
|
586
|
+
ci: true,
|
|
587
|
+
durationMs: Date.now() - startedAt,
|
|
588
|
+
failOn,
|
|
589
|
+
format,
|
|
590
|
+
outputWritten: Boolean(options.output),
|
|
591
|
+
projectRoot,
|
|
592
|
+
report
|
|
593
|
+
});
|
|
594
|
+
}
|
|
522
595
|
process.exitCode = 1;
|
|
523
596
|
}
|
|
524
597
|
}
|
|
@@ -552,9 +625,14 @@ function parseHealthArgs(args) {
|
|
|
552
625
|
options.initCi.jsonPath = args[++index];
|
|
553
626
|
} else if (arg.startsWith("--json-path=")) {
|
|
554
627
|
options.initCi.jsonPath = arg.split("=")[1];
|
|
628
|
+
} else if (arg === "--project" && args[index + 1]) {
|
|
629
|
+
options.initCi.projectPath = args[++index];
|
|
630
|
+
} else if (arg.startsWith("--project=")) {
|
|
631
|
+
options.initCi.projectPath = arg.split("=")[1];
|
|
555
632
|
}
|
|
556
633
|
}
|
|
557
634
|
normalizeHealthFailOn(options.initCi.failOn);
|
|
635
|
+
validateProjectPath(options.initCi.projectPath);
|
|
558
636
|
return options;
|
|
559
637
|
}
|
|
560
638
|
for (let index = 1; index < args.length; index += 1) {
|