@carllee1983/dbcli 1.29.0 → 1.31.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/dist/cli.mjs CHANGED
@@ -7136,9 +7136,11 @@ async function writeV2Config(path, config) {
7136
7136
  DbcliConfigV2Schema.parse(config);
7137
7137
  const storagePath = await resolveConfigStoragePath(path);
7138
7138
  const configPath = join2(storagePath, "config.json");
7139
+ const tmpPath = `${configPath}.tmp`;
7139
7140
  await Bun.$`mkdir -p ${storagePath}`;
7140
7141
  const json = JSON.stringify(config, null, 2);
7141
- await Bun.write(configPath, json);
7142
+ await Bun.write(tmpPath, json);
7143
+ await Bun.$`mv -f ${tmpPath} ${configPath}`;
7142
7144
  }
7143
7145
  async function patchConnectionSchema(dbcliPath, connectionName, schema, metadataUpdate) {
7144
7146
  const storagePath = await resolveConfigStoragePath(dbcliPath);
@@ -81222,7 +81224,7 @@ var {
81222
81224
  // package.json
81223
81225
  var package_default = {
81224
81226
  name: "@carllee1983/dbcli",
81225
- version: "1.29.0",
81227
+ version: "1.31.0",
81226
81228
  description: "Database CLI for AI agents",
81227
81229
  type: "module",
81228
81230
  publishConfig: {
package/dist/core.d.ts CHANGED
@@ -354,6 +354,40 @@ export declare class AdapterFactory {
354
354
  static createRedisAdapter(options: ConnectionOptions, blacklistRules?: string[], maskRules?: RedisMaskRule[]): QueryableAdapter;
355
355
  static createElasticsearchAdapter(options: ConnectionOptions): QueryableAdapter;
356
356
  }
357
+ /**
358
+ * Type definitions for data modification operations
359
+ * Defines results and options for data modification (INSERT, UPDATE, DELETE) operations
360
+ */
361
+ /**
362
+ * Result of a data execution operation
363
+ * Used to wrap the execution result and metadata of data modification operations
364
+ */
365
+ export interface DataExecutionResult {
366
+ /** Execution status: success or error */
367
+ status: "success" | "error";
368
+ /** Type of operation executed */
369
+ operation: "insert" | "update" | "delete";
370
+ /** Number of rows affected */
371
+ rows_affected: number;
372
+ /** Execution timestamp in ISO 8601 format */
373
+ timestamp?: string;
374
+ /** Generated SQL statement (for confirmation and error messages) */
375
+ sql?: string;
376
+ /** Error message (only when status is 'error') */
377
+ error?: string;
378
+ }
379
+ /**
380
+ * Data execution options
381
+ * Controls how data modification operations are executed
382
+ */
383
+ export interface DataExecutionOptions {
384
+ /** Dry run mode: display SQL without executing */
385
+ dryRun?: boolean;
386
+ /** Skip confirmation prompt */
387
+ force?: boolean;
388
+ /** Verbose output */
389
+ verbose?: boolean;
390
+ }
357
391
  interface SqlConnectionConfig {
358
392
  system: "postgresql" | "mysql" | "mariadb";
359
393
  host: string | {
@@ -2544,6 +2578,82 @@ export declare class QueryExecutor {
2544
2578
  limitValue?: number;
2545
2579
  }): Promise<QueryResult<Record<string, unknown>>>;
2546
2580
  }
2581
+ /**
2582
+ * DataExecutor class for executing INSERT, UPDATE, DELETE operations
2583
+ */
2584
+ export declare class DataExecutor {
2585
+ private adapter;
2586
+ private permission;
2587
+ private dbSystem;
2588
+ private blacklistValidator?;
2589
+ constructor(adapter: DatabaseAdapter, permission: Permission, dbSystem?: "postgresql" | "mysql", blacklistValidator?: BlacklistValidator | undefined);
2590
+ /**
2591
+ * Build a parameterized INSERT SQL statement
2592
+ * Returns {sql, params} form to prevent SQL injection
2593
+ *
2594
+ * @param tableName Table name
2595
+ * @param data Data object to insert {column: value, ...}
2596
+ * @param schema Table schema
2597
+ * @returns Parameterized SQL and parameters array
2598
+ * @throws Error if a data column is not found in the table schema
2599
+ */
2600
+ buildInsertSql(tableName: string, data: Record<string, unknown>, schema: TableSchema): {
2601
+ sql: string;
2602
+ params: (string | number | boolean | null)[];
2603
+ };
2604
+ /**
2605
+ * Execute an INSERT operation
2606
+ * Enforces permission check, builds SQL, shows confirmation prompt, executes
2607
+ *
2608
+ * @param tableName Table name
2609
+ * @param data Data object to insert
2610
+ * @param schema Table schema
2611
+ * @param options Execution options (dryRun, force, verbose)
2612
+ * @returns DataExecutionResult
2613
+ * @throws PermissionError if insufficient permissions
2614
+ * @throws Error if execution fails
2615
+ */
2616
+ executeInsert(tableName: string, data: Record<string, unknown>, schema: TableSchema, options?: DataExecutionOptions): Promise<DataExecutionResult>;
2617
+ /**
2618
+ * Execute an UPDATE operation
2619
+ * Enforces permission check, builds SQL, shows confirmation prompt, executes
2620
+ *
2621
+ * @param tableName Table name
2622
+ * @param data Updated data object
2623
+ * @param where WHERE clause condition object
2624
+ * @param schema Table schema
2625
+ * @param options Execution options
2626
+ * @returns DataExecutionResult
2627
+ */
2628
+ executeUpdate(tableName: string, data: Record<string, unknown>, where: Record<string, unknown>, schema: TableSchema, options?: DataExecutionOptions): Promise<DataExecutionResult>;
2629
+ /**
2630
+ * Execute a DELETE operation
2631
+ * Admin-only operation, requires strict permission check
2632
+ *
2633
+ * @param tableName Table name
2634
+ * @param where WHERE clause condition object
2635
+ * @param schema Table schema
2636
+ * @param options Execution options
2637
+ * @returns DataExecutionResult
2638
+ */
2639
+ executeDelete(tableName: string, where: Record<string, unknown>, schema: TableSchema, options?: DataExecutionOptions): Promise<DataExecutionResult>;
2640
+ /**
2641
+ * Get database system type (used to determine parameter placeholder and identifier quoting)
2642
+ */
2643
+ private getSystemType;
2644
+ /**
2645
+ * Get identifier quote character (for table names and column names)
2646
+ */
2647
+ private getQuoteChar;
2648
+ /**
2649
+ * Build a parameterized UPDATE SQL statement
2650
+ */
2651
+ private buildUpdateSql;
2652
+ /**
2653
+ * Build a parameterized DELETE SQL statement
2654
+ */
2655
+ private buildDeleteSql;
2656
+ }
2547
2657
  interface SchemaIndex {
2548
2658
  tables: Record<string, {
2549
2659
  location: "hot" | "cold";
@@ -2769,6 +2879,12 @@ export declare function loadConnectionEnv(resolved: ResolvedConnection, basePath
2769
2879
  * Read and validate a v2 config from disk
2770
2880
  */
2771
2881
  export declare function readV2Config(path: string): Promise<DbcliConfigV2>;
2882
+ /**
2883
+ * Write a v2 config to disk atomically (temp file + rename).
2884
+ * Writing to a temp file then renaming over the target is an atomic operation
2885
+ * on the same filesystem, so a crash mid-write can never leave a corrupt config.
2886
+ */
2887
+ export declare function writeV2Config(path: string, config: DbcliConfigV2): Promise<void>;
2772
2888
  /**
2773
2889
  * List all connection names in a v2 config
2774
2890
  */
@@ -2789,7 +2905,47 @@ export declare function listConnections(config: DbcliConfigV2): Array<{
2789
2905
  };
2790
2906
  isDefault: boolean;
2791
2907
  }>;
2908
+ export type SqlSystem = "postgresql" | "mysql" | "mariadb";
2909
+ /**
2910
+ * `$env` 變數名。per-connection 命名空間化:常駐 sidecar 共用 process.env,
2911
+ * 且 loadEnvFile 不覆寫既有 key——若兩連線都用 DB_PASSWORD 會撞名取到對方的值。
2912
+ */
2913
+ export declare function envVarNameFor(connName: string, field: "password"): string;
2914
+ /** 把 secret 寫進該連線的 envFile(KEY=VALUE);既有同名 key 就地覆寫,否則追加。 */
2915
+ export declare function writeConnectionSecret(projectPath: string, connName: string, field: "password", value: string): Promise<void>;
2916
+ export interface ConnectionInput {
2917
+ name: string;
2918
+ system: SqlSystem;
2919
+ host: string;
2920
+ port: number;
2921
+ user: string;
2922
+ database: string;
2923
+ }
2924
+ /** 刪除連線(immutable)。刪預設則改派為剩餘第一條;刪最後一條則擋下(v2 需至少一條)。 */
2925
+ export declare function removeConnection(config: DbcliConfigV2, name: string): DbcliConfigV2;
2926
+ /** 設定預設連線(immutable)。 */
2927
+ export declare function setDefaultConnection(config: DbcliConfigV2, name: string): DbcliConfigV2;
2928
+ /**
2929
+ * v1 單連線 → v2,產生唯一 'default' 連線。沿用 v1 既有密碼慣例:legacy
2930
+ * `.env.local` 的 `DB_PASSWORD`,故 default 連線 envFile 指向 '.env.local'、
2931
+ * password 設 {$env:'DB_PASSWORD'},不搬動既有 secret。blacklist/audit/metadata 原樣帶過。
2932
+ */
2933
+ export declare function migrateV1ToV2(v1: DbcliConfig$1): DbcliConfigV2;
2934
+ /** 新增或就地覆寫同名連線(immutable)。非機密欄存字面值,password 存 {$env} 參照 +
2935
+ * per-connection envFile。編輯時保留既有 permission;新建預設 'query-only'。 */
2936
+ export declare function upsertConnection(config: DbcliConfigV2, input: ConnectionInput): DbcliConfigV2;
2937
+ interface ProjectConfigBinding {
2938
+ version: 3;
2939
+ binding: {
2940
+ type: "home-storage";
2941
+ storagePath: string;
2942
+ projectPath: string;
2943
+ createdAt: string;
2944
+ };
2945
+ }
2946
+ export declare function getProjectStoragePath(projectPath: string): string;
2792
2947
  export declare function resolveConfigStoragePath(path: string): Promise<string>;
2948
+ export declare function writeProjectBinding(projectPath: string, storagePath?: string): Promise<ProjectConfigBinding>;
2793
2949
  /**
2794
2950
  * Read and fully resolve a `.dbcli` project config: handles project-binding
2795
2951
  * indirection, v1/v2 formats, per-connection `.env` loading and `{$env}`