@kaelio/ktx 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/python/{kaelio_ktx-0.8.0-py3-none-any.whl → kaelio_ktx-0.10.0-py3-none-any.whl} +0 -0
- package/assets/python/manifest.json +4 -4
- package/dist/.tsbuildinfo +1 -1
- package/dist/clack.d.ts +6 -0
- package/dist/clack.js +17 -2
- package/dist/cli-program.d.ts +3 -0
- package/dist/cli-program.js +42 -2
- package/dist/cli-runtime.d.ts +3 -0
- package/dist/cli-runtime.js +94 -3
- package/dist/commands/setup-commands.js +3 -4
- package/dist/connection-recovery.d.ts +34 -0
- package/dist/connection-recovery.js +82 -0
- package/dist/connection.js +26 -2
- package/dist/connectors/bigquery/connector.d.ts +2 -5
- package/dist/connectors/bigquery/connector.js +2 -2
- package/dist/connectors/clickhouse/connector.d.ts +2 -5
- package/dist/connectors/clickhouse/connector.js +2 -2
- package/dist/connectors/mysql/connector.d.ts +7 -6
- package/dist/connectors/mysql/connector.js +25 -5
- package/dist/connectors/mysql/dialect.d.ts +1 -1
- package/dist/connectors/mysql/dialect.js +12 -2
- package/dist/connectors/postgres/connector.d.ts +2 -5
- package/dist/connectors/postgres/connector.js +2 -2
- package/dist/connectors/snowflake/connector.d.ts +2 -5
- package/dist/connectors/snowflake/connector.js +2 -2
- package/dist/connectors/sqlite/connector.d.ts +2 -5
- package/dist/connectors/sqlite/connector.js +2 -2
- package/dist/connectors/sqlserver/connector.d.ts +2 -5
- package/dist/connectors/sqlserver/connector.js +2 -2
- package/dist/context/connections/drivers.d.ts +0 -1
- package/dist/context/connections/drivers.js +0 -7
- package/dist/context/connections/query-executor.d.ts +2 -1
- package/dist/context/core/abort.d.ts +9 -0
- package/dist/context/core/abort.js +36 -0
- package/dist/context/ingest/adapters/historic-sql/bigquery-query-history-reader.js +71 -20
- package/dist/context/ingest/adapters/historic-sql/chunk-unified.js +2 -1
- package/dist/context/ingest/adapters/historic-sql/connection-dialect.d.ts +9 -0
- package/dist/context/ingest/adapters/historic-sql/connection-dialect.js +15 -4
- package/dist/context/ingest/adapters/historic-sql/pattern-inputs.js +8 -2
- package/dist/context/ingest/adapters/historic-sql/query-history-filter-picker.d.ts +30 -0
- package/dist/context/ingest/adapters/historic-sql/query-history-filter-picker.js +194 -0
- package/dist/context/ingest/adapters/historic-sql/scope-floor.d.ts +18 -0
- package/dist/context/ingest/adapters/historic-sql/scope-floor.js +229 -0
- package/dist/context/ingest/adapters/historic-sql/scope-membership.d.ts +8 -0
- package/dist/context/ingest/adapters/historic-sql/scope-membership.js +29 -0
- package/dist/context/ingest/adapters/historic-sql/snowflake-query-history-reader.js +68 -19
- package/dist/context/ingest/adapters/historic-sql/stage-unified.js +57 -50
- package/dist/context/ingest/adapters/historic-sql/types.d.ts +36 -3
- package/dist/context/ingest/adapters/historic-sql/types.js +14 -2
- package/dist/context/ingest/context-candidates/curator-pagination.service.d.ts +1 -5
- package/dist/context/ingest/context-candidates/curator-pagination.service.js +1 -3
- package/dist/context/ingest/context-evidence/sqlite-context-evidence-store.d.ts +1 -1
- package/dist/context/ingest/final-gate-repair.d.ts +1 -0
- package/dist/context/ingest/final-gate-repair.js +1 -0
- package/dist/context/ingest/ingest-bundle.runner.d.ts +3 -0
- package/dist/context/ingest/ingest-bundle.runner.js +127 -53
- package/dist/context/ingest/isolated-diff/patch-integrator.js +75 -5
- package/dist/context/ingest/isolated-diff/textual-conflict-resolver.d.ts +1 -0
- package/dist/context/ingest/isolated-diff/textual-conflict-resolver.js +1 -0
- package/dist/context/ingest/isolated-diff/work-unit-executor.d.ts +1 -0
- package/dist/context/ingest/local-adapters.js +21 -4
- package/dist/context/ingest/local-bundle-runtime.js +13 -5
- package/dist/context/ingest/local-ingest.d.ts +1 -0
- package/dist/context/ingest/local-ingest.js +13 -3
- package/dist/context/ingest/memory-flow/events.js +1 -1
- package/dist/context/ingest/memory-flow/schema.js +8 -3
- package/dist/context/ingest/memory-flow/types.d.ts +7 -3
- package/dist/context/ingest/ports.d.ts +3 -5
- package/dist/context/ingest/stages/stage-3-work-units.d.ts +1 -4
- package/dist/context/ingest/stages/stage-3-work-units.js +5 -1
- package/dist/context/ingest/stages/stage-4-reconciliation.d.ts +1 -4
- package/dist/context/ingest/stages/stage-4-reconciliation.js +1 -1
- package/dist/context/ingest/types.d.ts +1 -0
- package/dist/context/llm/ai-sdk-runtime.d.ts +3 -0
- package/dist/context/llm/ai-sdk-runtime.js +152 -16
- package/dist/context/llm/claude-code-runtime.d.ts +6 -4
- package/dist/context/llm/claude-code-runtime.js +127 -48
- package/dist/context/llm/codex-exec-events.d.ts +20 -0
- package/dist/context/llm/codex-exec-events.js +155 -0
- package/dist/context/llm/codex-isolation.d.ts +3 -0
- package/dist/context/llm/codex-isolation.js +5 -0
- package/dist/context/llm/codex-mcp-runtime-server.d.ts +24 -0
- package/dist/context/llm/codex-mcp-runtime-server.js +51 -0
- package/dist/context/llm/codex-models.d.ts +2 -0
- package/dist/context/llm/codex-models.js +17 -0
- package/dist/context/llm/codex-runtime-config.d.ts +16 -0
- package/dist/context/llm/codex-runtime-config.js +19 -0
- package/dist/context/llm/codex-runtime.d.ts +37 -0
- package/dist/context/llm/codex-runtime.js +347 -0
- package/dist/context/llm/codex-sdk-runner.d.ts +21 -0
- package/dist/context/llm/codex-sdk-runner.js +63 -0
- package/dist/context/llm/local-config.d.ts +16 -4
- package/dist/context/llm/local-config.js +18 -2
- package/dist/context/llm/rate-limit-governor.d.ts +103 -0
- package/dist/context/llm/rate-limit-governor.js +285 -0
- package/dist/context/llm/runtime-port.d.ts +3 -6
- package/dist/context/mcp/context-tools.js +43 -13
- package/dist/context/project/config.d.ts +14 -0
- package/dist/context/project/config.js +37 -2
- package/dist/context/scan/types.d.ts +15 -2
- package/dist/context/scan/types.js +12 -0
- package/dist/context/sl/description-normalization.js +4 -14
- package/dist/context/sql-analysis/http-sql-analysis-port.js +32 -2
- package/dist/context/sql-analysis/ports.d.ts +12 -2
- package/dist/context/tools/context-candidate-mark.tool.d.ts +2 -2
- package/dist/context-build-view.d.ts +13 -0
- package/dist/context-build-view.js +63 -32
- package/dist/demo-metrics.d.ts +0 -2
- package/dist/demo-metrics.js +1 -11
- package/dist/ingest.d.ts +1 -0
- package/dist/ingest.js +32 -3
- package/dist/io/buffered-command-io.d.ts +11 -0
- package/dist/io/buffered-command-io.js +28 -0
- package/dist/io/symbols.d.ts +2 -0
- package/dist/io/symbols.js +2 -0
- package/dist/llm/types.d.ts +1 -1
- package/dist/local-adapters.d.ts +10 -2
- package/dist/local-adapters.js +19 -3
- package/dist/memory-flow-hud.js +8 -16
- package/dist/next-steps.js +1 -2
- package/dist/progress-port-adapter.d.ts +6 -0
- package/dist/progress-port-adapter.js +18 -0
- package/dist/public-ingest.d.ts +20 -1
- package/dist/public-ingest.js +228 -42
- package/dist/reveal-password-prompt.d.ts +24 -0
- package/dist/reveal-password-prompt.js +78 -0
- package/dist/scan.js +21 -3
- package/dist/setup-context.d.ts +2 -0
- package/dist/setup-context.js +133 -27
- package/dist/setup-databases.d.ts +18 -1
- package/dist/setup-databases.js +378 -249
- package/dist/setup-demo-tour.js +1 -0
- package/dist/setup-embeddings.js +1 -1
- package/dist/setup-models.d.ts +11 -15
- package/dist/setup-models.js +140 -276
- package/dist/setup-prompts.js +3 -2
- package/dist/setup-ready-menu.d.ts +16 -2
- package/dist/setup-ready-menu.js +37 -5
- package/dist/setup-sources.js +115 -35
- package/dist/setup.d.ts +1 -1
- package/dist/setup.js +23 -11
- package/dist/sl.d.ts +2 -2
- package/dist/sl.js +20 -4
- package/dist/sql.js +18 -2
- package/dist/star-prompt/cache.d.ts +16 -0
- package/dist/star-prompt/cache.js +45 -0
- package/dist/star-prompt/star-count.d.ts +7 -0
- package/dist/star-prompt/star-count.js +66 -0
- package/dist/star-prompt/star-line.d.ts +12 -0
- package/dist/star-prompt/star-line.js +26 -0
- package/dist/status-project.d.ts +11 -0
- package/dist/status-project.js +50 -1
- package/dist/telemetry/command-hook.d.ts +1 -0
- package/dist/telemetry/command-hook.js +3 -1
- package/dist/telemetry/emitter.d.ts +10 -0
- package/dist/telemetry/emitter.js +31 -0
- package/dist/telemetry/events.d.ts +35 -6
- package/dist/telemetry/events.js +25 -2
- package/dist/telemetry/exception.d.ts +18 -0
- package/dist/telemetry/exception.js +162 -0
- package/dist/telemetry/identity.d.ts +0 -1
- package/dist/telemetry/identity.js +6 -6
- package/dist/telemetry/index.d.ts +15 -2
- package/dist/telemetry/index.js +15 -3
- package/dist/telemetry/redaction-secrets.d.ts +11 -0
- package/dist/telemetry/redaction-secrets.js +92 -0
- package/dist/telemetry/scrubber.d.ts +10 -0
- package/dist/telemetry/scrubber.js +20 -0
- package/dist/update-check/cache.d.ts +21 -0
- package/dist/update-check/cache.js +38 -0
- package/dist/update-check/channel.d.ts +15 -0
- package/dist/update-check/channel.js +30 -0
- package/dist/update-check/registry.d.ts +1 -0
- package/dist/update-check/registry.js +45 -0
- package/dist/update-check/update-check.d.ts +43 -0
- package/dist/update-check/update-check.js +116 -0
- package/package.json +12 -4
- package/dist/context/connections/local-query-executor.d.ts +0 -6
- package/dist/context/connections/local-query-executor.js +0 -39
- package/dist/context/connections/postgres-query-executor.d.ts +0 -25
- package/dist/context/connections/postgres-query-executor.js +0 -53
- package/dist/context/connections/sqlite-query-executor.d.ts +0 -4
- package/dist/context/connections/sqlite-query-executor.js +0 -74
package/dist/clack.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { KtxCliIo } from './cli-runtime.js';
|
|
2
|
+
export interface CliStyleEnv {
|
|
3
|
+
NO_COLOR?: string;
|
|
4
|
+
TERM?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function dim(text: string, env?: CliStyleEnv): string;
|
|
7
|
+
export declare function cyan(text: string, env?: CliStyleEnv): string;
|
|
2
8
|
export interface RailBufferedSource {
|
|
3
9
|
stdoutText(): string;
|
|
4
10
|
stderrText(): string;
|
package/dist/clack.js
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import { cancel, confirm, isCancel, log, spinner } from '@clack/prompts';
|
|
2
2
|
const ESC = String.fromCharCode(0x1b);
|
|
3
|
+
function ansiEnabled(env = process.env) {
|
|
4
|
+
return !env.NO_COLOR && env.TERM !== 'dumb';
|
|
5
|
+
}
|
|
6
|
+
function ansiColor(text, open, close, env) {
|
|
7
|
+
if (!ansiEnabled(env)) {
|
|
8
|
+
return text;
|
|
9
|
+
}
|
|
10
|
+
return `${ESC}[${open}m${text}${ESC}[${close}m`;
|
|
11
|
+
}
|
|
12
|
+
export function dim(text, env) {
|
|
13
|
+
return ansiColor(text, 2, 22, env);
|
|
14
|
+
}
|
|
15
|
+
export function cyan(text, env) {
|
|
16
|
+
return ansiColor(text, 36, 39, env);
|
|
17
|
+
}
|
|
3
18
|
export function errorMessage(error) {
|
|
4
19
|
return error instanceof Error ? error.message : String(error);
|
|
5
20
|
}
|
|
@@ -24,10 +39,10 @@ export function createClackSpinner() {
|
|
|
24
39
|
return spinner();
|
|
25
40
|
}
|
|
26
41
|
function magenta(text) {
|
|
27
|
-
return
|
|
42
|
+
return ansiColor(text, 35, 39);
|
|
28
43
|
}
|
|
29
44
|
function red(text) {
|
|
30
|
-
return
|
|
45
|
+
return ansiColor(text, 31, 39);
|
|
31
46
|
}
|
|
32
47
|
export function createStaticCliSpinner(io) {
|
|
33
48
|
return {
|
package/dist/cli-program.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Command, type CommandUnknownOpts } from '@commander-js/extra-typings';
|
|
2
2
|
import type { KtxCliDeps, KtxCliIo, KtxCliPackageInfo } from './cli-runtime.js';
|
|
3
|
+
import { type PrepareUpdateCheckNoticeOptions } from './update-check/update-check.js';
|
|
3
4
|
export interface KtxCliCommandContext {
|
|
4
5
|
io: KtxCliIo;
|
|
5
6
|
deps: KtxCliDeps;
|
|
@@ -23,6 +24,7 @@ interface KtxCommanderProgramOptions {
|
|
|
23
24
|
force: boolean;
|
|
24
25
|
}, io: KtxCliIo) => Promise<number>;
|
|
25
26
|
}
|
|
27
|
+
type KtxCliUpdateCheckOptions = Pick<PrepareUpdateCheckNoticeOptions, 'env' | 'fetchDistTags' | 'homeDir' | 'now'>;
|
|
26
28
|
export interface BuildKtxProgramOptions {
|
|
27
29
|
io: KtxCliIo;
|
|
28
30
|
deps: KtxCliDeps;
|
|
@@ -34,6 +36,7 @@ export interface BuildKtxProgramOptions {
|
|
|
34
36
|
setExitCode?: (code: number) => void;
|
|
35
37
|
argv?: string[];
|
|
36
38
|
setTelemetryModule?: (telemetry: typeof import('./telemetry/index.js')) => void;
|
|
39
|
+
updateCheck?: KtxCliUpdateCheckOptions;
|
|
37
40
|
}
|
|
38
41
|
export interface CommandWithGlobalOptions {
|
|
39
42
|
opts: () => object;
|
package/dist/cli-program.js
CHANGED
|
@@ -14,6 +14,7 @@ import { registerAdminCommands } from './admin.js';
|
|
|
14
14
|
import { renderMissingProjectMessage } from './doctor.js';
|
|
15
15
|
import { findNearestKtxProjectDir, resolveKtxProjectDir } from './project-resolver.js';
|
|
16
16
|
import { profileMark, profileSpan } from './startup-profile.js';
|
|
17
|
+
import { prepareUpdateCheckNotice } from './update-check/update-check.js';
|
|
17
18
|
profileMark('module:cli-program');
|
|
18
19
|
const PROJECT_AWARE_ROOT_COMMANDS = new Set(['setup', 'connection', 'ingest', 'wiki', 'sl', 'sql', 'status', 'mcp']);
|
|
19
20
|
const PROJECT_INDEPENDENT_ADMIN_COMMANDS = new Set(['runtime', 'schema']);
|
|
@@ -319,16 +320,27 @@ export function collectCommandFlagsPresent(command) {
|
|
|
319
320
|
}
|
|
320
321
|
export function buildKtxProgram(options) {
|
|
321
322
|
const program = createBaseProgram(options.packageInfo, options.io);
|
|
323
|
+
let pendingUpdateNotice = null;
|
|
322
324
|
program.hook('preAction', async (_thisCommand, actionCommand) => {
|
|
323
325
|
// The hidden completion command must stay silent and side-effect free: skip
|
|
324
|
-
// the telemetry notice, command span, and
|
|
326
|
+
// the telemetry notice, command span, project checks, and update checks entirely.
|
|
325
327
|
if (commandPath(actionCommand).includes('__complete')) {
|
|
326
328
|
return;
|
|
327
329
|
}
|
|
330
|
+
const commandNode = actionCommand;
|
|
331
|
+
const updateCheck = await prepareUpdateCheckNotice({
|
|
332
|
+
io: options.io,
|
|
333
|
+
env: options.updateCheck?.env,
|
|
334
|
+
fetchDistTags: options.updateCheck?.fetchDistTags,
|
|
335
|
+
homeDir: options.updateCheck?.homeDir,
|
|
336
|
+
installedVersion: options.packageInfo.version,
|
|
337
|
+
now: options.updateCheck?.now,
|
|
338
|
+
commandOptions: commandOptions(commandNode),
|
|
339
|
+
});
|
|
340
|
+
pendingUpdateNotice = updateCheck.notice;
|
|
328
341
|
const telemetry = await import('./telemetry/index.js');
|
|
329
342
|
options.setTelemetryModule?.(telemetry);
|
|
330
343
|
await telemetry.showTelemetryNoticeIfNeeded(options.io, options.packageInfo);
|
|
331
|
-
const commandNode = actionCommand;
|
|
332
344
|
const path = commandPath(commandNode);
|
|
333
345
|
const projectDir = resolveCommandProjectDir(commandNode);
|
|
334
346
|
const hasProject = ktxYamlExists(projectDir);
|
|
@@ -344,6 +356,12 @@ export function buildKtxProgram(options) {
|
|
|
344
356
|
writeProjectDir(options.io, commandNode);
|
|
345
357
|
ensureProjectAvailable(options.io, commandNode);
|
|
346
358
|
});
|
|
359
|
+
program.hook('postAction', () => {
|
|
360
|
+
if (pendingUpdateNotice) {
|
|
361
|
+
options.io.stderr.write(pendingUpdateNotice);
|
|
362
|
+
pendingUpdateNotice = null;
|
|
363
|
+
}
|
|
364
|
+
});
|
|
347
365
|
const context = {
|
|
348
366
|
io: options.io,
|
|
349
367
|
deps: options.deps,
|
|
@@ -407,6 +425,13 @@ export async function runCommanderKtxCli(argv, io, deps, info, options) {
|
|
|
407
425
|
return await runBareInteractiveCommand(program, io, context);
|
|
408
426
|
}
|
|
409
427
|
catch (error) {
|
|
428
|
+
const telemetry = await import('./telemetry/index.js');
|
|
429
|
+
await telemetry.reportException({
|
|
430
|
+
error,
|
|
431
|
+
context: { source: 'bare-interactive', handled: true, fatal: false },
|
|
432
|
+
packageInfo: info,
|
|
433
|
+
io,
|
|
434
|
+
});
|
|
410
435
|
io.stderr.write(`${formatCliError(error)}\n`);
|
|
411
436
|
return 1;
|
|
412
437
|
}
|
|
@@ -443,6 +468,21 @@ export async function runCommanderKtxCli(argv, io, deps, info, options) {
|
|
|
443
468
|
outcome: commandOutcomeForParseResult(parseError, exitCode),
|
|
444
469
|
error: parseError,
|
|
445
470
|
});
|
|
471
|
+
if (parseError &&
|
|
472
|
+
!isCommanderExit(parseError) &&
|
|
473
|
+
!isKtxProjectMissingAbortError(parseError)) {
|
|
474
|
+
await telemetryModule.reportException({
|
|
475
|
+
error: parseError,
|
|
476
|
+
context: {
|
|
477
|
+
source: completed?.commandPath.join(' ') ?? 'commander parseAsync',
|
|
478
|
+
handled: true,
|
|
479
|
+
fatal: false,
|
|
480
|
+
},
|
|
481
|
+
projectDir: completed?.projectGroupAttached ? completed.projectDir : undefined,
|
|
482
|
+
packageInfo: info,
|
|
483
|
+
io,
|
|
484
|
+
});
|
|
485
|
+
}
|
|
446
486
|
await telemetryModule.emitCompletedCommand({ completed, packageInfo: info, io });
|
|
447
487
|
await telemetryModule.shutdownTelemetryEmitter();
|
|
448
488
|
}
|
package/dist/cli-runtime.d.ts
CHANGED
|
@@ -47,4 +47,7 @@ export declare function runInitForCommander(args: {
|
|
|
47
47
|
projectDir: string;
|
|
48
48
|
force: boolean;
|
|
49
49
|
}, io: KtxCliIo): Promise<number>;
|
|
50
|
+
/** @internal */
|
|
51
|
+
export declare function createGlobalExceptionReporter(io: KtxCliIo, info: KtxCliPackageInfo): (source: "uncaughtException" | "unhandledRejection", error: unknown) => Promise<void>;
|
|
52
|
+
export declare function installGlobalExceptionHandlers(io: KtxCliIo, info: KtxCliPackageInfo): () => void;
|
|
50
53
|
export declare function runKtxCli(argv?: string[], io?: KtxCliIo, deps?: KtxCliDeps): Promise<number>;
|
package/dist/cli-runtime.js
CHANGED
|
@@ -35,11 +35,102 @@ async function runInit(args, io) {
|
|
|
35
35
|
export async function runInitForCommander(args, io) {
|
|
36
36
|
return await runInit(args, io);
|
|
37
37
|
}
|
|
38
|
+
function signalExitCode(signal) {
|
|
39
|
+
// 128 + signal number: SIGINT (2) -> 130, SIGTERM (15) -> 143.
|
|
40
|
+
return signal === 'SIGTERM' ? 143 : 130;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Flush telemetry on interrupt for the real CLI process. `capture()` is
|
|
44
|
+
* fire-and-forget and the only flush guarantee lives in a `finally` a signal
|
|
45
|
+
* skips, so Ctrl-C / `kill` of a long-running command (ingest, `mcp stdio`)
|
|
46
|
+
* would otherwise drop its `command` event and queued events. Installed only
|
|
47
|
+
* when driving the actual process; programmatic/test callers pass their own
|
|
48
|
+
* `io` and never reach here. Returns a disposer that removes the listeners.
|
|
49
|
+
*/
|
|
50
|
+
function installTelemetrySignalFlush(io, info) {
|
|
51
|
+
let handling = false;
|
|
52
|
+
const handle = (signal) => {
|
|
53
|
+
if (handling) {
|
|
54
|
+
process.exit(signalExitCode(signal));
|
|
55
|
+
}
|
|
56
|
+
handling = true;
|
|
57
|
+
void (async () => {
|
|
58
|
+
try {
|
|
59
|
+
const { emitAbortedCommandAndShutdown } = await import('./telemetry/index.js');
|
|
60
|
+
await emitAbortedCommandAndShutdown({ packageInfo: info, io });
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Best-effort: never let a telemetry hiccup block the interrupt exit.
|
|
64
|
+
}
|
|
65
|
+
process.exit(signalExitCode(signal));
|
|
66
|
+
})();
|
|
67
|
+
};
|
|
68
|
+
const onSigint = () => handle('SIGINT');
|
|
69
|
+
const onSigterm = () => handle('SIGTERM');
|
|
70
|
+
process.on('SIGINT', onSigint);
|
|
71
|
+
process.on('SIGTERM', onSigterm);
|
|
72
|
+
return () => {
|
|
73
|
+
process.off('SIGINT', onSigint);
|
|
74
|
+
process.off('SIGTERM', onSigterm);
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** @internal */
|
|
78
|
+
export function createGlobalExceptionReporter(io, info) {
|
|
79
|
+
return async (source, error) => {
|
|
80
|
+
const { reportException, shutdownTelemetryEmitter } = await import('./telemetry/index.js');
|
|
81
|
+
await reportException({
|
|
82
|
+
error,
|
|
83
|
+
context: { source, handled: false, fatal: true },
|
|
84
|
+
io,
|
|
85
|
+
packageInfo: info,
|
|
86
|
+
immediate: true,
|
|
87
|
+
});
|
|
88
|
+
await shutdownTelemetryEmitter();
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export function installGlobalExceptionHandlers(io, info) {
|
|
92
|
+
const report = createGlobalExceptionReporter(io, info);
|
|
93
|
+
const handle = (source, error) => {
|
|
94
|
+
void (async () => {
|
|
95
|
+
try {
|
|
96
|
+
await report(source, error);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Best-effort: preserve Node's process termination behavior.
|
|
100
|
+
}
|
|
101
|
+
if (error instanceof Error && error.stack) {
|
|
102
|
+
io.stderr.write(`${error.stack}\n`);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
io.stderr.write(`${String(error)}\n`);
|
|
106
|
+
}
|
|
107
|
+
process.exit(1);
|
|
108
|
+
})();
|
|
109
|
+
};
|
|
110
|
+
const onUncaught = (error) => handle('uncaughtException', error);
|
|
111
|
+
const onUnhandled = (reason) => handle('unhandledRejection', reason);
|
|
112
|
+
process.on('uncaughtException', onUncaught);
|
|
113
|
+
process.on('unhandledRejection', onUnhandled);
|
|
114
|
+
return () => {
|
|
115
|
+
process.off('uncaughtException', onUncaught);
|
|
116
|
+
process.off('unhandledRejection', onUnhandled);
|
|
117
|
+
};
|
|
118
|
+
}
|
|
38
119
|
export async function runKtxCli(argv = process.argv.slice(2), io = process, deps = {}) {
|
|
39
120
|
const info = getKtxCliPackageInfo();
|
|
40
121
|
profileMark('runtime:runKtxCli');
|
|
41
122
|
const { runCommanderKtxCli } = await profileSpan('import ./cli-program.js', () => import('./cli-program.js'));
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
123
|
+
// Real-process entry only: flush telemetry if interrupted. Test/programmatic
|
|
124
|
+
// callers pass their own `io`, so they never install process-level handlers.
|
|
125
|
+
const removeSignalFlush = io === process ? installTelemetrySignalFlush(io, info) : undefined;
|
|
126
|
+
const removeGlobalExceptionHandlers = io === process ? installGlobalExceptionHandlers(io, info) : undefined;
|
|
127
|
+
try {
|
|
128
|
+
return await runCommanderKtxCli(argv, io, deps, info, {
|
|
129
|
+
runInit: runInitForCommander,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
removeGlobalExceptionHandlers?.();
|
|
134
|
+
removeSignalFlush?.();
|
|
135
|
+
}
|
|
45
136
|
}
|
|
@@ -18,7 +18,7 @@ function embeddingBackend(value) {
|
|
|
18
18
|
throw new InvalidArgumentError(`invalid choice '${value}'`);
|
|
19
19
|
}
|
|
20
20
|
function llmBackend(value) {
|
|
21
|
-
if (value === 'anthropic' || value === 'vertex' || value === 'claude-code') {
|
|
21
|
+
if (value === 'anthropic' || value === 'vertex' || value === 'claude-code' || value === 'codex') {
|
|
22
22
|
return value;
|
|
23
23
|
}
|
|
24
24
|
throw new InvalidArgumentError(`invalid choice '${value}'`);
|
|
@@ -89,7 +89,6 @@ function shouldShowSetupEntryMenu(options, command) {
|
|
|
89
89
|
'llmBackend',
|
|
90
90
|
'anthropicApiKeyEnv',
|
|
91
91
|
'anthropicApiKeyFile',
|
|
92
|
-
'llmModel',
|
|
93
92
|
'vertexProject',
|
|
94
93
|
'vertexLocation',
|
|
95
94
|
'skipLlm',
|
|
@@ -145,7 +144,6 @@ export function registerSetupCommands(program, context) {
|
|
|
145
144
|
.addOption(new Option('--llm-backend <backend>', 'LLM backend').argParser(llmBackend).hideHelp())
|
|
146
145
|
.addOption(new Option('--anthropic-api-key-env <name>', 'Environment variable containing the Anthropic API key').hideHelp())
|
|
147
146
|
.addOption(new Option('--anthropic-api-key-file <path>', 'File containing the Anthropic API key').hideHelp())
|
|
148
|
-
.addOption(new Option('--llm-model <model>', 'LLM model ID or backend model alias').hideHelp())
|
|
149
147
|
.addOption(new Option('--vertex-project <project>', 'Google Vertex AI project ID, env:NAME, or file:/path').hideHelp())
|
|
150
148
|
.addOption(new Option('--vertex-location <location>', 'Google Vertex AI location, env:NAME, or file:/path').hideHelp())
|
|
151
149
|
.addOption(new Option('--skip-llm', 'Leave LLM setup incomplete for now').hideHelp().default(false))
|
|
@@ -272,6 +270,7 @@ export function registerSetupCommands(program, context) {
|
|
|
272
270
|
return;
|
|
273
271
|
}
|
|
274
272
|
const resolvedAgentScope = options.local ? 'local' : options.global ? 'global' : 'project';
|
|
273
|
+
const debugEnabled = (command.optsWithGlobals ? command.optsWithGlobals() : command.opts()).debug === true;
|
|
275
274
|
await runSetupArgs(context, {
|
|
276
275
|
command: 'run',
|
|
277
276
|
projectDir: resolveCommandProjectDir(command),
|
|
@@ -281,12 +280,12 @@ export function registerSetupCommands(program, context) {
|
|
|
281
280
|
agentScope: resolvedAgentScope,
|
|
282
281
|
skipAgents: options.skipAgents === true,
|
|
283
282
|
inputMode: options.input === false ? 'disabled' : 'auto',
|
|
283
|
+
...(debugEnabled ? { debug: true } : {}),
|
|
284
284
|
yes: options.yes === true,
|
|
285
285
|
cliVersion: context.packageInfo.version,
|
|
286
286
|
...(options.llmBackend ? { llmBackend: options.llmBackend } : {}),
|
|
287
287
|
...(options.anthropicApiKeyEnv ? { anthropicApiKeyEnv: options.anthropicApiKeyEnv } : {}),
|
|
288
288
|
...(options.anthropicApiKeyFile ? { anthropicApiKeyFile: options.anthropicApiKeyFile } : {}),
|
|
289
|
-
...(options.llmModel ? { llmModel: options.llmModel } : {}),
|
|
290
289
|
...(options.vertexProject ? { vertexProject: options.vertexProject } : {}),
|
|
291
290
|
...(options.vertexLocation ? { vertexLocation: options.vertexLocation } : {}),
|
|
292
291
|
skipLlm: options.skipLlm === true,
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { KtxCliIo } from './cli-runtime.js';
|
|
2
|
+
import type { KtxSetupPromptOption } from './setup-prompts.js';
|
|
3
|
+
export type RecoveryOutcome = 'ready' | 'skip' | 'back' | 'failed';
|
|
4
|
+
/** @internal */
|
|
5
|
+
export interface RecoveryAction {
|
|
6
|
+
value: string;
|
|
7
|
+
label: string;
|
|
8
|
+
run: () => Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export type ConfigureResult = 'configured' | 'back' | 'cancelled';
|
|
11
|
+
export type ValidateResult = {
|
|
12
|
+
status: 'ok';
|
|
13
|
+
} | {
|
|
14
|
+
status: 'back';
|
|
15
|
+
} | {
|
|
16
|
+
status: 'failed';
|
|
17
|
+
extraActions?: RecoveryAction[];
|
|
18
|
+
};
|
|
19
|
+
export interface ConnectionRecoveryInput {
|
|
20
|
+
label: string;
|
|
21
|
+
interactive: boolean;
|
|
22
|
+
allowSkip: boolean;
|
|
23
|
+
io: KtxCliIo;
|
|
24
|
+
prompts: {
|
|
25
|
+
select(options: {
|
|
26
|
+
message: string;
|
|
27
|
+
options: KtxSetupPromptOption[];
|
|
28
|
+
}): Promise<string>;
|
|
29
|
+
};
|
|
30
|
+
snapshot: () => Promise<() => Promise<void>>;
|
|
31
|
+
configure: () => Promise<ConfigureResult>;
|
|
32
|
+
validate: () => Promise<ValidateResult>;
|
|
33
|
+
}
|
|
34
|
+
export declare function runConnectionSetupWithRecovery(input: ConnectionRecoveryInput): Promise<RecoveryOutcome>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
async function runRollbackOnce(input) {
|
|
2
|
+
if (input.state.rolledBack) {
|
|
3
|
+
return;
|
|
4
|
+
}
|
|
5
|
+
input.state.rolledBack = true;
|
|
6
|
+
await input.rollback();
|
|
7
|
+
}
|
|
8
|
+
function recoveryOptions(input) {
|
|
9
|
+
return [
|
|
10
|
+
{ value: 'retry', label: 'Retry connection test' },
|
|
11
|
+
{ value: 're-enter', label: 'Re-enter connection details' },
|
|
12
|
+
...(input.extraActions ?? []).map((action) => ({
|
|
13
|
+
value: action.value,
|
|
14
|
+
label: action.label,
|
|
15
|
+
})),
|
|
16
|
+
...(input.allowSkip ? [{ value: 'skip', label: 'Skip this connection' }] : []),
|
|
17
|
+
{ value: 'back', label: 'Back' },
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
export async function runConnectionSetupWithRecovery(input) {
|
|
21
|
+
const rollback = await input.snapshot();
|
|
22
|
+
const rollbackState = { rolledBack: false };
|
|
23
|
+
const firstConfig = await input.configure();
|
|
24
|
+
if (firstConfig === 'back') {
|
|
25
|
+
await runRollbackOnce({ rollback, state: rollbackState });
|
|
26
|
+
return 'back';
|
|
27
|
+
}
|
|
28
|
+
if (firstConfig === 'cancelled') {
|
|
29
|
+
await runRollbackOnce({ rollback, state: rollbackState });
|
|
30
|
+
return 'failed';
|
|
31
|
+
}
|
|
32
|
+
let validation = await input.validate();
|
|
33
|
+
while (validation.status !== 'ok') {
|
|
34
|
+
if (validation.status === 'back') {
|
|
35
|
+
await runRollbackOnce({ rollback, state: rollbackState });
|
|
36
|
+
return 'back';
|
|
37
|
+
}
|
|
38
|
+
if (!input.interactive) {
|
|
39
|
+
return 'failed';
|
|
40
|
+
}
|
|
41
|
+
const action = await input.prompts.select({
|
|
42
|
+
message: `Connection setup failed for ${input.label}`,
|
|
43
|
+
options: recoveryOptions({
|
|
44
|
+
allowSkip: input.allowSkip,
|
|
45
|
+
extraActions: validation.extraActions,
|
|
46
|
+
}),
|
|
47
|
+
});
|
|
48
|
+
if (action === 'back') {
|
|
49
|
+
await runRollbackOnce({ rollback, state: rollbackState });
|
|
50
|
+
return 'back';
|
|
51
|
+
}
|
|
52
|
+
if (action === 'skip' && input.allowSkip) {
|
|
53
|
+
await runRollbackOnce({ rollback, state: rollbackState });
|
|
54
|
+
return 'skip';
|
|
55
|
+
}
|
|
56
|
+
if (action === 're-enter') {
|
|
57
|
+
const nextConfig = await input.configure();
|
|
58
|
+
if (nextConfig === 'back') {
|
|
59
|
+
await runRollbackOnce({ rollback, state: rollbackState });
|
|
60
|
+
return 'back';
|
|
61
|
+
}
|
|
62
|
+
if (nextConfig === 'cancelled') {
|
|
63
|
+
await runRollbackOnce({ rollback, state: rollbackState });
|
|
64
|
+
return 'failed';
|
|
65
|
+
}
|
|
66
|
+
validation = await input.validate();
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (action === 'retry') {
|
|
70
|
+
validation = await input.validate();
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const extraAction = validation.extraActions?.find((candidate) => candidate.value === action);
|
|
74
|
+
if (extraAction) {
|
|
75
|
+
await extraAction.run();
|
|
76
|
+
validation = await input.validate();
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
validation = await input.validate();
|
|
80
|
+
}
|
|
81
|
+
return 'ready';
|
|
82
|
+
}
|
package/dist/connection.js
CHANGED
|
@@ -12,8 +12,9 @@ import { bold, dim, green, red, SYMBOLS } from './io/symbols.js';
|
|
|
12
12
|
import { createKtxCliScanConnector } from './local-scan-connectors.js';
|
|
13
13
|
import { profileMark } from './startup-profile.js';
|
|
14
14
|
import { isDemoConnection } from './telemetry/demo-detect.js';
|
|
15
|
-
import { emitTelemetryEvent } from './telemetry/index.js';
|
|
16
|
-
import {
|
|
15
|
+
import { emitTelemetryEvent, reportException } from './telemetry/index.js';
|
|
16
|
+
import { collectTelemetryRedactionSecrets } from './telemetry/redaction-secrets.js';
|
|
17
|
+
import { formatErrorDetail, scrubErrorClass } from './telemetry/scrubber.js';
|
|
17
18
|
profileMark('module:connection');
|
|
18
19
|
const SUPPORTED_TEST_DRIVERS = [
|
|
19
20
|
'sqlite',
|
|
@@ -44,6 +45,12 @@ async function testNativeConnection(project, connectionId, createScanConnector)
|
|
|
44
45
|
}
|
|
45
46
|
const result = await connector.testConnection();
|
|
46
47
|
if (!result.success) {
|
|
48
|
+
// Re-throw the driver's original error so connection_test telemetry records
|
|
49
|
+
// its real class (e.g. ConnectionError) and code (e.g. ELOGIN) instead of
|
|
50
|
+
// collapsing every native failure to a generic Error with no code.
|
|
51
|
+
if (result.cause instanceof Error) {
|
|
52
|
+
throw result.cause;
|
|
53
|
+
}
|
|
47
54
|
throw new Error(result.error ?? 'connection test failed');
|
|
48
55
|
}
|
|
49
56
|
return { driver: connector.driver };
|
|
@@ -168,6 +175,7 @@ async function testConnectionByDriver(project, connectionId, deps) {
|
|
|
168
175
|
}
|
|
169
176
|
async function emitConnectionTest(input) {
|
|
170
177
|
const errorClass = input.error ? scrubErrorClass(input.error) : undefined;
|
|
178
|
+
const errorDetail = input.error ? formatErrorDetail(input.error) : undefined;
|
|
171
179
|
await emitTelemetryEvent({
|
|
172
180
|
name: 'connection_test',
|
|
173
181
|
projectDir: input.project.projectDir,
|
|
@@ -178,8 +186,24 @@ async function emitConnectionTest(input) {
|
|
|
178
186
|
outcome: input.outcome,
|
|
179
187
|
durationMs: input.durationMs,
|
|
180
188
|
...(errorClass ? { errorClass } : {}),
|
|
189
|
+
...(errorDetail ? { errorDetail } : {}),
|
|
181
190
|
},
|
|
182
191
|
});
|
|
192
|
+
if (input.error) {
|
|
193
|
+
await reportException({
|
|
194
|
+
error: input.error,
|
|
195
|
+
context: { source: 'connection test', handled: true, fatal: false },
|
|
196
|
+
projectDir: input.project.projectDir,
|
|
197
|
+
io: input.io,
|
|
198
|
+
redactionSecrets: await collectTelemetryRedactionSecrets({
|
|
199
|
+
project: input.project,
|
|
200
|
+
connectionId: input.connectionId,
|
|
201
|
+
includeLlm: false,
|
|
202
|
+
includeEmbeddings: false,
|
|
203
|
+
env: process.env,
|
|
204
|
+
}),
|
|
205
|
+
});
|
|
206
|
+
}
|
|
183
207
|
}
|
|
184
208
|
function visualWidth(text) {
|
|
185
209
|
// styleText wraps content in ANSI escape sequences; strip them before measuring.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type TableField } from '@google-cloud/bigquery';
|
|
2
|
-
import { type KtxColumnSampleInput, type KtxColumnSampleResult, type KtxColumnStatsInput, type KtxColumnStatsResult, type KtxQueryResult, type KtxReadOnlyQueryInput, type KtxScanConnector, type KtxScanContext, type KtxScanInput, type KtxSchemaSnapshot, type KtxTableListEntry, type KtxTableRef, type KtxTableSampleInput, type KtxTableSampleResult } from '../../context/scan/types.js';
|
|
2
|
+
import { type KtxConnectorTestResult, type KtxColumnSampleInput, type KtxColumnSampleResult, type KtxColumnStatsInput, type KtxColumnStatsResult, type KtxQueryResult, type KtxReadOnlyQueryInput, type KtxScanConnector, type KtxScanContext, type KtxScanInput, type KtxSchemaSnapshot, type KtxTableListEntry, type KtxTableRef, type KtxTableSampleInput, type KtxTableSampleResult } from '../../context/scan/types.js';
|
|
3
3
|
export interface KtxBigQueryConnectionConfig {
|
|
4
4
|
driver?: string;
|
|
5
5
|
dataset_id?: string;
|
|
@@ -121,10 +121,7 @@ export declare class KtxBigQueryScanConnector implements KtxScanConnector {
|
|
|
121
121
|
private readonly dialect;
|
|
122
122
|
private client;
|
|
123
123
|
constructor(options: KtxBigQueryScanConnectorOptions);
|
|
124
|
-
testConnection(): Promise<
|
|
125
|
-
success: boolean;
|
|
126
|
-
error?: string;
|
|
127
|
-
}>;
|
|
124
|
+
testConnection(): Promise<KtxConnectorTestResult>;
|
|
128
125
|
introspect(input: KtxScanInput, _ctx: KtxScanContext): Promise<KtxSchemaSnapshot>;
|
|
129
126
|
sampleTable(input: KtxTableSampleInput, _ctx: KtxScanContext): Promise<KtxTableSampleResult & {
|
|
130
127
|
headerTypes?: string[];
|
|
@@ -4,7 +4,7 @@ import { getDialectForDriver } from '../../context/connections/dialects.js';
|
|
|
4
4
|
import { assertReadOnlySql, limitSqlForExecution } from '../../context/connections/read-only-sql.js';
|
|
5
5
|
import { tryConstraintQuery } from '../../context/scan/constraint-discovery.js';
|
|
6
6
|
import { scopedTableNames } from '../../context/scan/table-ref.js';
|
|
7
|
-
import { createKtxConnectorCapabilities, } from '../../context/scan/types.js';
|
|
7
|
+
import { connectorTestFailure, createKtxConnectorCapabilities, } from '../../context/scan/types.js';
|
|
8
8
|
import { readFileSync } from 'node:fs';
|
|
9
9
|
import { homedir } from 'node:os';
|
|
10
10
|
import { resolve } from 'node:path';
|
|
@@ -185,7 +185,7 @@ export class KtxBigQueryScanConnector {
|
|
|
185
185
|
return { success: true };
|
|
186
186
|
}
|
|
187
187
|
catch (error) {
|
|
188
|
-
return
|
|
188
|
+
return connectorTestFailure(error);
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
191
|
async introspect(input, _ctx) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createClient } from '@clickhouse/client';
|
|
2
|
-
import { type KtxColumnSampleInput, type KtxColumnSampleResult, type KtxColumnStatsInput, type KtxColumnStatsResult, type KtxQueryResult, type KtxReadOnlyQueryInput, type KtxScanConnector, type KtxScanContext, type KtxScanInput, type KtxSchemaSnapshot, type KtxTableRef, type KtxTableSampleInput, type KtxTableListEntry, type KtxTableSampleResult } from '../../context/scan/types.js';
|
|
2
|
+
import { type KtxConnectorTestResult, type KtxColumnSampleInput, type KtxColumnSampleResult, type KtxColumnStatsInput, type KtxColumnStatsResult, type KtxQueryResult, type KtxReadOnlyQueryInput, type KtxScanConnector, type KtxScanContext, type KtxScanInput, type KtxSchemaSnapshot, type KtxTableRef, type KtxTableSampleInput, type KtxTableListEntry, type KtxTableSampleResult } from '../../context/scan/types.js';
|
|
3
3
|
export interface KtxClickHouseConnectionConfig {
|
|
4
4
|
driver?: string;
|
|
5
5
|
host?: string;
|
|
@@ -94,10 +94,7 @@ export declare class KtxClickHouseScanConnector implements KtxScanConnector {
|
|
|
94
94
|
private client;
|
|
95
95
|
private resolvedEndpoint;
|
|
96
96
|
constructor(options: KtxClickHouseScanConnectorOptions);
|
|
97
|
-
testConnection(): Promise<
|
|
98
|
-
success: boolean;
|
|
99
|
-
error?: string;
|
|
100
|
-
}>;
|
|
97
|
+
testConnection(): Promise<KtxConnectorTestResult>;
|
|
101
98
|
introspect(input: KtxScanInput, _ctx: KtxScanContext): Promise<KtxSchemaSnapshot>;
|
|
102
99
|
private emptySnapshot;
|
|
103
100
|
sampleTable(input: KtxTableSampleInput, _ctx: KtxScanContext): Promise<KtxTableSampleResult>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createClient } from '@clickhouse/client';
|
|
2
2
|
import { getDialectForDriver } from '../../context/connections/dialects.js';
|
|
3
3
|
import { assertReadOnlySql, limitSqlForExecution } from '../../context/connections/read-only-sql.js';
|
|
4
|
-
import { createKtxConnectorCapabilities } from '../../context/scan/types.js';
|
|
4
|
+
import { connectorTestFailure, createKtxConnectorCapabilities } from '../../context/scan/types.js';
|
|
5
5
|
import { scopedTableNames } from '../../context/scan/table-ref.js';
|
|
6
6
|
import { readFileSync } from 'node:fs';
|
|
7
7
|
import { Agent as HttpsAgent } from 'node:https';
|
|
@@ -162,7 +162,7 @@ export class KtxClickHouseScanConnector {
|
|
|
162
162
|
return { success: true };
|
|
163
163
|
}
|
|
164
164
|
catch (error) {
|
|
165
|
-
return
|
|
165
|
+
return connectorTestFailure(error);
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
async introspect(input, _ctx) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type FieldPacket, type RowDataPacket } from 'mysql2/promise';
|
|
2
|
-
import { type KtxColumnSampleInput, type KtxColumnSampleResult, type KtxColumnStatsInput, type KtxColumnStatsResult, type KtxQueryResult, type KtxReadOnlyQueryInput, type KtxScanConnector, type KtxScanContext, type KtxScanInput, type KtxSchemaSnapshot, type KtxTableListEntry, type KtxTableRef, type KtxTableSampleInput, type KtxTableSampleResult } from '../../context/scan/types.js';
|
|
2
|
+
import { type KtxConnectorTestResult, type KtxColumnSampleInput, type KtxColumnSampleResult, type KtxColumnStatsInput, type KtxColumnStatsResult, type KtxQueryResult, type KtxReadOnlyQueryInput, type KtxScanConnector, type KtxScanContext, type KtxScanInput, type KtxSchemaSnapshot, type KtxTableListEntry, type KtxTableRef, type KtxTableSampleInput, type KtxTableSampleResult } from '../../context/scan/types.js';
|
|
3
3
|
export interface KtxMysqlConnectionConfig {
|
|
4
4
|
driver?: string;
|
|
5
5
|
host?: string;
|
|
@@ -71,6 +71,9 @@ export interface KtxMysqlColumnDistinctValuesResult {
|
|
|
71
71
|
values: string[] | null;
|
|
72
72
|
cardinality: number;
|
|
73
73
|
}
|
|
74
|
+
export interface KtxMysqlColumnStatisticsResult {
|
|
75
|
+
cardinalityByColumn: Map<string, number>;
|
|
76
|
+
}
|
|
74
77
|
/** @internal */
|
|
75
78
|
export declare function prepareMysqlReadOnlyQuery(sql: string, params?: Record<string, unknown>): {
|
|
76
79
|
sql: string;
|
|
@@ -97,15 +100,13 @@ export declare class KtxMysqlScanConnector implements KtxScanConnector {
|
|
|
97
100
|
private pool;
|
|
98
101
|
private resolvedEndpoint;
|
|
99
102
|
constructor(options: KtxMysqlScanConnectorOptions);
|
|
100
|
-
testConnection(): Promise<
|
|
101
|
-
success: boolean;
|
|
102
|
-
error?: string;
|
|
103
|
-
}>;
|
|
103
|
+
testConnection(): Promise<KtxConnectorTestResult>;
|
|
104
104
|
introspect(input: KtxScanInput, _ctx: KtxScanContext): Promise<KtxSchemaSnapshot>;
|
|
105
105
|
private emptySnapshot;
|
|
106
106
|
sampleTable(input: KtxTableSampleInput, _ctx: KtxScanContext): Promise<KtxTableSampleResult>;
|
|
107
107
|
sampleColumn(input: KtxColumnSampleInput, _ctx: KtxScanContext): Promise<KtxColumnSampleResult>;
|
|
108
|
-
columnStats(
|
|
108
|
+
columnStats(input: KtxColumnStatsInput, _ctx: KtxScanContext): Promise<KtxColumnStatsResult | null>;
|
|
109
|
+
getColumnStatistics(table: KtxTableRef): Promise<KtxMysqlColumnStatisticsResult | null>;
|
|
109
110
|
executeReadOnly(input: KtxMysqlReadOnlyQueryInput, _ctx: KtxScanContext): Promise<KtxQueryResult>;
|
|
110
111
|
getColumnDistinctValues(table: KtxTableRef, columnName: string, options: KtxMysqlColumnDistinctValuesOptions): Promise<KtxMysqlColumnDistinctValuesResult | null>;
|
|
111
112
|
getTableRowCount(tableName: string): Promise<number>;
|