// Generated by dts-bundle-generator v9.5.1 import { z } from 'zod'; /** * Database adapter type definitions and interfaces * Defines the contract that all database adapters must implement */ export type DatabaseSystem = "postgresql" | "mysql" | "mariadb" | "mongodb" | "redis" | "elasticsearch"; type SqlDatabaseSystem = Extract; type QueryableDatabaseSystem = Exclude; /** * Connection configuration for database adapters */ export interface ConnectionOptions { /** Database system type */ system: DatabaseSystem; /** Database host address or hostname */ host: string; /** Database port number */ port: number; /** Database user name */ user: string; /** Database password */ password: string; /** Database name */ database: string; /** MongoDB connection URI (optional, for MongoDB connections) */ uri?: string; /** MongoDB auth database — used when building URI from host/port/user/password (default: 'admin') */ authSource?: string; /** MongoDB replica set name (optional, field-based config) */ replicaSet?: string; /** MongoDB TLS switch (optional, field-based config; implied true when srv) */ tls?: boolean; /** MongoDB SRV lookup — build a mongodb+srv:// URI from host (optional, field-based config) */ srv?: boolean; /** Connection timeout in milliseconds (default: 5000) */ timeout?: number; /** * Statement timeout in milliseconds. Falls back to `timeout` when unset, and * to the server default when neither is given — an unset statement timeout * means the server decides, not that 5000ms applies. 0 removes the limit. */ statementTimeout?: number; /** Elasticsearch protocol (http or https) */ protocol?: "http" | "https"; /** Elasticsearch nodes for round-robin (optional) */ nodes?: string[]; /** Elasticsearch Cloud ID (optional) */ cloudId?: string; /** Elasticsearch API Key (optional) */ apiKey?: string; /** Elasticsearch CA Certificate Path (optional) */ caPath?: string; /** Whether to reject unauthorized TLS connections (default: true) */ rejectUnauthorized?: boolean; } export type SqlConnectionOptions = ConnectionOptions & { system: SqlDatabaseSystem; }; export type QueryableConnectionOptions = ConnectionOptions & { system: QueryableDatabaseSystem; }; /** * Schema information for a single column */ export interface ColumnSchema { /** Column name */ name: string; /** Column data type */ type: string; /** Whether column allows NULL values */ nullable: boolean; /** Default value for column (if any) */ default?: string; /** Whether column is primary key */ primaryKey?: boolean; /** Foreign key reference if applicable */ foreignKey?: { table: string; column: string; }; /** Whether column is auto-incremented */ autoIncrement?: boolean; /** Column comment/description */ comment?: string | null; /** Enum values if column is ENUM type */ enumValues?: string[]; /** MongoDB only: 0..1 fraction of sampled docs that contained this dot-path. Undefined for SQL. */ presence?: number; /** MongoDB only: true when this dot-path matches a blacklist pattern. Undefined for SQL. */ redacted?: boolean; } /** * Complete schema information for a table */ export interface TableSchema { /** Table name */ name: string; /** Exact database schema/catalog namespace, when reliably available */ schema?: string; /** Array of columns in the table */ columns: ColumnSchema[]; /** Approximate row count (if available) */ rowCount?: number; /** Storage engine (PostgreSQL/MySQL) */ engine?: string; /** Primary key column names */ primaryKey?: string[]; /** Foreign key constraints with metadata */ foreignKeys?: Array<{ name: string; columns: string[]; refSchema?: string; refTable: string; refColumns: string[]; }>; /** Table indexes with column information */ indexes?: Array<{ name: string; columns: string[]; unique: boolean; }>; /** Column count (used by listTables when full column details are not loaded) */ columnCount?: number; /** Estimated row count in table */ estimatedRowCount?: number; /** Type of table (table or view) */ tableType?: "table" | "view"; } type ConnectionErrorCode = "ECONNREFUSED" | "ETIMEDOUT" | "AUTH_FAILED" | "ENOTFOUND" | "EHOSTUNREACH" | "CONNECTION_LOST" | "TOO_MANY_CONNECTIONS" | "TLS_ERROR" | "SERVER_NOT_READY" | "CONNECTION_REJECTED" | "SQL_SYNTAX_ERROR" | "STATEMENT_TIMEOUT" | "TABLE_NOT_FOUND" | "COLUMN_NOT_FOUND" | "UNKNOWN"; export declare class ConnectionError extends Error { /** Error category code */ code: ConnectionErrorCode; /** Array of actionable troubleshooting hints */ hints: string[]; /** * The ceiling that was in force, in milliseconds. Set on STATEMENT_TIMEOUT so * consumers can state it without parsing `message`; the recovery envelope needs * it to tell an agent what `--statement-timeout ` it was already up against. */ limitMs?: number | undefined; constructor( /** Error category code */ code: ConnectionErrorCode, /** User-friendly error message */ message: string, /** Array of actionable troubleshooting hints */ hints: string[], /** * The ceiling that was in force, in milliseconds. Set on STATEMENT_TIMEOUT so * consumers can state it without parsing `message`; the recovery envelope needs * it to tell an agent what `--statement-timeout ` it was already up against. */ limitMs?: number | undefined); } /** * Result of a database query or command execution */ export interface ExecutionResult { /** Array of result rows as objects (for SELECT queries) */ rows: T[]; /** Number of rows affected by the operation (for INSERT/UPDATE/DELETE) */ affectedRows: number; /** Last inserted ID if applicable (for INSERT operations) */ lastInsertId?: number | string; /** Convenience row count — used by formatters; mirrors rows.length on read paths */ rowCount?: number; /** Column ordering for the rows, used by formatters that render tabular output */ columnNames?: string[]; /** Optional warnings — emitted today only by RedisAdapter (size guard / blacklist filter). */ warnings?: RedisWarning[]; } type RedisWarning = { code: "REDIS_SIZE_REWRITE"; command: string; original: string[]; rewritten: string[]; } | { code: "REDIS_SIZE_TRUNCATE"; command: string; kept: number; droppedAtLeast: number; } | { code: "REDIS_BLACKLIST_FILTERED"; count: number; }; interface TableSchemaOptions { /** MongoDB: 取樣文件數 */ sampleSize?: number; /** MongoDB: 取樣方式 */ sampleMethod?: "random" | "natural"; /** * 精確列數要掃全表。掃描整個資料庫時設為 false,改用引擎的估計值—— * 一百張表的資料庫做不起一百次全表 COUNT。預設 true。 */ exactRowCount?: boolean; } /** * Database adapter interface - contract for all database implementations * Defines methods that all database adapters must implement */ export interface DatabaseAdapter { /** * Establish connection and verify credentials * Throws ConnectionError with categorized error type on failure * @throws {ConnectionError} If connection fails (server down, auth failed, timeout, etc.) */ connect(): Promise; /** * Close connection and release resources * Should never throw; safe to call multiple times * Handles cleanup gracefully even if already disconnected */ disconnect(): Promise; /** * Execute arbitrary SQL query with parameterized values * Prevents SQL injection by using parameter binding * @param sql Query string with parameter placeholders ($1, $2, etc. for PostgreSQL or ? for MySQL) * @param params Array of parameter values in order * @returns Execution result containing rows and metadata * @throws {ConnectionError} If query execution fails */ execute(sql: string, params?: (string | number | boolean | null)[], options?: { noLimit?: boolean; }): Promise>; /** * List all tables in the connected database * Includes metadata such as row count and storage engine * @returns Array of table schemas with basic information * @throws {ConnectionError} If query fails */ listTables(): Promise; /** * Fetch complete schema for a single table * Includes all columns with types and constraints * @param tableName Name of table to inspect * @param options Optional adapter-specific knobs (e.g. mongo `sampleSize`); SQL adapters ignore them. * @returns Complete table schema including all column details * @throws {ConnectionError} If query fails */ getTableSchema(tableName: string, options?: TableSchemaOptions): Promise; /** * Test connection with lightweight probe query * Executes SELECT 1 or equivalent to verify connection is alive * @returns true if connection successful * @throws {ConnectionError} If connection test fails */ testConnection(): Promise; /** * Get the database server version string * @returns Raw version string from the server (e.g. "8.0.35", "15.4", "10.11.6-MariaDB") * @throws {ConnectionError} If not connected or query fails */ getServerVersion(): Promise; } interface QueryableAdapter { /** * Establish connection and verify credentials * Throws ConnectionError with categorized error type on failure * @throws {ConnectionError} If connection fails (server down, auth failed, timeout, etc.) */ connect(): Promise; /** * Close connection and release resources * Should never throw; safe to call multiple times * Handles cleanup gracefully even if already disconnected */ disconnect(): Promise; /** * Execute arbitrary query with parameterized values * Accepts JSON query strings for MongoDB operations * @param query Query string (JSON format for MongoDB) * @param params Array of parameter values in order * @param options Optional execution controls (e.g. result-cardinality limit) * @returns Execution result containing rows and metadata * @throws {ConnectionError} If query execution fails */ execute(query: string, params?: unknown[], options?: { limit?: number; noLimit?: boolean; projection?: Record; }): Promise>; /** * List all collections in the connected database * Includes metadata such as document count * @param options Optional filter for system indices * @returns Array of collection info with basic information * @throws {ConnectionError} If query fails */ listCollections(options?: { includeSystem?: boolean; /** Redis: 取樣上限。列 key 沒有 catalog 可查,只能掃,所以上限是必要的。 */ limit?: number; }): Promise<{ name: string; documentCount?: number; }[]>; /** * Redis-only: 取樣 key 名稱並回報是否觸及取樣上限。 * * 宣告在介面上而不是讓呼叫端 double-cast:`dbcli list` 與 shell 補全都需要 * `truncated` 才能誠實顯示「只看了前 N 個」,而那個資訊 listCollections * 的形狀裝不下。其他引擎有 catalog 可查,不需要取樣。 */ sampleKeyNames?(limit: number): Promise<{ names: string[]; truncated: boolean; }>; /** * SQL-compatible collection listing for shared command surfaces. * @param options Optional filter for system indices */ listTables?(options?: { includeSystem?: boolean; }): Promise; /** * SQL-compatible schema lookup for shared command surfaces. * @param tableName Name of collection/table to inspect * @param options Optional adapter-specific knobs (e.g. mongo `sampleSize`). */ getTableSchema?(tableName: string, options?: { sampleSize?: number; sampleMethod?: "random" | "natural"; }): Promise; /** * Test connection with lightweight probe query * Executes a ping or equivalent to verify connection is alive * @returns true if connection successful * @throws {ConnectionError} If connection test fails */ testConnection(): Promise; /** * Get the database server version string * @returns Raw version string from the server * @throws {ConnectionError} If not connected or query fails */ getServerVersion(): Promise; /** * Insert a single document/row * @param collection Collection or table name * @param data Data object to insert * @returns Execution result */ insert(collection: string, data: Record): Promise>; /** * Update documents/rows matching filter * @param collection Collection or table name * @param filter Filter object * @param update Update operations (e.g. {$set: ...}) * @returns Execution result */ update(collection: string, filter: Record, update: Record): Promise>; /** * Delete documents/rows matching filter * @param collection Collection or table name * @param filter Filter object * @returns Execution result */ delete(collection: string, filter: Record): Promise>; } interface BlacklistConfig { /** Table names to block all operations on */ tables: string[]; /** Column names to omit per table: { tableName: [col1, col2] } */ columns: Record; } interface RedisMaskRule { /** Redis-native glob (e.g. "user:*"). */ keyPattern: string; /** Hash field names to mask. Absent/empty → mask the whole value. */ fields?: string[]; } interface BlacklistState { /** Set of lowercase table names for O(1) case-insensitive lookup */ tables: Set; /** Map of table name -> Set of blacklisted column names */ columns: Map>; } /** * Error thrown when an operation is blocked by blacklist rules */ export declare class BlacklistError extends Error { readonly tableName: string; readonly operation: string; constructor(message: string, tableName: string, operation: string); } /** * Factory for creating database adapters * Implements factory pattern to route to correct adapter based on system type * Enables system-aware instantiation without coupling CLI commands to specific drivers */ export declare class AdapterFactory { static createSqlAdapter(rawOptions: SqlConnectionOptions): DatabaseAdapter; static createQueryableAdapter(rawOptions: QueryableConnectionOptions): QueryableAdapter; static createAdapter(options: SqlConnectionOptions): DatabaseAdapter; static createAdapter(options: QueryableConnectionOptions): QueryableAdapter; static createAdapter(options: ConnectionOptions): DatabaseAdapter | QueryableAdapter; static createMongoDBAdapter(options: ConnectionOptions): QueryableAdapter; static createRedisAdapter(rawOptions: ConnectionOptions, blacklistRules?: string[], maskRules?: RedisMaskRule[]): QueryableAdapter; static createElasticsearchAdapter(options: ConnectionOptions): QueryableAdapter; } /** * Type definitions for data modification operations * Defines results and options for data modification (INSERT, UPDATE, DELETE) operations */ /** * Result of a data execution operation * Used to wrap the execution result and metadata of data modification operations */ export interface DataExecutionResult { /** * What became of the operation. * * `success` means the statement ran — `rows_affected` may still be 0 if it * matched nothing. `cancelled` means a user declined at the confirmation. * `dry_run` means it was previewed and deliberately not run. The last two * were reported as `success` with `rows_affected: 0` until 2.0.0, which made * them indistinguishable from a write that matched no rows and caused the * audit log to record declined operations as writes that happened. */ status: "success" | "error" | "cancelled" | "dry_run"; /** Type of operation executed */ operation: "insert" | "update" | "delete"; /** Number of rows affected */ rows_affected: number; /** Execution timestamp in ISO 8601 format */ timestamp?: string; /** Generated SQL statement (for confirmation and error messages) */ sql?: string; /** Error message (only when status is 'error') */ error?: string; } /** * Data execution options * Controls how data modification operations are executed */ export interface DataExecutionOptions { /** Dry run mode: display SQL without executing */ dryRun?: boolean; /** Skip confirmation prompt */ force?: boolean; /** Verbose output */ verbose?: boolean; /** * How to ask the caller's user whether to proceed. * * Core states what is about to happen; the caller decides how to present it * and how to collect an answer. Required whenever a mutation would execute * without `force`, and absent by design rather than defaulted: silently * proceeding unconfirmed, or silently declining, are both worse than saying * that nobody was available to ask. */ confirm?: MutationConfirmer; } /** * Everything a caller needs to describe a pending mutation to its user. */ export interface MutationConfirmationRequest { operation: DataExecutionResult["operation"]; /** * Which engine will run it. * * Only presentation depends on this: a MongoDB shell line or a Redis command * announced as "Generated SQL" would be a lie about what is being approved, * and approving the wrong thing is the failure this whole prompt exists to * prevent. */ engine: "sql" | "mongodb" | "redis"; /** The parameterised statement that will run if confirmed */ sql: string; /** Values bound to the statement's placeholders */ params: (string | number | boolean | null)[]; /** * Whether this operation is irreversible. * * A flag rather than the warning sentence and the question themselves, which * is what this carried first. The division is not "core cannot translate" — * `permission-guard` translates the refusal it throws, and so does * `blacklist-validator` — it is that core owns facts and the command layer * owns presentation. Whether a delete can be undone is a fact. Which sentence * a person is shown about it, in what tone, on which stream, is presentation, * and a caller embedding the executor should be able to say it in its own * product's voice rather than inheriting dbcli's. */ destructive: boolean; } /** * Returns true to proceed, false to abandon the mutation. */ export type MutationConfirmer = (request: MutationConfirmationRequest) => Promise; interface SqlConnectionConfig { system: "postgresql" | "mysql" | "mariadb"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; password: string | { $env: string; }; database: string | { $env: string; }; } interface MongoDBConnectionConfig { system: "mongodb"; uri?: string | { $env: string; }; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; password: string | { $env: string; }; database: string | { $env: string; }; /** Auth database; defaults to 'admin' when credentials are present */ authSource?: string | { $env: string; }; replicaSet?: string | { $env: string; }; tls?: boolean; /** Build a mongodb+srv:// URI from host and expand it via DNS SRV lookup */ srv?: boolean; } interface RedisConnectionConfig { system: "redis"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; password: string | { $env: string; }; /** Redis logical DB index, kept as string for env-binding parity */ database: string | { $env: string; }; } interface ElasticsearchConnectionConfig { system: "elasticsearch"; protocol?: "http" | "https"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; password: string | { $env: string; }; database: string | { $env: string; }; nodes?: string[]; cloudId?: string | { $env: string; }; apiKey?: string | { $env: string; }; caPath?: string; rejectUnauthorized?: boolean; } type ConnectionConfig = SqlConnectionConfig | MongoDBConnectionConfig | RedisConnectionConfig | ElasticsearchConnectionConfig; /** * Permission level (coarse-grained access control) */ export type Permission = "query-only" | "read-write" | "data-admin" | "admin"; interface Metadata { createdAt?: string; version: string; } interface DbcliConfig { connection: ConnectionConfig; permission: Permission; schema?: Record; metadata?: Metadata; blacklist?: BlacklistConfig; } interface AppliedLimitMetadata { /** True only when the caller fetched and removed an additional row. */ truncated: boolean; /** User-facing row limit, never the internal lookahead size. */ limitApplied: number; } type SqlStatementType = "SELECT" | "INSERT" | "UPDATE" | "DELETE" | "UNKNOWN"; interface PerformanceAdvisory { code: "SLOW_QUERY"; executionTimeMs: number; thresholdMs: number; recommendation: string; } interface QueryMetadata { /** SQL statement type (SELECT, INSERT, UPDATE, DELETE) */ statement: SqlStatementType; /** Number of rows affected by INSERT/UPDATE/DELETE operations */ affectedRows?: number; /** Query execution time in milliseconds */ executionTimeMs?: number; /** Security notification when columns were omitted due to blacklist */ securityNotification?: string; /** Passive suggestion derived from already-measured execution time. */ performanceAdvisory?: PerformanceAdvisory; } /** * Generic query result wrapper with rows and metadata * Used to wrap database query results with structured metadata for AI parsing * @template T - Type of individual row objects * * Example: SELECT query result * ```typescript * const result: QueryResult<{id: number; name: string}> = { * rows: [{id: 1, name: 'Alice'}], * rowCount: 1, * columnNames: ['id', 'name'], * columnTypes: ['integer', 'varchar'], * executionTimeMs: 42, * metadata: { statement: 'SELECT' } * } * ``` */ export interface QueryResult { /** Array of result rows */ rows: T[]; /** Total number of rows in result set */ rowCount: number; /** Column names in order (matches Object.keys(rows[0]) for consistent ordering) */ columnNames: string[]; /** Optional: column data types (PostgreSQL: "integer", "varchar"; MySQL: "INT", "VARCHAR") */ columnTypes?: string[]; /** Optional: query execution time in milliseconds (only database execution, not formatting) */ executionTimeMs?: number; /** Optional: metadata about query type and affected rows */ metadata?: QueryMetadata; /** Internal row-limit proof, mapped into public JSON metadata by the formatter. */ appliedLimit?: AppliedLimitMetadata; } declare const SQL_DIALECTS: readonly [ "postgresql", "mysql", "mariadb" ]; type SqlDialect = (typeof SQL_DIALECTS)[number]; /** * Manager class for loading and querying blacklist rules. * Instantiate once per CLI invocation. */ export declare class BlacklistManager { private config; private state; private overrideEnabled; constructor(config: DbcliConfig, overrideEnvValue?: string); /** * Deserialize config.blacklist JSON into efficient Set/Map structures. * Case-insensitive table names (stored as lowercase). * Case-sensitive column names. * * @returns BlacklistState with Set for tables, Map> for columns */ loadBlacklist(): BlacklistState; /** * Check if a table is blacklisted. * Case-insensitive comparison. * * @param tableName Table name to check * @returns true if the table is blacklisted */ isTableBlacklisted(tableName: string): boolean; /** * Check if a specific column in a table is blacklisted. * Table name is case-insensitive; column name is case-sensitive. * * @param tableName Table name * @param columnName Column name * @returns true if the column is blacklisted */ isColumnBlacklisted(tableName: string, columnName: string): boolean; /** * Get all blacklisted column names for a specific table. * * @param tableName Table name * @returns Array of blacklisted column names, or empty array if none */ getBlacklistedColumns(tableName: string): string[]; /** * Every blacklisted column name, across all tables. * * Used when a statement's tables could not be identified: applying every * rule is the reading of "I do not know which table this came from" that * does not disclose data. * * @returns Array of blacklisted column names, deduplicated */ getAllBlacklistedColumns(): string[]; /** * Check if the blacklist override is enabled via environment variable. * When true, all blacklist checks are bypassed. * * @returns true if DBCLI_OVERRIDE_BLACKLIST=true */ canOverrideBlacklist(): boolean; /** * Get current blacklist state (for diagnostic purposes). */ getState(): BlacklistState; } interface FilterColumnsResult { filteredRows: Record[]; omittedColumns: string[]; } /** * Validator class for enforcing blacklist rules. * Instantiate once per CLI invocation with a BlacklistManager. */ export declare class BlacklistValidator { private manager; constructor(manager: BlacklistManager); /** * Check if an operation on a table is allowed. * Throws BlacklistError if the table is blacklisted and override is not active. * * @param operation SQL operation type: SELECT, INSERT, UPDATE, DELETE * @param tableName Table name to check * @param tableList Further tables the same statement references * @throws BlacklistError if any table is blacklisted */ checkTableBlacklist(operation: string, tableName: string, tableList?: string[]): void; /** * Check every table a statement references. * * A statement is blocked when *any* referenced table is blacklisted — the * table reached through a JOIN, a comma, or a UNION branch is as sensitive as * the one named first (issue #23). * * @param operation SQL operation type: SELECT, INSERT, UPDATE, DELETE * @param tableNames Every table the statement references * @throws BlacklistError if any table is blacklisted */ checkTablesBlacklist(operation: string, tableNames: string[]): void; /** * Check an Elasticsearch index expression against the table blacklist. * * `--index` is not a name: Elasticsearch accepts a comma list and wildcards, * so `secrets,orders`, `sec*`, `*` and `_all` all read a blacklisted index * while matching no blacklist entry by equality. Concrete names are checked * directly; a wildcard is refused when it *could* match a blacklisted index, * since which indices exist is server-side knowledge. * * @param operation Operation label for the error message * @param target Raw `--index` expression * @throws BlacklistError if any named or matchable index is blacklisted */ checkIndexBlacklist(operation: string, target: string): void; /** * Mask result fields for an Elasticsearch index *expression*. * * `filterColumns` looks the name up by equality, so `--index 'us*'` or * `--index 'users,orders'` matched no rule and returned every protected field * — the table check passing is not enough when only columns are blacklisted. * A wildcard is resolved server-side, so every rule it could reach is * applied. * * @param target Raw `--index` expression * @param rows Result documents * @param columnList Field names in the result */ filterColumnsForIndexExpression(target: string, rows: Record[], columnList: string[]): FilterColumnsResult; /** * Reject a write that touches blacklisted columns. * Computes the intersection of `fields` with the table's column blacklist * and throws BlacklistError when non-empty. When override is enabled, * emits a console warning and returns without throwing. * * @param tableName Table or collection name * @param fields Top-level field/column names being written * @param operation SQL operation type (defaults to 'WRITE') * @throws BlacklistError when any field is blacklisted and override is off */ checkColumnBlacklistOnWrite(tableName: string, fields: string[], operation?: string): void; /** * Filter blacklisted columns from query result rows. * Returns new row objects without blacklisted columns (immutable). * * @param tableName Table name to look up column blacklist * @param rows Query result rows * @param columnList Column names in result set * @returns Filtered rows and list of omitted column names */ filterColumns(tableName: string, rows: Record[], columnList: string[]): FilterColumnsResult; /** * Filter blacklisted columns using the rules of every referenced table. * * A result set built from a JOIN carries columns from several tables, and the * driver returns them unqualified — `u.password_hash` arrives as * `password_hash`. Attribution is therefore not recoverable from the result, * so a column blacklisted on *any* referenced table is omitted. That errs * towards hiding a same-named column of an innocent table, which is the * direction that does not disclose data. * * @param tableNames Every table the statement references * @param rows Query result rows * @param columnList Column names in result set * @returns Filtered rows and list of omitted column names */ filterColumnsForTables(tableNames: string[], rows: Record[], columnList: string[]): FilterColumnsResult; /** * Build a security notification message for omitted columns. * * @param _tableName Table name (reserved for future per-table messages) * @param omittedColumns List of column names that were omitted * @returns Security notification string, or empty string if no columns omitted */ buildSecurityNotification(_tableName: string, omittedColumns: string[]): string; } declare const DbcliConfigSchema: z.ZodObject<{ connection: z.ZodUnion<[ z.ZodObject<{ timeout: z.ZodOptional; statementTimeout: z.ZodOptional; system: z.ZodEnum<[ "postgresql", "mysql", "mariadb" ]>; host: z.ZodUnion<[ z.ZodString, z.ZodObject<{ $env: z.ZodString; }, "strict", z.ZodTypeAny, { $env: string; }, { $env: string; }> ]>; port: z.ZodUnion<[ z.ZodNumber, z.ZodObject<{ $env: z.ZodString; }, "strict", z.ZodTypeAny, { $env: string; }, { $env: string; }> ]>; user: z.ZodUnion<[ z.ZodString, z.ZodObject<{ $env: z.ZodString; }, "strict", z.ZodTypeAny, { $env: string; }, { $env: string; }> ]>; password: z.ZodDefault ]>>; database: z.ZodUnion<[ z.ZodString, z.ZodObject<{ $env: z.ZodString; }, "strict", z.ZodTypeAny, { $env: string; }, { $env: string; }> ]>; }, "strip", z.ZodTypeAny, { password: string | { $env: string; }; system: "postgresql" | "mysql" | "mariadb"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; database: string | { $env: string; }; timeout?: number | undefined; statementTimeout?: number | undefined; }, { system: "postgresql" | "mysql" | "mariadb"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; database: string | { $env: string; }; password?: string | { $env: string; } | undefined; timeout?: number | undefined; statementTimeout?: number | undefined; }>, z.ZodObject<{ timeout: z.ZodOptional; statementTimeout: z.ZodOptional; system: z.ZodLiteral<"mongodb">; uri: z.ZodOptional ]>>; host: z.ZodDefault ]>>>; port: z.ZodDefault ]>>>; user: z.ZodDefault ]>>>; password: z.ZodDefault ]>>>; database: z.ZodDefault ]>>>; authSource: z.ZodOptional ]>>; replicaSet: z.ZodOptional ]>>; tls: z.ZodOptional; srv: z.ZodDefault>; }, "strip", z.ZodTypeAny, { password: string | { $env: string; }; system: "mongodb"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; database: string | { $env: string; }; srv: boolean; uri?: string | { $env: string; } | undefined; authSource?: string | { $env: string; } | undefined; replicaSet?: string | { $env: string; } | undefined; tls?: boolean | undefined; timeout?: number | undefined; statementTimeout?: number | undefined; }, { system: "mongodb"; password?: string | { $env: string; } | undefined; host?: string | { $env: string; } | undefined; port?: number | { $env: string; } | undefined; user?: string | { $env: string; } | undefined; database?: string | { $env: string; } | undefined; uri?: string | { $env: string; } | undefined; authSource?: string | { $env: string; } | undefined; replicaSet?: string | { $env: string; } | undefined; tls?: boolean | undefined; srv?: boolean | undefined; timeout?: number | undefined; statementTimeout?: number | undefined; }>, z.ZodObject<{ timeout: z.ZodOptional; statementTimeout: z.ZodOptional; system: z.ZodLiteral<"redis">; host: z.ZodUnion<[ z.ZodString, z.ZodObject<{ $env: z.ZodString; }, "strict", z.ZodTypeAny, { $env: string; }, { $env: string; }> ]>; port: z.ZodUnion<[ z.ZodNumber, z.ZodObject<{ $env: z.ZodString; }, "strict", z.ZodTypeAny, { $env: string; }, { $env: string; }> ]>; user: z.ZodDefault ]>>>; password: z.ZodDefault ]>>>; database: z.ZodDefault ]>>>; }, "strip", z.ZodTypeAny, { password: string | { $env: string; }; system: "redis"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; database: string | { $env: string; }; timeout?: number | undefined; statementTimeout?: number | undefined; }, { system: "redis"; host: string | { $env: string; }; port: number | { $env: string; }; password?: string | { $env: string; } | undefined; user?: string | { $env: string; } | undefined; database?: string | { $env: string; } | undefined; timeout?: number | undefined; statementTimeout?: number | undefined; }>, z.ZodObject<{ timeout: z.ZodOptional; statementTimeout: z.ZodOptional; system: z.ZodLiteral<"elasticsearch">; protocol: z.ZodDefault>>; host: z.ZodDefault ]>>>; port: z.ZodDefault ]>>>; user: z.ZodDefault ]>>>; password: z.ZodDefault ]>>>; database: z.ZodDefault ]>>>; nodes: z.ZodOptional>; cloudId: z.ZodOptional ]>>; apiKey: z.ZodOptional ]>>; caPath: z.ZodOptional; rejectUnauthorized: z.ZodDefault>; }, "strip", z.ZodTypeAny, { password: string | { $env: string; }; system: "elasticsearch"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; database: string | { $env: string; }; rejectUnauthorized: boolean; protocol: "http" | "https"; timeout?: number | undefined; statementTimeout?: number | undefined; nodes?: string[] | undefined; cloudId?: string | { $env: string; } | undefined; apiKey?: string | { $env: string; } | undefined; caPath?: string | undefined; }, { system: "elasticsearch"; password?: string | { $env: string; } | undefined; host?: string | { $env: string; } | undefined; port?: number | { $env: string; } | undefined; user?: string | { $env: string; } | undefined; database?: string | { $env: string; } | undefined; rejectUnauthorized?: boolean | undefined; timeout?: number | undefined; statementTimeout?: number | undefined; protocol?: "http" | "https" | undefined; nodes?: string[] | undefined; cloudId?: string | { $env: string; } | undefined; apiKey?: string | { $env: string; } | undefined; caPath?: string | undefined; }> ]>; permission: z.ZodDefault>; schema: z.ZodDefault>>; metadata: z.ZodDefault; version: z.ZodDefault; schemaLastUpdated: z.ZodOptional; schemaTableCount: z.ZodOptional; }, "strip", z.ZodTypeAny, { version: string; createdAt?: string | undefined; schemaLastUpdated?: string | undefined; schemaTableCount?: number | undefined; }, { version?: string | undefined; createdAt?: string | undefined; schemaLastUpdated?: string | undefined; schemaTableCount?: number | undefined; }>>>; blacklist: z.ZodDefault>; columns: z.ZodDefault>>; }, "strip", z.ZodTypeAny, { columns: Record; tables: string[]; }, { columns?: Record | undefined; tables?: string[] | undefined; }>>>; audit: z.ZodDefault; rotation: z.ZodDefault; max_entries: z.ZodDefault; }, "strip", z.ZodTypeAny, { max_bytes: number; max_entries: number; }, { max_bytes?: number | undefined; max_entries?: number | undefined; }>>>; }, "strip", z.ZodTypeAny, { enabled: boolean; rotation: { max_bytes: number; max_entries: number; }; }, { enabled?: boolean | undefined; rotation?: { max_bytes?: number | undefined; max_entries?: number | undefined; } | undefined; }>>>; redis: z.ZodOptional>; }, "strip", z.ZodTypeAny, { keyPattern: string; fields?: string[] | undefined; }, { keyPattern: string; fields?: string[] | undefined; }>, "many">>; }, "strip", z.ZodTypeAny, { mask: { keyPattern: string; fields?: string[] | undefined; }[]; }, { mask?: { keyPattern: string; fields?: string[] | undefined; }[] | undefined; }>>; }, "strip", z.ZodTypeAny, { schema: Record; blacklist: { columns: Record; tables: string[]; }; audit: { enabled: boolean; rotation: { max_bytes: number; max_entries: number; }; }; permission: "admin" | "query-only" | "read-write" | "data-admin"; connection: { password: string | { $env: string; }; system: "mongodb"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; database: string | { $env: string; }; srv: boolean; uri?: string | { $env: string; } | undefined; authSource?: string | { $env: string; } | undefined; replicaSet?: string | { $env: string; } | undefined; tls?: boolean | undefined; timeout?: number | undefined; statementTimeout?: number | undefined; } | { password: string | { $env: string; }; system: "postgresql" | "mysql" | "mariadb"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; database: string | { $env: string; }; timeout?: number | undefined; statementTimeout?: number | undefined; } | { password: string | { $env: string; }; system: "redis"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; database: string | { $env: string; }; timeout?: number | undefined; statementTimeout?: number | undefined; } | { password: string | { $env: string; }; system: "elasticsearch"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; database: string | { $env: string; }; rejectUnauthorized: boolean; protocol: "http" | "https"; timeout?: number | undefined; statementTimeout?: number | undefined; nodes?: string[] | undefined; cloudId?: string | { $env: string; } | undefined; apiKey?: string | { $env: string; } | undefined; caPath?: string | undefined; }; metadata: { version: string; createdAt?: string | undefined; schemaLastUpdated?: string | undefined; schemaTableCount?: number | undefined; }; redis?: { mask: { keyPattern: string; fields?: string[] | undefined; }[]; } | undefined; }, { connection: { system: "mongodb"; password?: string | { $env: string; } | undefined; host?: string | { $env: string; } | undefined; port?: number | { $env: string; } | undefined; user?: string | { $env: string; } | undefined; database?: string | { $env: string; } | undefined; uri?: string | { $env: string; } | undefined; authSource?: string | { $env: string; } | undefined; replicaSet?: string | { $env: string; } | undefined; tls?: boolean | undefined; srv?: boolean | undefined; timeout?: number | undefined; statementTimeout?: number | undefined; } | { system: "postgresql" | "mysql" | "mariadb"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; database: string | { $env: string; }; password?: string | { $env: string; } | undefined; timeout?: number | undefined; statementTimeout?: number | undefined; } | { system: "redis"; host: string | { $env: string; }; port: number | { $env: string; }; password?: string | { $env: string; } | undefined; user?: string | { $env: string; } | undefined; database?: string | { $env: string; } | undefined; timeout?: number | undefined; statementTimeout?: number | undefined; } | { system: "elasticsearch"; password?: string | { $env: string; } | undefined; host?: string | { $env: string; } | undefined; port?: number | { $env: string; } | undefined; user?: string | { $env: string; } | undefined; database?: string | { $env: string; } | undefined; rejectUnauthorized?: boolean | undefined; timeout?: number | undefined; statementTimeout?: number | undefined; protocol?: "http" | "https" | undefined; nodes?: string[] | undefined; cloudId?: string | { $env: string; } | undefined; apiKey?: string | { $env: string; } | undefined; caPath?: string | undefined; }; redis?: { mask?: { keyPattern: string; fields?: string[] | undefined; }[] | undefined; } | undefined; schema?: Record | undefined; blacklist?: { columns?: Record | undefined; tables?: string[] | undefined; } | undefined; audit?: { enabled?: boolean | undefined; rotation?: { max_bytes?: number | undefined; max_entries?: number | undefined; } | undefined; } | undefined; permission?: "admin" | "query-only" | "read-write" | "data-admin" | undefined; metadata?: { version?: string | undefined; createdAt?: string | undefined; schemaLastUpdated?: string | undefined; schemaTableCount?: number | undefined; } | undefined; }>; /** * Types inferred from Zod schemas */ type DbcliConfig$1 = z.infer; declare const DbcliConfigV2Schema: z.ZodEffects; default: z.ZodString; connections: z.ZodEffects; statementTimeout: z.ZodOptional; system: z.ZodEnum<[ "postgresql", "mysql", "mariadb" ]>; host: z.ZodUnion<[ z.ZodString, z.ZodObject<{ $env: z.ZodString; }, "strict", z.ZodTypeAny, { $env: string; }, { $env: string; }> ]>; port: z.ZodUnion<[ z.ZodNumber, z.ZodObject<{ $env: z.ZodString; }, "strict", z.ZodTypeAny, { $env: string; }, { $env: string; }> ]>; user: z.ZodUnion<[ z.ZodString, z.ZodObject<{ $env: z.ZodString; }, "strict", z.ZodTypeAny, { $env: string; }, { $env: string; }> ]>; password: z.ZodDefault ]>>; database: z.ZodUnion<[ z.ZodString, z.ZodObject<{ $env: z.ZodString; }, "strict", z.ZodTypeAny, { $env: string; }, { $env: string; }> ]>; } & { permission: z.ZodDefault>; envFile: z.ZodOptional; environment: z.ZodOptional>; }, "strip", z.ZodTypeAny, { password: string | { $env: string; }; system: "postgresql" | "mysql" | "mariadb"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; database: string | { $env: string; }; permission: "admin" | "query-only" | "read-write" | "data-admin"; timeout?: number | undefined; statementTimeout?: number | undefined; envFile?: string | undefined; environment?: string | undefined; }, { system: "postgresql" | "mysql" | "mariadb"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; database: string | { $env: string; }; password?: string | { $env: string; } | undefined; timeout?: number | undefined; permission?: "admin" | "query-only" | "read-write" | "data-admin" | undefined; statementTimeout?: number | undefined; envFile?: string | undefined; environment?: string | undefined; }>, z.ZodObject<{ timeout: z.ZodOptional; statementTimeout: z.ZodOptional; system: z.ZodLiteral<"mongodb">; uri: z.ZodOptional ]>>; host: z.ZodDefault ]>>>; port: z.ZodDefault ]>>>; user: z.ZodDefault ]>>>; password: z.ZodDefault ]>>>; database: z.ZodDefault ]>>>; authSource: z.ZodOptional ]>>; replicaSet: z.ZodOptional ]>>; tls: z.ZodOptional; srv: z.ZodDefault>; } & { permission: z.ZodDefault>; envFile: z.ZodOptional; environment: z.ZodOptional>; }, "strip", z.ZodTypeAny, { password: string | { $env: string; }; system: "mongodb"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; database: string | { $env: string; }; srv: boolean; permission: "admin" | "query-only" | "read-write" | "data-admin"; uri?: string | { $env: string; } | undefined; authSource?: string | { $env: string; } | undefined; replicaSet?: string | { $env: string; } | undefined; tls?: boolean | undefined; timeout?: number | undefined; statementTimeout?: number | undefined; envFile?: string | undefined; environment?: string | undefined; }, { system: "mongodb"; password?: string | { $env: string; } | undefined; host?: string | { $env: string; } | undefined; port?: number | { $env: string; } | undefined; user?: string | { $env: string; } | undefined; database?: string | { $env: string; } | undefined; uri?: string | { $env: string; } | undefined; authSource?: string | { $env: string; } | undefined; replicaSet?: string | { $env: string; } | undefined; tls?: boolean | undefined; srv?: boolean | undefined; timeout?: number | undefined; permission?: "admin" | "query-only" | "read-write" | "data-admin" | undefined; statementTimeout?: number | undefined; envFile?: string | undefined; environment?: string | undefined; }>, z.ZodObject<{ timeout: z.ZodOptional; statementTimeout: z.ZodOptional; system: z.ZodLiteral<"redis">; host: z.ZodUnion<[ z.ZodString, z.ZodObject<{ $env: z.ZodString; }, "strict", z.ZodTypeAny, { $env: string; }, { $env: string; }> ]>; port: z.ZodUnion<[ z.ZodNumber, z.ZodObject<{ $env: z.ZodString; }, "strict", z.ZodTypeAny, { $env: string; }, { $env: string; }> ]>; user: z.ZodDefault ]>>>; password: z.ZodDefault ]>>>; database: z.ZodDefault ]>>>; } & { permission: z.ZodDefault>; envFile: z.ZodOptional; environment: z.ZodOptional>; }, "strip", z.ZodTypeAny, { password: string | { $env: string; }; system: "redis"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; database: string | { $env: string; }; permission: "admin" | "query-only" | "read-write" | "data-admin"; timeout?: number | undefined; statementTimeout?: number | undefined; envFile?: string | undefined; environment?: string | undefined; }, { system: "redis"; host: string | { $env: string; }; port: number | { $env: string; }; password?: string | { $env: string; } | undefined; user?: string | { $env: string; } | undefined; database?: string | { $env: string; } | undefined; timeout?: number | undefined; permission?: "admin" | "query-only" | "read-write" | "data-admin" | undefined; statementTimeout?: number | undefined; envFile?: string | undefined; environment?: string | undefined; }>, z.ZodObject<{ timeout: z.ZodOptional; statementTimeout: z.ZodOptional; system: z.ZodLiteral<"elasticsearch">; protocol: z.ZodDefault>>; host: z.ZodDefault ]>>>; port: z.ZodDefault ]>>>; user: z.ZodDefault ]>>>; password: z.ZodDefault ]>>>; database: z.ZodDefault ]>>>; nodes: z.ZodOptional>; cloudId: z.ZodOptional ]>>; apiKey: z.ZodOptional ]>>; caPath: z.ZodOptional; rejectUnauthorized: z.ZodDefault>; } & { permission: z.ZodDefault>; envFile: z.ZodOptional; environment: z.ZodOptional>; }, "strip", z.ZodTypeAny, { password: string | { $env: string; }; system: "elasticsearch"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; database: string | { $env: string; }; rejectUnauthorized: boolean; permission: "admin" | "query-only" | "read-write" | "data-admin"; protocol: "http" | "https"; timeout?: number | undefined; statementTimeout?: number | undefined; nodes?: string[] | undefined; cloudId?: string | { $env: string; } | undefined; apiKey?: string | { $env: string; } | undefined; caPath?: string | undefined; envFile?: string | undefined; environment?: string | undefined; }, { system: "elasticsearch"; password?: string | { $env: string; } | undefined; host?: string | { $env: string; } | undefined; port?: number | { $env: string; } | undefined; user?: string | { $env: string; } | undefined; database?: string | { $env: string; } | undefined; rejectUnauthorized?: boolean | undefined; timeout?: number | undefined; permission?: "admin" | "query-only" | "read-write" | "data-admin" | undefined; statementTimeout?: number | undefined; protocol?: "http" | "https" | undefined; nodes?: string[] | undefined; cloudId?: string | { $env: string; } | undefined; apiKey?: string | { $env: string; } | undefined; caPath?: string | undefined; envFile?: string | undefined; environment?: string | undefined; }> ]>>, Record, Record>; schema: z.ZodDefault>>; schemas: z.ZodDefault>>>; metadata: z.ZodDefault; version: z.ZodDefault; schemaLastUpdated: z.ZodOptional; schemaTableCount: z.ZodOptional; }, "strip", z.ZodTypeAny, { version: string; createdAt?: string | undefined; schemaLastUpdated?: string | undefined; schemaTableCount?: number | undefined; }, { version?: string | undefined; createdAt?: string | undefined; schemaLastUpdated?: string | undefined; schemaTableCount?: number | undefined; }>>>; blacklist: z.ZodDefault>; columns: z.ZodDefault>>; }, "strip", z.ZodTypeAny, { columns: Record; tables: string[]; }, { columns?: Record | undefined; tables?: string[] | undefined; }>>>; audit: z.ZodDefault; rotation: z.ZodDefault; max_entries: z.ZodDefault; }, "strip", z.ZodTypeAny, { max_bytes: number; max_entries: number; }, { max_bytes?: number | undefined; max_entries?: number | undefined; }>>>; }, "strip", z.ZodTypeAny, { enabled: boolean; rotation: { max_bytes: number; max_entries: number; }; }, { enabled?: boolean | undefined; rotation?: { max_bytes?: number | undefined; max_entries?: number | undefined; } | undefined; }>>>; redis: z.ZodOptional>; }, "strip", z.ZodTypeAny, { keyPattern: string; fields?: string[] | undefined; }, { keyPattern: string; fields?: string[] | undefined; }>, "many">>; }, "strip", z.ZodTypeAny, { mask: { keyPattern: string; fields?: string[] | undefined; }[]; }, { mask?: { keyPattern: string; fields?: string[] | undefined; }[] | undefined; }>>; }, "strip", z.ZodTypeAny, { schema: Record; blacklist: { columns: Record; tables: string[]; }; audit: { enabled: boolean; rotation: { max_bytes: number; max_entries: number; }; }; version: 2; default: string; metadata: { version: string; createdAt?: string | undefined; schemaLastUpdated?: string | undefined; schemaTableCount?: number | undefined; }; connections: Record; schemas: Record>; redis?: { mask: { keyPattern: string; fields?: string[] | undefined; }[]; } | undefined; }, { version: 2; default: string; connections: Record; redis?: { mask?: { keyPattern: string; fields?: string[] | undefined; }[] | undefined; } | undefined; schema?: Record | undefined; blacklist?: { columns?: Record | undefined; tables?: string[] | undefined; } | undefined; audit?: { enabled?: boolean | undefined; rotation?: { max_bytes?: number | undefined; max_entries?: number | undefined; } | undefined; } | undefined; metadata?: { version?: string | undefined; createdAt?: string | undefined; schemaLastUpdated?: string | undefined; schemaTableCount?: number | undefined; } | undefined; schemas?: Record> | undefined; }>, { schema: Record; blacklist: { columns: Record; tables: string[]; }; audit: { enabled: boolean; rotation: { max_bytes: number; max_entries: number; }; }; version: 2; default: string; metadata: { version: string; createdAt?: string | undefined; schemaLastUpdated?: string | undefined; schemaTableCount?: number | undefined; }; connections: Record; schemas: Record>; redis?: { mask: { keyPattern: string; fields?: string[] | undefined; }[]; } | undefined; }, { version: 2; default: string; connections: Record; redis?: { mask?: { keyPattern: string; fields?: string[] | undefined; }[] | undefined; } | undefined; schema?: Record | undefined; blacklist?: { columns?: Record | undefined; tables?: string[] | undefined; } | undefined; audit?: { enabled?: boolean | undefined; rotation?: { max_bytes?: number | undefined; max_entries?: number | undefined; } | undefined; } | undefined; metadata?: { version?: string | undefined; createdAt?: string | undefined; schemaLastUpdated?: string | undefined; schemaTableCount?: number | undefined; } | undefined; schemas?: Record> | undefined; }>; export type DbcliConfigV2 = z.infer; type FieldSelection = { mode: "include"; paths: readonly string[]; } | { mode: "exclude"; paths: readonly string[]; }; /** * QueryExecutor class for executing SQL queries with permission checks */ export declare class QueryExecutor { private adapter; private permission; private blacklistValidator?; private config?; private options; private pendingDiagnostics; constructor(adapter: DatabaseAdapter, permission: Permission, blacklistValidator?: BlacklistValidator | undefined, config?: DbcliConfig$1 | undefined, options?: { config?: string; connectionName?: string; recovery?: boolean; deferDiagnostics?: boolean; /** * Quoting rules that decide what counts as a statement separator differ * per dialect. Without this, the stacking check has to fail closed. */ dialect?: SqlDialect; }); /** * The dialect the statement will actually run under. Falls back to the * connection config, then to undefined — where the stacking check fails * closed rather than guessing. */ private resolveDialect; takeDiagnostics(): string[]; /** * Execute a SQL query with permission enforcement and error handling * * @param sql The SQL query string * @param options Execution options (autoLimit, limitValue) * @returns QueryResult with rows and metadata * @throws PermissionError if query violates permission level * @throws BlacklistError if table is blacklisted * @throws Error for database execution errors */ execute(sql: string, options?: { autoLimit?: boolean; limitValue?: number; detectTruncation?: boolean; fieldSelection?: FieldSelection; }): Promise>>; } /** * DataExecutor class for executing INSERT, UPDATE, DELETE operations */ export declare class DataExecutor { private adapter; private permission; private dbSystem; private blacklistValidator?; constructor(adapter: DatabaseAdapter, permission: Permission, dbSystem?: "postgresql" | "mysql", blacklistValidator?: BlacklistValidator | undefined); /** * Build a parameterized INSERT SQL statement * Returns {sql, params} form to prevent SQL injection * * @param tableName Table name * @param data Data object to insert {column: value, ...} * @param schema Table schema * @returns Parameterized SQL and parameters array * @throws Error if a data column is not found in the table schema */ buildInsertSql(tableName: string, data: Record, schema: TableSchema): { sql: string; params: (string | number | boolean | null)[]; }; /** * Execute an INSERT operation * Enforces permission check, builds SQL, shows confirmation prompt, executes * * @param tableName Table name * @param data Data object to insert * @param schema Table schema * @param options Execution options (dryRun, force, verbose) * @returns DataExecutionResult * @throws PermissionError if insufficient permissions * @throws Error if execution fails */ executeInsert(tableName: string, data: Record, schema: TableSchema, options?: DataExecutionOptions): Promise; /** * Execute an UPDATE operation * Enforces permission check, builds SQL, shows confirmation prompt, executes * * @param tableName Table name * @param data Updated data object * @param where WHERE clause condition object * @param schema Table schema * @param options Execution options * @returns DataExecutionResult */ executeUpdate(tableName: string, data: Record, where: Record, schema: TableSchema, options?: DataExecutionOptions): Promise; /** * Execute a DELETE operation * Admin-only operation, requires strict permission check * * @param tableName Table name * @param where WHERE clause condition object * @param schema Table schema * @param options Execution options * @returns DataExecutionResult */ executeDelete(tableName: string, where: Record, schema: TableSchema, options?: DataExecutionOptions): Promise; /** * Get database system type (used to determine parameter placeholder and identifier quoting) */ private getSystemType; /** * Get identifier quote character (for table names and column names) */ private getQuoteChar; private checkBlacklist; private executeMutation; private outcomeResult; private handleMutationError; /** * Build a parameterized UPDATE SQL statement */ private buildUpdateSql; /** * Build a parameterized DELETE SQL statement */ private buildDeleteSql; } interface SchemaIndex { tables: Record; hotTables: string[]; metadata: { version: string; lastRefreshed: string; totalTables: number; }; } interface CacheStats { hotTables: number; cachedTables: number; cacheSize: number; cacheHitRate: string; maxItems: number; maxSize: number; } interface LoaderOptions { maxCacheItems?: number; maxCacheSize?: number; hotTableThreshold?: number; enableStreaming?: boolean; streamingTimeout?: number; /** V2 named connection — layered files under `.dbcli/schemas//` */ connectionName?: string; } declare class SchemaCacheManager { private cache; private index; private hotSchemas; private dbcliPath; /** Root for index.json, hot-schemas.json, cold/ (V2: per-connection subfolder) */ private schemaRoot; private maxItems; private maxSize; /** * Constructor * @param dbcliPath Path to .dbcli directory * @param options Cache configuration (optional `connectionName` for V2 isolation) */ constructor(dbcliPath: string, options?: { maxCacheItems?: number; maxCacheSize?: number; connectionName?: string; }); /** * Initialize: Load index and hot schemas * * Performance: < 10ms for typical cases (hot-schemas < 1MB) * Graceful degradation: If files missing, continues with empty cache */ initialize(): Promise; /** * Get table schema - Three-tier lookup strategy * * 1. Hot schemas (< 1ms) - in-memory map lookup * 2. LRU cache (< 5ms) - in-memory cache hit * 3. Cold load (10-50ms) - from file, then cache * * @param tableName Name of table to retrieve * @returns TableSchema or null if not found */ getTableSchema(tableName: string): Promise; /** * Find fields by name across hot tables * * Performance: < 1ms for typical field searches (O(n) over hot tables only) * Note: Cold tables not searched for efficiency * * @param fieldName Column name to search for * @returns Array of { table, column } matches */ findFieldsByName(fieldName: string): Promise>; /** * Get cache statistics * * @returns Cache stats including hit rate and capacity */ /** * Remove a table from all cache tiers (hot + LRU) * Used after DROP TABLE to keep cache consistent */ invalidateTable(tableName: string): void; /** * Insert or update a table schema in cache * Used after CREATE TABLE or ALTER TABLE to keep cache consistent */ refreshTable(tableName: string, schema: TableSchema): void; getStats(): CacheStats; } /** * Schema Layered Loader * Manages hierarchical schema loading: hot on startup, cold on-demand */ export declare class SchemaLayeredLoader { private dbcliPath; /** V2 named connection for `.dbcli/schemas//` */ private connectionName; private options; private cache; private index; private loadTime; /** * Constructor * @param dbcliPath Path to .dbcli directory * @param options Loader configuration */ constructor(dbcliPath: string, options?: LoaderOptions); /** * Initialize: Main entry point for startup * * Performance Target: < 100ms (including file I/O, JSON parsing, hot-table preload) * For 100+ tables: Should still meet target through layered approach * * Flow: * 1. Load index (schemas/index.json) * 2. Initialize cache manager * 3. Preload hot tables * 4. Return cache, index, and timing * * @returns Initialization result with cache, index, and load time */ initialize(): Promise<{ cache: SchemaCacheManager; index: SchemaIndex | null; loadTime: number; }>; /** * Load cold table on-demand * * Called when first querying a table not in hot cache * * @param tableName Name of cold table to load * @param cache SchemaCacheManager instance * @returns TableSchema or null if not found */ loadColdTable(tableName: string, cache: SchemaCacheManager): Promise; /** * Ensure required directories exist * * Creates: * - .dbcli/schemas/ * - .dbcli/schemas/cold/ * * @private */ private ensureDirectories; /** * Get performance benchmark data * * Used for monitoring and tuning * * @returns Benchmark metrics */ getBenchmark(): { initTime: number; hotTables: number; totalTables: number; estimatedSize: number; }; } /** * Detect config version from raw parsed JSON */ export declare function detectConfigVersion(raw: unknown): 1 | 2; /** * Resolved connection result — what commands receive * Supports SQL, MongoDB, Redis, and Elasticsearch connections */ export interface ResolvedConnection { name: string; connection: { system: "postgresql" | "mysql" | "mariadb" | "mongodb" | "redis" | "elasticsearch"; host: string | { $env: string; }; port: number | { $env: string; }; user: string | { $env: string; }; password: string | { $env: string; }; database: string | { $env: string; }; uri?: string | { $env: string; }; protocol?: "http" | "https"; nodes?: string[]; cloudId?: string | { $env: string; }; apiKey?: string | { $env: string; }; caPath?: string; rejectUnauthorized?: boolean; }; permission: "query-only" | "read-write" | "data-admin" | "admin"; envFile?: string; environment?: string; } /** * Resolve a named connection from v2 config */ export declare function resolveConnection(config: DbcliConfigV2, name: string | undefined): ResolvedConnection; /** * Load env file for a connection if specified */ export declare function loadConnectionEnv(resolved: ResolvedConnection, basePath: string): Promise; /** * Read and validate a v2 config from disk */ export declare function readV2Config(path: string): Promise; /** * Write a v2 config and its integrity records as one recoverable publication. */ export declare function writeV2Config(path: string, config: DbcliConfigV2): Promise; /** * List all connection names in a v2 config */ export declare function listConnections(config: DbcliConfigV2): Array<{ name: string; system: string; host: string | { $env: string; }; port: number | { $env: string; }; database: string | { $env: string; }; uri?: string | { $env: string; }; isDefault: boolean; }>; export type SqlSystem = "postgresql" | "mysql" | "mariadb"; /** * `$env` 變數名。per-connection 命名空間化:常駐 sidecar 共用 process.env, * 且 loadEnvFile 不覆寫既有 key——若兩連線都用 DB_PASSWORD 會撞名取到對方的值。 */ export declare function envVarNameFor(connName: string, field: "password"): string; export interface ConnectionInput { name: string; system: SqlSystem; host: string; port: number; user: string; database: string; } /** 刪除連線(immutable)。刪預設則改派為剩餘第一條;刪最後一條則擋下(v2 需至少一條)。 */ export declare function removeConnection(config: DbcliConfigV2, name: string): DbcliConfigV2; /** 設定預設連線(immutable)。 */ export declare function setDefaultConnection(config: DbcliConfigV2, name: string): DbcliConfigV2; /** * v1 單連線 → v2,產生唯一 'default' 連線。沿用 v1 既有密碼慣例:legacy * `.env.local` 的 `DB_PASSWORD`,故 default 連線 envFile 指向 '.env.local'、 * password 設 {$env:'DB_PASSWORD'},不搬動既有 secret。blacklist/audit/metadata 原樣帶過。 */ export declare function migrateV1ToV2(v1: DbcliConfig$1): DbcliConfigV2; /** 新增或就地覆寫同名連線(immutable)。非機密欄存字面值,password 存 {$env} 參照 + * per-connection envFile。編輯時保留既有 permission;新建預設 'query-only'。 */ export declare function upsertConnection(config: DbcliConfigV2, input: ConnectionInput): DbcliConfigV2; /** * 單一連線的密碼輪替:只動該連線的密碼,其餘設定原封不動。 * * 密碼實際落在哪裡由 config 決定,不是靠命名規則猜的—— * 連線若已用 `{ $env: NAME }`,就改寫 NAME 這個 key;若還是明文, * 先把 config 轉成 env 參照再寫檔,之後的輪替就不必再碰 config.json。 */ export interface PasswordTarget { /** 被更新的連線名稱 */ connection: string; /** 密碼寫入的 env 檔(相對於 config storage 目錄) */ envFile: string; /** 寫入的環境變數名稱 */ varName: string; /** 這次是否需要把 config 裡的明文密碼轉成 $env 參照 */ convertedToEnvRef: boolean; } /** * 查出「這條連線的密碼該寫到哪個 env 檔的哪個 key」,不寫入任何檔案。 * * 驗證新密碼時得先知道 key 名稱才能注入,所以查詢與寫入分開。 */ export declare function resolvePasswordTarget(projectPath: string, connectionName?: string): Promise; export declare function setConnectionPassword(projectPath: string, connectionName: string | undefined, password: string): Promise; /** * Resolve the per-user dbcli root lazily so embedders and tests can provide an * isolated config home without reloading the module. `DBCLI_CONFIG_HOME` is a * dbcli-specific override; otherwise preserve the existing `~/.config` path. */ export declare function getDbcliConfigHome(): string; interface ProjectConfigBinding { version: 3; binding: { type: "home-storage"; storagePath: string; projectPath: string; createdAt: string; }; } /** Canonical user-global configuration directory (`~/.config/dbcli`). */ export declare function getGlobalConfigPath(): string; /** Whether a path points at the canonical user-global configuration directory. */ export declare function isGlobalConfigPath(path: string): boolean; export declare function getProjectStoragePath(projectPath: string): string; export declare function resolveConfigStoragePath(path: string): Promise; export declare function writeProjectBinding(projectPath: string, storagePath?: string): Promise; /** * Read and fully resolve a `.dbcli` project config: handles project-binding * indirection, v1/v2 formats, per-connection `.env` loading and `{$env}` * expansion. `path` is the `.dbcli` directory (or legacy file). Returns the * default config if none exists. Thin wrapper over the same entrypoint the * CLI commands use. */ export declare const readConfig: (path: string, connectionName?: string) => Promise; export { DbcliConfig$1 as DbcliConfig, }; export {};