@carllee1983/dbcli 9.1.2 → 11.0.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
@@ -3,7 +3,7 @@
3
3
  // package.json
4
4
  var package_default = {
5
5
  name: "@carllee1983/dbcli",
6
- version: "9.1.2",
6
+ version: "11.0.0",
7
7
  description: "Database CLI for AI agents",
8
8
  type: "module",
9
9
  publishConfig: {
@@ -44,7 +44,7 @@ var package_default = {
44
44
  "blacklist"
45
45
  ],
46
46
  engines: {
47
- bun: ">=1.3.3"
47
+ bun: ">=1.4.0"
48
48
  },
49
49
  files: [
50
50
  "dist/",
@@ -103,6 +103,7 @@ var package_default = {
103
103
  "lru-cache": "^11.4.0",
104
104
  "lucide-react": "^1.16.0",
105
105
  mongodb: "^7.2.0",
106
+ "mongodb-connection-string-url": "^7.0.1",
106
107
  mysql2: "^3.24.3",
107
108
  "node-sql-parser": "5",
108
109
  open: "^11.0.0",
package/dist/core.d.ts CHANGED
@@ -36,6 +36,8 @@ export interface ConnectionOptions {
36
36
  replicaSet?: string;
37
37
  /** MongoDB TLS switch (optional, field-based config; implied true when srv) */
38
38
  tls?: boolean;
39
+ /** MongoDB extra driver options appended to the URI query string (field-based config, plain strings only) */
40
+ options?: Record<string, string>;
39
41
  /** MongoDB SRV lookup — build a mongodb+srv:// URI from host (optional, field-based config) */
40
42
  srv?: boolean;
41
43
  /** Connection timeout in milliseconds (default: 5000) */
@@ -440,6 +442,8 @@ interface MongoDBConnectionConfig {
440
442
  $env: string;
441
443
  };
442
444
  tls?: boolean;
445
+ /** Extra driver options appended to the URI query string; plain strings, no env-ref */
446
+ options?: Record<string, string>;
443
447
  /** Build a mongodb+srv:// URI from host and expand it via DNS SRV lookup */
444
448
  srv?: boolean;
445
449
  }
@@ -1105,6 +1109,7 @@ declare const DbcliConfigSchema: z.ZodObject<{
1105
1109
  }>
1106
1110
  ]>>;
1107
1111
  tls: z.ZodOptional<z.ZodBoolean>;
1112
+ options: z.ZodOptional<z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodString>, Record<string, string>, Record<string, string>>>;
1108
1113
  srv: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
1109
1114
  }, "strip", z.ZodTypeAny, {
1110
1115
  password: string | {
@@ -1134,6 +1139,7 @@ declare const DbcliConfigSchema: z.ZodObject<{
1134
1139
  $env: string;
1135
1140
  } | undefined;
1136
1141
  tls?: boolean | undefined;
1142
+ options?: Record<string, string> | undefined;
1137
1143
  timeout?: number | undefined;
1138
1144
  statementTimeout?: number | undefined;
1139
1145
  }, {
@@ -1163,6 +1169,7 @@ declare const DbcliConfigSchema: z.ZodObject<{
1163
1169
  $env: string;
1164
1170
  } | undefined;
1165
1171
  tls?: boolean | undefined;
1172
+ options?: Record<string, string> | undefined;
1166
1173
  srv?: boolean | undefined;
1167
1174
  timeout?: number | undefined;
1168
1175
  statementTimeout?: number | undefined;
@@ -1569,6 +1576,7 @@ declare const DbcliConfigSchema: z.ZodObject<{
1569
1576
  $env: string;
1570
1577
  } | undefined;
1571
1578
  tls?: boolean | undefined;
1579
+ options?: Record<string, string> | undefined;
1572
1580
  timeout?: number | undefined;
1573
1581
  statementTimeout?: number | undefined;
1574
1582
  } | {
@@ -1701,6 +1709,7 @@ declare const DbcliConfigSchema: z.ZodObject<{
1701
1709
  $env: string;
1702
1710
  } | undefined;
1703
1711
  tls?: boolean | undefined;
1712
+ options?: Record<string, string> | undefined;
1704
1713
  srv?: boolean | undefined;
1705
1714
  timeout?: number | undefined;
1706
1715
  statementTimeout?: number | undefined;
@@ -1827,7 +1836,7 @@ declare const DbcliConfigSchema: z.ZodObject<{
1827
1836
  type DbcliConfig$1 = z.infer<typeof DbcliConfigSchema>;
1828
1837
  declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
1829
1838
  version: z.ZodLiteral<2>;
1830
- default: z.ZodString;
1839
+ default: z.ZodOptional<z.ZodString>;
1831
1840
  connections: z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodUnion<[
1832
1841
  z.ZodObject<{
1833
1842
  timeout: z.ZodOptional<z.ZodNumber>;
@@ -2154,6 +2163,7 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
2154
2163
  }>
2155
2164
  ]>>;
2156
2165
  tls: z.ZodOptional<z.ZodBoolean>;
2166
+ options: z.ZodOptional<z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodString>, Record<string, string>, Record<string, string>>>;
2157
2167
  srv: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
2158
2168
  } & {
2159
2169
  permission: z.ZodDefault<z.ZodEnum<[
@@ -2193,6 +2203,7 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
2193
2203
  $env: string;
2194
2204
  } | undefined;
2195
2205
  tls?: boolean | undefined;
2206
+ options?: Record<string, string> | undefined;
2196
2207
  timeout?: number | undefined;
2197
2208
  statementTimeout?: number | undefined;
2198
2209
  envFile?: string | undefined;
@@ -2224,6 +2235,7 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
2224
2235
  $env: string;
2225
2236
  } | undefined;
2226
2237
  tls?: boolean | undefined;
2238
+ options?: Record<string, string> | undefined;
2227
2239
  srv?: boolean | undefined;
2228
2240
  timeout?: number | undefined;
2229
2241
  permission?: "admin" | "query-only" | "read-write" | "data-admin" | undefined;
@@ -2570,6 +2582,7 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
2570
2582
  $env: string;
2571
2583
  } | undefined;
2572
2584
  tls?: boolean | undefined;
2585
+ options?: Record<string, string> | undefined;
2573
2586
  timeout?: number | undefined;
2574
2587
  statementTimeout?: number | undefined;
2575
2588
  envFile?: string | undefined;
@@ -2704,6 +2717,7 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
2704
2717
  $env: string;
2705
2718
  } | undefined;
2706
2719
  tls?: boolean | undefined;
2720
+ options?: Record<string, string> | undefined;
2707
2721
  timeout?: number | undefined;
2708
2722
  statementTimeout?: number | undefined;
2709
2723
  envFile?: string | undefined;
@@ -2898,7 +2912,6 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
2898
2912
  };
2899
2913
  };
2900
2914
  version: 2;
2901
- default: string;
2902
2915
  metadata: {
2903
2916
  version: string;
2904
2917
  createdAt?: string | undefined;
@@ -2981,6 +2994,7 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
2981
2994
  $env: string;
2982
2995
  } | undefined;
2983
2996
  tls?: boolean | undefined;
2997
+ options?: Record<string, string> | undefined;
2984
2998
  timeout?: number | undefined;
2985
2999
  statementTimeout?: number | undefined;
2986
3000
  envFile?: string | undefined;
@@ -3047,9 +3061,9 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
3047
3061
  fields?: string[] | undefined;
3048
3062
  }[];
3049
3063
  } | undefined;
3064
+ default?: string | undefined;
3050
3065
  }, {
3051
3066
  version: 2;
3052
- default: string;
3053
3067
  connections: Record<string, unknown>;
3054
3068
  redis?: {
3055
3069
  mask?: {
@@ -3070,6 +3084,7 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
3070
3084
  max_entries?: number | undefined;
3071
3085
  } | undefined;
3072
3086
  } | undefined;
3087
+ default?: string | undefined;
3073
3088
  metadata?: {
3074
3089
  version?: string | undefined;
3075
3090
  createdAt?: string | undefined;
@@ -3092,7 +3107,6 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
3092
3107
  };
3093
3108
  };
3094
3109
  version: 2;
3095
- default: string;
3096
3110
  metadata: {
3097
3111
  version: string;
3098
3112
  createdAt?: string | undefined;
@@ -3175,6 +3189,7 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
3175
3189
  $env: string;
3176
3190
  } | undefined;
3177
3191
  tls?: boolean | undefined;
3192
+ options?: Record<string, string> | undefined;
3178
3193
  timeout?: number | undefined;
3179
3194
  statementTimeout?: number | undefined;
3180
3195
  envFile?: string | undefined;
@@ -3241,9 +3256,9 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
3241
3256
  fields?: string[] | undefined;
3242
3257
  }[];
3243
3258
  } | undefined;
3259
+ default?: string | undefined;
3244
3260
  }, {
3245
3261
  version: 2;
3246
- default: string;
3247
3262
  connections: Record<string, unknown>;
3248
3263
  redis?: {
3249
3264
  mask?: {
@@ -3264,6 +3279,7 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
3264
3279
  max_entries?: number | undefined;
3265
3280
  } | undefined;
3266
3281
  } | undefined;
3282
+ default?: string | undefined;
3267
3283
  metadata?: {
3268
3284
  version?: string | undefined;
3269
3285
  createdAt?: string | undefined;
@@ -3630,9 +3646,7 @@ export declare function resolveConnection(config: DbcliConfigV2, name: string |
3630
3646
  * Load env file for a connection if specified
3631
3647
  */
3632
3648
  export declare function loadConnectionEnv(resolved: ResolvedConnection, basePath: string): Promise<void>;
3633
- /**
3634
- * Read and validate a v2 config from disk
3635
- */
3649
+ /** Read and validate a v2 config from disk. */
3636
3650
  export declare function readV2Config(path: string): Promise<DbcliConfigV2>;
3637
3651
  /**
3638
3652
  * Write a v2 config and its integrity records as one recoverable publication.
@@ -3675,7 +3689,7 @@ export interface ConnectionInput {
3675
3689
  user: string;
3676
3690
  database: string;
3677
3691
  }
3678
- /** 刪除連線(immutable)。刪預設則改派為剩餘第一條;刪最後一條則擋下(v2 需至少一條)。 */
3692
+ /** 刪除連線(immutable)。刪預設則清空預設;刪最後一條則擋下(v2 需至少一條)。 */
3679
3693
  export declare function removeConnection(config: DbcliConfigV2, name: string): DbcliConfigV2;
3680
3694
  /** 設定預設連線(immutable)。 */
3681
3695
  export declare function setDefaultConnection(config: DbcliConfigV2, name: string): DbcliConfigV2;
package/dist/core.mjs CHANGED
@@ -1251,6 +1251,8 @@ var messages_default = {
1251
1251
  init: {
1252
1252
  description: "Initialize dbcli configuration with .env parsing and interactive prompts",
1253
1253
  welcome: "Welcome to dbcli",
1254
+ prompt_connection_name: "Connection name",
1255
+ connection_name_required: "Connection name is required. Provide --conn-name <name> (this is separate from the database --name).",
1254
1256
  select_system: "Select database system:",
1255
1257
  prompt_host: "Database host: ",
1256
1258
  prompt_port: "Database port: ",
@@ -1259,6 +1261,22 @@ var messages_default = {
1259
1261
  secret_alternatives_sql: "pass --password, supply the credential through .env or the process environment, or store a reference with --use-env-refs",
1260
1262
  secret_alternatives_mongo_password: "pass --password, supply the credential through .env or the process environment, or paste the connection string with --uri",
1261
1263
  secret_alternatives_mongo_uri: "pass the connection string with --uri",
1264
+ mongo_uri_conflicts_fields: "--uri cannot be combined with {flags}: the connection string already carries those settings. Use one or the other (--name may be combined to override the database name).",
1265
+ mongo_uri_with_env_refs: "--uri cannot be combined with --use-env-refs: the connection string is decomposed into config fields, and its credentials are not moved into environment variables. Either remove --use-env-refs so dbcli decomposes the string into the field config, or use the --env-* flags (--env-host, --env-user, --env-password, ...) to name one variable per field.",
1266
+ mongo_uri_fallback_warning: "\u26A0\uFE0F This connection string {reasons}, so it cannot become fields. It is stored as-is in uri, and its credentials will sit in plaintext in the config file.",
1267
+ mongo_uri_reason_multi_host: "contains more than one host (a field config holds only one)",
1268
+ mongo_uri_reason_secret_option: "contains secret option(s) ({keys}) that would land in plaintext options",
1269
+ mongo_uri_reason_duplicate_key: "repeats the query key(s) {keys} (a field config can hold only one value per key)",
1270
+ mongo_uri_reason_non_scram: "uses the non-SCRAM auth mechanism {mechanism} (field config cannot express it)",
1271
+ mongo_decomposed_header: "Connection string decomposed into these fields (password hidden):",
1272
+ mongo_paste_env_refs_warning: "\u26A0\uFE0F --use-env-refs does not apply to a pasted connection string: its credentials are written to the config file as they are, not as environment-variable references.",
1273
+ mongo_setup_mode_paste: "Paste a connection string (copied from Atlas / Compass)",
1274
+ mongo_string_invalid: "Not a valid MongoDB connection string (it is not echoed because it may carry credentials).",
1275
+ mongo_string_bad_host: "The connection string has an invalid host or port (the port must be an integer from 1 to 65535).",
1276
+ mongo_string_bad_credentials: "The connection string's credentials contain an unescaped reserved character such as @, : or /. Percent-encode it (for example @ as %40).",
1277
+ mongo_string_tls_conflict: "The connection string sets tls and ssl to different values.",
1278
+ mongo_string_bad_tls: "The connection string's {key} must be true or false.",
1279
+ mongo_string_empty_option: "The connection string sets {key} but leaves it empty. Give it a value or remove it.",
1262
1280
  prompt_name: "Database name: ",
1263
1281
  prompt_permission: "Permission level (query-only, read-write, data-admin, admin): ",
1264
1282
  env_parse_note: "Note: Unable to parse .env configuration, using interactive prompts",
@@ -1275,7 +1293,7 @@ var messages_default = {
1275
1293
  config_exists_use_force: ".dbcli exists. Use --force option to overwrite.",
1276
1294
  connection_added: "Connection '{name}' added",
1277
1295
  connection_removed: "Connection '{name}' removed",
1278
- connection_removed_switched: "Connection '{name}' removed. Default connection switched to '{newDefault}'",
1296
+ connection_removed_default_cleared: "Connection '{name}' removed. Default connection cleared. Specify --use <name> or DBCLI_CONNECTION for database commands.",
1279
1297
  connection_renamed: "Connection '{oldName}' renamed to '{newName}'",
1280
1298
  v1_migration_prompt: "Detected old config format. Create new format and import existing connection as 'default'?",
1281
1299
  config_saved_v2: "V2 configuration saved to .dbcli",
@@ -1313,6 +1331,9 @@ var messages_default = {
1313
1331
  description: "Switch or display the default database connection",
1314
1332
  switched: "Switched default connection to {name}",
1315
1333
  current: "Current default connection: {name}",
1334
+ current_none: "No default connection. Specify --use <name> or DBCLI_CONNECTION.",
1335
+ unset: "Default connection cleared. Specify --use <name> or DBCLI_CONNECTION for database commands.",
1336
+ unset_conflict: "--unset cannot be combined with a connection name, --list, --confirm-production, or --format json",
1316
1337
  requires_v2: "This feature requires v2 config format. Use 'dbcli init --conn-name <name>' to create one",
1317
1338
  available: "Available connections"
1318
1339
  },
@@ -1583,6 +1604,8 @@ var messages_default2 = {
1583
1604
  init: {
1584
1605
  description: "\u521D\u59CB\u5316 dbcli \u914D\u7F6E\uFF0C\u89E3\u6790 .env \u4E26\u9032\u884C\u4E92\u52D5\u5F0F\u63D0\u793A",
1585
1606
  welcome: "\u6B61\u8FCE\u4F7F\u7528 dbcli",
1607
+ prompt_connection_name: "\u9023\u7DDA\u540D\u7A31",
1608
+ connection_name_required: "\u9023\u7DDA\u540D\u7A31\u4E0D\u53EF\u7A7A\u767D\uFF0C\u8ACB\u63D0\u4F9B --conn-name <name>\uFF08\u8207\u8CC7\u6599\u5EAB\u540D\u7A31 --name \u4E0D\u540C\uFF09\u3002",
1586
1609
  select_system: "\u9078\u64C7\u8CC7\u6599\u5EAB\u7CFB\u7D71\uFF1A",
1587
1610
  prompt_host: "\u8CC7\u6599\u5EAB\u4E3B\u6A5F\uFF1A",
1588
1611
  prompt_port: "\u8CC7\u6599\u5EAB\u57E0\u865F\uFF1A",
@@ -1591,6 +1614,22 @@ var messages_default2 = {
1591
1614
  secret_alternatives_sql: "\u6539\u7528 --password\u3001\u628A\u6191\u8B49\u653E\u9032 .env \u6216\u884C\u7A0B\u74B0\u5883\u8B8A\u6578\uFF0C\u6216\u4EE5 --use-env-refs \u5B58\u6210\u53C3\u7167",
1592
1615
  secret_alternatives_mongo_password: "\u6539\u7528 --password\u3001\u628A\u6191\u8B49\u653E\u9032 .env \u6216\u884C\u7A0B\u74B0\u5883\u8B8A\u6578\uFF0C\u6216\u4EE5 --uri \u8CBC\u4E0A\u9023\u7DDA\u5B57\u4E32",
1593
1616
  secret_alternatives_mongo_uri: "\u4EE5 --uri \u50B3\u5165\u9023\u7DDA\u5B57\u4E32",
1617
+ mongo_uri_conflicts_fields: "--uri \u4E0D\u80FD\u8207 {flags} \u4E26\u7528\uFF1A\u9023\u7DDA\u5B57\u4E32\u5DF2\u5305\u542B\u9019\u4E9B\u8A2D\u5B9A\u3002\u8ACB\u64C7\u4E00\u4F7F\u7528\uFF08--name \u53EF\u4E26\u7528\uFF0C\u7528\u4F86\u8986\u84CB\u8CC7\u6599\u5EAB\u540D\u7A31\uFF09\u3002",
1618
+ mongo_uri_with_env_refs: "--uri \u4E0D\u80FD\u8207 --use-env-refs \u4E26\u7528\uFF1A\u9023\u7DDA\u5B57\u4E32\u6703\u88AB\u62C6\u89E3\u6210\u6B04\u4F4D\u8A2D\u5B9A\u5BEB\u5165\uFF0C\u5E33\u5BC6\u4E0D\u6703\u88AB\u62BD\u6210\u74B0\u5883\u8B8A\u6578\u53C3\u7167\u3002\u8ACB\u6539\u8D70\u4E0B\u5217\u4EFB\u4E00\u505A\u6CD5\uFF1A\u62FF\u6389 --use-env-refs\uFF0C\u8B93 dbcli \u62C6\u89E3\u5B57\u4E32\u5BEB\u5165\u6B04\u4F4D\u8A2D\u5B9A\uFF1B\u6216\u6539\u7528 --env-* flag\uFF08--env-host\u3001--env-user\u3001--env-password \u7B49\uFF09\u9010\u6B04\u7D66\u8B8A\u6578\u540D\u7A31\u3002",
1619
+ mongo_uri_fallback_warning: "\u26A0\uFE0F \u6B64\u9023\u7DDA\u5B57\u4E32{reasons}\uFF0C\u7121\u6CD5\u62C6\u6210\u6B04\u4F4D\u8A2D\u5B9A\uFF0C\u5DF2\u539F\u6A23\u5B58\u5165 uri\uFF1B\u5E33\u5BC6\u5C07\u660E\u6587\u5B58\u653E\u65BC\u8A2D\u5B9A\u6A94\u3002",
1620
+ mongo_uri_reason_multi_host: "\u542B\u591A\u7D44 host\uFF08\u6B04\u4F4D\u8A2D\u5B9A\u53EA\u80FD\u8868\u9054\u4E00\u7D44\uFF09",
1621
+ mongo_uri_reason_secret_option: "\u542B\u6A5F\u5BC6 option\uFF08{keys}\uFF09\uFF0C\u62C6\u9032 options \u6703\u660E\u6587\u843D\u76E4",
1622
+ mongo_uri_reason_duplicate_key: "\u542B\u91CD\u8907\u7684 query \u9375\uFF08{keys}\uFF09\uFF08\u6B04\u4F4D\u8A2D\u5B9A\u6BCF\u500B\u9375\u53EA\u80FD\u5B58\u4E00\u500B\u503C\uFF09",
1623
+ mongo_uri_reason_non_scram: "\u4F7F\u7528\u975E SCRAM \u7684\u8A8D\u8B49\u6A5F\u5236 {mechanism}\uFF08\u6B04\u4F4D\u8A2D\u5B9A\u7121\u6CD5\u8868\u9054\uFF09",
1624
+ mongo_decomposed_header: "\u9023\u7DDA\u5B57\u4E32\u5DF2\u62C6\u89E3\u6210\u4E0B\u5217\u6B04\u4F4D\uFF08\u5BC6\u78BC\u5DF2\u906E\u853D\uFF09\uFF1A",
1625
+ mongo_paste_env_refs_warning: "\u26A0\uFE0F --use-env-refs \u4E0D\u9069\u7528\u65BC\u8CBC\u4E0A\u7684\u9023\u7DDA\u5B57\u4E32\uFF1A\u5E33\u5BC6\u6703\u4EE5\u5B57\u9762\u503C\u5BEB\u5165\u8A2D\u5B9A\u6A94\uFF0C\u4E0D\u6703\u8B8A\u6210\u74B0\u5883\u8B8A\u6578\u53C3\u7167\u3002",
1626
+ mongo_setup_mode_paste: "\u8CBC\u4E0A\u9023\u7DDA\u5B57\u4E32\uFF08Atlas / Compass \u8907\u88FD\u7684\uFF09",
1627
+ mongo_string_invalid: "\u4E0D\u662F\u5408\u6CD5\u7684 MongoDB \u9023\u7DDA\u5B57\u4E32\uFF08\u5B57\u4E32\u53EF\u80FD\u5E36\u6709\u5E33\u5BC6\uFF0C\u6240\u4EE5\u4E0D\u5370\u51FA\uFF09\u3002",
1628
+ mongo_string_bad_host: "\u9023\u7DDA\u5B57\u4E32\u7684 host \u6216\u57E0\u865F\u4E0D\u5408\u6CD5\uFF08\u57E0\u865F\u9808\u70BA 1 \u81F3 65535 \u7684\u6574\u6578\uFF09\u3002",
1629
+ mongo_string_bad_credentials: "\u9023\u7DDA\u5B57\u4E32\u7684\u5E33\u865F\u6216\u5BC6\u78BC\u542B\u6709\u672A\u8DF3\u812B\u7684\u4FDD\u7559\u5B57\u5143\uFF08\u5982 @\u3001:\u3001/\uFF09\u3002\u8ACB\u505A\u767E\u5206\u6BD4\u7DE8\u78BC\uFF08\u4F8B\u5982 @ \u5BEB\u6210 %40\uFF09\u3002",
1630
+ mongo_string_tls_conflict: "\u9023\u7DDA\u5B57\u4E32\u540C\u6642\u6307\u5B9A\u4E86 tls \u8207 ssl \u4E14\u503C\u4E0D\u540C\u3002",
1631
+ mongo_string_bad_tls: "\u9023\u7DDA\u5B57\u4E32\u7684 {key} \u53EA\u63A5\u53D7 true \u6216 false\u3002",
1632
+ mongo_string_empty_option: "\u9023\u7DDA\u5B57\u4E32\u6307\u5B9A\u4E86 {key} \u537B\u6C92\u6709\u503C\u3002\u8ACB\u7D66\u503C\u6216\u79FB\u9664\u3002",
1594
1633
  prompt_name: "\u8CC7\u6599\u5EAB\u540D\u7A31\uFF1A",
1595
1634
  prompt_permission: "\u6B0A\u9650\u7B49\u7D1A\uFF08query-only, read-write, data-admin, admin\uFF09\uFF1A",
1596
1635
  env_parse_note: "\u63D0\u793A\uFF1A\u7121\u6CD5\u89E3\u6790 .env \u914D\u7F6E\uFF0C\u4F7F\u7528\u4E92\u52D5\u5F0F\u63D0\u793A",
@@ -1607,7 +1646,7 @@ var messages_default2 = {
1607
1646
  config_exists_use_force: ".dbcli \u5DF2\u5B58\u5728\u3002\u4F7F\u7528 --force \u9078\u9805\u8986\u84CB\u3002",
1608
1647
  connection_added: "\u5DF2\u65B0\u589E\u9023\u7DDA '{name}'",
1609
1648
  connection_removed: "\u5DF2\u79FB\u9664\u9023\u7DDA '{name}'",
1610
- connection_removed_switched: "\u5DF2\u79FB\u9664\u9023\u7DDA '{name}'\uFF0C\u9810\u8A2D\u9023\u7DDA\u5DF2\u5207\u63DB\u70BA '{newDefault}'",
1649
+ connection_removed_default_cleared: "\u5DF2\u79FB\u9664\u9023\u7DDA '{name}'\uFF0C\u9810\u8A2D\u9023\u7DDA\u5DF2\u6E05\u7A7A\u3002\u57F7\u884C\u8CC7\u6599\u5EAB\u6307\u4EE4\u6642\u8ACB\u4F7F\u7528 --use <name> \u6216\u8A2D\u5B9A DBCLI_CONNECTION\u3002",
1611
1650
  connection_renamed: "\u5DF2\u5C07\u9023\u7DDA '{oldName}' \u91CD\u65B0\u547D\u540D\u70BA '{newName}'",
1612
1651
  v1_migration_prompt: "\u5075\u6E2C\u5230\u820A\u683C\u5F0F\u8A2D\u5B9A\uFF0C\u5C07\u5EFA\u7ACB\u65B0\u683C\u5F0F\u4E26\u5C07\u73FE\u6709\u9023\u7DDA\u532F\u5165\u70BA 'default'\uFF0C\u662F\u5426\u7E7C\u7E8C\uFF1F",
1613
1652
  config_saved_v2: "V2 \u8A2D\u5B9A\u5DF2\u5132\u5B58\u81F3 .dbcli",
@@ -1645,6 +1684,9 @@ var messages_default2 = {
1645
1684
  description: "\u5207\u63DB\u6216\u986F\u793A\u9810\u8A2D\u8CC7\u6599\u5EAB\u9023\u7DDA",
1646
1685
  switched: "\u5DF2\u5207\u63DB\u9810\u8A2D\u9023\u7DDA\u70BA {name}",
1647
1686
  current: "\u76EE\u524D\u7684\u9810\u8A2D\u9023\u7DDA\uFF1A{name}",
1687
+ current_none: "\u76EE\u524D\u6C92\u6709\u9810\u8A2D\u9023\u7DDA\u3002\u8ACB\u4F7F\u7528 --use <name> \u6216\u8A2D\u5B9A DBCLI_CONNECTION\u3002",
1688
+ unset: "\u9810\u8A2D\u9023\u7DDA\u5DF2\u6E05\u7A7A\u3002\u57F7\u884C\u8CC7\u6599\u5EAB\u6307\u4EE4\u6642\u8ACB\u4F7F\u7528 --use <name> \u6216\u8A2D\u5B9A DBCLI_CONNECTION\u3002",
1689
+ unset_conflict: "--unset \u4E0D\u53EF\u8207\u9023\u7DDA\u540D\u7A31\u3001--list\u3001--confirm-production \u6216 --format json \u540C\u6642\u4F7F\u7528",
1648
1690
  requires_v2: "\u6B64\u529F\u80FD\u9700\u8981\u65B0\u683C\u5F0F\u8A2D\u5B9A\u3002\u8ACB\u4F7F\u7528 dbcli init --conn-name <\u540D\u7A31> \u5EFA\u7ACB\u591A\u9023\u7DDA\u8A2D\u5B9A",
1649
1691
  available: "\u53EF\u7528\u9023\u7DDA"
1650
1692
  },
@@ -8486,6 +8528,24 @@ var TimeoutField = {
8486
8528
  timeout: numberType().int().min(MIN_CONNECTION_TIMEOUT_MS).max(MAX_CONNECTION_TIMEOUT_MS).optional(),
8487
8529
  statementTimeout: numberType().int().min(MIN_STATEMENT_TIMEOUT_MS).max(MAX_STATEMENT_TIMEOUT_MS).optional()
8488
8530
  };
8531
+ var RESERVED_MONGODB_OPTION_KEYS = {
8532
+ authsource: "authSource",
8533
+ replicaset: "replicaSet",
8534
+ tls: "tls",
8535
+ ssl: "tls"
8536
+ };
8537
+ var MongoDBOptionsSchema = recordType(stringType(), stringType()).superRefine((options, ctx) => {
8538
+ for (const key of Object.keys(options)) {
8539
+ const field = RESERVED_MONGODB_OPTION_KEYS[key.toLowerCase()];
8540
+ if (field) {
8541
+ ctx.addIssue({
8542
+ code: ZodIssueCode.custom,
8543
+ path: [key],
8544
+ message: `options.${key} duplicates the dedicated '${field}' field; set '${field}' instead`
8545
+ });
8546
+ }
8547
+ }
8548
+ });
8489
8549
  var MongoDBConnectionConfigSchema = objectType({
8490
8550
  system: literalType("mongodb"),
8491
8551
  uri: unionType([stringType(), EnvRefSchema]).optional(),
@@ -8497,6 +8557,7 @@ var MongoDBConnectionConfigSchema = objectType({
8497
8557
  authSource: unionType([stringType(), EnvRefSchema]).optional(),
8498
8558
  replicaSet: unionType([stringType(), EnvRefSchema]).optional(),
8499
8559
  tls: booleanType().optional(),
8560
+ options: MongoDBOptionsSchema.optional(),
8500
8561
  srv: booleanType().optional().default(false),
8501
8562
  ...TimeoutField
8502
8563
  });
@@ -8676,7 +8737,7 @@ var NamedConnectionSchema = preprocessType((raw, ctx) => {
8676
8737
  }, NamedConnectionUnion);
8677
8738
  var DbcliConfigV2Schema = objectType({
8678
8739
  version: literalType(2),
8679
- default: stringType().min(1),
8740
+ default: stringType().min(1).optional(),
8680
8741
  connections: recordType(NamedConnectionSchema).refine((conns) => Object.keys(conns).length > 0, {
8681
8742
  message: "At least one connection is required"
8682
8743
  }),
@@ -8686,7 +8747,7 @@ var DbcliConfigV2Schema = objectType({
8686
8747
  blacklist: BlacklistConfigSchema,
8687
8748
  audit: AuditConfigSchema,
8688
8749
  redis: RedisConfigSchema
8689
- }).refine((config) => (config.default in config.connections), {
8750
+ }).refine((config) => config.default === undefined || Object.hasOwn(config.connections, config.default), {
8690
8751
  message: "Default connection must exist in connections",
8691
8752
  path: ["default"]
8692
8753
  });
@@ -9037,14 +9098,26 @@ function findSimilarConnectionNames(requestedName, availableNames) {
9037
9098
  }).filter(({ isSimilar }) => isSimilar).sort((a, b) => a.distance - b.distance || a.name.localeCompare(b.name)).slice(0, 3).map(({ name }) => name);
9038
9099
  }
9039
9100
  function connectionNotFoundMessage(requestedName, availableNames) {
9101
+ if (requestedName === undefined) {
9102
+ return "\u5C1A\u672A\u8A2D\u5B9A\u9810\u8A2D\u9023\u7DDA\u3002\u8ACB\u4F7F\u7528 --use <name> \u6216\u8A2D\u5B9A DBCLI_CONNECTION \u660E\u78BA\u6307\u5B9A\u9023\u7DDA\u3002" + ` \u53EF\u7528\u9023\u7DDA\uFF1A${availableNames.join(", ")}`;
9103
+ }
9040
9104
  const suggestions = findSimilarConnectionNames(requestedName, availableNames);
9041
9105
  const suggestion = suggestions.length > 0 ? ` \u4F60\u662F\u5426\u8981\u4F7F\u7528\uFF1A${suggestions.join("\u3001")}\uFF1F` : "";
9042
9106
  return `\u9023\u7DDA '${requestedName}' \u4E0D\u5B58\u5728\u3002${suggestion} \u53EF\u7528\u9023\u7DDA\uFF1A${availableNames.join(", ")}`;
9043
9107
  }
9108
+
9109
+ class ConnectionSelectionRequiredError extends ConfigError {
9110
+ constructor(availableNames) {
9111
+ super(connectionNotFoundMessage(undefined, availableNames));
9112
+ }
9113
+ }
9044
9114
  function resolveConnection(config, name) {
9045
9115
  const connectionName = name ?? config.default;
9116
+ if (connectionName === undefined) {
9117
+ throw new ConnectionSelectionRequiredError(Object.keys(config.connections));
9118
+ }
9046
9119
  const conn = config.connections[connectionName];
9047
- if (!conn) {
9120
+ if (!Object.hasOwn(config.connections, connectionName) || !conn) {
9048
9121
  throw new ConfigError(connectionNotFoundMessage(connectionName, Object.keys(config.connections)));
9049
9122
  }
9050
9123
  const { permission, envFile, environment, ...connectionFields } = conn;
@@ -9062,7 +9135,7 @@ async function loadConnectionEnv(resolved, basePath) {
9062
9135
  await loadEnvFile(envPath);
9063
9136
  }
9064
9137
  }
9065
- async function readV2Config(path) {
9138
+ async function readV2ConfigDocument(path) {
9066
9139
  const storagePath = await resolveConfigStoragePath(path);
9067
9140
  const configPath = join7(storagePath, "config.json");
9068
9141
  const file = Bun.file(configPath);
@@ -9072,8 +9145,10 @@ async function readV2Config(path) {
9072
9145
  await assertAgentReadableFile(configPath);
9073
9146
  const content = await file.text();
9074
9147
  await assertConfigIntegrity(storagePath, content, { requireRecord: true });
9075
- const raw = JSON.parse(content);
9076
- return DbcliConfigV2Schema.parse(raw);
9148
+ return JSON.parse(content);
9149
+ }
9150
+ async function readV2Config(path) {
9151
+ return DbcliConfigV2Schema.parse(await readV2ConfigDocument(path));
9077
9152
  }
9078
9153
  async function writeV2Config(path, config) {
9079
9154
  assertConfigMutationApproved();
@@ -9104,18 +9179,20 @@ function envVarNameFor(connName, field) {
9104
9179
  return `DBCLI_${slug}_${field.toUpperCase()}`;
9105
9180
  }
9106
9181
  function removeConnection(config, name) {
9107
- if (!(name in config.connections))
9182
+ if (!Object.hasOwn(config.connections, name))
9108
9183
  throw new Error(`\u9023\u7DDA '${name}' \u4E0D\u5B58\u5728`);
9109
9184
  const rest = { ...config.connections };
9110
9185
  delete rest[name];
9111
9186
  const remaining = Object.keys(rest);
9112
9187
  if (remaining.length === 0)
9113
9188
  throw new Error("\u7121\u6CD5\u522A\u9664\u6700\u5F8C\u4E00\u689D\u9023\u7DDA");
9114
- const nextDefault = config.default === name ? remaining[0] : config.default;
9115
- return { ...config, connections: rest, default: nextDefault };
9189
+ const updated = { ...config, connections: rest };
9190
+ if (config.default === name)
9191
+ delete updated.default;
9192
+ return updated;
9116
9193
  }
9117
9194
  function setDefaultConnection(config, name) {
9118
- if (!(name in config.connections))
9195
+ if (!Object.hasOwn(config.connections, name))
9119
9196
  throw new Error(`\u9023\u7DDA '${name}' \u4E0D\u5B58\u5728`);
9120
9197
  return { ...config, default: name };
9121
9198
  }
@@ -9240,15 +9317,11 @@ async function resolvePasswordTarget(projectPath, connectionName) {
9240
9317
  };
9241
9318
  }
9242
9319
  const config = await readV2Config(projectPath);
9243
- const targetName = connectionName ?? config.default;
9244
- const connection = config.connections[targetName];
9245
- if (!connection) {
9246
- throw new ConfigError(connectionNotFoundMessage(targetName, Object.keys(config.connections)));
9247
- }
9320
+ const { name: targetName, connection, envFile } = resolveConnection(config, connectionName);
9248
9321
  const referencedVar = envRefName(connection.password);
9249
9322
  return {
9250
9323
  connection: targetName,
9251
- envFile: connection.envFile ?? DEFAULT_ENV_FILE,
9324
+ envFile: envFile ?? DEFAULT_ENV_FILE,
9252
9325
  varName: referencedVar ?? envVarNameFor(targetName, "password"),
9253
9326
  convertedToEnvRef: referencedVar === undefined
9254
9327
  };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbcli-agent",
3
- "version": "9.1.2",
3
+ "version": "11.0.0",
4
4
  "description": "Database CLI skill and command reference for AI agents.",
5
5
  "contextFileName": "AGENTS.md"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carllee1983/dbcli",
3
- "version": "9.1.2",
3
+ "version": "11.0.0",
4
4
  "description": "Database CLI for AI agents",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -41,7 +41,7 @@
41
41
  "blacklist"
42
42
  ],
43
43
  "engines": {
44
- "bun": ">=1.3.3"
44
+ "bun": ">=1.4.0"
45
45
  },
46
46
  "files": [
47
47
  "dist/",
@@ -100,6 +100,7 @@
100
100
  "lru-cache": "^11.4.0",
101
101
  "lucide-react": "^1.16.0",
102
102
  "mongodb": "^7.2.0",
103
+ "mongodb-connection-string-url": "^7.0.1",
103
104
  "mysql2": "^3.24.3",
104
105
  "node-sql-parser": "5",
105
106
  "open": "^11.0.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbcli-agent",
3
- "version": "9.1.2",
3
+ "version": "11.0.0",
4
4
  "description": "Database CLI skill and command reference for AI agents",
5
5
  "author": {
6
6
  "name": "Carl Lee",