mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-10 08:05:14 +02:00
feat(cli): redesign database scope picker for searchable schema-first setup (#203)
* feat: add searchable setup prompt pickers * fix: make snowflake scope discovery single query * fix: make bigquery table discovery schema scoped * fix: honor mysql and clickhouse database scope * feat: wire schema scope discovery for all relational setup drivers * feat: add schema-first database scope picker * test: update setup prompt stubs for type-check * docs: document database scope picker fields * Fix database setup edit preservation --------- Co-authored-by: Andrey Avtomonov <7889985+andreybavt@users.noreply.github.com>
This commit is contained in:
parent
fd2ba62d92
commit
c87d14a554
30 changed files with 1530 additions and 331 deletions
|
|
@ -0,0 +1,19 @@
|
|||
import { describe, expect, it } from 'vitest';
|
||||
import { normalizeBigQueryProjectId, normalizeBigQueryRegion } from './bigquery-identifiers.js';
|
||||
|
||||
describe('BigQuery identifier normalization', () => {
|
||||
it('normalizes project ids and regions for information schema paths', () => {
|
||||
expect(normalizeBigQueryProjectId('project-1')).toBe('project-1');
|
||||
expect(normalizeBigQueryRegion('US')).toBe('us');
|
||||
expect(normalizeBigQueryRegion('region-eu')).toBe('eu');
|
||||
});
|
||||
|
||||
it('rejects malformed project ids and regions with caller-specific context', () => {
|
||||
expect(() => normalizeBigQueryProjectId('project`1', 'table discovery')).toThrow(
|
||||
'Invalid BigQuery project id for table discovery: project`1',
|
||||
);
|
||||
expect(() => normalizeBigQueryRegion('US;DROP', 'table discovery')).toThrow(
|
||||
'Invalid BigQuery region for table discovery: US;DROP',
|
||||
);
|
||||
});
|
||||
});
|
||||
17
packages/cli/src/context/connections/bigquery-identifiers.ts
Normal file
17
packages/cli/src/context/connections/bigquery-identifiers.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
const BIGQUERY_PROJECT_ID_PATTERN = /^[A-Za-z0-9_-]+$/;
|
||||
const BIGQUERY_REGION_PATTERN = /^[a-z0-9-]+$/;
|
||||
|
||||
export function normalizeBigQueryProjectId(value: string, context = 'historic-SQL ingest'): string {
|
||||
if (!BIGQUERY_PROJECT_ID_PATTERN.test(value)) {
|
||||
throw new Error(`Invalid BigQuery project id for ${context}: ${value}`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export function normalizeBigQueryRegion(value: string, context = 'historic-SQL ingest'): string {
|
||||
const normalized = value.trim().toLowerCase().replace(/^region-/, '');
|
||||
if (!BIGQUERY_REGION_PATTERN.test(normalized)) {
|
||||
throw new Error(`Invalid BigQuery region for ${context}: ${value}`);
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import {
|
|||
type HistoricSqlTimeWindow,
|
||||
type HistoricSqlUnifiedPullConfig,
|
||||
} from './types.js';
|
||||
import { normalizeBigQueryProjectId, normalizeBigQueryRegion } from '../../../connections/bigquery-identifiers.js';
|
||||
|
||||
interface QueryResultLike {
|
||||
headers: string[];
|
||||
|
|
@ -52,21 +53,6 @@ function grantsError(cause: unknown): HistoricSqlGrantsMissingError {
|
|||
});
|
||||
}
|
||||
|
||||
function normalizeProjectId(value: string): string {
|
||||
if (!/^[A-Za-z0-9_-]+$/.test(value)) {
|
||||
throw new Error(`Invalid BigQuery project id for historic-SQL ingest: ${value}`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function normalizeRegion(value: string): string {
|
||||
const region = value.trim().toLowerCase().replace(/^region-/, '');
|
||||
if (!/^[a-z0-9-]+$/.test(region)) {
|
||||
throw new Error(`Invalid BigQuery region for historic-SQL ingest: ${value}`);
|
||||
}
|
||||
return region;
|
||||
}
|
||||
|
||||
function timestampExpression(value: Date | string): string {
|
||||
const date = value instanceof Date ? value : new Date(value);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
|
|
@ -190,8 +176,8 @@ export class BigQueryHistoricSqlQueryHistoryReader {
|
|||
private readonly viewPath: string;
|
||||
|
||||
constructor(options: BigQueryHistoricSqlQueryHistoryReaderOptions) {
|
||||
const projectId = normalizeProjectId(options.projectId);
|
||||
const region = normalizeRegion(options.region);
|
||||
const projectId = normalizeBigQueryProjectId(options.projectId);
|
||||
const region = normalizeBigQueryRegion(options.region);
|
||||
this.viewPath = `\`${projectId}.region-${region}.INFORMATION_SCHEMA.JOBS_BY_PROJECT\``;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue