@driftdev/cli 0.42.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/drift.js +80 -33
- package/package.json +2 -2
package/dist/drift.js
CHANGED
|
@@ -578,7 +578,7 @@ function formatOutput(command, data, startTime, version, humanRenderer, next) {
|
|
|
578
578
|
...next ? { next } : {}
|
|
579
579
|
};
|
|
580
580
|
if (humanRenderer && shouldRenderHuman()) {
|
|
581
|
-
process.stdout.write(humanRenderer(data));
|
|
581
|
+
process.stdout.write(humanRenderer(data, next));
|
|
582
582
|
process.stdout.write(`
|
|
583
583
|
`);
|
|
584
584
|
} else {
|
|
@@ -589,12 +589,16 @@ function formatOutput(command, data, startTime, version, humanRenderer, next) {
|
|
|
589
589
|
}
|
|
590
590
|
return envelope;
|
|
591
591
|
}
|
|
592
|
-
function formatError(command, error, startTime, version) {
|
|
592
|
+
function formatError(command, error, startTime, version, suggestion) {
|
|
593
593
|
const duration = Date.now() - startTime;
|
|
594
594
|
if (shouldRenderHuman()) {
|
|
595
595
|
process.stdout.write(`
|
|
596
596
|
${c.red("x")} ${error}
|
|
597
|
-
|
|
597
|
+
`);
|
|
598
|
+
if (suggestion)
|
|
599
|
+
process.stdout.write(` ${c.gray(suggestion)}
|
|
600
|
+
`);
|
|
601
|
+
process.stdout.write(`
|
|
598
602
|
`);
|
|
599
603
|
} else {
|
|
600
604
|
const envelope = {
|
|
@@ -609,6 +613,15 @@ function formatError(command, error, startTime, version) {
|
|
|
609
613
|
}
|
|
610
614
|
process.exitCode = 1;
|
|
611
615
|
}
|
|
616
|
+
function formatWarning(message) {
|
|
617
|
+
if (shouldRenderHuman()) {
|
|
618
|
+
process.stderr.write(` ${c.yellow("!")} ${message}
|
|
619
|
+
`);
|
|
620
|
+
} else {
|
|
621
|
+
process.stderr.write(`warning: ${message}
|
|
622
|
+
`);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
612
625
|
|
|
613
626
|
// src/utils/resolve-specs.ts
|
|
614
627
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
@@ -845,35 +858,43 @@ function filterPublic(packages) {
|
|
|
845
858
|
// src/utils/detect-entry.ts
|
|
846
859
|
function detectEntry(cwd = process.cwd()) {
|
|
847
860
|
const pkgPath = path6.join(cwd, "package.json");
|
|
861
|
+
const tried = [];
|
|
862
|
+
function tryResolve(source, filePath) {
|
|
863
|
+
const resolved = resolveToSource(cwd, filePath);
|
|
864
|
+
if (resolved)
|
|
865
|
+
return resolved;
|
|
866
|
+
tried.push(`${source}: ${filePath} -> not found`);
|
|
867
|
+
return null;
|
|
868
|
+
}
|
|
848
869
|
if (existsSync6(pkgPath)) {
|
|
849
870
|
try {
|
|
850
871
|
const pkg = JSON.parse(readFileSync4(pkgPath, "utf-8"));
|
|
851
872
|
const typesField = pkg.types || pkg.typings;
|
|
852
873
|
if (typesField && typeof typesField === "string") {
|
|
853
|
-
const resolved =
|
|
874
|
+
const resolved = tryResolve("types", typesField);
|
|
854
875
|
if (resolved)
|
|
855
876
|
return resolved;
|
|
856
877
|
}
|
|
857
878
|
if (pkg.exports && typeof pkg.exports === "object") {
|
|
858
879
|
const dot = pkg.exports["."];
|
|
859
880
|
for (const candidate of collectExportCandidates(dot)) {
|
|
860
|
-
const resolved =
|
|
881
|
+
const resolved = tryResolve('exports["."]', candidate);
|
|
861
882
|
if (resolved)
|
|
862
883
|
return resolved;
|
|
863
884
|
}
|
|
864
885
|
}
|
|
865
886
|
if (pkg.main && typeof pkg.main === "string") {
|
|
866
|
-
const resolved =
|
|
887
|
+
const resolved = tryResolve("main", pkg.main);
|
|
867
888
|
if (resolved)
|
|
868
889
|
return resolved;
|
|
869
890
|
}
|
|
870
891
|
if (pkg.module && typeof pkg.module === "string") {
|
|
871
|
-
const resolved =
|
|
892
|
+
const resolved = tryResolve("module", pkg.module);
|
|
872
893
|
if (resolved)
|
|
873
894
|
return resolved;
|
|
874
895
|
}
|
|
875
896
|
for (const binPath of collectBinCandidates(pkg.bin)) {
|
|
876
|
-
const resolved =
|
|
897
|
+
const resolved = tryResolve("bin", binPath);
|
|
877
898
|
if (resolved)
|
|
878
899
|
return resolved;
|
|
879
900
|
}
|
|
@@ -892,22 +913,28 @@ function detectEntry(cwd = process.cwd()) {
|
|
|
892
913
|
const full = path6.join(cwd, f);
|
|
893
914
|
if (existsSync6(full))
|
|
894
915
|
return full;
|
|
916
|
+
tried.push(`fallback: ${f} -> not found`);
|
|
895
917
|
}
|
|
896
918
|
const workspaces = detectWorkspaces(cwd);
|
|
897
919
|
if (workspaces) {
|
|
898
920
|
const dirs = resolveGlobs(cwd, workspaces);
|
|
899
|
-
const
|
|
921
|
+
const lines2 = ["Monorepo detected. Use --cwd <pkg> or --all.", "", " Packages:"];
|
|
900
922
|
for (const dir of dirs) {
|
|
901
|
-
|
|
923
|
+
lines2.push(` ${dir}`);
|
|
902
924
|
}
|
|
903
|
-
|
|
904
|
-
throw new Error(
|
|
925
|
+
lines2.push("", " Examples:", ` drift coverage --cwd ${dirs[0] ?? "packages/foo"}`, " drift coverage --all");
|
|
926
|
+
throw new Error(lines2.join(`
|
|
905
927
|
`));
|
|
906
928
|
}
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
929
|
+
const lines = ["Could not detect entry point."];
|
|
930
|
+
if (tried.length > 0) {
|
|
931
|
+
lines.push("", " Tried:");
|
|
932
|
+
for (const t of tried)
|
|
933
|
+
lines.push(` ${t}`);
|
|
934
|
+
}
|
|
935
|
+
lines.push("", " Try: drift scan ./path/to/entry.ts");
|
|
936
|
+
throw new Error(lines.join(`
|
|
937
|
+
`));
|
|
911
938
|
}
|
|
912
939
|
function resolveToSource(cwd, filePath) {
|
|
913
940
|
const normalized = filePath.replace(/^\.\//, "");
|
|
@@ -1798,7 +1825,9 @@ function registerCiCommand(program) {
|
|
|
1798
1825
|
name = pkg.name;
|
|
1799
1826
|
if (pkg.private === true)
|
|
1800
1827
|
isPrivate = true;
|
|
1801
|
-
} catch {
|
|
1828
|
+
} catch (err) {
|
|
1829
|
+
formatWarning(`Could not parse package.json for ${dir}${err instanceof Error ? `: ${err.message}` : ""}`);
|
|
1830
|
+
}
|
|
1802
1831
|
}
|
|
1803
1832
|
if (isPrivate && !options.private) {
|
|
1804
1833
|
skipped.push(name);
|
|
@@ -1870,7 +1899,8 @@ function registerCiCommand(program) {
|
|
|
1870
1899
|
diff,
|
|
1871
1900
|
undocumented
|
|
1872
1901
|
});
|
|
1873
|
-
} catch {
|
|
1902
|
+
} catch (err) {
|
|
1903
|
+
formatWarning(`Analysis failed for ${name}: ${err instanceof Error ? err.message : String(err)}`);
|
|
1874
1904
|
results.push({
|
|
1875
1905
|
name,
|
|
1876
1906
|
coverage: 0,
|
|
@@ -2169,7 +2199,8 @@ function registerContextCommand(program) {
|
|
|
2169
2199
|
try {
|
|
2170
2200
|
const { spec } = await cachedExtract(pkg.entry);
|
|
2171
2201
|
packages.push(buildPackageContext(pkg.name, spec));
|
|
2172
|
-
} catch {
|
|
2202
|
+
} catch (err) {
|
|
2203
|
+
formatWarning(`Extraction failed for ${pkg.name}: ${err instanceof Error ? err.message : String(err)}`);
|
|
2173
2204
|
packages.push({
|
|
2174
2205
|
name: pkg.name,
|
|
2175
2206
|
coverage: 0,
|
|
@@ -3055,7 +3086,7 @@ import * as path21 from "node:path";
|
|
|
3055
3086
|
import { computeDrift as computeDrift3 } from "@driftdev/sdk";
|
|
3056
3087
|
|
|
3057
3088
|
// src/formatters/health.ts
|
|
3058
|
-
function renderHealth(data) {
|
|
3089
|
+
function renderHealth(data, next) {
|
|
3059
3090
|
const lines = [""];
|
|
3060
3091
|
if (data.packageName) {
|
|
3061
3092
|
const ver = data.packageVersion ? ` v${data.packageVersion}` : "";
|
|
@@ -3088,8 +3119,8 @@ function renderHealth(data) {
|
|
|
3088
3119
|
} else {
|
|
3089
3120
|
lines.push(indent(`${c.green(sym.ok)} Health ${data.health}%`));
|
|
3090
3121
|
}
|
|
3091
|
-
if (
|
|
3092
|
-
lines.push(indent(c.gray(
|
|
3122
|
+
if (next) {
|
|
3123
|
+
lines.push(indent(c.gray(`-> Next: ${next.suggested} (${next.reason})`)));
|
|
3093
3124
|
}
|
|
3094
3125
|
lines.push("");
|
|
3095
3126
|
return lines.join(`
|
|
@@ -3125,7 +3156,8 @@ function getPackageInfo(cwd) {
|
|
|
3125
3156
|
try {
|
|
3126
3157
|
const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
|
|
3127
3158
|
return { name: pkg.name, version: pkg.version };
|
|
3128
|
-
} catch {
|
|
3159
|
+
} catch (err) {
|
|
3160
|
+
formatWarning(`Could not parse package.json${err instanceof Error ? `: ${err.message}` : ""}`);
|
|
3129
3161
|
return {};
|
|
3130
3162
|
}
|
|
3131
3163
|
}
|
|
@@ -3632,7 +3664,7 @@ import {
|
|
|
3632
3664
|
} from "@driftdev/sdk";
|
|
3633
3665
|
|
|
3634
3666
|
// src/formatters/lint.ts
|
|
3635
|
-
function renderLint(data) {
|
|
3667
|
+
function renderLint(data, next) {
|
|
3636
3668
|
const lines = [""];
|
|
3637
3669
|
if (data.count === 0) {
|
|
3638
3670
|
lines.push(indent(`${c.green("ok")} No issues found`));
|
|
@@ -3657,6 +3689,9 @@ function renderLint(data) {
|
|
|
3657
3689
|
lines.push("");
|
|
3658
3690
|
}
|
|
3659
3691
|
lines.push(indent(`${data.count} issue${data.count === 1 ? "" : "s"} found`));
|
|
3692
|
+
if (next) {
|
|
3693
|
+
lines.push(indent(c.gray(`-> Next: ${next.suggested} (${next.reason})`)));
|
|
3694
|
+
}
|
|
3660
3695
|
lines.push("");
|
|
3661
3696
|
return lines.join(`
|
|
3662
3697
|
`);
|
|
@@ -3739,7 +3774,9 @@ function registerLintCommand(program) {
|
|
|
3739
3774
|
});
|
|
3740
3775
|
}
|
|
3741
3776
|
}
|
|
3742
|
-
} catch {
|
|
3777
|
+
} catch (err) {
|
|
3778
|
+
formatWarning(`Prose drift skipped: ${err instanceof Error ? err.message : String(err)}`);
|
|
3779
|
+
}
|
|
3743
3780
|
const data = { issues, count: issues.length };
|
|
3744
3781
|
const next = issues.length > 0 ? {
|
|
3745
3782
|
suggested: "drift-fix skill",
|
|
@@ -4220,7 +4257,7 @@ import {
|
|
|
4220
4257
|
} from "@driftdev/sdk";
|
|
4221
4258
|
|
|
4222
4259
|
// src/formatters/scan.ts
|
|
4223
|
-
function renderScan(data) {
|
|
4260
|
+
function renderScan(data, next) {
|
|
4224
4261
|
const lines = [""];
|
|
4225
4262
|
if (data.packageName) {
|
|
4226
4263
|
const ver = data.packageVersion ? ` v${data.packageVersion}` : "";
|
|
@@ -4251,6 +4288,9 @@ function renderScan(data) {
|
|
|
4251
4288
|
} else {
|
|
4252
4289
|
lines.push(indent(`${c.red(sym.x)} Scan failed`));
|
|
4253
4290
|
}
|
|
4291
|
+
if (next) {
|
|
4292
|
+
lines.push(indent(c.gray(`-> Next: ${next.suggested} (${next.reason})`)));
|
|
4293
|
+
}
|
|
4254
4294
|
lines.push("");
|
|
4255
4295
|
return lines.join(`
|
|
4256
4296
|
`);
|
|
@@ -4282,7 +4322,8 @@ function getPackageInfo2(cwd) {
|
|
|
4282
4322
|
try {
|
|
4283
4323
|
const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
|
|
4284
4324
|
return { name: pkg.name, version: pkg.version };
|
|
4285
|
-
} catch {
|
|
4325
|
+
} catch (err) {
|
|
4326
|
+
formatWarning(`Could not parse package.json${err instanceof Error ? `: ${err.message}` : ""}`);
|
|
4286
4327
|
return {};
|
|
4287
4328
|
}
|
|
4288
4329
|
}
|
|
@@ -4385,7 +4426,9 @@ function registerScanCommand(program) {
|
|
|
4385
4426
|
});
|
|
4386
4427
|
}
|
|
4387
4428
|
}
|
|
4388
|
-
} catch {
|
|
4429
|
+
} catch (err) {
|
|
4430
|
+
formatWarning(`Prose drift skipped: ${err instanceof Error ? err.message : String(err)}`);
|
|
4431
|
+
}
|
|
4389
4432
|
const healthIssues = issues.map((i) => ({ export: i.export, issue: i.issue }));
|
|
4390
4433
|
const h = computeHealth(total, documented, healthIssues);
|
|
4391
4434
|
const pkg = getPackageInfo2(process.cwd());
|
|
@@ -4602,11 +4645,11 @@ function extractCapabilities(program) {
|
|
|
4602
4645
|
}
|
|
4603
4646
|
],
|
|
4604
4647
|
workflows: {
|
|
4605
|
-
"detect-drift": ["extract", "lint"],
|
|
4606
|
-
"full-scan": ["scan"],
|
|
4607
|
-
"detect-and-enrich": ["scan", "context"],
|
|
4608
|
-
"ci-pipeline": ["ci"],
|
|
4609
|
-
"pre-release": ["scan", "breaking", "release"]
|
|
4648
|
+
"detect-drift": { steps: ["extract", "lint"], description: "Find stale JSDoc and prose drift" },
|
|
4649
|
+
"full-scan": { steps: ["scan"], description: "Coverage + lint + prose in one pass" },
|
|
4650
|
+
"detect-and-enrich": { steps: ["scan", "context"], description: "Scan and generate agent context" },
|
|
4651
|
+
"ci-pipeline": { steps: ["ci"], description: "Run CI checks on changed packages" },
|
|
4652
|
+
"pre-release": { steps: ["scan", "breaking", "release"], description: "Full pre-release quality gate" }
|
|
4610
4653
|
}
|
|
4611
4654
|
};
|
|
4612
4655
|
}
|
|
@@ -4654,6 +4697,10 @@ for (const cmd of program.commands) {
|
|
|
4654
4697
|
cmd._hidden = true;
|
|
4655
4698
|
}
|
|
4656
4699
|
}
|
|
4700
|
+
program.addHelpText("after", `
|
|
4701
|
+
Agent mode:
|
|
4702
|
+
drift --tools JSON manifest of all commands for agent use
|
|
4703
|
+
`);
|
|
4657
4704
|
if (process.argv.includes("--tools")) {
|
|
4658
4705
|
const caps = extractCapabilities(program);
|
|
4659
4706
|
process.stdout.write(`${JSON.stringify(caps, null, 2)}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@driftdev/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Drift CLI - Documentation coverage and drift detection for TypeScript",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"dist"
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@driftdev/sdk": "^0.
|
|
46
|
+
"@driftdev/sdk": "^1.0.0",
|
|
47
47
|
"@openpkg-ts/sdk": "^0.37.0",
|
|
48
48
|
"@openpkg-ts/spec": "^0.37.0",
|
|
49
49
|
"chalk": "^5.4.1",
|