@kaelio/ktx 0.9.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.9.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 +44 -0
- package/dist/commands/setup-commands.js +2 -3
- package/dist/connection.js +23 -1
- 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/query-history-filter-picker.d.ts +1 -0
- package/dist/context/ingest/adapters/historic-sql/query-history-filter-picker.js +6 -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/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-bundle-runtime.js +11 -4
- 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-runtime.d.ts +3 -3
- package/dist/context/llm/codex-runtime.js +90 -47
- package/dist/context/llm/local-config.d.ts +15 -5
- package/dist/context/llm/local-config.js +6 -1
- 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 +12 -0
- package/dist/context/project/config.js +35 -0
- 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/tools/context-candidate-mark.tool.d.ts +2 -2
- package/dist/context-build-view.d.ts +13 -0
- package/dist/context-build-view.js +60 -1
- 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/symbols.d.ts +2 -0
- package/dist/io/symbols.js +2 -0
- package/dist/memory-flow-hud.js +8 -16
- package/dist/public-ingest.js +50 -15
- package/dist/reveal-password-prompt.d.ts +24 -0
- package/dist/reveal-password-prompt.js +78 -0
- package/dist/scan.js +18 -2
- package/dist/setup-databases.d.ts +1 -0
- package/dist/setup-databases.js +23 -3
- package/dist/setup-demo-tour.js +1 -0
- package/dist/setup-embeddings.js +1 -1
- package/dist/setup-models.d.ts +1 -14
- package/dist/setup-models.js +116 -340
- package/dist/setup-prompts.js +3 -2
- package/dist/setup-sources.js +7 -7
- package/dist/setup.d.ts +1 -1
- package/dist/setup.js +1 -1
- 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/telemetry/emitter.d.ts +10 -0
- package/dist/telemetry/emitter.js +31 -0
- package/dist/telemetry/events.d.ts +24 -0
- package/dist/telemetry/events.js +15 -0
- package/dist/telemetry/exception.d.ts +18 -0
- package/dist/telemetry/exception.js +162 -0
- package/dist/telemetry/index.d.ts +3 -2
- package/dist/telemetry/index.js +2 -1
- package/dist/telemetry/redaction-secrets.d.ts +11 -0
- package/dist/telemetry/redaction-secrets.js +92 -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 +8 -1
- 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
|
@@ -74,6 +74,48 @@ function installTelemetrySignalFlush(io, info) {
|
|
|
74
74
|
process.off('SIGTERM', onSigterm);
|
|
75
75
|
};
|
|
76
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
|
+
}
|
|
77
119
|
export async function runKtxCli(argv = process.argv.slice(2), io = process, deps = {}) {
|
|
78
120
|
const info = getKtxCliPackageInfo();
|
|
79
121
|
profileMark('runtime:runKtxCli');
|
|
@@ -81,12 +123,14 @@ export async function runKtxCli(argv = process.argv.slice(2), io = process, deps
|
|
|
81
123
|
// Real-process entry only: flush telemetry if interrupted. Test/programmatic
|
|
82
124
|
// callers pass their own `io`, so they never install process-level handlers.
|
|
83
125
|
const removeSignalFlush = io === process ? installTelemetrySignalFlush(io, info) : undefined;
|
|
126
|
+
const removeGlobalExceptionHandlers = io === process ? installGlobalExceptionHandlers(io, info) : undefined;
|
|
84
127
|
try {
|
|
85
128
|
return await runCommanderKtxCli(argv, io, deps, info, {
|
|
86
129
|
runInit: runInitForCommander,
|
|
87
130
|
});
|
|
88
131
|
}
|
|
89
132
|
finally {
|
|
133
|
+
removeGlobalExceptionHandlers?.();
|
|
90
134
|
removeSignalFlush?.();
|
|
91
135
|
}
|
|
92
136
|
}
|
|
@@ -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,
|
package/dist/connection.js
CHANGED
|
@@ -12,7 +12,8 @@ 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';
|
|
15
|
+
import { emitTelemetryEvent, reportException } from './telemetry/index.js';
|
|
16
|
+
import { collectTelemetryRedactionSecrets } from './telemetry/redaction-secrets.js';
|
|
16
17
|
import { formatErrorDetail, scrubErrorClass } from './telemetry/scrubber.js';
|
|
17
18
|
profileMark('module:connection');
|
|
18
19
|
const SUPPORTED_TEST_DRIVERS = [
|
|
@@ -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 };
|
|
@@ -182,6 +189,21 @@ async function emitConnectionTest(input) {
|
|
|
182
189
|
...(errorDetail ? { errorDetail } : {}),
|
|
183
190
|
},
|
|
184
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
|
+
}
|
|
185
207
|
}
|
|
186
208
|
function visualWidth(text) {
|
|
187
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>;
|
|
@@ -6,7 +6,7 @@ import { getDialectForDriver } from '../../context/connections/dialects.js';
|
|
|
6
6
|
import { assertReadOnlySql, limitSqlForExecution } from '../../context/connections/read-only-sql.js';
|
|
7
7
|
import { constraintDiscoveryWarning, tryConstraintQuery, } from '../../context/scan/constraint-discovery.js';
|
|
8
8
|
import { scopedTableNames } from '../../context/scan/table-ref.js';
|
|
9
|
-
import { createKtxConnectorCapabilities, } from '../../context/scan/types.js';
|
|
9
|
+
import { connectorTestFailure, createKtxConnectorCapabilities, } from '../../context/scan/types.js';
|
|
10
10
|
class DefaultMysqlPoolFactory {
|
|
11
11
|
createPool(config) {
|
|
12
12
|
return mysql.createPool(config);
|
|
@@ -185,7 +185,7 @@ export class KtxMysqlScanConnector {
|
|
|
185
185
|
capabilities = createKtxConnectorCapabilities({
|
|
186
186
|
tableSampling: true,
|
|
187
187
|
columnSampling: true,
|
|
188
|
-
columnStats:
|
|
188
|
+
columnStats: true,
|
|
189
189
|
readOnlySql: true,
|
|
190
190
|
nestedAnalysis: true,
|
|
191
191
|
formalForeignKeys: true,
|
|
@@ -219,7 +219,7 @@ export class KtxMysqlScanConnector {
|
|
|
219
219
|
return { success: true };
|
|
220
220
|
}
|
|
221
221
|
catch (error) {
|
|
222
|
-
return
|
|
222
|
+
return connectorTestFailure(error);
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
225
|
async introspect(input, _ctx) {
|
|
@@ -324,8 +324,28 @@ export class KtxMysqlScanConnector {
|
|
|
324
324
|
const values = result.rows.filter((row) => row.length > 0 && row[0] !== null).map((row) => row[0]);
|
|
325
325
|
return { values, nullCount: null, distinctCount: null };
|
|
326
326
|
}
|
|
327
|
-
async columnStats(
|
|
328
|
-
|
|
327
|
+
async columnStats(input, _ctx) {
|
|
328
|
+
const stats = await this.getColumnStatistics(input.table);
|
|
329
|
+
const value = stats?.cardinalityByColumn.get(input.column);
|
|
330
|
+
return value === undefined
|
|
331
|
+
? null
|
|
332
|
+
: { min: null, max: null, average: null, nullCount: null, distinctCount: value };
|
|
333
|
+
}
|
|
334
|
+
async getColumnStatistics(table) {
|
|
335
|
+
const schema = table.db ?? this.poolConfig.database;
|
|
336
|
+
const sql = this.dialect.generateColumnStatisticsQuery(schema, table.name);
|
|
337
|
+
if (!sql) {
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
const rows = await this.queryRaw(sql);
|
|
341
|
+
const cardinalityByColumn = new Map();
|
|
342
|
+
for (const row of rows) {
|
|
343
|
+
const cardinality = Number(row.estimated_cardinality);
|
|
344
|
+
if (Number.isFinite(cardinality) && cardinality >= 0) {
|
|
345
|
+
cardinalityByColumn.set(row.column_name, cardinality);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return cardinalityByColumn.size > 0 ? { cardinalityByColumn } : null;
|
|
329
349
|
}
|
|
330
350
|
async executeReadOnly(input, _ctx) {
|
|
331
351
|
this.assertConnection(input.connectionId);
|
|
@@ -25,7 +25,7 @@ export declare class KtxMysqlDialect implements KtxDialect {
|
|
|
25
25
|
getSampleValueAggregation(innerSql: string): string;
|
|
26
26
|
generateCardinalitySampleQuery(tableName: string, columnName: string, sampleSize: number): string;
|
|
27
27
|
generateDistinctValuesQuery(tableName: string, columnName: string, limit: number): string;
|
|
28
|
-
generateColumnStatisticsQuery(
|
|
28
|
+
generateColumnStatisticsQuery(schemaName: string, tableName: string): string | null;
|
|
29
29
|
generateRandomizedCardinalitySampleQuery(tableName: string, columnName: string, sampleSize: number): string;
|
|
30
30
|
}
|
|
31
31
|
export {};
|
|
@@ -135,8 +135,18 @@ export class KtxMysqlDialect {
|
|
|
135
135
|
LIMIT ${limit}
|
|
136
136
|
`;
|
|
137
137
|
}
|
|
138
|
-
generateColumnStatisticsQuery(
|
|
139
|
-
return
|
|
138
|
+
generateColumnStatisticsQuery(schemaName, tableName) {
|
|
139
|
+
return `
|
|
140
|
+
SELECT
|
|
141
|
+
COLUMN_NAME AS column_name,
|
|
142
|
+
MAX(CARDINALITY) AS estimated_cardinality
|
|
143
|
+
FROM INFORMATION_SCHEMA.STATISTICS
|
|
144
|
+
WHERE TABLE_SCHEMA = '${schemaName.replace(/'/g, "''")}'
|
|
145
|
+
AND TABLE_NAME = '${tableName.replace(/'/g, "''")}'
|
|
146
|
+
AND CARDINALITY IS NOT NULL
|
|
147
|
+
AND SEQ_IN_INDEX = 1
|
|
148
|
+
GROUP BY COLUMN_NAME
|
|
149
|
+
`;
|
|
140
150
|
}
|
|
141
151
|
generateRandomizedCardinalitySampleQuery(tableName, columnName, sampleSize) {
|
|
142
152
|
return `
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
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';
|
|
1
|
+
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';
|
|
2
2
|
export interface KtxPostgresConnectionConfig {
|
|
3
3
|
driver?: string;
|
|
4
4
|
host?: string;
|
|
@@ -117,10 +117,7 @@ export declare class KtxPostgresScanConnector implements KtxScanConnector {
|
|
|
117
117
|
private lastIdlePoolError;
|
|
118
118
|
private resolvedEndpoint;
|
|
119
119
|
constructor(options: KtxPostgresScanConnectorOptions);
|
|
120
|
-
testConnection(): Promise<
|
|
121
|
-
success: boolean;
|
|
122
|
-
error?: string;
|
|
123
|
-
}>;
|
|
120
|
+
testConnection(): Promise<KtxConnectorTestResult>;
|
|
124
121
|
introspect(input: KtxScanInput, _ctx: KtxScanContext): Promise<KtxSchemaSnapshot>;
|
|
125
122
|
sampleTable(input: KtxTableSampleInput, _ctx: KtxScanContext): Promise<KtxPostgresTableSampleResult>;
|
|
126
123
|
sampleColumn(input: KtxColumnSampleInput, _ctx: KtxScanContext): Promise<KtxColumnSampleResult>;
|
|
@@ -5,7 +5,7 @@ import { getDialectForDriver } from '../../context/connections/dialects.js';
|
|
|
5
5
|
import { assertReadOnlySql, limitSqlForExecution } from '../../context/connections/read-only-sql.js';
|
|
6
6
|
import { tryConstraintQuery } from '../../context/scan/constraint-discovery.js';
|
|
7
7
|
import { scopedTableNames } from '../../context/scan/table-ref.js';
|
|
8
|
-
import { createKtxConnectorCapabilities, } from '../../context/scan/types.js';
|
|
8
|
+
import { connectorTestFailure, createKtxConnectorCapabilities, } from '../../context/scan/types.js';
|
|
9
9
|
import { Pool } from 'pg';
|
|
10
10
|
const PG_OID_TYPE_MAP = {
|
|
11
11
|
16: 'boolean',
|
|
@@ -231,7 +231,7 @@ export class KtxPostgresScanConnector {
|
|
|
231
231
|
return { success: true };
|
|
232
232
|
}
|
|
233
233
|
catch (error) {
|
|
234
|
-
return
|
|
234
|
+
return connectorTestFailure(error);
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
237
|
async introspect(input, _ctx) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
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';
|
|
1
|
+
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';
|
|
2
2
|
export interface KtxSnowflakeConnectionConfig {
|
|
3
3
|
driver?: string;
|
|
4
4
|
authMethod?: 'password' | 'rsa';
|
|
@@ -117,10 +117,7 @@ export declare class KtxSnowflakeScanConnector implements KtxScanConnector {
|
|
|
117
117
|
private readonly now;
|
|
118
118
|
private driverInstance;
|
|
119
119
|
constructor(options: KtxSnowflakeScanConnectorOptions);
|
|
120
|
-
testConnection(): Promise<
|
|
121
|
-
success: boolean;
|
|
122
|
-
error?: string;
|
|
123
|
-
}>;
|
|
120
|
+
testConnection(): Promise<KtxConnectorTestResult>;
|
|
124
121
|
introspect(input: KtxScanInput, _ctx: KtxScanContext): Promise<KtxSchemaSnapshot>;
|
|
125
122
|
sampleTable(input: KtxTableSampleInput, _ctx: KtxScanContext): Promise<KtxTableSampleResult>;
|
|
126
123
|
sampleColumn(input: KtxColumnSampleInput, _ctx: KtxScanContext): Promise<KtxColumnSampleResult>;
|
|
@@ -6,7 +6,7 @@ import { getDialectForDriver } from '../../context/connections/dialects.js';
|
|
|
6
6
|
import { assertReadOnlySql, limitSqlForExecution } from '../../context/connections/read-only-sql.js';
|
|
7
7
|
import { tryConstraintQuery } from '../../context/scan/constraint-discovery.js';
|
|
8
8
|
import { scopedTableNames } from '../../context/scan/table-ref.js';
|
|
9
|
-
import { createKtxConnectorCapabilities, } from '../../context/scan/types.js';
|
|
9
|
+
import { connectorTestFailure, createKtxConnectorCapabilities, } from '../../context/scan/types.js';
|
|
10
10
|
import snowflake from 'snowflake-sdk';
|
|
11
11
|
import { assertSafeSnowflakeIdentifier, quoteSnowflakeIdentifier } from './identifiers.js';
|
|
12
12
|
import { configureSnowflakeSdkLogger } from './sdk-logger.js';
|
|
@@ -282,7 +282,7 @@ class SnowflakeSdkDriver {
|
|
|
282
282
|
return { success: true };
|
|
283
283
|
}
|
|
284
284
|
catch (error) {
|
|
285
|
-
return
|
|
285
|
+
return connectorTestFailure(error);
|
|
286
286
|
}
|
|
287
287
|
}
|
|
288
288
|
async getPool() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
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';
|
|
1
|
+
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';
|
|
2
2
|
export interface KtxSqliteConnectionConfig {
|
|
3
3
|
driver?: string;
|
|
4
4
|
path?: string;
|
|
@@ -39,10 +39,7 @@ export declare class KtxSqliteScanConnector implements KtxScanConnector {
|
|
|
39
39
|
private readonly dialect;
|
|
40
40
|
private db;
|
|
41
41
|
constructor(options: KtxSqliteScanConnectorOptions);
|
|
42
|
-
testConnection(): Promise<
|
|
43
|
-
success: boolean;
|
|
44
|
-
error?: string;
|
|
45
|
-
}>;
|
|
42
|
+
testConnection(): Promise<KtxConnectorTestResult>;
|
|
46
43
|
introspect(input: KtxScanInput, _ctx: KtxScanContext): Promise<KtxSchemaSnapshot>;
|
|
47
44
|
listSchemas(): Promise<string[]>;
|
|
48
45
|
listTables(_schemas?: string[]): Promise<KtxTableListEntry[]>;
|
|
@@ -6,7 +6,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
6
6
|
import { getDialectForDriver } from '../../context/connections/dialects.js';
|
|
7
7
|
import { assertReadOnlySql, limitSqlForExecution } from '../../context/connections/read-only-sql.js';
|
|
8
8
|
import { normalizeQueryRows } from '../../context/connections/query-executor.js';
|
|
9
|
-
import { createKtxConnectorCapabilities } from '../../context/scan/types.js';
|
|
9
|
+
import { connectorTestFailure, createKtxConnectorCapabilities } from '../../context/scan/types.js';
|
|
10
10
|
import { scopedTableNames } from '../../context/scan/table-ref.js';
|
|
11
11
|
function stringConfigValue(connection, key) {
|
|
12
12
|
const value = connection?.[key];
|
|
@@ -106,7 +106,7 @@ export class KtxSqliteScanConnector {
|
|
|
106
106
|
return { success: true };
|
|
107
107
|
}
|
|
108
108
|
catch (error) {
|
|
109
|
-
return
|
|
109
|
+
return connectorTestFailure(error);
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
async introspect(input, _ctx) {
|