@driftdev/cli 0.40.0 → 0.42.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 +1 -1
- package/dist/drift.js +135 -93
- package/package.json +2 -3
package/README.md
CHANGED
package/dist/drift.js
CHANGED
|
@@ -1134,6 +1134,26 @@ function registerBreakingCommand(program) {
|
|
|
1134
1134
|
});
|
|
1135
1135
|
}
|
|
1136
1136
|
|
|
1137
|
+
// src/commands/commands.ts
|
|
1138
|
+
var GROUPS = {
|
|
1139
|
+
Composed: ["scan", "ci", "health"],
|
|
1140
|
+
Analysis: ["coverage", "lint", "examples"],
|
|
1141
|
+
Extraction: ["extract", "list", "get"],
|
|
1142
|
+
Comparison: ["diff", "breaking", "semver", "changelog"],
|
|
1143
|
+
Setup: ["init", "config", "context"],
|
|
1144
|
+
Plumbing: ["validate", "filter", "cache", "report", "release"]
|
|
1145
|
+
};
|
|
1146
|
+
function registerCommandsCommand(program) {
|
|
1147
|
+
program.command("commands").description("List all available commands grouped by category").action(() => {
|
|
1148
|
+
const maxGroup = Math.max(...Object.keys(GROUPS).map((g) => g.length));
|
|
1149
|
+
for (const [group, cmds] of Object.entries(GROUPS)) {
|
|
1150
|
+
const pad2 = " ".repeat(maxGroup - group.length);
|
|
1151
|
+
process.stdout.write(` ${group}${pad2} ${cmds.join(", ")}
|
|
1152
|
+
`);
|
|
1153
|
+
}
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1137
1157
|
// src/formatters/cache.ts
|
|
1138
1158
|
function renderCacheStatus(data) {
|
|
1139
1159
|
const lines = [];
|
|
@@ -1388,6 +1408,30 @@ function renderContextMarkdown(data) {
|
|
|
1388
1408
|
lines.push(`**Average coverage**: ${avgCoverage}% `);
|
|
1389
1409
|
lines.push(`**Total lint issues**: ${totalIssues}`);
|
|
1390
1410
|
lines.push("");
|
|
1411
|
+
for (const pkg of data.packages) {
|
|
1412
|
+
if (pkg.issues && pkg.issues.length > 0) {
|
|
1413
|
+
lines.push(`### ${pkg.name} — Issues`);
|
|
1414
|
+
lines.push("");
|
|
1415
|
+
lines.push("| Export | Type | Location |");
|
|
1416
|
+
lines.push("|--------|------|----------|");
|
|
1417
|
+
for (const issue of pkg.issues) {
|
|
1418
|
+
const loc = issue.filePath ? `${issue.filePath}${issue.line ? `:${issue.line}` : ""}` : "—";
|
|
1419
|
+
lines.push(`| ${issue.export} | ${issue.type} | ${loc} |`);
|
|
1420
|
+
}
|
|
1421
|
+
lines.push("");
|
|
1422
|
+
}
|
|
1423
|
+
if (pkg.undocumentedExports && pkg.undocumentedExports.length > 0) {
|
|
1424
|
+
lines.push(`### ${pkg.name} — Undocumented Exports`);
|
|
1425
|
+
lines.push("");
|
|
1426
|
+
lines.push("| Export | Kind | Location |");
|
|
1427
|
+
lines.push("|--------|------|----------|");
|
|
1428
|
+
for (const exp of pkg.undocumentedExports) {
|
|
1429
|
+
const loc = exp.filePath ? `${exp.filePath}${exp.line ? `:${exp.line}` : ""}` : "—";
|
|
1430
|
+
lines.push(`| ${exp.name} | ${exp.kind} | ${loc} |`);
|
|
1431
|
+
}
|
|
1432
|
+
lines.push("");
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1391
1435
|
}
|
|
1392
1436
|
if (data.history.length > 0) {
|
|
1393
1437
|
lines.push("## Recent Activity");
|
|
@@ -2061,6 +2105,52 @@ function getCommitSha2() {
|
|
|
2061
2105
|
return null;
|
|
2062
2106
|
}
|
|
2063
2107
|
}
|
|
2108
|
+
function buildPackageContext(name, spec) {
|
|
2109
|
+
const exports = spec.exports ?? [];
|
|
2110
|
+
let documented = 0;
|
|
2111
|
+
const undocumented = [];
|
|
2112
|
+
const undocumentedExports = [];
|
|
2113
|
+
for (const exp of exports) {
|
|
2114
|
+
if (exp.description?.trim()) {
|
|
2115
|
+
documented++;
|
|
2116
|
+
} else {
|
|
2117
|
+
undocumented.push(exp.name);
|
|
2118
|
+
undocumentedExports.push({
|
|
2119
|
+
name: exp.name,
|
|
2120
|
+
kind: exp.kind,
|
|
2121
|
+
filePath: exp.source?.file,
|
|
2122
|
+
line: exp.source?.line
|
|
2123
|
+
});
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
const coverage = exports.length > 0 ? Math.round(documented / exports.length * 100) : 100;
|
|
2127
|
+
const driftResult = computeDrift2(spec);
|
|
2128
|
+
const issues = [];
|
|
2129
|
+
let lintIssues = 0;
|
|
2130
|
+
for (const [exportName, drifts] of driftResult.exports) {
|
|
2131
|
+
lintIssues += drifts.length;
|
|
2132
|
+
const exp = exports.find((e) => e.name === exportName);
|
|
2133
|
+
for (const drift of drifts) {
|
|
2134
|
+
issues.push({
|
|
2135
|
+
export: exportName,
|
|
2136
|
+
type: drift.type,
|
|
2137
|
+
issue: drift.issue,
|
|
2138
|
+
filePath: drift.filePath ?? exp?.source?.file,
|
|
2139
|
+
line: drift.line ?? exp?.source?.line
|
|
2140
|
+
});
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
return {
|
|
2144
|
+
name,
|
|
2145
|
+
coverage,
|
|
2146
|
+
lintIssues,
|
|
2147
|
+
exports: exports.length,
|
|
2148
|
+
documented,
|
|
2149
|
+
undocumented,
|
|
2150
|
+
issues: issues.length > 0 ? issues : undefined,
|
|
2151
|
+
undocumentedExports: undocumentedExports.length > 0 ? undocumentedExports : undefined
|
|
2152
|
+
};
|
|
2153
|
+
}
|
|
2064
2154
|
function registerContextCommand(program) {
|
|
2065
2155
|
program.command("context [entry]").description("Generate agent context file with project state").option("--all", "Include all workspace packages").option("--private", "Include private packages in --all mode").option("--output <path>", "Output path (default: ~/.drift/projects/<slug>/context.md)").action(async (entry, options) => {
|
|
2066
2156
|
const startTime = Date.now();
|
|
@@ -2078,28 +2168,7 @@ function registerContextCommand(program) {
|
|
|
2078
2168
|
for (const pkg of pkgs) {
|
|
2079
2169
|
try {
|
|
2080
2170
|
const { spec } = await cachedExtract(pkg.entry);
|
|
2081
|
-
|
|
2082
|
-
let documented = 0;
|
|
2083
|
-
const undocumented = [];
|
|
2084
|
-
for (const exp of exports) {
|
|
2085
|
-
if (exp.description?.trim())
|
|
2086
|
-
documented++;
|
|
2087
|
-
else
|
|
2088
|
-
undocumented.push(exp.name);
|
|
2089
|
-
}
|
|
2090
|
-
const coverage = exports.length > 0 ? Math.round(documented / exports.length * 100) : 100;
|
|
2091
|
-
const driftResult = computeDrift2(spec);
|
|
2092
|
-
let lintIssues = 0;
|
|
2093
|
-
for (const [, drifts] of driftResult.exports)
|
|
2094
|
-
lintIssues += drifts.length;
|
|
2095
|
-
packages.push({
|
|
2096
|
-
name: pkg.name,
|
|
2097
|
-
coverage,
|
|
2098
|
-
lintIssues,
|
|
2099
|
-
exports: exports.length,
|
|
2100
|
-
documented,
|
|
2101
|
-
undocumented
|
|
2102
|
-
});
|
|
2171
|
+
packages.push(buildPackageContext(pkg.name, spec));
|
|
2103
2172
|
} catch {
|
|
2104
2173
|
packages.push({
|
|
2105
2174
|
name: pkg.name,
|
|
@@ -2114,64 +2183,22 @@ function registerContextCommand(program) {
|
|
|
2114
2183
|
} else {
|
|
2115
2184
|
const entryFile = config.entry ? path14.resolve(cwd, config.entry) : detectEntry();
|
|
2116
2185
|
const { spec } = await cachedExtract(entryFile);
|
|
2117
|
-
const exports = spec.exports ?? [];
|
|
2118
|
-
let documented = 0;
|
|
2119
|
-
const undocumented = [];
|
|
2120
|
-
for (const exp of exports) {
|
|
2121
|
-
if (exp.description?.trim())
|
|
2122
|
-
documented++;
|
|
2123
|
-
else
|
|
2124
|
-
undocumented.push(exp.name);
|
|
2125
|
-
}
|
|
2126
|
-
const coverage = exports.length > 0 ? Math.round(documented / exports.length * 100) : 100;
|
|
2127
|
-
const driftResult = computeDrift2(spec);
|
|
2128
|
-
let lintIssues = 0;
|
|
2129
|
-
for (const [, drifts] of driftResult.exports)
|
|
2130
|
-
lintIssues += drifts.length;
|
|
2131
2186
|
const pkgJsonPath = path14.resolve(cwd, "package.json");
|
|
2132
2187
|
let name = path14.basename(cwd);
|
|
2133
2188
|
try {
|
|
2134
2189
|
name = JSON.parse(readFileSync12(pkgJsonPath, "utf-8")).name ?? name;
|
|
2135
2190
|
} catch {}
|
|
2136
|
-
packages.push(
|
|
2137
|
-
name,
|
|
2138
|
-
coverage,
|
|
2139
|
-
lintIssues,
|
|
2140
|
-
exports: exports.length,
|
|
2141
|
-
documented,
|
|
2142
|
-
undocumented
|
|
2143
|
-
});
|
|
2191
|
+
packages.push(buildPackageContext(name, spec));
|
|
2144
2192
|
}
|
|
2145
2193
|
} else {
|
|
2146
2194
|
const entryFile = path14.resolve(cwd, entry);
|
|
2147
2195
|
const { spec } = await cachedExtract(entryFile);
|
|
2148
|
-
const exports = spec.exports ?? [];
|
|
2149
|
-
let documented = 0;
|
|
2150
|
-
const undocumented = [];
|
|
2151
|
-
for (const exp of exports) {
|
|
2152
|
-
if (exp.description?.trim())
|
|
2153
|
-
documented++;
|
|
2154
|
-
else
|
|
2155
|
-
undocumented.push(exp.name);
|
|
2156
|
-
}
|
|
2157
|
-
const coverage = exports.length > 0 ? Math.round(documented / exports.length * 100) : 100;
|
|
2158
|
-
const driftResult = computeDrift2(spec);
|
|
2159
|
-
let lintIssues = 0;
|
|
2160
|
-
for (const [, drifts] of driftResult.exports)
|
|
2161
|
-
lintIssues += drifts.length;
|
|
2162
2196
|
const pkgJsonPath = path14.resolve(cwd, "package.json");
|
|
2163
2197
|
let name = path14.basename(cwd);
|
|
2164
2198
|
try {
|
|
2165
2199
|
name = JSON.parse(readFileSync12(pkgJsonPath, "utf-8")).name ?? name;
|
|
2166
2200
|
} catch {}
|
|
2167
|
-
packages.push(
|
|
2168
|
-
name,
|
|
2169
|
-
coverage,
|
|
2170
|
-
lintIssues,
|
|
2171
|
-
exports: exports.length,
|
|
2172
|
-
documented,
|
|
2173
|
-
undocumented
|
|
2174
|
-
});
|
|
2201
|
+
packages.push(buildPackageContext(name, spec));
|
|
2175
2202
|
}
|
|
2176
2203
|
const contextData = { packages, history, config, commit: commit ?? null };
|
|
2177
2204
|
if (options.output) {
|
|
@@ -3601,8 +3628,7 @@ import {
|
|
|
3601
3628
|
buildExportRegistry,
|
|
3602
3629
|
computeDrift as computeDrift4,
|
|
3603
3630
|
detectProseDrift,
|
|
3604
|
-
discoverMarkdownFiles
|
|
3605
|
-
isFixableDrift
|
|
3631
|
+
discoverMarkdownFiles
|
|
3606
3632
|
} from "@driftdev/sdk";
|
|
3607
3633
|
|
|
3608
3634
|
// src/formatters/lint.ts
|
|
@@ -3715,16 +3741,9 @@ function registerLintCommand(program) {
|
|
|
3715
3741
|
}
|
|
3716
3742
|
} catch {}
|
|
3717
3743
|
const data = { issues, count: issues.length };
|
|
3718
|
-
let fixableCount = 0;
|
|
3719
|
-
for (const [, drifts] of driftResult.exports) {
|
|
3720
|
-
for (const d of drifts) {
|
|
3721
|
-
if (isFixableDrift(d))
|
|
3722
|
-
fixableCount++;
|
|
3723
|
-
}
|
|
3724
|
-
}
|
|
3725
3744
|
const next = issues.length > 0 ? {
|
|
3726
3745
|
suggested: "drift-fix skill",
|
|
3727
|
-
reason: `${
|
|
3746
|
+
reason: `${issues.length} issue${issues.length === 1 ? "" : "s"} found`
|
|
3728
3747
|
} : undefined;
|
|
3729
3748
|
formatOutput("lint", data, startTime, version, renderLint, next);
|
|
3730
3749
|
if (issues.length > 0) {
|
|
@@ -4197,8 +4216,7 @@ import {
|
|
|
4197
4216
|
buildExportRegistry as buildExportRegistry2,
|
|
4198
4217
|
computeDrift as computeDrift8,
|
|
4199
4218
|
detectProseDrift as detectProseDrift2,
|
|
4200
|
-
discoverMarkdownFiles as discoverMarkdownFiles2
|
|
4201
|
-
isFixableDrift as isFixableDrift2
|
|
4219
|
+
discoverMarkdownFiles as discoverMarkdownFiles2
|
|
4202
4220
|
} from "@driftdev/sdk";
|
|
4203
4221
|
|
|
4204
4222
|
// src/formatters/scan.ts
|
|
@@ -4387,16 +4405,9 @@ function registerScanCommand(program) {
|
|
|
4387
4405
|
};
|
|
4388
4406
|
let next;
|
|
4389
4407
|
if (issues.length > 0) {
|
|
4390
|
-
let fixableCount = 0;
|
|
4391
|
-
for (const [, drs] of driftResult.exports) {
|
|
4392
|
-
for (const d of drs) {
|
|
4393
|
-
if (isFixableDrift2(d))
|
|
4394
|
-
fixableCount++;
|
|
4395
|
-
}
|
|
4396
|
-
}
|
|
4397
4408
|
next = {
|
|
4398
4409
|
suggested: "drift-fix skill",
|
|
4399
|
-
reason: `${
|
|
4410
|
+
reason: `${issues.length} issue${issues.length === 1 ? "" : "s"} found`
|
|
4400
4411
|
};
|
|
4401
4412
|
} else if (total - documented > 0) {
|
|
4402
4413
|
next = {
|
|
@@ -4516,6 +4527,29 @@ function extractFlags(cmd) {
|
|
|
4516
4527
|
type: optionType(opt)
|
|
4517
4528
|
}));
|
|
4518
4529
|
}
|
|
4530
|
+
var COMMAND_EXAMPLES = {
|
|
4531
|
+
scan: ["drift scan --json", "drift scan --all --json", "drift scan --ci --json"],
|
|
4532
|
+
lint: ["drift lint --json", "drift lint --all --json"],
|
|
4533
|
+
coverage: ["drift coverage --json", "drift coverage --min 80 --json"],
|
|
4534
|
+
extract: ["drift extract --json"],
|
|
4535
|
+
list: ["drift list --json"],
|
|
4536
|
+
get: ["drift get createClient --json"],
|
|
4537
|
+
diff: ["drift diff --base main --json"],
|
|
4538
|
+
breaking: ["drift breaking --base main --json"],
|
|
4539
|
+
semver: ["drift semver --base main --json"],
|
|
4540
|
+
changelog: ["drift changelog --base main --json"],
|
|
4541
|
+
ci: ["drift ci --json", "drift ci --all --json"],
|
|
4542
|
+
release: ["drift release --json"],
|
|
4543
|
+
context: ["drift context --json", "drift context --all --json"],
|
|
4544
|
+
examples: ["drift examples --typecheck --json"],
|
|
4545
|
+
health: ["drift health --json"],
|
|
4546
|
+
config: ["drift config list --json", "drift config get coverage.min --json"],
|
|
4547
|
+
init: ["drift init --json"],
|
|
4548
|
+
validate: ["drift validate spec.json --json"],
|
|
4549
|
+
filter: ["drift filter spec.json --kind function --json"],
|
|
4550
|
+
report: ["drift report --json"],
|
|
4551
|
+
cache: ["drift cache status", "drift cache clear"]
|
|
4552
|
+
};
|
|
4519
4553
|
function extractCapabilities(program) {
|
|
4520
4554
|
const commands = [];
|
|
4521
4555
|
for (const cmd of program.commands) {
|
|
@@ -4524,11 +4558,14 @@ function extractCapabilities(program) {
|
|
|
4524
4558
|
name: cmd.name(),
|
|
4525
4559
|
description: cmd.description(),
|
|
4526
4560
|
flags: extractFlags(cmd),
|
|
4527
|
-
...positionalArgs.length > 0 ? { positional: positionalArgs.map((a) => a.name()).join(" ") } : {}
|
|
4561
|
+
...positionalArgs.length > 0 ? { positional: positionalArgs.map((a) => a.name()).join(" ") } : {},
|
|
4562
|
+
...COMMAND_EXAMPLES[cmd.name()] ? { examples: COMMAND_EXAMPLES[cmd.name()] } : {}
|
|
4528
4563
|
});
|
|
4529
4564
|
}
|
|
4530
4565
|
return {
|
|
4531
4566
|
version: program.version() ?? "0.0.0",
|
|
4567
|
+
hint: "Run 'drift' for human output. Use these primitives with --json for agent workflows.",
|
|
4568
|
+
humanCommands: ["scan", "ci", "init"],
|
|
4532
4569
|
commands,
|
|
4533
4570
|
globalFlags: extractFlags(program),
|
|
4534
4571
|
entities: [
|
|
@@ -4579,7 +4616,7 @@ var __filename2 = fileURLToPath2(import.meta.url);
|
|
|
4579
4616
|
var __dirname3 = path29.dirname(__filename2);
|
|
4580
4617
|
var packageJson = JSON.parse(readFileSync22(path29.join(__dirname3, "../package.json"), "utf-8"));
|
|
4581
4618
|
var program = new Command;
|
|
4582
|
-
program.name("drift").description("drift — documentation quality
|
|
4619
|
+
program.name("drift").description("drift — documentation quality for TypeScript").version(packageJson.version).option("--json", "Force JSON output (default when piped)").option("--human", "Force human-readable output (default in terminal)").option("--config <path>", "Path to drift config file").option("--cwd <dir>", "Run as if started in <dir>").option("--no-cache", "Bypass spec cache").option("--tools", "List all available tools for agent use (JSON)").hook("preAction", (_thisCommand) => {
|
|
4583
4620
|
const opts = program.opts();
|
|
4584
4621
|
if (opts.cwd) {
|
|
4585
4622
|
process.chdir(path29.resolve(opts.cwd));
|
|
@@ -4610,19 +4647,24 @@ registerInitCommand(program);
|
|
|
4610
4647
|
registerConfigCommand(program);
|
|
4611
4648
|
registerContextCommand(program);
|
|
4612
4649
|
registerCacheCommand(program);
|
|
4613
|
-
|
|
4650
|
+
registerCommandsCommand(program);
|
|
4651
|
+
var HUMAN_COMMANDS = new Set(["scan", "ci", "init", "commands"]);
|
|
4652
|
+
for (const cmd of program.commands) {
|
|
4653
|
+
if (!HUMAN_COMMANDS.has(cmd.name())) {
|
|
4654
|
+
cmd._hidden = true;
|
|
4655
|
+
}
|
|
4656
|
+
}
|
|
4657
|
+
if (process.argv.includes("--tools")) {
|
|
4614
4658
|
const caps = extractCapabilities(program);
|
|
4615
4659
|
process.stdout.write(`${JSON.stringify(caps, null, 2)}
|
|
4616
4660
|
`);
|
|
4617
4661
|
process.exit(0);
|
|
4618
4662
|
}
|
|
4619
4663
|
var rawArgs = process.argv.slice(2);
|
|
4620
|
-
var hasHelpOrVersion = rawArgs.some((a) => ["-h", "--help", "-V", "--version"].includes(a));
|
|
4664
|
+
var hasHelpOrVersion = rawArgs.some((a) => ["-h", "--help", "-V", "--version", "--tools"].includes(a));
|
|
4621
4665
|
var userArgs = rawArgs.filter((a) => !a.startsWith("-"));
|
|
4622
4666
|
if (userArgs.length === 0 && !hasHelpOrVersion) {
|
|
4623
|
-
|
|
4624
|
-
const subcommand = configPath ? "health" : "init";
|
|
4625
|
-
process.argv.splice(2, 0, subcommand);
|
|
4667
|
+
process.argv.splice(2, 0, "scan");
|
|
4626
4668
|
}
|
|
4627
4669
|
program.parseAsync().catch(() => {
|
|
4628
4670
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@driftdev/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.42.0",
|
|
4
4
|
"description": "Drift CLI - Documentation coverage and drift detection for TypeScript",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -43,8 +43,7 @@
|
|
|
43
43
|
"dist"
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@driftdev/sdk": "^0.
|
|
47
|
-
"@driftdev/spec": "^0.36.0",
|
|
46
|
+
"@driftdev/sdk": "^0.42.0",
|
|
48
47
|
"@openpkg-ts/sdk": "^0.37.0",
|
|
49
48
|
"@openpkg-ts/spec": "^0.37.0",
|
|
50
49
|
"chalk": "^5.4.1",
|