@driftdev/cli 1.12.1 → 1.12.2
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 +78 -47
- package/package.json +2 -2
package/dist/drift.js
CHANGED
|
@@ -52,7 +52,7 @@ var init_global = () => {};
|
|
|
52
52
|
|
|
53
53
|
// src/drift.ts
|
|
54
54
|
import { readFileSync as readFileSync23 } from "node:fs";
|
|
55
|
-
import * as
|
|
55
|
+
import * as path35 from "node:path";
|
|
56
56
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
57
57
|
import { Command } from "commander";
|
|
58
58
|
|
|
@@ -4271,7 +4271,7 @@ function registerInitCommand(program) {
|
|
|
4271
4271
|
}
|
|
4272
4272
|
|
|
4273
4273
|
// src/commands/lint.ts
|
|
4274
|
-
import * as
|
|
4274
|
+
import * as path29 from "node:path";
|
|
4275
4275
|
import { buildExportRegistry, computeDrift as computeDrift4, detectProseDrift } from "@driftdev/sdk";
|
|
4276
4276
|
|
|
4277
4277
|
// src/formatters/lint.ts
|
|
@@ -4309,6 +4309,13 @@ function renderLint(data, next) {
|
|
|
4309
4309
|
}
|
|
4310
4310
|
|
|
4311
4311
|
// src/utils/annotations.ts
|
|
4312
|
+
import * as path28 from "node:path";
|
|
4313
|
+
function annotationPath(filePath) {
|
|
4314
|
+
if (!path28.isAbsolute(filePath))
|
|
4315
|
+
return filePath;
|
|
4316
|
+
const rel = path28.relative(process.cwd(), filePath);
|
|
4317
|
+
return rel.startsWith("..") ? filePath : rel;
|
|
4318
|
+
}
|
|
4312
4319
|
function escapeData(value) {
|
|
4313
4320
|
return value.replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A");
|
|
4314
4321
|
}
|
|
@@ -4319,7 +4326,7 @@ function emitAnnotations(issues, level = "error") {
|
|
|
4319
4326
|
for (const issue of issues) {
|
|
4320
4327
|
const props = [];
|
|
4321
4328
|
if (issue.filePath)
|
|
4322
|
-
props.push(`file=${escapeProperty(issue.filePath)}`);
|
|
4329
|
+
props.push(`file=${escapeProperty(annotationPath(issue.filePath))}`);
|
|
4323
4330
|
if (issue.line !== undefined)
|
|
4324
4331
|
props.push(`line=${issue.line}`);
|
|
4325
4332
|
props.push(`title=${escapeProperty(`drift: ${issue.export || "docs"}`)}`);
|
|
@@ -4382,9 +4389,9 @@ function registerLintCommand(program) {
|
|
|
4382
4389
|
formatOutput("lint", { issues: [], count: 0 }, startTime, version, renderLint);
|
|
4383
4390
|
return;
|
|
4384
4391
|
}
|
|
4385
|
-
let entryFile = entry ?
|
|
4392
|
+
let entryFile = entry ? path29.resolve(process.cwd(), entry) : undefined;
|
|
4386
4393
|
if (lang === "typescript" && !entryFile) {
|
|
4387
|
-
entryFile = config.entry ?
|
|
4394
|
+
entryFile = config.entry ? path29.resolve(process.cwd(), config.entry) : detectEntry();
|
|
4388
4395
|
}
|
|
4389
4396
|
const { apiSpec: spec } = await resolveTruth({
|
|
4390
4397
|
entry: entryFile,
|
|
@@ -4450,7 +4457,7 @@ function registerLintCommand(program) {
|
|
|
4450
4457
|
}
|
|
4451
4458
|
|
|
4452
4459
|
// src/commands/list.ts
|
|
4453
|
-
import * as
|
|
4460
|
+
import * as path30 from "node:path";
|
|
4454
4461
|
import { computeDrift as computeDrift5 } from "@driftdev/sdk";
|
|
4455
4462
|
import { listExports as listExports2 } from "@openpkg-ts/sdk";
|
|
4456
4463
|
|
|
@@ -4565,7 +4572,7 @@ function registerListCommand(program) {
|
|
|
4565
4572
|
} else {
|
|
4566
4573
|
let entryFile;
|
|
4567
4574
|
if (searchOrEntry && looksLikeFilePath(searchOrEntry)) {
|
|
4568
|
-
entryFile =
|
|
4575
|
+
entryFile = path30.resolve(process.cwd(), searchOrEntry);
|
|
4569
4576
|
} else if (searchOrEntry) {
|
|
4570
4577
|
entryFile = detectEntry();
|
|
4571
4578
|
searchTerm = searchOrEntry;
|
|
@@ -4822,7 +4829,7 @@ function diffArgs(command, args) {
|
|
|
4822
4829
|
// src/commands/release.ts
|
|
4823
4830
|
import { execSync as execSync4 } from "node:child_process";
|
|
4824
4831
|
import { existsSync as existsSync15, readFileSync as readFileSync20 } from "node:fs";
|
|
4825
|
-
import * as
|
|
4832
|
+
import * as path31 from "node:path";
|
|
4826
4833
|
import { computeDrift as computeDrift6 } from "@driftdev/sdk";
|
|
4827
4834
|
|
|
4828
4835
|
// src/formatters/release.ts
|
|
@@ -4870,7 +4877,7 @@ function getLastTag() {
|
|
|
4870
4877
|
}
|
|
4871
4878
|
}
|
|
4872
4879
|
function getPackageVersion(cwd) {
|
|
4873
|
-
const pkgPath =
|
|
4880
|
+
const pkgPath = path31.join(cwd, "package.json");
|
|
4874
4881
|
if (!existsSync15(pkgPath))
|
|
4875
4882
|
return null;
|
|
4876
4883
|
try {
|
|
@@ -4886,7 +4893,7 @@ function registerReleaseCommand(program) {
|
|
|
4886
4893
|
const cwd = process.cwd();
|
|
4887
4894
|
try {
|
|
4888
4895
|
const { config } = loadConfig();
|
|
4889
|
-
const entryFile = entry ?
|
|
4896
|
+
const entryFile = entry ? path31.resolve(cwd, entry) : config.entry ? path31.resolve(cwd, config.entry) : detectEntry();
|
|
4890
4897
|
const { spec } = await cachedExtract(entryFile);
|
|
4891
4898
|
const exports = spec.exports ?? [];
|
|
4892
4899
|
const total = exports.length;
|
|
@@ -5011,7 +5018,7 @@ function renderReport(data) {
|
|
|
5011
5018
|
// src/utils/scan-packages.ts
|
|
5012
5019
|
import { execSync as execSync5 } from "node:child_process";
|
|
5013
5020
|
import { existsSync as existsSync16, readFileSync as readFileSync21 } from "node:fs";
|
|
5014
|
-
import * as
|
|
5021
|
+
import * as path32 from "node:path";
|
|
5015
5022
|
import { computeDrift as computeDrift7 } from "@driftdev/sdk";
|
|
5016
5023
|
function detectPackageDirs2(cwd) {
|
|
5017
5024
|
const workspaces = detectWorkspaces(cwd);
|
|
@@ -5030,11 +5037,11 @@ async function scanAllPackages(cwd) {
|
|
|
5030
5037
|
const packageDirs = detectPackageDirs2(cwd);
|
|
5031
5038
|
const results = [];
|
|
5032
5039
|
for (const dir of packageDirs) {
|
|
5033
|
-
const absDir = dir === "." ? cwd :
|
|
5040
|
+
const absDir = dir === "." ? cwd : path32.join(cwd, dir);
|
|
5034
5041
|
if (!existsSync16(absDir))
|
|
5035
5042
|
continue;
|
|
5036
5043
|
let name = dir;
|
|
5037
|
-
const pkgPath =
|
|
5044
|
+
const pkgPath = path32.join(absDir, "package.json");
|
|
5038
5045
|
if (existsSync16(pkgPath)) {
|
|
5039
5046
|
try {
|
|
5040
5047
|
const pkg = JSON.parse(readFileSync21(pkgPath, "utf-8"));
|
|
@@ -5133,7 +5140,7 @@ function registerReportCommand(program) {
|
|
|
5133
5140
|
}
|
|
5134
5141
|
|
|
5135
5142
|
// src/commands/scan.ts
|
|
5136
|
-
import * as
|
|
5143
|
+
import * as path33 from "node:path";
|
|
5137
5144
|
import {
|
|
5138
5145
|
buildExportRegistry as buildExportRegistry2,
|
|
5139
5146
|
computeDrift as computeDrift8,
|
|
@@ -5149,13 +5156,15 @@ function renderScan(data, next) {
|
|
|
5149
5156
|
lines.push(indent(`${c.bold(data.packageName)}${c.gray(ver)}`));
|
|
5150
5157
|
lines.push("");
|
|
5151
5158
|
}
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
+
if (data.health !== undefined && data.coverage && data.lint) {
|
|
5160
|
+
const hColor = coverageColor(data.health);
|
|
5161
|
+
lines.push(indent(`Health ${hColor(`${data.health}%`)}`));
|
|
5162
|
+
const externalNote = data.coverage.external ? c.gray(` +${data.coverage.external} external (not resolvable here)`) : "";
|
|
5163
|
+
lines.push(indent(`Coverage ${coverageColor(data.coverage.score)(`${data.coverage.score}%`)} (${data.coverage.documented}/${data.coverage.total} exports)${externalNote}`));
|
|
5164
|
+
lines.push(indent(`Lint ${data.lint.count === 0 ? c.green("0 issues") : c.red(`${data.lint.count} issues`)}`));
|
|
5165
|
+
lines.push("");
|
|
5166
|
+
}
|
|
5167
|
+
if (data.lint && data.lint.count > 0) {
|
|
5159
5168
|
lines.push(indent("Issues"));
|
|
5160
5169
|
lines.push(indent(c.gray(separator())));
|
|
5161
5170
|
const shown = data.lint.issues.slice(0, 10);
|
|
@@ -5215,6 +5224,25 @@ function renderBatchScan(data) {
|
|
|
5215
5224
|
}
|
|
5216
5225
|
|
|
5217
5226
|
// src/commands/scan.ts
|
|
5227
|
+
function toDocsCoverageResult(run) {
|
|
5228
|
+
return {
|
|
5229
|
+
pass: run.pass,
|
|
5230
|
+
pages: run.pages.map((p) => ({
|
|
5231
|
+
page: p.page,
|
|
5232
|
+
type: p.type,
|
|
5233
|
+
status: p.status,
|
|
5234
|
+
baselineGaps: p.baselineGaps,
|
|
5235
|
+
counts: p.result.counts,
|
|
5236
|
+
failures: p.failures,
|
|
5237
|
+
warnings: p.warnings,
|
|
5238
|
+
gaps: p.result.gaps,
|
|
5239
|
+
ghosts: p.result.ghosts,
|
|
5240
|
+
inversions: p.result.inversions,
|
|
5241
|
+
documentedKeysFromOtherTypes: p.result.documentedKeysFromOtherTypes,
|
|
5242
|
+
annotated: p.result.annotated
|
|
5243
|
+
}))
|
|
5244
|
+
};
|
|
5245
|
+
}
|
|
5218
5246
|
function registerScanCommand(program) {
|
|
5219
5247
|
program.command("scan [entry]").description("Run coverage + lint + prose drift in one pass").option("--min <n>", "Minimum health threshold (exit 1 if below)").option("--all", "Run across all workspace packages").option("--private", "Include private packages in --all mode").option("--lang <language>", "Source language (inferred from --spec/--abi/.clar; default typescript)").option("--abi <path>", "ABI JSON file (required for --lang clarity)").option("--spec <path>", "OpenAPI document: path or URL (implies --lang openapi)").option("--docs <patterns...>", "Markdown corpus for prose drift: glob patterns or directories (overrides repo-local defaults)").option("--docs-map <file>", "Docs map (page→type) activating key-coverage mode: gaps/ghosts/inversions per page").option("--annotations", "Emit GitHub Actions ::error/::warning annotations for findings").action(async (entry, options) => {
|
|
5220
5248
|
const startTime = Date.now();
|
|
@@ -5294,10 +5322,31 @@ function registerScanCommand(program) {
|
|
|
5294
5322
|
process.exitCode = 1;
|
|
5295
5323
|
return;
|
|
5296
5324
|
}
|
|
5325
|
+
if (options.docsMap && !entry) {
|
|
5326
|
+
const loaded = loadDocsMap(options.docsMap);
|
|
5327
|
+
if (loaded.map.pages.every((p) => p.spec || p.entry)) {
|
|
5328
|
+
const run = await runDocsCoverage(loaded);
|
|
5329
|
+
const data2 = { pass: run.pass, docsCoverage: toDocsCoverageResult(run) };
|
|
5330
|
+
formatOutput("scan", data2, startTime, version, renderScan);
|
|
5331
|
+
if (options.annotations) {
|
|
5332
|
+
emitAnnotations(run.annotations.errors, "error");
|
|
5333
|
+
emitAnnotations(run.annotations.warnings, "warning");
|
|
5334
|
+
}
|
|
5335
|
+
if (!run.pass) {
|
|
5336
|
+
if (!shouldRenderHuman()) {
|
|
5337
|
+
const covFails = run.pages.flatMap((p) => p.failures.map((f) => `${p.page}: ${f}`));
|
|
5338
|
+
process.stderr.write(`scan failed: docs coverage: ${covFails.join(" | ")}
|
|
5339
|
+
`);
|
|
5340
|
+
}
|
|
5341
|
+
process.exitCode = 1;
|
|
5342
|
+
}
|
|
5343
|
+
return;
|
|
5344
|
+
}
|
|
5345
|
+
}
|
|
5297
5346
|
const { config } = loadConfig();
|
|
5298
|
-
let entryFile = entry ?
|
|
5347
|
+
let entryFile = entry ? path33.resolve(process.cwd(), entry) : undefined;
|
|
5299
5348
|
if (lang === "typescript" && !entryFile) {
|
|
5300
|
-
entryFile = config.entry ?
|
|
5349
|
+
entryFile = config.entry ? path33.resolve(process.cwd(), config.entry) : detectEntry();
|
|
5301
5350
|
}
|
|
5302
5351
|
const { apiSpec, packageName, packageVersion } = await resolveTruth({
|
|
5303
5352
|
entry: entryFile,
|
|
@@ -5379,25 +5428,7 @@ function registerScanCommand(program) {
|
|
|
5379
5428
|
pass,
|
|
5380
5429
|
packageName,
|
|
5381
5430
|
packageVersion,
|
|
5382
|
-
...docsCoverage ? {
|
|
5383
|
-
docsCoverage: {
|
|
5384
|
-
pass: docsCoverage.pass,
|
|
5385
|
-
pages: docsCoverage.pages.map((p) => ({
|
|
5386
|
-
page: p.page,
|
|
5387
|
-
type: p.type,
|
|
5388
|
-
status: p.status,
|
|
5389
|
-
baselineGaps: p.baselineGaps,
|
|
5390
|
-
counts: p.result.counts,
|
|
5391
|
-
failures: p.failures,
|
|
5392
|
-
warnings: p.warnings,
|
|
5393
|
-
gaps: p.result.gaps,
|
|
5394
|
-
ghosts: p.result.ghosts,
|
|
5395
|
-
inversions: p.result.inversions,
|
|
5396
|
-
documentedKeysFromOtherTypes: p.result.documentedKeysFromOtherTypes,
|
|
5397
|
-
annotated: p.result.annotated
|
|
5398
|
-
}))
|
|
5399
|
-
}
|
|
5400
|
-
} : {}
|
|
5431
|
+
...docsCoverage ? { docsCoverage: toDocsCoverageResult(docsCoverage) } : {}
|
|
5401
5432
|
};
|
|
5402
5433
|
let next;
|
|
5403
5434
|
if (issues.length > 0) {
|
|
@@ -5473,7 +5504,7 @@ function registerSemverCommand(program) {
|
|
|
5473
5504
|
|
|
5474
5505
|
// src/commands/validate.ts
|
|
5475
5506
|
import { readFileSync as readFileSync22 } from "node:fs";
|
|
5476
|
-
import * as
|
|
5507
|
+
import * as path34 from "node:path";
|
|
5477
5508
|
import { validateSpec } from "@openpkg-ts/spec";
|
|
5478
5509
|
|
|
5479
5510
|
// src/formatters/validate.ts
|
|
@@ -5499,7 +5530,7 @@ function registerValidateCommand(program) {
|
|
|
5499
5530
|
const startTime = Date.now();
|
|
5500
5531
|
const version = getVersion();
|
|
5501
5532
|
try {
|
|
5502
|
-
const filePath =
|
|
5533
|
+
const filePath = path34.resolve(process.cwd(), file);
|
|
5503
5534
|
const content = readFileSync22(filePath, "utf-8");
|
|
5504
5535
|
const spec = JSON.parse(content);
|
|
5505
5536
|
const result = validateSpec(spec);
|
|
@@ -5642,13 +5673,13 @@ function extractCapabilities(program) {
|
|
|
5642
5673
|
|
|
5643
5674
|
// src/drift.ts
|
|
5644
5675
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
5645
|
-
var __dirname3 =
|
|
5646
|
-
var packageJson = JSON.parse(readFileSync23(
|
|
5676
|
+
var __dirname3 = path35.dirname(__filename2);
|
|
5677
|
+
var packageJson = JSON.parse(readFileSync23(path35.join(__dirname3, "../package.json"), "utf-8"));
|
|
5647
5678
|
var program = new Command;
|
|
5648
5679
|
program.name("drift").description("drift — detect when your docs drift from your code").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) => {
|
|
5649
5680
|
const opts = program.opts();
|
|
5650
5681
|
if (opts.cwd) {
|
|
5651
|
-
process.chdir(
|
|
5682
|
+
process.chdir(path35.resolve(opts.cwd));
|
|
5652
5683
|
}
|
|
5653
5684
|
setOutputMode({ json: opts.json, human: opts.human });
|
|
5654
5685
|
setConfigPath(opts.config);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@driftdev/cli",
|
|
3
|
-
"version": "1.12.
|
|
3
|
+
"version": "1.12.2",
|
|
4
4
|
"description": "Drift CLI - detect when your docs drift from your code",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@driftdev/clarity-adapter": "^1.0.1",
|
|
49
49
|
"@driftdev/openapi-adapter": "^1.0.1",
|
|
50
|
-
"@driftdev/sdk": "^1.12.
|
|
50
|
+
"@driftdev/sdk": "^1.12.2",
|
|
51
51
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
52
52
|
"@openpkg-ts/sdk": "^0.43.0",
|
|
53
53
|
"@openpkg-ts/spec": "^0.43.0",
|