@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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor/rules/dbcli.mdc +20 -3
- package/.cursor/skills/dbcli/reference.md +13 -7
- package/.cursor-plugin/plugin.json +1 -1
- package/.github/skills/dbcli/SKILL.md +20 -3
- package/.github/skills/dbcli/reference.md +13 -7
- package/CHANGELOG.md +23 -0
- package/assets/SKILL.md +20 -3
- package/assets/reference.md +13 -7
- package/dist/cli.mjs +475 -272
- package/dist/core.d.ts +156 -0
- package/dist/core.mjs +74 -16
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/plugins/dbcli-agent/.codex-plugin/plugin.json +1 -1
- package/plugins/dbcli-agent/skills/dbcli/SKILL.md +20 -3
- package/plugins/dbcli-agent/skills/dbcli/reference.md +13 -7
- package/skills/dbcli/SKILL.md +20 -3
- package/skills/dbcli/reference.md +13 -7
package/dist/cli.mjs
CHANGED
|
@@ -52,7 +52,7 @@ var package_default;
|
|
|
52
52
|
var init_package = __esm(() => {
|
|
53
53
|
package_default = {
|
|
54
54
|
name: "@carllee1983/dbcli",
|
|
55
|
-
version: "1.
|
|
55
|
+
version: "1.46.0",
|
|
56
56
|
description: "Database CLI for AI agents",
|
|
57
57
|
type: "module",
|
|
58
58
|
publishConfig: {
|
|
@@ -7463,7 +7463,11 @@ var init_validation = __esm(() => {
|
|
|
7463
7463
|
port: OptNumberOrEnvRef,
|
|
7464
7464
|
user: OptStringOrEnvRef,
|
|
7465
7465
|
password: OptStringOrEnvRef,
|
|
7466
|
-
database: OptStringOrEnvRef
|
|
7466
|
+
database: OptStringOrEnvRef,
|
|
7467
|
+
authSource: exports_external.union([exports_external.string(), EnvRefSchema]).optional(),
|
|
7468
|
+
replicaSet: exports_external.union([exports_external.string(), EnvRefSchema]).optional(),
|
|
7469
|
+
tls: exports_external.boolean().optional(),
|
|
7470
|
+
srv: exports_external.boolean().optional().default(false)
|
|
7467
7471
|
});
|
|
7468
7472
|
SqlConnectionConfigSchema = exports_external.object({
|
|
7469
7473
|
system: exports_external.enum(["postgresql", "mysql", "mariadb"]),
|
|
@@ -24355,12 +24359,40 @@ class MongoDBAdapter {
|
|
|
24355
24359
|
buildUri() {
|
|
24356
24360
|
if (this.options.uri)
|
|
24357
24361
|
return this.options.uri;
|
|
24358
|
-
const { user, password, host, port, database, authSource } = this.options;
|
|
24359
|
-
if (
|
|
24360
|
-
|
|
24361
|
-
|
|
24362
|
+
const { user, password, host, port, database, authSource, replicaSet, tls, srv } = this.options;
|
|
24363
|
+
if (!host) {
|
|
24364
|
+
throw new ConnectionError("UNKNOWN", "MongoDB host \u672A\u8A2D\u5B9A", [
|
|
24365
|
+
"\u8ACB\u586B\u5BEB host\uFF0C\u6216\u6539\u7528 uri \u6B04\u4F4D\u6307\u5B9A\u5B8C\u6574\u9023\u7DDA\u5B57\u4E32"
|
|
24366
|
+
]);
|
|
24367
|
+
}
|
|
24368
|
+
const isBracketedIpv6 = /^\[[0-9a-f:]+\]$/i.test(host);
|
|
24369
|
+
if (!isBracketedIpv6 && /[/@?#:\s\\]/.test(host)) {
|
|
24370
|
+
throw new ConnectionError("UNKNOWN", `MongoDB host \u542B\u6709\u975E\u6CD5\u5B57\u5143: ${host}`, [
|
|
24371
|
+
"host \u53EA\u61C9\u5305\u542B\u4E3B\u6A5F\u540D\u7A31\u6216 IP\uFF0C\u4E0D\u8981\u542B /\u3001@\u3001?\u3001#\u3001: \u6216\u7A7A\u767D",
|
|
24372
|
+
"\u57E0\u865F\u8ACB\u586B\u5728 port \u6B04\u4F4D\uFF0C\u4E0D\u8981\u4F75\u9032 host",
|
|
24373
|
+
"IPv6 \u4F4D\u5740\u8ACB\u52A0\u65B9\u62EC\u865F\uFF0C\u4F8B\u5982 [::1]",
|
|
24374
|
+
"\u82E5\u8981\u6307\u5B9A\u5B8C\u6574\u9023\u7DDA\u5B57\u4E32\uFF0C\u8ACB\u6539\u7528 uri \u6B04\u4F4D"
|
|
24375
|
+
]);
|
|
24376
|
+
}
|
|
24377
|
+
if (user && !password) {
|
|
24378
|
+
throw new ConnectionError("UNKNOWN", "\u5DF2\u6307\u5B9A user \u4F46\u672A\u63D0\u4F9B password", [
|
|
24379
|
+
'\u8ACB\u88DC\u4E0A password\uFF0C\u6216\u6539\u7528\u74B0\u5883\u8B8A\u6578\u53C3\u7167 {"$env": "..."}',
|
|
24380
|
+
"\u82E5\u78BA\u5B9A\u8981\u4EE5\u7121\u8A8D\u8B49\u65B9\u5F0F\u9023\u7DDA\uFF0C\u8ACB\u4E00\u4F75\u6E05\u7A7A user"
|
|
24381
|
+
]);
|
|
24362
24382
|
}
|
|
24363
|
-
|
|
24383
|
+
const userInfo = user ? `${encodeURIComponent(user)}:${encodeURIComponent(password)}@` : "";
|
|
24384
|
+
const scheme = srv ? "mongodb+srv://" : "mongodb://";
|
|
24385
|
+
const authority = srv ? host : `${host}:${port}`;
|
|
24386
|
+
const path5 = database ? `/${encodeURIComponent(database)}` : "/";
|
|
24387
|
+
const query = new URLSearchParams;
|
|
24388
|
+
if (user)
|
|
24389
|
+
query.set("authSource", authSource || "admin");
|
|
24390
|
+
if (replicaSet)
|
|
24391
|
+
query.set("replicaSet", replicaSet);
|
|
24392
|
+
if (tls !== undefined)
|
|
24393
|
+
query.set("tls", String(tls));
|
|
24394
|
+
const search = query.toString();
|
|
24395
|
+
return `${scheme}${userInfo}${authority}${path5}${search ? `?${search}` : ""}`;
|
|
24364
24396
|
}
|
|
24365
24397
|
parseTxtRecords(records) {
|
|
24366
24398
|
const combined = records.flat().map((record) => record.replace(/^"|"$/g, "")).join("&");
|
|
@@ -24422,13 +24454,11 @@ class MongoDBAdapter {
|
|
|
24422
24454
|
return this.parseTxtRecords(payload.Answer.map((answer) => [answer.data]));
|
|
24423
24455
|
}
|
|
24424
24456
|
async buildResolvedUri() {
|
|
24425
|
-
|
|
24426
|
-
|
|
24427
|
-
|
|
24428
|
-
if (!this.options.uri.startsWith("mongodb+srv://")) {
|
|
24429
|
-
return this.options.uri;
|
|
24457
|
+
const canonical = this.buildUri();
|
|
24458
|
+
if (!canonical.startsWith("mongodb+srv://")) {
|
|
24459
|
+
return canonical;
|
|
24430
24460
|
}
|
|
24431
|
-
const url = new URL(
|
|
24461
|
+
const url = new URL(canonical);
|
|
24432
24462
|
const hosts = await this.resolveSrvHosts(url.hostname);
|
|
24433
24463
|
const txtOptions = await this.resolveTxtOptions(url.hostname);
|
|
24434
24464
|
const query = new URLSearchParams(url.searchParams);
|
|
@@ -24448,6 +24478,37 @@ class MongoDBAdapter {
|
|
|
24448
24478
|
const search = query.toString();
|
|
24449
24479
|
return `mongodb://${userInfo}${hosts.join(",")}${path5}${search ? `?${search}` : ""}`;
|
|
24450
24480
|
}
|
|
24481
|
+
connectionHints(error, message) {
|
|
24482
|
+
const AUTH_HINTS = [
|
|
24483
|
+
"\u8A8D\u8B49\u5931\u6557\uFF1A\u8ACB\u78BA\u8A8D user / password \u6B63\u78BA",
|
|
24484
|
+
"\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"
|
|
24485
|
+
];
|
|
24486
|
+
const DNS_HINTS = [
|
|
24487
|
+
"DNS/SRV \u89E3\u6790\u5931\u6557\uFF1A\u8ACB\u78BA\u8A8D host \u70BA SRV \u7DB2\u57DF\uFF0C\u4E14 srv \u8A2D\u5B9A\u8207\u5B83\u4E00\u81F4",
|
|
24488
|
+
"\u82E5\u8A72\u4E3B\u6A5F\u4E0D\u662F SRV \u7DB2\u57DF\uFF0C\u8ACB\u95DC\u9589 srv \u4E26\u6539\u586B host \u8207 port",
|
|
24489
|
+
"\u8ACB\u78BA\u8A8D\u672C\u6A5F DNS \u6216\u7DB2\u8DEF\uFF08VPN\u3001\u516C\u53F8\u7DB2\u8DEF\uFF09\u5141\u8A31 SRV \u67E5\u8A62"
|
|
24490
|
+
];
|
|
24491
|
+
const TLS_HINTS = [
|
|
24492
|
+
"TLS \u63E1\u624B\u5931\u6557\uFF1A\u8ACB\u78BA\u8A8D tls \u6B04\u4F4D\u8A2D\u5B9A\u8207\u4F3A\u670D\u5668\u4E00\u81F4",
|
|
24493
|
+
"\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"
|
|
24494
|
+
];
|
|
24495
|
+
const err = error;
|
|
24496
|
+
const causeCode = String(err?.cause?.code ?? err?.code ?? "");
|
|
24497
|
+
if (err?.code === 18 || err?.codeName === "AuthenticationFailed")
|
|
24498
|
+
return AUTH_HINTS;
|
|
24499
|
+
if (["ENOTFOUND", "EAI_AGAIN"].includes(causeCode))
|
|
24500
|
+
return DNS_HINTS;
|
|
24501
|
+
if (causeCode.startsWith("ERR_TLS") || causeCode.startsWith("SELF_SIGNED"))
|
|
24502
|
+
return TLS_HINTS;
|
|
24503
|
+
if (/authentication failed|not authorized|bad auth/i.test(message))
|
|
24504
|
+
return AUTH_HINTS;
|
|
24505
|
+
if (/querySrv|getaddrinfo (ENOTFOUND|EAI_AGAIN)/i.test(message))
|
|
24506
|
+
return DNS_HINTS;
|
|
24507
|
+
if (/unable to verify the first certificate|self.signed certificate|certificate has expired|ERR_TLS/i.test(message)) {
|
|
24508
|
+
return TLS_HINTS;
|
|
24509
|
+
}
|
|
24510
|
+
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"];
|
|
24511
|
+
}
|
|
24451
24512
|
getDatabase() {
|
|
24452
24513
|
if (!this.client) {
|
|
24453
24514
|
throw new ConnectionError("UNKNOWN", "\u5C1A\u672A\u9023\u7DDA\uFF0C\u8ACB\u5148\u547C\u53EB connect()", []);
|
|
@@ -24463,10 +24524,7 @@ class MongoDBAdapter {
|
|
|
24463
24524
|
} catch (err) {
|
|
24464
24525
|
const message = err.message ?? "Unknown error";
|
|
24465
24526
|
const code = message.includes("ECONNREFUSED") ? "ECONNREFUSED" : message.includes("ETIMEDOUT") ? "ETIMEDOUT" : "UNKNOWN";
|
|
24466
|
-
throw new ConnectionError(code, `MongoDB \u9023\u7DDA\u5931\u6557: ${message}`,
|
|
24467
|
-
"\u8ACB\u78BA\u8A8D MongoDB \u670D\u52D9\u6B63\u5728\u57F7\u884C",
|
|
24468
|
-
"\u8ACB\u78BA\u8A8D\u9023\u7DDA\u8A2D\u5B9A\uFF08URI \u6216 host/port\uFF09\u6B63\u78BA"
|
|
24469
|
-
]);
|
|
24527
|
+
throw new ConnectionError(code, `MongoDB \u9023\u7DDA\u5931\u6557: ${message}`, this.connectionHints(err, message));
|
|
24470
24528
|
}
|
|
24471
24529
|
}
|
|
24472
24530
|
async disconnect() {
|
|
@@ -26112,9 +26170,8 @@ var init_adapters = __esm(() => {
|
|
|
26112
26170
|
init_elasticsearch_adapter();
|
|
26113
26171
|
});
|
|
26114
26172
|
|
|
26115
|
-
// src/commands/init.ts
|
|
26173
|
+
// src/commands/init-shared.ts
|
|
26116
26174
|
import { join as join14 } from "path";
|
|
26117
|
-
import { mkdir as mkdir5 } from "fs/promises";
|
|
26118
26175
|
async function checkOverwrite(configPath, shouldPrompt, force) {
|
|
26119
26176
|
const storagePath = await resolveConfigStoragePath(configPath);
|
|
26120
26177
|
const fileExists = await Bun.file(configPath).exists();
|
|
@@ -26132,68 +26189,6 @@ async function checkOverwrite(configPath, shouldPrompt, force) {
|
|
|
26132
26189
|
}
|
|
26133
26190
|
throw new Error(t("init.config_exists_use_force"));
|
|
26134
26191
|
}
|
|
26135
|
-
async function handleRemove(configPath, name2) {
|
|
26136
|
-
const storagePath = await resolveConfigStoragePath(configPath);
|
|
26137
|
-
const configFile = Bun.file(join14(storagePath, "config.json"));
|
|
26138
|
-
if (!await configFile.exists()) {
|
|
26139
|
-
throw new Error(t("init.config_not_found"));
|
|
26140
|
-
}
|
|
26141
|
-
const raw = JSON.parse(await configFile.text());
|
|
26142
|
-
if (detectConfigVersion(raw) !== 2) {
|
|
26143
|
-
throw new Error(t("init.requires_v2_remove"));
|
|
26144
|
-
}
|
|
26145
|
-
const config = await readV2Config(storagePath);
|
|
26146
|
-
if (!config.connections[name2]) {
|
|
26147
|
-
throw new Error(t_vars("init.connection_not_found", { name: name2 }));
|
|
26148
|
-
}
|
|
26149
|
-
const connectionCount = Object.keys(config.connections).length;
|
|
26150
|
-
if (connectionCount <= 1) {
|
|
26151
|
-
throw new Error(t("init.cannot_remove_last"));
|
|
26152
|
-
}
|
|
26153
|
-
const remaining = Object.fromEntries(Object.entries(config.connections).filter(([connectionName]) => connectionName !== name2));
|
|
26154
|
-
const newDefault = config.default === name2 ? Object.keys(remaining)[0] : config.default;
|
|
26155
|
-
const updated = {
|
|
26156
|
-
...config,
|
|
26157
|
-
default: newDefault,
|
|
26158
|
-
connections: remaining
|
|
26159
|
-
};
|
|
26160
|
-
await writeV2Config(storagePath, updated);
|
|
26161
|
-
if (config.default === name2) {
|
|
26162
|
-
console.log(t_vars("init.connection_removed_switched", { name: name2, newDefault }));
|
|
26163
|
-
} else {
|
|
26164
|
-
console.log(t_vars("init.connection_removed", { name: name2 }));
|
|
26165
|
-
}
|
|
26166
|
-
}
|
|
26167
|
-
async function handleRename(configPath, renameArg) {
|
|
26168
|
-
const [oldName, newName] = renameArg.split(":");
|
|
26169
|
-
if (!oldName || !newName) {
|
|
26170
|
-
throw new Error(t("init.rename_invalid_format"));
|
|
26171
|
-
}
|
|
26172
|
-
const storagePath = await resolveConfigStoragePath(configPath);
|
|
26173
|
-
const configFile = Bun.file(join14(storagePath, "config.json"));
|
|
26174
|
-
if (!await configFile.exists()) {
|
|
26175
|
-
throw new Error(t("init.config_not_found"));
|
|
26176
|
-
}
|
|
26177
|
-
const raw = JSON.parse(await configFile.text());
|
|
26178
|
-
if (detectConfigVersion(raw) !== 2) {
|
|
26179
|
-
throw new Error(t("init.requires_v2_rename"));
|
|
26180
|
-
}
|
|
26181
|
-
const config = await readV2Config(storagePath);
|
|
26182
|
-
if (!config.connections[oldName]) {
|
|
26183
|
-
throw new Error(t_vars("init.connection_not_found", { name: oldName }));
|
|
26184
|
-
}
|
|
26185
|
-
if (config.connections[newName]) {
|
|
26186
|
-
throw new Error(t_vars("init.connection_already_exists", { name: newName }));
|
|
26187
|
-
}
|
|
26188
|
-
const entries = Object.entries(config.connections).map(([key, value]) => [key === oldName ? newName : key, value]);
|
|
26189
|
-
const updated = {
|
|
26190
|
-
...config,
|
|
26191
|
-
default: config.default === oldName ? newName : config.default,
|
|
26192
|
-
connections: Object.fromEntries(entries)
|
|
26193
|
-
};
|
|
26194
|
-
await writeV2Config(storagePath, updated);
|
|
26195
|
-
console.log(t_vars("init.connection_renamed", { oldName, newName }));
|
|
26196
|
-
}
|
|
26197
26192
|
async function writeV2InitConfig(configPath, connectionName, connection, permission, envFile) {
|
|
26198
26193
|
const globalConfig = isGlobalConfigPath(configPath);
|
|
26199
26194
|
const storagePath = globalConfig ? configPath : getProjectStoragePath(configPath);
|
|
@@ -26319,6 +26314,270 @@ async function writeV2InitConfig(configPath, connectionName, connection, permiss
|
|
|
26319
26314
|
}
|
|
26320
26315
|
console.log(globalConfig ? t_vars("init.config_saved_global", { path: join14(configPath, "config.json") }) : t("init.config_saved"));
|
|
26321
26316
|
}
|
|
26317
|
+
var init_init_shared = __esm(() => {
|
|
26318
|
+
init_message_loader();
|
|
26319
|
+
init_config();
|
|
26320
|
+
init_config_v2();
|
|
26321
|
+
init_prompts();
|
|
26322
|
+
init_config_binding();
|
|
26323
|
+
});
|
|
26324
|
+
|
|
26325
|
+
// src/commands/init-mongodb.ts
|
|
26326
|
+
import { mkdir as mkdir5 } from "fs/promises";
|
|
26327
|
+
async function handleMongoDBInit(ctx) {
|
|
26328
|
+
const { options, configPath, connectionName, isV2Init, existingConfig } = ctx;
|
|
26329
|
+
const isInteractive = options.interactive !== false && process.stdin.isTTY;
|
|
26330
|
+
const SETUP_MODES = ["\u9010\u6B04\u586B\u5BEB\uFF08\u5EFA\u8B70\uFF09", "\u8CBC\u4E0A\u5B8C\u6574\u9023\u7DDA\u5B57\u4E32\uFF08\u9032\u968E\uFF09"];
|
|
26331
|
+
const URI_MODE_INDEX = 1;
|
|
26332
|
+
const useEnvRefs = Boolean(options.useEnvRefs);
|
|
26333
|
+
let mongoUri = options.uri;
|
|
26334
|
+
let useUriMode = Boolean(mongoUri);
|
|
26335
|
+
if (!mongoUri && isInteractive) {
|
|
26336
|
+
const mode = await promptUser.select("\u9023\u7DDA\u8A2D\u5B9A\u65B9\u5F0F / Connection setup", [...SETUP_MODES]);
|
|
26337
|
+
useUriMode = mode === SETUP_MODES[URI_MODE_INDEX];
|
|
26338
|
+
while (useUriMode && !mongoUri) {
|
|
26339
|
+
const input = await promptUser.text("MongoDB \u9023\u7DDA\u5B57\u4E32 / connection string (mongodb://user:pass@host:27017/db)", "");
|
|
26340
|
+
if (input.trim()) {
|
|
26341
|
+
mongoUri = input.trim();
|
|
26342
|
+
} else {
|
|
26343
|
+
console.log("\u672A\u8F38\u5165\u9023\u7DDA\u5B57\u4E32\uFF0C\u6539\u7528\u9010\u6B04\u586B\u5BEB\u3002");
|
|
26344
|
+
useUriMode = false;
|
|
26345
|
+
}
|
|
26346
|
+
}
|
|
26347
|
+
}
|
|
26348
|
+
const useFieldEnvRefs = useEnvRefs && !useUriMode;
|
|
26349
|
+
if (useEnvRefs && useUriMode) {
|
|
26350
|
+
console.warn("\u26A0\uFE0F --use-env-refs \u4E0D\u9069\u7528\u65BC\u5B8C\u6574\u9023\u7DDA\u5B57\u4E32\uFF1AURI \u6703\u539F\u6A23\u5BEB\u5165\u8A2D\u5B9A\u6A94\uFF0C\u5E33\u5BC6\u4E0D\u6703\u88AB\u62BD\u6210\u74B0\u5883\u8B8A\u6578\u53C3\u7167\u3002");
|
|
26351
|
+
}
|
|
26352
|
+
const fields = {
|
|
26353
|
+
host: options.host || "localhost",
|
|
26354
|
+
port: parseInt(options.port || "27017", 10),
|
|
26355
|
+
user: options.user || "",
|
|
26356
|
+
password: options.password || "",
|
|
26357
|
+
authSource: options.authSource || "",
|
|
26358
|
+
replicaSet: "",
|
|
26359
|
+
tls: undefined,
|
|
26360
|
+
srv: false
|
|
26361
|
+
};
|
|
26362
|
+
const promptPort = async (fallback) => {
|
|
26363
|
+
for (;; ) {
|
|
26364
|
+
const raw = await promptUser.text("Port\uFF08\u57E0\u865F\uFF09", String(fallback));
|
|
26365
|
+
const parsed = parseInt(raw, 10);
|
|
26366
|
+
if (Number.isInteger(parsed) && parsed > 0 && parsed <= 65535)
|
|
26367
|
+
return parsed;
|
|
26368
|
+
console.log("\u8ACB\u8F38\u5165 1-65535 \u7684\u6574\u6578\u3002");
|
|
26369
|
+
}
|
|
26370
|
+
};
|
|
26371
|
+
if (!useUriMode && isInteractive) {
|
|
26372
|
+
if (!useFieldEnvRefs) {
|
|
26373
|
+
fields.host = await promptUser.text("Host\uFF08\u4E3B\u6A5F\u4F4D\u5740\uFF09", fields.host);
|
|
26374
|
+
}
|
|
26375
|
+
fields.srv = await promptUser.confirm("\u9019\u662F SRV \u7DB2\u57DF\u55CE\uFF08Atlas \u7B49 mongodb+srv \u9023\u7DDA\uFF09\uFF1F");
|
|
26376
|
+
if (!fields.srv && !useFieldEnvRefs) {
|
|
26377
|
+
fields.port = await promptPort(fields.port);
|
|
26378
|
+
}
|
|
26379
|
+
if (!useFieldEnvRefs) {
|
|
26380
|
+
fields.user = await promptUser.text("User\uFF08\u5E33\u865F\uFF0C\u7121\u8A8D\u8B49\u8ACB\u7559\u7A7A\uFF09", fields.user);
|
|
26381
|
+
if (fields.user) {
|
|
26382
|
+
fields.password = await promptUser.text("Password\uFF08\u5BC6\u78BC\uFF09", fields.password);
|
|
26383
|
+
fields.authSource = await promptUser.text("authSource\uFF08\u8A8D\u8B49\u8CC7\u6599\u5EAB\uFF09", fields.authSource || "admin");
|
|
26384
|
+
}
|
|
26385
|
+
}
|
|
26386
|
+
if (await promptUser.confirm("\u8A2D\u5B9A\u9032\u968E\u9078\u9805\uFF08replicaSet / tls\uFF09\uFF1F")) {
|
|
26387
|
+
fields.replicaSet = await promptUser.text("replicaSet\uFF08\u8907\u672C\u96C6\u540D\u7A31\uFF0C\u53EF\u7559\u7A7A\uFF09", "");
|
|
26388
|
+
fields.tls = await promptUser.confirm("\u555F\u7528 tls\uFF1F");
|
|
26389
|
+
}
|
|
26390
|
+
}
|
|
26391
|
+
let database = options.name || "";
|
|
26392
|
+
if (!database && isInteractive && !useFieldEnvRefs) {
|
|
26393
|
+
database = await promptUser.text("Database name", "testdb");
|
|
26394
|
+
}
|
|
26395
|
+
const envRefFor = async (flag, label, suggestion) => {
|
|
26396
|
+
const name2 = flag ?? (isInteractive ? await promptUser.text(label, suggestion) : "");
|
|
26397
|
+
return name2.trim() ? { $env: name2.trim() } : null;
|
|
26398
|
+
};
|
|
26399
|
+
let envRefConfig = null;
|
|
26400
|
+
if (useFieldEnvRefs) {
|
|
26401
|
+
const hostRef = await envRefFor(options.envHost, "Host \u7684\u74B0\u5883\u8B8A\u6578\u540D\u7A31", "MONGO_HOST");
|
|
26402
|
+
const portRef = await envRefFor(options.envPort, "Port \u7684\u74B0\u5883\u8B8A\u6578\u540D\u7A31\uFF08\u53EF\u7559\u7A7A\uFF09", "");
|
|
26403
|
+
const userRef = await envRefFor(options.envUser, "User \u7684\u74B0\u5883\u8B8A\u6578\u540D\u7A31\uFF08\u53EF\u7559\u7A7A\uFF09", "");
|
|
26404
|
+
const passwordRef = await envRefFor(options.envPassword, "Password \u7684\u74B0\u5883\u8B8A\u6578\u540D\u7A31\uFF08\u53EF\u7559\u7A7A\uFF09", "");
|
|
26405
|
+
const databaseRef = await envRefFor(options.envDatabase, "Database \u7684\u74B0\u5883\u8B8A\u6578\u540D\u7A31\uFF08\u53EF\u7559\u7A7A\uFF09", "");
|
|
26406
|
+
if (!hostRef) {
|
|
26407
|
+
throw new Error("--use-env-refs \u9700\u8981 host \u7684\u74B0\u5883\u8B8A\u6578\u540D\u7A31\uFF08--env-host\uFF09");
|
|
26408
|
+
}
|
|
26409
|
+
if (!databaseRef && !database && isInteractive) {
|
|
26410
|
+
database = await promptUser.text("Database name", "testdb");
|
|
26411
|
+
}
|
|
26412
|
+
if (!databaseRef && !database) {
|
|
26413
|
+
throw new Error(t("errors.require_name"));
|
|
26414
|
+
}
|
|
26415
|
+
envRefConfig = {
|
|
26416
|
+
system: "mongodb",
|
|
26417
|
+
host: hostRef,
|
|
26418
|
+
port: portRef ?? fields.port,
|
|
26419
|
+
user: userRef ?? "",
|
|
26420
|
+
password: passwordRef ?? "",
|
|
26421
|
+
database: databaseRef ?? database,
|
|
26422
|
+
...fields.authSource ? { authSource: fields.authSource } : {},
|
|
26423
|
+
...fields.replicaSet ? { replicaSet: fields.replicaSet } : {},
|
|
26424
|
+
...fields.tls !== undefined ? { tls: fields.tls } : {},
|
|
26425
|
+
...fields.srv ? { srv: true } : {}
|
|
26426
|
+
};
|
|
26427
|
+
}
|
|
26428
|
+
if (!database && !isInteractive && !useFieldEnvRefs) {
|
|
26429
|
+
throw new Error(t("errors.require_name"));
|
|
26430
|
+
}
|
|
26431
|
+
const mongoConfig = envRefConfig ?? (useUriMode ? {
|
|
26432
|
+
system: "mongodb",
|
|
26433
|
+
uri: mongoUri,
|
|
26434
|
+
database,
|
|
26435
|
+
host: "",
|
|
26436
|
+
port: 27017,
|
|
26437
|
+
user: "",
|
|
26438
|
+
password: ""
|
|
26439
|
+
} : {
|
|
26440
|
+
system: "mongodb",
|
|
26441
|
+
host: fields.host,
|
|
26442
|
+
port: fields.port,
|
|
26443
|
+
user: fields.user,
|
|
26444
|
+
password: fields.password,
|
|
26445
|
+
database,
|
|
26446
|
+
...fields.user ? { authSource: fields.authSource || "admin" } : {},
|
|
26447
|
+
...fields.replicaSet ? { replicaSet: fields.replicaSet } : {},
|
|
26448
|
+
...fields.tls !== undefined ? { tls: fields.tls } : {},
|
|
26449
|
+
...fields.srv ? { srv: true } : {}
|
|
26450
|
+
});
|
|
26451
|
+
let permission = options.permission || "query-only";
|
|
26452
|
+
if (isInteractive && !options.permission) {
|
|
26453
|
+
permission = await promptUser.select(t("init.prompt_permission"), [
|
|
26454
|
+
"query-only",
|
|
26455
|
+
"read-write",
|
|
26456
|
+
"data-admin",
|
|
26457
|
+
"admin"
|
|
26458
|
+
]);
|
|
26459
|
+
}
|
|
26460
|
+
if (!VALID_PERMISSIONS.includes(permission)) {
|
|
26461
|
+
throw new Error(t_vars("errors.invalid_permission", { permission }));
|
|
26462
|
+
}
|
|
26463
|
+
const canProceed = await checkOverwrite(configPath, isInteractive, !!options.force);
|
|
26464
|
+
if (!canProceed)
|
|
26465
|
+
return;
|
|
26466
|
+
if (!options.skipTest && !useFieldEnvRefs) {
|
|
26467
|
+
console.log(t("init.connection_testing"));
|
|
26468
|
+
const mongoAdapter = AdapterFactory.createMongoDBAdapter(mongoConfig);
|
|
26469
|
+
try {
|
|
26470
|
+
await mongoAdapter.connect();
|
|
26471
|
+
await mongoAdapter.testConnection();
|
|
26472
|
+
console.log(t("init.connection_success"));
|
|
26473
|
+
} catch (error) {
|
|
26474
|
+
if (error instanceof ConnectionError) {
|
|
26475
|
+
console.error(t_vars("errors.connection_failed", { message: error.message }));
|
|
26476
|
+
console.error(t("init.connection_hints"));
|
|
26477
|
+
error.hints.forEach((hint) => console.error(` \u2022 ${hint}`));
|
|
26478
|
+
process.exit(1);
|
|
26479
|
+
}
|
|
26480
|
+
throw error;
|
|
26481
|
+
} finally {
|
|
26482
|
+
await mongoAdapter.disconnect();
|
|
26483
|
+
}
|
|
26484
|
+
} else {
|
|
26485
|
+
console.log(`\u23ED\uFE0F ${t(useFieldEnvRefs ? "init.skip_test_env_ref" : "init.skip_test")}`);
|
|
26486
|
+
}
|
|
26487
|
+
if (isV2Init) {
|
|
26488
|
+
await writeV2InitConfig(configPath, connectionName, mongoConfig, permission, options.envFile);
|
|
26489
|
+
return;
|
|
26490
|
+
}
|
|
26491
|
+
const newConfig = configModule.merge(existingConfig, {
|
|
26492
|
+
connection: mongoConfig,
|
|
26493
|
+
permission
|
|
26494
|
+
});
|
|
26495
|
+
const globalConfig = isGlobalConfigPath(configPath);
|
|
26496
|
+
const storagePath = globalConfig ? configPath : getProjectStoragePath(configPath);
|
|
26497
|
+
await mkdir5(storagePath, { recursive: true });
|
|
26498
|
+
await configModule.write(storagePath, newConfig);
|
|
26499
|
+
if (!globalConfig) {
|
|
26500
|
+
await migrateLegacyProjectEnvLocal(configPath, storagePath);
|
|
26501
|
+
await writeProjectBinding(configPath, storagePath);
|
|
26502
|
+
}
|
|
26503
|
+
console.log(t("init.config_saved"));
|
|
26504
|
+
}
|
|
26505
|
+
var VALID_PERMISSIONS;
|
|
26506
|
+
var init_init_mongodb = __esm(() => {
|
|
26507
|
+
init_message_loader();
|
|
26508
|
+
init_config();
|
|
26509
|
+
init_prompts();
|
|
26510
|
+
init_adapters();
|
|
26511
|
+
init_config_binding();
|
|
26512
|
+
init_init_shared();
|
|
26513
|
+
VALID_PERMISSIONS = ["query-only", "read-write", "data-admin", "admin"];
|
|
26514
|
+
});
|
|
26515
|
+
|
|
26516
|
+
// src/commands/init.ts
|
|
26517
|
+
import { join as join15 } from "path";
|
|
26518
|
+
import { mkdir as mkdir6 } from "fs/promises";
|
|
26519
|
+
async function handleRemove(configPath, name2) {
|
|
26520
|
+
const storagePath = await resolveConfigStoragePath(configPath);
|
|
26521
|
+
const configFile = Bun.file(join15(storagePath, "config.json"));
|
|
26522
|
+
if (!await configFile.exists()) {
|
|
26523
|
+
throw new Error(t("init.config_not_found"));
|
|
26524
|
+
}
|
|
26525
|
+
const raw = JSON.parse(await configFile.text());
|
|
26526
|
+
if (detectConfigVersion(raw) !== 2) {
|
|
26527
|
+
throw new Error(t("init.requires_v2_remove"));
|
|
26528
|
+
}
|
|
26529
|
+
const config = await readV2Config(storagePath);
|
|
26530
|
+
if (!config.connections[name2]) {
|
|
26531
|
+
throw new Error(t_vars("init.connection_not_found", { name: name2 }));
|
|
26532
|
+
}
|
|
26533
|
+
const connectionCount = Object.keys(config.connections).length;
|
|
26534
|
+
if (connectionCount <= 1) {
|
|
26535
|
+
throw new Error(t("init.cannot_remove_last"));
|
|
26536
|
+
}
|
|
26537
|
+
const remaining = Object.fromEntries(Object.entries(config.connections).filter(([connectionName]) => connectionName !== name2));
|
|
26538
|
+
const newDefault = config.default === name2 ? Object.keys(remaining)[0] : config.default;
|
|
26539
|
+
const updated = {
|
|
26540
|
+
...config,
|
|
26541
|
+
default: newDefault,
|
|
26542
|
+
connections: remaining
|
|
26543
|
+
};
|
|
26544
|
+
await writeV2Config(storagePath, updated);
|
|
26545
|
+
if (config.default === name2) {
|
|
26546
|
+
console.log(t_vars("init.connection_removed_switched", { name: name2, newDefault }));
|
|
26547
|
+
} else {
|
|
26548
|
+
console.log(t_vars("init.connection_removed", { name: name2 }));
|
|
26549
|
+
}
|
|
26550
|
+
}
|
|
26551
|
+
async function handleRename(configPath, renameArg) {
|
|
26552
|
+
const [oldName, newName] = renameArg.split(":");
|
|
26553
|
+
if (!oldName || !newName) {
|
|
26554
|
+
throw new Error(t("init.rename_invalid_format"));
|
|
26555
|
+
}
|
|
26556
|
+
const storagePath = await resolveConfigStoragePath(configPath);
|
|
26557
|
+
const configFile = Bun.file(join15(storagePath, "config.json"));
|
|
26558
|
+
if (!await configFile.exists()) {
|
|
26559
|
+
throw new Error(t("init.config_not_found"));
|
|
26560
|
+
}
|
|
26561
|
+
const raw = JSON.parse(await configFile.text());
|
|
26562
|
+
if (detectConfigVersion(raw) !== 2) {
|
|
26563
|
+
throw new Error(t("init.requires_v2_rename"));
|
|
26564
|
+
}
|
|
26565
|
+
const config = await readV2Config(storagePath);
|
|
26566
|
+
if (!config.connections[oldName]) {
|
|
26567
|
+
throw new Error(t_vars("init.connection_not_found", { name: oldName }));
|
|
26568
|
+
}
|
|
26569
|
+
if (config.connections[newName]) {
|
|
26570
|
+
throw new Error(t_vars("init.connection_already_exists", { name: newName }));
|
|
26571
|
+
}
|
|
26572
|
+
const entries = Object.entries(config.connections).map(([key, value]) => [key === oldName ? newName : key, value]);
|
|
26573
|
+
const updated = {
|
|
26574
|
+
...config,
|
|
26575
|
+
default: config.default === oldName ? newName : config.default,
|
|
26576
|
+
connections: Object.fromEntries(entries)
|
|
26577
|
+
};
|
|
26578
|
+
await writeV2Config(storagePath, updated);
|
|
26579
|
+
console.log(t_vars("init.connection_renamed", { oldName, newName }));
|
|
26580
|
+
}
|
|
26322
26581
|
async function initCommandHandler(options, command) {
|
|
26323
26582
|
const configPath = resolveConfigPath(command);
|
|
26324
26583
|
if (options.remove) {
|
|
@@ -26399,7 +26658,7 @@ async function initCommandHandler(options, command) {
|
|
|
26399
26658
|
"admin"
|
|
26400
26659
|
]);
|
|
26401
26660
|
}
|
|
26402
|
-
if (!
|
|
26661
|
+
if (!VALID_PERMISSIONS2.includes(permission2)) {
|
|
26403
26662
|
throw new Error(t_vars("errors.invalid_permission", { permission: permission2 }));
|
|
26404
26663
|
}
|
|
26405
26664
|
const newConfig2 = configModule.merge(existingConfig, {
|
|
@@ -26415,7 +26674,7 @@ async function initCommandHandler(options, command) {
|
|
|
26415
26674
|
return;
|
|
26416
26675
|
}
|
|
26417
26676
|
const storagePath2 = isGlobalConfig ? configPath : getProjectStoragePath(configPath);
|
|
26418
|
-
await
|
|
26677
|
+
await mkdir6(storagePath2, { recursive: true });
|
|
26419
26678
|
await configModule.write(storagePath2, newConfig2);
|
|
26420
26679
|
if (!isGlobalConfig) {
|
|
26421
26680
|
await migrateLegacyProjectEnvLocal(configPath, storagePath2);
|
|
@@ -26454,7 +26713,7 @@ async function initCommandHandler(options, command) {
|
|
|
26454
26713
|
"admin"
|
|
26455
26714
|
]);
|
|
26456
26715
|
}
|
|
26457
|
-
if (!
|
|
26716
|
+
if (!VALID_PERMISSIONS2.includes(permission)) {
|
|
26458
26717
|
throw new Error(t_vars("errors.invalid_permission", { permission }));
|
|
26459
26718
|
}
|
|
26460
26719
|
configForWrite = connection;
|
|
@@ -26531,7 +26790,7 @@ async function initCommandHandler(options, command) {
|
|
|
26531
26790
|
return;
|
|
26532
26791
|
}
|
|
26533
26792
|
const storagePath = isGlobalConfig ? configPath : getProjectStoragePath(configPath);
|
|
26534
|
-
await
|
|
26793
|
+
await mkdir6(storagePath, { recursive: true });
|
|
26535
26794
|
await configModule.write(storagePath, newConfig);
|
|
26536
26795
|
if (!isGlobalConfig) {
|
|
26537
26796
|
await migrateLegacyProjectEnvLocal(configPath, storagePath);
|
|
@@ -26539,95 +26798,7 @@ async function initCommandHandler(options, command) {
|
|
|
26539
26798
|
}
|
|
26540
26799
|
console.log(t("init.config_saved"));
|
|
26541
26800
|
}
|
|
26542
|
-
|
|
26543
|
-
const { options, configPath, connectionName, isV2Init, existingConfig } = ctx;
|
|
26544
|
-
const isInteractive = options.interactive !== false && process.stdin.isTTY;
|
|
26545
|
-
let mongoUri = options.uri;
|
|
26546
|
-
if (!mongoUri && isInteractive) {
|
|
26547
|
-
const input = await promptUser.text("MongoDB URI (e.g. mongodb://user:pass@host:27017/db?authSource=admin) \u2014 \u7559\u7A7A\u7528 host/port/user/password", "");
|
|
26548
|
-
if (input.trim())
|
|
26549
|
-
mongoUri = input.trim();
|
|
26550
|
-
}
|
|
26551
|
-
let database = options.name || "";
|
|
26552
|
-
if (!database && isInteractive) {
|
|
26553
|
-
database = await promptUser.text("Database name", "testdb");
|
|
26554
|
-
}
|
|
26555
|
-
if (!database && !isInteractive) {
|
|
26556
|
-
throw new Error(t("errors.require_name"));
|
|
26557
|
-
}
|
|
26558
|
-
const authSource = options.authSource || "";
|
|
26559
|
-
const mongoConfig = mongoUri ? {
|
|
26560
|
-
system: "mongodb",
|
|
26561
|
-
uri: mongoUri,
|
|
26562
|
-
database,
|
|
26563
|
-
host: "",
|
|
26564
|
-
port: 27017,
|
|
26565
|
-
user: "",
|
|
26566
|
-
password: ""
|
|
26567
|
-
} : {
|
|
26568
|
-
system: "mongodb",
|
|
26569
|
-
host: options.host || "localhost",
|
|
26570
|
-
port: parseInt(options.port || "27017", 10),
|
|
26571
|
-
user: options.user || "",
|
|
26572
|
-
password: options.password || "",
|
|
26573
|
-
database,
|
|
26574
|
-
...authSource ? { authSource } : {}
|
|
26575
|
-
};
|
|
26576
|
-
let permission = options.permission || "query-only";
|
|
26577
|
-
if (isInteractive && !options.permission) {
|
|
26578
|
-
permission = await promptUser.select(t("init.prompt_permission"), [
|
|
26579
|
-
"query-only",
|
|
26580
|
-
"read-write",
|
|
26581
|
-
"data-admin",
|
|
26582
|
-
"admin"
|
|
26583
|
-
]);
|
|
26584
|
-
}
|
|
26585
|
-
if (!VALID_PERMISSIONS.includes(permission)) {
|
|
26586
|
-
throw new Error(t_vars("errors.invalid_permission", { permission }));
|
|
26587
|
-
}
|
|
26588
|
-
const canProceed = await checkOverwrite(configPath, isInteractive, !!options.force);
|
|
26589
|
-
if (!canProceed)
|
|
26590
|
-
return;
|
|
26591
|
-
if (!options.skipTest) {
|
|
26592
|
-
console.log(t("init.connection_testing"));
|
|
26593
|
-
const mongoAdapter = AdapterFactory.createMongoDBAdapter(mongoConfig);
|
|
26594
|
-
try {
|
|
26595
|
-
await mongoAdapter.connect();
|
|
26596
|
-
await mongoAdapter.testConnection();
|
|
26597
|
-
console.log(t("init.connection_success"));
|
|
26598
|
-
} catch (error) {
|
|
26599
|
-
if (error instanceof ConnectionError) {
|
|
26600
|
-
console.error(t_vars("errors.connection_failed", { message: error.message }));
|
|
26601
|
-
console.error(t("init.connection_hints"));
|
|
26602
|
-
error.hints.forEach((hint) => console.error(` \u2022 ${hint}`));
|
|
26603
|
-
process.exit(1);
|
|
26604
|
-
}
|
|
26605
|
-
throw error;
|
|
26606
|
-
} finally {
|
|
26607
|
-
await mongoAdapter.disconnect();
|
|
26608
|
-
}
|
|
26609
|
-
} else {
|
|
26610
|
-
console.log(`\u23ED\uFE0F ${t("init.skip_test")}`);
|
|
26611
|
-
}
|
|
26612
|
-
if (isV2Init) {
|
|
26613
|
-
await writeV2InitConfig(configPath, connectionName, mongoConfig, permission, options.envFile);
|
|
26614
|
-
return;
|
|
26615
|
-
}
|
|
26616
|
-
const newConfig = configModule.merge(existingConfig, {
|
|
26617
|
-
connection: mongoConfig,
|
|
26618
|
-
permission
|
|
26619
|
-
});
|
|
26620
|
-
const globalConfig = isGlobalConfigPath(configPath);
|
|
26621
|
-
const storagePath = globalConfig ? configPath : getProjectStoragePath(configPath);
|
|
26622
|
-
await mkdir5(storagePath, { recursive: true });
|
|
26623
|
-
await configModule.write(storagePath, newConfig);
|
|
26624
|
-
if (!globalConfig) {
|
|
26625
|
-
await migrateLegacyProjectEnvLocal(configPath, storagePath);
|
|
26626
|
-
await writeProjectBinding(configPath, storagePath);
|
|
26627
|
-
}
|
|
26628
|
-
console.log(t("init.config_saved"));
|
|
26629
|
-
}
|
|
26630
|
-
var VALID_PERMISSIONS, initCommand;
|
|
26801
|
+
var VALID_PERMISSIONS2, initCommand;
|
|
26631
26802
|
var init_init = __esm(() => {
|
|
26632
26803
|
init_esm();
|
|
26633
26804
|
init_message_loader();
|
|
@@ -26638,7 +26809,9 @@ var init_init = __esm(() => {
|
|
|
26638
26809
|
init_adapters();
|
|
26639
26810
|
init_config_path();
|
|
26640
26811
|
init_config_binding();
|
|
26641
|
-
|
|
26812
|
+
init_init_shared();
|
|
26813
|
+
init_init_mongodb();
|
|
26814
|
+
VALID_PERMISSIONS2 = ["query-only", "read-write", "data-admin", "admin"];
|
|
26642
26815
|
initCommand = new Command("init").description("Initialize dbcli configuration with .env parsing and interactive prompts").option("--host <host>", "Database host").option("--port <port>", "Database port").option("--user <user>", "Database user").option("--password <password>", "Database password").option("--name <name>", "Database name").option("--system <system>", "Database system (postgresql, mysql, mariadb, mongodb, redis, elasticsearch)").option("--cloud-id <id>", "Elasticsearch Cloud ID").option("--api-key <key>", "Elasticsearch API Key").option("--uri <uri>", "MongoDB connection URI (mongodb://user:pass@host:27017/db?authSource=admin)").option("--auth-source <authSource>", "MongoDB auth database (default: admin when user/password are set)").option("--permission <permission>", "Permission level (query-only, read-write, data-admin, admin)", "query-only").option("--use-env-refs", "Store env var references in config instead of actual values (for CI/CD or multi-env)", false).option("--env-host <var>", "Env var name for host (with --use-env-refs)").option("--env-port <var>", "Env var name for port (with --use-env-refs)").option("--env-user <var>", "Env var name for user (with --use-env-refs)").option("--env-password <var>", "Env var name for password (with --use-env-refs)").option("--env-database <var>", "Env var name for database (with --use-env-refs)").option("--skip-test", "Skip database connection test").option("--no-interactive", "Non-interactive mode (requires all values via flags)").option("--force", "Skip overwrite confirmation if .dbcli exists").option("--conn-name <name>", "Connection name (creates v2 multi-connection config)").option("--env-file <path>", "Path to env file for this connection").option("--remove <name>", "Remove a named connection").option("--rename <names>", "Rename a connection (format: old:new)").action(async (options) => {
|
|
26643
26816
|
try {
|
|
26644
26817
|
await initCommandHandler(options, initCommand);
|
|
@@ -28906,7 +29079,7 @@ class AtomicFileWriter {
|
|
|
28906
29079
|
}
|
|
28907
29080
|
|
|
28908
29081
|
// src/core/schema-writer.ts
|
|
28909
|
-
import { join as
|
|
29082
|
+
import { join as join16 } from "path";
|
|
28910
29083
|
|
|
28911
29084
|
class SchemaWriter {
|
|
28912
29085
|
dbcliPath;
|
|
@@ -28927,7 +29100,7 @@ class SchemaWriter {
|
|
|
28927
29100
|
hotSchemas[item.table] = tableSchema;
|
|
28928
29101
|
}
|
|
28929
29102
|
}
|
|
28930
|
-
await this.writer.writeJSON(
|
|
29103
|
+
await this.writer.writeJSON(join16(schemaRoot, "hot-schemas.json"), hotSchemas);
|
|
28931
29104
|
const coldGroups = {};
|
|
28932
29105
|
for (const item of mapping.cold) {
|
|
28933
29106
|
if (!coldGroups[item.file]) {
|
|
@@ -28938,10 +29111,10 @@ class SchemaWriter {
|
|
|
28938
29111
|
coldGroups[item.file][item.table] = tableSchema;
|
|
28939
29112
|
}
|
|
28940
29113
|
}
|
|
28941
|
-
const coldDir =
|
|
29114
|
+
const coldDir = join16(schemaRoot, "cold");
|
|
28942
29115
|
await this.ensureDir(coldDir);
|
|
28943
29116
|
for (const [fileName, tables] of Object.entries(coldGroups)) {
|
|
28944
|
-
const filePath =
|
|
29117
|
+
const filePath = join16(schemaRoot, fileName);
|
|
28945
29118
|
await this.writer.writeJSON(filePath, tables);
|
|
28946
29119
|
}
|
|
28947
29120
|
}
|
|
@@ -29487,8 +29660,8 @@ var init_artifact = __esm(() => {
|
|
|
29487
29660
|
});
|
|
29488
29661
|
|
|
29489
29662
|
// src/core/verification/artifact-writer.ts
|
|
29490
|
-
import { mkdir as
|
|
29491
|
-
import { join as
|
|
29663
|
+
import { mkdir as mkdir7, writeFile as writeFile2, link, unlink as unlink4 } from "fs/promises";
|
|
29664
|
+
import { join as join17 } from "path";
|
|
29492
29665
|
function pad(n, len = 2) {
|
|
29493
29666
|
return String(n).padStart(len, "0");
|
|
29494
29667
|
}
|
|
@@ -29505,9 +29678,9 @@ function verificationArtifactFilename(artifact) {
|
|
|
29505
29678
|
return `verification-${timeStamp(artifact.createdAt)}-${shortId(artifact.id)}.json`;
|
|
29506
29679
|
}
|
|
29507
29680
|
async function writeVerificationArtifact(storageDir, artifact) {
|
|
29508
|
-
const dir =
|
|
29509
|
-
await
|
|
29510
|
-
const target =
|
|
29681
|
+
const dir = join17(storageDir, VERIFICATION_DIR_RELATIVE);
|
|
29682
|
+
await mkdir7(dir, { recursive: true });
|
|
29683
|
+
const target = join17(dir, verificationArtifactFilename(artifact));
|
|
29511
29684
|
const tmp = `${target}.${process.pid}.tmp`;
|
|
29512
29685
|
try {
|
|
29513
29686
|
await writeFile2(tmp, JSON.stringify(artifact, null, 2), "utf8");
|
|
@@ -29768,7 +29941,7 @@ var init_assert_artifact = __esm(() => {
|
|
|
29768
29941
|
|
|
29769
29942
|
// src/core/verification/reader.ts
|
|
29770
29943
|
import { lstat as lstat2, readdir as readdir2, readFile as readFile2 } from "fs/promises";
|
|
29771
|
-
import { join as
|
|
29944
|
+
import { join as join18, isAbsolute, resolve as resolve4, sep as sep2 } from "path";
|
|
29772
29945
|
function isArtifactFilename(name2) {
|
|
29773
29946
|
return /^verification-.*\.json$/.test(name2);
|
|
29774
29947
|
}
|
|
@@ -29852,7 +30025,7 @@ function validateVerificationArtifact(value) {
|
|
|
29852
30025
|
return value;
|
|
29853
30026
|
}
|
|
29854
30027
|
async function readVerificationArtifacts(storageRoot) {
|
|
29855
|
-
const storageDir =
|
|
30028
|
+
const storageDir = join18(storageRoot, VERIFICATION_DIR_RELATIVE);
|
|
29856
30029
|
let names;
|
|
29857
30030
|
try {
|
|
29858
30031
|
names = await readdir2(storageDir);
|
|
@@ -29865,7 +30038,7 @@ async function readVerificationArtifacts(storageRoot) {
|
|
|
29865
30038
|
const artifacts = [];
|
|
29866
30039
|
const invalid = [];
|
|
29867
30040
|
for (const filename of names.filter(isArtifactFilename)) {
|
|
29868
|
-
const path5 =
|
|
30041
|
+
const path5 = join18(storageDir, filename);
|
|
29869
30042
|
try {
|
|
29870
30043
|
const stats = await lstat2(path5);
|
|
29871
30044
|
if (!stats.isFile()) {
|
|
@@ -30346,7 +30519,7 @@ var init_core = __esm(() => {
|
|
|
30346
30519
|
// src/core/audit/lock.ts
|
|
30347
30520
|
import { hostname } from "os";
|
|
30348
30521
|
import { dirname as dirname5 } from "path";
|
|
30349
|
-
import { mkdir as
|
|
30522
|
+
import { mkdir as mkdir8, open as open2, rm } from "fs/promises";
|
|
30350
30523
|
|
|
30351
30524
|
class AuditLockManager {
|
|
30352
30525
|
auditFilePath;
|
|
@@ -30404,7 +30577,7 @@ class AuditLockManager {
|
|
|
30404
30577
|
}
|
|
30405
30578
|
async tryAcquireLock(operationName) {
|
|
30406
30579
|
try {
|
|
30407
|
-
await
|
|
30580
|
+
await mkdir8(dirname5(this.lockPath), { recursive: true });
|
|
30408
30581
|
const lockFile = Bun.file(this.lockPath);
|
|
30409
30582
|
if (await lockFile.exists()) {
|
|
30410
30583
|
const lockContent = await lockFile.json();
|
|
@@ -30457,8 +30630,8 @@ var init_rotation = __esm(() => {
|
|
|
30457
30630
|
});
|
|
30458
30631
|
|
|
30459
30632
|
// src/core/audit/logger.ts
|
|
30460
|
-
import { appendFile, mkdir as
|
|
30461
|
-
import { join as
|
|
30633
|
+
import { appendFile, mkdir as mkdir9, readFile as readFile3, stat as stat2 } from "fs/promises";
|
|
30634
|
+
import { join as join19 } from "path";
|
|
30462
30635
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
30463
30636
|
|
|
30464
30637
|
class AuditLogger {
|
|
@@ -30484,8 +30657,8 @@ class AuditLogger {
|
|
|
30484
30657
|
this.enabled = opts.enabled;
|
|
30485
30658
|
this.maxBytes = opts.rotation.maxBytes;
|
|
30486
30659
|
this.maxEntries = opts.rotation.maxEntries;
|
|
30487
|
-
this.auditDir =
|
|
30488
|
-
this.auditFilePath =
|
|
30660
|
+
this.auditDir = join19(opts.storagePath, ".dbcli", "audit");
|
|
30661
|
+
this.auditFilePath = join19(this.auditDir, `${opts.connectionName}.jsonl`);
|
|
30489
30662
|
this.previousFilePath = `${this.auditFilePath}.1`;
|
|
30490
30663
|
this.sessionIdService = opts.sessionIdService;
|
|
30491
30664
|
this.lockManager = opts.lockManager ?? new AuditLockManager(this.auditFilePath);
|
|
@@ -30506,7 +30679,7 @@ class AuditLogger {
|
|
|
30506
30679
|
try {
|
|
30507
30680
|
const sessionId = await this.sessionIdService.resolve();
|
|
30508
30681
|
this.cachedSessionId = sessionId;
|
|
30509
|
-
await
|
|
30682
|
+
await mkdir9(this.auditDir, { recursive: true });
|
|
30510
30683
|
if (!this.writerInitialized) {
|
|
30511
30684
|
await this.syncCountersFromDisk();
|
|
30512
30685
|
this.writerInitialized = true;
|
|
@@ -30611,15 +30784,15 @@ var init_logger2 = __esm(() => {
|
|
|
30611
30784
|
});
|
|
30612
30785
|
|
|
30613
30786
|
// src/core/audit/session-id.ts
|
|
30614
|
-
import { mkdir as
|
|
30787
|
+
import { mkdir as mkdir10, readFile as readFile4, rename as rename4, stat as stat3, writeFile as writeFile3 } from "fs/promises";
|
|
30615
30788
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
30616
|
-
import { dirname as dirname6, join as
|
|
30789
|
+
import { dirname as dirname6, join as join20 } from "path";
|
|
30617
30790
|
function generateSessionId(pid, nowMs) {
|
|
30618
30791
|
const random = randomBytes2(3).toString("hex");
|
|
30619
30792
|
return `${pid}-${nowMs}-${random}`;
|
|
30620
30793
|
}
|
|
30621
30794
|
async function readSessionIdFile(storagePath) {
|
|
30622
|
-
const target =
|
|
30795
|
+
const target = join20(storagePath, LAST_SESSION_ID_RELATIVE);
|
|
30623
30796
|
try {
|
|
30624
30797
|
await stat3(target);
|
|
30625
30798
|
} catch {
|
|
@@ -30641,10 +30814,10 @@ async function readSessionIdFile(storagePath) {
|
|
|
30641
30814
|
}
|
|
30642
30815
|
}
|
|
30643
30816
|
async function writeSessionIdFile(storagePath, payload) {
|
|
30644
|
-
const target =
|
|
30817
|
+
const target = join20(storagePath, LAST_SESSION_ID_RELATIVE);
|
|
30645
30818
|
const tmp = `${target}.tmp`;
|
|
30646
30819
|
try {
|
|
30647
|
-
await
|
|
30820
|
+
await mkdir10(dirname6(target), { recursive: true });
|
|
30648
30821
|
await writeFile3(tmp, JSON.stringify(payload, null, 2), "utf8");
|
|
30649
30822
|
await rename4(tmp, target);
|
|
30650
30823
|
} catch {}
|
|
@@ -32373,14 +32546,14 @@ var init_render_markdown = __esm(() => {
|
|
|
32373
32546
|
});
|
|
32374
32547
|
|
|
32375
32548
|
// src/core/recovery/last-envelope.ts
|
|
32376
|
-
import { writeFile as writeFile4, readFile as readFile5, rename as rename5, mkdir as
|
|
32377
|
-
import { dirname as dirname7, join as
|
|
32549
|
+
import { writeFile as writeFile4, readFile as readFile5, rename as rename5, mkdir as mkdir11, stat as stat4 } from "fs/promises";
|
|
32550
|
+
import { dirname as dirname7, join as join21 } from "path";
|
|
32378
32551
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
32379
32552
|
function sanitizeCommandSummary(argv) {
|
|
32380
32553
|
return redactArgv(argv);
|
|
32381
32554
|
}
|
|
32382
32555
|
async function writeLastEnvelope(cwd, envelope, argv, now = () => new Date, id = randomUUID4(), auditRef) {
|
|
32383
|
-
const target =
|
|
32556
|
+
const target = join21(cwd, LAST_ENVELOPE_PATH);
|
|
32384
32557
|
const tmp = `${target}.tmp`;
|
|
32385
32558
|
const payload = {
|
|
32386
32559
|
schemaVersion: 1,
|
|
@@ -32392,13 +32565,13 @@ async function writeLastEnvelope(cwd, envelope, argv, now = () => new Date, id =
|
|
|
32392
32565
|
envelope
|
|
32393
32566
|
};
|
|
32394
32567
|
try {
|
|
32395
|
-
await
|
|
32568
|
+
await mkdir11(dirname7(target), { recursive: true });
|
|
32396
32569
|
await writeFile4(tmp, JSON.stringify(payload, null, 2), "utf8");
|
|
32397
32570
|
await rename5(tmp, target);
|
|
32398
32571
|
} catch {}
|
|
32399
32572
|
}
|
|
32400
32573
|
async function readLastEnvelope(cwd) {
|
|
32401
|
-
const target =
|
|
32574
|
+
const target = join21(cwd, LAST_ENVELOPE_PATH);
|
|
32402
32575
|
try {
|
|
32403
32576
|
await stat4(target);
|
|
32404
32577
|
} catch {
|
|
@@ -32412,7 +32585,7 @@ async function readLastEnvelope(cwd) {
|
|
|
32412
32585
|
}
|
|
32413
32586
|
}
|
|
32414
32587
|
async function readLastEnvelopeRaw(cwd) {
|
|
32415
|
-
const target =
|
|
32588
|
+
const target = join21(cwd, LAST_ENVELOPE_PATH);
|
|
32416
32589
|
try {
|
|
32417
32590
|
await stat4(target);
|
|
32418
32591
|
} catch {
|
|
@@ -32437,7 +32610,7 @@ var init_last_envelope = __esm(() => {
|
|
|
32437
32610
|
|
|
32438
32611
|
// src/core/recovery/emit.ts
|
|
32439
32612
|
import { writeFileSync as writeFileSync2, mkdirSync, renameSync, writeSync } from "fs";
|
|
32440
|
-
import { dirname as dirname8, join as
|
|
32613
|
+
import { dirname as dirname8, join as join22 } from "path";
|
|
32441
32614
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
32442
32615
|
function emitRecoveryEnvelope(error, ctx, options = {}) {
|
|
32443
32616
|
const envelope = classifyError(error, ctx);
|
|
@@ -32454,7 +32627,7 @@ function buildArgvFromProcess() {
|
|
|
32454
32627
|
return ["dbcli", ...userArgs];
|
|
32455
32628
|
}
|
|
32456
32629
|
function writeLastEnvelopeSync(cwd, envelope, argv, id, auditRef) {
|
|
32457
|
-
const target =
|
|
32630
|
+
const target = join22(cwd, LAST_ENVELOPE_PATH);
|
|
32458
32631
|
const tmp = `${target}.tmp`;
|
|
32459
32632
|
const payload = {
|
|
32460
32633
|
schemaVersion: 1,
|
|
@@ -34387,7 +34560,7 @@ var init_query_size_guard = __esm(() => {
|
|
|
34387
34560
|
// src/commands/query.ts
|
|
34388
34561
|
import crypto3 from "crypto";
|
|
34389
34562
|
import { tmpdir } from "os";
|
|
34390
|
-
import { join as
|
|
34563
|
+
import { join as join23 } from "path";
|
|
34391
34564
|
function requireSqlConnection2(connection) {
|
|
34392
34565
|
if (!["postgresql", "mysql", "mariadb"].includes(connection.system)) {
|
|
34393
34566
|
throw new Error(`This command requires a SQL connection, got: ${connection.system}`);
|
|
@@ -34698,7 +34871,7 @@ async function presentSingleResult(query, options, execution, tableCellLimit) {
|
|
|
34698
34871
|
} : {}
|
|
34699
34872
|
});
|
|
34700
34873
|
if (options.ui) {
|
|
34701
|
-
const tempPath =
|
|
34874
|
+
const tempPath = join23(tmpdir(), `dbcli-query-${Date.now()}.html`);
|
|
34702
34875
|
await Bun.write(tempPath, html);
|
|
34703
34876
|
await openInBrowser(tempPath);
|
|
34704
34877
|
} else {
|
|
@@ -35458,7 +35631,7 @@ __export(exports_q_mongo, {
|
|
|
35458
35631
|
qMongoBranch: () => qMongoBranch
|
|
35459
35632
|
});
|
|
35460
35633
|
import { tmpdir as tmpdir2 } from "os";
|
|
35461
|
-
import { join as
|
|
35634
|
+
import { join as join24 } from "path";
|
|
35462
35635
|
async function qMongoBranch(snippet, prepared, options, config) {
|
|
35463
35636
|
const collection = options.collection ?? prepared.execHints?.collection;
|
|
35464
35637
|
if (!collection) {
|
|
@@ -35490,7 +35663,7 @@ async function qMongoBranch(snippet, prepared, options, config) {
|
|
|
35490
35663
|
...securityNotification ? { securityNotification } : {}
|
|
35491
35664
|
});
|
|
35492
35665
|
if (options.ui) {
|
|
35493
|
-
const tempPath =
|
|
35666
|
+
const tempPath = join24(tmpdir2(), `dbcli-report-${Date.now()}.html`);
|
|
35494
35667
|
await Bun.write(tempPath, html);
|
|
35495
35668
|
await openInBrowser(tempPath);
|
|
35496
35669
|
} else {
|
|
@@ -35531,7 +35704,7 @@ var init_q_mongo = __esm(() => {
|
|
|
35531
35704
|
// src/commands/q.ts
|
|
35532
35705
|
import crypto4 from "crypto";
|
|
35533
35706
|
import { tmpdir as tmpdir3 } from "os";
|
|
35534
|
-
import { join as
|
|
35707
|
+
import { join as join25 } from "path";
|
|
35535
35708
|
function formatDryRun(input) {
|
|
35536
35709
|
const lines = ["Dry-run preview (no execution):"];
|
|
35537
35710
|
if (input.family === "es") {
|
|
@@ -35632,7 +35805,7 @@ async function qCommand(name2, options, command) {
|
|
|
35632
35805
|
...securityNotification ? { securityNotification } : {}
|
|
35633
35806
|
});
|
|
35634
35807
|
if (options.ui) {
|
|
35635
|
-
const tempPath =
|
|
35808
|
+
const tempPath = join25(tmpdir3(), `dbcli-report-${Date.now()}.html`);
|
|
35636
35809
|
await Bun.write(tempPath, html);
|
|
35637
35810
|
await openInBrowser(tempPath);
|
|
35638
35811
|
} else {
|
|
@@ -36081,7 +36254,7 @@ var exports_queries_rename = {};
|
|
|
36081
36254
|
__export(exports_queries_rename, {
|
|
36082
36255
|
queriesRename: () => queriesRename
|
|
36083
36256
|
});
|
|
36084
|
-
import { rename as rename6, mkdir as
|
|
36257
|
+
import { rename as rename6, mkdir as mkdir12 } from "fs/promises";
|
|
36085
36258
|
import { dirname as dirname9 } from "path";
|
|
36086
36259
|
async function queriesRename(oldName, newName, options = {}) {
|
|
36087
36260
|
if (!oldName.startsWith("@") || !newName.startsWith("@")) {
|
|
@@ -36103,7 +36276,7 @@ async function queriesRename(oldName, newName, options = {}) {
|
|
|
36103
36276
|
for (const v of local) {
|
|
36104
36277
|
const dst = snippetKeyToFile(cwd, newName, "local");
|
|
36105
36278
|
const dstWithSuffix = preserveEngineSuffix(v.query.file, dst);
|
|
36106
|
-
await
|
|
36279
|
+
await mkdir12(dirname9(dstWithSuffix), { recursive: true });
|
|
36107
36280
|
await rename6(v.query.file, dstWithSuffix);
|
|
36108
36281
|
await rewriteFrontmatterName(dstWithSuffix, newName.slice(1));
|
|
36109
36282
|
console.log(`renamed ${v.query.file} \u2192 ${dstWithSuffix}`);
|
|
@@ -36129,7 +36302,7 @@ var exports_queries_copy = {};
|
|
|
36129
36302
|
__export(exports_queries_copy, {
|
|
36130
36303
|
queriesCopy: () => queriesCopy
|
|
36131
36304
|
});
|
|
36132
|
-
import { mkdir as
|
|
36305
|
+
import { mkdir as mkdir13, copyFile } from "fs/promises";
|
|
36133
36306
|
import { dirname as dirname10, basename as basename4 } from "path";
|
|
36134
36307
|
async function queriesCopy(src, dst, options = {}) {
|
|
36135
36308
|
if (!src.startsWith("@") || !dst.startsWith("@")) {
|
|
@@ -36148,7 +36321,7 @@ async function queriesCopy(src, dst, options = {}) {
|
|
|
36148
36321
|
}
|
|
36149
36322
|
for (const v of variants) {
|
|
36150
36323
|
const dstFile = mapEngineSuffix(v.query.file, snippetKeyToFile(cwd, dst, "local"));
|
|
36151
|
-
await
|
|
36324
|
+
await mkdir13(dirname10(dstFile), { recursive: true });
|
|
36152
36325
|
await copyFile(v.query.file, dstFile);
|
|
36153
36326
|
console.log(`copied ${v.query.file} \u2192 ${dstFile}`);
|
|
36154
36327
|
}
|
|
@@ -36166,8 +36339,8 @@ var exports_queries_import = {};
|
|
|
36166
36339
|
__export(exports_queries_import, {
|
|
36167
36340
|
queriesImport: () => queriesImport
|
|
36168
36341
|
});
|
|
36169
|
-
import { stat as stat6, mkdir as
|
|
36170
|
-
import { basename as basename5, join as
|
|
36342
|
+
import { stat as stat6, mkdir as mkdir14, copyFile as copyFile2 } from "fs/promises";
|
|
36343
|
+
import { basename as basename5, join as join26, extname as extname2 } from "path";
|
|
36171
36344
|
async function queriesImport(filePath, options = {}) {
|
|
36172
36345
|
const cwd = options.cwd ?? process.cwd();
|
|
36173
36346
|
if (extname2(filePath) !== ".sql") {
|
|
@@ -36178,9 +36351,9 @@ async function queriesImport(filePath, options = {}) {
|
|
|
36178
36351
|
const baseName = options.as ? options.as.replace(/^@/, "") : basename5(filePath, ".sql").replace(/\.(postgres|mysql)$/, "");
|
|
36179
36352
|
const key = "@" + baseName;
|
|
36180
36353
|
parseSavedQuery({ key, file: filePath, source: "local", text: text2 });
|
|
36181
|
-
const targetDir =
|
|
36182
|
-
await
|
|
36183
|
-
const target =
|
|
36354
|
+
const targetDir = join26(cwd, ".dbcli/queries");
|
|
36355
|
+
await mkdir14(targetDir, { recursive: true });
|
|
36356
|
+
const target = join26(targetDir, basename5(filePath));
|
|
36184
36357
|
if (await Bun.file(target).exists()) {
|
|
36185
36358
|
if (!options.force) {
|
|
36186
36359
|
const ok = await dist_default6({ message: `Overwrite ${target}?`, default: false });
|
|
@@ -36233,7 +36406,7 @@ var init_queries_export = __esm(() => {
|
|
|
36233
36406
|
});
|
|
36234
36407
|
|
|
36235
36408
|
// src/commands/queries.ts
|
|
36236
|
-
import { mkdir as
|
|
36409
|
+
import { mkdir as mkdir15, writeFile as writeFile6 } from "fs/promises";
|
|
36237
36410
|
import { dirname as dirname11 } from "path";
|
|
36238
36411
|
import { spawn as spawn2 } from "child_process";
|
|
36239
36412
|
async function deriveEngine(command) {
|
|
@@ -36342,7 +36515,7 @@ async function queriesNew(name2, options) {
|
|
|
36342
36515
|
process.exit(1);
|
|
36343
36516
|
return;
|
|
36344
36517
|
}
|
|
36345
|
-
await
|
|
36518
|
+
await mkdir15(dirname11(file), { recursive: true });
|
|
36346
36519
|
await writeFile6(file, scaffold(name2), "utf8");
|
|
36347
36520
|
console.log(`Created ${file}`);
|
|
36348
36521
|
if (source === "shared")
|
|
@@ -39064,15 +39237,15 @@ var init_types6 = __esm(() => {
|
|
|
39064
39237
|
});
|
|
39065
39238
|
|
|
39066
39239
|
// src/core/agent-tasks/task-paths.ts
|
|
39067
|
-
import { join as
|
|
39240
|
+
import { join as join27 } from "path";
|
|
39068
39241
|
function resolveBuiltinDir2() {
|
|
39069
39242
|
return packageAssetPath("tasks");
|
|
39070
39243
|
}
|
|
39071
39244
|
function resolveAgentTaskDirs(workspaceRoot) {
|
|
39072
39245
|
return {
|
|
39073
39246
|
builtinDir: resolveBuiltinDir2(),
|
|
39074
|
-
sharedDir:
|
|
39075
|
-
localDir:
|
|
39247
|
+
sharedDir: join27(workspaceRoot, ".dbcli-shared", "tasks"),
|
|
39248
|
+
localDir: join27(workspaceRoot, ".dbcli", "tasks")
|
|
39076
39249
|
};
|
|
39077
39250
|
}
|
|
39078
39251
|
var init_task_paths = __esm(() => {
|
|
@@ -39219,7 +39392,7 @@ var init_parser2 = __esm(() => {
|
|
|
39219
39392
|
|
|
39220
39393
|
// src/core/agent-tasks/loader.ts
|
|
39221
39394
|
import { readdir as readdir3 } from "fs/promises";
|
|
39222
|
-
import { join as
|
|
39395
|
+
import { join as join28, relative as relative2, sep as sep4 } from "path";
|
|
39223
39396
|
async function loadAgentTasks(opts, flags) {
|
|
39224
39397
|
const errors3 = [];
|
|
39225
39398
|
const builtin = await walkAndParse2(opts.builtinDir, "builtin", errors3);
|
|
@@ -39276,7 +39449,7 @@ async function safeCollectMd(root) {
|
|
|
39276
39449
|
return;
|
|
39277
39450
|
}
|
|
39278
39451
|
for (const e of entries) {
|
|
39279
|
-
const full =
|
|
39452
|
+
const full = join28(dir, e.name);
|
|
39280
39453
|
if (e.isDirectory())
|
|
39281
39454
|
await walk(full);
|
|
39282
39455
|
else
|
|
@@ -92641,7 +92814,7 @@ var init_collect_snippets = __esm(() => {
|
|
|
92641
92814
|
});
|
|
92642
92815
|
|
|
92643
92816
|
// src/core/inspect/collect-schema-cache.ts
|
|
92644
|
-
import { join as
|
|
92817
|
+
import { join as join29 } from "path";
|
|
92645
92818
|
async function collectSchemaCache(opts) {
|
|
92646
92819
|
const warnings = [];
|
|
92647
92820
|
if (opts.system && !SQL_SYSTEMS2.includes(opts.system)) {
|
|
@@ -92651,7 +92824,7 @@ async function collectSchemaCache(opts) {
|
|
|
92651
92824
|
};
|
|
92652
92825
|
}
|
|
92653
92826
|
const root = resolveSchemaPath(opts.dbcliPath, opts.connectionName);
|
|
92654
|
-
const indexPath =
|
|
92827
|
+
const indexPath = join29(root, "index.json");
|
|
92655
92828
|
const file = Bun.file(indexPath);
|
|
92656
92829
|
if (!await file.exists()) {
|
|
92657
92830
|
return { section: { available: false }, warnings };
|
|
@@ -92921,7 +93094,7 @@ function buildHints(snap, ctx = {}) {
|
|
|
92921
93094
|
}
|
|
92922
93095
|
|
|
92923
93096
|
// src/core/inspect/collector.ts
|
|
92924
|
-
import { join as
|
|
93097
|
+
import { join as join30 } from "path";
|
|
92925
93098
|
async function collectInspect(opts) {
|
|
92926
93099
|
const warnings = [];
|
|
92927
93100
|
let config = null;
|
|
@@ -93005,7 +93178,7 @@ async function collectInspect(opts) {
|
|
|
93005
93178
|
return { ...snapWithoutSuggestions, suggestedCommands, hints, warnings };
|
|
93006
93179
|
}
|
|
93007
93180
|
async function hasConfig(configPath) {
|
|
93008
|
-
if (await Bun.file(
|
|
93181
|
+
if (await Bun.file(join30(configPath, "config.json")).exists())
|
|
93009
93182
|
return true;
|
|
93010
93183
|
if (await Bun.file(configPath).exists()) {
|
|
93011
93184
|
const stat7 = await Bun.file(configPath).stat().catch(() => null);
|
|
@@ -96094,9 +96267,9 @@ function relationBindings(statement) {
|
|
|
96094
96267
|
const bindings = [];
|
|
96095
96268
|
for (const item of statement.from) {
|
|
96096
96269
|
const source = item;
|
|
96097
|
-
const
|
|
96098
|
-
const nullExtendsPrevious =
|
|
96099
|
-
const nullExtendsCurrent =
|
|
96270
|
+
const join31 = typeof source.join === "string" ? source.join.toUpperCase() : "";
|
|
96271
|
+
const nullExtendsPrevious = join31.startsWith("RIGHT") || join31.startsWith("FULL");
|
|
96272
|
+
const nullExtendsCurrent = join31.startsWith("LEFT") || join31.startsWith("FULL");
|
|
96100
96273
|
if (nullExtendsPrevious) {
|
|
96101
96274
|
for (const binding of bindings)
|
|
96102
96275
|
binding.nullExtended = true;
|
|
@@ -97412,7 +97585,7 @@ var init_serializer = __esm(() => {
|
|
|
97412
97585
|
});
|
|
97413
97586
|
|
|
97414
97587
|
// src/commands/snapshot.ts
|
|
97415
|
-
import { join as
|
|
97588
|
+
import { join as join31 } from "path";
|
|
97416
97589
|
function requireSqlConnection9(connection) {
|
|
97417
97590
|
if (!SQL_SYSTEMS6.includes(connection.system)) {
|
|
97418
97591
|
throw new Error(`snapshot currently supports SQL engines only, got: ${connection.system}`);
|
|
@@ -97425,7 +97598,7 @@ function pad2(n) {
|
|
|
97425
97598
|
function defaultSnapshotPath() {
|
|
97426
97599
|
const d = new Date;
|
|
97427
97600
|
const stamp = `${d.getFullYear()}${pad2(d.getMonth() + 1)}${pad2(d.getDate())}-${pad2(d.getHours())}${pad2(d.getMinutes())}${pad2(d.getSeconds())}`;
|
|
97428
|
-
return
|
|
97601
|
+
return join31(".dbcli", "snapshots", `snap-${stamp}.json`);
|
|
97429
97602
|
}
|
|
97430
97603
|
var ALLOWED_FORMATS12, SQL_SYSTEMS6, snapshotCommand;
|
|
97431
97604
|
var init_snapshot = __esm(() => {
|
|
@@ -100414,12 +100587,12 @@ Verification artifact: ${verificationArtifactPath}`);
|
|
|
100414
100587
|
|
|
100415
100588
|
// src/commands/audit.ts
|
|
100416
100589
|
import { rm as rm3, stat as stat8 } from "fs/promises";
|
|
100417
|
-
import { join as
|
|
100590
|
+
import { join as join32 } from "path";
|
|
100418
100591
|
async function resolveAuditPaths(configPath, config) {
|
|
100419
100592
|
const storagePath = await resolveConfigStoragePath(configPath);
|
|
100420
100593
|
const connName = config.effectiveConnectionName || getGlobalConnectionName() || "default";
|
|
100421
|
-
const auditDir =
|
|
100422
|
-
const auditFile =
|
|
100594
|
+
const auditDir = join32(storagePath, ".dbcli", "audit");
|
|
100595
|
+
const auditFile = join32(auditDir, `${connName}.jsonl`);
|
|
100423
100596
|
return { auditDir, connectionName: connName, auditFile };
|
|
100424
100597
|
}
|
|
100425
100598
|
function isAuditDisabled(config) {
|
|
@@ -100847,7 +101020,7 @@ var init_audit = __esm(() => {
|
|
|
100847
101020
|
});
|
|
100848
101021
|
|
|
100849
101022
|
// src/utils/runtime-info.ts
|
|
100850
|
-
import { join as
|
|
101023
|
+
import { join as join33, normalize, relative as relative3, sep as sep5 } from "path";
|
|
100851
101024
|
function normalized(path6) {
|
|
100852
101025
|
return normalize(path6).replaceAll("\\", "/");
|
|
100853
101026
|
}
|
|
@@ -100873,7 +101046,7 @@ async function collectRuntimeInfo(packageVersion) {
|
|
|
100873
101046
|
const launcherPath = process.argv[1] ?? "unknown";
|
|
100874
101047
|
let packageFileVersion = null;
|
|
100875
101048
|
try {
|
|
100876
|
-
const packageFile = Bun.file(
|
|
101049
|
+
const packageFile = Bun.file(join33(packageRoot, "package.json"));
|
|
100877
101050
|
if (await packageFile.exists()) {
|
|
100878
101051
|
const parsed = await packageFile.json();
|
|
100879
101052
|
if (typeof parsed.version === "string" && parsed.version.length > 0) {
|
|
@@ -100901,7 +101074,7 @@ var init_runtime_info = __esm(() => {
|
|
|
100901
101074
|
});
|
|
100902
101075
|
|
|
100903
101076
|
// src/commands/doctor.ts
|
|
100904
|
-
import { join as
|
|
101077
|
+
import { join as join34 } from "path";
|
|
100905
101078
|
import { resolveSrv as resolveSrv2 } from "dns/promises";
|
|
100906
101079
|
function requireSqlConnection12(connection) {
|
|
100907
101080
|
if (!["postgresql", "mysql", "mariadb"].includes(connection.system)) {
|
|
@@ -101013,13 +101186,33 @@ async function collectMongoDoctorResults(config) {
|
|
|
101013
101186
|
const results = [];
|
|
101014
101187
|
const mongoConn = config.connection.system === "mongodb" ? config.connection : null;
|
|
101015
101188
|
const mongoUriString = mongoConn && typeof mongoConn.uri === "string" ? mongoConn.uri : undefined;
|
|
101016
|
-
const
|
|
101189
|
+
const srvProbeUri = mongoUriString ?? (mongoConn?.srv === true && typeof mongoConn.host === "string" && mongoConn.host ? `mongodb+srv://${mongoConn.host}/` : undefined);
|
|
101190
|
+
const srvCheck = await runDoctorChecks.checkMongoSrvConnectivity(srvProbeUri);
|
|
101017
101191
|
if (srvCheck) {
|
|
101018
101192
|
results.push(srvCheck);
|
|
101019
101193
|
if (srvCheck.status === "error") {
|
|
101020
101194
|
return results;
|
|
101021
101195
|
}
|
|
101022
101196
|
}
|
|
101197
|
+
if (mongoConn) {
|
|
101198
|
+
const hasFieldConfig = Boolean(mongoConn.host) || Boolean(mongoConn.user);
|
|
101199
|
+
if (mongoUriString && hasFieldConfig) {
|
|
101200
|
+
results.push({
|
|
101201
|
+
group: "Connection & Data",
|
|
101202
|
+
label: "MongoDB connection fields",
|
|
101203
|
+
status: "warn",
|
|
101204
|
+
message: "Both uri and per-field settings (host/user) are present; uri takes precedence and the per-field values are ignored."
|
|
101205
|
+
});
|
|
101206
|
+
}
|
|
101207
|
+
if (mongoConn.srv === true && typeof mongoConn.port === "number" && mongoConn.port !== 27017) {
|
|
101208
|
+
results.push({
|
|
101209
|
+
group: "Connection & Data",
|
|
101210
|
+
label: "MongoDB SRV port",
|
|
101211
|
+
status: "warn",
|
|
101212
|
+
message: `srv is enabled, so port ${mongoConn.port} is ignored \u2014 SRV records carry their own ports.`
|
|
101213
|
+
});
|
|
101214
|
+
}
|
|
101215
|
+
}
|
|
101023
101216
|
const adapter = AdapterFactory.createMongoDBAdapter(config.connection);
|
|
101024
101217
|
try {
|
|
101025
101218
|
await adapter.connect();
|
|
@@ -101217,7 +101410,7 @@ var init_doctor = __esm(() => {
|
|
|
101217
101410
|
}
|
|
101218
101411
|
},
|
|
101219
101412
|
async checkConfigExists(configPath, existsFn) {
|
|
101220
|
-
const exists = existsFn ? await existsFn(configPath) : await Bun.file(configPath).exists() || await Bun.file(
|
|
101413
|
+
const exists = existsFn ? await existsFn(configPath) : await Bun.file(configPath).exists() || await Bun.file(join34(configPath, "config.json")).exists();
|
|
101221
101414
|
return {
|
|
101222
101415
|
group: "Configuration",
|
|
101223
101416
|
label: "Config exists",
|
|
@@ -101301,7 +101494,17 @@ var init_doctor = __esm(() => {
|
|
|
101301
101494
|
if (!uri || !uri.startsWith("mongodb+srv://")) {
|
|
101302
101495
|
return null;
|
|
101303
101496
|
}
|
|
101304
|
-
|
|
101497
|
+
let url;
|
|
101498
|
+
try {
|
|
101499
|
+
url = new URL(uri);
|
|
101500
|
+
} catch {
|
|
101501
|
+
return {
|
|
101502
|
+
group: "Environment",
|
|
101503
|
+
label: "MongoDB SRV lookup",
|
|
101504
|
+
status: "error",
|
|
101505
|
+
message: `Cannot parse ${uri} as a connection string \u2014 check the host value`
|
|
101506
|
+
};
|
|
101507
|
+
}
|
|
101305
101508
|
const srvName = `_mongodb._tcp.${url.hostname}`;
|
|
101306
101509
|
const resolveSrvFn = deps.resolveSrvFn ?? resolveSrv2;
|
|
101307
101510
|
const fetchFn = deps.fetchFn ?? fetch;
|
|
@@ -101384,7 +101587,7 @@ var init_doctor = __esm(() => {
|
|
|
101384
101587
|
async checkV2Config(configPath) {
|
|
101385
101588
|
const results = [];
|
|
101386
101589
|
const storagePath = await resolveConfigStoragePath(configPath);
|
|
101387
|
-
const configFile = Bun.file(
|
|
101590
|
+
const configFile = Bun.file(join34(storagePath, "config.json"));
|
|
101388
101591
|
if (!await configFile.exists())
|
|
101389
101592
|
return results;
|
|
101390
101593
|
let raw;
|
|
@@ -101424,7 +101627,7 @@ var init_doctor = __esm(() => {
|
|
|
101424
101627
|
}
|
|
101425
101628
|
for (const [name2, conn] of Object.entries(config.connections)) {
|
|
101426
101629
|
if (conn.envFile) {
|
|
101427
|
-
const envPath =
|
|
101630
|
+
const envPath = join34(storagePath, conn.envFile);
|
|
101428
101631
|
const exists = await Bun.file(envPath).exists();
|
|
101429
101632
|
results.push({
|
|
101430
101633
|
group: "Configuration",
|
|
@@ -101534,7 +101737,7 @@ var init_doctor = __esm(() => {
|
|
|
101534
101737
|
}
|
|
101535
101738
|
try {
|
|
101536
101739
|
const schemaConnName = await getSchemaIsolationConnectionName(configPath);
|
|
101537
|
-
const indexPath =
|
|
101740
|
+
const indexPath = join34(resolveSchemaPath(storagePath, schemaConnName), "index.json");
|
|
101538
101741
|
const indexFile = Bun.file(indexPath);
|
|
101539
101742
|
let indexParsed = null;
|
|
101540
101743
|
if (await indexFile.exists()) {
|
|
@@ -101643,9 +101846,9 @@ function flattenCommandTree(root) {
|
|
|
101643
101846
|
}
|
|
101644
101847
|
|
|
101645
101848
|
// src/commands/completion.ts
|
|
101646
|
-
import { join as
|
|
101849
|
+
import { join as join35 } from "path";
|
|
101647
101850
|
import { homedir as homedir3 } from "os";
|
|
101648
|
-
import { mkdir as
|
|
101851
|
+
import { mkdir as mkdir16 } from "fs/promises";
|
|
101649
101852
|
function resolveHome() {
|
|
101650
101853
|
return process.env.HOME ?? homedir3();
|
|
101651
101854
|
}
|
|
@@ -101895,11 +102098,11 @@ function getInstallPath2(shell) {
|
|
|
101895
102098
|
const home = resolveHome();
|
|
101896
102099
|
switch (shell) {
|
|
101897
102100
|
case "bash":
|
|
101898
|
-
return
|
|
102101
|
+
return join35(home, ".bashrc");
|
|
101899
102102
|
case "zsh":
|
|
101900
|
-
return
|
|
102103
|
+
return join35(home, ".zshrc");
|
|
101901
102104
|
case "fish":
|
|
101902
|
-
return
|
|
102105
|
+
return join35(home, ".config", "fish", "completions", "dbcli.fish");
|
|
101903
102106
|
default:
|
|
101904
102107
|
throw new Error(`Unsupported shell: ${shell}. Supported: bash, zsh, fish`);
|
|
101905
102108
|
}
|
|
@@ -101917,8 +102120,8 @@ function detectShell() {
|
|
|
101917
102120
|
async function installCompletion(shell, script) {
|
|
101918
102121
|
const targetPath = getInstallPath2(shell);
|
|
101919
102122
|
if (shell === "fish") {
|
|
101920
|
-
const dir =
|
|
101921
|
-
await
|
|
102123
|
+
const dir = join35(resolveHome(), ".config", "fish", "completions");
|
|
102124
|
+
await mkdir16(dir, { recursive: true });
|
|
101922
102125
|
await Bun.file(targetPath).write(script);
|
|
101923
102126
|
console.log(colors.success(`\u2713 Fish completion installed to ${targetPath}`));
|
|
101924
102127
|
return;
|
|
@@ -102902,7 +103105,7 @@ var init_command_registry = __esm(() => {
|
|
|
102902
103105
|
|
|
102903
103106
|
// src/commands/shell.ts
|
|
102904
103107
|
import { createInterface as createInterface3 } from "readline";
|
|
102905
|
-
import { join as
|
|
103108
|
+
import { join as join36 } from "path";
|
|
102906
103109
|
import { homedir as homedir4 } from "os";
|
|
102907
103110
|
function requireSqlConnection13(connection) {
|
|
102908
103111
|
if (!["postgresql", "mysql", "mariadb"].includes(connection.system)) {
|
|
@@ -103096,7 +103299,7 @@ var init_shell3 = __esm(() => {
|
|
|
103096
103299
|
init_message_loader();
|
|
103097
103300
|
init_es_shell();
|
|
103098
103301
|
import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
103099
|
-
HISTORY_PATH =
|
|
103302
|
+
HISTORY_PATH = join36(homedir4(), ".dbcli_history");
|
|
103100
103303
|
shellCommand = new Command("shell").description("Interactive database shell with auto-completion and syntax highlighting").option("--sql", "SQL-only mode (skip dbcli command parsing)").action(async (options, command) => {
|
|
103101
103304
|
const configPath = resolveConfigPath(command);
|
|
103102
103305
|
await runShell(options, configPath);
|
|
@@ -103941,7 +104144,7 @@ var init_migrate = __esm(() => {
|
|
|
103941
104144
|
});
|
|
103942
104145
|
|
|
103943
104146
|
// src/commands/use.ts
|
|
103944
|
-
import { join as
|
|
104147
|
+
import { join as join37 } from "path";
|
|
103945
104148
|
async function switchDefault(configPath, name2, config, options = {}) {
|
|
103946
104149
|
const connection = config.connections[name2];
|
|
103947
104150
|
if (!connection) {
|
|
@@ -103984,7 +104187,7 @@ function listConnectionIdentities(config) {
|
|
|
103984
104187
|
}
|
|
103985
104188
|
async function ensureV2Config(configPath) {
|
|
103986
104189
|
const storagePath = await resolveConfigStoragePath(configPath);
|
|
103987
|
-
const configFile = Bun.file(
|
|
104190
|
+
const configFile = Bun.file(join37(storagePath, "config.json"));
|
|
103988
104191
|
const legacyFile = Bun.file(configPath);
|
|
103989
104192
|
if (!await configFile.exists() && !await legacyFile.exists()) {
|
|
103990
104193
|
throw new ConfigError(t("init.config_not_found"));
|
|
@@ -104142,7 +104345,7 @@ var init_sql_metadata = __esm(() => {
|
|
|
104142
104345
|
});
|
|
104143
104346
|
|
|
104144
104347
|
// src/proxy/events.ts
|
|
104145
|
-
import { appendFile as appendFile2, mkdir as
|
|
104348
|
+
import { appendFile as appendFile2, mkdir as mkdir17, readFile as readFile8, stat as stat9 } from "fs/promises";
|
|
104146
104349
|
import { dirname as dirname13 } from "path";
|
|
104147
104350
|
function hasSql(e) {
|
|
104148
104351
|
return e.type === "query_observed" || e.type === "query_completed" || e.type === "query_errored";
|
|
@@ -104182,7 +104385,7 @@ class EventWriter {
|
|
|
104182
104385
|
}
|
|
104183
104386
|
async writeInternal(event) {
|
|
104184
104387
|
if (!this.dirEnsured) {
|
|
104185
|
-
await
|
|
104388
|
+
await mkdir17(dirname13(this.path), { recursive: true });
|
|
104186
104389
|
this.dirEnsured = true;
|
|
104187
104390
|
}
|
|
104188
104391
|
if (!this.initialized) {
|
|
@@ -105111,7 +105314,7 @@ function renderAnalysisText(report, top) {
|
|
|
105111
105314
|
}
|
|
105112
105315
|
|
|
105113
105316
|
// src/commands/proxy.ts
|
|
105114
|
-
import { join as
|
|
105317
|
+
import { join as join38 } from "path";
|
|
105115
105318
|
function parseHostPort(value) {
|
|
105116
105319
|
const idx = value.lastIndexOf(":");
|
|
105117
105320
|
if (idx <= 0 || idx === value.length - 1) {
|
|
@@ -105174,7 +105377,7 @@ async function runProxy(subcommandEngine, options, command) {
|
|
|
105174
105377
|
target: options.target,
|
|
105175
105378
|
connection
|
|
105176
105379
|
});
|
|
105177
|
-
const eventsPath = options.events ??
|
|
105380
|
+
const eventsPath = options.events ?? join38(".dbcli", "proxy", "events.jsonl");
|
|
105178
105381
|
const slowMs = Number(options.slowMs ?? 1000);
|
|
105179
105382
|
if (!Number.isFinite(slowMs) || slowMs < 0) {
|
|
105180
105383
|
throw new Error(`Invalid --slow-ms "${options.slowMs}". Expected a non-negative number`);
|
|
@@ -105223,7 +105426,7 @@ async function runProxy(subcommandEngine, options, command) {
|
|
|
105223
105426
|
}
|
|
105224
105427
|
}
|
|
105225
105428
|
function addCommonOptions(cmd) {
|
|
105226
|
-
return cmd.option("--listen <host:port>", "Local proxy listen address (required)").option("--target <host:port>", "Upstream DB target (optional when config provides host/port)").option("--events <path>", "Event JSONL path",
|
|
105429
|
+
return cmd.option("--listen <host:port>", "Local proxy listen address (required)").option("--target <host:port>", "Upstream DB target (optional when config provides host/port)").option("--events <path>", "Event JSONL path", join38(".dbcli", "proxy", "events.jsonl")).option("--slow-ms <number>", "Threshold (ms); queries at/above it get slow:true in the event + a terminal warning", "1000").option("--redact <mode>", "SQL redaction: none | literals", "none").option("--format <format>", "Runtime status output: text | json", "text");
|
|
105227
105430
|
}
|
|
105228
105431
|
function parseNonNegInt(value, flag, fallback) {
|
|
105229
105432
|
if (value === undefined)
|
|
@@ -105241,7 +105444,7 @@ async function runAnalyze(options) {
|
|
|
105241
105444
|
const top = parseNonNegInt(options.top, "top", 20);
|
|
105242
105445
|
const slowMs = parseNonNegInt(options.slowMs, "slow-ms", 1000);
|
|
105243
105446
|
const nPlusOne = parseNonNegInt(options.nPlusOne, "n-plus-one", 10);
|
|
105244
|
-
const eventsPath = options.events ??
|
|
105447
|
+
const eventsPath = options.events ?? join38(".dbcli", "proxy", "events.jsonl");
|
|
105245
105448
|
const { events, malformedLines, files } = await readEvents(eventsPath, {
|
|
105246
105449
|
includeRotated: options.includeRotated !== false
|
|
105247
105450
|
});
|
|
@@ -105288,7 +105491,7 @@ var init_proxy = __esm(() => {
|
|
|
105288
105491
|
});
|
|
105289
105492
|
}
|
|
105290
105493
|
ANALYZE_FORMATS = ["json", "text"];
|
|
105291
|
-
proxyCommand.command("analyze").description("Analyze a proxy event log offline (no DB connection)").option("--events <path>", "Event JSONL path",
|
|
105494
|
+
proxyCommand.command("analyze").description("Analyze a proxy event log offline (no DB connection)").option("--events <path>", "Event JSONL path", join38(".dbcli", "proxy", "events.jsonl")).option("--format <format>", "Output format: json | text", "json").option("--top <number>", "Rows shown in text + suggestedCommands depth", "20").option("--slow-ms <number>", "Slow-query threshold (ms) for slowCount", "1000").option("--n-plus-one <number>", "Min repeats per (session,fingerprint) to flag N+1", "10").option("--no-include-rotated", "Do not merge the rotated <events>.1 segment").action(async (options) => {
|
|
105292
105495
|
await runAnalyze(options);
|
|
105293
105496
|
});
|
|
105294
105497
|
addCommonOptions(proxyCommand).action(async (options, command) => {
|
|
@@ -105497,7 +105700,7 @@ var init_backfill_artifact = __esm(() => {
|
|
|
105497
105700
|
|
|
105498
105701
|
// src/commands/backfill.ts
|
|
105499
105702
|
import { dirname as dirname14, resolve as resolve9 } from "path";
|
|
105500
|
-
import { mkdir as
|
|
105703
|
+
import { mkdir as mkdir18 } from "fs/promises";
|
|
105501
105704
|
function identityFor(config, name2) {
|
|
105502
105705
|
const connection = config.connections[name2];
|
|
105503
105706
|
if (!connection) {
|
|
@@ -105547,7 +105750,7 @@ var init_backfill = __esm(() => {
|
|
|
105547
105750
|
return;
|
|
105548
105751
|
}
|
|
105549
105752
|
const out = resolve9(options.out ?? `.dbcli/backfills/${artifact2.source.sha256.slice(0, 12)}.json`);
|
|
105550
|
-
await
|
|
105753
|
+
await mkdir18(dirname14(out), { recursive: true });
|
|
105551
105754
|
await Bun.write(out, JSON.stringify(artifact2, null, 2) + `
|
|
105552
105755
|
`);
|
|
105553
105756
|
console.log(JSON.stringify({ path: out, artifact: artifact2 }, null, 2));
|
|
@@ -105862,7 +106065,7 @@ async function claimUpdateHint(configPath, kind, sessionKey, value) {
|
|
|
105862
106065
|
// src/cli.ts
|
|
105863
106066
|
init_program();
|
|
105864
106067
|
init_cli_error();
|
|
105865
|
-
import { join as
|
|
106068
|
+
import { join as join39 } from "path";
|
|
105866
106069
|
import { writeSync as writeSync2 } from "fs";
|
|
105867
106070
|
import { format } from "util";
|
|
105868
106071
|
function installSynchronousRedirectedStdout() {
|
|
@@ -105990,7 +106193,7 @@ program2.hook("preAction", (thisCommand, actionCommand) => {
|
|
|
105990
106193
|
try {
|
|
105991
106194
|
let cache = null;
|
|
105992
106195
|
try {
|
|
105993
|
-
const cacheFile = Bun.file(
|
|
106196
|
+
const cacheFile = Bun.file(join39(configPath, "version-check.json"));
|
|
105994
106197
|
if (await cacheFile.exists()) {
|
|
105995
106198
|
cache = await cacheFile.json();
|
|
105996
106199
|
}
|