@buoy-design/cli 0.8.1 → 0.8.3
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/commands/fix.d.ts.map +1 -1
- package/dist/commands/fix.js +17 -0
- package/dist/commands/fix.js.map +1 -1
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +9 -2
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/scan.d.ts.map +1 -1
- package/dist/commands/scan.js +26 -1
- package/dist/commands/scan.js.map +1 -1
- package/dist/commands/tokens.d.ts.map +1 -1
- package/dist/commands/tokens.js +4 -71
- package/dist/commands/tokens.js.map +1 -1
- package/dist/config/auto-detect.js +6 -6
- package/dist/config/auto-detect.js.map +1 -1
- package/dist/detect/frameworks.js +6 -6
- package/dist/detect/frameworks.js.map +1 -1
- package/dist/detect/project-detector.js +13 -13
- package/dist/detect/project-detector.js.map +1 -1
- package/dist/mcp/file-check.d.ts.map +1 -1
- package/dist/mcp/file-check.js +5 -2
- package/dist/mcp/file-check.js.map +1 -1
- package/dist/mcp/hook.d.ts +0 -5
- package/dist/mcp/hook.d.ts.map +1 -1
- package/dist/mcp/hook.js +13 -2
- package/dist/mcp/hook.js.map +1 -1
- package/dist/mcp/project.d.ts +5 -0
- package/dist/mcp/project.d.ts.map +1 -1
- package/dist/mcp/project.js +42 -7
- package/dist/mcp/project.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +43 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/services/drift-analysis.d.ts.map +1 -1
- package/dist/services/drift-analysis.js +38 -32
- package/dist/services/drift-analysis.js.map +1 -1
- package/dist/services/inferred-system.d.ts +50 -0
- package/dist/services/inferred-system.d.ts.map +1 -0
- package/dist/services/inferred-system.js +167 -0
- package/dist/services/inferred-system.js.map +1 -0
- package/dist/services/stylesheet-drift.d.ts +8 -0
- package/dist/services/stylesheet-drift.d.ts.map +1 -0
- package/dist/services/stylesheet-drift.js +108 -0
- package/dist/services/stylesheet-drift.js.map +1 -0
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +2 -3
- package/dist/store/index.js.map +1 -1
- package/package.json +3 -3
package/dist/mcp/project.js
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Both need the same thing: this repo's tokens, and drift for some files.
|
|
5
5
|
* Everything here reuses the CLI's scan pipeline; nothing is re-detected.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { existsSync } from "node:fs";
|
|
8
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
8
9
|
import { loadConfig, getConfigPath } from "../config/loader.js";
|
|
9
10
|
import { buildAutoConfig } from "../config/auto-detect.js";
|
|
10
11
|
import { ScanOrchestrator } from "../scan/orchestrator.js";
|
|
@@ -17,8 +18,23 @@ export async function loadProject(cwd) {
|
|
|
17
18
|
const loaded = await loadConfig(cwd);
|
|
18
19
|
return { config: loaded.config, projectRoot: loaded.configPath ? dirname(loaded.configPath) : cwd };
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
// No config: agents and hooks can run from a subdirectory, where the repo's
|
|
22
|
+
// tokens are out of sight. Use the repository root instead.
|
|
23
|
+
const root = findRepoRoot(cwd) ?? cwd;
|
|
24
|
+
const auto = await buildAutoConfig(root);
|
|
25
|
+
return { config: auto.config, projectRoot: root };
|
|
26
|
+
}
|
|
27
|
+
/** The nearest ancestor with a `.git` entry (a directory, or a file in worktrees). */
|
|
28
|
+
export function findRepoRoot(start) {
|
|
29
|
+
let current = resolve(start);
|
|
30
|
+
while (true) {
|
|
31
|
+
if (existsSync(join(current, ".git")))
|
|
32
|
+
return current;
|
|
33
|
+
const parent = dirname(current);
|
|
34
|
+
if (parent === current)
|
|
35
|
+
return null;
|
|
36
|
+
current = parent;
|
|
37
|
+
}
|
|
22
38
|
}
|
|
23
39
|
export function formatTokenValue(token) {
|
|
24
40
|
const v = token.value;
|
|
@@ -51,11 +67,22 @@ export function normalizeValue(value) {
|
|
|
51
67
|
v = v.replace(/(\d)\.0+(px|rem|em|%)?$/, "$1$2").replace(/^0(px|rem|em)$/, "0");
|
|
52
68
|
return v;
|
|
53
69
|
}
|
|
70
|
+
/** Root font size used to compare px with rem, matching core's token suggestions. */
|
|
71
|
+
const BASE_FONT_SIZE_PX = 16;
|
|
72
|
+
/** `1rem` and `16px` are the same length; compare them as px. */
|
|
73
|
+
function comparableValue(value) {
|
|
74
|
+
const v = normalizeValue(value);
|
|
75
|
+
const rem = /^(-?\d*\.?\d+)rem$/.exec(v);
|
|
76
|
+
if (!rem)
|
|
77
|
+
return v;
|
|
78
|
+
const px = Math.round(parseFloat(rem[1]) * BASE_FONT_SIZE_PX * 1000) / 1000;
|
|
79
|
+
return px === 0 ? "0" : `${px}px`;
|
|
80
|
+
}
|
|
54
81
|
export function findTokensByValue(tokens, value, category) {
|
|
55
|
-
const wanted =
|
|
82
|
+
const wanted = comparableValue(value);
|
|
56
83
|
return tokens
|
|
57
84
|
.filter((t) => !category || t.category === category)
|
|
58
|
-
.filter((t) =>
|
|
85
|
+
.filter((t) => comparableValue(formatTokenValue(t)) === wanted)
|
|
59
86
|
.map(summarizeToken);
|
|
60
87
|
}
|
|
61
88
|
export async function scanTokens(project) {
|
|
@@ -98,10 +125,18 @@ function summarize(issues, tokenCount) {
|
|
|
98
125
|
*/
|
|
99
126
|
export async function checkDrift(project, files, tokens) {
|
|
100
127
|
if (files && files.length > 0) {
|
|
101
|
-
const
|
|
128
|
+
const notFound = files.filter((file) => !existsSync(isAbsolute(file) ? file : join(project.projectRoot, file)));
|
|
129
|
+
const scannable = filterScannableFiles(files.filter((file) => !notFound.includes(file)));
|
|
102
130
|
const known = tokens ?? (await scanTokens(project));
|
|
103
131
|
const issues = scannable.length ? await checkFiles(scannable, project.projectRoot, known) : [];
|
|
104
|
-
|
|
132
|
+
const check = summarize(issues, known.length);
|
|
133
|
+
if (notFound.length === 0)
|
|
134
|
+
return check;
|
|
135
|
+
return {
|
|
136
|
+
...check,
|
|
137
|
+
notFound,
|
|
138
|
+
note: `Not checked, no such file: ${notFound.join(", ")}. Paths are relative to ${project.projectRoot} or absolute.`,
|
|
139
|
+
};
|
|
105
140
|
}
|
|
106
141
|
const service = new DriftAnalysisService(project.config, project.projectRoot);
|
|
107
142
|
const result = await service.analyze({ includeIgnored: false });
|
package/dist/mcp/project.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/mcp/project.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/mcp/project.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAkBpE,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,CAqJtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAGvE"}
|
package/dist/mcp/server.js
CHANGED
|
@@ -9,6 +9,7 @@ import { z } from "zod";
|
|
|
9
9
|
import { generateContext } from "../services/context-generator.js";
|
|
10
10
|
import { ScanOrchestrator } from "../scan/orchestrator.js";
|
|
11
11
|
import { checkDrift, findTokensByValue, loadProject, scanTokens, summarizeToken, } from "./project.js";
|
|
12
|
+
import { inferDesignSystem, normalizeLiteral, summarizeInferredSystem } from "../services/inferred-system.js";
|
|
12
13
|
const TOKEN_CACHE_MS = 30_000;
|
|
13
14
|
export function createBuoyMcpServer(options) {
|
|
14
15
|
const server = new McpServer({ name: "buoy", version: options.version });
|
|
@@ -22,6 +23,16 @@ export function createBuoyMcpServer(options) {
|
|
|
22
23
|
tokenCache = { at: Date.now(), tokens };
|
|
23
24
|
return tokens;
|
|
24
25
|
};
|
|
26
|
+
let inferredCache = null;
|
|
27
|
+
// Repos with no tokens still have a de facto system: the values they use most.
|
|
28
|
+
const getInferred = async () => {
|
|
29
|
+
if (inferredCache && Date.now() - inferredCache.at < TOKEN_CACHE_MS)
|
|
30
|
+
return inferredCache.system;
|
|
31
|
+
const proj = await getProject();
|
|
32
|
+
const system = await inferDesignSystem(proj.projectRoot, proj.config).catch(() => null);
|
|
33
|
+
inferredCache = { at: Date.now(), system: system && system.tokens.length > 0 ? summarizeInferredSystem(system, 200) : null };
|
|
34
|
+
return inferredCache.system;
|
|
35
|
+
};
|
|
25
36
|
const json = (value) => ({ content: [{ type: "text", text: JSON.stringify(value, null, 2) }] });
|
|
26
37
|
server.registerTool("list_design_tokens", {
|
|
27
38
|
title: "List design tokens",
|
|
@@ -45,7 +56,7 @@ export function createBuoyMcpServer(options) {
|
|
|
45
56
|
byCategory,
|
|
46
57
|
matched: matched.length,
|
|
47
58
|
tokens: matched.slice(0, limit ?? 200).map(summarizeToken),
|
|
48
|
-
...(tokens.length === 0 ?
|
|
59
|
+
...(tokens.length === 0 ? await inferredFallback(category, q) : {}),
|
|
49
60
|
});
|
|
50
61
|
});
|
|
51
62
|
server.registerTool("find_token_for_value", {
|
|
@@ -56,7 +67,22 @@ export function createBuoyMcpServer(options) {
|
|
|
56
67
|
category: z.string().optional().describe("Restrict to a category such as color or spacing"),
|
|
57
68
|
},
|
|
58
69
|
}, async ({ value, category }) => {
|
|
59
|
-
const
|
|
70
|
+
const tokens = await getTokens();
|
|
71
|
+
const matches = findTokensByValue(tokens, value, category);
|
|
72
|
+
if (tokens.length === 0) {
|
|
73
|
+
const inferred = await getInferred();
|
|
74
|
+
const wanted = normalizeLiteral(value);
|
|
75
|
+
const hit = inferred?.tokens.find((t) => (!category || t.category === category) &&
|
|
76
|
+
(normalizeLiteral(t.value) === wanted || t.replaces?.includes(wanted)));
|
|
77
|
+
return json({
|
|
78
|
+
value,
|
|
79
|
+
matches: [],
|
|
80
|
+
inferredMatch: hit ?? null,
|
|
81
|
+
suggestion: hit
|
|
82
|
+
? `This repo has no tokens yet. Its most-used equivalent is ${hit.value} (${hit.uses} uses); write ${hit.value} so values stay consistent.`
|
|
83
|
+
: null,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
60
86
|
return json({ value, matches, suggestion: matches[0] ? `Use ${matches[0].name} instead of ${value}` : null });
|
|
61
87
|
});
|
|
62
88
|
server.registerTool("check_design_drift", {
|
|
@@ -89,6 +115,21 @@ export function createBuoyMcpServer(options) {
|
|
|
89
115
|
const result = generateContext({ tokens: scan.tokens, components: scan.components, drifts: diff.drifts, projectName: proj.projectRoot.split("/").pop() || "project" }, { detailLevel: detail ?? "standard" });
|
|
90
116
|
return { content: [{ type: "text", text: result.content }] };
|
|
91
117
|
});
|
|
118
|
+
async function inferredFallback(category, q) {
|
|
119
|
+
const inferred = await getInferred();
|
|
120
|
+
if (!inferred) {
|
|
121
|
+
return { note: "No tokens found and no repeated hardcoded values to infer from." };
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
note: "This repo has no design tokens yet. `inferred` is the system its code already uses (most-used values, near-duplicates merged). Reuse these exact values instead of inventing new ones, and prefer `use` over each `insteadOf` value. `buoy dock tokens` turns them into a tokens file.",
|
|
125
|
+
inferred: {
|
|
126
|
+
...inferred,
|
|
127
|
+
tokens: inferred.tokens
|
|
128
|
+
.filter((t) => !category || t.category === category)
|
|
129
|
+
.filter((t) => !q || t.name.toLowerCase().includes(q)),
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
92
133
|
return server;
|
|
93
134
|
}
|
|
94
135
|
export async function serveStdio(options) {
|
package/dist/mcp/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,UAAU,EACV,cAAc,GAEf,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drift-analysis.d.ts","sourceRoot":"","sources":["../../src/services/drift-analysis.ts"],"names":[],"mappings":"AACA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"drift-analysis.d.ts","sourceRoot":"","sources":["../../src/services/drift-analysis.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { ScanOrchestrator } from "../scan/orchestrator.js";
|
|
12
12
|
import { consolidateRepeatedPatterns } from "./repeated-patterns.js";
|
|
13
|
-
import {
|
|
13
|
+
import { checkStylesheets, stylesheetIssuesToDrifts } from "./stylesheet-drift.js";
|
|
14
|
+
import { getSeverityWeight, classifyFileContext, findStringLiterals } from "@buoy-design/core";
|
|
14
15
|
import { readFileSync } from "fs";
|
|
15
16
|
import { TailwindScanner, extractStaticClassStrings, } from "@buoy-design/scanners";
|
|
16
17
|
import { detectRepeatedPatterns, checkVariantConsistency, checkExampleCompliance, detectTokenUtilities, checkTokenUtilityUsage, } from "@buoy-design/core";
|
|
@@ -592,6 +593,13 @@ export class DriftAnalysisService {
|
|
|
592
593
|
onProgress?.(`Found ${tailwindResult.drifts.length} Tailwind arbitrary value issues`);
|
|
593
594
|
}
|
|
594
595
|
}
|
|
596
|
+
// Step 2.55: Hardcoded values in stylesheets and <style> blocks, with the
|
|
597
|
+
// same per-line rules the agent hook and PR reviews apply.
|
|
598
|
+
if (isDriftTypeEnabled(this.config, "hardcoded-value")) {
|
|
599
|
+
onProgress?.("Checking stylesheets...");
|
|
600
|
+
const stylesheetDrifts = stylesheetIssuesToDrifts(await checkStylesheets(this.projectRoot, scannedTokens), this.projectRoot);
|
|
601
|
+
drifts.push(...applySeverityOverrides(stylesheetDrifts, this.config.drift.severity));
|
|
602
|
+
}
|
|
595
603
|
// Step 2.6: Repeated pattern detection (always-on, opt-out via config)
|
|
596
604
|
const repeatedPatternConfig = (this.config.drift?.types?.["repeated-pattern"] ?? {});
|
|
597
605
|
if (repeatedPatternConfig.enabled !== false) {
|
|
@@ -745,12 +753,12 @@ export class DriftAnalysisService {
|
|
|
745
753
|
"**/build/**",
|
|
746
754
|
"**/.next/**",
|
|
747
755
|
];
|
|
748
|
-
const files = await glob(include, {
|
|
756
|
+
const files = (await glob(include, {
|
|
749
757
|
cwd: this.projectRoot,
|
|
750
758
|
ignore: exclude,
|
|
751
759
|
absolute: false,
|
|
752
760
|
nodir: true,
|
|
753
|
-
});
|
|
761
|
+
})).sort();
|
|
754
762
|
for (const file of files) {
|
|
755
763
|
let content = "";
|
|
756
764
|
try {
|
|
@@ -871,10 +879,8 @@ export class DriftAnalysisService {
|
|
|
871
879
|
extractTailwindClassTokens(content) {
|
|
872
880
|
const classTokens = new Set();
|
|
873
881
|
// Generic string literal scan catches JSX, Astro, template literals, and utility wrappers.
|
|
874
|
-
const
|
|
875
|
-
|
|
876
|
-
while ((match = stringPattern.exec(content)) !== null) {
|
|
877
|
-
const raw = match[2];
|
|
882
|
+
for (const literal of findStringLiterals(content)) {
|
|
883
|
+
const raw = literal.value;
|
|
878
884
|
if (!raw || (!raw.includes("-") && !raw.includes(":")))
|
|
879
885
|
continue;
|
|
880
886
|
for (const token of raw.split(/\s+/)) {
|
|
@@ -895,7 +901,7 @@ export class DriftAnalysisService {
|
|
|
895
901
|
*/
|
|
896
902
|
async scanBarrelReExports(componentUsageMap) {
|
|
897
903
|
const cwd = this.projectRoot;
|
|
898
|
-
const barrelFiles = await glob("**/index.{ts,tsx,js,jsx}", {
|
|
904
|
+
const barrelFiles = (await glob("**/index.{ts,tsx,js,jsx}", {
|
|
899
905
|
cwd,
|
|
900
906
|
ignore: [
|
|
901
907
|
"**/node_modules/**",
|
|
@@ -905,7 +911,7 @@ export class DriftAnalysisService {
|
|
|
905
911
|
],
|
|
906
912
|
nodir: true,
|
|
907
913
|
maxDepth: 6,
|
|
908
|
-
});
|
|
914
|
+
})).sort();
|
|
909
915
|
for (const barrelFile of barrelFiles.slice(0, 200)) {
|
|
910
916
|
try {
|
|
911
917
|
const content = await readFile(resolve(cwd, barrelFile), "utf-8");
|
|
@@ -954,7 +960,7 @@ export class DriftAnalysisService {
|
|
|
954
960
|
*/
|
|
955
961
|
async scanDynamicImports(componentUsageMap) {
|
|
956
962
|
const cwd = this.projectRoot;
|
|
957
|
-
const sourceFiles = await glob("**/*.{tsx,jsx,ts,js}", {
|
|
963
|
+
const sourceFiles = (await glob("**/*.{tsx,jsx,ts,js}", {
|
|
958
964
|
cwd,
|
|
959
965
|
ignore: [
|
|
960
966
|
"**/node_modules/**",
|
|
@@ -966,7 +972,7 @@ export class DriftAnalysisService {
|
|
|
966
972
|
],
|
|
967
973
|
nodir: true,
|
|
968
974
|
maxDepth: 6,
|
|
969
|
-
});
|
|
975
|
+
})).sort();
|
|
970
976
|
for (const file of sourceFiles.slice(0, 200)) {
|
|
971
977
|
try {
|
|
972
978
|
const content = await readFile(resolve(cwd, file), "utf-8");
|
|
@@ -998,7 +1004,7 @@ export class DriftAnalysisService {
|
|
|
998
1004
|
if (knownComponents.length === 0)
|
|
999
1005
|
return;
|
|
1000
1006
|
const cwd = this.projectRoot;
|
|
1001
|
-
const templateFiles = await glob("**/*.{vue,svelte,html}", {
|
|
1007
|
+
const templateFiles = (await glob("**/*.{vue,svelte,html}", {
|
|
1002
1008
|
cwd,
|
|
1003
1009
|
ignore: [
|
|
1004
1010
|
"**/node_modules/**",
|
|
@@ -1008,7 +1014,7 @@ export class DriftAnalysisService {
|
|
|
1008
1014
|
],
|
|
1009
1015
|
nodir: true,
|
|
1010
1016
|
maxDepth: 8,
|
|
1011
|
-
});
|
|
1017
|
+
})).sort();
|
|
1012
1018
|
const knownSet = new Set(knownComponents);
|
|
1013
1019
|
// Build a kebab-case lookup for Vue/Angular (MyComponent -> my-component)
|
|
1014
1020
|
const kebabMap = new Map();
|
|
@@ -1052,7 +1058,7 @@ export class DriftAnalysisService {
|
|
|
1052
1058
|
*/
|
|
1053
1059
|
async scanAutoRegistration(componentUsageMap) {
|
|
1054
1060
|
const cwd = this.projectRoot;
|
|
1055
|
-
const sourceFiles = await glob("**/*.{ts,js,tsx,jsx}", {
|
|
1061
|
+
const sourceFiles = (await glob("**/*.{ts,js,tsx,jsx}", {
|
|
1056
1062
|
cwd,
|
|
1057
1063
|
ignore: [
|
|
1058
1064
|
"**/node_modules/**",
|
|
@@ -1062,7 +1068,7 @@ export class DriftAnalysisService {
|
|
|
1062
1068
|
],
|
|
1063
1069
|
nodir: true,
|
|
1064
1070
|
maxDepth: 4,
|
|
1065
|
-
});
|
|
1071
|
+
})).sort();
|
|
1066
1072
|
for (const file of sourceFiles.slice(0, 100)) {
|
|
1067
1073
|
try {
|
|
1068
1074
|
const content = await readFile(resolve(cwd, file), "utf-8");
|
|
@@ -1087,12 +1093,12 @@ export class DriftAnalysisService {
|
|
|
1087
1093
|
*/
|
|
1088
1094
|
async scanNgModuleDeclarations(componentUsageMap) {
|
|
1089
1095
|
const cwd = this.projectRoot;
|
|
1090
|
-
const moduleFiles = await glob("**/*.module.ts", {
|
|
1096
|
+
const moduleFiles = (await glob("**/*.module.ts", {
|
|
1091
1097
|
cwd,
|
|
1092
1098
|
ignore: ["**/node_modules/**", "**/dist/**", "**/build/**"],
|
|
1093
1099
|
nodir: true,
|
|
1094
1100
|
maxDepth: 8,
|
|
1095
|
-
});
|
|
1101
|
+
})).sort();
|
|
1096
1102
|
for (const file of moduleFiles.slice(0, 50)) {
|
|
1097
1103
|
try {
|
|
1098
1104
|
const content = await readFile(resolve(cwd, file), "utf-8");
|
|
@@ -1132,12 +1138,12 @@ export class DriftAnalysisService {
|
|
|
1132
1138
|
*/
|
|
1133
1139
|
async scanStoryFileUsages(componentUsageMap) {
|
|
1134
1140
|
const cwd = this.projectRoot;
|
|
1135
|
-
const storyFiles = await glob("**/*.stories.{ts,tsx,js,jsx}", {
|
|
1141
|
+
const storyFiles = (await glob("**/*.stories.{ts,tsx,js,jsx}", {
|
|
1136
1142
|
cwd,
|
|
1137
1143
|
ignore: ["**/node_modules/**", "**/dist/**", "**/build/**"],
|
|
1138
1144
|
nodir: true,
|
|
1139
1145
|
maxDepth: 8,
|
|
1140
|
-
});
|
|
1146
|
+
})).sort();
|
|
1141
1147
|
for (const file of storyFiles.slice(0, 200)) {
|
|
1142
1148
|
try {
|
|
1143
1149
|
const content = await readFile(resolve(cwd, file), "utf-8");
|
|
@@ -1181,7 +1187,7 @@ export class DriftAnalysisService {
|
|
|
1181
1187
|
*/
|
|
1182
1188
|
async scanWebComponentRegistrations(componentUsageMap) {
|
|
1183
1189
|
const cwd = this.projectRoot;
|
|
1184
|
-
const files = await glob("**/*.{ts,js}", {
|
|
1190
|
+
const files = (await glob("**/*.{ts,js}", {
|
|
1185
1191
|
cwd,
|
|
1186
1192
|
ignore: [
|
|
1187
1193
|
"**/node_modules/**",
|
|
@@ -1193,7 +1199,7 @@ export class DriftAnalysisService {
|
|
|
1193
1199
|
],
|
|
1194
1200
|
nodir: true,
|
|
1195
1201
|
maxDepth: 8,
|
|
1196
|
-
});
|
|
1202
|
+
})).sort();
|
|
1197
1203
|
for (const file of files.slice(0, 500)) {
|
|
1198
1204
|
try {
|
|
1199
1205
|
const content = await readFile(resolve(cwd, file), "utf-8");
|
|
@@ -1225,10 +1231,10 @@ export class DriftAnalysisService {
|
|
|
1225
1231
|
async scanNuxtAutoImports(componentUsageMap, componentNames) {
|
|
1226
1232
|
const cwd = this.projectRoot;
|
|
1227
1233
|
// Check for Nuxt config
|
|
1228
|
-
const nuxtConfigs = await glob("nuxt.config.{ts,js,mjs}", {
|
|
1234
|
+
const nuxtConfigs = (await glob("nuxt.config.{ts,js,mjs}", {
|
|
1229
1235
|
cwd,
|
|
1230
1236
|
nodir: true,
|
|
1231
|
-
});
|
|
1237
|
+
})).sort();
|
|
1232
1238
|
if (nuxtConfigs.length === 0)
|
|
1233
1239
|
return;
|
|
1234
1240
|
// In Nuxt, all components in components/ are auto-imported
|
|
@@ -1243,12 +1249,12 @@ export class DriftAnalysisService {
|
|
|
1243
1249
|
*/
|
|
1244
1250
|
async scanTestFileUsages(componentUsageMap) {
|
|
1245
1251
|
const cwd = this.projectRoot;
|
|
1246
|
-
const testFiles = await glob("**/*.{test,spec}.{ts,tsx,js,jsx}", {
|
|
1252
|
+
const testFiles = (await glob("**/*.{test,spec}.{ts,tsx,js,jsx}", {
|
|
1247
1253
|
cwd,
|
|
1248
1254
|
ignore: ["**/node_modules/**", "**/dist/**", "**/build/**"],
|
|
1249
1255
|
nodir: true,
|
|
1250
1256
|
maxDepth: 8,
|
|
1251
|
-
});
|
|
1257
|
+
})).sort();
|
|
1252
1258
|
for (const file of testFiles.slice(0, 300)) {
|
|
1253
1259
|
try {
|
|
1254
1260
|
const content = await readFile(resolve(cwd, file), "utf-8");
|
|
@@ -1287,7 +1293,7 @@ export class DriftAnalysisService {
|
|
|
1287
1293
|
*/
|
|
1288
1294
|
async scanHOCWrapperUsages(componentUsageMap) {
|
|
1289
1295
|
const cwd = this.projectRoot;
|
|
1290
|
-
const sourceFiles = await glob("**/*.{ts,tsx,js,jsx}", {
|
|
1296
|
+
const sourceFiles = (await glob("**/*.{ts,tsx,js,jsx}", {
|
|
1291
1297
|
cwd,
|
|
1292
1298
|
ignore: [
|
|
1293
1299
|
"**/node_modules/**",
|
|
@@ -1298,7 +1304,7 @@ export class DriftAnalysisService {
|
|
|
1298
1304
|
],
|
|
1299
1305
|
nodir: true,
|
|
1300
1306
|
maxDepth: 8,
|
|
1301
|
-
});
|
|
1307
|
+
})).sort();
|
|
1302
1308
|
for (const file of sourceFiles.slice(0, 500)) {
|
|
1303
1309
|
try {
|
|
1304
1310
|
const content = await readFile(resolve(cwd, file), "utf-8");
|
|
@@ -1380,10 +1386,10 @@ export class DriftAnalysisService {
|
|
|
1380
1386
|
if (!isLibraryPattern)
|
|
1381
1387
|
return;
|
|
1382
1388
|
// Scan the root barrel file(s) for exports — these are the public API
|
|
1383
|
-
const rootBarrels = await glob("src/index.{ts,tsx,js,jsx}", {
|
|
1389
|
+
const rootBarrels = (await glob("src/index.{ts,tsx,js,jsx}", {
|
|
1384
1390
|
cwd,
|
|
1385
1391
|
nodir: true,
|
|
1386
|
-
});
|
|
1392
|
+
})).sort();
|
|
1387
1393
|
for (const barrel of rootBarrels) {
|
|
1388
1394
|
try {
|
|
1389
1395
|
const content = await readFile(resolve(cwd, barrel), "utf-8");
|
|
@@ -1443,7 +1449,7 @@ export class DriftAnalysisService {
|
|
|
1443
1449
|
if (knownComponents.length === 0)
|
|
1444
1450
|
return;
|
|
1445
1451
|
const cwd = this.projectRoot;
|
|
1446
|
-
const sourceFiles = await glob("**/*.{tsx,jsx,ts,js}", {
|
|
1452
|
+
const sourceFiles = (await glob("**/*.{tsx,jsx,ts,js}", {
|
|
1447
1453
|
cwd,
|
|
1448
1454
|
ignore: [
|
|
1449
1455
|
"**/node_modules/**",
|
|
@@ -1454,7 +1460,7 @@ export class DriftAnalysisService {
|
|
|
1454
1460
|
],
|
|
1455
1461
|
nodir: true,
|
|
1456
1462
|
maxDepth: 8,
|
|
1457
|
-
});
|
|
1463
|
+
})).sort();
|
|
1458
1464
|
// Build a Set for O(1) lookup
|
|
1459
1465
|
const knownSet = new Set(knownComponents);
|
|
1460
1466
|
for (const file of sourceFiles.slice(0, 500)) {
|
|
@@ -1495,7 +1501,7 @@ export class DriftAnalysisService {
|
|
|
1495
1501
|
"**/.next/**",
|
|
1496
1502
|
"**/build/**",
|
|
1497
1503
|
];
|
|
1498
|
-
const files = await glob(patterns, { cwd, ignore, absolute: true });
|
|
1504
|
+
const files = (await glob(patterns, { cwd, ignore, absolute: true })).sort();
|
|
1499
1505
|
for (const file of files) {
|
|
1500
1506
|
try {
|
|
1501
1507
|
const content = await readFile(file, "utf-8");
|