perf: cache guard inventory checks

This commit is contained in:
Peter Steinberger
2026-04-25 10:01:33 +01:00
parent 70b3ba2fed
commit f7d276b842
6 changed files with 124 additions and 89 deletions

View File

@@ -20,6 +20,7 @@ import {
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const scanRoots = resolveSourceRoots(repoRoot, ["src/plugin-sdk", "src/plugins/runtime"]);
let architectureSmellsPromise;
function compareEntries(left, right) {
return (
@@ -195,21 +196,32 @@ function scanRuntimeServiceLocatorSmells(sourceFile, filePath) {
}
export async function collectArchitectureSmells() {
const files = (await collectTypeScriptFilesFromRoots(scanRoots)).toSorted((left, right) =>
normalizeRepoPath(repoRoot, left).localeCompare(normalizeRepoPath(repoRoot, right)),
);
return await collectTypeScriptInventory({
ts,
files,
compareEntries,
collectEntries(sourceFile, filePath) {
return [
...scanPluginSdkExtensionFacadeSmells(sourceFile, filePath),
...scanRuntimeTypeImplementationSmells(sourceFile, filePath),
...scanRuntimeServiceLocatorSmells(sourceFile, filePath),
];
},
});
if (!architectureSmellsPromise) {
architectureSmellsPromise = (async () => {
const files = (await collectTypeScriptFilesFromRoots(scanRoots)).toSorted((left, right) =>
normalizeRepoPath(repoRoot, left).localeCompare(normalizeRepoPath(repoRoot, right)),
);
return await collectTypeScriptInventory({
ts,
files,
compareEntries,
collectEntries(sourceFile, filePath) {
return [
...scanPluginSdkExtensionFacadeSmells(sourceFile, filePath),
...scanRuntimeTypeImplementationSmells(sourceFile, filePath),
...scanRuntimeServiceLocatorSmells(sourceFile, filePath),
];
},
});
})();
try {
return await architectureSmellsPromise;
} catch (error) {
architectureSmellsPromise = undefined;
throw error;
}
}
return await architectureSmellsPromise;
}
function formatInventoryHuman(inventory) {

View File

@@ -101,9 +101,12 @@ async function collectParsedExtensionSourceFiles() {
if (!parsedExtensionSourceFilesPromise) {
parsedExtensionSourceFilesPromise = (async () => {
const files = await collectExtensionSourceFiles(extensionsRoot);
return await Promise.all(
const parsed = await Promise.all(
files.map(async (filePath) => {
const source = await fs.readFile(filePath, "utf8");
if (!mayContainModuleSpecifier(source)) {
return null;
}
const scriptKind =
filePath.endsWith(".tsx") || filePath.endsWith(".jsx")
? ts.ScriptKind.TSX
@@ -120,11 +123,20 @@ async function collectParsedExtensionSourceFiles() {
};
}),
);
return parsed.filter(Boolean);
})();
}
return await parsedExtensionSourceFilesPromise;
}
function mayContainModuleSpecifier(source) {
return (
/\bfrom\s*["']/.test(source) ||
/\bimport\s*(?:\(|["']|type\b|[\w*{])/.test(source) ||
/\bexport\s*(?:type\s+)?(?:\*|{)[^;\n]*\bfrom\s*["']/.test(source)
);
}
function resolveExtensionRoot(filePath) {
const relativePath = normalizeRepoPath(repoRoot, filePath);
const segments = relativePath.split("/");

View File

@@ -32,40 +32,53 @@ const suspiciousPatterns = [
/id:\s*"firecrawl"/,
];
let webFetchProviderViolationsPromise;
export async function collectWebFetchProviderBoundaryViolations() {
const violations = [];
const files = await collectSourceFileContents({
repoRoot,
scanRoots: ["src"],
scanExtensions,
ignoredDirNames,
});
for (const { relativeFile, content } of files) {
if (
allowedFiles.has(relativeFile) ||
relativeFile.includes(".test.") ||
relativeFile.includes("test-support")
) {
continue;
}
const lines = content.split(/\r?\n/);
for (const [index, line] of lines.entries()) {
if (!line.includes("firecrawl") && !line.includes("Firecrawl")) {
continue;
}
if (!suspiciousPatterns.some((pattern) => pattern.test(line))) {
continue;
}
violations.push({
file: relativeFile,
line: index + 1,
reason: "core web-fetch runtime/tooling contains Firecrawl-specific fetch logic",
if (!webFetchProviderViolationsPromise) {
webFetchProviderViolationsPromise = (async () => {
const violations = [];
const files = await collectSourceFileContents({
repoRoot,
scanRoots: ["src"],
scanExtensions,
ignoredDirNames,
});
for (const { relativeFile, content } of files) {
if (
allowedFiles.has(relativeFile) ||
relativeFile.includes(".test.") ||
relativeFile.includes("test-support")
) {
continue;
}
const lines = content.split(/\r?\n/);
for (const [index, line] of lines.entries()) {
if (!line.includes("firecrawl") && !line.includes("Firecrawl")) {
continue;
}
if (!suspiciousPatterns.some((pattern) => pattern.test(line))) {
continue;
}
violations.push({
file: relativeFile,
line: index + 1,
reason: "core web-fetch runtime/tooling contains Firecrawl-specific fetch logic",
});
}
}
return violations.toSorted(
(left, right) => left.file.localeCompare(right.file) || left.line - right.line,
);
})();
try {
return await webFetchProviderViolationsPromise;
} catch (error) {
webFetchProviderViolationsPromise = undefined;
throw error;
}
}
return violations.toSorted(
(left, right) => left.file.localeCompare(right.file) || left.line - right.line,
);
return await webFetchProviderViolationsPromise;
}
export async function main(argv = process.argv.slice(2), io) {

View File

@@ -2,6 +2,7 @@ import { promises as fs } from "node:fs";
import path from "node:path";
const parsedTypeScriptSourceCache = new Map();
const sourceTextCache = new Map();
export function normalizeRepoPath(repoRoot, filePath) {
return path.relative(repoRoot, filePath).split(path.sep).join("/");
@@ -118,7 +119,11 @@ export async function collectTypeScriptInventory(params) {
const cacheKey = `${scriptKind}:${filePath}`;
let sourceFile = parsedTypeScriptSourceCache.get(cacheKey);
if (!sourceFile) {
const source = await fs.readFile(filePath, "utf8");
let source = sourceTextCache.get(filePath);
if (source === undefined) {
source = await fs.readFile(filePath, "utf8");
sourceTextCache.set(filePath, source);
}
if (params.shouldParseSource && !params.shouldParseSource(source, filePath)) {
continue;
}