@mortice/mapwright 0.8.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/CHANGELOG.md +161 -0
- package/LICENSE +21 -0
- package/README.md +262 -0
- package/dist/catalogue/canonicalisation.d.ts +36 -0
- package/dist/catalogue/canonicalisation.js +262 -0
- package/dist/catalogue/config.d.ts +13 -0
- package/dist/catalogue/config.js +77 -0
- package/dist/catalogue/deterministic.d.ts +3 -0
- package/dist/catalogue/deterministic.js +25 -0
- package/dist/catalogue/diagnostics.d.ts +2 -0
- package/dist/catalogue/diagnostics.js +34 -0
- package/dist/catalogue/evidence.d.ts +1 -0
- package/dist/catalogue/evidence.js +10 -0
- package/dist/catalogue/examples.d.ts +3 -0
- package/dist/catalogue/examples.js +20 -0
- package/dist/catalogue/identity.d.ts +61 -0
- package/dist/catalogue/identity.js +114 -0
- package/dist/catalogue/ignore.d.ts +4 -0
- package/dist/catalogue/ignore.js +29 -0
- package/dist/catalogue/indexer.d.ts +20 -0
- package/dist/catalogue/indexer.js +1393 -0
- package/dist/catalogue/linkage.d.ts +16 -0
- package/dist/catalogue/linkage.js +419 -0
- package/dist/catalogue/moduleResolution.d.ts +4 -0
- package/dist/catalogue/moduleResolution.js +67 -0
- package/dist/catalogue/ordering.d.ts +13 -0
- package/dist/catalogue/ordering.js +86 -0
- package/dist/catalogue/packages.d.ts +12 -0
- package/dist/catalogue/packages.js +475 -0
- package/dist/catalogue/pythonReExports.d.ts +7 -0
- package/dist/catalogue/pythonReExports.js +113 -0
- package/dist/catalogue/resolveRefs.d.ts +40 -0
- package/dist/catalogue/resolveRefs.js +284 -0
- package/dist/catalogue/scanner.d.ts +8 -0
- package/dist/catalogue/scanner.js +99 -0
- package/dist/catalogue/schema.d.ts +289 -0
- package/dist/catalogue/schema.js +1 -0
- package/dist/catalogue/store.d.ts +41 -0
- package/dist/catalogue/store.js +209 -0
- package/dist/catalogue/templates.d.ts +18 -0
- package/dist/catalogue/templates.js +158 -0
- package/dist/catalogue/version.d.ts +12 -0
- package/dist/catalogue/version.js +30 -0
- package/dist/cli/commands/adoptionPlan.d.ts +8 -0
- package/dist/cli/commands/adoptionPlan.js +24 -0
- package/dist/cli/commands/auditDocs.d.ts +8 -0
- package/dist/cli/commands/auditDocs.js +24 -0
- package/dist/cli/commands/changeImpact.d.ts +10 -0
- package/dist/cli/commands/changeImpact.js +36 -0
- package/dist/cli/commands/changes.d.ts +12 -0
- package/dist/cli/commands/changes.js +31 -0
- package/dist/cli/commands/check.d.ts +9 -0
- package/dist/cli/commands/check.js +4 -0
- package/dist/cli/commands/compatibility.d.ts +10 -0
- package/dist/cli/commands/compatibility.js +43 -0
- package/dist/cli/commands/diff.d.ts +31 -0
- package/dist/cli/commands/diff.js +118 -0
- package/dist/cli/commands/dogfood.d.ts +8 -0
- package/dist/cli/commands/dogfood.js +24 -0
- package/dist/cli/commands/drift.d.ts +8 -0
- package/dist/cli/commands/drift.js +13 -0
- package/dist/cli/commands/index.d.ts +9 -0
- package/dist/cli/commands/index.js +9 -0
- package/dist/cli/commands/indexWorkspace.d.ts +8 -0
- package/dist/cli/commands/indexWorkspace.js +23 -0
- package/dist/cli/commands/recommendConfig.d.ts +7 -0
- package/dist/cli/commands/recommendConfig.js +20 -0
- package/dist/cli/commands/schema.d.ts +1 -0
- package/dist/cli/commands/schema.js +37 -0
- package/dist/cli/commands/template.d.ts +5 -0
- package/dist/cli/commands/template.js +44 -0
- package/dist/cli/commands/validate.d.ts +9 -0
- package/dist/cli/commands/validate.js +85 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +211 -0
- package/dist/comparison/artefactValidate.d.ts +19 -0
- package/dist/comparison/artefactValidate.js +334 -0
- package/dist/comparison/candidates.d.ts +12 -0
- package/dist/comparison/candidates.js +391 -0
- package/dist/comparison/compare.d.ts +15 -0
- package/dist/comparison/compare.js +240 -0
- package/dist/comparison/compatibility.d.ts +26 -0
- package/dist/comparison/compatibility.js +316 -0
- package/dist/comparison/drift.d.ts +34 -0
- package/dist/comparison/drift.js +71 -0
- package/dist/comparison/identity.d.ts +30 -0
- package/dist/comparison/identity.js +73 -0
- package/dist/comparison/impact.d.ts +14 -0
- package/dist/comparison/impact.js +291 -0
- package/dist/comparison/index.d.ts +6 -0
- package/dist/comparison/index.js +6 -0
- package/dist/comparison/integrity.d.ts +12 -0
- package/dist/comparison/integrity.js +199 -0
- package/dist/comparison/ordering.d.ts +4 -0
- package/dist/comparison/ordering.js +69 -0
- package/dist/comparison/projections.d.ts +19 -0
- package/dist/comparison/projections.js +185 -0
- package/dist/comparison/relationshipPolicy.d.ts +19 -0
- package/dist/comparison/relationshipPolicy.js +98 -0
- package/dist/comparison/schema.d.ts +178 -0
- package/dist/comparison/schema.js +16 -0
- package/dist/comparison/store.d.ts +58 -0
- package/dist/comparison/store.js +462 -0
- package/dist/comparison/validate.d.ts +23 -0
- package/dist/comparison/validate.js +137 -0
- package/dist/comparison/version.d.ts +9 -0
- package/dist/comparison/version.js +11 -0
- package/dist/extractors/docTags.d.ts +9 -0
- package/dist/extractors/docTags.js +106 -0
- package/dist/extractors/generic.d.ts +5 -0
- package/dist/extractors/generic.js +3 -0
- package/dist/extractors/javascript.d.ts +3 -0
- package/dist/extractors/javascript.js +4 -0
- package/dist/extractors/markdown.d.ts +7 -0
- package/dist/extractors/markdown.js +269 -0
- package/dist/extractors/python.d.ts +7 -0
- package/dist/extractors/python.js +314 -0
- package/dist/extractors/typescript.d.ts +7 -0
- package/dist/extractors/typescript.js +387 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/mcp/resources.d.ts +18 -0
- package/dist/mcp/resources.js +57 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.js +95 -0
- package/dist/mcp/tools.d.ts +29 -0
- package/dist/mcp/tools.js +902 -0
- package/dist/queries/adoption.d.ts +62 -0
- package/dist/queries/adoption.js +366 -0
- package/dist/queries/capabilities.d.ts +45 -0
- package/dist/queries/capabilities.js +124 -0
- package/dist/queries/changes.d.ts +33 -0
- package/dist/queries/changes.js +53 -0
- package/dist/queries/dependencies.d.ts +17 -0
- package/dist/queries/dependencies.js +94 -0
- package/dist/queries/dogfood.d.ts +50 -0
- package/dist/queries/dogfood.js +116 -0
- package/dist/queries/editingContext.d.ts +84 -0
- package/dist/queries/editingContext.js +240 -0
- package/dist/queries/examples.d.ts +8 -0
- package/dist/queries/examples.js +16 -0
- package/dist/queries/files.d.ts +8 -0
- package/dist/queries/files.js +14 -0
- package/dist/queries/lists.d.ts +94 -0
- package/dist/queries/lists.js +184 -0
- package/dist/queries/overview.d.ts +2 -0
- package/dist/queries/overview.js +8 -0
- package/dist/queries/publicApis.d.ts +60 -0
- package/dist/queries/publicApis.js +120 -0
- package/dist/queries/ranking.d.ts +67 -0
- package/dist/queries/ranking.js +387 -0
- package/dist/queries/recommendConfig.d.ts +47 -0
- package/dist/queries/recommendConfig.js +123 -0
- package/dist/queries/relationships.d.ts +5 -0
- package/dist/queries/relationships.js +15 -0
- package/dist/queries/reuseCandidates.d.ts +34 -0
- package/dist/queries/reuseCandidates.js +181 -0
- package/dist/queries/symbols.d.ts +40 -0
- package/dist/queries/symbols.js +41 -0
- package/dist/security/pathPolicy.d.ts +12 -0
- package/dist/security/pathPolicy.js +46 -0
- package/dist/security/secretPatterns.d.ts +1 -0
- package/dist/security/secretPatterns.js +4 -0
- package/dist/security/sourceAccess.d.ts +12 -0
- package/dist/security/sourceAccess.js +35 -0
- package/package.json +60 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { loadComparisonArtefact } from "../../comparison/store.js";
|
|
3
|
+
import { getCompatibilityReport } from "../../queries/changes.js";
|
|
4
|
+
const SEVERITY = {
|
|
5
|
+
breaking: 0,
|
|
6
|
+
potentially_breaking: 1,
|
|
7
|
+
unknown: 2,
|
|
8
|
+
non_breaking: 3,
|
|
9
|
+
documentation_only: 4,
|
|
10
|
+
not_applicable: 5
|
|
11
|
+
};
|
|
12
|
+
export function runCompatibilityCommand(options) {
|
|
13
|
+
if (!options.comparisonDir) {
|
|
14
|
+
return {
|
|
15
|
+
output: { ok: false, error: { code: "usage_error", message: "--comparison-dir is required" } },
|
|
16
|
+
exitCode: 2
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const loaded = loadComparisonArtefact(path.resolve(options.comparisonDir));
|
|
20
|
+
if (!loaded.ok) {
|
|
21
|
+
return { output: { ok: false, error: loaded.error }, exitCode: 3 };
|
|
22
|
+
}
|
|
23
|
+
const report = getCompatibilityReport(loaded.comparison, {
|
|
24
|
+
offset: options.offset,
|
|
25
|
+
limit: options.limit
|
|
26
|
+
});
|
|
27
|
+
const failOn = options.failOn ?? "never";
|
|
28
|
+
const aggregate = report.aggregate;
|
|
29
|
+
let exitCode = 0;
|
|
30
|
+
if (failOn === "breaking" && aggregate === "breaking")
|
|
31
|
+
exitCode = 1;
|
|
32
|
+
if (failOn === "potentially-breaking" && aggregate && SEVERITY[aggregate] <= SEVERITY.potentially_breaking) {
|
|
33
|
+
exitCode = 1;
|
|
34
|
+
}
|
|
35
|
+
if (failOn === "unknown" && aggregate && SEVERITY[aggregate] <= SEVERITY.unknown)
|
|
36
|
+
exitCode = 1;
|
|
37
|
+
if (failOn === "any-change" || failOn === "any-public-change") {
|
|
38
|
+
if ((loaded.comparison.manifest.counts.added + loaded.comparison.manifest.counts.removed + loaded.comparison.manifest.counts.modified) > 0) {
|
|
39
|
+
exitCode = 1;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return { output: { ok: true, data: report }, exitCode };
|
|
43
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type FailOn = "never" | "unknown" | "potentially-breaking" | "breaking" | "any-public-change" | "any-change";
|
|
2
|
+
export declare function hasPublicFacingChange(input: {
|
|
3
|
+
changes: Array<{
|
|
4
|
+
domain: string;
|
|
5
|
+
status: string;
|
|
6
|
+
}>;
|
|
7
|
+
candidates: Array<{
|
|
8
|
+
domain: string;
|
|
9
|
+
}>;
|
|
10
|
+
compatibilityFindings: Array<{
|
|
11
|
+
ruleId: string;
|
|
12
|
+
classification: string;
|
|
13
|
+
}>;
|
|
14
|
+
}): boolean;
|
|
15
|
+
export declare function runDiffCommand(options: {
|
|
16
|
+
baseWorkspace: string;
|
|
17
|
+
baseCatalogueDir: string;
|
|
18
|
+
headWorkspace: string;
|
|
19
|
+
headCatalogueDir: string;
|
|
20
|
+
writeDir?: string;
|
|
21
|
+
failOn?: FailOn;
|
|
22
|
+
}): {
|
|
23
|
+
output: Record<string, unknown>;
|
|
24
|
+
exitCode: number;
|
|
25
|
+
};
|
|
26
|
+
export declare function runLoadComparisonCommand(options: {
|
|
27
|
+
comparisonDir: string;
|
|
28
|
+
}): {
|
|
29
|
+
output: Record<string, unknown>;
|
|
30
|
+
exitCode: number;
|
|
31
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { loadCataloguePair } from "../../comparison/validate.js";
|
|
3
|
+
import { compareCatalogues } from "../../comparison/compare.js";
|
|
4
|
+
import { writeComparisonArtefact, loadComparisonArtefact } from "../../comparison/store.js";
|
|
5
|
+
import { DEFAULT_COMPARISON_OPTIONS } from "../../comparison/schema.js";
|
|
6
|
+
const SEVERITY = {
|
|
7
|
+
breaking: 0,
|
|
8
|
+
potentially_breaking: 1,
|
|
9
|
+
unknown: 2,
|
|
10
|
+
non_breaking: 3,
|
|
11
|
+
documentation_only: 4,
|
|
12
|
+
not_applicable: 5
|
|
13
|
+
};
|
|
14
|
+
export function hasPublicFacingChange(input) {
|
|
15
|
+
if (input.changes.some((c) => c.domain === "publicApis" && c.status !== "unchanged")) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
if (input.candidates.some((c) => c.domain === "publicApis")) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
if (input.compatibilityFindings.some((f) => f.ruleId.startsWith("public-") ||
|
|
22
|
+
f.ruleId.startsWith("python-console-script") ||
|
|
23
|
+
f.ruleId.startsWith("stability-"))) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
if (input.changes.some((c) => c.domain === "packages" &&
|
|
27
|
+
c.status === "modified" &&
|
|
28
|
+
input.compatibilityFindings.some((f) => f.ruleId.startsWith("python-console-script")))) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
function thresholdReached(failOn, aggregate, counts, publicFacing) {
|
|
34
|
+
if (failOn === "never")
|
|
35
|
+
return false;
|
|
36
|
+
if (failOn === "any-change") {
|
|
37
|
+
return counts.added + counts.removed + counts.modified > 0;
|
|
38
|
+
}
|
|
39
|
+
if (failOn === "any-public-change") {
|
|
40
|
+
return publicFacing;
|
|
41
|
+
}
|
|
42
|
+
if (!aggregate)
|
|
43
|
+
return false;
|
|
44
|
+
if (failOn === "breaking")
|
|
45
|
+
return aggregate === "breaking";
|
|
46
|
+
if (failOn === "potentially-breaking") {
|
|
47
|
+
return SEVERITY[aggregate] <= SEVERITY.potentially_breaking;
|
|
48
|
+
}
|
|
49
|
+
if (failOn === "unknown") {
|
|
50
|
+
return SEVERITY[aggregate] <= SEVERITY.unknown;
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
export function runDiffCommand(options) {
|
|
55
|
+
const pair = loadCataloguePair({
|
|
56
|
+
baseWorkspaceRoot: path.resolve(options.baseWorkspace),
|
|
57
|
+
baseCatalogueDir: options.baseCatalogueDir,
|
|
58
|
+
headWorkspaceRoot: path.resolve(options.headWorkspace),
|
|
59
|
+
headCatalogueDir: options.headCatalogueDir
|
|
60
|
+
});
|
|
61
|
+
if (!pair.ok) {
|
|
62
|
+
const code = pair.error.code === "comparison_path_rejected" ? 4 : 3;
|
|
63
|
+
return { output: { ok: false, error: pair.error }, exitCode: code };
|
|
64
|
+
}
|
|
65
|
+
const compared = compareCatalogues(pair.base, pair.head, DEFAULT_COMPARISON_OPTIONS);
|
|
66
|
+
if (!compared.ok) {
|
|
67
|
+
const code = compared.error.code === "comparison_path_rejected" ? 4 : 3;
|
|
68
|
+
return { output: { ok: false, error: compared.error }, exitCode: code };
|
|
69
|
+
}
|
|
70
|
+
if (options.writeDir) {
|
|
71
|
+
const written = writeComparisonArtefact(path.resolve(options.writeDir), compared.comparison);
|
|
72
|
+
if (!written.ok) {
|
|
73
|
+
return {
|
|
74
|
+
output: { ok: false, error: written.error },
|
|
75
|
+
exitCode: written.error.code === "comparison_path_rejected" ? 4 : 3
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const failOn = options.failOn ?? "never";
|
|
80
|
+
const publicFacing = hasPublicFacingChange(compared.comparison);
|
|
81
|
+
const hit = thresholdReached(failOn, compared.comparison.manifest.aggregateCompatibility, compared.comparison.manifest.counts, publicFacing);
|
|
82
|
+
return {
|
|
83
|
+
output: {
|
|
84
|
+
ok: true,
|
|
85
|
+
data: {
|
|
86
|
+
comparisonId: compared.comparison.manifest.comparisonId,
|
|
87
|
+
counts: compared.comparison.manifest.counts,
|
|
88
|
+
aggregateCompatibility: compared.comparison.manifest.aggregateCompatibility,
|
|
89
|
+
baseCatalogueId: compared.comparison.manifest.baseCatalogueId,
|
|
90
|
+
headCatalogueId: compared.comparison.manifest.headCatalogueId,
|
|
91
|
+
baseGeneratorVersion: compared.comparison.manifest.baseGeneratorVersion,
|
|
92
|
+
headGeneratorVersion: compared.comparison.manifest.headGeneratorVersion,
|
|
93
|
+
warnings: compared.comparison.warnings ?? []
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
exitCode: hit ? 1 : 0
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
export function runLoadComparisonCommand(options) {
|
|
100
|
+
const loaded = loadComparisonArtefact(path.resolve(options.comparisonDir));
|
|
101
|
+
if (!loaded.ok) {
|
|
102
|
+
return {
|
|
103
|
+
output: { ok: false, error: loaded.error },
|
|
104
|
+
exitCode: loaded.error.code === "comparison_path_rejected" ? 4 : 3
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
output: {
|
|
109
|
+
ok: true,
|
|
110
|
+
data: {
|
|
111
|
+
comparisonId: loaded.comparison.manifest.comparisonId,
|
|
112
|
+
counts: loaded.comparison.manifest.counts,
|
|
113
|
+
aggregateCompatibility: loaded.comparison.manifest.aggregateCompatibility
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
exitCode: 0
|
|
117
|
+
};
|
|
118
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface DogfoodCommandOptions {
|
|
2
|
+
workspace: string;
|
|
3
|
+
config?: string;
|
|
4
|
+
mode?: "committed" | "local" | "memory";
|
|
5
|
+
maxDiagnostics?: number;
|
|
6
|
+
maxGaps?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function runDogfoodCommand(options: DogfoodCommandOptions): Record<string, unknown>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { indexWorkspace } from "../../catalogue/indexer.js";
|
|
3
|
+
import { getDogfoodReport } from "../../queries/dogfood.js";
|
|
4
|
+
export function runDogfoodCommand(options) {
|
|
5
|
+
const workspaceRoot = path.resolve(options.workspace);
|
|
6
|
+
const { snapshot } = indexWorkspace({
|
|
7
|
+
workspaceRoot,
|
|
8
|
+
configPath: options.config,
|
|
9
|
+
mode: options.mode ?? "local",
|
|
10
|
+
write: false
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
ok: true,
|
|
14
|
+
data: getDogfoodReport(snapshot, {
|
|
15
|
+
workspace: workspaceRoot,
|
|
16
|
+
maxDiagnostics: options.maxDiagnostics,
|
|
17
|
+
maxGaps: options.maxGaps
|
|
18
|
+
}),
|
|
19
|
+
warnings: [],
|
|
20
|
+
provenance: {
|
|
21
|
+
source: "mapwright"
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { checkCatalogueDrift } from "../../comparison/drift.js";
|
|
3
|
+
export function runDriftCommand(options) {
|
|
4
|
+
const result = checkCatalogueDrift({
|
|
5
|
+
workspaceRoot: path.resolve(options.workspace),
|
|
6
|
+
catalogueDir: options.catalogueDir,
|
|
7
|
+
configPath: options.config
|
|
8
|
+
});
|
|
9
|
+
if (!result.ok) {
|
|
10
|
+
return { output: { ok: false, error: result.error }, exitCode: 3 };
|
|
11
|
+
}
|
|
12
|
+
return { output: { ok: true, data: result.data }, exitCode: 0 };
|
|
13
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./indexWorkspace.js";
|
|
2
|
+
export * from "./validate.js";
|
|
3
|
+
export * from "./check.js";
|
|
4
|
+
export * from "./schema.js";
|
|
5
|
+
export * from "./auditDocs.js";
|
|
6
|
+
export * from "./adoptionPlan.js";
|
|
7
|
+
export * from "./template.js";
|
|
8
|
+
export * from "./dogfood.js";
|
|
9
|
+
export * from "./recommendConfig.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./indexWorkspace.js";
|
|
2
|
+
export * from "./validate.js";
|
|
3
|
+
export * from "./check.js";
|
|
4
|
+
export * from "./schema.js";
|
|
5
|
+
export * from "./auditDocs.js";
|
|
6
|
+
export * from "./adoptionPlan.js";
|
|
7
|
+
export * from "./template.js";
|
|
8
|
+
export * from "./dogfood.js";
|
|
9
|
+
export * from "./recommendConfig.js";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { indexWorkspace } from "../../catalogue/indexer.js";
|
|
3
|
+
export function runIndexCommand(options) {
|
|
4
|
+
const workspaceRoot = path.resolve(options.workspace);
|
|
5
|
+
const { snapshot } = indexWorkspace({
|
|
6
|
+
workspaceRoot,
|
|
7
|
+
configPath: options.config,
|
|
8
|
+
mode: options.mode,
|
|
9
|
+
write: options.write,
|
|
10
|
+
pretty: options.pretty
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
ok: true,
|
|
14
|
+
data: {
|
|
15
|
+
catalogueId: snapshot.catalogueId,
|
|
16
|
+
stats: snapshot.stats
|
|
17
|
+
},
|
|
18
|
+
warnings: [],
|
|
19
|
+
provenance: {
|
|
20
|
+
source: "cli:index"
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface RecommendConfigCommandOptions {
|
|
2
|
+
workspace: string;
|
|
3
|
+
config?: string;
|
|
4
|
+
mode?: "committed" | "local" | "memory";
|
|
5
|
+
limit?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function runRecommendConfigCommand(options: RecommendConfigCommandOptions): Record<string, unknown>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { indexWorkspace } from "../../catalogue/indexer.js";
|
|
3
|
+
import { recommendConfig } from "../../queries/recommendConfig.js";
|
|
4
|
+
export function runRecommendConfigCommand(options) {
|
|
5
|
+
const workspaceRoot = path.resolve(options.workspace);
|
|
6
|
+
const { snapshot } = indexWorkspace({
|
|
7
|
+
workspaceRoot,
|
|
8
|
+
configPath: options.config,
|
|
9
|
+
mode: options.mode ?? "memory",
|
|
10
|
+
write: false
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
ok: true,
|
|
14
|
+
data: recommendConfig(snapshot, { limit: options.limit }),
|
|
15
|
+
warnings: [],
|
|
16
|
+
provenance: {
|
|
17
|
+
source: "mapwright"
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runSchemaCommand(): Record<string, unknown>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { CURRENT_SCHEMA_VERSION, SUPPORTED_SCHEMA_VERSIONS, SUPPORTED_IDENTITY_SCHEMES } from "../../catalogue/store.js";
|
|
2
|
+
import { IDENTITY_SCHEME } from "../../catalogue/identity.js";
|
|
3
|
+
export function runSchemaCommand() {
|
|
4
|
+
return {
|
|
5
|
+
ok: true,
|
|
6
|
+
data: {
|
|
7
|
+
schemaVersion: CURRENT_SCHEMA_VERSION,
|
|
8
|
+
supportedSchemaVersions: [...SUPPORTED_SCHEMA_VERSIONS],
|
|
9
|
+
identityScheme: IDENTITY_SCHEME,
|
|
10
|
+
supportedIdentitySchemes: [...SUPPORTED_IDENTITY_SCHEMES],
|
|
11
|
+
snapshot: {
|
|
12
|
+
required: [
|
|
13
|
+
"schemaVersion",
|
|
14
|
+
"identityScheme",
|
|
15
|
+
"catalogueId",
|
|
16
|
+
"generator",
|
|
17
|
+
"mode",
|
|
18
|
+
"stats",
|
|
19
|
+
"files",
|
|
20
|
+
"packages",
|
|
21
|
+
"capabilities",
|
|
22
|
+
"publicApis",
|
|
23
|
+
"examples",
|
|
24
|
+
"symbols",
|
|
25
|
+
"relationships",
|
|
26
|
+
"tests",
|
|
27
|
+
"diagnostics",
|
|
28
|
+
"provenance"
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
warnings: [],
|
|
33
|
+
provenance: {
|
|
34
|
+
source: "cli:schema"
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { getDocumentationTemplate, listDocumentationTemplateIds, listDocumentationTemplates } from "../../catalogue/templates.js";
|
|
2
|
+
export function runTemplateCommand(options) {
|
|
3
|
+
if (options.list) {
|
|
4
|
+
return {
|
|
5
|
+
ok: true,
|
|
6
|
+
data: {
|
|
7
|
+
templates: listDocumentationTemplates()
|
|
8
|
+
},
|
|
9
|
+
warnings: [],
|
|
10
|
+
provenance: {
|
|
11
|
+
source: "mapwright"
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const templateId = options.templateId ?? "";
|
|
16
|
+
if (!isDocumentationTemplateId(templateId)) {
|
|
17
|
+
return {
|
|
18
|
+
ok: false,
|
|
19
|
+
error: {
|
|
20
|
+
code: "template_not_found",
|
|
21
|
+
message: `Unknown template ${templateId}.`
|
|
22
|
+
},
|
|
23
|
+
warnings: [],
|
|
24
|
+
data: {
|
|
25
|
+
availableTemplateIds: listDocumentationTemplateIds(),
|
|
26
|
+
templates: listDocumentationTemplates()
|
|
27
|
+
},
|
|
28
|
+
provenance: {
|
|
29
|
+
source: "mapwright"
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
ok: true,
|
|
35
|
+
data: getDocumentationTemplate(templateId),
|
|
36
|
+
warnings: [],
|
|
37
|
+
provenance: {
|
|
38
|
+
source: "mapwright"
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function isDocumentationTemplateId(value) {
|
|
43
|
+
return listDocumentationTemplateIds().includes(value);
|
|
44
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface ValidateCommandOptions {
|
|
2
|
+
workspace: string;
|
|
3
|
+
config?: string;
|
|
4
|
+
failOn?: "info" | "warning" | "error" | "never";
|
|
5
|
+
}
|
|
6
|
+
export declare function runValidateCommand(options: ValidateCommandOptions): {
|
|
7
|
+
output: Record<string, unknown>;
|
|
8
|
+
exitCode: number;
|
|
9
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { indexWorkspace, shouldFailFromDiagnostics, staleCommittedCatalogue } from "../../catalogue/indexer.js";
|
|
4
|
+
import { loadConfig } from "../../catalogue/config.js";
|
|
5
|
+
import { OUTPUT_FILES } from "../../catalogue/store.js";
|
|
6
|
+
export function runValidateCommand(options) {
|
|
7
|
+
const workspaceRoot = path.resolve(options.workspace);
|
|
8
|
+
const { config } = loadConfig({ workspaceRoot, configPath: options.config });
|
|
9
|
+
const { snapshot } = indexWorkspace({ workspaceRoot, configPath: options.config, mode: "committed", write: false });
|
|
10
|
+
let state = "catalogue_current";
|
|
11
|
+
const diagnostics = [...snapshot.diagnostics];
|
|
12
|
+
const committedPath = path.resolve(workspaceRoot, config.catalogueDir, OUTPUT_FILES.catalogue);
|
|
13
|
+
if (config.committedCatalogue) {
|
|
14
|
+
if (!existsSync(committedPath)) {
|
|
15
|
+
state = "catalogue_missing";
|
|
16
|
+
diagnostics.push({
|
|
17
|
+
id: "diag:catalogue_missing",
|
|
18
|
+
severity: "error",
|
|
19
|
+
category: "determinism",
|
|
20
|
+
code: "catalogue_missing",
|
|
21
|
+
message: "Committed catalogue file is missing.",
|
|
22
|
+
provenance: { source: "validate" }
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
try {
|
|
27
|
+
JSON.parse(readFileSync(committedPath, "utf8"));
|
|
28
|
+
const stale = staleCommittedCatalogue(workspaceRoot, snapshot, config.catalogueDir);
|
|
29
|
+
if (stale) {
|
|
30
|
+
state = "catalogue_stale";
|
|
31
|
+
diagnostics.push({
|
|
32
|
+
id: "diag:catalogue_stale",
|
|
33
|
+
severity: "error",
|
|
34
|
+
category: "determinism",
|
|
35
|
+
code: "catalogue_stale",
|
|
36
|
+
message: "Committed catalogue is stale compared with indexed snapshot.",
|
|
37
|
+
provenance: { source: "validate" }
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
state = "catalogue_unreadable";
|
|
43
|
+
diagnostics.push({
|
|
44
|
+
id: "diag:catalogue_unreadable",
|
|
45
|
+
severity: "error",
|
|
46
|
+
category: "determinism",
|
|
47
|
+
code: "catalogue_unreadable",
|
|
48
|
+
message: "Committed catalogue exists but cannot be parsed.",
|
|
49
|
+
provenance: { source: "validate" }
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const failOn = options.failOn ?? config.validation.failOn;
|
|
55
|
+
const diagnosticsFailedThreshold = shouldFailFromDiagnostics(failOn, diagnostics);
|
|
56
|
+
const structuralFailure = config.committedCatalogue && state !== "catalogue_current";
|
|
57
|
+
const failed = structuralFailure || diagnosticsFailedThreshold;
|
|
58
|
+
if (diagnosticsFailedThreshold) {
|
|
59
|
+
diagnostics.push({
|
|
60
|
+
id: "diag:diagnostics_failed_threshold",
|
|
61
|
+
severity: "error",
|
|
62
|
+
category: "determinism",
|
|
63
|
+
code: "diagnostics_failed_threshold",
|
|
64
|
+
message: `Diagnostics met or exceeded configured fail threshold ${failOn}.`,
|
|
65
|
+
provenance: { source: "validate" }
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
diagnostics.sort((a, b) => a.id.localeCompare(b.id));
|
|
69
|
+
return {
|
|
70
|
+
output: {
|
|
71
|
+
ok: !failed,
|
|
72
|
+
data: {
|
|
73
|
+
state,
|
|
74
|
+
diagnostics,
|
|
75
|
+
failOn,
|
|
76
|
+
diagnosticsFailedThreshold
|
|
77
|
+
},
|
|
78
|
+
warnings: [],
|
|
79
|
+
provenance: {
|
|
80
|
+
source: "cli:validate"
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
exitCode: failed ? 1 : 0
|
|
84
|
+
};
|
|
85
|
+
}
|