mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-19 08:28:06 +02:00
refactor: remove legacy compatibility shims (#208)
This commit is contained in:
parent
394a985d2a
commit
db09936085
17 changed files with 61 additions and 361 deletions
|
|
@ -1,20 +1,9 @@
|
|||
import type { HistoricSqlDialect } from './types.js';
|
||||
|
||||
const KNOWN_DIALECTS = ['postgres', 'bigquery', 'snowflake'] as const;
|
||||
|
||||
function isKnownDialect(value: string): value is HistoricSqlDialect {
|
||||
return (KNOWN_DIALECTS as readonly string[]).includes(value);
|
||||
}
|
||||
|
||||
function recordOrNull(value: unknown): Record<string, unknown> | null {
|
||||
return value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : null;
|
||||
}
|
||||
|
||||
function historicSqlRecord(connection: unknown): Record<string, unknown> | null {
|
||||
const conn = recordOrNull(connection);
|
||||
return conn ? recordOrNull(conn.historicSql) : null;
|
||||
}
|
||||
|
||||
function queryHistoryRecord(connection: unknown): Record<string, unknown> | null {
|
||||
const conn = recordOrNull(connection);
|
||||
const context = conn ? recordOrNull(conn.context) : null;
|
||||
|
|
@ -22,11 +11,7 @@ function queryHistoryRecord(connection: unknown): Record<string, unknown> | null
|
|||
}
|
||||
|
||||
export function isQueryHistoryEnabled(connection: unknown): boolean {
|
||||
const queryHistory = queryHistoryRecord(connection);
|
||||
if (queryHistory) {
|
||||
return queryHistory.enabled === true;
|
||||
}
|
||||
return historicSqlRecord(connection)?.enabled === true;
|
||||
return queryHistoryRecord(connection)?.enabled === true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -43,6 +28,5 @@ export function queryHistoryDialectForConnection(connection: unknown): HistoricS
|
|||
if (driver === 'postgres' || driver === 'postgresql') return 'postgres';
|
||||
if (driver === 'bigquery') return 'bigquery';
|
||||
if (driver === 'snowflake') return 'snowflake';
|
||||
const legacy = String(historicSqlRecord(connection)?.dialect ?? '').toLowerCase();
|
||||
return isKnownDialect(legacy) ? legacy : null;
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,10 +152,10 @@ async function writeHistoricSqlProject(project: KtxLocalProject): Promise<KtxLoc
|
|||
'connections:',
|
||||
' warehouse:',
|
||||
' driver: postgres',
|
||||
' historicSql:',
|
||||
' enabled: true',
|
||||
' dialect: postgres',
|
||||
' minExecutions: 2',
|
||||
' context:',
|
||||
' queryHistory:',
|
||||
' enabled: true',
|
||||
' minExecutions: 2',
|
||||
'ingest:',
|
||||
' adapters:',
|
||||
' - historic-sql',
|
||||
|
|
|
|||
|
|
@ -187,14 +187,15 @@ describe('local ingest adapters', () => {
|
|||
warehouse: {
|
||||
driver: 'postgres',
|
||||
url: 'env:WAREHOUSE_DATABASE_URL',
|
||||
historicSql: {
|
||||
enabled: true,
|
||||
dialect: 'postgres',
|
||||
minExecutions: 7,
|
||||
maxTemplatesPerRun: 123,
|
||||
filters: {
|
||||
serviceAccounts: { patterns: ['^svc_'], mode: 'exclude' },
|
||||
dropTrivialProbes: true,
|
||||
context: {
|
||||
queryHistory: {
|
||||
enabled: true,
|
||||
minExecutions: 7,
|
||||
maxTemplatesPerRun: 123,
|
||||
filters: {
|
||||
serviceAccounts: { patterns: ['^svc_'], mode: 'exclude' },
|
||||
dropTrivialProbes: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -236,22 +237,6 @@ describe('local ingest adapters', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('prefers context.queryHistory over legacy historicSql', async () => {
|
||||
const project = projectWithConnections({
|
||||
warehouse: {
|
||||
driver: 'postgres',
|
||||
historicSql: { enabled: true, dialect: 'postgres', windowDays: 90 },
|
||||
context: { queryHistory: { enabled: true, windowDays: 30 } },
|
||||
},
|
||||
});
|
||||
const adapter = { source: 'historic-sql' } as never;
|
||||
|
||||
await expect(localPullConfigForAdapter(project, adapter, 'warehouse')).resolves.toMatchObject({
|
||||
dialect: 'postgres',
|
||||
minExecutions: 5,
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects local historic-sql pulls when the connection has not enabled historic SQL', async () => {
|
||||
const historicSql = createDefaultLocalIngestAdapters(project, {
|
||||
historicSql: {
|
||||
|
|
|
|||
|
|
@ -247,16 +247,10 @@ export async function localPullConfigForAdapter(
|
|||
return historicSqlUnifiedPullConfigSchema.parse(options.historicSqlPullConfigOverride);
|
||||
}
|
||||
const queryHistory = queryHistoryPullConfig(connection);
|
||||
if (queryHistory) {
|
||||
return historicSqlUnifiedPullConfigSchema.parse(queryHistory);
|
||||
}
|
||||
const historicSql = isRecord(connection?.historicSql) ? connection.historicSql : null;
|
||||
if (historicSql?.enabled !== true) {
|
||||
if (!queryHistory) {
|
||||
throw new Error(`Connection "${connectionId}" does not have context.queryHistory.enabled: true`);
|
||||
}
|
||||
return historicSqlUnifiedPullConfigSchema.parse({
|
||||
...historicSql,
|
||||
});
|
||||
return historicSqlUnifiedPullConfigSchema.parse(queryHistory);
|
||||
}
|
||||
if (adapter.source === 'looker') {
|
||||
await seedLocalMappingStateFromKtxYaml(project, connectionId);
|
||||
|
|
|
|||
|
|
@ -369,7 +369,7 @@ ingest:
|
|||
llm:
|
||||
backend: anthropic
|
||||
`),
|
||||
).toThrow('Unsupported ingest.llm: use top-level llm.provider, llm.models, and ingest.workUnits');
|
||||
).toThrow('Unsupported ingest.llm: unknown field');
|
||||
|
||||
expect(() =>
|
||||
parseKtxProjectConfig(`
|
||||
|
|
@ -377,7 +377,7 @@ scan:
|
|||
enrichment:
|
||||
backend: gateway
|
||||
`),
|
||||
).toThrow('Unsupported scan.enrichment.backend: use scan.enrichment.mode');
|
||||
).toThrow('Unsupported scan.enrichment.backend: unknown field');
|
||||
|
||||
expect(() =>
|
||||
parseKtxProjectConfig(`
|
||||
|
|
@ -387,7 +387,7 @@ scan:
|
|||
llm:
|
||||
backend: gateway
|
||||
`),
|
||||
).toThrow('Unsupported scan.enrichment.llm: use top-level llm.provider and llm.models');
|
||||
).toThrow('Unsupported scan.enrichment.llm: unknown field');
|
||||
|
||||
expect(() =>
|
||||
parseKtxProjectConfig(`
|
||||
|
|
@ -478,28 +478,6 @@ scan:
|
|||
);
|
||||
});
|
||||
|
||||
it('attaches migration hints for known deprecated keys', () => {
|
||||
const result = validateKtxProjectConfig(`
|
||||
ingest:
|
||||
llm:
|
||||
backend: anthropic
|
||||
scan:
|
||||
enrichment:
|
||||
backend: none
|
||||
`);
|
||||
|
||||
expect(result.ok).toBe(false);
|
||||
const findIssue = (path: string) => result.issues.find((issue) => issue.path === path);
|
||||
expect(findIssue('ingest.llm')).toMatchObject({
|
||||
message: 'Unsupported ingest.llm: use top-level llm.provider, llm.models, and ingest.workUnits',
|
||||
fix: 'use top-level llm.provider, llm.models, and ingest.workUnits',
|
||||
});
|
||||
expect(findIssue('scan.enrichment.backend')).toMatchObject({
|
||||
message: 'Unsupported scan.enrichment.backend: use scan.enrichment.mode',
|
||||
fix: 'use scan.enrichment.mode',
|
||||
});
|
||||
});
|
||||
|
||||
it('reports YAML parse errors as a root-level issue', () => {
|
||||
const result = validateKtxProjectConfig(': not valid yaml :\n');
|
||||
expect(result.ok).toBe(false);
|
||||
|
|
|
|||
|
|
@ -11,15 +11,6 @@ const KTX_WORK_UNIT_FAILURE_MODES = ['abort', 'continue'] as const;
|
|||
const KTX_STORAGE_STATES = ['sqlite', 'postgres'] as const;
|
||||
const KTX_SEARCH_BACKENDS = ['sqlite-fts5', 'postgres-hybrid'] as const;
|
||||
|
||||
const DEPRECATED_KEY_HINTS: Record<string, string> = {
|
||||
'llm.provider.provider': 'use llm.provider.backend',
|
||||
'ingest.llm': 'use top-level llm.provider, llm.models, and ingest.workUnits',
|
||||
'ingest.embeddings.provider': 'use ingest.embeddings.backend',
|
||||
'scan.enrichment.backend': 'use scan.enrichment.mode',
|
||||
'scan.enrichment.llm': 'use top-level llm.provider and llm.models',
|
||||
'scan.enrichment.embeddings.provider': 'use scan.enrichment.embeddings.backend',
|
||||
};
|
||||
|
||||
const apiCredentialsSchema = z
|
||||
.strictObject({
|
||||
api_key: z.string().min(1).optional().describe('API key for the provider. Read from this value or the provider-specific environment variable.'),
|
||||
|
|
@ -189,12 +180,7 @@ const setupSchema = z
|
|||
.array(z.string().min(1))
|
||||
.default([])
|
||||
.describe('Connection IDs (keys of the top-level `connections` map) that the setup wizard treats as the project\'s primary databases.'),
|
||||
completed_steps: z
|
||||
.unknown()
|
||||
.optional()
|
||||
.describe('Deprecated. Accepted for backward compatibility but ignored; KTX no longer tracks setup progress here.'),
|
||||
})
|
||||
.transform(({ database_connection_ids }) => ({ database_connection_ids }))
|
||||
.describe('Setup-wizard state captured during `ktx setup`.');
|
||||
|
||||
const storageGitSchema = z
|
||||
|
|
@ -309,10 +295,6 @@ function formatIssue(issue: z.core.$ZodIssue, input: unknown): KtxConfigIssue[]
|
|||
const keys = (issue as { keys?: readonly string[] }).keys ?? [];
|
||||
return keys.map((key) => {
|
||||
const fullPath = basePath.length > 0 ? `${basePath}.${key}` : key;
|
||||
const hint = DEPRECATED_KEY_HINTS[fullPath];
|
||||
if (hint !== undefined) {
|
||||
return { path: fullPath, message: `Unsupported ${fullPath}: ${hint}`, fix: hint };
|
||||
}
|
||||
return { path: fullPath, message: `Unsupported ${fullPath}: unknown field` };
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@ describe('connectionConfigSchema (driver discriminated union)', () => {
|
|||
const parsed = connectionConfigSchema.parse({
|
||||
driver: 'postgres',
|
||||
url: 'postgres://x',
|
||||
historicSql: { enabled: true },
|
||||
customField: { enabled: true },
|
||||
context: { queryHistory: { enabled: false } },
|
||||
});
|
||||
expect(parsed).toMatchObject({
|
||||
driver: 'postgres',
|
||||
historicSql: { enabled: true },
|
||||
customField: { enabled: true },
|
||||
context: { queryHistory: { enabled: false } },
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ function warehouseConnectionSchema<const Driver extends WarehouseDriver>(driver:
|
|||
),
|
||||
})
|
||||
.describe(
|
||||
`${driver} warehouse connection. Additional driver-tunable fields (e.g. historicSql, context.queryHistory) are accepted and passed through.`,
|
||||
`${driver} warehouse connection. Additional driver-tunable fields (e.g. context.queryHistory) are accepted and passed through.`,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue