chore(workspace): enforce dialect import boundary

This commit is contained in:
Andrey Avtomonov 2026-05-25 00:16:01 +02:00
parent e1598809b7
commit c0932c98cb
2 changed files with 64 additions and 0 deletions

View file

@ -68,6 +68,13 @@ const contextProductionLlmBoundaryPatterns = [
},
];
const concreteDialectImportPatterns = [
/from\s+['"][^'"]*connectors\/[^'"]+\/dialect\.js['"]/,
/import\s*\(\s*['"][^'"]*connectors\/[^'"]+\/dialect\.js['"]\s*\)/,
/from\s+['"]\.\/dialect\.js['"]/,
/import\s*\(\s*['"]\.\/dialect\.js['"]\s*\)/,
];
function normalizePath(filePath) {
return filePath.split(path.sep).join('/');
}
@ -99,6 +106,13 @@ function scansForContextProductionLlmBoundaries(relativePath) {
return scansForLlmBoundaries(relativePath) && !isTestSource(relativePath);
}
function scansForConcreteDialectImportBoundaries(relativePath) {
return (
relativePath.startsWith('packages/cli/src/context/scan/') ||
/^packages\/cli\/src\/connectors\/[^/]+\/connector\.ts$/.test(relativePath)
);
}
function scansForForbiddenIdentifiers(relativePath) {
return (isCodeSource(relativePath) && !isTestSource(relativePath)) || isRuntimeAsset(relativePath);
}
@ -151,6 +165,19 @@ export function scanFileContent(relativePath, content) {
}
}
if (scansForConcreteDialectImportBoundaries(normalizedPath)) {
for (const pattern of concreteDialectImportPatterns) {
if (pattern.test(content)) {
violations.push({
file: normalizedPath,
kind: 'dialect-boundary',
message:
'Forbidden concrete connector dialect import; use getDialectForDriver() from context/connections/dialects.ts',
});
}
}
}
if (
scansForForbiddenIdentifiers(normalizedPath) &&
!skipsIdentifierScan(normalizedPath) &&

View file

@ -112,6 +112,43 @@ describe('scanFileContent', () => {
);
});
it('rejects concrete connector dialect imports from scan workflow and connector classes', () => {
const violations = [
...scanFileContent(
'packages/cli/src/context/scan/relationship-profiling.ts',
"import { KtxPostgresDialect } from '../../connectors/postgres/dialect.js';",
),
...scanFileContent(
'packages/cli/src/connectors/postgres/connector.ts',
"import { KtxPostgresDialect } from './dialect.js';",
),
];
assert.deepEqual(
violations.map((violation) => violation.kind),
['dialect-boundary', 'dialect-boundary'],
);
assert.equal(
violations[0]?.message,
'Forbidden concrete connector dialect import; use getDialectForDriver() from context/connections/dialects.ts',
);
assert.deepEqual(
scanFileContent(
'packages/cli/src/context/connections/dialects.ts',
"import { KtxPostgresDialect } from '../../connectors/postgres/dialect.js';",
),
[],
);
assert.deepEqual(
scanFileContent(
'packages/cli/src/connectors/postgres/dialect.test.ts',
"import { KtxPostgresDialect } from './dialect.js';",
),
[],
);
});
it('rejects old KTX LLM port declarations in context', () => {
const violations = [
...scanFileContent('packages/cli/src/context/agent/agent-runner.service.ts', 'export interface LlmProviderPort {}'),