Skip to content

Commit 4e0e509

Browse files
committed
fix: stop scoped query actions from fanning out
The analyzer now follows workspace package imports and preserves dynamic query-key templates while carrying client, test, and suite scope metadata through records. Wildcard, pass-through, refetch, and clear matching now stay within the relevant scope instead of linking unrelated query keys across tests, helper packages, or broad cache lookups. Constraint: Static analysis must work when helper packages and re-exported source files are outside scan scope Rejected: Keep project-wide fallback for broad actions | caused cross-test and cross-hook pollution Confidence: medium Scope-risk: broad Directive: Query/action matching now depends on client/test/suite scope metadata; do not relax without rerunning query-core/preact-query/vue-query fixtures Tested: pnpm test; pnpm lint; pnpm type-check; pnpm build Not-tested: Real VS Code extension interaction after repeated Scan Now cycles
1 parent 05f7570 commit 4e0e509

18 files changed

Lines changed: 1299 additions & 38 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
node_modules
22
dist
33
*.vsix
4+
.omx

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"release:marketplaces": "pnpm run build && pnpm run release:vsce && pnpm run release:ovsx",
3131
"release:ovsx": "pnpm dlx ovsx publish --no-dependencies --skip-duplicate",
3232
"release:vsce": "pnpm exec vsce publish --no-dependencies --skip-duplicate",
33+
"test": "node scripts/runTests.mjs",
3334
"type-check": "tsc --noEmit",
3435
"version:changeset": "changeset version",
3536
"watch:webview": "pnpm run build:webview:bundle -- --watch"

scripts/runTests.mjs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { mkdtemp, readdir, rm } from 'node:fs/promises';
2+
import os from 'node:os';
3+
import path from 'node:path';
4+
import { spawn } from 'node:child_process';
5+
import { fileURLToPath } from 'node:url';
6+
7+
import { build } from 'esbuild';
8+
9+
const __filename = fileURLToPath(import.meta.url);
10+
const __dirname = path.dirname(__filename);
11+
const repoRoot = path.resolve(__dirname, '..');
12+
const testsDir = path.join(repoRoot, 'tests');
13+
const outDir = await mkdtemp(path.join(os.tmpdir(), 'rqv-tests-'));
14+
15+
async function listTestFiles() {
16+
const entries = await readdir(testsDir, { withFileTypes: true });
17+
return entries
18+
.filter((entry) => entry.isFile() && entry.name.endsWith('.test.ts'))
19+
.map((entry) => path.join(testsDir, entry.name))
20+
.sort((left, right) => left.localeCompare(right));
21+
}
22+
23+
function runNodeTest(compiledFiles) {
24+
return new Promise((resolve, reject) => {
25+
const child = spawn(process.execPath, ['--test', ...compiledFiles], {
26+
cwd: repoRoot,
27+
stdio: 'inherit',
28+
});
29+
30+
child.on('error', reject);
31+
child.on('exit', (code) => {
32+
if (code === 0) {
33+
resolve();
34+
return;
35+
}
36+
37+
reject(new Error(`Tests failed with exit code ${code ?? 'unknown'}`));
38+
});
39+
});
40+
}
41+
42+
const testFiles = await listTestFiles();
43+
if (testFiles.length === 0) {
44+
process.exit(0);
45+
}
46+
47+
try {
48+
const compiledFiles = [];
49+
for (const testFile of testFiles) {
50+
const outputFile = path.join(outDir, `${path.basename(testFile, '.ts')}.cjs`);
51+
await build({
52+
entryPoints: [testFile],
53+
bundle: true,
54+
format: 'cjs',
55+
platform: 'node',
56+
target: 'node24',
57+
outfile: outputFile,
58+
sourcemap: 'inline',
59+
});
60+
compiledFiles.push(outputFile);
61+
}
62+
63+
await runNodeTest(compiledFiles);
64+
} finally {
65+
await rm(outDir, { recursive: true, force: true });
66+
}

src/core/analyzer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ async function analyzeParsedFiles(parsedAsts: Map<string, t.File>, rootPath: str
4545
const resolver = createQueryKeyResolver(filePath, symbolIndex, rootPath);
4646

4747
scanImports(ast, context);
48-
scanLocalBindings(ast, context, resolver);
48+
scanLocalBindings(ast, context, resolver, filePath);
4949
scanCalls(ast, filePath, context, records, resolver);
5050
}
5151

0 commit comments

Comments
 (0)