@carllee1983/dbcli 1.45.1 → 1.46.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/core.d.ts CHANGED
@@ -29,6 +29,12 @@ export interface ConnectionOptions {
29
29
  uri?: string;
30
30
  /** MongoDB auth database — used when building URI from host/port/user/password (default: 'admin') */
31
31
  authSource?: string;
32
+ /** MongoDB replica set name (optional, field-based config) */
33
+ replicaSet?: string;
34
+ /** MongoDB TLS switch (optional, field-based config; implied true when srv) */
35
+ tls?: boolean;
36
+ /** MongoDB SRV lookup — build a mongodb+srv:// URI from host (optional, field-based config) */
37
+ srv?: boolean;
32
38
  /** Connection timeout in milliseconds (default: 5000) */
33
39
  timeout?: number;
34
40
  /** Elasticsearch protocol (http or https) */
@@ -430,6 +436,16 @@ interface MongoDBConnectionConfig {
430
436
  database: string | {
431
437
  $env: string;
432
438
  };
439
+ /** Auth database; defaults to 'admin' when credentials are present */
440
+ authSource?: string | {
441
+ $env: string;
442
+ };
443
+ replicaSet?: string | {
444
+ $env: string;
445
+ };
446
+ tls?: boolean;
447
+ /** Build a mongodb+srv:// URI from host and expand it via DNS SRV lookup */
448
+ srv?: boolean;
433
449
  }
434
450
  interface RedisConnectionConfig {
435
451
  system: "redis";
@@ -804,6 +820,28 @@ declare const DbcliConfigSchema: z.ZodObject<{
804
820
  $env: string;
805
821
  }>
806
822
  ]>>>;
823
+ authSource: z.ZodOptional<z.ZodUnion<[
824
+ z.ZodString,
825
+ z.ZodObject<{
826
+ $env: z.ZodString;
827
+ }, "strict", z.ZodTypeAny, {
828
+ $env: string;
829
+ }, {
830
+ $env: string;
831
+ }>
832
+ ]>>;
833
+ replicaSet: z.ZodOptional<z.ZodUnion<[
834
+ z.ZodString,
835
+ z.ZodObject<{
836
+ $env: z.ZodString;
837
+ }, "strict", z.ZodTypeAny, {
838
+ $env: string;
839
+ }, {
840
+ $env: string;
841
+ }>
842
+ ]>>;
843
+ tls: z.ZodOptional<z.ZodBoolean>;
844
+ srv: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
807
845
  }, "strip", z.ZodTypeAny, {
808
846
  password: string | {
809
847
  $env: string;
@@ -821,6 +859,14 @@ declare const DbcliConfigSchema: z.ZodObject<{
821
859
  database: string | {
822
860
  $env: string;
823
861
  };
862
+ srv: boolean;
863
+ authSource?: string | {
864
+ $env: string;
865
+ } | undefined;
866
+ replicaSet?: string | {
867
+ $env: string;
868
+ } | undefined;
869
+ tls?: boolean | undefined;
824
870
  uri?: string | {
825
871
  $env: string;
826
872
  } | undefined;
@@ -841,6 +887,14 @@ declare const DbcliConfigSchema: z.ZodObject<{
841
887
  database?: string | {
842
888
  $env: string;
843
889
  } | undefined;
890
+ authSource?: string | {
891
+ $env: string;
892
+ } | undefined;
893
+ replicaSet?: string | {
894
+ $env: string;
895
+ } | undefined;
896
+ tls?: boolean | undefined;
897
+ srv?: boolean | undefined;
844
898
  uri?: string | {
845
899
  $env: string;
846
900
  } | undefined;
@@ -1183,6 +1237,14 @@ declare const DbcliConfigSchema: z.ZodObject<{
1183
1237
  database: string | {
1184
1238
  $env: string;
1185
1239
  };
1240
+ srv: boolean;
1241
+ authSource?: string | {
1242
+ $env: string;
1243
+ } | undefined;
1244
+ replicaSet?: string | {
1245
+ $env: string;
1246
+ } | undefined;
1247
+ tls?: boolean | undefined;
1186
1248
  uri?: string | {
1187
1249
  $env: string;
1188
1250
  } | undefined;
@@ -1273,6 +1335,14 @@ declare const DbcliConfigSchema: z.ZodObject<{
1273
1335
  database?: string | {
1274
1336
  $env: string;
1275
1337
  } | undefined;
1338
+ authSource?: string | {
1339
+ $env: string;
1340
+ } | undefined;
1341
+ replicaSet?: string | {
1342
+ $env: string;
1343
+ } | undefined;
1344
+ tls?: boolean | undefined;
1345
+ srv?: boolean | undefined;
1276
1346
  uri?: string | {
1277
1347
  $env: string;
1278
1348
  } | undefined;
@@ -1540,6 +1610,28 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
1540
1610
  $env: string;
1541
1611
  }>
1542
1612
  ]>>>;
1613
+ authSource: z.ZodOptional<z.ZodUnion<[
1614
+ z.ZodString,
1615
+ z.ZodObject<{
1616
+ $env: z.ZodString;
1617
+ }, "strict", z.ZodTypeAny, {
1618
+ $env: string;
1619
+ }, {
1620
+ $env: string;
1621
+ }>
1622
+ ]>>;
1623
+ replicaSet: z.ZodOptional<z.ZodUnion<[
1624
+ z.ZodString,
1625
+ z.ZodObject<{
1626
+ $env: z.ZodString;
1627
+ }, "strict", z.ZodTypeAny, {
1628
+ $env: string;
1629
+ }, {
1630
+ $env: string;
1631
+ }>
1632
+ ]>>;
1633
+ tls: z.ZodOptional<z.ZodBoolean>;
1634
+ srv: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
1543
1635
  } & {
1544
1636
  permission: z.ZodDefault<z.ZodEnum<[
1545
1637
  "query-only",
@@ -1566,7 +1658,15 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
1566
1658
  database: string | {
1567
1659
  $env: string;
1568
1660
  };
1661
+ srv: boolean;
1569
1662
  permission: "admin" | "query-only" | "read-write" | "data-admin";
1663
+ authSource?: string | {
1664
+ $env: string;
1665
+ } | undefined;
1666
+ replicaSet?: string | {
1667
+ $env: string;
1668
+ } | undefined;
1669
+ tls?: boolean | undefined;
1570
1670
  uri?: string | {
1571
1671
  $env: string;
1572
1672
  } | undefined;
@@ -1589,6 +1689,14 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
1589
1689
  database?: string | {
1590
1690
  $env: string;
1591
1691
  } | undefined;
1692
+ authSource?: string | {
1693
+ $env: string;
1694
+ } | undefined;
1695
+ replicaSet?: string | {
1696
+ $env: string;
1697
+ } | undefined;
1698
+ tls?: boolean | undefined;
1699
+ srv?: boolean | undefined;
1592
1700
  uri?: string | {
1593
1701
  $env: string;
1594
1702
  } | undefined;
@@ -1884,7 +1992,15 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
1884
1992
  database: string | {
1885
1993
  $env: string;
1886
1994
  };
1995
+ srv: boolean;
1887
1996
  permission: "admin" | "query-only" | "read-write" | "data-admin";
1997
+ authSource?: string | {
1998
+ $env: string;
1999
+ } | undefined;
2000
+ replicaSet?: string | {
2001
+ $env: string;
2002
+ } | undefined;
2003
+ tls?: boolean | undefined;
1888
2004
  uri?: string | {
1889
2005
  $env: string;
1890
2006
  } | undefined;
@@ -1977,6 +2093,14 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
1977
2093
  database?: string | {
1978
2094
  $env: string;
1979
2095
  } | undefined;
2096
+ authSource?: string | {
2097
+ $env: string;
2098
+ } | undefined;
2099
+ replicaSet?: string | {
2100
+ $env: string;
2101
+ } | undefined;
2102
+ tls?: boolean | undefined;
2103
+ srv?: boolean | undefined;
1980
2104
  uri?: string | {
1981
2105
  $env: string;
1982
2106
  } | undefined;
@@ -2167,7 +2291,15 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
2167
2291
  database: string | {
2168
2292
  $env: string;
2169
2293
  };
2294
+ srv: boolean;
2170
2295
  permission: "admin" | "query-only" | "read-write" | "data-admin";
2296
+ authSource?: string | {
2297
+ $env: string;
2298
+ } | undefined;
2299
+ replicaSet?: string | {
2300
+ $env: string;
2301
+ } | undefined;
2302
+ tls?: boolean | undefined;
2171
2303
  uri?: string | {
2172
2304
  $env: string;
2173
2305
  } | undefined;
@@ -2271,6 +2403,14 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
2271
2403
  database?: string | {
2272
2404
  $env: string;
2273
2405
  } | undefined;
2406
+ authSource?: string | {
2407
+ $env: string;
2408
+ } | undefined;
2409
+ replicaSet?: string | {
2410
+ $env: string;
2411
+ } | undefined;
2412
+ tls?: boolean | undefined;
2413
+ srv?: boolean | undefined;
2274
2414
  uri?: string | {
2275
2415
  $env: string;
2276
2416
  } | undefined;
@@ -2411,7 +2551,15 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
2411
2551
  database: string | {
2412
2552
  $env: string;
2413
2553
  };
2554
+ srv: boolean;
2414
2555
  permission: "admin" | "query-only" | "read-write" | "data-admin";
2556
+ authSource?: string | {
2557
+ $env: string;
2558
+ } | undefined;
2559
+ replicaSet?: string | {
2560
+ $env: string;
2561
+ } | undefined;
2562
+ tls?: boolean | undefined;
2415
2563
  uri?: string | {
2416
2564
  $env: string;
2417
2565
  } | undefined;
@@ -2515,6 +2663,14 @@ declare const DbcliConfigV2Schema: z.ZodEffects<z.ZodObject<{
2515
2663
  database?: string | {
2516
2664
  $env: string;
2517
2665
  } | undefined;
2666
+ authSource?: string | {
2667
+ $env: string;
2668
+ } | undefined;
2669
+ replicaSet?: string | {
2670
+ $env: string;
2671
+ } | undefined;
2672
+ tls?: boolean | undefined;
2673
+ srv?: boolean | undefined;
2518
2674
  uri?: string | {
2519
2675
  $env: string;
2520
2676
  } | undefined;
package/dist/core.mjs CHANGED
@@ -15022,12 +15022,40 @@ class MongoDBAdapter {
15022
15022
  buildUri() {
15023
15023
  if (this.options.uri)
15024
15024
  return this.options.uri;
15025
- const { user, password, host, port, database, authSource } = this.options;
15026
- if (user && password) {
15027
- const auth = authSource ?? "admin";
15028
- return `mongodb://${user}:${encodeURIComponent(password)}@${host}:${port}/${database}?authSource=${auth}`;
15025
+ const { user, password, host, port, database, authSource, replicaSet, tls, srv } = this.options;
15026
+ if (!host) {
15027
+ throw new ConnectionError("UNKNOWN", "MongoDB host \u672A\u8A2D\u5B9A", [
15028
+ "\u8ACB\u586B\u5BEB host\uFF0C\u6216\u6539\u7528 uri \u6B04\u4F4D\u6307\u5B9A\u5B8C\u6574\u9023\u7DDA\u5B57\u4E32"
15029
+ ]);
15030
+ }
15031
+ const isBracketedIpv6 = /^\[[0-9a-f:]+\]$/i.test(host);
15032
+ if (!isBracketedIpv6 && /[/@?#:\s\\]/.test(host)) {
15033
+ throw new ConnectionError("UNKNOWN", `MongoDB host \u542B\u6709\u975E\u6CD5\u5B57\u5143: ${host}`, [
15034
+ "host \u53EA\u61C9\u5305\u542B\u4E3B\u6A5F\u540D\u7A31\u6216 IP\uFF0C\u4E0D\u8981\u542B /\u3001@\u3001?\u3001#\u3001: \u6216\u7A7A\u767D",
15035
+ "\u57E0\u865F\u8ACB\u586B\u5728 port \u6B04\u4F4D\uFF0C\u4E0D\u8981\u4F75\u9032 host",
15036
+ "IPv6 \u4F4D\u5740\u8ACB\u52A0\u65B9\u62EC\u865F\uFF0C\u4F8B\u5982 [::1]",
15037
+ "\u82E5\u8981\u6307\u5B9A\u5B8C\u6574\u9023\u7DDA\u5B57\u4E32\uFF0C\u8ACB\u6539\u7528 uri \u6B04\u4F4D"
15038
+ ]);
15039
+ }
15040
+ if (user && !password) {
15041
+ throw new ConnectionError("UNKNOWN", "\u5DF2\u6307\u5B9A user \u4F46\u672A\u63D0\u4F9B password", [
15042
+ '\u8ACB\u88DC\u4E0A password\uFF0C\u6216\u6539\u7528\u74B0\u5883\u8B8A\u6578\u53C3\u7167 {"$env": "..."}',
15043
+ "\u82E5\u78BA\u5B9A\u8981\u4EE5\u7121\u8A8D\u8B49\u65B9\u5F0F\u9023\u7DDA\uFF0C\u8ACB\u4E00\u4F75\u6E05\u7A7A user"
15044
+ ]);
15029
15045
  }
15030
- return `mongodb://${host}:${port}/${database}`;
15046
+ const userInfo = user ? `${encodeURIComponent(user)}:${encodeURIComponent(password)}@` : "";
15047
+ const scheme = srv ? "mongodb+srv://" : "mongodb://";
15048
+ const authority = srv ? host : `${host}:${port}`;
15049
+ const path = database ? `/${encodeURIComponent(database)}` : "/";
15050
+ const query = new URLSearchParams;
15051
+ if (user)
15052
+ query.set("authSource", authSource || "admin");
15053
+ if (replicaSet)
15054
+ query.set("replicaSet", replicaSet);
15055
+ if (tls !== undefined)
15056
+ query.set("tls", String(tls));
15057
+ const search = query.toString();
15058
+ return `${scheme}${userInfo}${authority}${path}${search ? `?${search}` : ""}`;
15031
15059
  }
15032
15060
  parseTxtRecords(records) {
15033
15061
  const combined = records.flat().map((record) => record.replace(/^"|"$/g, "")).join("&");
@@ -15089,13 +15117,11 @@ class MongoDBAdapter {
15089
15117
  return this.parseTxtRecords(payload.Answer.map((answer) => [answer.data]));
15090
15118
  }
15091
15119
  async buildResolvedUri() {
15092
- if (!this.options.uri) {
15093
- return this.buildUri();
15094
- }
15095
- if (!this.options.uri.startsWith("mongodb+srv://")) {
15096
- return this.options.uri;
15120
+ const canonical = this.buildUri();
15121
+ if (!canonical.startsWith("mongodb+srv://")) {
15122
+ return canonical;
15097
15123
  }
15098
- const url = new URL(this.options.uri);
15124
+ const url = new URL(canonical);
15099
15125
  const hosts = await this.resolveSrvHosts(url.hostname);
15100
15126
  const txtOptions = await this.resolveTxtOptions(url.hostname);
15101
15127
  const query = new URLSearchParams(url.searchParams);
@@ -15115,6 +15141,37 @@ class MongoDBAdapter {
15115
15141
  const search = query.toString();
15116
15142
  return `mongodb://${userInfo}${hosts.join(",")}${path}${search ? `?${search}` : ""}`;
15117
15143
  }
15144
+ connectionHints(error, message) {
15145
+ const AUTH_HINTS = [
15146
+ "\u8A8D\u8B49\u5931\u6557\uFF1A\u8ACB\u78BA\u8A8D user / password \u6B63\u78BA",
15147
+ "\u8ACB\u78BA\u8A8D authSource \u6307\u5411\u5B58\u653E\u8A72\u5E33\u865F\u7684\u8CC7\u6599\u5EAB\uFF08Atlas \u8207\u591A\u6578\u81EA\u67B6\u74B0\u5883\u70BA admin\uFF09"
15148
+ ];
15149
+ const DNS_HINTS = [
15150
+ "DNS/SRV \u89E3\u6790\u5931\u6557\uFF1A\u8ACB\u78BA\u8A8D host \u70BA SRV \u7DB2\u57DF\uFF0C\u4E14 srv \u8A2D\u5B9A\u8207\u5B83\u4E00\u81F4",
15151
+ "\u82E5\u8A72\u4E3B\u6A5F\u4E0D\u662F SRV \u7DB2\u57DF\uFF0C\u8ACB\u95DC\u9589 srv \u4E26\u6539\u586B host \u8207 port",
15152
+ "\u8ACB\u78BA\u8A8D\u672C\u6A5F DNS \u6216\u7DB2\u8DEF\uFF08VPN\u3001\u516C\u53F8\u7DB2\u8DEF\uFF09\u5141\u8A31 SRV \u67E5\u8A62"
15153
+ ];
15154
+ const TLS_HINTS = [
15155
+ "TLS \u63E1\u624B\u5931\u6557\uFF1A\u8ACB\u78BA\u8A8D tls \u6B04\u4F4D\u8A2D\u5B9A\u8207\u4F3A\u670D\u5668\u4E00\u81F4",
15156
+ "\u81EA\u7C3D\u6191\u8B49\u74B0\u5883\u9700\u8981\u5728\u4F3A\u670D\u5668\u7AEF\u6216\u7CFB\u7D71\u4FE1\u4EFB\u93C8\u4E2D\u5B89\u88DD CA \u6191\u8B49"
15157
+ ];
15158
+ const err = error;
15159
+ const causeCode = String(err?.cause?.code ?? err?.code ?? "");
15160
+ if (err?.code === 18 || err?.codeName === "AuthenticationFailed")
15161
+ return AUTH_HINTS;
15162
+ if (["ENOTFOUND", "EAI_AGAIN"].includes(causeCode))
15163
+ return DNS_HINTS;
15164
+ if (causeCode.startsWith("ERR_TLS") || causeCode.startsWith("SELF_SIGNED"))
15165
+ return TLS_HINTS;
15166
+ if (/authentication failed|not authorized|bad auth/i.test(message))
15167
+ return AUTH_HINTS;
15168
+ if (/querySrv|getaddrinfo (ENOTFOUND|EAI_AGAIN)/i.test(message))
15169
+ return DNS_HINTS;
15170
+ if (/unable to verify the first certificate|self.signed certificate|certificate has expired|ERR_TLS/i.test(message)) {
15171
+ return TLS_HINTS;
15172
+ }
15173
+ return ["\u8ACB\u78BA\u8A8D MongoDB \u670D\u52D9\u6B63\u5728\u57F7\u884C", "\u8ACB\u78BA\u8A8D\u9023\u7DDA\u8A2D\u5B9A\uFF08URI \u6216 host/port\uFF09\u6B63\u78BA"];
15174
+ }
15118
15175
  getDatabase() {
15119
15176
  if (!this.client) {
15120
15177
  throw new ConnectionError("UNKNOWN", "\u5C1A\u672A\u9023\u7DDA\uFF0C\u8ACB\u5148\u547C\u53EB connect()", []);
@@ -15130,10 +15187,7 @@ class MongoDBAdapter {
15130
15187
  } catch (err) {
15131
15188
  const message = err.message ?? "Unknown error";
15132
15189
  const code = message.includes("ECONNREFUSED") ? "ECONNREFUSED" : message.includes("ETIMEDOUT") ? "ETIMEDOUT" : "UNKNOWN";
15133
- throw new ConnectionError(code, `MongoDB \u9023\u7DDA\u5931\u6557: ${message}`, [
15134
- "\u8ACB\u78BA\u8A8D MongoDB \u670D\u52D9\u6B63\u5728\u57F7\u884C",
15135
- "\u8ACB\u78BA\u8A8D\u9023\u7DDA\u8A2D\u5B9A\uFF08URI \u6216 host/port\uFF09\u6B63\u78BA"
15136
- ]);
15190
+ throw new ConnectionError(code, `MongoDB \u9023\u7DDA\u5931\u6557: ${message}`, this.connectionHints(err, message));
15137
15191
  }
15138
15192
  }
15139
15193
  async disconnect() {
@@ -21804,7 +21858,11 @@ var MongoDBConnectionConfigSchema = exports_external.object({
21804
21858
  port: OptNumberOrEnvRef,
21805
21859
  user: OptStringOrEnvRef,
21806
21860
  password: OptStringOrEnvRef,
21807
- database: OptStringOrEnvRef
21861
+ database: OptStringOrEnvRef,
21862
+ authSource: exports_external.union([exports_external.string(), EnvRefSchema]).optional(),
21863
+ replicaSet: exports_external.union([exports_external.string(), EnvRefSchema]).optional(),
21864
+ tls: exports_external.boolean().optional(),
21865
+ srv: exports_external.boolean().optional().default(false)
21808
21866
  });
21809
21867
  var SqlConnectionConfigSchema = exports_external.object({
21810
21868
  system: exports_external.enum(["postgresql", "mysql", "mariadb"]),
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbcli-agent",
3
- "version": "1.45.1",
3
+ "version": "1.46.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": "1.45.1",
3
+ "version": "1.46.0",
4
4
  "description": "Database CLI for AI agents",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbcli-agent",
3
- "version": "1.45.1",
3
+ "version": "1.46.0",
4
4
  "description": "Database CLI skill and command reference for AI agents",
5
5
  "author": {
6
6
  "name": "Carl Lee",
@@ -229,11 +229,13 @@ dbcli init --system postgresql --host localhost --port 5432 \
229
229
  # Reuse an existing .env (DATABASE_URL=postgresql://user:pw@host:5432/db)
230
230
  dbcli init # parses .env in cwd
231
231
 
232
- # MongoDB — full URI (Atlas / replica sets / authSource)
232
+ # MongoDB — field-by-field (no auth = omit --user/--password)
233
+ dbcli init --system mongodb --host localhost --port 27017 --name mydb
234
+ dbcli init --system mongodb --host localhost --port 27017 \
235
+ --user admin --password '<secret>' --auth-source admin --name mydb
236
+ # MongoDB — full URI (advanced escape hatch: multi-host, non-standard driver options)
233
237
  dbcli init --system mongodb \
234
238
  --uri "mongodb+srv://user:pw@cluster.example.mongodb.net/mydb?authSource=admin"
235
- # MongoDB — discrete params (no auth = omit --user/--password)
236
- dbcli init --system mongodb --host localhost --port 27017 --name mydb
237
239
 
238
240
  # Redis — `--name` is the LOGICAL DB INDEX ("0".."15"), not a database name
239
241
  dbcli init --system redis --host localhost --port 6379 --password '<secret>' --name 0
@@ -301,10 +303,25 @@ as a `$env` ref. In a **non-interactive / CI** run you **must** pass all five `-
301
303
  flags; otherwise `init` exits with an error — it never silently falls back to plaintext.
302
304
  `--env-file <path>` is the path to the env file, independent of the `$env` key names.
303
305
 
306
+ **MongoDB is the exception**: only `--env-host` is required non-interactively.
307
+ `--env-port` / `--env-user` / `--env-password` / `--env-database` are optional — an
308
+ omitted one is written as a literal value (empty string for `user` / `password`, the
309
+ resolved value for `port` / `database`) instead of an `$env` ref, so a field the
310
+ connection never needed doesn't later fail closed on an undefined variable. `init`
311
+ also skips the connection test in this mode regardless of `--skip-test` — the `$env`
312
+ refs have no value to connect with yet.
313
+
304
314
  ### Common gotchas
305
315
 
306
316
  - **MongoDB `mongodb+srv://`** — `dbcli doctor` reports whether SRV resolves
307
317
  natively or via the DoH fallback; useful when the runtime restricts DNS.
318
+ - **MongoDB `authSource` / `replicaSet` / `tls` / `srv`** — `init` asks for
319
+ these interactively (`authSource` only when a user is set; `replicaSet` /
320
+ `tls` behind an "advanced options?" prompt); `--auth-source <db>` is the
321
+ only one with a dedicated non-interactive flag, so set `replicaSet` / `tls`
322
+ interactively or edit `.dbcli` afterward. If a config has both `uri` and
323
+ per-field values, `uri` wins silently — `dbcli doctor` flags this and also
324
+ warns when `srv: true` is combined with a non-default `port`.
308
325
  - **MySQL/Postgres password with `@` `:` `/`** — when using `DATABASE_URL`,
309
326
  percent-encode (`@` → `%40`); discrete `--password` flags do not need encoding.
310
327
  - **Redis `--name`** — accepts only the logical DB index string; non-numeric
@@ -32,10 +32,11 @@ dbcli init --system mysql --host localhost --port 3306 --user root --name mydb
32
32
  dbcli init --use-env-refs # Store env var references
33
33
  dbcli init --no-interactive --force # Non-interactive mode
34
34
 
35
- # MongoDB
36
- dbcli init --system mongodb --uri "mongodb://user:pass@host:27017/mydb?authSource=admin"
37
- dbcli init --system mongodb --host localhost --port 27017 --user admin --password secret --name mydb
35
+ # MongoDB — field-by-field (primary path, same shape as SQL)
36
+ dbcli init --system mongodb --host localhost --port 27017 --user admin --password secret --auth-source admin --name mydb
38
37
  dbcli init --system mongodb --host localhost --port 27017 --name mydb # No auth
38
+ # MongoDB — full URI (advanced fallback: multi-host, non-standard driver options)
39
+ dbcli init --system mongodb --uri "mongodb://user:pass@host:27017/mydb?authSource=admin"
39
40
 
40
41
  # Redis (database = logical DB index)
41
42
  dbcli init --system redis --host localhost --port 6379
@@ -62,7 +63,7 @@ dbcli --global use --list
62
63
 
63
64
  **Environment-reference options:** `--env-host <var>`, `--env-port <var>`, `--env-user <var>`, `--env-password <var>`, `--env-database <var>`
64
65
 
65
- **MongoDB-specific options:** `--uri <uri>` (full connection URI), `--auth-source <db>` (auth database, default: `admin` when user/password set)
66
+ **MongoDB-specific options:** `--uri <uri>` (full connection URI — advanced fallback), `--auth-source <db>` (auth database, default: `admin` when user/password set). Interactive `init` also asks for `replicaSet` and `tls` under an "advanced options?" prompt; there is no dedicated non-interactive flag for either yet — set them interactively or edit `.dbcli` afterward. `srv` (boolean, builds `mongodb+srv://` and resolves hosts via DNS SRV, ignoring `port`) is asked right after `host`, before `port`, since it decides whether `port` is even relevant.
66
67
 
67
68
  **Elasticsearch-specific options:** `--cloud-id <id>` (Elastic Cloud), `--api-key <key>` (ApiKey auth). Other ES fields (`nodes[]`, `protocol`, `caPath`, `rejectUnauthorized`) can be edited directly in `.dbcli`.
68
69
 
@@ -2025,7 +2026,9 @@ dbcli doctor --format json # JSON output for AI agents
2025
2026
  - Configuration: config file exists/valid, permission level, blacklist completeness (detects unprotected sensitive columns)
2026
2027
  - Connection & Data: database connectivity, schema cache freshness (warns if > 7 days), large table warnings (> 1M rows)
2027
2028
 
2028
- > **MongoDB SRV diagnostics:** When the active connection uses `mongodb+srv://`, `doctor` reports whether the current runtime can resolve SRV records directly or only through the DNS-over-HTTPS fallback used by dbcli. This helps spot execution-environment DNS restrictions even when Compass can connect.
2029
+ > **MongoDB SRV diagnostics:** When the active connection uses `mongodb+srv://` (via a full `uri` or the per-field `srv: true`), `doctor` reports whether the current runtime can resolve SRV records directly or only through the DNS-over-HTTPS fallback used by dbcli. This helps spot execution-environment DNS restrictions even when Compass can connect.
2030
+
2031
+ > **MongoDB connection-field warnings:** `doctor` also warns when a config has both `uri` and per-field values (`host` / `user`) present — `uri` silently wins and the per-field values are ignored — and when `srv: true` is combined with a non-default `port`, since SRV records carry their own ports.
2029
2032
 
2030
2033
  **Exit code:** 0 if all pass or warnings only, 1 if any error
2031
2034
  **Options:** `--format <text|json>`, `--remediation`
@@ -2600,7 +2603,7 @@ Parser behaviour (`src/core/saved-queries/parser.ts::normaliseVisual`):
2600
2603
 
2601
2604
  MongoDB connections use a JSON-based query model instead of SQL. Treat MongoDB support as a narrower document-database path, not as a full SQL feature equivalent.
2602
2605
 
2603
- Atlas-style `mongodb+srv://` URIs are supported. `list` and `query` run against the database configured for the connection, and `query` always requires `--collection <name>`.
2606
+ `init --system mongodb` defaults to a field-by-field wizard (`host`, `srv`, `port`, `user`, `password` + `authSource`, then optional `replicaSet` / `tls`); a full `uri` is an explicit advanced choice in the interactive flow and the unchanged non-interactive path via `--uri`. Optional fields `authSource`, `replicaSet`, `tls`, and `srv` express what previously required embedding options in the `uri` query string. Atlas-style `mongodb+srv://` URIs are supported both as a full `uri` and via the per-field `srv: true` option. `list` and `query` run against the database configured for the connection, and `query` always requires `--collection <name>`.
2604
2607
 
2605
2608
  **Supported commands:** `init`, `use`, `list`, `schema`, `query`, `q`, `insert`, `update`, `delete`, `export`, `status`, `shell`, `doctor`, `upgrade`, `completion`
2606
2609
 
@@ -2623,7 +2626,10 @@ Atlas-style `mongodb+srv://` URIs are supported. `list` and `query` run against
2623
2626
  ### MongoDB-specific workflow
2624
2627
 
2625
2628
  ```bash
2626
- # 1. Initialize (URI or individual params)
2629
+ # 1. Initialize field-by-field (primary path)
2630
+ dbcli init --system mongodb --host localhost --port 27017 \
2631
+ --user admin --password '<secret>' --auth-source admin --name mydb
2632
+ # ...or a full URI (advanced fallback, e.g. Atlas SRV clusters)
2627
2633
  dbcli init --system mongodb --uri "mongodb+srv://user:pass@cluster.example.mongodb.net/mydb"
2628
2634
 
2629
2635
  # 2. List collections
@@ -229,11 +229,13 @@ dbcli init --system postgresql --host localhost --port 5432 \
229
229
  # Reuse an existing .env (DATABASE_URL=postgresql://user:pw@host:5432/db)
230
230
  dbcli init # parses .env in cwd
231
231
 
232
- # MongoDB — full URI (Atlas / replica sets / authSource)
232
+ # MongoDB — field-by-field (no auth = omit --user/--password)
233
+ dbcli init --system mongodb --host localhost --port 27017 --name mydb
234
+ dbcli init --system mongodb --host localhost --port 27017 \
235
+ --user admin --password '<secret>' --auth-source admin --name mydb
236
+ # MongoDB — full URI (advanced escape hatch: multi-host, non-standard driver options)
233
237
  dbcli init --system mongodb \
234
238
  --uri "mongodb+srv://user:pw@cluster.example.mongodb.net/mydb?authSource=admin"
235
- # MongoDB — discrete params (no auth = omit --user/--password)
236
- dbcli init --system mongodb --host localhost --port 27017 --name mydb
237
239
 
238
240
  # Redis — `--name` is the LOGICAL DB INDEX ("0".."15"), not a database name
239
241
  dbcli init --system redis --host localhost --port 6379 --password '<secret>' --name 0
@@ -301,10 +303,25 @@ as a `$env` ref. In a **non-interactive / CI** run you **must** pass all five `-
301
303
  flags; otherwise `init` exits with an error — it never silently falls back to plaintext.
302
304
  `--env-file <path>` is the path to the env file, independent of the `$env` key names.
303
305
 
306
+ **MongoDB is the exception**: only `--env-host` is required non-interactively.
307
+ `--env-port` / `--env-user` / `--env-password` / `--env-database` are optional — an
308
+ omitted one is written as a literal value (empty string for `user` / `password`, the
309
+ resolved value for `port` / `database`) instead of an `$env` ref, so a field the
310
+ connection never needed doesn't later fail closed on an undefined variable. `init`
311
+ also skips the connection test in this mode regardless of `--skip-test` — the `$env`
312
+ refs have no value to connect with yet.
313
+
304
314
  ### Common gotchas
305
315
 
306
316
  - **MongoDB `mongodb+srv://`** — `dbcli doctor` reports whether SRV resolves
307
317
  natively or via the DoH fallback; useful when the runtime restricts DNS.
318
+ - **MongoDB `authSource` / `replicaSet` / `tls` / `srv`** — `init` asks for
319
+ these interactively (`authSource` only when a user is set; `replicaSet` /
320
+ `tls` behind an "advanced options?" prompt); `--auth-source <db>` is the
321
+ only one with a dedicated non-interactive flag, so set `replicaSet` / `tls`
322
+ interactively or edit `.dbcli` afterward. If a config has both `uri` and
323
+ per-field values, `uri` wins silently — `dbcli doctor` flags this and also
324
+ warns when `srv: true` is combined with a non-default `port`.
308
325
  - **MySQL/Postgres password with `@` `:` `/`** — when using `DATABASE_URL`,
309
326
  percent-encode (`@` → `%40`); discrete `--password` flags do not need encoding.
310
327
  - **Redis `--name`** — accepts only the logical DB index string; non-numeric
@@ -32,10 +32,11 @@ dbcli init --system mysql --host localhost --port 3306 --user root --name mydb
32
32
  dbcli init --use-env-refs # Store env var references
33
33
  dbcli init --no-interactive --force # Non-interactive mode
34
34
 
35
- # MongoDB
36
- dbcli init --system mongodb --uri "mongodb://user:pass@host:27017/mydb?authSource=admin"
37
- dbcli init --system mongodb --host localhost --port 27017 --user admin --password secret --name mydb
35
+ # MongoDB — field-by-field (primary path, same shape as SQL)
36
+ dbcli init --system mongodb --host localhost --port 27017 --user admin --password secret --auth-source admin --name mydb
38
37
  dbcli init --system mongodb --host localhost --port 27017 --name mydb # No auth
38
+ # MongoDB — full URI (advanced fallback: multi-host, non-standard driver options)
39
+ dbcli init --system mongodb --uri "mongodb://user:pass@host:27017/mydb?authSource=admin"
39
40
 
40
41
  # Redis (database = logical DB index)
41
42
  dbcli init --system redis --host localhost --port 6379
@@ -62,7 +63,7 @@ dbcli --global use --list
62
63
 
63
64
  **Environment-reference options:** `--env-host <var>`, `--env-port <var>`, `--env-user <var>`, `--env-password <var>`, `--env-database <var>`
64
65
 
65
- **MongoDB-specific options:** `--uri <uri>` (full connection URI), `--auth-source <db>` (auth database, default: `admin` when user/password set)
66
+ **MongoDB-specific options:** `--uri <uri>` (full connection URI — advanced fallback), `--auth-source <db>` (auth database, default: `admin` when user/password set). Interactive `init` also asks for `replicaSet` and `tls` under an "advanced options?" prompt; there is no dedicated non-interactive flag for either yet — set them interactively or edit `.dbcli` afterward. `srv` (boolean, builds `mongodb+srv://` and resolves hosts via DNS SRV, ignoring `port`) is asked right after `host`, before `port`, since it decides whether `port` is even relevant.
66
67
 
67
68
  **Elasticsearch-specific options:** `--cloud-id <id>` (Elastic Cloud), `--api-key <key>` (ApiKey auth). Other ES fields (`nodes[]`, `protocol`, `caPath`, `rejectUnauthorized`) can be edited directly in `.dbcli`.
68
69
 
@@ -2025,7 +2026,9 @@ dbcli doctor --format json # JSON output for AI agents
2025
2026
  - Configuration: config file exists/valid, permission level, blacklist completeness (detects unprotected sensitive columns)
2026
2027
  - Connection & Data: database connectivity, schema cache freshness (warns if > 7 days), large table warnings (> 1M rows)
2027
2028
 
2028
- > **MongoDB SRV diagnostics:** When the active connection uses `mongodb+srv://`, `doctor` reports whether the current runtime can resolve SRV records directly or only through the DNS-over-HTTPS fallback used by dbcli. This helps spot execution-environment DNS restrictions even when Compass can connect.
2029
+ > **MongoDB SRV diagnostics:** When the active connection uses `mongodb+srv://` (via a full `uri` or the per-field `srv: true`), `doctor` reports whether the current runtime can resolve SRV records directly or only through the DNS-over-HTTPS fallback used by dbcli. This helps spot execution-environment DNS restrictions even when Compass can connect.
2030
+
2031
+ > **MongoDB connection-field warnings:** `doctor` also warns when a config has both `uri` and per-field values (`host` / `user`) present — `uri` silently wins and the per-field values are ignored — and when `srv: true` is combined with a non-default `port`, since SRV records carry their own ports.
2029
2032
 
2030
2033
  **Exit code:** 0 if all pass or warnings only, 1 if any error
2031
2034
  **Options:** `--format <text|json>`, `--remediation`
@@ -2600,7 +2603,7 @@ Parser behaviour (`src/core/saved-queries/parser.ts::normaliseVisual`):
2600
2603
 
2601
2604
  MongoDB connections use a JSON-based query model instead of SQL. Treat MongoDB support as a narrower document-database path, not as a full SQL feature equivalent.
2602
2605
 
2603
- Atlas-style `mongodb+srv://` URIs are supported. `list` and `query` run against the database configured for the connection, and `query` always requires `--collection <name>`.
2606
+ `init --system mongodb` defaults to a field-by-field wizard (`host`, `srv`, `port`, `user`, `password` + `authSource`, then optional `replicaSet` / `tls`); a full `uri` is an explicit advanced choice in the interactive flow and the unchanged non-interactive path via `--uri`. Optional fields `authSource`, `replicaSet`, `tls`, and `srv` express what previously required embedding options in the `uri` query string. Atlas-style `mongodb+srv://` URIs are supported both as a full `uri` and via the per-field `srv: true` option. `list` and `query` run against the database configured for the connection, and `query` always requires `--collection <name>`.
2604
2607
 
2605
2608
  **Supported commands:** `init`, `use`, `list`, `schema`, `query`, `q`, `insert`, `update`, `delete`, `export`, `status`, `shell`, `doctor`, `upgrade`, `completion`
2606
2609
 
@@ -2623,7 +2626,10 @@ Atlas-style `mongodb+srv://` URIs are supported. `list` and `query` run against
2623
2626
  ### MongoDB-specific workflow
2624
2627
 
2625
2628
  ```bash
2626
- # 1. Initialize (URI or individual params)
2629
+ # 1. Initialize field-by-field (primary path)
2630
+ dbcli init --system mongodb --host localhost --port 27017 \
2631
+ --user admin --password '<secret>' --auth-source admin --name mydb
2632
+ # ...or a full URI (advanced fallback, e.g. Atlas SRV clusters)
2627
2633
  dbcli init --system mongodb --uri "mongodb+srv://user:pass@cluster.example.mongodb.net/mydb"
2628
2634
 
2629
2635
  # 2. List collections