typegraph-mcp 0.9.38 → 0.9.39
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/check.ts +55 -16
- package/cli.ts +129 -46
- package/dist/benchmark.js +2 -2
- package/dist/check.js +48 -18
- package/dist/cli.js +417 -97
- package/dist/module-graph.js +4 -3
- package/dist/server.js +261 -43
- package/dist/smoke-test.js +2 -2
- package/export-surface-test.ts +202 -0
- package/install-oxlint-test.ts +95 -0
- package/module-graph.ts +3 -3
- package/package.json +2 -2
- package/server.ts +375 -55
package/check.ts
CHANGED
|
@@ -209,6 +209,44 @@ function hasDeclaredDependency(packageJson: Record<string, unknown> | null, pack
|
|
|
209
209
|
});
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
+
const ESLINT_CONFIG_NAMES = [
|
|
213
|
+
"eslint.config.mjs",
|
|
214
|
+
"eslint.config.js",
|
|
215
|
+
"eslint.config.ts",
|
|
216
|
+
"eslint.config.cjs",
|
|
217
|
+
];
|
|
218
|
+
const OXLINT_CONFIG_NAMES = [
|
|
219
|
+
".oxlintrc.json",
|
|
220
|
+
"oxlint.config.ts",
|
|
221
|
+
"oxlint.config.js",
|
|
222
|
+
"oxlint.config.mjs",
|
|
223
|
+
"oxlint.config.cjs",
|
|
224
|
+
];
|
|
225
|
+
|
|
226
|
+
type LintConfigCheck =
|
|
227
|
+
| { tool: "ESLint"; fileName: string; fullPath: string; propertyName: "ignores" }
|
|
228
|
+
| { tool: "Oxlint"; fileName: string; fullPath: string; propertyName: "ignorePatterns" };
|
|
229
|
+
|
|
230
|
+
function findLintConfigs(projectRoot: string): LintConfigCheck[] {
|
|
231
|
+
const configs: LintConfigCheck[] = [];
|
|
232
|
+
|
|
233
|
+
for (const fileName of ESLINT_CONFIG_NAMES) {
|
|
234
|
+
const fullPath = path.resolve(projectRoot, fileName);
|
|
235
|
+
if (fs.existsSync(fullPath)) {
|
|
236
|
+
configs.push({ tool: "ESLint", fileName, fullPath, propertyName: "ignores" });
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
for (const fileName of OXLINT_CONFIG_NAMES) {
|
|
241
|
+
const fullPath = path.resolve(projectRoot, fileName);
|
|
242
|
+
if (fs.existsSync(fullPath)) {
|
|
243
|
+
configs.push({ tool: "Oxlint", fileName, fullPath, propertyName: "ignorePatterns" });
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return configs;
|
|
248
|
+
}
|
|
249
|
+
|
|
212
250
|
// ─── Main ────────────────────────────────────────────────────────────────────
|
|
213
251
|
|
|
214
252
|
export async function main(configOverride?: TypegraphConfig): Promise<CheckResult> {
|
|
@@ -527,31 +565,32 @@ export async function main(configOverride?: TypegraphConfig): Promise<CheckResul
|
|
|
527
565
|
);
|
|
528
566
|
}
|
|
529
567
|
|
|
530
|
-
// 11.
|
|
568
|
+
// 11. Lint ignores (only when typegraph-mcp is embedded inside the project)
|
|
531
569
|
if (toolIsEmbedded) {
|
|
532
|
-
const
|
|
533
|
-
|
|
534
|
-
if (eslintConfigFile) {
|
|
535
|
-
const eslintConfigPath = path.resolve(projectRoot, eslintConfigFile);
|
|
536
|
-
const eslintContent = fs.readFileSync(eslintConfigPath, "utf-8");
|
|
570
|
+
const lintConfigs = findLintConfigs(projectRoot);
|
|
571
|
+
if (lintConfigs.length > 0) {
|
|
537
572
|
// Determine the parent directory (e.g. "plugins") for the ignore pattern
|
|
538
573
|
const parentDir = path.basename(path.dirname(toolDir));
|
|
539
574
|
const parentIgnorePattern = new RegExp(`["']${parentDir}\\/\\*\\*["']`);
|
|
540
|
-
const hasParentIgnore = parentIgnorePattern.test(eslintContent);
|
|
541
575
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
576
|
+
for (const config of lintConfigs) {
|
|
577
|
+
const content = fs.readFileSync(config.fullPath, "utf-8");
|
|
578
|
+
const hasParentIgnore = parentIgnorePattern.test(content);
|
|
579
|
+
|
|
580
|
+
if (hasParentIgnore) {
|
|
581
|
+
pass(`${config.tool} ignores ${parentDir}/ (${config.fileName})`);
|
|
582
|
+
} else {
|
|
583
|
+
fail(
|
|
584
|
+
`${config.tool} missing ignore: "${parentDir}/**" (${config.fileName})`,
|
|
585
|
+
`Add to ${config.propertyName} in ${config.fileName}:\n "${parentDir}/**",`
|
|
586
|
+
);
|
|
587
|
+
}
|
|
549
588
|
}
|
|
550
589
|
} else {
|
|
551
|
-
skip("
|
|
590
|
+
skip("Lint config check (no ESLint or Oxlint config found)");
|
|
552
591
|
}
|
|
553
592
|
} else {
|
|
554
|
-
skip("
|
|
593
|
+
skip("Lint config check (typegraph-mcp is external to project)");
|
|
555
594
|
}
|
|
556
595
|
|
|
557
596
|
// 12. .gitignore check (optional)
|
package/cli.ts
CHANGED
|
@@ -601,19 +601,13 @@ function ensureTsconfigExclude(projectRoot: string): void {
|
|
|
601
601
|
|
|
602
602
|
try {
|
|
603
603
|
const raw = fs.readFileSync(tsconfigPath, "utf-8");
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
.replace(/,(\s*[}\]])/g, "$1");
|
|
608
|
-
const tsconfig = JSON.parse(stripped);
|
|
609
|
-
|
|
610
|
-
const exclude: string[] = tsconfig.exclude || [];
|
|
611
|
-
if (exclude.some((e: string) => e === "plugins" || e === "plugins/**" || e === "plugins/*")) {
|
|
612
|
-
return; // Already excluded
|
|
604
|
+
const excludeArrayMatch = raw.match(/("exclude"\s*:\s*\[)([\s\S]*?)(\])/);
|
|
605
|
+
if (excludeArrayMatch && /["']plugins(?:\/\*\*|\/\*|)["']/.test(excludeArrayMatch[2])) {
|
|
606
|
+
return;
|
|
613
607
|
}
|
|
614
608
|
|
|
615
609
|
// Insert "plugins/**" into the exclude array in the original file
|
|
616
|
-
if (
|
|
610
|
+
if (excludeArrayMatch) {
|
|
617
611
|
// Existing exclude array — append to it
|
|
618
612
|
const updated = raw.replace(
|
|
619
613
|
/("exclude"\s*:\s*\[)([\s\S]*?)(\])/,
|
|
@@ -642,48 +636,137 @@ function ensureTsconfigExclude(projectRoot: string): void {
|
|
|
642
636
|
}
|
|
643
637
|
}
|
|
644
638
|
|
|
645
|
-
// ───
|
|
639
|
+
// ─── Lint Ignore ─────────────────────────────────────────────────────────────
|
|
646
640
|
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
641
|
+
const ESLINT_CONFIG_NAMES = [
|
|
642
|
+
"eslint.config.mjs",
|
|
643
|
+
"eslint.config.js",
|
|
644
|
+
"eslint.config.ts",
|
|
645
|
+
"eslint.config.cjs",
|
|
646
|
+
];
|
|
647
|
+
const OXLINT_CONFIG_NAMES = [
|
|
648
|
+
".oxlintrc.json",
|
|
649
|
+
"oxlint.config.ts",
|
|
650
|
+
"oxlint.config.js",
|
|
651
|
+
"oxlint.config.mjs",
|
|
652
|
+
"oxlint.config.cjs",
|
|
653
|
+
];
|
|
652
654
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
if (pattern.test(raw)) return; // Already ignored
|
|
655
|
+
type LintConfig =
|
|
656
|
+
| { tool: "ESLint"; fileName: string; fullPath: string; format: "flat" }
|
|
657
|
+
| { tool: "Oxlint"; fileName: string; fullPath: string; format: "json" | "module" };
|
|
657
658
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
return `${open}${items.trimEnd()}${needsComma ? "," : ""} "plugins/**"${close}`;
|
|
666
|
-
});
|
|
667
|
-
fs.writeFileSync(eslintConfigPath, updated);
|
|
668
|
-
p.log.success(`Added "plugins/**" to ${eslintConfigFile} ignores`);
|
|
669
|
-
return;
|
|
659
|
+
function findLintConfigs(projectRoot: string): LintConfig[] {
|
|
660
|
+
const configs: LintConfig[] = [];
|
|
661
|
+
|
|
662
|
+
for (const fileName of ESLINT_CONFIG_NAMES) {
|
|
663
|
+
const fullPath = path.resolve(projectRoot, fileName);
|
|
664
|
+
if (fs.existsSync(fullPath)) {
|
|
665
|
+
configs.push({ tool: "ESLint", fileName, fullPath, format: "flat" });
|
|
670
666
|
}
|
|
667
|
+
}
|
|
671
668
|
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
669
|
+
for (const fileName of OXLINT_CONFIG_NAMES) {
|
|
670
|
+
const fullPath = path.resolve(projectRoot, fileName);
|
|
671
|
+
if (fs.existsSync(fullPath)) {
|
|
672
|
+
configs.push({
|
|
673
|
+
tool: "Oxlint",
|
|
674
|
+
fileName,
|
|
675
|
+
fullPath,
|
|
676
|
+
format: fileName.endsWith(".json") ? "json" : "module",
|
|
678
677
|
});
|
|
679
|
-
fs.writeFileSync(eslintConfigPath, updated);
|
|
680
|
-
p.log.success(`Added "plugins/**" to ${eslintConfigFile} ignores`);
|
|
681
|
-
return;
|
|
682
678
|
}
|
|
679
|
+
}
|
|
683
680
|
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
681
|
+
return configs;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
function appendToArrayLiteral(raw: string, propertyPattern: RegExp, valueLiteral: string): string | null {
|
|
685
|
+
if (!propertyPattern.test(raw)) return null;
|
|
686
|
+
return raw.replace(propertyPattern, (_match, open, items, close) => {
|
|
687
|
+
const trimmed = items.trimEnd();
|
|
688
|
+
const needsComma = trimmed.length > 0 && !trimmed.endsWith(",");
|
|
689
|
+
return `${open}${items.trimEnd()}${needsComma ? "," : ""} ${valueLiteral}${close}`;
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
function insertTopLevelJsonArrayProperty(raw: string, propertyName: string, valueLiteral: string): string | null {
|
|
694
|
+
const lastBrace = raw.lastIndexOf("}");
|
|
695
|
+
if (lastBrace === -1) return null;
|
|
696
|
+
const before = raw.slice(0, lastBrace).trimEnd();
|
|
697
|
+
const needsComma = !before.endsWith(",") && !before.endsWith("{");
|
|
698
|
+
return `${before}${needsComma ? "," : ""}\n "${propertyName}": [${valueLiteral}]\n}\n`;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
function patchEslintConfig(raw: string): string | null {
|
|
702
|
+
const updatedIgnores = appendToArrayLiteral(raw, /(ignores\s*:\s*\[)([\s\S]*?)(\])/, '"plugins/**"');
|
|
703
|
+
if (updatedIgnores) return updatedIgnores;
|
|
704
|
+
|
|
705
|
+
// Matches: export default [ or export default tseslint.config(
|
|
706
|
+
const exportArrayRe = /(export\s+default\s+(?:\w+\.config\(|\[))\s*\n?/;
|
|
707
|
+
if (exportArrayRe.test(raw)) {
|
|
708
|
+
return raw.replace(exportArrayRe, (match) => `${match} { ignores: ["plugins/**"] },\n`);
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
return null;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
function patchOxlintJsonConfig(raw: string): string | null {
|
|
715
|
+
const updatedIgnores = appendToArrayLiteral(
|
|
716
|
+
raw,
|
|
717
|
+
/("ignorePatterns"\s*:\s*\[)([\s\S]*?)(\])/,
|
|
718
|
+
'"plugins/**"'
|
|
719
|
+
);
|
|
720
|
+
if (updatedIgnores) return updatedIgnores;
|
|
721
|
+
return insertTopLevelJsonArrayProperty(raw, "ignorePatterns", '"plugins/**"');
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
function patchOxlintModuleConfig(raw: string): string | null {
|
|
725
|
+
const updatedIgnores = appendToArrayLiteral(
|
|
726
|
+
raw,
|
|
727
|
+
/(ignorePatterns\s*:\s*\[)([\s\S]*?)(\])/,
|
|
728
|
+
'"plugins/**"'
|
|
729
|
+
);
|
|
730
|
+
if (updatedIgnores) return updatedIgnores;
|
|
731
|
+
|
|
732
|
+
const exportObjectRe = /(export\s+default\s*\{)\s*\n?/;
|
|
733
|
+
if (exportObjectRe.test(raw)) {
|
|
734
|
+
return raw.replace(exportObjectRe, (match) => `${match}\n ignorePatterns: ["plugins/**"],`);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
return null;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
function ensureLintIgnores(projectRoot: string): void {
|
|
741
|
+
const configs = findLintConfigs(projectRoot);
|
|
742
|
+
for (const config of configs) {
|
|
743
|
+
try {
|
|
744
|
+
const raw = fs.readFileSync(config.fullPath, "utf-8");
|
|
745
|
+
if (/["']plugins\/\*\*["']/.test(raw)) continue;
|
|
746
|
+
|
|
747
|
+
const updated =
|
|
748
|
+
config.tool === "ESLint"
|
|
749
|
+
? patchEslintConfig(raw)
|
|
750
|
+
: config.format === "json"
|
|
751
|
+
? patchOxlintJsonConfig(raw)
|
|
752
|
+
: patchOxlintModuleConfig(raw);
|
|
753
|
+
|
|
754
|
+
if (updated) {
|
|
755
|
+
fs.writeFileSync(config.fullPath, updated);
|
|
756
|
+
const propertyName = config.tool === "ESLint" ? "ignores" : "ignorePatterns";
|
|
757
|
+
p.log.success(`Added "plugins/**" to ${config.fileName} ${propertyName}`);
|
|
758
|
+
} else {
|
|
759
|
+
const propertyName = config.tool === "ESLint" ? "ignores" : "ignorePatterns";
|
|
760
|
+
p.log.warn(
|
|
761
|
+
`Could not patch ${config.fileName} — manually add "plugins/**" to ${propertyName}`
|
|
762
|
+
);
|
|
763
|
+
}
|
|
764
|
+
} catch {
|
|
765
|
+
const propertyName = config.tool === "ESLint" ? "ignores" : "ignorePatterns";
|
|
766
|
+
p.log.warn(
|
|
767
|
+
`Could not update ${config.fileName} — manually add "plugins/**" to ${propertyName}`
|
|
768
|
+
);
|
|
769
|
+
}
|
|
687
770
|
}
|
|
688
771
|
}
|
|
689
772
|
|
|
@@ -920,8 +1003,8 @@ async function setup(yes: boolean): Promise<void> {
|
|
|
920
1003
|
// 8. Ensure plugins/ is excluded from tsconfig
|
|
921
1004
|
ensureTsconfigExclude(projectRoot);
|
|
922
1005
|
|
|
923
|
-
// 9. Ensure plugins/ is ignored by
|
|
924
|
-
|
|
1006
|
+
// 9. Ensure plugins/ is ignored by supported lint configs
|
|
1007
|
+
ensureLintIgnores(projectRoot);
|
|
925
1008
|
|
|
926
1009
|
// 10. Verification
|
|
927
1010
|
await runVerification(targetDir, selectedAgents);
|
package/dist/benchmark.js
CHANGED
|
@@ -387,7 +387,7 @@ function distToSource(resolvedPath, projectRoot2) {
|
|
|
387
387
|
}
|
|
388
388
|
return resolvedPath;
|
|
389
389
|
}
|
|
390
|
-
function
|
|
390
|
+
function resolveProjectImport(resolver, fromDir, specifier, projectRoot2) {
|
|
391
391
|
try {
|
|
392
392
|
const result = resolver.sync(fromDir, specifier);
|
|
393
393
|
if (result.path && !result.path.includes("node_modules")) {
|
|
@@ -438,7 +438,7 @@ function buildForwardEdges(files, resolver, projectRoot2) {
|
|
|
438
438
|
const edges = [];
|
|
439
439
|
const fromDir = path2.dirname(filePath);
|
|
440
440
|
for (const raw of rawImports) {
|
|
441
|
-
const target =
|
|
441
|
+
const target = resolveProjectImport(resolver, fromDir, raw.specifier, projectRoot2);
|
|
442
442
|
if (target) {
|
|
443
443
|
edges.push({
|
|
444
444
|
target,
|
package/dist/check.js
CHANGED
|
@@ -15,6 +15,7 @@ __export(module_graph_exports, {
|
|
|
15
15
|
createResolver: () => createResolver,
|
|
16
16
|
discoverFiles: () => discoverFiles,
|
|
17
17
|
removeFile: () => removeFile,
|
|
18
|
+
resolveProjectImport: () => resolveProjectImport,
|
|
18
19
|
startWatcher: () => startWatcher,
|
|
19
20
|
updateFile: () => updateFile
|
|
20
21
|
});
|
|
@@ -120,7 +121,7 @@ function distToSource(resolvedPath, projectRoot) {
|
|
|
120
121
|
}
|
|
121
122
|
return resolvedPath;
|
|
122
123
|
}
|
|
123
|
-
function
|
|
124
|
+
function resolveProjectImport(resolver, fromDir, specifier, projectRoot) {
|
|
124
125
|
try {
|
|
125
126
|
const result = resolver.sync(fromDir, specifier);
|
|
126
127
|
if (result.path && !result.path.includes("node_modules")) {
|
|
@@ -171,7 +172,7 @@ function buildForwardEdges(files, resolver, projectRoot) {
|
|
|
171
172
|
const edges = [];
|
|
172
173
|
const fromDir = path2.dirname(filePath);
|
|
173
174
|
for (const raw of rawImports) {
|
|
174
|
-
const target =
|
|
175
|
+
const target = resolveProjectImport(resolver, fromDir, raw.specifier, projectRoot);
|
|
175
176
|
if (target) {
|
|
176
177
|
edges.push({
|
|
177
178
|
target,
|
|
@@ -252,7 +253,7 @@ function updateFile(graph, filePath, resolver, projectRoot) {
|
|
|
252
253
|
const fromDir = path2.dirname(filePath);
|
|
253
254
|
const newEdges = [];
|
|
254
255
|
for (const raw of rawImports) {
|
|
255
|
-
const target =
|
|
256
|
+
const target = resolveProjectImport(resolver, fromDir, raw.specifier, projectRoot);
|
|
256
257
|
if (target) {
|
|
257
258
|
newEdges.push({
|
|
258
259
|
target,
|
|
@@ -506,6 +507,35 @@ function hasDeclaredDependency(packageJson, packageName) {
|
|
|
506
507
|
return typeof deps === "object" && deps !== null && packageName in deps;
|
|
507
508
|
});
|
|
508
509
|
}
|
|
510
|
+
var ESLINT_CONFIG_NAMES = [
|
|
511
|
+
"eslint.config.mjs",
|
|
512
|
+
"eslint.config.js",
|
|
513
|
+
"eslint.config.ts",
|
|
514
|
+
"eslint.config.cjs"
|
|
515
|
+
];
|
|
516
|
+
var OXLINT_CONFIG_NAMES = [
|
|
517
|
+
".oxlintrc.json",
|
|
518
|
+
"oxlint.config.ts",
|
|
519
|
+
"oxlint.config.js",
|
|
520
|
+
"oxlint.config.mjs",
|
|
521
|
+
"oxlint.config.cjs"
|
|
522
|
+
];
|
|
523
|
+
function findLintConfigs(projectRoot) {
|
|
524
|
+
const configs = [];
|
|
525
|
+
for (const fileName of ESLINT_CONFIG_NAMES) {
|
|
526
|
+
const fullPath = path3.resolve(projectRoot, fileName);
|
|
527
|
+
if (fs2.existsSync(fullPath)) {
|
|
528
|
+
configs.push({ tool: "ESLint", fileName, fullPath, propertyName: "ignores" });
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
for (const fileName of OXLINT_CONFIG_NAMES) {
|
|
532
|
+
const fullPath = path3.resolve(projectRoot, fileName);
|
|
533
|
+
if (fs2.existsSync(fullPath)) {
|
|
534
|
+
configs.push({ tool: "Oxlint", fileName, fullPath, propertyName: "ignorePatterns" });
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
return configs;
|
|
538
|
+
}
|
|
509
539
|
async function main(configOverride) {
|
|
510
540
|
const { projectRoot, tsconfigPath, toolDir, toolIsEmbedded, toolRelPath } = configOverride ?? resolveConfig(import.meta.dirname);
|
|
511
541
|
let passed = 0;
|
|
@@ -783,28 +813,28 @@ async function main(configOverride) {
|
|
|
783
813
|
);
|
|
784
814
|
}
|
|
785
815
|
if (toolIsEmbedded) {
|
|
786
|
-
const
|
|
787
|
-
|
|
788
|
-
if (eslintConfigFile) {
|
|
789
|
-
const eslintConfigPath = path3.resolve(projectRoot, eslintConfigFile);
|
|
790
|
-
const eslintContent = fs2.readFileSync(eslintConfigPath, "utf-8");
|
|
816
|
+
const lintConfigs = findLintConfigs(projectRoot);
|
|
817
|
+
if (lintConfigs.length > 0) {
|
|
791
818
|
const parentDir = path3.basename(path3.dirname(toolDir));
|
|
792
819
|
const parentIgnorePattern = new RegExp(`["']${parentDir}\\/\\*\\*["']`);
|
|
793
|
-
const
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
820
|
+
for (const config of lintConfigs) {
|
|
821
|
+
const content = fs2.readFileSync(config.fullPath, "utf-8");
|
|
822
|
+
const hasParentIgnore = parentIgnorePattern.test(content);
|
|
823
|
+
if (hasParentIgnore) {
|
|
824
|
+
pass(`${config.tool} ignores ${parentDir}/ (${config.fileName})`);
|
|
825
|
+
} else {
|
|
826
|
+
fail(
|
|
827
|
+
`${config.tool} missing ignore: "${parentDir}/**" (${config.fileName})`,
|
|
828
|
+
`Add to ${config.propertyName} in ${config.fileName}:
|
|
800
829
|
"${parentDir}/**",`
|
|
801
|
-
|
|
830
|
+
);
|
|
831
|
+
}
|
|
802
832
|
}
|
|
803
833
|
} else {
|
|
804
|
-
skip("
|
|
834
|
+
skip("Lint config check (no ESLint or Oxlint config found)");
|
|
805
835
|
}
|
|
806
836
|
} else {
|
|
807
|
-
skip("
|
|
837
|
+
skip("Lint config check (typegraph-mcp is external to project)");
|
|
808
838
|
}
|
|
809
839
|
const gitignorePath = path3.resolve(projectRoot, ".gitignore");
|
|
810
840
|
if (fs2.existsSync(gitignorePath)) {
|