@carllee1983/dbcli 1.5.0 → 1.6.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/CHANGELOG.md +30 -0
- package/README.dev.md +51 -54
- package/README.md +45 -17
- package/README.zh-TW.md +43 -15
- package/assets/SKILL.md +63 -506
- package/assets/reference.md +371 -0
- package/dist/cli.mjs +975 -424
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -6146,7 +6146,10 @@ var init_validation = __esm(() => {
|
|
|
6146
6146
|
password: exports_external.union([exports_external.string(), EnvRefSchema]).default(""),
|
|
6147
6147
|
database: StringOrEnvRef
|
|
6148
6148
|
});
|
|
6149
|
-
ConnectionConfigSchema = exports_external.union([
|
|
6149
|
+
ConnectionConfigSchema = exports_external.union([
|
|
6150
|
+
SqlConnectionConfigSchema,
|
|
6151
|
+
MongoDBConnectionConfigSchema
|
|
6152
|
+
]);
|
|
6150
6153
|
PermissionSchema = exports_external.enum(["query-only", "read-write", "data-admin", "admin"]).default("query-only");
|
|
6151
6154
|
MetadataSchema = exports_external.object({
|
|
6152
6155
|
createdAt: exports_external.string().datetime().optional(),
|
|
@@ -6173,7 +6176,10 @@ var init_validation = __esm(() => {
|
|
|
6173
6176
|
permission: PermissionSchema,
|
|
6174
6177
|
envFile: exports_external.string().optional()
|
|
6175
6178
|
});
|
|
6176
|
-
NamedConnectionSchema = exports_external.union([
|
|
6179
|
+
NamedConnectionSchema = exports_external.union([
|
|
6180
|
+
SqlNamedConnectionSchema,
|
|
6181
|
+
MongoDBNamedConnectionSchema
|
|
6182
|
+
]);
|
|
6177
6183
|
DbcliConfigV2Schema = exports_external.object({
|
|
6178
6184
|
version: exports_external.literal(2),
|
|
6179
6185
|
default: exports_external.string().min(1),
|
|
@@ -7297,16 +7303,16 @@ var init_esm = __esm(() => {
|
|
|
7297
7303
|
});
|
|
7298
7304
|
|
|
7299
7305
|
// src/utils/schema-path.ts
|
|
7300
|
-
import { join as
|
|
7306
|
+
import { join as join3 } from "path";
|
|
7301
7307
|
function resolveSchemaPath(dbcliPath, connectionName) {
|
|
7302
7308
|
if (!connectionName)
|
|
7303
|
-
return
|
|
7304
|
-
return
|
|
7309
|
+
return join3(dbcliPath, "schemas");
|
|
7310
|
+
return join3(dbcliPath, "schemas", connectionName);
|
|
7305
7311
|
}
|
|
7306
7312
|
var init_schema_path = () => {};
|
|
7307
7313
|
|
|
7308
7314
|
// src/core/schema-cache.ts
|
|
7309
|
-
import { join as
|
|
7315
|
+
import { join as join4 } from "path";
|
|
7310
7316
|
|
|
7311
7317
|
class SchemaCacheManager {
|
|
7312
7318
|
cache;
|
|
@@ -7332,13 +7338,13 @@ class SchemaCacheManager {
|
|
|
7332
7338
|
}
|
|
7333
7339
|
async initialize() {
|
|
7334
7340
|
try {
|
|
7335
|
-
const indexPath =
|
|
7341
|
+
const indexPath = join4(this.schemaRoot, "index.json");
|
|
7336
7342
|
const indexFile = Bun.file(indexPath);
|
|
7337
7343
|
if (await indexFile.exists()) {
|
|
7338
7344
|
const indexContent = await indexFile.text();
|
|
7339
7345
|
this.index = JSON.parse(indexContent);
|
|
7340
7346
|
}
|
|
7341
|
-
const hotPath =
|
|
7347
|
+
const hotPath = join4(this.schemaRoot, "hot-schemas.json");
|
|
7342
7348
|
const hotFile = Bun.file(hotPath);
|
|
7343
7349
|
if (await hotFile.exists()) {
|
|
7344
7350
|
const hotContent = await hotFile.text();
|
|
@@ -7371,7 +7377,7 @@ class SchemaCacheManager {
|
|
|
7371
7377
|
return null;
|
|
7372
7378
|
}
|
|
7373
7379
|
try {
|
|
7374
|
-
const filePath =
|
|
7380
|
+
const filePath = join4(this.schemaRoot, tableInfo.file);
|
|
7375
7381
|
const file = Bun.file(filePath);
|
|
7376
7382
|
if (!await file.exists()) {
|
|
7377
7383
|
console.error(`Cold table file not found: ${tableInfo.file} for table ${tableName}`);
|
|
@@ -7426,12 +7432,12 @@ var init_schema_cache = __esm(() => {
|
|
|
7426
7432
|
});
|
|
7427
7433
|
|
|
7428
7434
|
// src/core/schema-index.ts
|
|
7429
|
-
import { join as
|
|
7435
|
+
import { join as join5 } from "path";
|
|
7430
7436
|
|
|
7431
7437
|
class SchemaIndexBuilder {
|
|
7432
7438
|
static async loadIndex(dbcliPath, connectionName) {
|
|
7433
7439
|
try {
|
|
7434
|
-
const indexPath =
|
|
7440
|
+
const indexPath = join5(resolveSchemaPath(dbcliPath, connectionName), "index.json");
|
|
7435
7441
|
const file = Bun.file(indexPath);
|
|
7436
7442
|
if (!await file.exists()) {
|
|
7437
7443
|
return null;
|
|
@@ -7478,7 +7484,7 @@ class SchemaIndexBuilder {
|
|
|
7478
7484
|
try {
|
|
7479
7485
|
const schemasDir = resolveSchemaPath(dbcliPath, connectionName);
|
|
7480
7486
|
await this.ensureDir(schemasDir);
|
|
7481
|
-
const indexPath =
|
|
7487
|
+
const indexPath = join5(schemasDir, "index.json");
|
|
7482
7488
|
const indexFile = Bun.file(indexPath);
|
|
7483
7489
|
await indexFile.write(JSON.stringify(index, null, 2));
|
|
7484
7490
|
} catch (error) {
|
|
@@ -7524,7 +7530,7 @@ var exports_schema_loader = {};
|
|
|
7524
7530
|
__export(exports_schema_loader, {
|
|
7525
7531
|
SchemaLayeredLoader: () => SchemaLayeredLoader2
|
|
7526
7532
|
});
|
|
7527
|
-
import { join as
|
|
7533
|
+
import { join as join6 } from "path";
|
|
7528
7534
|
|
|
7529
7535
|
class SchemaLayeredLoader2 {
|
|
7530
7536
|
dbcliPath;
|
|
@@ -7591,7 +7597,7 @@ class SchemaLayeredLoader2 {
|
|
|
7591
7597
|
}
|
|
7592
7598
|
async ensureDirectories() {
|
|
7593
7599
|
const base = resolveSchemaPath(this.dbcliPath, this.connectionName);
|
|
7594
|
-
const dirs = [base,
|
|
7600
|
+
const dirs = [base, join6(base, "cold")];
|
|
7595
7601
|
for (const dir of dirs) {
|
|
7596
7602
|
try {
|
|
7597
7603
|
const dirFile = Bun.file(dir);
|
|
@@ -10287,13 +10293,13 @@ var PromisePolyfill;
|
|
|
10287
10293
|
var init_promise_polyfill = __esm(() => {
|
|
10288
10294
|
PromisePolyfill = class PromisePolyfill extends Promise {
|
|
10289
10295
|
static withResolver() {
|
|
10290
|
-
let
|
|
10296
|
+
let resolve2;
|
|
10291
10297
|
let reject;
|
|
10292
10298
|
const promise = new Promise((res, rej) => {
|
|
10293
|
-
|
|
10299
|
+
resolve2 = res;
|
|
10294
10300
|
reject = rej;
|
|
10295
10301
|
});
|
|
10296
|
-
return { promise, resolve, reject };
|
|
10302
|
+
return { promise, resolve: resolve2, reject };
|
|
10297
10303
|
}
|
|
10298
10304
|
};
|
|
10299
10305
|
});
|
|
@@ -10313,7 +10319,7 @@ function createPrompt(view) {
|
|
|
10313
10319
|
output
|
|
10314
10320
|
});
|
|
10315
10321
|
const screen = new ScreenManager(rl);
|
|
10316
|
-
const { promise, resolve, reject } = PromisePolyfill.withResolver();
|
|
10322
|
+
const { promise, resolve: resolve2, reject } = PromisePolyfill.withResolver();
|
|
10317
10323
|
const cancel = () => reject(new CancelPromptError);
|
|
10318
10324
|
if (signal) {
|
|
10319
10325
|
const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
|
|
@@ -10337,7 +10343,7 @@ function createPrompt(view) {
|
|
|
10337
10343
|
cycle(() => {
|
|
10338
10344
|
try {
|
|
10339
10345
|
const nextView = view(config, (value) => {
|
|
10340
|
-
setImmediate(() =>
|
|
10346
|
+
setImmediate(() => resolve2(value));
|
|
10341
10347
|
});
|
|
10342
10348
|
const [content, bottomContent] = typeof nextView === "string" ? [nextView] : nextView;
|
|
10343
10349
|
screen.render(content, bottomContent);
|
|
@@ -23694,7 +23700,7 @@ var require_dist = __commonJS((exports) => {
|
|
|
23694
23700
|
function parse(stream, callback) {
|
|
23695
23701
|
const parser = new parser_1.Parser;
|
|
23696
23702
|
stream.on("data", (buffer) => parser.parse(buffer, callback));
|
|
23697
|
-
return new Promise((
|
|
23703
|
+
return new Promise((resolve2) => stream.on("end", () => resolve2()));
|
|
23698
23704
|
}
|
|
23699
23705
|
exports.parse = parse;
|
|
23700
23706
|
});
|
|
@@ -24373,12 +24379,12 @@ var require_client = __commonJS((exports, module) => {
|
|
|
24373
24379
|
this._connect(callback);
|
|
24374
24380
|
return;
|
|
24375
24381
|
}
|
|
24376
|
-
return new this._Promise((
|
|
24382
|
+
return new this._Promise((resolve2, reject) => {
|
|
24377
24383
|
this._connect((error) => {
|
|
24378
24384
|
if (error) {
|
|
24379
24385
|
reject(error);
|
|
24380
24386
|
} else {
|
|
24381
|
-
|
|
24387
|
+
resolve2(this);
|
|
24382
24388
|
}
|
|
24383
24389
|
});
|
|
24384
24390
|
});
|
|
@@ -24710,8 +24716,8 @@ var require_client = __commonJS((exports, module) => {
|
|
|
24710
24716
|
readTimeout = config.query_timeout || this.connectionParameters.query_timeout;
|
|
24711
24717
|
query = new Query(config, values, callback);
|
|
24712
24718
|
if (!query.callback) {
|
|
24713
|
-
result = new this._Promise((
|
|
24714
|
-
query.callback = (err, res) => err ? reject(err) :
|
|
24719
|
+
result = new this._Promise((resolve2, reject) => {
|
|
24720
|
+
query.callback = (err, res) => err ? reject(err) : resolve2(res);
|
|
24715
24721
|
}).catch((err) => {
|
|
24716
24722
|
Error.captureStackTrace(err);
|
|
24717
24723
|
throw err;
|
|
@@ -24786,8 +24792,8 @@ var require_client = __commonJS((exports, module) => {
|
|
|
24786
24792
|
if (cb) {
|
|
24787
24793
|
this.connection.once("end", cb);
|
|
24788
24794
|
} else {
|
|
24789
|
-
return new this._Promise((
|
|
24790
|
-
this.connection.once("end",
|
|
24795
|
+
return new this._Promise((resolve2) => {
|
|
24796
|
+
this.connection.once("end", resolve2);
|
|
24791
24797
|
});
|
|
24792
24798
|
}
|
|
24793
24799
|
}
|
|
@@ -24834,8 +24840,8 @@ var require_pg_pool = __commonJS((exports, module) => {
|
|
|
24834
24840
|
const cb = function(err, client) {
|
|
24835
24841
|
err ? rej(err) : res(client);
|
|
24836
24842
|
};
|
|
24837
|
-
const result = new Promise2(function(
|
|
24838
|
-
res =
|
|
24843
|
+
const result = new Promise2(function(resolve2, reject) {
|
|
24844
|
+
res = resolve2;
|
|
24839
24845
|
rej = reject;
|
|
24840
24846
|
}).catch((err) => {
|
|
24841
24847
|
Error.captureStackTrace(err);
|
|
@@ -24896,7 +24902,7 @@ var require_pg_pool = __commonJS((exports, module) => {
|
|
|
24896
24902
|
if (typeof Promise2.try === "function") {
|
|
24897
24903
|
return Promise2.try(f);
|
|
24898
24904
|
}
|
|
24899
|
-
return new Promise2((
|
|
24905
|
+
return new Promise2((resolve2) => resolve2(f()));
|
|
24900
24906
|
}
|
|
24901
24907
|
_isFull() {
|
|
24902
24908
|
return this._clients.length >= this.options.max;
|
|
@@ -25272,8 +25278,8 @@ var require_query2 = __commonJS((exports, module) => {
|
|
|
25272
25278
|
NativeQuery.prototype._getPromise = function() {
|
|
25273
25279
|
if (this._promise)
|
|
25274
25280
|
return this._promise;
|
|
25275
|
-
this._promise = new Promise(function(
|
|
25276
|
-
this._once("end",
|
|
25281
|
+
this._promise = new Promise(function(resolve2, reject) {
|
|
25282
|
+
this._once("end", resolve2);
|
|
25277
25283
|
this._once("error", reject);
|
|
25278
25284
|
}.bind(this));
|
|
25279
25285
|
return this._promise;
|
|
@@ -25447,12 +25453,12 @@ var require_client2 = __commonJS((exports, module) => {
|
|
|
25447
25453
|
this._connect(callback);
|
|
25448
25454
|
return;
|
|
25449
25455
|
}
|
|
25450
|
-
return new this._Promise((
|
|
25456
|
+
return new this._Promise((resolve2, reject) => {
|
|
25451
25457
|
this._connect((error) => {
|
|
25452
25458
|
if (error) {
|
|
25453
25459
|
reject(error);
|
|
25454
25460
|
} else {
|
|
25455
|
-
|
|
25461
|
+
resolve2(this);
|
|
25456
25462
|
}
|
|
25457
25463
|
});
|
|
25458
25464
|
});
|
|
@@ -25476,8 +25482,8 @@ var require_client2 = __commonJS((exports, module) => {
|
|
|
25476
25482
|
query = new NativeQuery(config, values, callback);
|
|
25477
25483
|
if (!query.callback) {
|
|
25478
25484
|
let resolveOut, rejectOut;
|
|
25479
|
-
result = new this._Promise((
|
|
25480
|
-
resolveOut =
|
|
25485
|
+
result = new this._Promise((resolve2, reject) => {
|
|
25486
|
+
resolveOut = resolve2;
|
|
25481
25487
|
rejectOut = reject;
|
|
25482
25488
|
}).catch((err) => {
|
|
25483
25489
|
Error.captureStackTrace(err);
|
|
@@ -25535,8 +25541,8 @@ var require_client2 = __commonJS((exports, module) => {
|
|
|
25535
25541
|
}
|
|
25536
25542
|
let result;
|
|
25537
25543
|
if (!cb) {
|
|
25538
|
-
result = new this._Promise(function(
|
|
25539
|
-
cb = (err) => err ? reject(err) :
|
|
25544
|
+
result = new this._Promise(function(resolve2, reject) {
|
|
25545
|
+
cb = (err) => err ? reject(err) : resolve2();
|
|
25540
25546
|
});
|
|
25541
25547
|
}
|
|
25542
25548
|
this.native.end(function() {
|
|
@@ -44473,7 +44479,7 @@ var require_named_placeholders = __commonJS((exports, module) => {
|
|
|
44473
44479
|
}
|
|
44474
44480
|
return s;
|
|
44475
44481
|
}
|
|
44476
|
-
function
|
|
44482
|
+
function join8(tree) {
|
|
44477
44483
|
if (tree.length === 1) {
|
|
44478
44484
|
return tree;
|
|
44479
44485
|
}
|
|
@@ -44499,7 +44505,7 @@ var require_named_placeholders = __commonJS((exports, module) => {
|
|
|
44499
44505
|
if (cache && (tree = cache.get(query))) {
|
|
44500
44506
|
return toArrayParams(tree, paramsObj);
|
|
44501
44507
|
}
|
|
44502
|
-
tree =
|
|
44508
|
+
tree = join8(parse(query));
|
|
44503
44509
|
if (cache) {
|
|
44504
44510
|
cache.set(query, tree);
|
|
44505
44511
|
}
|
|
@@ -44650,11 +44656,11 @@ var require_connection2 = __commonJS((exports, module) => {
|
|
|
44650
44656
|
this.addCommand(handshakeCommand);
|
|
44651
44657
|
if (shouldTrace(connectChannel)) {
|
|
44652
44658
|
const config = this.config;
|
|
44653
|
-
tracePromise(connectChannel, () => new Promise((
|
|
44659
|
+
tracePromise(connectChannel, () => new Promise((resolve2, reject) => {
|
|
44654
44660
|
let onConnect, onError;
|
|
44655
44661
|
onConnect = (param) => {
|
|
44656
44662
|
this.removeListener("error", onError);
|
|
44657
|
-
|
|
44663
|
+
resolve2(param);
|
|
44658
44664
|
};
|
|
44659
44665
|
onError = (err) => {
|
|
44660
44666
|
this.removeListener("connect", onConnect);
|
|
@@ -45017,9 +45023,9 @@ var require_connection2 = __commonJS((exports, module) => {
|
|
|
45017
45023
|
};
|
|
45018
45024
|
}, null, cmdQuery.onResult);
|
|
45019
45025
|
} else if (shouldTrace(queryChannel)) {
|
|
45020
|
-
tracePromise(queryChannel, () => new Promise((
|
|
45026
|
+
tracePromise(queryChannel, () => new Promise((resolve2, reject) => {
|
|
45021
45027
|
cmdQuery.once("error", reject);
|
|
45022
|
-
cmdQuery.once("end", () =>
|
|
45028
|
+
cmdQuery.once("end", () => resolve2());
|
|
45023
45029
|
this.addCommand(cmdQuery);
|
|
45024
45030
|
}), () => {
|
|
45025
45031
|
const server = getServerContext(this.config);
|
|
@@ -45145,12 +45151,12 @@ var require_connection2 = __commonJS((exports, module) => {
|
|
|
45145
45151
|
};
|
|
45146
45152
|
}, null, origExecCb);
|
|
45147
45153
|
} else if (shouldTrace(executeChannel)) {
|
|
45148
|
-
tracePromise(executeChannel, () => new Promise((
|
|
45154
|
+
tracePromise(executeChannel, () => new Promise((resolve2, reject) => {
|
|
45149
45155
|
prepareAndExecute((err) => {
|
|
45150
45156
|
executeCommand.emit("error", err);
|
|
45151
45157
|
});
|
|
45152
45158
|
executeCommand.once("error", reject);
|
|
45153
|
-
executeCommand.once("end", () =>
|
|
45159
|
+
executeCommand.once("end", () => resolve2());
|
|
45154
45160
|
}), () => {
|
|
45155
45161
|
const server = getServerContext(this.config);
|
|
45156
45162
|
return {
|
|
@@ -45367,7 +45373,7 @@ var require_connection2 = __commonJS((exports, module) => {
|
|
|
45367
45373
|
|
|
45368
45374
|
// node_modules/mysql2/lib/promise/make_done_cb.js
|
|
45369
45375
|
var require_make_done_cb = __commonJS((exports, module) => {
|
|
45370
|
-
function makeDoneCb(
|
|
45376
|
+
function makeDoneCb(resolve2, reject, localErr) {
|
|
45371
45377
|
return function(err, rows, fields) {
|
|
45372
45378
|
if (err) {
|
|
45373
45379
|
localErr.message = err.message;
|
|
@@ -45378,7 +45384,7 @@ var require_make_done_cb = __commonJS((exports, module) => {
|
|
|
45378
45384
|
localErr.sqlMessage = err.sqlMessage;
|
|
45379
45385
|
reject(localErr);
|
|
45380
45386
|
} else {
|
|
45381
|
-
|
|
45387
|
+
resolve2([rows, fields]);
|
|
45382
45388
|
}
|
|
45383
45389
|
};
|
|
45384
45390
|
}
|
|
@@ -45397,8 +45403,8 @@ var require_prepared_statement_info = __commonJS((exports, module) => {
|
|
|
45397
45403
|
execute(parameters) {
|
|
45398
45404
|
const s = this.statement;
|
|
45399
45405
|
const localErr = new Error;
|
|
45400
|
-
return new this.Promise((
|
|
45401
|
-
const done = makeDoneCb(
|
|
45406
|
+
return new this.Promise((resolve2, reject) => {
|
|
45407
|
+
const done = makeDoneCb(resolve2, reject, localErr);
|
|
45402
45408
|
if (parameters) {
|
|
45403
45409
|
s.execute(parameters, done);
|
|
45404
45410
|
} else {
|
|
@@ -45407,9 +45413,9 @@ var require_prepared_statement_info = __commonJS((exports, module) => {
|
|
|
45407
45413
|
});
|
|
45408
45414
|
}
|
|
45409
45415
|
close() {
|
|
45410
|
-
return new this.Promise((
|
|
45416
|
+
return new this.Promise((resolve2) => {
|
|
45411
45417
|
this.statement.close();
|
|
45412
|
-
|
|
45418
|
+
resolve2();
|
|
45413
45419
|
});
|
|
45414
45420
|
}
|
|
45415
45421
|
}
|
|
@@ -45468,8 +45474,8 @@ var require_connection3 = __commonJS((exports, module) => {
|
|
|
45468
45474
|
if (typeof params === "function") {
|
|
45469
45475
|
throw new Error("Callback function is not available with promise clients.");
|
|
45470
45476
|
}
|
|
45471
|
-
return new this.Promise((
|
|
45472
|
-
const done = makeDoneCb(
|
|
45477
|
+
return new this.Promise((resolve2, reject) => {
|
|
45478
|
+
const done = makeDoneCb(resolve2, reject, localErr);
|
|
45473
45479
|
if (params !== undefined) {
|
|
45474
45480
|
c.query(query, params, done);
|
|
45475
45481
|
} else {
|
|
@@ -45483,8 +45489,8 @@ var require_connection3 = __commonJS((exports, module) => {
|
|
|
45483
45489
|
if (typeof params === "function") {
|
|
45484
45490
|
throw new Error("Callback function is not available with promise clients.");
|
|
45485
45491
|
}
|
|
45486
|
-
return new this.Promise((
|
|
45487
|
-
const done = makeDoneCb(
|
|
45492
|
+
return new this.Promise((resolve2, reject) => {
|
|
45493
|
+
const done = makeDoneCb(resolve2, reject, localErr);
|
|
45488
45494
|
if (params !== undefined) {
|
|
45489
45495
|
c.execute(query, params, done);
|
|
45490
45496
|
} else {
|
|
@@ -45493,8 +45499,8 @@ var require_connection3 = __commonJS((exports, module) => {
|
|
|
45493
45499
|
});
|
|
45494
45500
|
}
|
|
45495
45501
|
end() {
|
|
45496
|
-
return new this.Promise((
|
|
45497
|
-
this.connection.end(
|
|
45502
|
+
return new this.Promise((resolve2) => {
|
|
45503
|
+
this.connection.end(resolve2);
|
|
45498
45504
|
});
|
|
45499
45505
|
}
|
|
45500
45506
|
async[Symbol.asyncDispose]() {
|
|
@@ -45505,31 +45511,31 @@ var require_connection3 = __commonJS((exports, module) => {
|
|
|
45505
45511
|
beginTransaction() {
|
|
45506
45512
|
const c = this.connection;
|
|
45507
45513
|
const localErr = new Error;
|
|
45508
|
-
return new this.Promise((
|
|
45509
|
-
const done = makeDoneCb(
|
|
45514
|
+
return new this.Promise((resolve2, reject) => {
|
|
45515
|
+
const done = makeDoneCb(resolve2, reject, localErr);
|
|
45510
45516
|
c.beginTransaction(done);
|
|
45511
45517
|
});
|
|
45512
45518
|
}
|
|
45513
45519
|
commit() {
|
|
45514
45520
|
const c = this.connection;
|
|
45515
45521
|
const localErr = new Error;
|
|
45516
|
-
return new this.Promise((
|
|
45517
|
-
const done = makeDoneCb(
|
|
45522
|
+
return new this.Promise((resolve2, reject) => {
|
|
45523
|
+
const done = makeDoneCb(resolve2, reject, localErr);
|
|
45518
45524
|
c.commit(done);
|
|
45519
45525
|
});
|
|
45520
45526
|
}
|
|
45521
45527
|
rollback() {
|
|
45522
45528
|
const c = this.connection;
|
|
45523
45529
|
const localErr = new Error;
|
|
45524
|
-
return new this.Promise((
|
|
45525
|
-
const done = makeDoneCb(
|
|
45530
|
+
return new this.Promise((resolve2, reject) => {
|
|
45531
|
+
const done = makeDoneCb(resolve2, reject, localErr);
|
|
45526
45532
|
c.rollback(done);
|
|
45527
45533
|
});
|
|
45528
45534
|
}
|
|
45529
45535
|
ping() {
|
|
45530
45536
|
const c = this.connection;
|
|
45531
45537
|
const localErr = new Error;
|
|
45532
|
-
return new this.Promise((
|
|
45538
|
+
return new this.Promise((resolve2, reject) => {
|
|
45533
45539
|
c.ping((err) => {
|
|
45534
45540
|
if (err) {
|
|
45535
45541
|
localErr.message = err.message;
|
|
@@ -45539,7 +45545,7 @@ var require_connection3 = __commonJS((exports, module) => {
|
|
|
45539
45545
|
localErr.sqlMessage = err.sqlMessage;
|
|
45540
45546
|
reject(localErr);
|
|
45541
45547
|
} else {
|
|
45542
|
-
|
|
45548
|
+
resolve2(true);
|
|
45543
45549
|
}
|
|
45544
45550
|
});
|
|
45545
45551
|
});
|
|
@@ -45547,7 +45553,7 @@ var require_connection3 = __commonJS((exports, module) => {
|
|
|
45547
45553
|
connect() {
|
|
45548
45554
|
const c = this.connection;
|
|
45549
45555
|
const localErr = new Error;
|
|
45550
|
-
return new this.Promise((
|
|
45556
|
+
return new this.Promise((resolve2, reject) => {
|
|
45551
45557
|
c.connect((err, param) => {
|
|
45552
45558
|
if (err) {
|
|
45553
45559
|
localErr.message = err.message;
|
|
@@ -45557,7 +45563,7 @@ var require_connection3 = __commonJS((exports, module) => {
|
|
|
45557
45563
|
localErr.sqlMessage = err.sqlMessage;
|
|
45558
45564
|
reject(localErr);
|
|
45559
45565
|
} else {
|
|
45560
|
-
|
|
45566
|
+
resolve2(param);
|
|
45561
45567
|
}
|
|
45562
45568
|
});
|
|
45563
45569
|
});
|
|
@@ -45566,7 +45572,7 @@ var require_connection3 = __commonJS((exports, module) => {
|
|
|
45566
45572
|
const c = this.connection;
|
|
45567
45573
|
const promiseImpl = this.Promise;
|
|
45568
45574
|
const localErr = new Error;
|
|
45569
|
-
return new this.Promise((
|
|
45575
|
+
return new this.Promise((resolve2, reject) => {
|
|
45570
45576
|
c.prepare(options, (err, statement) => {
|
|
45571
45577
|
if (err) {
|
|
45572
45578
|
localErr.message = err.message;
|
|
@@ -45577,7 +45583,7 @@ var require_connection3 = __commonJS((exports, module) => {
|
|
|
45577
45583
|
reject(localErr);
|
|
45578
45584
|
} else {
|
|
45579
45585
|
const wrappedStatement = new PromisePreparedStatementInfo(statement, promiseImpl);
|
|
45580
|
-
|
|
45586
|
+
resolve2(wrappedStatement);
|
|
45581
45587
|
}
|
|
45582
45588
|
});
|
|
45583
45589
|
});
|
|
@@ -45585,7 +45591,7 @@ var require_connection3 = __commonJS((exports, module) => {
|
|
|
45585
45591
|
changeUser(options) {
|
|
45586
45592
|
const c = this.connection;
|
|
45587
45593
|
const localErr = new Error;
|
|
45588
|
-
return new this.Promise((
|
|
45594
|
+
return new this.Promise((resolve2, reject) => {
|
|
45589
45595
|
c.changeUser(options, (err) => {
|
|
45590
45596
|
if (err) {
|
|
45591
45597
|
localErr.message = err.message;
|
|
@@ -45595,7 +45601,7 @@ var require_connection3 = __commonJS((exports, module) => {
|
|
|
45595
45601
|
localErr.sqlMessage = err.sqlMessage;
|
|
45596
45602
|
reject(localErr);
|
|
45597
45603
|
} else {
|
|
45598
|
-
|
|
45604
|
+
resolve2();
|
|
45599
45605
|
}
|
|
45600
45606
|
});
|
|
45601
45607
|
});
|
|
@@ -45997,12 +46003,12 @@ var require_pool2 = __commonJS((exports, module) => {
|
|
|
45997
46003
|
}
|
|
45998
46004
|
getConnection() {
|
|
45999
46005
|
const corePool = this.pool;
|
|
46000
|
-
return new this.Promise((
|
|
46006
|
+
return new this.Promise((resolve2, reject) => {
|
|
46001
46007
|
corePool.getConnection((err, coreConnection) => {
|
|
46002
46008
|
if (err) {
|
|
46003
46009
|
reject(err);
|
|
46004
46010
|
} else {
|
|
46005
|
-
|
|
46011
|
+
resolve2(new PromisePoolConnection(coreConnection, this.Promise));
|
|
46006
46012
|
}
|
|
46007
46013
|
});
|
|
46008
46014
|
});
|
|
@@ -46017,8 +46023,8 @@ var require_pool2 = __commonJS((exports, module) => {
|
|
|
46017
46023
|
if (typeof args === "function") {
|
|
46018
46024
|
throw new Error("Callback function is not available with promise clients.");
|
|
46019
46025
|
}
|
|
46020
|
-
return new this.Promise((
|
|
46021
|
-
const done = makeDoneCb(
|
|
46026
|
+
return new this.Promise((resolve2, reject) => {
|
|
46027
|
+
const done = makeDoneCb(resolve2, reject, localErr);
|
|
46022
46028
|
if (args !== undefined) {
|
|
46023
46029
|
corePool.query(sql, args, done);
|
|
46024
46030
|
} else {
|
|
@@ -46032,8 +46038,8 @@ var require_pool2 = __commonJS((exports, module) => {
|
|
|
46032
46038
|
if (typeof args === "function") {
|
|
46033
46039
|
throw new Error("Callback function is not available with promise clients.");
|
|
46034
46040
|
}
|
|
46035
|
-
return new this.Promise((
|
|
46036
|
-
const done = makeDoneCb(
|
|
46041
|
+
return new this.Promise((resolve2, reject) => {
|
|
46042
|
+
const done = makeDoneCb(resolve2, reject, localErr);
|
|
46037
46043
|
if (args) {
|
|
46038
46044
|
corePool.execute(sql, args, done);
|
|
46039
46045
|
} else {
|
|
@@ -46044,7 +46050,7 @@ var require_pool2 = __commonJS((exports, module) => {
|
|
|
46044
46050
|
end() {
|
|
46045
46051
|
const corePool = this.pool;
|
|
46046
46052
|
const localErr = new Error;
|
|
46047
|
-
return new this.Promise((
|
|
46053
|
+
return new this.Promise((resolve2, reject) => {
|
|
46048
46054
|
corePool.end((err) => {
|
|
46049
46055
|
if (err) {
|
|
46050
46056
|
localErr.message = err.message;
|
|
@@ -46054,7 +46060,7 @@ var require_pool2 = __commonJS((exports, module) => {
|
|
|
46054
46060
|
localErr.sqlMessage = err.sqlMessage;
|
|
46055
46061
|
reject(localErr);
|
|
46056
46062
|
} else {
|
|
46057
|
-
|
|
46063
|
+
resolve2();
|
|
46058
46064
|
}
|
|
46059
46065
|
});
|
|
46060
46066
|
});
|
|
@@ -46452,12 +46458,12 @@ var require_pool_cluster2 = __commonJS((exports, module) => {
|
|
|
46452
46458
|
}
|
|
46453
46459
|
getConnection() {
|
|
46454
46460
|
const corePoolNamespace = this.poolNamespace;
|
|
46455
|
-
return new this.Promise((
|
|
46461
|
+
return new this.Promise((resolve2, reject) => {
|
|
46456
46462
|
corePoolNamespace.getConnection((err, coreConnection) => {
|
|
46457
46463
|
if (err) {
|
|
46458
46464
|
reject(err);
|
|
46459
46465
|
} else {
|
|
46460
|
-
|
|
46466
|
+
resolve2(new PromisePoolConnection(coreConnection, this.Promise));
|
|
46461
46467
|
}
|
|
46462
46468
|
});
|
|
46463
46469
|
});
|
|
@@ -46468,8 +46474,8 @@ var require_pool_cluster2 = __commonJS((exports, module) => {
|
|
|
46468
46474
|
if (typeof values === "function") {
|
|
46469
46475
|
throw new Error("Callback function is not available with promise clients.");
|
|
46470
46476
|
}
|
|
46471
|
-
return new this.Promise((
|
|
46472
|
-
const done = makeDoneCb(
|
|
46477
|
+
return new this.Promise((resolve2, reject) => {
|
|
46478
|
+
const done = makeDoneCb(resolve2, reject, localErr);
|
|
46473
46479
|
corePoolNamespace.query(sql, values, done);
|
|
46474
46480
|
});
|
|
46475
46481
|
}
|
|
@@ -46479,8 +46485,8 @@ var require_pool_cluster2 = __commonJS((exports, module) => {
|
|
|
46479
46485
|
if (typeof values === "function") {
|
|
46480
46486
|
throw new Error("Callback function is not available with promise clients.");
|
|
46481
46487
|
}
|
|
46482
|
-
return new this.Promise((
|
|
46483
|
-
const done = makeDoneCb(
|
|
46488
|
+
return new this.Promise((resolve2, reject) => {
|
|
46489
|
+
const done = makeDoneCb(resolve2, reject, localErr);
|
|
46484
46490
|
corePoolNamespace.execute(sql, values, done);
|
|
46485
46491
|
});
|
|
46486
46492
|
}
|
|
@@ -46510,9 +46516,9 @@ var require_promise = __commonJS((exports) => {
|
|
|
46510
46516
|
if (!thePromise) {
|
|
46511
46517
|
throw new Error("no Promise implementation available." + "Use promise-enabled node version or pass userland Promise" + " implementation as parameter, for example: { Promise: require('bluebird') }");
|
|
46512
46518
|
}
|
|
46513
|
-
return new thePromise((
|
|
46519
|
+
return new thePromise((resolve2, reject) => {
|
|
46514
46520
|
coreConnection.once("connect", () => {
|
|
46515
|
-
|
|
46521
|
+
resolve2(new PromiseConnection(coreConnection, thePromise));
|
|
46516
46522
|
});
|
|
46517
46523
|
coreConnection.once("error", (err) => {
|
|
46518
46524
|
createConnectionErr.message = err.message;
|
|
@@ -46541,12 +46547,12 @@ var require_promise = __commonJS((exports) => {
|
|
|
46541
46547
|
}
|
|
46542
46548
|
getConnection(pattern, selector) {
|
|
46543
46549
|
const corePoolCluster = this.poolCluster;
|
|
46544
|
-
return new this.Promise((
|
|
46550
|
+
return new this.Promise((resolve2, reject) => {
|
|
46545
46551
|
corePoolCluster.getConnection(pattern, selector, (err, coreConnection) => {
|
|
46546
46552
|
if (err) {
|
|
46547
46553
|
reject(err);
|
|
46548
46554
|
} else {
|
|
46549
|
-
|
|
46555
|
+
resolve2(new PromisePoolConnection(coreConnection, this.Promise));
|
|
46550
46556
|
}
|
|
46551
46557
|
});
|
|
46552
46558
|
});
|
|
@@ -46557,8 +46563,8 @@ var require_promise = __commonJS((exports) => {
|
|
|
46557
46563
|
if (typeof args === "function") {
|
|
46558
46564
|
throw new Error("Callback function is not available with promise clients.");
|
|
46559
46565
|
}
|
|
46560
|
-
return new this.Promise((
|
|
46561
|
-
const done = makeDoneCb(
|
|
46566
|
+
return new this.Promise((resolve2, reject) => {
|
|
46567
|
+
const done = makeDoneCb(resolve2, reject, localErr);
|
|
46562
46568
|
corePoolCluster.query(sql, args, done);
|
|
46563
46569
|
});
|
|
46564
46570
|
}
|
|
@@ -46568,8 +46574,8 @@ var require_promise = __commonJS((exports) => {
|
|
|
46568
46574
|
if (typeof args === "function") {
|
|
46569
46575
|
throw new Error("Callback function is not available with promise clients.");
|
|
46570
46576
|
}
|
|
46571
|
-
return new this.Promise((
|
|
46572
|
-
const done = makeDoneCb(
|
|
46577
|
+
return new this.Promise((resolve2, reject) => {
|
|
46578
|
+
const done = makeDoneCb(resolve2, reject, localErr);
|
|
46573
46579
|
corePoolCluster.execute(sql, args, done);
|
|
46574
46580
|
});
|
|
46575
46581
|
}
|
|
@@ -46579,7 +46585,7 @@ var require_promise = __commonJS((exports) => {
|
|
|
46579
46585
|
end() {
|
|
46580
46586
|
const corePoolCluster = this.poolCluster;
|
|
46581
46587
|
const localErr = new Error;
|
|
46582
|
-
return new this.Promise((
|
|
46588
|
+
return new this.Promise((resolve2, reject) => {
|
|
46583
46589
|
corePoolCluster.end((err) => {
|
|
46584
46590
|
if (err) {
|
|
46585
46591
|
localErr.message = err.message;
|
|
@@ -46589,7 +46595,7 @@ var require_promise = __commonJS((exports) => {
|
|
|
46589
46595
|
localErr.sqlMessage = err.sqlMessage;
|
|
46590
46596
|
reject(localErr);
|
|
46591
46597
|
} else {
|
|
46592
|
-
|
|
46598
|
+
resolve2();
|
|
46593
46599
|
}
|
|
46594
46600
|
});
|
|
46595
46601
|
});
|
|
@@ -53612,7 +53618,7 @@ var require_utils3 = __commonJS((exports) => {
|
|
|
53612
53618
|
}
|
|
53613
53619
|
}
|
|
53614
53620
|
function get(url, options = {}) {
|
|
53615
|
-
return new Promise((
|
|
53621
|
+
return new Promise((resolve2, reject) => {
|
|
53616
53622
|
let timeoutId;
|
|
53617
53623
|
const request = http.get(url, options, (response) => {
|
|
53618
53624
|
response.setEncoding("utf8");
|
|
@@ -53620,7 +53626,7 @@ var require_utils3 = __commonJS((exports) => {
|
|
|
53620
53626
|
response.on("data", (chunk) => body += chunk);
|
|
53621
53627
|
response.on("end", () => {
|
|
53622
53628
|
(0, timers_1.clearTimeout)(timeoutId);
|
|
53623
|
-
|
|
53629
|
+
resolve2({ status: response.statusCode, body });
|
|
53624
53630
|
});
|
|
53625
53631
|
}).on("error", (error) => {
|
|
53626
53632
|
(0, timers_1.clearTimeout)(timeoutId);
|
|
@@ -53639,13 +53645,13 @@ var require_utils3 = __commonJS((exports) => {
|
|
|
53639
53645
|
return host && match.test(host.toLowerCase()) ? true : false;
|
|
53640
53646
|
}
|
|
53641
53647
|
function promiseWithResolvers() {
|
|
53642
|
-
let
|
|
53648
|
+
let resolve2;
|
|
53643
53649
|
let reject;
|
|
53644
53650
|
const promise = new Promise(function withResolversExecutor(promiseResolve, promiseReject) {
|
|
53645
|
-
|
|
53651
|
+
resolve2 = promiseResolve;
|
|
53646
53652
|
reject = promiseReject;
|
|
53647
53653
|
});
|
|
53648
|
-
return { promise, resolve, reject };
|
|
53654
|
+
return { promise, resolve: resolve2, reject };
|
|
53649
53655
|
}
|
|
53650
53656
|
function squashError(_error) {
|
|
53651
53657
|
return;
|
|
@@ -53656,8 +53662,8 @@ var require_utils3 = __commonJS((exports) => {
|
|
|
53656
53662
|
exports.randomBytes = randomBytes;
|
|
53657
53663
|
async function once(ee, name, options) {
|
|
53658
53664
|
options?.signal?.throwIfAborted();
|
|
53659
|
-
const { promise, resolve, reject } = promiseWithResolvers();
|
|
53660
|
-
const onEvent = (data) =>
|
|
53665
|
+
const { promise, resolve: resolve2, reject } = promiseWithResolvers();
|
|
53666
|
+
const onEvent = (data) => resolve2(data);
|
|
53661
53667
|
const onError = (error) => reject(error);
|
|
53662
53668
|
const abortListener = addAbortListener(options?.signal, function() {
|
|
53663
53669
|
reject(this.reason);
|
|
@@ -55980,13 +55986,13 @@ var require_mongo_logger = __commonJS((exports) => {
|
|
|
55980
55986
|
function createStdioLogger(stream) {
|
|
55981
55987
|
return {
|
|
55982
55988
|
write: (log) => {
|
|
55983
|
-
return new Promise((
|
|
55989
|
+
return new Promise((resolve2, reject) => {
|
|
55984
55990
|
const logLine = (0, util_1.inspect)(log, { compact: true, breakLength: Infinity });
|
|
55985
55991
|
stream.write(`${logLine}
|
|
55986
55992
|
`, "utf-8", (error) => {
|
|
55987
55993
|
if (error)
|
|
55988
55994
|
return reject(error);
|
|
55989
|
-
|
|
55995
|
+
resolve2(true);
|
|
55990
55996
|
});
|
|
55991
55997
|
});
|
|
55992
55998
|
}
|
|
@@ -63644,7 +63650,7 @@ var require_URLSearchParams = __commonJS((exports) => {
|
|
|
63644
63650
|
}
|
|
63645
63651
|
const ctorRegistry = utils.initCtorRegistry(globalObject);
|
|
63646
63652
|
|
|
63647
|
-
class
|
|
63653
|
+
class URLSearchParams2 {
|
|
63648
63654
|
constructor() {
|
|
63649
63655
|
const args = [];
|
|
63650
63656
|
{
|
|
@@ -63923,7 +63929,7 @@ var require_URLSearchParams = __commonJS((exports) => {
|
|
|
63923
63929
|
return esValue[implSymbol]["size"];
|
|
63924
63930
|
}
|
|
63925
63931
|
}
|
|
63926
|
-
Object.defineProperties(
|
|
63932
|
+
Object.defineProperties(URLSearchParams2.prototype, {
|
|
63927
63933
|
append: { enumerable: true },
|
|
63928
63934
|
delete: { enumerable: true },
|
|
63929
63935
|
get: { enumerable: true },
|
|
@@ -63938,9 +63944,9 @@ var require_URLSearchParams = __commonJS((exports) => {
|
|
|
63938
63944
|
forEach: { enumerable: true },
|
|
63939
63945
|
size: { enumerable: true },
|
|
63940
63946
|
[Symbol.toStringTag]: { value: "URLSearchParams", configurable: true },
|
|
63941
|
-
[Symbol.iterator]: { value:
|
|
63947
|
+
[Symbol.iterator]: { value: URLSearchParams2.prototype.entries, configurable: true, writable: true }
|
|
63942
63948
|
});
|
|
63943
|
-
ctorRegistry[interfaceName] =
|
|
63949
|
+
ctorRegistry[interfaceName] = URLSearchParams2;
|
|
63944
63950
|
ctorRegistry["URLSearchParams Iterator"] = Object.create(ctorRegistry["%IteratorPrototype%"], {
|
|
63945
63951
|
[Symbol.toStringTag]: {
|
|
63946
63952
|
configurable: true,
|
|
@@ -63967,7 +63973,7 @@ var require_URLSearchParams = __commonJS((exports) => {
|
|
|
63967
63973
|
Object.defineProperty(globalObject, interfaceName, {
|
|
63968
63974
|
configurable: true,
|
|
63969
63975
|
writable: true,
|
|
63970
|
-
value:
|
|
63976
|
+
value: URLSearchParams2
|
|
63971
63977
|
});
|
|
63972
63978
|
};
|
|
63973
63979
|
var Impl = require_URLSearchParams_impl();
|
|
@@ -63977,7 +63983,7 @@ var require_URLSearchParams = __commonJS((exports) => {
|
|
|
63977
63983
|
var require_URL_impl = __commonJS((exports) => {
|
|
63978
63984
|
var usm = require_url_state_machine();
|
|
63979
63985
|
var urlencoded = require_urlencoded();
|
|
63980
|
-
var
|
|
63986
|
+
var URLSearchParams2 = require_URLSearchParams();
|
|
63981
63987
|
exports.implementation = class URLImpl {
|
|
63982
63988
|
constructor(globalObject, [url, base]) {
|
|
63983
63989
|
let parsedBase = null;
|
|
@@ -63993,7 +63999,7 @@ var require_URL_impl = __commonJS((exports) => {
|
|
|
63993
63999
|
}
|
|
63994
64000
|
const query = parsedURL.query !== null ? parsedURL.query : "";
|
|
63995
64001
|
this._url = parsedURL;
|
|
63996
|
-
this._query =
|
|
64002
|
+
this._query = URLSearchParams2.createImpl(globalObject, [query], { doNotStripQMark: true });
|
|
63997
64003
|
this._query._url = this;
|
|
63998
64004
|
}
|
|
63999
64005
|
static parse(globalObject, input, base) {
|
|
@@ -64551,19 +64557,19 @@ var require_URL = __commonJS((exports) => {
|
|
|
64551
64557
|
// node_modules/whatwg-url/webidl2js-wrapper.js
|
|
64552
64558
|
var require_webidl2js_wrapper = __commonJS((exports) => {
|
|
64553
64559
|
var URL2 = require_URL();
|
|
64554
|
-
var
|
|
64560
|
+
var URLSearchParams2 = require_URLSearchParams();
|
|
64555
64561
|
exports.URL = URL2;
|
|
64556
|
-
exports.URLSearchParams =
|
|
64562
|
+
exports.URLSearchParams = URLSearchParams2;
|
|
64557
64563
|
});
|
|
64558
64564
|
|
|
64559
64565
|
// node_modules/whatwg-url/index.js
|
|
64560
64566
|
var require_whatwg_url = __commonJS((exports) => {
|
|
64561
|
-
var { URL: URL2, URLSearchParams } = require_webidl2js_wrapper();
|
|
64567
|
+
var { URL: URL2, URLSearchParams: URLSearchParams2 } = require_webidl2js_wrapper();
|
|
64562
64568
|
var urlStateMachine = require_url_state_machine();
|
|
64563
64569
|
var percentEncoding = require_percent_encoding();
|
|
64564
64570
|
var sharedGlobalObject = { Array, Object, Promise, String, TypeError };
|
|
64565
64571
|
URL2.install(sharedGlobalObject, ["Window"]);
|
|
64566
|
-
|
|
64572
|
+
URLSearchParams2.install(sharedGlobalObject, ["Window"]);
|
|
64567
64573
|
exports.URL = sharedGlobalObject.URL;
|
|
64568
64574
|
exports.URLSearchParams = sharedGlobalObject.URLSearchParams;
|
|
64569
64575
|
exports.parseURL = urlStateMachine.parseURL;
|
|
@@ -65372,20 +65378,20 @@ var require_compression = __commonJS((exports) => {
|
|
|
65372
65378
|
]);
|
|
65373
65379
|
var ZSTD_COMPRESSION_LEVEL = 3;
|
|
65374
65380
|
var zlibInflate = (buf) => {
|
|
65375
|
-
return new Promise((
|
|
65381
|
+
return new Promise((resolve2, reject) => {
|
|
65376
65382
|
zlib.inflate(buf, (error, result) => {
|
|
65377
65383
|
if (error)
|
|
65378
65384
|
return reject(error);
|
|
65379
|
-
|
|
65385
|
+
resolve2(result);
|
|
65380
65386
|
});
|
|
65381
65387
|
});
|
|
65382
65388
|
};
|
|
65383
65389
|
var zlibDeflate = (buf, options) => {
|
|
65384
|
-
return new Promise((
|
|
65390
|
+
return new Promise((resolve2, reject) => {
|
|
65385
65391
|
zlib.deflate(buf, options, (error, result) => {
|
|
65386
65392
|
if (error)
|
|
65387
65393
|
return reject(error);
|
|
65388
|
-
|
|
65394
|
+
resolve2(result);
|
|
65389
65395
|
});
|
|
65390
65396
|
});
|
|
65391
65397
|
};
|
|
@@ -66016,7 +66022,7 @@ var require_state_machine = __commonJS((exports) => {
|
|
|
66016
66022
|
socket = tls.connect(socketOptions, () => {
|
|
66017
66023
|
socket.write(message);
|
|
66018
66024
|
});
|
|
66019
|
-
const { promise: willResolveKmsRequest, reject: rejectOnTlsSocketError, resolve } = (0, utils_1.promiseWithResolvers)();
|
|
66025
|
+
const { promise: willResolveKmsRequest, reject: rejectOnTlsSocketError, resolve: resolve2 } = (0, utils_1.promiseWithResolvers)();
|
|
66020
66026
|
abortListener = (0, utils_1.addAbortListener)(options?.signal, function() {
|
|
66021
66027
|
destroySockets();
|
|
66022
66028
|
rejectOnTlsSocketError(this.reason);
|
|
@@ -66028,7 +66034,7 @@ var require_state_machine = __commonJS((exports) => {
|
|
|
66028
66034
|
request.addResponse(buffer.read(bytesNeeded));
|
|
66029
66035
|
}
|
|
66030
66036
|
if (request.bytesNeeded <= 0) {
|
|
66031
|
-
|
|
66037
|
+
resolve2();
|
|
66032
66038
|
}
|
|
66033
66039
|
});
|
|
66034
66040
|
await (options?.timeoutContext?.csotEnabled() ? Promise.all([
|
|
@@ -67142,8 +67148,8 @@ var require_on_data = __commonJS((exports) => {
|
|
|
67142
67148
|
}
|
|
67143
67149
|
if (finished)
|
|
67144
67150
|
return closeHandler();
|
|
67145
|
-
const { promise, resolve, reject } = (0, utils_1.promiseWithResolvers)();
|
|
67146
|
-
unconsumedPromises.push({ resolve, reject });
|
|
67151
|
+
const { promise, resolve: resolve2, reject } = (0, utils_1.promiseWithResolvers)();
|
|
67152
|
+
unconsumedPromises.push({ resolve: resolve2, reject });
|
|
67147
67153
|
return promise;
|
|
67148
67154
|
},
|
|
67149
67155
|
return() {
|
|
@@ -68253,13 +68259,13 @@ var require_connect = __commonJS((exports) => {
|
|
|
68253
68259
|
socket.setNoDelay(noDelay);
|
|
68254
68260
|
socket.setTimeout(connectTimeoutMS);
|
|
68255
68261
|
let cancellationHandler = null;
|
|
68256
|
-
const { promise: connectedSocket, resolve, reject } = (0, utils_1.promiseWithResolvers)();
|
|
68262
|
+
const { promise: connectedSocket, resolve: resolve2, reject } = (0, utils_1.promiseWithResolvers)();
|
|
68257
68263
|
if (existingSocket) {
|
|
68258
|
-
|
|
68264
|
+
resolve2(socket);
|
|
68259
68265
|
} else {
|
|
68260
68266
|
const start = performance.now();
|
|
68261
68267
|
const connectEvent = useTLS ? "secureConnect" : "connect";
|
|
68262
|
-
socket.once(connectEvent, () =>
|
|
68268
|
+
socket.once(connectEvent, () => resolve2(socket)).once("error", (cause) => reject(new error_1.MongoNetworkError(error_1.MongoError.buildErrorMessage(cause), { cause }))).once("timeout", () => {
|
|
68263
68269
|
reject(new error_1.MongoNetworkTimeoutError(`Socket '${connectEvent}' timed out after ${performance.now() - start | 0}ms (connectTimeoutMS: ${connectTimeoutMS})`));
|
|
68264
68270
|
}).once("close", () => reject(new error_1.MongoNetworkError(`Socket closed after ${performance.now() - start | 0} during connection establishment`)));
|
|
68265
68271
|
if (options.cancellationToken != null) {
|
|
@@ -68734,10 +68740,10 @@ var require_connection_pool = __commonJS((exports) => {
|
|
|
68734
68740
|
async checkOut(options) {
|
|
68735
68741
|
const checkoutTime = (0, utils_1.processTimeMS)();
|
|
68736
68742
|
this.emitAndLog(ConnectionPool.CONNECTION_CHECK_OUT_STARTED, new connection_pool_events_1.ConnectionCheckOutStartedEvent(this));
|
|
68737
|
-
const { promise, resolve, reject } = (0, utils_1.promiseWithResolvers)();
|
|
68743
|
+
const { promise, resolve: resolve2, reject } = (0, utils_1.promiseWithResolvers)();
|
|
68738
68744
|
const timeout = options.timeoutContext.connectionCheckoutTimeout;
|
|
68739
68745
|
const waitQueueMember = {
|
|
68740
|
-
resolve,
|
|
68746
|
+
resolve: resolve2,
|
|
68741
68747
|
reject,
|
|
68742
68748
|
cancelled: false,
|
|
68743
68749
|
checkoutTime
|
|
@@ -69882,13 +69888,13 @@ var require_connection_string = __commonJS((exports) => {
|
|
|
69882
69888
|
var LB_REPLICA_SET_ERROR = "loadBalanced option not supported with a replicaSet option";
|
|
69883
69889
|
var LB_DIRECT_CONNECTION_ERROR = "loadBalanced option not supported when directConnection is provided";
|
|
69884
69890
|
function retryDNSTimeoutFor(rrtype) {
|
|
69885
|
-
const
|
|
69891
|
+
const resolve2 = rrtype === "SRV" ? (address) => dns.promises.resolve(address, "SRV") : (address) => dns.promises.resolve(address, "TXT");
|
|
69886
69892
|
return async function dnsReqRetryTimeout(lookupAddress) {
|
|
69887
69893
|
try {
|
|
69888
|
-
return await
|
|
69894
|
+
return await resolve2(lookupAddress);
|
|
69889
69895
|
} catch (firstDNSError) {
|
|
69890
69896
|
if (firstDNSError.code === dns.TIMEOUT) {
|
|
69891
|
-
return await
|
|
69897
|
+
return await resolve2(lookupAddress);
|
|
69892
69898
|
} else {
|
|
69893
69899
|
throw firstDNSError;
|
|
69894
69900
|
}
|
|
@@ -73356,13 +73362,13 @@ var require_topology = __commonJS((exports) => {
|
|
|
73356
73362
|
}
|
|
73357
73363
|
return transaction.server;
|
|
73358
73364
|
}
|
|
73359
|
-
const { promise: serverPromise, resolve, reject } = (0, utils_1.promiseWithResolvers)();
|
|
73365
|
+
const { promise: serverPromise, resolve: resolve2, reject } = (0, utils_1.promiseWithResolvers)();
|
|
73360
73366
|
const waitQueueMember = {
|
|
73361
73367
|
serverSelector,
|
|
73362
73368
|
topologyDescription: this.description,
|
|
73363
73369
|
mongoLogger: this.client.mongoLogger,
|
|
73364
73370
|
transaction,
|
|
73365
|
-
resolve,
|
|
73371
|
+
resolve: resolve2,
|
|
73366
73372
|
reject,
|
|
73367
73373
|
cancelled: false,
|
|
73368
73374
|
startTime: (0, utils_1.processTimeMS)(),
|
|
@@ -77140,7 +77146,7 @@ var {
|
|
|
77140
77146
|
// package.json
|
|
77141
77147
|
var package_default = {
|
|
77142
77148
|
name: "@carllee1983/dbcli",
|
|
77143
|
-
version: "1.
|
|
77149
|
+
version: "1.6.0",
|
|
77144
77150
|
description: "Database CLI for AI agents",
|
|
77145
77151
|
type: "module",
|
|
77146
77152
|
publishConfig: {
|
|
@@ -77244,24 +77250,24 @@ var messages_default = {
|
|
|
77244
77250
|
skip_test: "Skipping connection test (--skip-test)",
|
|
77245
77251
|
connection_hints: "Hints:",
|
|
77246
77252
|
config_exists_use_force: ".dbcli exists. Use --force option to overwrite.",
|
|
77247
|
-
connection_added: "Connection '{
|
|
77248
|
-
connection_removed: "Connection '{
|
|
77249
|
-
connection_removed_switched: "Connection '{
|
|
77250
|
-
connection_renamed: "Connection '{
|
|
77253
|
+
connection_added: "Connection '{name}' added",
|
|
77254
|
+
connection_removed: "Connection '{name}' removed",
|
|
77255
|
+
connection_removed_switched: "Connection '{name}' removed. Default connection switched to '{newDefault}'",
|
|
77256
|
+
connection_renamed: "Connection '{oldName}' renamed to '{newName}'",
|
|
77251
77257
|
v1_migration_prompt: "Detected old config format. Create new format and import existing connection as 'default'?",
|
|
77252
77258
|
config_saved_v2: "V2 configuration saved to .dbcli",
|
|
77253
77259
|
config_not_found: "Configuration file not found",
|
|
77254
77260
|
requires_v2_remove: "Removing a connection requires V2 config format",
|
|
77255
77261
|
requires_v2_rename: "Renaming a connection requires V2 config format",
|
|
77256
|
-
connection_not_found: "Connection '{
|
|
77262
|
+
connection_not_found: "Connection '{name}' does not exist",
|
|
77257
77263
|
cannot_remove_last: "Cannot remove the last connection",
|
|
77258
|
-
connection_already_exists: "Connection '{
|
|
77264
|
+
connection_already_exists: "Connection '{name}' already exists",
|
|
77259
77265
|
rename_invalid_format: "Usage: --rename <old-name>:<new-name>"
|
|
77260
77266
|
},
|
|
77261
77267
|
use: {
|
|
77262
77268
|
description: "Switch or display the default database connection",
|
|
77263
|
-
switched: "Switched default connection to {
|
|
77264
|
-
current: "Current default connection: {
|
|
77269
|
+
switched: "Switched default connection to {name}",
|
|
77270
|
+
current: "Current default connection: {name}",
|
|
77265
77271
|
requires_v2: "This feature requires v2 config format. Use 'dbcli init --conn-name <name>' to create one",
|
|
77266
77272
|
available: "Available connections"
|
|
77267
77273
|
},
|
|
@@ -77361,7 +77367,8 @@ Hint: run 'export {envKey}=<value>' and retry`
|
|
|
77361
77367
|
},
|
|
77362
77368
|
skill: {
|
|
77363
77369
|
description: "Generate AI skill documentation",
|
|
77364
|
-
installed:
|
|
77370
|
+
installed: `Skill: {path}
|
|
77371
|
+
Reference: {referencePath}`,
|
|
77365
77372
|
update_available: "Skill updates available for the following platforms:",
|
|
77366
77373
|
update_hint: 'Run "dbcli skill --install <platform>" to update.'
|
|
77367
77374
|
},
|
|
@@ -77434,24 +77441,24 @@ var messages_default2 = {
|
|
|
77434
77441
|
skip_test: "\u8DF3\u904E\u9023\u7DDA\u6E2C\u8A66\uFF08--skip-test\uFF09",
|
|
77435
77442
|
connection_hints: "\u63D0\u793A\uFF1A",
|
|
77436
77443
|
config_exists_use_force: ".dbcli \u5DF2\u5B58\u5728\u3002\u4F7F\u7528 --force \u9078\u9805\u8986\u84CB\u3002",
|
|
77437
|
-
connection_added: "\u5DF2\u65B0\u589E\u9023\u7DDA '{
|
|
77438
|
-
connection_removed: "\u5DF2\u79FB\u9664\u9023\u7DDA '{
|
|
77439
|
-
connection_removed_switched: "\u5DF2\u79FB\u9664\u9023\u7DDA '{
|
|
77440
|
-
connection_renamed: "\u5DF2\u5C07\u9023\u7DDA '{
|
|
77444
|
+
connection_added: "\u5DF2\u65B0\u589E\u9023\u7DDA '{name}'",
|
|
77445
|
+
connection_removed: "\u5DF2\u79FB\u9664\u9023\u7DDA '{name}'",
|
|
77446
|
+
connection_removed_switched: "\u5DF2\u79FB\u9664\u9023\u7DDA '{name}'\uFF0C\u9810\u8A2D\u9023\u7DDA\u5DF2\u5207\u63DB\u70BA '{newDefault}'",
|
|
77447
|
+
connection_renamed: "\u5DF2\u5C07\u9023\u7DDA '{oldName}' \u91CD\u65B0\u547D\u540D\u70BA '{newName}'",
|
|
77441
77448
|
v1_migration_prompt: "\u5075\u6E2C\u5230\u820A\u683C\u5F0F\u8A2D\u5B9A\uFF0C\u5C07\u5EFA\u7ACB\u65B0\u683C\u5F0F\u4E26\u5C07\u73FE\u6709\u9023\u7DDA\u532F\u5165\u70BA 'default'\uFF0C\u662F\u5426\u7E7C\u7E8C\uFF1F",
|
|
77442
77449
|
config_saved_v2: "V2 \u8A2D\u5B9A\u5DF2\u5132\u5B58\u81F3 .dbcli",
|
|
77443
77450
|
config_not_found: "\u627E\u4E0D\u5230\u8A2D\u5B9A\u6A94",
|
|
77444
77451
|
requires_v2_remove: "\u79FB\u9664\u9023\u7DDA\u9700\u8981 V2 \u683C\u5F0F\u8A2D\u5B9A",
|
|
77445
77452
|
requires_v2_rename: "\u91CD\u65B0\u547D\u540D\u9023\u7DDA\u9700\u8981 V2 \u683C\u5F0F\u8A2D\u5B9A",
|
|
77446
|
-
connection_not_found: "\u9023\u7DDA '{
|
|
77453
|
+
connection_not_found: "\u9023\u7DDA '{name}' \u4E0D\u5B58\u5728",
|
|
77447
77454
|
cannot_remove_last: "\u7121\u6CD5\u79FB\u9664\u6700\u5F8C\u4E00\u500B\u9023\u7DDA",
|
|
77448
|
-
connection_already_exists: "\u9023\u7DDA '{
|
|
77455
|
+
connection_already_exists: "\u9023\u7DDA '{name}' \u5DF2\u5B58\u5728",
|
|
77449
77456
|
rename_invalid_format: "\u7528\u6CD5\uFF1A--rename <\u820A\u540D\u7A31>:<\u65B0\u540D\u7A31>"
|
|
77450
77457
|
},
|
|
77451
77458
|
use: {
|
|
77452
77459
|
description: "\u5207\u63DB\u6216\u986F\u793A\u9810\u8A2D\u8CC7\u6599\u5EAB\u9023\u7DDA",
|
|
77453
|
-
switched: "\u5DF2\u5207\u63DB\u9810\u8A2D\u9023\u7DDA\u70BA {
|
|
77454
|
-
current: "\u76EE\u524D\u9810\u8A2D\u9023\u7DDA\uFF1A{
|
|
77460
|
+
switched: "\u5DF2\u5207\u63DB\u9810\u8A2D\u9023\u7DDA\u70BA {name}",
|
|
77461
|
+
current: "\u76EE\u524D\u7684\u9810\u8A2D\u9023\u7DDA\uFF1A{name}",
|
|
77455
77462
|
requires_v2: "\u6B64\u529F\u80FD\u9700\u8981\u65B0\u683C\u5F0F\u8A2D\u5B9A\u3002\u8ACB\u4F7F\u7528 dbcli init --conn-name <\u540D\u7A31> \u5EFA\u7ACB\u591A\u9023\u7DDA\u8A2D\u5B9A",
|
|
77456
77463
|
available: "\u53EF\u7528\u9023\u7DDA"
|
|
77457
77464
|
},
|
|
@@ -77551,7 +77558,8 @@ var messages_default2 = {
|
|
|
77551
77558
|
},
|
|
77552
77559
|
skill: {
|
|
77553
77560
|
description: "\u751F\u6210 AI \u6280\u80FD\u6587\u6A94",
|
|
77554
|
-
installed:
|
|
77561
|
+
installed: `\u6280\u80FD: {path}
|
|
77562
|
+
\u53C3\u8003: {referencePath}`,
|
|
77555
77563
|
update_available: "\u4EE5\u4E0B\u5E73\u53F0\u7684\u6280\u80FD\u9700\u8981\u66F4\u65B0\uFF1A",
|
|
77556
77564
|
update_hint: '\u57F7\u884C "dbcli skill --install <platform>" \u9032\u884C\u66F4\u65B0\u3002'
|
|
77557
77565
|
},
|
|
@@ -77757,7 +77765,7 @@ function getLogger() {
|
|
|
77757
77765
|
}
|
|
77758
77766
|
|
|
77759
77767
|
// src/commands/init.ts
|
|
77760
|
-
import { join as
|
|
77768
|
+
import { join as join8 } from "path";
|
|
77761
77769
|
|
|
77762
77770
|
// src/utils/errors.ts
|
|
77763
77771
|
class EnvParseError extends Error {
|
|
@@ -77823,7 +77831,11 @@ function parseConnectionUrl(url) {
|
|
|
77823
77831
|
throw new Error(`Unsupported protocol: ${protocol}`);
|
|
77824
77832
|
}
|
|
77825
77833
|
const host = parsed.hostname || "localhost";
|
|
77826
|
-
const
|
|
77834
|
+
const defaultPort = (() => {
|
|
77835
|
+
const p = getDefaultsForSystem(system).port;
|
|
77836
|
+
return typeof p === "number" ? p : 5432;
|
|
77837
|
+
})();
|
|
77838
|
+
const port = parsed.port !== "" ? parseInt(parsed.port, 10) : defaultPort;
|
|
77827
77839
|
const user = decodeURIComponent(parsed.username || "");
|
|
77828
77840
|
const password = decodeURIComponent(parsed.password || "");
|
|
77829
77841
|
const database = parsed.pathname.slice(1);
|
|
@@ -77847,13 +77859,14 @@ function parseEnvDatabase(env) {
|
|
|
77847
77859
|
throw new EnvParseError("DB_NAME or DB_DATABASE is required when using component format");
|
|
77848
77860
|
}
|
|
77849
77861
|
const defaults = getDefaultsForSystem(system);
|
|
77850
|
-
const
|
|
77862
|
+
const defaultPort = typeof defaults.port === "number" ? defaults.port : 5432;
|
|
77863
|
+
const port = env.DB_PORT ? parseInt(env.DB_PORT, 10) : defaultPort;
|
|
77851
77864
|
if (isNaN(port) || port < 1 || port > 65535) {
|
|
77852
77865
|
throw new EnvParseError(`DB_PORT must be between 1 and 65535, got: ${env.DB_PORT}`);
|
|
77853
77866
|
}
|
|
77854
77867
|
return {
|
|
77855
77868
|
system,
|
|
77856
|
-
host: env.DB_HOST || defaults.host
|
|
77869
|
+
host: env.DB_HOST || (typeof defaults.host === "string" ? defaults.host : "localhost"),
|
|
77857
77870
|
port,
|
|
77858
77871
|
user,
|
|
77859
77872
|
password: env.DB_PASSWORD || "",
|
|
@@ -77904,8 +77917,72 @@ async function loadEnvFile(filePath) {
|
|
|
77904
77917
|
}
|
|
77905
77918
|
}
|
|
77906
77919
|
|
|
77920
|
+
// src/core/config-binding.ts
|
|
77921
|
+
import { createHash } from "crypto";
|
|
77922
|
+
import { homedir } from "os";
|
|
77923
|
+
import { basename, join, resolve } from "path";
|
|
77924
|
+
var BINDING_FILE_NAME = "config.json";
|
|
77925
|
+
var DBCLI_HOME_ROOT = join(homedir(), ".config", "dbcli");
|
|
77926
|
+
function isProjectConfigBinding(raw) {
|
|
77927
|
+
if (typeof raw !== "object" || raw === null)
|
|
77928
|
+
return false;
|
|
77929
|
+
const candidate = raw;
|
|
77930
|
+
return candidate.version === 3 && typeof candidate.binding === "object" && candidate.binding !== null && candidate.binding.type === "home-storage" && typeof candidate.binding.storagePath === "string" && candidate.binding.storagePath.length > 0 && typeof candidate.binding.projectPath === "string" && candidate.binding.projectPath.length > 0 && typeof candidate.binding.createdAt === "string" && candidate.binding.createdAt.length > 0;
|
|
77931
|
+
}
|
|
77932
|
+
function getDbcliHomeRoot() {
|
|
77933
|
+
return DBCLI_HOME_ROOT;
|
|
77934
|
+
}
|
|
77935
|
+
function getProjectStoragePath(projectPath) {
|
|
77936
|
+
const normalizedProjectPath = resolve(projectPath);
|
|
77937
|
+
const projectName = basename(normalizedProjectPath) || "project";
|
|
77938
|
+
const hash = createHash("sha1").update(normalizedProjectPath).digest("hex").slice(0, 12);
|
|
77939
|
+
return join(getDbcliHomeRoot(), "projects", `${projectName}-${hash}`);
|
|
77940
|
+
}
|
|
77941
|
+
async function readProjectBinding(projectPath) {
|
|
77942
|
+
const configFile = Bun.file(join(projectPath, BINDING_FILE_NAME));
|
|
77943
|
+
if (!await configFile.exists())
|
|
77944
|
+
return null;
|
|
77945
|
+
try {
|
|
77946
|
+
const raw = JSON.parse(await configFile.text());
|
|
77947
|
+
return isProjectConfigBinding(raw) ? raw : null;
|
|
77948
|
+
} catch {
|
|
77949
|
+
return null;
|
|
77950
|
+
}
|
|
77951
|
+
}
|
|
77952
|
+
async function resolveConfigStoragePath(path) {
|
|
77953
|
+
const binding = await readProjectBinding(path);
|
|
77954
|
+
return binding?.binding.storagePath ?? path;
|
|
77955
|
+
}
|
|
77956
|
+
async function writeProjectBinding(projectPath, storagePath = getProjectStoragePath(projectPath)) {
|
|
77957
|
+
const binding = {
|
|
77958
|
+
version: 3,
|
|
77959
|
+
binding: {
|
|
77960
|
+
type: "home-storage",
|
|
77961
|
+
storagePath,
|
|
77962
|
+
projectPath: resolve(projectPath),
|
|
77963
|
+
createdAt: new Date().toISOString()
|
|
77964
|
+
}
|
|
77965
|
+
};
|
|
77966
|
+
await Bun.$`mkdir -p ${projectPath}`;
|
|
77967
|
+
await Bun.$`mkdir -p ${storagePath}`;
|
|
77968
|
+
await Bun.file(join(projectPath, BINDING_FILE_NAME)).write(JSON.stringify(binding, null, 2));
|
|
77969
|
+
return binding;
|
|
77970
|
+
}
|
|
77971
|
+
async function migrateLegacyProjectEnvLocal(projectPath, storagePath = getProjectStoragePath(projectPath)) {
|
|
77972
|
+
const projectEnvPath = join(projectPath, ".env.local");
|
|
77973
|
+
const projectEnvFile = Bun.file(projectEnvPath);
|
|
77974
|
+
if (!await projectEnvFile.exists())
|
|
77975
|
+
return;
|
|
77976
|
+
const storageEnvPath = join(storagePath, ".env.local");
|
|
77977
|
+
await Bun.$`mkdir -p ${storagePath}`;
|
|
77978
|
+
if (!await Bun.file(storageEnvPath).exists()) {
|
|
77979
|
+
await Bun.file(storageEnvPath).write(await projectEnvFile.text());
|
|
77980
|
+
}
|
|
77981
|
+
await Bun.$`rm -f ${projectEnvPath}`;
|
|
77982
|
+
}
|
|
77983
|
+
|
|
77907
77984
|
// src/core/config-v2.ts
|
|
77908
|
-
import { join } from "path";
|
|
77985
|
+
import { join as join2 } from "path";
|
|
77909
77986
|
function detectConfigVersion(raw) {
|
|
77910
77987
|
if (typeof raw === "object" && raw !== null && "version" in raw && raw.version === 2 && "connections" in raw) {
|
|
77911
77988
|
return 2;
|
|
@@ -77929,12 +78006,13 @@ function resolveConnection(config, name) {
|
|
|
77929
78006
|
}
|
|
77930
78007
|
async function loadConnectionEnv(resolved, basePath) {
|
|
77931
78008
|
if (resolved.envFile) {
|
|
77932
|
-
const envPath =
|
|
78009
|
+
const envPath = join2(basePath, resolved.envFile);
|
|
77933
78010
|
await loadEnvFile(envPath);
|
|
77934
78011
|
}
|
|
77935
78012
|
}
|
|
77936
78013
|
async function readV2Config(path) {
|
|
77937
|
-
const
|
|
78014
|
+
const storagePath = await resolveConfigStoragePath(path);
|
|
78015
|
+
const configPath = join2(storagePath, "config.json");
|
|
77938
78016
|
const file = Bun.file(configPath);
|
|
77939
78017
|
if (!await file.exists()) {
|
|
77940
78018
|
throw new ConfigError(`\u627E\u4E0D\u5230 V2 \u8A2D\u5B9A\u6A94\uFF1A${configPath}`);
|
|
@@ -77945,12 +78023,15 @@ async function readV2Config(path) {
|
|
|
77945
78023
|
}
|
|
77946
78024
|
async function writeV2Config(path, config) {
|
|
77947
78025
|
DbcliConfigV2Schema.parse(config);
|
|
77948
|
-
const
|
|
78026
|
+
const storagePath = await resolveConfigStoragePath(path);
|
|
78027
|
+
const configPath = join2(storagePath, "config.json");
|
|
78028
|
+
await Bun.$`mkdir -p ${storagePath}`;
|
|
77949
78029
|
const json = JSON.stringify(config, null, 2);
|
|
77950
78030
|
await Bun.write(configPath, json);
|
|
77951
78031
|
}
|
|
77952
78032
|
async function patchConnectionSchema(dbcliPath, connectionName, schema, metadataUpdate) {
|
|
77953
|
-
const
|
|
78033
|
+
const storagePath = await resolveConfigStoragePath(dbcliPath);
|
|
78034
|
+
const v2Config = await readV2Config(storagePath);
|
|
77954
78035
|
const updated = {
|
|
77955
78036
|
...v2Config,
|
|
77956
78037
|
schemas: {
|
|
@@ -77962,11 +78043,11 @@ async function patchConnectionSchema(dbcliPath, connectionName, schema, metadata
|
|
|
77962
78043
|
...metadataUpdate ?? {}
|
|
77963
78044
|
}
|
|
77964
78045
|
};
|
|
77965
|
-
await writeV2Config(
|
|
78046
|
+
await writeV2Config(storagePath, updated);
|
|
77966
78047
|
}
|
|
77967
78048
|
|
|
77968
78049
|
// src/core/config.ts
|
|
77969
|
-
import { join as
|
|
78050
|
+
import { join as join7 } from "path";
|
|
77970
78051
|
var _globalConnectionName;
|
|
77971
78052
|
function setGlobalConnectionName(name) {
|
|
77972
78053
|
_globalConnectionName = name;
|
|
@@ -77977,11 +78058,12 @@ function getGlobalConnectionName() {
|
|
|
77977
78058
|
async function getSchemaIsolationConnectionName(dbcliPath) {
|
|
77978
78059
|
const effectiveName = getGlobalConnectionName();
|
|
77979
78060
|
try {
|
|
77980
|
-
const
|
|
78061
|
+
const storagePath = await resolveConfigStoragePath(dbcliPath);
|
|
78062
|
+
const stat = await Bun.file(storagePath).stat();
|
|
77981
78063
|
const isDirectory = stat?.isDirectory() ?? false;
|
|
77982
78064
|
if (!isDirectory)
|
|
77983
78065
|
return;
|
|
77984
|
-
const configJsonPath =
|
|
78066
|
+
const configJsonPath = join7(storagePath, "config.json");
|
|
77985
78067
|
const configFile = Bun.file(configJsonPath);
|
|
77986
78068
|
if (!await configFile.exists())
|
|
77987
78069
|
return;
|
|
@@ -78007,7 +78089,8 @@ var DEFAULT_CONFIG = {
|
|
|
78007
78089
|
schema: {},
|
|
78008
78090
|
metadata: {
|
|
78009
78091
|
version: "1.0"
|
|
78010
|
-
}
|
|
78092
|
+
},
|
|
78093
|
+
blacklist: { tables: [], columns: {} }
|
|
78011
78094
|
};
|
|
78012
78095
|
function isEnvReference(value) {
|
|
78013
78096
|
return typeof value === "object" && value !== null && "$env" in value && typeof value.$env === "string";
|
|
@@ -78047,21 +78130,29 @@ function resolveEnvReferences(config, env, parentKey, strict = false) {
|
|
|
78047
78130
|
}
|
|
78048
78131
|
function parseEnvPassword(content) {
|
|
78049
78132
|
const match = content.match(/^DBCLI_PASSWORD=(.+)$/m);
|
|
78050
|
-
return match ? match[1].trim() : null;
|
|
78133
|
+
return match?.[1] != null ? match[1].trim() : null;
|
|
78051
78134
|
}
|
|
78052
78135
|
var configModule = {
|
|
78053
78136
|
async read(path, connectionName) {
|
|
78054
78137
|
const effectiveConnectionName = connectionName ?? _globalConnectionName;
|
|
78055
78138
|
try {
|
|
78139
|
+
const binding = await readProjectBinding(path);
|
|
78140
|
+
const storagePath = await resolveConfigStoragePath(path);
|
|
78141
|
+
if (binding) {
|
|
78142
|
+
const storageConfigExists = await Bun.file(join7(storagePath, "config.json")).exists();
|
|
78143
|
+
if (!storageConfigExists) {
|
|
78144
|
+
throw new ConfigError(`Bound dbcli config not found: ${join7(storagePath, "config.json")}`);
|
|
78145
|
+
}
|
|
78146
|
+
}
|
|
78056
78147
|
let isDirectory = false;
|
|
78057
78148
|
try {
|
|
78058
|
-
const stat = await Bun.file(
|
|
78149
|
+
const stat = await Bun.file(storagePath).stat();
|
|
78059
78150
|
isDirectory = stat?.isDirectory() ?? false;
|
|
78060
78151
|
} catch {
|
|
78061
78152
|
isDirectory = false;
|
|
78062
78153
|
}
|
|
78063
78154
|
if (isDirectory) {
|
|
78064
|
-
const configPath =
|
|
78155
|
+
const configPath = join7(storagePath, "config.json");
|
|
78065
78156
|
const configFile = Bun.file(configPath);
|
|
78066
78157
|
const configExists = await configFile.exists();
|
|
78067
78158
|
if (configExists) {
|
|
@@ -78070,8 +78161,8 @@ var configModule = {
|
|
|
78070
78161
|
if (detectConfigVersion(config) === 2) {
|
|
78071
78162
|
const v2Config = DbcliConfigV2Schema.parse(config);
|
|
78072
78163
|
const resolved = resolveConnection(v2Config, effectiveConnectionName);
|
|
78073
|
-
await loadConnectionEnv(resolved,
|
|
78074
|
-
const envLocalPath =
|
|
78164
|
+
await loadConnectionEnv(resolved, storagePath);
|
|
78165
|
+
const envLocalPath = join7(storagePath, ".env.local");
|
|
78075
78166
|
const envLocalFile = Bun.file(envLocalPath);
|
|
78076
78167
|
let legacyPassword = null;
|
|
78077
78168
|
if (await envLocalFile.exists()) {
|
|
@@ -78088,7 +78179,7 @@ var configModule = {
|
|
|
78088
78179
|
let schema = (v2Config.schemas ?? {})[resolved.name] ?? v2Config.schema;
|
|
78089
78180
|
try {
|
|
78090
78181
|
const { SchemaLayeredLoader: SchemaLayeredLoader3 } = await Promise.resolve().then(() => (init_schema_loader(), exports_schema_loader));
|
|
78091
|
-
const loader = new SchemaLayeredLoader3(
|
|
78182
|
+
const loader = new SchemaLayeredLoader3(storagePath, { connectionName: resolved.name });
|
|
78092
78183
|
const { cache, index } = await loader.initialize();
|
|
78093
78184
|
if (index && Object.keys(index.tables).length > 0) {
|
|
78094
78185
|
const layeredSchema = {};
|
|
@@ -78113,7 +78204,7 @@ var configModule = {
|
|
|
78113
78204
|
});
|
|
78114
78205
|
}
|
|
78115
78206
|
const resolvedConfig = resolveEnvReferences(config, process.env, undefined, false);
|
|
78116
|
-
const envPath =
|
|
78207
|
+
const envPath = join7(storagePath, ".env.local");
|
|
78117
78208
|
const envFile = Bun.file(envPath);
|
|
78118
78209
|
if (await envFile.exists()) {
|
|
78119
78210
|
const envContent = await envFile.text();
|
|
@@ -78175,12 +78266,19 @@ var configModule = {
|
|
|
78175
78266
|
async write(path, config) {
|
|
78176
78267
|
try {
|
|
78177
78268
|
this.validate(config);
|
|
78178
|
-
const
|
|
78179
|
-
|
|
78180
|
-
|
|
78269
|
+
const storagePath = await resolveConfigStoragePath(path);
|
|
78270
|
+
let isDirectory = false;
|
|
78271
|
+
try {
|
|
78272
|
+
const stat = await Bun.file(storagePath).stat();
|
|
78273
|
+
isDirectory = stat?.isDirectory() ?? false;
|
|
78274
|
+
} catch {
|
|
78275
|
+
isDirectory = false;
|
|
78276
|
+
}
|
|
78277
|
+
if (isDirectory || path.endsWith(".dbcli") || path === storagePath && isDirectory) {
|
|
78278
|
+
await Bun.$`mkdir -p ${storagePath}`;
|
|
78181
78279
|
const hasEnvReferences = isEnvReference(config.connection.password);
|
|
78182
78280
|
if (hasEnvReferences) {
|
|
78183
|
-
const configPath =
|
|
78281
|
+
const configPath = join7(storagePath, "config.json");
|
|
78184
78282
|
const configJson = JSON.stringify(config, null, 2);
|
|
78185
78283
|
await Bun.file(configPath).write(configJson);
|
|
78186
78284
|
} else {
|
|
@@ -78193,11 +78291,11 @@ var configModule = {
|
|
|
78193
78291
|
}
|
|
78194
78292
|
};
|
|
78195
78293
|
delete configWithoutPassword.connection.password;
|
|
78196
|
-
const configPath =
|
|
78294
|
+
const configPath = join7(storagePath, "config.json");
|
|
78197
78295
|
const configJson = JSON.stringify(configWithoutPassword, null, 2);
|
|
78198
78296
|
await Bun.file(configPath).write(configJson);
|
|
78199
78297
|
if (password) {
|
|
78200
|
-
const envPath =
|
|
78298
|
+
const envPath = join7(storagePath, ".env.local");
|
|
78201
78299
|
const envContent = `# Database Credentials - DO NOT commit to git
|
|
78202
78300
|
|
|
78203
78301
|
DBCLI_PASSWORD=${password}
|
|
@@ -78220,7 +78318,7 @@ DBCLI_PASSWORD=${password}
|
|
|
78220
78318
|
|
|
78221
78319
|
// src/utils/prompts.ts
|
|
78222
78320
|
async function readLineFromStdin(prompt = "") {
|
|
78223
|
-
return new Promise((
|
|
78321
|
+
return new Promise((resolve2) => {
|
|
78224
78322
|
if (prompt) {
|
|
78225
78323
|
process.stdout.write(prompt);
|
|
78226
78324
|
}
|
|
@@ -78235,12 +78333,12 @@ async function readLineFromStdin(prompt = "") {
|
|
|
78235
78333
|
process.stdin.pause();
|
|
78236
78334
|
process.stdin.removeListener("data", onData);
|
|
78237
78335
|
process.stdin.removeListener("end", onEnd);
|
|
78238
|
-
|
|
78336
|
+
resolve2(lines2[0].trim());
|
|
78239
78337
|
}
|
|
78240
78338
|
};
|
|
78241
78339
|
const onEnd = () => {
|
|
78242
78340
|
process.stdin.removeListener("data", onData);
|
|
78243
|
-
|
|
78341
|
+
resolve2(data.trim());
|
|
78244
78342
|
};
|
|
78245
78343
|
process.stdin.on("data", onData);
|
|
78246
78344
|
process.stdin.on("end", onEnd);
|
|
@@ -78535,7 +78633,9 @@ class PostgreSQLAdapter {
|
|
|
78535
78633
|
}
|
|
78536
78634
|
async testConnection() {
|
|
78537
78635
|
if (!this.pool) {
|
|
78538
|
-
throw new ConnectionError("UNKNOWN", "Database connection not established", [
|
|
78636
|
+
throw new ConnectionError("UNKNOWN", "Database connection not established", [
|
|
78637
|
+
"Call connect() to establish a connection"
|
|
78638
|
+
]);
|
|
78539
78639
|
}
|
|
78540
78640
|
try {
|
|
78541
78641
|
const result = await this.execute("SELECT 1 as count");
|
|
@@ -78546,7 +78646,9 @@ class PostgreSQLAdapter {
|
|
|
78546
78646
|
}
|
|
78547
78647
|
async execute(sql, params) {
|
|
78548
78648
|
if (!this.pool) {
|
|
78549
|
-
throw new ConnectionError("UNKNOWN", "Database connection not established", [
|
|
78649
|
+
throw new ConnectionError("UNKNOWN", "Database connection not established", [
|
|
78650
|
+
"Call connect() to establish a connection"
|
|
78651
|
+
]);
|
|
78550
78652
|
}
|
|
78551
78653
|
try {
|
|
78552
78654
|
const result = params ? await this.pool.query(sql, params) : await this.pool.query(sql);
|
|
@@ -78564,7 +78666,9 @@ class PostgreSQLAdapter {
|
|
|
78564
78666
|
}
|
|
78565
78667
|
async listTables() {
|
|
78566
78668
|
if (!this.pool) {
|
|
78567
|
-
throw new ConnectionError("UNKNOWN", "Database connection not established", [
|
|
78669
|
+
throw new ConnectionError("UNKNOWN", "Database connection not established", [
|
|
78670
|
+
"Call connect() to establish a connection"
|
|
78671
|
+
]);
|
|
78568
78672
|
}
|
|
78569
78673
|
try {
|
|
78570
78674
|
const query = `
|
|
@@ -78601,7 +78705,9 @@ class PostgreSQLAdapter {
|
|
|
78601
78705
|
}
|
|
78602
78706
|
async getTableSchema(tableName) {
|
|
78603
78707
|
if (!this.pool) {
|
|
78604
|
-
throw new ConnectionError("UNKNOWN", "Database connection not established", [
|
|
78708
|
+
throw new ConnectionError("UNKNOWN", "Database connection not established", [
|
|
78709
|
+
"Call connect() to establish a connection"
|
|
78710
|
+
]);
|
|
78605
78711
|
}
|
|
78606
78712
|
try {
|
|
78607
78713
|
const columnQuery = `
|
|
@@ -78695,7 +78801,9 @@ class PostgreSQLAdapter {
|
|
|
78695
78801
|
FROM pg_class
|
|
78696
78802
|
WHERE relname = $1
|
|
78697
78803
|
`;
|
|
78698
|
-
const estimateResult = await this.execute(estimateQuery, [
|
|
78804
|
+
const estimateResult = await this.execute(estimateQuery, [
|
|
78805
|
+
tableName
|
|
78806
|
+
]);
|
|
78699
78807
|
const estimateResults = estimateResult.rows;
|
|
78700
78808
|
const pkQuery = `
|
|
78701
78809
|
SELECT array_agg(a.attname) as columns
|
|
@@ -78799,7 +78907,9 @@ class MySQLAdapter {
|
|
|
78799
78907
|
}
|
|
78800
78908
|
async testConnection() {
|
|
78801
78909
|
if (!this.db) {
|
|
78802
|
-
throw new ConnectionError("UNKNOWN", "Database connection not established", [
|
|
78910
|
+
throw new ConnectionError("UNKNOWN", "Database connection not established", [
|
|
78911
|
+
"Call connect() to establish a connection"
|
|
78912
|
+
]);
|
|
78803
78913
|
}
|
|
78804
78914
|
try {
|
|
78805
78915
|
const result = await this.execute("SELECT 1 as count");
|
|
@@ -78810,7 +78920,9 @@ class MySQLAdapter {
|
|
|
78810
78920
|
}
|
|
78811
78921
|
async execute(sql, params) {
|
|
78812
78922
|
if (!this.db) {
|
|
78813
|
-
throw new ConnectionError("UNKNOWN", "Database connection not established", [
|
|
78923
|
+
throw new ConnectionError("UNKNOWN", "Database connection not established", [
|
|
78924
|
+
"Call connect() to establish a connection"
|
|
78925
|
+
]);
|
|
78814
78926
|
}
|
|
78815
78927
|
try {
|
|
78816
78928
|
const [result] = params ? await this.db.execute(sql, params) : await this.db.execute(sql);
|
|
@@ -78836,7 +78948,9 @@ class MySQLAdapter {
|
|
|
78836
78948
|
}
|
|
78837
78949
|
async listTables() {
|
|
78838
78950
|
if (!this.db) {
|
|
78839
|
-
throw new ConnectionError("UNKNOWN", "Database connection not established", [
|
|
78951
|
+
throw new ConnectionError("UNKNOWN", "Database connection not established", [
|
|
78952
|
+
"Call connect() to establish a connection"
|
|
78953
|
+
]);
|
|
78840
78954
|
}
|
|
78841
78955
|
try {
|
|
78842
78956
|
const query = `
|
|
@@ -78869,7 +78983,9 @@ class MySQLAdapter {
|
|
|
78869
78983
|
}
|
|
78870
78984
|
async getTableSchema(tableName) {
|
|
78871
78985
|
if (!this.db) {
|
|
78872
|
-
throw new ConnectionError("UNKNOWN", "Database connection not established", [
|
|
78986
|
+
throw new ConnectionError("UNKNOWN", "Database connection not established", [
|
|
78987
|
+
"Call connect() to establish a connection"
|
|
78988
|
+
]);
|
|
78873
78989
|
}
|
|
78874
78990
|
try {
|
|
78875
78991
|
const columnQuery = `
|
|
@@ -78937,7 +79053,9 @@ class MySQLAdapter {
|
|
|
78937
79053
|
FROM information_schema.TABLES
|
|
78938
79054
|
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?
|
|
78939
79055
|
`;
|
|
78940
|
-
const estimateResult = await this.execute(estimateQuery, [
|
|
79056
|
+
const estimateResult = await this.execute(estimateQuery, [
|
|
79057
|
+
tableName
|
|
79058
|
+
]);
|
|
78941
79059
|
const estimateResults = estimateResult.rows;
|
|
78942
79060
|
const schema = {
|
|
78943
79061
|
name: tableName,
|
|
@@ -78976,6 +79094,7 @@ class MySQLAdapter {
|
|
|
78976
79094
|
}
|
|
78977
79095
|
|
|
78978
79096
|
// src/adapters/mongodb-adapter.ts
|
|
79097
|
+
import { resolveSrv, resolveTxt } from "dns/promises";
|
|
78979
79098
|
class MongoDBAdapter {
|
|
78980
79099
|
options;
|
|
78981
79100
|
ClientClass;
|
|
@@ -79000,9 +79119,101 @@ class MongoDBAdapter {
|
|
|
79000
79119
|
}
|
|
79001
79120
|
return `mongodb://${host}:${port}/${database}`;
|
|
79002
79121
|
}
|
|
79122
|
+
parseTxtRecords(records) {
|
|
79123
|
+
const combined = records.flat().map((record) => record.replace(/^"|"$/g, "")).join("&");
|
|
79124
|
+
if (!combined)
|
|
79125
|
+
return {};
|
|
79126
|
+
const params = new URLSearchParams(combined);
|
|
79127
|
+
return Object.fromEntries(params.entries());
|
|
79128
|
+
}
|
|
79129
|
+
async resolveSrvHosts(hostname) {
|
|
79130
|
+
const srvName = `_mongodb._tcp.${hostname}`;
|
|
79131
|
+
try {
|
|
79132
|
+
const records = await resolveSrv(srvName);
|
|
79133
|
+
if (!records.length) {
|
|
79134
|
+
throw new Error(`No SRV records found for ${srvName}`);
|
|
79135
|
+
}
|
|
79136
|
+
return records.map((record) => {
|
|
79137
|
+
const target = String(record.name || record.target || "").replace(/\.$/, "");
|
|
79138
|
+
return `${target}:${record.port}`;
|
|
79139
|
+
});
|
|
79140
|
+
} catch (error) {
|
|
79141
|
+
const code = error?.code;
|
|
79142
|
+
if (code !== "ECONNREFUSED") {
|
|
79143
|
+
throw error;
|
|
79144
|
+
}
|
|
79145
|
+
}
|
|
79146
|
+
const response = await fetch(`https://dns.google/resolve?name=${encodeURIComponent(srvName)}&type=SRV`);
|
|
79147
|
+
if (!response.ok) {
|
|
79148
|
+
throw new Error(`SRV lookup failed with HTTP ${response.status}`);
|
|
79149
|
+
}
|
|
79150
|
+
const payload = await response.json();
|
|
79151
|
+
if (payload.Status !== 0 || !payload.Answer?.length) {
|
|
79152
|
+
throw new Error(payload.Comment || `No SRV records found for ${srvName}`);
|
|
79153
|
+
}
|
|
79154
|
+
return payload.Answer.map((answer) => {
|
|
79155
|
+
const parts = answer.data.trim().split(/\s+/);
|
|
79156
|
+
const port = parts[2];
|
|
79157
|
+
const target = parts.slice(3).join(" ").replace(/\.$/, "");
|
|
79158
|
+
return `${target}:${port}`;
|
|
79159
|
+
});
|
|
79160
|
+
}
|
|
79161
|
+
async resolveTxtOptions(hostname) {
|
|
79162
|
+
try {
|
|
79163
|
+
const records = await resolveTxt(hostname);
|
|
79164
|
+
return this.parseTxtRecords(records);
|
|
79165
|
+
} catch (error) {
|
|
79166
|
+
const code = error?.code;
|
|
79167
|
+
if (code !== "ECONNREFUSED") {
|
|
79168
|
+
throw error;
|
|
79169
|
+
}
|
|
79170
|
+
}
|
|
79171
|
+
const response = await fetch(`https://dns.google/resolve?name=${encodeURIComponent(hostname)}&type=TXT`);
|
|
79172
|
+
if (!response.ok) {
|
|
79173
|
+
throw new Error(`TXT lookup failed with HTTP ${response.status}`);
|
|
79174
|
+
}
|
|
79175
|
+
const payload = await response.json();
|
|
79176
|
+
if (payload.Status !== 0 || !payload.Answer?.length) {
|
|
79177
|
+
return {};
|
|
79178
|
+
}
|
|
79179
|
+
return this.parseTxtRecords(payload.Answer.map((answer) => [answer.data]));
|
|
79180
|
+
}
|
|
79181
|
+
async buildResolvedUri() {
|
|
79182
|
+
if (!this.options.uri) {
|
|
79183
|
+
return this.buildUri();
|
|
79184
|
+
}
|
|
79185
|
+
if (!this.options.uri.startsWith("mongodb+srv://")) {
|
|
79186
|
+
return this.options.uri;
|
|
79187
|
+
}
|
|
79188
|
+
const url = new URL(this.options.uri);
|
|
79189
|
+
const hosts = await this.resolveSrvHosts(url.hostname);
|
|
79190
|
+
const txtOptions = await this.resolveTxtOptions(url.hostname);
|
|
79191
|
+
const query = new URLSearchParams(url.searchParams);
|
|
79192
|
+
for (const [key2, value] of Object.entries(txtOptions)) {
|
|
79193
|
+
if (!query.has(key2)) {
|
|
79194
|
+
query.set(key2, value);
|
|
79195
|
+
}
|
|
79196
|
+
}
|
|
79197
|
+
if (!query.has("tls") && !query.has("ssl")) {
|
|
79198
|
+
query.set("tls", "true");
|
|
79199
|
+
}
|
|
79200
|
+
if ((url.username || url.password) && !query.has("authSource")) {
|
|
79201
|
+
query.set("authSource", "admin");
|
|
79202
|
+
}
|
|
79203
|
+
const userInfo = url.username || url.password ? `${encodeURIComponent(decodeURIComponent(url.username))}${url.password ? `:${encodeURIComponent(decodeURIComponent(url.password))}` : ""}@` : "";
|
|
79204
|
+
const path = url.pathname && url.pathname !== "/" ? url.pathname : `/${this.options.database || "test"}`;
|
|
79205
|
+
const search = query.toString();
|
|
79206
|
+
return `mongodb://${userInfo}${hosts.join(",")}${path}${search ? `?${search}` : ""}`;
|
|
79207
|
+
}
|
|
79208
|
+
getDatabase() {
|
|
79209
|
+
if (!this.client) {
|
|
79210
|
+
throw new ConnectionError("UNKNOWN", "\u5C1A\u672A\u9023\u7DDA\uFF0C\u8ACB\u5148\u547C\u53EB connect()", []);
|
|
79211
|
+
}
|
|
79212
|
+
return this.client.db(this.options.database || undefined);
|
|
79213
|
+
}
|
|
79003
79214
|
async connect() {
|
|
79004
79215
|
const ClientClass = await this.resolveClientClass();
|
|
79005
|
-
const uri = this.
|
|
79216
|
+
const uri = await this.buildResolvedUri();
|
|
79006
79217
|
try {
|
|
79007
79218
|
this.client = new ClientClass(uri, { serverSelectionTimeoutMS: this.options.timeout ?? 5000 });
|
|
79008
79219
|
await this.client.connect();
|
|
@@ -79022,11 +79233,8 @@ class MongoDBAdapter {
|
|
|
79022
79233
|
}
|
|
79023
79234
|
}
|
|
79024
79235
|
async execute(query, params) {
|
|
79025
|
-
|
|
79026
|
-
throw new ConnectionError("UNKNOWN", "\u5C1A\u672A\u9023\u7DDA\uFF0C\u8ACB\u5148\u547C\u53EB connect()", []);
|
|
79027
|
-
}
|
|
79236
|
+
const db = this.getDatabase();
|
|
79028
79237
|
const collectionName = params?.[0];
|
|
79029
|
-
const db = this.client.db();
|
|
79030
79238
|
const collection = db.collection(collectionName);
|
|
79031
79239
|
let parsed;
|
|
79032
79240
|
try {
|
|
@@ -79043,10 +79251,7 @@ class MongoDBAdapter {
|
|
|
79043
79251
|
return { rows: docs, affectedRows: docs.length };
|
|
79044
79252
|
}
|
|
79045
79253
|
async listCollections() {
|
|
79046
|
-
|
|
79047
|
-
throw new ConnectionError("UNKNOWN", "\u5C1A\u672A\u9023\u7DDA\uFF0C\u8ACB\u5148\u547C\u53EB connect()", []);
|
|
79048
|
-
}
|
|
79049
|
-
const db = this.client.db();
|
|
79254
|
+
const db = this.getDatabase();
|
|
79050
79255
|
const colls = await db.listCollections().toArray();
|
|
79051
79256
|
const results = await Promise.all(colls.map(async (col) => {
|
|
79052
79257
|
try {
|
|
@@ -79058,19 +79263,75 @@ class MongoDBAdapter {
|
|
|
79058
79263
|
}));
|
|
79059
79264
|
return results;
|
|
79060
79265
|
}
|
|
79266
|
+
async listTables() {
|
|
79267
|
+
const collections = await this.listCollections();
|
|
79268
|
+
return collections.map((c) => ({
|
|
79269
|
+
name: c.name,
|
|
79270
|
+
estimatedRowCount: c.documentCount,
|
|
79271
|
+
columns: []
|
|
79272
|
+
}));
|
|
79273
|
+
}
|
|
79274
|
+
async getTableSchema(collectionName) {
|
|
79275
|
+
const db = this.getDatabase();
|
|
79276
|
+
const collection = db.collection(collectionName);
|
|
79277
|
+
const estimatedRowCount = await collection.estimatedDocumentCount();
|
|
79278
|
+
const samples = await collection.find().limit(5).toArray();
|
|
79279
|
+
const columnMap = new Map;
|
|
79280
|
+
for (const doc of samples) {
|
|
79281
|
+
for (const [key2, value] of Object.entries(doc)) {
|
|
79282
|
+
if (!columnMap.has(key2)) {
|
|
79283
|
+
columnMap.set(key2, new Set);
|
|
79284
|
+
}
|
|
79285
|
+
columnMap.get(key2).add(typeof value);
|
|
79286
|
+
}
|
|
79287
|
+
}
|
|
79288
|
+
const columns = Array.from(columnMap.entries()).map(([name, types3]) => ({
|
|
79289
|
+
name,
|
|
79290
|
+
type: Array.from(types3).join(" | "),
|
|
79291
|
+
nullable: true
|
|
79292
|
+
}));
|
|
79293
|
+
return {
|
|
79294
|
+
name: collectionName,
|
|
79295
|
+
columns,
|
|
79296
|
+
estimatedRowCount,
|
|
79297
|
+
tableType: "collection"
|
|
79298
|
+
};
|
|
79299
|
+
}
|
|
79061
79300
|
async testConnection() {
|
|
79062
79301
|
if (!this.client)
|
|
79063
79302
|
return false;
|
|
79064
|
-
await this.
|
|
79303
|
+
await this.getDatabase().command({ ping: 1 });
|
|
79065
79304
|
return true;
|
|
79066
79305
|
}
|
|
79067
79306
|
async getServerVersion() {
|
|
79068
|
-
|
|
79069
|
-
throw new ConnectionError("UNKNOWN", "\u5C1A\u672A\u9023\u7DDA\uFF0C\u8ACB\u5148\u547C\u53EB connect()", []);
|
|
79070
|
-
}
|
|
79071
|
-
const info = await this.client.db().admin().serverInfo();
|
|
79307
|
+
const info = await this.getDatabase().admin().serverInfo();
|
|
79072
79308
|
return info.version ?? "unknown";
|
|
79073
79309
|
}
|
|
79310
|
+
async insert(collection, data) {
|
|
79311
|
+
const db = this.getDatabase();
|
|
79312
|
+
const result = await db.collection(collection).insertOne(data);
|
|
79313
|
+
return {
|
|
79314
|
+
rows: [],
|
|
79315
|
+
affectedRows: result.acknowledged ? 1 : 0,
|
|
79316
|
+
lastInsertId: result.insertedId.toString()
|
|
79317
|
+
};
|
|
79318
|
+
}
|
|
79319
|
+
async update(collection, filter, update) {
|
|
79320
|
+
const db = this.getDatabase();
|
|
79321
|
+
const result = await db.collection(collection).updateMany(filter, update);
|
|
79322
|
+
return {
|
|
79323
|
+
rows: [],
|
|
79324
|
+
affectedRows: result.modifiedCount
|
|
79325
|
+
};
|
|
79326
|
+
}
|
|
79327
|
+
async delete(collection, filter) {
|
|
79328
|
+
const db = this.getDatabase();
|
|
79329
|
+
const result = await db.collection(collection).deleteMany(filter);
|
|
79330
|
+
return {
|
|
79331
|
+
rows: [],
|
|
79332
|
+
affectedRows: result.deletedCount
|
|
79333
|
+
};
|
|
79334
|
+
}
|
|
79074
79335
|
}
|
|
79075
79336
|
|
|
79076
79337
|
// src/adapters/factory.ts
|
|
@@ -79082,6 +79343,8 @@ class AdapterFactory {
|
|
|
79082
79343
|
case "mysql":
|
|
79083
79344
|
case "mariadb":
|
|
79084
79345
|
return new MySQLAdapter(options);
|
|
79346
|
+
case "mongodb":
|
|
79347
|
+
return new MongoDBAdapter(options);
|
|
79085
79348
|
default:
|
|
79086
79349
|
throw new Error(`Unsupported database system: ${options.system}`);
|
|
79087
79350
|
}
|
|
@@ -79113,9 +79376,11 @@ function resolveConfigPath(command, options, fallback = ".dbcli") {
|
|
|
79113
79376
|
// src/commands/init.ts
|
|
79114
79377
|
var VALID_PERMISSIONS = ["query-only", "read-write", "data-admin", "admin"];
|
|
79115
79378
|
async function checkOverwrite(configPath, shouldPrompt, force) {
|
|
79379
|
+
const storagePath = await resolveConfigStoragePath(configPath);
|
|
79116
79380
|
const fileExists = await Bun.file(configPath).exists();
|
|
79117
|
-
const dirConfigExists = await Bun.file(
|
|
79118
|
-
|
|
79381
|
+
const dirConfigExists = await Bun.file(join8(configPath, "config.json")).exists();
|
|
79382
|
+
const storageConfigExists = await Bun.file(join8(storagePath, "config.json")).exists();
|
|
79383
|
+
if (!fileExists && !dirConfigExists && !storageConfigExists || force)
|
|
79119
79384
|
return true;
|
|
79120
79385
|
if (shouldPrompt) {
|
|
79121
79386
|
const overwrite = await promptUser.confirm(t("init.config_exists_overwrite"));
|
|
@@ -79128,7 +79393,8 @@ async function checkOverwrite(configPath, shouldPrompt, force) {
|
|
|
79128
79393
|
throw new Error(t("init.config_exists_use_force"));
|
|
79129
79394
|
}
|
|
79130
79395
|
async function handleRemove(configPath, name) {
|
|
79131
|
-
const
|
|
79396
|
+
const storagePath = await resolveConfigStoragePath(configPath);
|
|
79397
|
+
const configFile = Bun.file(join8(storagePath, "config.json"));
|
|
79132
79398
|
if (!await configFile.exists()) {
|
|
79133
79399
|
throw new Error(t("init.config_not_found"));
|
|
79134
79400
|
}
|
|
@@ -79136,7 +79402,7 @@ async function handleRemove(configPath, name) {
|
|
|
79136
79402
|
if (detectConfigVersion(raw) !== 2) {
|
|
79137
79403
|
throw new Error(t("init.requires_v2_remove"));
|
|
79138
79404
|
}
|
|
79139
|
-
const config = await readV2Config(
|
|
79405
|
+
const config = await readV2Config(storagePath);
|
|
79140
79406
|
if (!config.connections[name]) {
|
|
79141
79407
|
throw new Error(t_vars("init.connection_not_found", { name }));
|
|
79142
79408
|
}
|
|
@@ -79144,14 +79410,14 @@ async function handleRemove(configPath, name) {
|
|
|
79144
79410
|
if (connectionCount <= 1) {
|
|
79145
79411
|
throw new Error(t("init.cannot_remove_last"));
|
|
79146
79412
|
}
|
|
79147
|
-
const
|
|
79413
|
+
const remaining = Object.fromEntries(Object.entries(config.connections).filter(([connectionName]) => connectionName !== name));
|
|
79148
79414
|
const newDefault = config.default === name ? Object.keys(remaining)[0] : config.default;
|
|
79149
79415
|
const updated = {
|
|
79150
79416
|
...config,
|
|
79151
79417
|
default: newDefault,
|
|
79152
79418
|
connections: remaining
|
|
79153
79419
|
};
|
|
79154
|
-
await writeV2Config(
|
|
79420
|
+
await writeV2Config(storagePath, updated);
|
|
79155
79421
|
if (config.default === name) {
|
|
79156
79422
|
console.log(t_vars("init.connection_removed_switched", { name, newDefault }));
|
|
79157
79423
|
} else {
|
|
@@ -79163,7 +79429,8 @@ async function handleRename(configPath, renameArg) {
|
|
|
79163
79429
|
if (!oldName || !newName) {
|
|
79164
79430
|
throw new Error(t("init.rename_invalid_format"));
|
|
79165
79431
|
}
|
|
79166
|
-
const
|
|
79432
|
+
const storagePath = await resolveConfigStoragePath(configPath);
|
|
79433
|
+
const configFile = Bun.file(join8(storagePath, "config.json"));
|
|
79167
79434
|
if (!await configFile.exists()) {
|
|
79168
79435
|
throw new Error(t("init.config_not_found"));
|
|
79169
79436
|
}
|
|
@@ -79171,7 +79438,7 @@ async function handleRename(configPath, renameArg) {
|
|
|
79171
79438
|
if (detectConfigVersion(raw) !== 2) {
|
|
79172
79439
|
throw new Error(t("init.requires_v2_rename"));
|
|
79173
79440
|
}
|
|
79174
|
-
const config = await readV2Config(
|
|
79441
|
+
const config = await readV2Config(storagePath);
|
|
79175
79442
|
if (!config.connections[oldName]) {
|
|
79176
79443
|
throw new Error(t_vars("init.connection_not_found", { name: oldName }));
|
|
79177
79444
|
}
|
|
@@ -79184,17 +79451,54 @@ async function handleRename(configPath, renameArg) {
|
|
|
79184
79451
|
default: config.default === oldName ? newName : config.default,
|
|
79185
79452
|
connections: Object.fromEntries(entries)
|
|
79186
79453
|
};
|
|
79187
|
-
await writeV2Config(
|
|
79454
|
+
await writeV2Config(storagePath, updated);
|
|
79188
79455
|
console.log(t_vars("init.connection_renamed", { oldName, newName }));
|
|
79189
79456
|
}
|
|
79190
79457
|
async function writeV2InitConfig(configPath, connectionName, connection, permission, envFile) {
|
|
79191
|
-
const
|
|
79458
|
+
const storagePath = getProjectStoragePath(configPath);
|
|
79459
|
+
const configJsonPath = join8(storagePath, "config.json");
|
|
79192
79460
|
const configFile = Bun.file(configJsonPath);
|
|
79461
|
+
const projectConfigFile = Bun.file(join8(configPath, "config.json"));
|
|
79193
79462
|
let existingV2 = null;
|
|
79194
79463
|
if (await configFile.exists()) {
|
|
79195
79464
|
const raw = JSON.parse(await configFile.text());
|
|
79196
79465
|
if (detectConfigVersion(raw) === 2) {
|
|
79197
|
-
existingV2 = await readV2Config(
|
|
79466
|
+
existingV2 = await readV2Config(storagePath);
|
|
79467
|
+
} else {
|
|
79468
|
+
const v1Config = await configModule.read(storagePath);
|
|
79469
|
+
existingV2 = {
|
|
79470
|
+
version: 2,
|
|
79471
|
+
default: "default",
|
|
79472
|
+
connections: {
|
|
79473
|
+
default: {
|
|
79474
|
+
...v1Config.connection,
|
|
79475
|
+
permission: v1Config.permission
|
|
79476
|
+
}
|
|
79477
|
+
},
|
|
79478
|
+
schema: v1Config.schema || {},
|
|
79479
|
+
schemas: { default: v1Config.schema || {} },
|
|
79480
|
+
metadata: v1Config.metadata || { version: "1.0" },
|
|
79481
|
+
blacklist: v1Config.blacklist || { tables: [], columns: {} }
|
|
79482
|
+
};
|
|
79483
|
+
}
|
|
79484
|
+
} else if (await projectConfigFile.exists()) {
|
|
79485
|
+
const raw = JSON.parse(await projectConfigFile.text());
|
|
79486
|
+
if (detectConfigVersion(raw) === 2) {
|
|
79487
|
+
const v1Config = await configModule.read(configPath);
|
|
79488
|
+
existingV2 = {
|
|
79489
|
+
version: 2,
|
|
79490
|
+
default: "default",
|
|
79491
|
+
connections: {
|
|
79492
|
+
default: {
|
|
79493
|
+
...v1Config.connection,
|
|
79494
|
+
permission: v1Config.permission
|
|
79495
|
+
}
|
|
79496
|
+
},
|
|
79497
|
+
schema: v1Config.schema || {},
|
|
79498
|
+
schemas: { default: v1Config.schema || {} },
|
|
79499
|
+
metadata: v1Config.metadata || { version: "1.0" },
|
|
79500
|
+
blacklist: v1Config.blacklist || { tables: [], columns: {} }
|
|
79501
|
+
};
|
|
79198
79502
|
} else {
|
|
79199
79503
|
const v1Config = await configModule.read(configPath);
|
|
79200
79504
|
existingV2 = {
|
|
@@ -79207,16 +79511,17 @@ async function writeV2InitConfig(configPath, connectionName, connection, permiss
|
|
|
79207
79511
|
}
|
|
79208
79512
|
},
|
|
79209
79513
|
schema: v1Config.schema || {},
|
|
79514
|
+
schemas: { default: v1Config.schema || {} },
|
|
79210
79515
|
metadata: v1Config.metadata || { version: "1.0" },
|
|
79211
79516
|
blacklist: v1Config.blacklist || { tables: [], columns: {} }
|
|
79212
79517
|
};
|
|
79213
79518
|
}
|
|
79214
79519
|
} else {
|
|
79215
|
-
const legacyFile = Bun.file(
|
|
79520
|
+
const legacyFile = Bun.file(storagePath);
|
|
79216
79521
|
if (await legacyFile.exists()) {
|
|
79217
79522
|
const raw = JSON.parse(await legacyFile.text());
|
|
79218
79523
|
if (detectConfigVersion(raw) !== 2) {
|
|
79219
|
-
const v1Config = await configModule.read(
|
|
79524
|
+
const v1Config = await configModule.read(storagePath);
|
|
79220
79525
|
existingV2 = {
|
|
79221
79526
|
version: 2,
|
|
79222
79527
|
default: "default",
|
|
@@ -79227,6 +79532,7 @@ async function writeV2InitConfig(configPath, connectionName, connection, permiss
|
|
|
79227
79532
|
}
|
|
79228
79533
|
},
|
|
79229
79534
|
schema: v1Config.schema || {},
|
|
79535
|
+
schemas: { default: v1Config.schema || {} },
|
|
79230
79536
|
metadata: v1Config.metadata || { version: "1.0" },
|
|
79231
79537
|
blacklist: v1Config.blacklist || { tables: [], columns: {} }
|
|
79232
79538
|
};
|
|
@@ -79253,11 +79559,13 @@ async function writeV2InitConfig(configPath, connectionName, connection, permiss
|
|
|
79253
79559
|
[connectionName]: connEntry
|
|
79254
79560
|
},
|
|
79255
79561
|
schema: {},
|
|
79562
|
+
schemas: {},
|
|
79256
79563
|
metadata: { version: "1.0", createdAt: new Date().toISOString() },
|
|
79257
79564
|
blacklist: { tables: [], columns: {} }
|
|
79258
79565
|
};
|
|
79259
|
-
await
|
|
79260
|
-
await
|
|
79566
|
+
await writeV2Config(storagePath, v2Config);
|
|
79567
|
+
await migrateLegacyProjectEnvLocal(configPath, storagePath);
|
|
79568
|
+
await writeProjectBinding(configPath, storagePath);
|
|
79261
79569
|
console.log(t("init.config_saved"));
|
|
79262
79570
|
}
|
|
79263
79571
|
var 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)").option("--uri <uri>", "MongoDB connection URI (mongodb://user:pass@host:port/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) => {
|
|
@@ -79296,7 +79604,8 @@ async function initCommandHandler(options, command) {
|
|
|
79296
79604
|
console.log(t("init.env_parse_note"));
|
|
79297
79605
|
}
|
|
79298
79606
|
}
|
|
79299
|
-
|
|
79607
|
+
const systemFromCli = typeof options.system === "string" ? options.system : undefined;
|
|
79608
|
+
let system = systemFromCli ?? envConfig?.system ?? "postgresql";
|
|
79300
79609
|
if (shouldPrompt && !options.system && !envConfig?.system) {
|
|
79301
79610
|
system = await promptUser.select(t("init.select_system"), [
|
|
79302
79611
|
"postgresql",
|
|
@@ -79325,11 +79634,11 @@ async function initCommandHandler(options, command) {
|
|
|
79325
79634
|
};
|
|
79326
79635
|
let configForWrite;
|
|
79327
79636
|
if (options.useEnvRefs && shouldPrompt) {
|
|
79328
|
-
|
|
79329
|
-
|
|
79330
|
-
|
|
79331
|
-
|
|
79332
|
-
|
|
79637
|
+
const envHost = options.envHost || await promptUser.text(t("init.prompt_host"), "DB_HOST");
|
|
79638
|
+
const envPort = options.envPort || await promptUser.text(t("init.prompt_port"), "DB_PORT");
|
|
79639
|
+
const envUser = options.envUser || await promptUser.text(t("init.prompt_user"), "DB_USER");
|
|
79640
|
+
const envPassword = options.envPassword || await promptUser.text(t("init.prompt_password"), "DB_PASSWORD");
|
|
79641
|
+
const envDatabase = options.envDatabase || await promptUser.text(t("init.prompt_name"), "DB_DATABASE");
|
|
79333
79642
|
configForWrite = {
|
|
79334
79643
|
system: connection.system,
|
|
79335
79644
|
host: { $env: envHost },
|
|
@@ -79338,7 +79647,8 @@ async function initCommandHandler(options, command) {
|
|
|
79338
79647
|
password: { $env: envPassword },
|
|
79339
79648
|
database: { $env: envDatabase }
|
|
79340
79649
|
};
|
|
79341
|
-
|
|
79650
|
+
const permissionFromCli2 = typeof options.permission === "string" ? options.permission : undefined;
|
|
79651
|
+
let permission2 = permissionFromCli2 ?? "query-only";
|
|
79342
79652
|
if (!options.permission) {
|
|
79343
79653
|
permission2 = await promptUser.select(t("init.prompt_permission"), [
|
|
79344
79654
|
"query-only",
|
|
@@ -79362,27 +79672,36 @@ async function initCommandHandler(options, command) {
|
|
|
79362
79672
|
await writeV2InitConfig(configPath, connectionName, configForWrite, permission2, options.envFile);
|
|
79363
79673
|
return;
|
|
79364
79674
|
}
|
|
79365
|
-
|
|
79675
|
+
const storagePath2 = getProjectStoragePath(configPath);
|
|
79676
|
+
await Bun.$`mkdir -p ${storagePath2}`;
|
|
79677
|
+
await configModule.write(storagePath2, newConfig2);
|
|
79678
|
+
await migrateLegacyProjectEnvLocal(configPath, storagePath2);
|
|
79679
|
+
await writeProjectBinding(configPath, storagePath2);
|
|
79366
79680
|
console.log(t("init.config_saved"));
|
|
79367
79681
|
return;
|
|
79368
79682
|
}
|
|
79369
|
-
|
|
79370
|
-
const
|
|
79683
|
+
const strOpt = (v) => typeof v === "string" ? v : undefined;
|
|
79684
|
+
const portStrOpt = (v) => typeof v === "string" || typeof v === "number" ? String(v) : undefined;
|
|
79685
|
+
const defaultHost = typeof defaults2.host === "string" ? defaults2.host : "localhost";
|
|
79686
|
+
const defaultPort = typeof defaults2.port === "number" ? defaults2.port : 5432;
|
|
79687
|
+
connection.host = strOpt(options.host) ?? envConfig?.host ?? (shouldPrompt ? await promptUser.text(t("init.prompt_host"), defaultHost) : defaultHost);
|
|
79688
|
+
const portStr = portStrOpt(options.port) ?? (envConfig?.port != null ? String(envConfig.port) : null) ?? (shouldPrompt ? await promptUser.text(t("init.prompt_port"), String(defaultPort)) : String(defaultPort));
|
|
79371
79689
|
const port = parseInt(portStr, 10);
|
|
79372
79690
|
if (isNaN(port) || port < 1 || port > 65535) {
|
|
79373
79691
|
throw new Error(t_vars("errors.invalid_port", { port: portStr }));
|
|
79374
79692
|
}
|
|
79375
79693
|
connection.port = port;
|
|
79376
|
-
connection.user = options.user
|
|
79694
|
+
connection.user = strOpt(options.user) ?? envConfig?.user ?? (shouldPrompt ? await promptUser.text(t("init.prompt_user")) : "");
|
|
79377
79695
|
if (!connection.user && !shouldPrompt && !options.useEnvRefs) {
|
|
79378
79696
|
throw new Error(t("errors.require_user"));
|
|
79379
79697
|
}
|
|
79380
|
-
connection.password = options.password
|
|
79381
|
-
connection.database = options.name
|
|
79698
|
+
connection.password = strOpt(options.password) ?? envConfig?.password ?? (shouldPrompt ? await promptUser.text(t("init.prompt_password")) : "");
|
|
79699
|
+
connection.database = strOpt(options.name) ?? envConfig?.database ?? (shouldPrompt ? await promptUser.text(t("init.prompt_name")) : "");
|
|
79382
79700
|
if (!connection.database && !shouldPrompt && !options.useEnvRefs) {
|
|
79383
79701
|
throw new Error(t("errors.require_name"));
|
|
79384
79702
|
}
|
|
79385
|
-
|
|
79703
|
+
const permissionFromCli = typeof options.permission === "string" ? options.permission : undefined;
|
|
79704
|
+
let permission = permissionFromCli ?? "query-only";
|
|
79386
79705
|
if (shouldPrompt && !options.permission) {
|
|
79387
79706
|
permission = await promptUser.select(t("init.prompt_permission"), [
|
|
79388
79707
|
"query-only",
|
|
@@ -79467,7 +79786,11 @@ async function initCommandHandler(options, command) {
|
|
|
79467
79786
|
await writeV2InitConfig(configPath, connectionName, configForWrite, permission, options.envFile);
|
|
79468
79787
|
return;
|
|
79469
79788
|
}
|
|
79470
|
-
|
|
79789
|
+
const storagePath = getProjectStoragePath(configPath);
|
|
79790
|
+
await Bun.$`mkdir -p ${storagePath}`;
|
|
79791
|
+
await configModule.write(storagePath, newConfig);
|
|
79792
|
+
await migrateLegacyProjectEnvLocal(configPath, storagePath);
|
|
79793
|
+
await writeProjectBinding(configPath, storagePath);
|
|
79471
79794
|
console.log(t("init.config_saved"));
|
|
79472
79795
|
}
|
|
79473
79796
|
async function handleMongoDBInit(ctx) {
|
|
@@ -79548,7 +79871,11 @@ async function handleMongoDBInit(ctx) {
|
|
|
79548
79871
|
connection: mongoConfig,
|
|
79549
79872
|
permission
|
|
79550
79873
|
});
|
|
79551
|
-
|
|
79874
|
+
const storagePath = getProjectStoragePath(configPath);
|
|
79875
|
+
await Bun.$`mkdir -p ${storagePath}`;
|
|
79876
|
+
await configModule.write(storagePath, newConfig);
|
|
79877
|
+
await migrateLegacyProjectEnvLocal(configPath, storagePath);
|
|
79878
|
+
await writeProjectBinding(configPath, storagePath);
|
|
79552
79879
|
console.log(t("init.config_saved"));
|
|
79553
79880
|
}
|
|
79554
79881
|
|
|
@@ -79569,13 +79896,7 @@ class TableFormatter {
|
|
|
79569
79896
|
} else if (col.foreignKey) {
|
|
79570
79897
|
keyType = `FK \u2192 ${col.foreignKey.table}.${col.foreignKey.column}`;
|
|
79571
79898
|
}
|
|
79572
|
-
table.push([
|
|
79573
|
-
col.name,
|
|
79574
|
-
col.type,
|
|
79575
|
-
col.nullable ? "YES" : "NO",
|
|
79576
|
-
col.default || "NULL",
|
|
79577
|
-
keyType
|
|
79578
|
-
]);
|
|
79899
|
+
table.push([col.name, col.type, col.nullable ? "YES" : "NO", col.default || "NULL", keyType]);
|
|
79579
79900
|
});
|
|
79580
79901
|
return table.toString();
|
|
79581
79902
|
}
|
|
@@ -79891,7 +80212,7 @@ init_schema_cache();
|
|
|
79891
80212
|
|
|
79892
80213
|
// src/core/schema-writer.ts
|
|
79893
80214
|
init_schema_index();
|
|
79894
|
-
import { join as
|
|
80215
|
+
import { join as join9 } from "path";
|
|
79895
80216
|
|
|
79896
80217
|
// src/core/atomic-writer.ts
|
|
79897
80218
|
class AtomicFileWriter {
|
|
@@ -80024,7 +80345,7 @@ class SchemaWriter {
|
|
|
80024
80345
|
for (const item of mapping.hot) {
|
|
80025
80346
|
hotSchemas[item.table] = schema[item.table];
|
|
80026
80347
|
}
|
|
80027
|
-
await this.writer.writeJSON(
|
|
80348
|
+
await this.writer.writeJSON(join9(schemaRoot, "hot-schemas.json"), hotSchemas);
|
|
80028
80349
|
const coldGroups = {};
|
|
80029
80350
|
for (const item of mapping.cold) {
|
|
80030
80351
|
if (!coldGroups[item.file]) {
|
|
@@ -80032,10 +80353,10 @@ class SchemaWriter {
|
|
|
80032
80353
|
}
|
|
80033
80354
|
coldGroups[item.file][item.table] = schema[item.table];
|
|
80034
80355
|
}
|
|
80035
|
-
const coldDir =
|
|
80356
|
+
const coldDir = join9(schemaRoot, "cold");
|
|
80036
80357
|
await this.ensureDir(coldDir);
|
|
80037
80358
|
for (const [fileName, tables] of Object.entries(coldGroups)) {
|
|
80038
|
-
const filePath =
|
|
80359
|
+
const filePath = join9(schemaRoot, fileName);
|
|
80039
80360
|
await this.writer.writeJSON(filePath, tables);
|
|
80040
80361
|
}
|
|
80041
80362
|
}
|
|
@@ -80467,20 +80788,17 @@ var schemaCommand = new Command().name("schema").description("Display table sche
|
|
|
80467
80788
|
async function schemaAction(table, options) {
|
|
80468
80789
|
try {
|
|
80469
80790
|
validateFormat(options.format, ALLOWED_FORMATS2, "schema");
|
|
80791
|
+
const storagePath = await resolveConfigStoragePath(options.config);
|
|
80470
80792
|
const config = await configModule.read(options.config);
|
|
80471
80793
|
if (!config.connection) {
|
|
80472
80794
|
console.error("Database not configured. Run: dbcli init");
|
|
80473
80795
|
process.exit(1);
|
|
80474
80796
|
}
|
|
80475
|
-
if (config.connection?.system === "mongodb") {
|
|
80476
|
-
console.error("\u6B64\u547D\u4EE4\u76EE\u524D\u4E0D\u652F\u63F4 MongoDB");
|
|
80477
|
-
process.exit(1);
|
|
80478
|
-
}
|
|
80479
80797
|
const connectionName = await getSchemaIsolationConnectionName(options.config);
|
|
80480
80798
|
let existingSchemaCount;
|
|
80481
80799
|
if (connectionName !== undefined) {
|
|
80482
80800
|
try {
|
|
80483
|
-
const v2Raw = await readV2Config(
|
|
80801
|
+
const v2Raw = await readV2Config(storagePath);
|
|
80484
80802
|
existingSchemaCount = Object.keys(v2Raw.schemas?.[connectionName] ?? {}).length;
|
|
80485
80803
|
} catch {
|
|
80486
80804
|
existingSchemaCount = 0;
|
|
@@ -80492,13 +80810,13 @@ async function schemaAction(table, options) {
|
|
|
80492
80810
|
await adapter.connect();
|
|
80493
80811
|
try {
|
|
80494
80812
|
if (options.reset) {
|
|
80495
|
-
await handleSchemaReset(adapter, config, options, connectionName, existingSchemaCount);
|
|
80813
|
+
await handleSchemaReset(adapter, config, options, connectionName, existingSchemaCount, storagePath);
|
|
80496
80814
|
} else if (options.refresh) {
|
|
80497
|
-
await handleSchemaRefresh(adapter, config, options, connectionName);
|
|
80815
|
+
await handleSchemaRefresh(adapter, config, options, connectionName, storagePath);
|
|
80498
80816
|
} else if (table) {
|
|
80499
80817
|
await handleSingleTableSchema(adapter, table, options.format);
|
|
80500
80818
|
} else {
|
|
80501
|
-
await handleFullDatabaseScan(adapter, config, options, connectionName, existingSchemaCount);
|
|
80819
|
+
await handleFullDatabaseScan(adapter, config, options, connectionName, existingSchemaCount, storagePath);
|
|
80502
80820
|
}
|
|
80503
80821
|
} finally {
|
|
80504
80822
|
await adapter.disconnect();
|
|
@@ -80558,7 +80876,7 @@ Indexes:`);
|
|
|
80558
80876
|
}
|
|
80559
80877
|
}
|
|
80560
80878
|
}
|
|
80561
|
-
async function handleSchemaRefresh(adapter, config, options, connectionName) {
|
|
80879
|
+
async function handleSchemaRefresh(adapter, config, options, connectionName, storagePath) {
|
|
80562
80880
|
const diffEngine = new SchemaDiffEngine(adapter, config);
|
|
80563
80881
|
const report = await diffEngine.diff();
|
|
80564
80882
|
if (report.tablesAdded.length === 0 && report.tablesRemoved.length === 0 && Object.keys(report.tablesModified).length === 0) {
|
|
@@ -80569,7 +80887,7 @@ async function handleSchemaRefresh(adapter, config, options, connectionName) {
|
|
|
80569
80887
|
schemaTableCount: Object.keys(config.schema || {}).length
|
|
80570
80888
|
}
|
|
80571
80889
|
});
|
|
80572
|
-
await writeSchema(
|
|
80890
|
+
await writeSchema(storagePath, updatedConfig2, connectionName);
|
|
80573
80891
|
console.log("\u2705 Schema is up-to-date (no changes detected)");
|
|
80574
80892
|
return;
|
|
80575
80893
|
}
|
|
@@ -80593,16 +80911,16 @@ async function handleSchemaRefresh(adapter, config, options, connectionName) {
|
|
|
80593
80911
|
schemaTableCount: Object.keys(newSchema).length
|
|
80594
80912
|
}
|
|
80595
80913
|
});
|
|
80596
|
-
const writer = new SchemaWriter(
|
|
80914
|
+
const writer = new SchemaWriter(storagePath);
|
|
80597
80915
|
await writer.save(newSchema, connectionName);
|
|
80598
80916
|
console.log(`\u2705 Schema persisted to layered storage (.dbcli/schemas/${connectionName || ""})`);
|
|
80599
|
-
await writeSchema(
|
|
80917
|
+
await writeSchema(storagePath, updatedConfig, connectionName);
|
|
80600
80918
|
console.log(`\u2705 Schema updated in .dbcli`);
|
|
80601
80919
|
}
|
|
80602
|
-
async function handleSchemaReset(adapter, config, options, connectionName, existingCount) {
|
|
80920
|
+
async function handleSchemaReset(adapter, config, options, connectionName, existingCount, storagePath) {
|
|
80603
80921
|
if (existingCount > 0 && !options.force) {
|
|
80604
80922
|
const { SchemaLayeredLoader: SchemaLayeredLoader3 } = await Promise.resolve().then(() => (init_schema_loader(), exports_schema_loader));
|
|
80605
|
-
const loader = new SchemaLayeredLoader3(
|
|
80923
|
+
const loader = new SchemaLayeredLoader3(storagePath, { connectionName });
|
|
80606
80924
|
const { index } = await loader.initialize();
|
|
80607
80925
|
if (!index || Object.keys(index.tables).length === 0) {
|
|
80608
80926
|
console.log(`\u26A0 This will clear ${existingCount} existing table schemas and re-fetch from database.`);
|
|
@@ -80621,8 +80939,8 @@ async function handleSchemaReset(adapter, config, options, connectionName, exist
|
|
|
80621
80939
|
schema: {},
|
|
80622
80940
|
metadata: { ...config.metadata, ...emptyMeta }
|
|
80623
80941
|
};
|
|
80624
|
-
await writeSchema(
|
|
80625
|
-
const writer = new SchemaWriter(
|
|
80942
|
+
await writeSchema(storagePath, configWithoutSchema, connectionName);
|
|
80943
|
+
const writer = new SchemaWriter(storagePath);
|
|
80626
80944
|
await writer.clear(connectionName);
|
|
80627
80945
|
console.log(t("schema.scanning_database"));
|
|
80628
80946
|
const tables = await adapter.listTables();
|
|
@@ -80658,7 +80976,7 @@ async function handleSchemaReset(adapter, config, options, connectionName, exist
|
|
|
80658
80976
|
};
|
|
80659
80977
|
await writer.save(schemaData, connectionName);
|
|
80660
80978
|
console.log(`\u2705 Schema persisted to layered storage (.dbcli/schemas/${connectionName || ""})`);
|
|
80661
|
-
await writeSchema(
|
|
80979
|
+
await writeSchema(storagePath, updatedConfig, connectionName);
|
|
80662
80980
|
if (existingCount > 0) {
|
|
80663
80981
|
console.log(`
|
|
80664
80982
|
\u2705 Schema reset complete \u2014 cleared ${existingCount} old tables, fetched ${tables.length} tables from database`);
|
|
@@ -80667,7 +80985,7 @@ async function handleSchemaReset(adapter, config, options, connectionName, exist
|
|
|
80667
80985
|
\u2705 Schema fetched \u2014 ${tables.length} tables from database`);
|
|
80668
80986
|
}
|
|
80669
80987
|
}
|
|
80670
|
-
async function handleFullDatabaseScan(adapter, config, options, connectionName, existingSchemaCount) {
|
|
80988
|
+
async function handleFullDatabaseScan(adapter, config, options, connectionName, existingSchemaCount, storagePath) {
|
|
80671
80989
|
console.log(t("schema.scanning_database"));
|
|
80672
80990
|
const tables = await adapter.listTables();
|
|
80673
80991
|
console.log(t_vars("schema.tables_found", { count: tables.length }));
|
|
@@ -80693,7 +81011,7 @@ async function handleFullDatabaseScan(adapter, config, options, connectionName,
|
|
|
80693
81011
|
}
|
|
80694
81012
|
if (existingSchemaCount > 0 && !options.force) {
|
|
80695
81013
|
const { SchemaLayeredLoader: SchemaLayeredLoader3 } = await Promise.resolve().then(() => (init_schema_loader(), exports_schema_loader));
|
|
80696
|
-
const loader = new SchemaLayeredLoader3(
|
|
81014
|
+
const loader = new SchemaLayeredLoader3(storagePath, { connectionName });
|
|
80697
81015
|
const { index } = await loader.initialize();
|
|
80698
81016
|
if (!index || Object.keys(index.tables).length === 0) {
|
|
80699
81017
|
console.log(`
|
|
@@ -80717,10 +81035,10 @@ async function handleFullDatabaseScan(adapter, config, options, connectionName,
|
|
|
80717
81035
|
schemaTableCount: tables.length
|
|
80718
81036
|
}
|
|
80719
81037
|
};
|
|
80720
|
-
const writer = new SchemaWriter(
|
|
81038
|
+
const writer = new SchemaWriter(storagePath);
|
|
80721
81039
|
await writer.save(schemaData, connectionName);
|
|
80722
81040
|
console.log(`\u2705 Schema persisted to layered storage (.dbcli/schemas/${connectionName || ""})`);
|
|
80723
|
-
await writeSchema(
|
|
81041
|
+
await writeSchema(storagePath, updatedConfig, connectionName);
|
|
80724
81042
|
console.log(`
|
|
80725
81043
|
\u2705 Schema updated in .dbcli`);
|
|
80726
81044
|
console.log(` ${tables.length} tables with full column details and relationships`);
|
|
@@ -80919,12 +81237,7 @@ function determineConfidence(type, keyword, sql) {
|
|
|
80919
81237
|
if (highConfidenceTypes.includes(type)) {
|
|
80920
81238
|
return "HIGH";
|
|
80921
81239
|
}
|
|
80922
|
-
const mediumConfidenceTypes = [
|
|
80923
|
-
"CREATE",
|
|
80924
|
-
"ALTER",
|
|
80925
|
-
"DROP",
|
|
80926
|
-
"TRUNCATE"
|
|
80927
|
-
];
|
|
81240
|
+
const mediumConfidenceTypes = ["CREATE", "ALTER", "DROP", "TRUNCATE"];
|
|
80928
81241
|
if (mediumConfidenceTypes.includes(type)) {
|
|
80929
81242
|
return "MEDIUM";
|
|
80930
81243
|
}
|
|
@@ -80958,15 +81271,7 @@ function checkPermission(sql, permission) {
|
|
|
80958
81271
|
};
|
|
80959
81272
|
}
|
|
80960
81273
|
if (permission === "data-admin") {
|
|
80961
|
-
const allowedTypes = [
|
|
80962
|
-
"SELECT",
|
|
80963
|
-
"INSERT",
|
|
80964
|
-
"UPDATE",
|
|
80965
|
-
"DELETE",
|
|
80966
|
-
"SHOW",
|
|
80967
|
-
"DESCRIBE",
|
|
80968
|
-
"EXPLAIN"
|
|
80969
|
-
];
|
|
81274
|
+
const allowedTypes = ["SELECT", "INSERT", "UPDATE", "DELETE", "SHOW", "DESCRIBE", "EXPLAIN"];
|
|
80970
81275
|
if (allowedTypes.includes(classification.type)) {
|
|
80971
81276
|
return {
|
|
80972
81277
|
allowed: true,
|
|
@@ -80981,14 +81286,7 @@ function checkPermission(sql, permission) {
|
|
|
80981
81286
|
};
|
|
80982
81287
|
}
|
|
80983
81288
|
if (permission === "read-write") {
|
|
80984
|
-
const allowedTypes = [
|
|
80985
|
-
"SELECT",
|
|
80986
|
-
"INSERT",
|
|
80987
|
-
"UPDATE",
|
|
80988
|
-
"SHOW",
|
|
80989
|
-
"DESCRIBE",
|
|
80990
|
-
"EXPLAIN"
|
|
80991
|
-
];
|
|
81289
|
+
const allowedTypes = ["SELECT", "INSERT", "UPDATE", "SHOW", "DESCRIBE", "EXPLAIN"];
|
|
80992
81290
|
if (allowedTypes.includes(classification.type)) {
|
|
80993
81291
|
return {
|
|
80994
81292
|
allowed: true,
|
|
@@ -81279,7 +81577,7 @@ async function queryCommand(sql, options, command) {
|
|
|
81279
81577
|
throw new Error('Run "dbcli init" first');
|
|
81280
81578
|
}
|
|
81281
81579
|
if (config.connection.system === "mongodb") {
|
|
81282
|
-
return mongoQueryBranch(sql, options
|
|
81580
|
+
return mongoQueryBranch(sql, options, config);
|
|
81283
81581
|
}
|
|
81284
81582
|
const mainTable = extractMainTable(sql);
|
|
81285
81583
|
if (mainTable && config.schema && !options.noLimit) {
|
|
@@ -81333,10 +81631,12 @@ async function queryCommand(sql, options, command) {
|
|
|
81333
81631
|
}
|
|
81334
81632
|
function extractMainTable(sql) {
|
|
81335
81633
|
const match = sql.match(/\bFROM\s+[`"']?(\w+)[`"']?/i);
|
|
81336
|
-
return match
|
|
81634
|
+
return match?.[1] ?? null;
|
|
81337
81635
|
}
|
|
81338
81636
|
var SQL_PATTERN = /^\s*(SELECT|INSERT|UPDATE|DELETE|CREATE|DROP|ALTER|SHOW|DESCRIBE)\b/i;
|
|
81339
|
-
async function mongoQueryBranch(queryStr,
|
|
81637
|
+
async function mongoQueryBranch(queryStr, options, config) {
|
|
81638
|
+
const collection = options.collection;
|
|
81639
|
+
const format = options.format ?? "table";
|
|
81340
81640
|
if (SQL_PATTERN.test(queryStr)) {
|
|
81341
81641
|
console.error("\u9019\u662F MongoDB \u9023\u7DDA\uFF0C\u8ACB\u4F7F\u7528 JSON filter \u8A9E\u6CD5\u3002");
|
|
81342
81642
|
console.error(`\u7BC4\u4F8B\uFF1Adbcli query '{"field": "value"}' --collection <name>`);
|
|
@@ -81352,19 +81652,50 @@ async function mongoQueryBranch(queryStr, collection, config, format) {
|
|
|
81352
81652
|
console.error("MongoDB \u67E5\u8A62\u5FC5\u9808\u662F\u6709\u6548\u7684 JSON\uFF08object filter \u6216 array pipeline\uFF09");
|
|
81353
81653
|
process.exit(1);
|
|
81354
81654
|
}
|
|
81655
|
+
const blacklistManager = new BlacklistManager(config);
|
|
81656
|
+
const blacklistValidator = new BlacklistValidator(blacklistManager);
|
|
81657
|
+
try {
|
|
81658
|
+
blacklistValidator.checkTableBlacklist("SELECT", collection, []);
|
|
81659
|
+
} catch (error) {
|
|
81660
|
+
if (error instanceof BlacklistError) {
|
|
81661
|
+
console.error(error.message);
|
|
81662
|
+
process.exit(1);
|
|
81663
|
+
}
|
|
81664
|
+
throw error;
|
|
81665
|
+
}
|
|
81666
|
+
if (config.schema && !options.noLimit) {
|
|
81667
|
+
const tableSchema = config.schema[collection];
|
|
81668
|
+
if (tableSchema) {
|
|
81669
|
+
const { shouldBlockQuery: shouldBlockQuery2 } = await Promise.resolve().then(() => (init_query_size_guard(), exports_query_size_guard));
|
|
81670
|
+
const isFiltered = queryStr.length > 2;
|
|
81671
|
+
const hasLimit = options.limit !== undefined;
|
|
81672
|
+
const dummySql = `SELECT * FROM ${collection}${isFiltered ? " WHERE" : ""}${hasLimit ? " LIMIT" : ""}`;
|
|
81673
|
+
const guard = shouldBlockQuery2(dummySql, tableSchema);
|
|
81674
|
+
if (guard.blocked) {
|
|
81675
|
+
console.error(`\u26A0 ${guard.reason}`);
|
|
81676
|
+
process.exit(1);
|
|
81677
|
+
}
|
|
81678
|
+
}
|
|
81679
|
+
}
|
|
81355
81680
|
const mongoAdapter = AdapterFactory.createMongoDBAdapter(config.connection);
|
|
81356
81681
|
await mongoAdapter.connect();
|
|
81357
81682
|
try {
|
|
81358
81683
|
const result = await mongoAdapter.execute(queryStr, [collection]);
|
|
81359
|
-
const columnNames = result.rows
|
|
81684
|
+
const columnNames = result.rows[0] ? Object.keys(result.rows[0]) : [];
|
|
81685
|
+
const filterResult = blacklistValidator.filterColumns(collection, result.rows, columnNames);
|
|
81360
81686
|
const queryResult = {
|
|
81361
|
-
rows:
|
|
81362
|
-
rowCount:
|
|
81363
|
-
columnNames
|
|
81687
|
+
rows: filterResult.filteredRows,
|
|
81688
|
+
rowCount: filterResult.filteredRows.length,
|
|
81689
|
+
columnNames: columnNames.filter((col) => !filterResult.omittedColumns.includes(col))
|
|
81364
81690
|
};
|
|
81365
81691
|
const formatter = new QueryResultFormatter;
|
|
81366
81692
|
const output = formatter.format(queryResult, { format });
|
|
81693
|
+
const securityNote = blacklistValidator.buildSecurityNotification(collection, filterResult.omittedColumns);
|
|
81367
81694
|
console.log(output);
|
|
81695
|
+
if (securityNote) {
|
|
81696
|
+
console.log(`
|
|
81697
|
+
\u2139 ${securityNote}`);
|
|
81698
|
+
}
|
|
81368
81699
|
} finally {
|
|
81369
81700
|
await mongoAdapter.disconnect();
|
|
81370
81701
|
}
|
|
@@ -81702,8 +82033,23 @@ async function insertCommand(table, options, command) {
|
|
|
81702
82033
|
throw new Error('Run "dbcli init" to configure database connection');
|
|
81703
82034
|
}
|
|
81704
82035
|
if (config.connection.system === "mongodb") {
|
|
81705
|
-
|
|
81706
|
-
|
|
82036
|
+
enforcePermission("INSERT INTO dummy", config.permission);
|
|
82037
|
+
const adapter2 = AdapterFactory.createMongoDBAdapter(config.connection);
|
|
82038
|
+
await adapter2.connect();
|
|
82039
|
+
try {
|
|
82040
|
+
const result = await adapter2.insert(table, data);
|
|
82041
|
+
const output = {
|
|
82042
|
+
status: "success",
|
|
82043
|
+
operation: "insert",
|
|
82044
|
+
rows_affected: result.affectedRows,
|
|
82045
|
+
timestamp: new Date().toISOString(),
|
|
82046
|
+
lastInsertId: result.lastInsertId
|
|
82047
|
+
};
|
|
82048
|
+
console.log(JSON.stringify(output, null, 2));
|
|
82049
|
+
return;
|
|
82050
|
+
} finally {
|
|
82051
|
+
await adapter2.disconnect();
|
|
82052
|
+
}
|
|
81707
82053
|
}
|
|
81708
82054
|
const adapter = AdapterFactory.createAdapter(config.connection);
|
|
81709
82055
|
await adapter.connect();
|
|
@@ -81776,7 +82122,11 @@ function parseWhereClause(whereClause) {
|
|
|
81776
82122
|
if (!match) {
|
|
81777
82123
|
throw new Error(`Cannot parse WHERE clause: "${part}". Use format "column=value" or "col1=val1 AND col2=val2"`);
|
|
81778
82124
|
}
|
|
81779
|
-
const
|
|
82125
|
+
const column = match[1];
|
|
82126
|
+
const valueStr = match[2];
|
|
82127
|
+
if (valueStr === undefined || column === undefined) {
|
|
82128
|
+
throw new Error(`Cannot parse WHERE clause: "${part}". Use format "column=value" or "col1=val1 AND col2=val2"`);
|
|
82129
|
+
}
|
|
81780
82130
|
let value = valueStr.trim();
|
|
81781
82131
|
if (value.startsWith("'") && value.endsWith("'") || value.startsWith('"') && value.endsWith('"')) {
|
|
81782
82132
|
value = value.slice(1, -1);
|
|
@@ -81806,11 +82156,10 @@ async function updateCommand(table, options, command) {
|
|
|
81806
82156
|
if (!options.set || options.set.trim() === "") {
|
|
81807
82157
|
throw new Error(`UPDATE requires --set flag with JSON data (e.g. --set '{"name":"Bob"}')`);
|
|
81808
82158
|
}
|
|
81809
|
-
|
|
81810
|
-
|
|
81811
|
-
|
|
81812
|
-
|
|
81813
|
-
throw new Error(`WHERE clause parsing failed: ${error.message}`);
|
|
82159
|
+
const configPath = resolveConfigPath(command, options);
|
|
82160
|
+
const config = await configModule.read(configPath);
|
|
82161
|
+
if (!config.connection) {
|
|
82162
|
+
throw new Error('Run "dbcli init" to configure database connection');
|
|
81814
82163
|
}
|
|
81815
82164
|
let setData;
|
|
81816
82165
|
try {
|
|
@@ -81821,14 +82170,36 @@ async function updateCommand(table, options, command) {
|
|
|
81821
82170
|
if (!setData || typeof setData !== "object" || Array.isArray(setData)) {
|
|
81822
82171
|
throw new Error('JSON in --set must be an object (e.g. {"name":"Bob","email":"b@example.com"})');
|
|
81823
82172
|
}
|
|
81824
|
-
const configPath = resolveConfigPath(command, options);
|
|
81825
|
-
const config = await configModule.read(configPath);
|
|
81826
|
-
if (!config.connection) {
|
|
81827
|
-
throw new Error('Run "dbcli init" to configure database connection');
|
|
81828
|
-
}
|
|
81829
82173
|
if (config.connection?.system === "mongodb") {
|
|
81830
|
-
|
|
81831
|
-
|
|
82174
|
+
enforcePermission("UPDATE dummy", config.permission);
|
|
82175
|
+
const adapter2 = AdapterFactory.createMongoDBAdapter(config.connection);
|
|
82176
|
+
await adapter2.connect();
|
|
82177
|
+
try {
|
|
82178
|
+
let filter;
|
|
82179
|
+
try {
|
|
82180
|
+
filter = JSON.parse(options.where);
|
|
82181
|
+
} catch {
|
|
82182
|
+
filter = parseWhereClause(options.where);
|
|
82183
|
+
}
|
|
82184
|
+
const updateDoc = Object.keys(setData).some((key2) => key2.startsWith("$")) ? setData : { $set: setData };
|
|
82185
|
+
const result = await adapter2.update(table, filter, updateDoc);
|
|
82186
|
+
const output = {
|
|
82187
|
+
status: "success",
|
|
82188
|
+
operation: "update",
|
|
82189
|
+
rows_affected: result.affectedRows,
|
|
82190
|
+
timestamp: new Date().toISOString()
|
|
82191
|
+
};
|
|
82192
|
+
console.log(JSON.stringify(output, null, 2));
|
|
82193
|
+
return;
|
|
82194
|
+
} finally {
|
|
82195
|
+
await adapter2.disconnect();
|
|
82196
|
+
}
|
|
82197
|
+
}
|
|
82198
|
+
let whereConditions;
|
|
82199
|
+
try {
|
|
82200
|
+
whereConditions = parseWhereClause(options.where);
|
|
82201
|
+
} catch (error) {
|
|
82202
|
+
throw new Error(`WHERE clause parsing failed: ${error.message}`);
|
|
81832
82203
|
}
|
|
81833
82204
|
const adapter = AdapterFactory.createAdapter(config.connection);
|
|
81834
82205
|
await adapter.connect();
|
|
@@ -81929,23 +82300,48 @@ async function deleteCommand(table, options, command) {
|
|
|
81929
82300
|
if (!options.where || options.where.trim() === "") {
|
|
81930
82301
|
throw new Error('DELETE requires --where clause (e.g. --where "id=1")');
|
|
81931
82302
|
}
|
|
81932
|
-
let whereConditions;
|
|
81933
|
-
try {
|
|
81934
|
-
whereConditions = parseWhereClause2(options.where);
|
|
81935
|
-
} catch (error) {
|
|
81936
|
-
throw new Error(`WHERE clause parsing failed: ${error.message}`);
|
|
81937
|
-
}
|
|
81938
82303
|
const configPath = resolveConfigPath(command, options);
|
|
81939
82304
|
const config = await configModule.read(configPath);
|
|
81940
82305
|
if (!config.connection) {
|
|
81941
82306
|
throw new Error('Run "dbcli init" to configure database connection');
|
|
81942
82307
|
}
|
|
82308
|
+
if (config.permission !== "data-admin" && config.permission !== "admin") {
|
|
82309
|
+
throw new PermissionError(t("delete.admin_only"), {
|
|
82310
|
+
type: "DELETE",
|
|
82311
|
+
isDangerous: true,
|
|
82312
|
+
keywords: ["DELETE"],
|
|
82313
|
+
isComposite: false,
|
|
82314
|
+
confidence: "HIGH"
|
|
82315
|
+
}, config.permission);
|
|
82316
|
+
}
|
|
81943
82317
|
if (config.connection?.system === "mongodb") {
|
|
81944
|
-
|
|
81945
|
-
|
|
82318
|
+
const adapter2 = AdapterFactory.createMongoDBAdapter(config.connection);
|
|
82319
|
+
await adapter2.connect();
|
|
82320
|
+
try {
|
|
82321
|
+
let filter;
|
|
82322
|
+
try {
|
|
82323
|
+
filter = JSON.parse(options.where);
|
|
82324
|
+
} catch {
|
|
82325
|
+
filter = parseWhereClause2(options.where);
|
|
82326
|
+
}
|
|
82327
|
+
const result = await adapter2.delete(table, filter);
|
|
82328
|
+
const output = {
|
|
82329
|
+
status: "success",
|
|
82330
|
+
operation: "delete",
|
|
82331
|
+
rows_affected: result.affectedRows,
|
|
82332
|
+
timestamp: new Date().toISOString()
|
|
82333
|
+
};
|
|
82334
|
+
console.log(JSON.stringify(output, null, 2));
|
|
82335
|
+
return;
|
|
82336
|
+
} finally {
|
|
82337
|
+
await adapter2.disconnect();
|
|
82338
|
+
}
|
|
81946
82339
|
}
|
|
81947
|
-
|
|
81948
|
-
|
|
82340
|
+
let whereConditions;
|
|
82341
|
+
try {
|
|
82342
|
+
whereConditions = parseWhereClause2(options.where);
|
|
82343
|
+
} catch (error) {
|
|
82344
|
+
throw new Error(`WHERE clause parsing failed: ${error.message}`);
|
|
81949
82345
|
}
|
|
81950
82346
|
const adapter = AdapterFactory.createAdapter(config.connection);
|
|
81951
82347
|
await adapter.connect();
|
|
@@ -82073,7 +82469,7 @@ async function exportCommand(sql, options, command) {
|
|
|
82073
82469
|
// src/commands/skill.ts
|
|
82074
82470
|
var {$ } = globalThis.Bun;
|
|
82075
82471
|
import * as path from "path";
|
|
82076
|
-
import { homedir } from "os";
|
|
82472
|
+
import { homedir as homedir2 } from "os";
|
|
82077
82473
|
function findPackageRoot() {
|
|
82078
82474
|
let dir = import.meta.dir;
|
|
82079
82475
|
for (let i = 0;i < 5; i++) {
|
|
@@ -82085,6 +82481,7 @@ function findPackageRoot() {
|
|
|
82085
82481
|
return path.resolve(import.meta.dir, "../..");
|
|
82086
82482
|
}
|
|
82087
82483
|
var SKILL_SOURCE_PATH = path.join(findPackageRoot(), "assets", "SKILL.md");
|
|
82484
|
+
var REFERENCE_SOURCE_PATH = path.join(findPackageRoot(), "assets", "reference.md");
|
|
82088
82485
|
var SUPPORTED_PLATFORMS = ["claude", "gemini", "copilot", "cursor"];
|
|
82089
82486
|
async function skillCommand(_program, options) {
|
|
82090
82487
|
try {
|
|
@@ -82092,7 +82489,12 @@ async function skillCommand(_program, options) {
|
|
|
82092
82489
|
if (!await skillFile.exists()) {
|
|
82093
82490
|
throw new Error(`Skill source not found: ${SKILL_SOURCE_PATH}`);
|
|
82094
82491
|
}
|
|
82492
|
+
const refFile = Bun.file(REFERENCE_SOURCE_PATH);
|
|
82493
|
+
if (!await refFile.exists()) {
|
|
82494
|
+
throw new Error(`Skill reference not found: ${REFERENCE_SOURCE_PATH}`);
|
|
82495
|
+
}
|
|
82095
82496
|
const skillMarkdown = await skillFile.text();
|
|
82497
|
+
const referenceMarkdown = await refFile.text();
|
|
82096
82498
|
if (options.output) {
|
|
82097
82499
|
await Bun.file(options.output).write(skillMarkdown);
|
|
82098
82500
|
console.error(`Skill written to ${options.output}`);
|
|
@@ -82100,9 +82502,8 @@ async function skillCommand(_program, options) {
|
|
|
82100
82502
|
}
|
|
82101
82503
|
if (options.install) {
|
|
82102
82504
|
const installPath = getInstallPath(options.install);
|
|
82103
|
-
await
|
|
82104
|
-
|
|
82105
|
-
console.error(t_vars("skill.installed", { path: installPath }));
|
|
82505
|
+
const { referencePath } = await writeSkillInstall(options.install, installPath, skillMarkdown, referenceMarkdown);
|
|
82506
|
+
console.error(t_vars("skill.installed", { path: installPath, referencePath: referencePath ?? "" }));
|
|
82106
82507
|
return;
|
|
82107
82508
|
}
|
|
82108
82509
|
console.log(skillMarkdown);
|
|
@@ -82135,7 +82536,7 @@ async function checkSkillUpdates() {
|
|
|
82135
82536
|
return outdated;
|
|
82136
82537
|
}
|
|
82137
82538
|
function getInstallPath(platform) {
|
|
82138
|
-
const home = process.env.HOME ||
|
|
82539
|
+
const home = process.env.HOME || homedir2();
|
|
82139
82540
|
const platformLower = platform.toLowerCase();
|
|
82140
82541
|
switch (platformLower) {
|
|
82141
82542
|
case "claude":
|
|
@@ -82150,6 +82551,20 @@ function getInstallPath(platform) {
|
|
|
82150
82551
|
throw new Error(`Unknown platform: ${platform}. Supported platforms: ${SUPPORTED_PLATFORMS.join(", ")}`);
|
|
82151
82552
|
}
|
|
82152
82553
|
}
|
|
82554
|
+
async function writeSkillInstall(platform, installPath, skillMarkdown, referenceMarkdown) {
|
|
82555
|
+
const platformLower = platform.toLowerCase();
|
|
82556
|
+
await ensureDir(path.dirname(installPath));
|
|
82557
|
+
await Bun.file(installPath).write(skillMarkdown);
|
|
82558
|
+
if (platformLower === "cursor") {
|
|
82559
|
+
const refPath2 = path.join(process.cwd(), ".cursor", "skills", "dbcli", "reference.md");
|
|
82560
|
+
await ensureDir(path.dirname(refPath2));
|
|
82561
|
+
await Bun.file(refPath2).write(referenceMarkdown);
|
|
82562
|
+
return { referencePath: refPath2 };
|
|
82563
|
+
}
|
|
82564
|
+
const refPath = path.join(path.dirname(installPath), "reference.md");
|
|
82565
|
+
await Bun.file(refPath).write(referenceMarkdown);
|
|
82566
|
+
return { referencePath: refPath };
|
|
82567
|
+
}
|
|
82153
82568
|
async function ensureDir(dirPath) {
|
|
82154
82569
|
try {
|
|
82155
82570
|
await $`mkdir -p ${dirPath}`.quiet();
|
|
@@ -82242,7 +82657,7 @@ async function blacklistTableRemove(tableName, configPath) {
|
|
|
82242
82657
|
}
|
|
82243
82658
|
const newBlacklist = {
|
|
82244
82659
|
...blacklist,
|
|
82245
|
-
tables: blacklist.tables.filter((
|
|
82660
|
+
tables: blacklist.tables.filter((t6) => t6 !== tableName)
|
|
82246
82661
|
};
|
|
82247
82662
|
await configModule.write(configPath, { ...config, blacklist: newBlacklist });
|
|
82248
82663
|
console.log(t_vars("blacklist.table_removed", { table: tableName }));
|
|
@@ -82377,21 +82792,21 @@ async function checkAction(table, options) {
|
|
|
82377
82792
|
const tables = await adapter.listTables();
|
|
82378
82793
|
const reports = [];
|
|
82379
82794
|
const skipped = [];
|
|
82380
|
-
for (const
|
|
82381
|
-
if (blacklistedTables.has(
|
|
82382
|
-
skipped.push(`${
|
|
82795
|
+
for (const t6 of tables) {
|
|
82796
|
+
if (blacklistedTables.has(t6.name.toLowerCase())) {
|
|
82797
|
+
skipped.push(`${t6.name} (blacklisted)`);
|
|
82383
82798
|
continue;
|
|
82384
82799
|
}
|
|
82385
|
-
if (
|
|
82386
|
-
skipped.push(`${
|
|
82800
|
+
if (t6.tableType === "view") {
|
|
82801
|
+
skipped.push(`${t6.name} (view)`);
|
|
82387
82802
|
continue;
|
|
82388
82803
|
}
|
|
82389
|
-
const category = getSizeCategory(
|
|
82804
|
+
const category = getSizeCategory(t6.estimatedRowCount);
|
|
82390
82805
|
if (category === "huge" && !options.includeLarge) {
|
|
82391
|
-
skipped.push(`${
|
|
82806
|
+
skipped.push(`${t6.name} (~${(t6.estimatedRowCount || 0).toLocaleString()} rows, huge)`);
|
|
82392
82807
|
continue;
|
|
82393
82808
|
}
|
|
82394
|
-
const schema = await adapter.getTableSchema(
|
|
82809
|
+
const schema = await adapter.getTableSchema(t6.name);
|
|
82395
82810
|
const report = await checker.check(schema, {
|
|
82396
82811
|
checks: checkTypes,
|
|
82397
82812
|
sample: sampleSize,
|
|
@@ -82475,31 +82890,49 @@ var ALLOWED_FORMATS5 = ["json", "table"];
|
|
|
82475
82890
|
function compareSnapshots(before, after) {
|
|
82476
82891
|
const beforeTables = new Set(Object.keys(before.tables));
|
|
82477
82892
|
const afterTables = new Set(Object.keys(after.tables));
|
|
82478
|
-
const addedTables = Array.from(afterTables).filter((
|
|
82479
|
-
const removedTables = Array.from(beforeTables).filter((
|
|
82893
|
+
const addedTables = Array.from(afterTables).filter((t6) => !beforeTables.has(t6));
|
|
82894
|
+
const removedTables = Array.from(beforeTables).filter((t6) => !afterTables.has(t6));
|
|
82480
82895
|
const addedColumns = [];
|
|
82481
82896
|
const removedColumns = [];
|
|
82482
82897
|
const modifiedColumns = [];
|
|
82483
82898
|
const indexChanges = [];
|
|
82484
82899
|
for (const tableName of addedTables) {
|
|
82485
|
-
|
|
82486
|
-
|
|
82900
|
+
const added = after.tables[tableName];
|
|
82901
|
+
if (!added)
|
|
82902
|
+
continue;
|
|
82903
|
+
for (const col of added.columns) {
|
|
82904
|
+
addedColumns.push({
|
|
82905
|
+
table: tableName,
|
|
82906
|
+
column: col.name,
|
|
82907
|
+
type: col.type,
|
|
82908
|
+
nullable: col.nullable
|
|
82909
|
+
});
|
|
82487
82910
|
}
|
|
82488
82911
|
}
|
|
82489
82912
|
for (const tableName of removedTables) {
|
|
82490
|
-
|
|
82913
|
+
const removed = before.tables[tableName];
|
|
82914
|
+
if (!removed)
|
|
82915
|
+
continue;
|
|
82916
|
+
for (const col of removed.columns) {
|
|
82491
82917
|
removedColumns.push({ table: tableName, column: col.name, type: col.type });
|
|
82492
82918
|
}
|
|
82493
82919
|
}
|
|
82494
|
-
const commonTables = Array.from(afterTables).filter((
|
|
82920
|
+
const commonTables = Array.from(afterTables).filter((t6) => beforeTables.has(t6));
|
|
82495
82921
|
for (const tableName of commonTables) {
|
|
82496
82922
|
const beforeTable = before.tables[tableName];
|
|
82497
82923
|
const afterTable = after.tables[tableName];
|
|
82924
|
+
if (!beforeTable || !afterTable)
|
|
82925
|
+
continue;
|
|
82498
82926
|
const beforeColMap = new Map(beforeTable.columns.map((c) => [c.name, c]));
|
|
82499
82927
|
const afterColMap = new Map(afterTable.columns.map((c) => [c.name, c]));
|
|
82500
82928
|
for (const [name, col] of afterColMap) {
|
|
82501
82929
|
if (!beforeColMap.has(name)) {
|
|
82502
|
-
addedColumns.push({
|
|
82930
|
+
addedColumns.push({
|
|
82931
|
+
table: tableName,
|
|
82932
|
+
column: name,
|
|
82933
|
+
type: col.type,
|
|
82934
|
+
nullable: col.nullable
|
|
82935
|
+
});
|
|
82503
82936
|
}
|
|
82504
82937
|
}
|
|
82505
82938
|
for (const [name, col] of beforeColMap) {
|
|
@@ -82569,11 +83002,11 @@ async function diffAction(options) {
|
|
|
82569
83002
|
tables: {},
|
|
82570
83003
|
createdAt: new Date().toISOString()
|
|
82571
83004
|
};
|
|
82572
|
-
for (const
|
|
82573
|
-
if (
|
|
83005
|
+
for (const t6 of tables) {
|
|
83006
|
+
if (t6.tableType === "view")
|
|
82574
83007
|
continue;
|
|
82575
|
-
const schema = await adapter.getTableSchema(
|
|
82576
|
-
currentSnapshot.tables[
|
|
83008
|
+
const schema = await adapter.getTableSchema(t6.name);
|
|
83009
|
+
currentSnapshot.tables[t6.name] = {
|
|
82577
83010
|
name: schema.name,
|
|
82578
83011
|
columns: schema.columns,
|
|
82579
83012
|
indexes: schema.indexes || []
|
|
@@ -82686,7 +83119,8 @@ var statusCommand = new Command("status").description("Show current configuratio
|
|
|
82686
83119
|
// src/commands/doctor.ts
|
|
82687
83120
|
init_validation();
|
|
82688
83121
|
init_schema_path();
|
|
82689
|
-
import { join as
|
|
83122
|
+
import { join as join11 } from "path";
|
|
83123
|
+
import { resolveSrv as resolveSrv2 } from "dns/promises";
|
|
82690
83124
|
var ALLOWED_FORMATS7 = ["text", "json"];
|
|
82691
83125
|
var SENSITIVE_PATTERNS = [
|
|
82692
83126
|
"password",
|
|
@@ -82735,7 +83169,9 @@ var runDoctorChecks = {
|
|
|
82735
83169
|
},
|
|
82736
83170
|
async checkLatestVersion(currentVersion) {
|
|
82737
83171
|
try {
|
|
82738
|
-
const response = await fetch("https://registry.npmjs.org/@carllee1983/dbcli/latest", {
|
|
83172
|
+
const response = await fetch("https://registry.npmjs.org/@carllee1983/dbcli/latest", {
|
|
83173
|
+
signal: AbortSignal.timeout(5000)
|
|
83174
|
+
});
|
|
82739
83175
|
if (!response.ok)
|
|
82740
83176
|
throw new Error(`HTTP ${response.status}`);
|
|
82741
83177
|
const data = await response.json();
|
|
@@ -82757,7 +83193,7 @@ var runDoctorChecks = {
|
|
|
82757
83193
|
}
|
|
82758
83194
|
},
|
|
82759
83195
|
async checkConfigExists(configPath, existsFn) {
|
|
82760
|
-
const exists = existsFn ? await existsFn(configPath) : await Bun.file(configPath).exists() || await Bun.file(
|
|
83196
|
+
const exists = existsFn ? await existsFn(configPath) : await Bun.file(configPath).exists() || await Bun.file(join11(configPath, "config.json")).exists();
|
|
82761
83197
|
return {
|
|
82762
83198
|
group: "Configuration",
|
|
82763
83199
|
label: "Config exists",
|
|
@@ -82831,8 +83267,70 @@ var runDoctorChecks = {
|
|
|
82831
83267
|
message: versionResult.supported ? t_vars("version.doctor_pass", vars) : t_vars("version.doctor_warn", vars)
|
|
82832
83268
|
};
|
|
82833
83269
|
},
|
|
83270
|
+
async checkMongoSrvConnectivity(uri, deps = {}) {
|
|
83271
|
+
if (!uri || !uri.startsWith("mongodb+srv://")) {
|
|
83272
|
+
return null;
|
|
83273
|
+
}
|
|
83274
|
+
const url = new URL(uri);
|
|
83275
|
+
const srvName = `_mongodb._tcp.${url.hostname}`;
|
|
83276
|
+
const resolveSrvFn = deps.resolveSrvFn ?? resolveSrv2;
|
|
83277
|
+
const fetchFn = deps.fetchFn ?? fetch;
|
|
83278
|
+
try {
|
|
83279
|
+
const records = await resolveSrvFn(srvName);
|
|
83280
|
+
if (!records.length) {
|
|
83281
|
+
return {
|
|
83282
|
+
group: "Environment",
|
|
83283
|
+
label: "MongoDB SRV lookup",
|
|
83284
|
+
status: "error",
|
|
83285
|
+
message: `No SRV records found for ${url.hostname}`
|
|
83286
|
+
};
|
|
83287
|
+
}
|
|
83288
|
+
return {
|
|
83289
|
+
group: "Environment",
|
|
83290
|
+
label: "MongoDB SRV lookup",
|
|
83291
|
+
status: "pass",
|
|
83292
|
+
message: `MongoDB SRV lookup reachable for ${url.hostname} (${records.length} record(s))`
|
|
83293
|
+
};
|
|
83294
|
+
} catch (error) {
|
|
83295
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
83296
|
+
const code = error?.code;
|
|
83297
|
+
const isExecutionEnvIssue = code === "ECONNREFUSED" || code === "ETIMEDOUT" || message.includes("Unable to connect. Is the computer able to access the url?") || message.includes("ConnectionRefused");
|
|
83298
|
+
if (!isExecutionEnvIssue) {
|
|
83299
|
+
return {
|
|
83300
|
+
group: "Environment",
|
|
83301
|
+
label: "MongoDB SRV lookup",
|
|
83302
|
+
status: "error",
|
|
83303
|
+
message: `MongoDB SRV lookup failed for ${url.hostname}: ${message}`
|
|
83304
|
+
};
|
|
83305
|
+
}
|
|
83306
|
+
try {
|
|
83307
|
+
const response = await fetchFn(`https://dns.google/resolve?name=${encodeURIComponent(srvName)}&type=SRV`, { signal: AbortSignal.timeout(5000) });
|
|
83308
|
+
if (!response.ok) {
|
|
83309
|
+
throw new Error(`HTTP ${response.status}`);
|
|
83310
|
+
}
|
|
83311
|
+
const payload = await response.json();
|
|
83312
|
+
if (payload.Status !== 0 || !payload.Answer?.length) {
|
|
83313
|
+
throw new Error(payload.Comment || `No SRV records found for ${url.hostname}`);
|
|
83314
|
+
}
|
|
83315
|
+
return {
|
|
83316
|
+
group: "Environment",
|
|
83317
|
+
label: "MongoDB SRV lookup",
|
|
83318
|
+
status: "warn",
|
|
83319
|
+
message: `Direct SRV DNS lookup failed in this shell, but DNS-over-HTTPS fallback resolved ` + `${url.hostname}. dbcli can still connect here, but this runtime environment cannot perform direct SRV lookups.`
|
|
83320
|
+
};
|
|
83321
|
+
} catch (fallbackError) {
|
|
83322
|
+
const fallbackMessage = fallbackError instanceof Error ? fallbackError.message : String(fallbackError);
|
|
83323
|
+
return {
|
|
83324
|
+
group: "Environment",
|
|
83325
|
+
label: "MongoDB SRV lookup",
|
|
83326
|
+
status: "error",
|
|
83327
|
+
message: `MongoDB SRV lookup failed in this environment (${code || "unknown"}); ` + `DNS-over-HTTPS fallback also failed: ${fallbackMessage}`
|
|
83328
|
+
};
|
|
83329
|
+
}
|
|
83330
|
+
}
|
|
83331
|
+
},
|
|
82834
83332
|
checkLargeTables(tables) {
|
|
82835
|
-
const large = tables.filter((
|
|
83333
|
+
const large = tables.filter((t6) => (t6.estimatedRowCount ?? 0) > 1e6);
|
|
82836
83334
|
if (large.length === 0) {
|
|
82837
83335
|
return {
|
|
82838
83336
|
group: "Connection & Data",
|
|
@@ -82841,7 +83339,7 @@ var runDoctorChecks = {
|
|
|
82841
83339
|
message: "No tables exceed 1M rows"
|
|
82842
83340
|
};
|
|
82843
83341
|
}
|
|
82844
|
-
const list = large.map((
|
|
83342
|
+
const list = large.map((t6) => `${t6.name} (${((t6.estimatedRowCount ?? 0) / 1e6).toFixed(1)}M rows)`).join(", ");
|
|
82845
83343
|
return {
|
|
82846
83344
|
group: "Connection & Data",
|
|
82847
83345
|
label: "Large tables",
|
|
@@ -82851,7 +83349,8 @@ var runDoctorChecks = {
|
|
|
82851
83349
|
},
|
|
82852
83350
|
async checkV2Config(configPath) {
|
|
82853
83351
|
const results = [];
|
|
82854
|
-
const
|
|
83352
|
+
const storagePath = await resolveConfigStoragePath(configPath);
|
|
83353
|
+
const configFile = Bun.file(join11(storagePath, "config.json"));
|
|
82855
83354
|
if (!await configFile.exists())
|
|
82856
83355
|
return results;
|
|
82857
83356
|
let raw;
|
|
@@ -82891,7 +83390,7 @@ var runDoctorChecks = {
|
|
|
82891
83390
|
}
|
|
82892
83391
|
for (const [name, conn] of Object.entries(config.connections)) {
|
|
82893
83392
|
if (conn.envFile) {
|
|
82894
|
-
const envPath =
|
|
83393
|
+
const envPath = join11(storagePath, conn.envFile);
|
|
82895
83394
|
const exists = await Bun.file(envPath).exists();
|
|
82896
83395
|
results.push({
|
|
82897
83396
|
group: "Configuration",
|
|
@@ -82927,9 +83426,18 @@ var runDoctorChecks = {
|
|
|
82927
83426
|
};
|
|
82928
83427
|
async function collectMongoDoctorResults(config) {
|
|
82929
83428
|
const results = [];
|
|
83429
|
+
const mongoConn = config.connection.system === "mongodb" ? config.connection : null;
|
|
83430
|
+
const mongoUriString = mongoConn && typeof mongoConn.uri === "string" ? mongoConn.uri : undefined;
|
|
83431
|
+
const srvCheck = await runDoctorChecks.checkMongoSrvConnectivity(mongoUriString);
|
|
83432
|
+
if (srvCheck) {
|
|
83433
|
+
results.push(srvCheck);
|
|
83434
|
+
if (srvCheck.status === "error") {
|
|
83435
|
+
return results;
|
|
83436
|
+
}
|
|
83437
|
+
}
|
|
82930
83438
|
const adapter = AdapterFactory.createMongoDBAdapter(config.connection);
|
|
82931
|
-
await adapter.connect();
|
|
82932
83439
|
try {
|
|
83440
|
+
await adapter.connect();
|
|
82933
83441
|
results.push({
|
|
82934
83442
|
group: "Connection & Data",
|
|
82935
83443
|
label: "Connection",
|
|
@@ -82945,10 +83453,20 @@ async function collectMongoDoctorResults(config) {
|
|
|
82945
83453
|
message: `MongoDB ${version}`
|
|
82946
83454
|
});
|
|
82947
83455
|
} catch {}
|
|
82948
|
-
const collections = await adapter.
|
|
82949
|
-
|
|
82950
|
-
|
|
82951
|
-
|
|
83456
|
+
const collections = await adapter.listTables();
|
|
83457
|
+
const tableColumns = new Map;
|
|
83458
|
+
for (const coll of collections) {
|
|
83459
|
+
try {
|
|
83460
|
+
const schema = await adapter.getTableSchema(coll.name);
|
|
83461
|
+
tableColumns.set(coll.name, schema.columns.map((c) => c.name));
|
|
83462
|
+
} catch {}
|
|
83463
|
+
}
|
|
83464
|
+
if (config.blacklistedColumns) {
|
|
83465
|
+
results.push(runDoctorChecks.checkBlacklistCompleteness(tableColumns, config.blacklistedColumns));
|
|
83466
|
+
}
|
|
83467
|
+
results.push(runDoctorChecks.checkLargeTables(collections.map((coll) => ({
|
|
83468
|
+
name: coll.name,
|
|
83469
|
+
estimatedRowCount: coll.estimatedRowCount
|
|
82952
83470
|
}))));
|
|
82953
83471
|
results.push({
|
|
82954
83472
|
group: "Connection & Data",
|
|
@@ -82956,11 +83474,18 @@ async function collectMongoDoctorResults(config) {
|
|
|
82956
83474
|
status: "pass",
|
|
82957
83475
|
message: collections.length === 0 ? "No collections found" : `Found ${collections.length} collection(s)`
|
|
82958
83476
|
});
|
|
83477
|
+
const lastUpdated = config.metadata?.schemaLastUpdated ?? null;
|
|
83478
|
+
const freshness = runDoctorChecks.checkSchemaCacheFreshness(lastUpdated);
|
|
83479
|
+
if (!lastUpdated) {
|
|
83480
|
+
freshness.message = 'Schema cache is not tracked for MongoDB \u2014 run "dbcli schema --refresh" to scan collections';
|
|
83481
|
+
}
|
|
83482
|
+
results.push(freshness);
|
|
83483
|
+
} catch (error) {
|
|
82959
83484
|
results.push({
|
|
82960
83485
|
group: "Connection & Data",
|
|
82961
|
-
label: "
|
|
82962
|
-
status: "
|
|
82963
|
-
message:
|
|
83486
|
+
label: "Connection",
|
|
83487
|
+
status: "error",
|
|
83488
|
+
message: `Connection failed: ${error.message}`
|
|
82964
83489
|
});
|
|
82965
83490
|
} finally {
|
|
82966
83491
|
await adapter.disconnect();
|
|
@@ -82972,11 +83497,12 @@ var doctorCommand = new Command("doctor").description("Run diagnostic checks on
|
|
|
82972
83497
|
const logger = getLogger();
|
|
82973
83498
|
const results = [];
|
|
82974
83499
|
const configPath = resolveConfigPath(doctorCommand);
|
|
83500
|
+
const storagePath = await resolveConfigStoragePath(configPath);
|
|
82975
83501
|
const bunVersion = process.versions.bun ?? "unknown";
|
|
82976
83502
|
const requiredBun = package_default.engines?.bun?.replace(">=", "") ?? "1.3.3";
|
|
82977
83503
|
results.push(runDoctorChecks.checkBunVersion(bunVersion, requiredBun));
|
|
82978
83504
|
results.push(await runDoctorChecks.checkLatestVersion(package_default.version));
|
|
82979
|
-
const configExists = await runDoctorChecks.checkConfigExists(
|
|
83505
|
+
const configExists = await runDoctorChecks.checkConfigExists(storagePath);
|
|
82980
83506
|
results.push(configExists);
|
|
82981
83507
|
if (configExists.status !== "error") {
|
|
82982
83508
|
try {
|
|
@@ -83003,7 +83529,10 @@ var doctorCommand = new Command("doctor").description("Run diagnostic checks on
|
|
|
83003
83529
|
}
|
|
83004
83530
|
try {
|
|
83005
83531
|
if (config.connection.system === "mongodb") {
|
|
83006
|
-
results.push(...await collectMongoDoctorResults(
|
|
83532
|
+
results.push(...await collectMongoDoctorResults({
|
|
83533
|
+
...config,
|
|
83534
|
+
blacklistedColumns
|
|
83535
|
+
}));
|
|
83007
83536
|
} else {
|
|
83008
83537
|
const adapter = AdapterFactory.createAdapter(config.connection);
|
|
83009
83538
|
await adapter.connect();
|
|
@@ -83023,8 +83552,8 @@ var doctorCommand = new Command("doctor").description("Run diagnostic checks on
|
|
|
83023
83552
|
try {
|
|
83024
83553
|
const tables = await adapter.listTables();
|
|
83025
83554
|
const tableColumns = new Map;
|
|
83026
|
-
for (const
|
|
83027
|
-
tableColumns.set(
|
|
83555
|
+
for (const t6 of tables) {
|
|
83556
|
+
tableColumns.set(t6.name, t6.columns.map((c) => c.name));
|
|
83028
83557
|
}
|
|
83029
83558
|
results.push(runDoctorChecks.checkBlacklistCompleteness(tableColumns, blacklistedColumns));
|
|
83030
83559
|
results.push(runDoctorChecks.checkLargeTables(tables));
|
|
@@ -83033,7 +83562,7 @@ var doctorCommand = new Command("doctor").description("Run diagnostic checks on
|
|
|
83033
83562
|
}
|
|
83034
83563
|
try {
|
|
83035
83564
|
const schemaConnName = await getSchemaIsolationConnectionName(configPath);
|
|
83036
|
-
const indexPath =
|
|
83565
|
+
const indexPath = join11(resolveSchemaPath(storagePath, schemaConnName), "index.json");
|
|
83037
83566
|
const indexFile = Bun.file(indexPath);
|
|
83038
83567
|
let indexParsed = null;
|
|
83039
83568
|
if (await indexFile.exists()) {
|
|
@@ -83075,8 +83604,8 @@ var doctorCommand = new Command("doctor").description("Run diagnostic checks on
|
|
|
83075
83604
|
});
|
|
83076
83605
|
|
|
83077
83606
|
// src/commands/completion.ts
|
|
83078
|
-
import { join as
|
|
83079
|
-
import { homedir as
|
|
83607
|
+
import { join as join12 } from "path";
|
|
83608
|
+
import { homedir as homedir3 } from "os";
|
|
83080
83609
|
function extractCommands(program2) {
|
|
83081
83610
|
return program2.commands.map((cmd) => ({
|
|
83082
83611
|
name: cmd.name(),
|
|
@@ -83155,10 +83684,7 @@ _dbcli
|
|
|
83155
83684
|
`;
|
|
83156
83685
|
}
|
|
83157
83686
|
function generateFishCompletion(commands, globalOptions) {
|
|
83158
|
-
const lines2 = [
|
|
83159
|
-
"# dbcli fish completion \u2014 auto-generated, do not edit",
|
|
83160
|
-
""
|
|
83161
|
-
];
|
|
83687
|
+
const lines2 = ["# dbcli fish completion \u2014 auto-generated, do not edit", ""];
|
|
83162
83688
|
for (const opt of globalOptions) {
|
|
83163
83689
|
const longName = opt.replace(/^--/, "");
|
|
83164
83690
|
lines2.push(`complete -c dbcli -n '__fish_use_subcommand' -l ${longName} -d '${opt}'`);
|
|
@@ -83177,14 +83703,14 @@ function generateFishCompletion(commands, globalOptions) {
|
|
|
83177
83703
|
`;
|
|
83178
83704
|
}
|
|
83179
83705
|
function getInstallPath2(shell) {
|
|
83180
|
-
const home =
|
|
83706
|
+
const home = homedir3();
|
|
83181
83707
|
switch (shell) {
|
|
83182
83708
|
case "bash":
|
|
83183
|
-
return
|
|
83709
|
+
return join12(home, ".bashrc");
|
|
83184
83710
|
case "zsh":
|
|
83185
|
-
return
|
|
83711
|
+
return join12(home, ".zshrc");
|
|
83186
83712
|
case "fish":
|
|
83187
|
-
return
|
|
83713
|
+
return join12(home, ".config", "fish", "completions", "dbcli.fish");
|
|
83188
83714
|
default:
|
|
83189
83715
|
throw new Error(`Unsupported shell: ${shell}. Supported: bash, zsh, fish`);
|
|
83190
83716
|
}
|
|
@@ -83204,7 +83730,7 @@ var MARKER_END = "# <<< dbcli completion <<<";
|
|
|
83204
83730
|
async function installCompletion(shell, script) {
|
|
83205
83731
|
const targetPath = getInstallPath2(shell);
|
|
83206
83732
|
if (shell === "fish") {
|
|
83207
|
-
const dir =
|
|
83733
|
+
const dir = join12(homedir3(), ".config", "fish", "completions");
|
|
83208
83734
|
await Bun.$`mkdir -p ${dir}`.quiet();
|
|
83209
83735
|
await Bun.file(targetPath).write(script);
|
|
83210
83736
|
console.log(colors.success(`\u2713 Fish completion installed to ${targetPath}`));
|
|
@@ -83431,8 +83957,8 @@ ${t("upgrade.failed")}`));
|
|
|
83431
83957
|
|
|
83432
83958
|
// src/commands/shell.ts
|
|
83433
83959
|
import { createInterface as createInterface2 } from "readline";
|
|
83434
|
-
import { join as
|
|
83435
|
-
import { homedir as
|
|
83960
|
+
import { join as join13 } from "path";
|
|
83961
|
+
import { homedir as homedir4 } from "os";
|
|
83436
83962
|
|
|
83437
83963
|
// src/core/repl/types.ts
|
|
83438
83964
|
var SQL_KEYWORDS_FOR_DETECTION = [
|
|
@@ -83952,7 +84478,7 @@ class ReplEngine {
|
|
|
83952
84478
|
const tableName = this.extractTableName(sql);
|
|
83953
84479
|
if (tableName) {
|
|
83954
84480
|
const blacklistedTables = this.config.blacklist.tables ?? [];
|
|
83955
|
-
const isBlacklisted = blacklistedTables.some((
|
|
84481
|
+
const isBlacklisted = blacklistedTables.some((t6) => t6.toLowerCase() === tableName.toLowerCase());
|
|
83956
84482
|
if (isBlacklisted) {
|
|
83957
84483
|
return {
|
|
83958
84484
|
action: "continue",
|
|
@@ -84027,13 +84553,7 @@ var TABLE_POSITION_KEYWORDS = new Set([
|
|
|
84027
84553
|
"UPDATE",
|
|
84028
84554
|
"TABLE"
|
|
84029
84555
|
]);
|
|
84030
|
-
var COMMANDS_TAKING_TABLE_ARG = new Set([
|
|
84031
|
-
"schema",
|
|
84032
|
-
"insert",
|
|
84033
|
-
"update",
|
|
84034
|
-
"delete",
|
|
84035
|
-
"check"
|
|
84036
|
-
]);
|
|
84556
|
+
var COMMANDS_TAKING_TABLE_ARG = new Set(["schema", "insert", "update", "delete", "check"]);
|
|
84037
84557
|
function createCompleter(ctx) {
|
|
84038
84558
|
const allTableNames = ctx.tableNames;
|
|
84039
84559
|
const allColumns = Object.values(ctx.columnsByTable).flat();
|
|
@@ -84107,7 +84627,7 @@ function extractTableFromLine(line, tableNames) {
|
|
|
84107
84627
|
if (fromIdx >= 0) {
|
|
84108
84628
|
const afterFrom = line.slice(fromIdx + 5).trim().split(/\s+/)[0];
|
|
84109
84629
|
const candidate = afterFrom.replace(/[;,]/g, "").toLowerCase();
|
|
84110
|
-
return tableNames.find((
|
|
84630
|
+
return tableNames.find((t6) => t6.toLowerCase() === candidate);
|
|
84111
84631
|
}
|
|
84112
84632
|
return;
|
|
84113
84633
|
}
|
|
@@ -84157,7 +84677,7 @@ class MongoShellAdapter {
|
|
|
84157
84677
|
}
|
|
84158
84678
|
|
|
84159
84679
|
// src/commands/shell.ts
|
|
84160
|
-
var HISTORY_PATH =
|
|
84680
|
+
var HISTORY_PATH = join13(homedir4(), ".dbcli_history");
|
|
84161
84681
|
var 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) => {
|
|
84162
84682
|
const configPath = resolveConfigPath(command);
|
|
84163
84683
|
await runShell(options, configPath);
|
|
@@ -84171,7 +84691,8 @@ async function runShell(options, configPath) {
|
|
|
84171
84691
|
process.exit(1);
|
|
84172
84692
|
}
|
|
84173
84693
|
const isMongoDB = config.connection.system === "mongodb";
|
|
84174
|
-
const
|
|
84694
|
+
const connectionOpts = config.connection;
|
|
84695
|
+
const adapter = isMongoDB ? new MongoShellAdapter(AdapterFactory.createMongoDBAdapter(connectionOpts)) : AdapterFactory.createAdapter(connectionOpts);
|
|
84175
84696
|
try {
|
|
84176
84697
|
await adapter.connect();
|
|
84177
84698
|
} catch (error) {
|
|
@@ -84179,7 +84700,7 @@ async function runShell(options, configPath) {
|
|
|
84179
84700
|
process.exit(1);
|
|
84180
84701
|
}
|
|
84181
84702
|
let tableNames = [];
|
|
84182
|
-
|
|
84703
|
+
const columnsByTable = {};
|
|
84183
84704
|
if (isMongoDB) {
|
|
84184
84705
|
const collections = await adapter.listTables();
|
|
84185
84706
|
tableNames = collections.map((collection) => collection.name);
|
|
@@ -84349,25 +84870,25 @@ class PostgreSQLDDLGenerator {
|
|
|
84349
84870
|
alterColumn(options) {
|
|
84350
84871
|
const statements = [];
|
|
84351
84872
|
const warnings = [];
|
|
84352
|
-
const
|
|
84873
|
+
const t6 = q(options.table);
|
|
84353
84874
|
const c = q(options.column);
|
|
84354
84875
|
if (options.type) {
|
|
84355
|
-
statements.push(`ALTER TABLE ${
|
|
84876
|
+
statements.push(`ALTER TABLE ${t6} ALTER COLUMN ${c} TYPE ${options.type.toUpperCase()};`);
|
|
84356
84877
|
}
|
|
84357
84878
|
if (options.rename) {
|
|
84358
|
-
statements.push(`ALTER TABLE ${
|
|
84879
|
+
statements.push(`ALTER TABLE ${t6} RENAME COLUMN ${c} TO ${q(options.rename)};`);
|
|
84359
84880
|
}
|
|
84360
84881
|
if (options.setDefault !== undefined) {
|
|
84361
|
-
statements.push(`ALTER TABLE ${
|
|
84882
|
+
statements.push(`ALTER TABLE ${t6} ALTER COLUMN ${c} SET DEFAULT ${options.setDefault};`);
|
|
84362
84883
|
}
|
|
84363
84884
|
if (options.dropDefault) {
|
|
84364
|
-
statements.push(`ALTER TABLE ${
|
|
84885
|
+
statements.push(`ALTER TABLE ${t6} ALTER COLUMN ${c} DROP DEFAULT;`);
|
|
84365
84886
|
}
|
|
84366
84887
|
if (options.setNullable) {
|
|
84367
|
-
statements.push(`ALTER TABLE ${
|
|
84888
|
+
statements.push(`ALTER TABLE ${t6} ALTER COLUMN ${c} DROP NOT NULL;`);
|
|
84368
84889
|
}
|
|
84369
84890
|
if (options.dropNullable) {
|
|
84370
|
-
statements.push(`ALTER TABLE ${
|
|
84891
|
+
statements.push(`ALTER TABLE ${t6} ALTER COLUMN ${c} SET NOT NULL;`);
|
|
84371
84892
|
}
|
|
84372
84893
|
if (statements.length === 0) {
|
|
84373
84894
|
warnings.push("No alter operations specified");
|
|
@@ -84389,14 +84910,14 @@ class PostgreSQLDDLGenerator {
|
|
|
84389
84910
|
return { sql: `DROP INDEX ${q(indexName)};`, warnings: [] };
|
|
84390
84911
|
}
|
|
84391
84912
|
addConstraint(constraint) {
|
|
84392
|
-
const
|
|
84913
|
+
const t6 = q(constraint.table);
|
|
84393
84914
|
const warnings = [];
|
|
84394
84915
|
switch (constraint.type) {
|
|
84395
84916
|
case "foreign_key": {
|
|
84396
84917
|
const name = constraint.name || `fk_${constraint.table}_${constraint.column}`;
|
|
84397
84918
|
const onDelete = constraint.onDelete ? ` ON DELETE ${constraint.onDelete.toUpperCase().replace("_", " ")}` : "";
|
|
84398
84919
|
return {
|
|
84399
|
-
sql: `ALTER TABLE ${
|
|
84920
|
+
sql: `ALTER TABLE ${t6} ADD CONSTRAINT ${q(name)} FOREIGN KEY (${q(constraint.column)}) REFERENCES ${q(constraint.references.table)}(${q(constraint.references.column)})${onDelete};`,
|
|
84400
84921
|
warnings
|
|
84401
84922
|
};
|
|
84402
84923
|
}
|
|
@@ -84404,14 +84925,14 @@ class PostgreSQLDDLGenerator {
|
|
|
84404
84925
|
const name = constraint.name || `uq_${constraint.table}_${constraint.columns.join("_")}`;
|
|
84405
84926
|
const cols = constraint.columns.map(q).join(", ");
|
|
84406
84927
|
return {
|
|
84407
|
-
sql: `ALTER TABLE ${
|
|
84928
|
+
sql: `ALTER TABLE ${t6} ADD CONSTRAINT ${q(name)} UNIQUE (${cols});`,
|
|
84408
84929
|
warnings
|
|
84409
84930
|
};
|
|
84410
84931
|
}
|
|
84411
84932
|
case "check": {
|
|
84412
84933
|
const name = constraint.name || `ck_${constraint.table}`;
|
|
84413
84934
|
return {
|
|
84414
|
-
sql: `ALTER TABLE ${
|
|
84935
|
+
sql: `ALTER TABLE ${t6} ADD CONSTRAINT ${q(name)} CHECK (${constraint.expression});`,
|
|
84415
84936
|
warnings
|
|
84416
84937
|
};
|
|
84417
84938
|
}
|
|
@@ -84514,19 +85035,19 @@ class MySQLDDLGenerator {
|
|
|
84514
85035
|
alterColumn(options) {
|
|
84515
85036
|
const statements = [];
|
|
84516
85037
|
const warnings = [];
|
|
84517
|
-
const
|
|
85038
|
+
const t6 = q2(options.table);
|
|
84518
85039
|
const c = q2(options.column);
|
|
84519
85040
|
if (options.type) {
|
|
84520
85041
|
const nullable = options.dropNullable ? " NOT NULL" : "";
|
|
84521
85042
|
const def = options.setDefault !== undefined ? ` DEFAULT ${options.setDefault}` : "";
|
|
84522
|
-
statements.push(`ALTER TABLE ${
|
|
85043
|
+
statements.push(`ALTER TABLE ${t6} MODIFY COLUMN ${c} ${options.type.toUpperCase()}${nullable}${def};`);
|
|
84523
85044
|
warnings.push("MySQL MODIFY COLUMN resets column attributes not explicitly specified");
|
|
84524
85045
|
} else {
|
|
84525
85046
|
if (options.setDefault !== undefined) {
|
|
84526
|
-
statements.push(`ALTER TABLE ${
|
|
85047
|
+
statements.push(`ALTER TABLE ${t6} ALTER COLUMN ${c} SET DEFAULT ${options.setDefault};`);
|
|
84527
85048
|
}
|
|
84528
85049
|
if (options.dropDefault) {
|
|
84529
|
-
statements.push(`ALTER TABLE ${
|
|
85050
|
+
statements.push(`ALTER TABLE ${t6} ALTER COLUMN ${c} DROP DEFAULT;`);
|
|
84530
85051
|
}
|
|
84531
85052
|
if (options.setNullable) {
|
|
84532
85053
|
warnings.push("MySQL requires MODIFY COLUMN with full type to change nullability \u2014 use --type to specify");
|
|
@@ -84536,7 +85057,7 @@ class MySQLDDLGenerator {
|
|
|
84536
85057
|
}
|
|
84537
85058
|
}
|
|
84538
85059
|
if (options.rename) {
|
|
84539
|
-
statements.push(`ALTER TABLE ${
|
|
85060
|
+
statements.push(`ALTER TABLE ${t6} RENAME COLUMN ${c} TO ${q2(options.rename)};`);
|
|
84540
85061
|
}
|
|
84541
85062
|
if (statements.length === 0 && warnings.length === 0) {
|
|
84542
85063
|
warnings.push("No alter operations specified");
|
|
@@ -84562,14 +85083,14 @@ class MySQLDDLGenerator {
|
|
|
84562
85083
|
};
|
|
84563
85084
|
}
|
|
84564
85085
|
addConstraint(constraint) {
|
|
84565
|
-
const
|
|
85086
|
+
const t6 = q2(constraint.table);
|
|
84566
85087
|
const warnings = [];
|
|
84567
85088
|
switch (constraint.type) {
|
|
84568
85089
|
case "foreign_key": {
|
|
84569
85090
|
const name = constraint.name || `fk_${constraint.table}_${constraint.column}`;
|
|
84570
85091
|
const onDelete = constraint.onDelete ? ` ON DELETE ${constraint.onDelete.toUpperCase().replace("_", " ")}` : "";
|
|
84571
85092
|
return {
|
|
84572
|
-
sql: `ALTER TABLE ${
|
|
85093
|
+
sql: `ALTER TABLE ${t6} ADD CONSTRAINT ${q2(name)} FOREIGN KEY (${q2(constraint.column)}) REFERENCES ${q2(constraint.references.table)}(${q2(constraint.references.column)})${onDelete};`,
|
|
84573
85094
|
warnings
|
|
84574
85095
|
};
|
|
84575
85096
|
}
|
|
@@ -84577,14 +85098,14 @@ class MySQLDDLGenerator {
|
|
|
84577
85098
|
const name = constraint.name || `uq_${constraint.table}_${constraint.columns.join("_")}`;
|
|
84578
85099
|
const cols = constraint.columns.map(q2).join(", ");
|
|
84579
85100
|
return {
|
|
84580
|
-
sql: `ALTER TABLE ${
|
|
85101
|
+
sql: `ALTER TABLE ${t6} ADD CONSTRAINT ${q2(name)} UNIQUE (${cols});`,
|
|
84581
85102
|
warnings
|
|
84582
85103
|
};
|
|
84583
85104
|
}
|
|
84584
85105
|
case "check": {
|
|
84585
85106
|
const name = constraint.name || `ck_${constraint.table}`;
|
|
84586
85107
|
return {
|
|
84587
|
-
sql: `ALTER TABLE ${
|
|
85108
|
+
sql: `ALTER TABLE ${t6} ADD CONSTRAINT ${q2(name)} CHECK (${constraint.expression});`,
|
|
84588
85109
|
warnings: ["CHECK constraints enforced in MySQL 8.0.16+ and MariaDB 10.2.1+ only"]
|
|
84589
85110
|
};
|
|
84590
85111
|
}
|
|
@@ -84599,13 +85120,17 @@ class MySQLDDLGenerator {
|
|
|
84599
85120
|
addEnum(_definition) {
|
|
84600
85121
|
return {
|
|
84601
85122
|
sql: "",
|
|
84602
|
-
warnings: [
|
|
85123
|
+
warnings: [
|
|
85124
|
+
`MySQL has no standalone ENUM type \u2014 use ENUM in column definition instead (e.g., "status:enum('a','b'):not-null")`
|
|
85125
|
+
]
|
|
84603
85126
|
};
|
|
84604
85127
|
}
|
|
84605
85128
|
alterEnum(_name, _addValue) {
|
|
84606
85129
|
return {
|
|
84607
85130
|
sql: "",
|
|
84608
|
-
warnings: [
|
|
85131
|
+
warnings: [
|
|
85132
|
+
"MySQL has no standalone ENUM type \u2014 use ALTER TABLE MODIFY COLUMN to change enum values"
|
|
85133
|
+
]
|
|
84609
85134
|
};
|
|
84610
85135
|
}
|
|
84611
85136
|
dropEnum(_name) {
|
|
@@ -85093,7 +85618,7 @@ addExecOpts(migrateCommand.command("drop-enum <name>").description(t("migrate.dr
|
|
|
85093
85618
|
});
|
|
85094
85619
|
|
|
85095
85620
|
// src/commands/use.ts
|
|
85096
|
-
import { join as
|
|
85621
|
+
import { join as join14 } from "path";
|
|
85097
85622
|
async function switchDefault(configPath, name, config) {
|
|
85098
85623
|
if (!config.connections[name]) {
|
|
85099
85624
|
const available = Object.keys(config.connections).join(", ");
|
|
@@ -85115,15 +85640,41 @@ function listConnectionsForDisplay(config) {
|
|
|
85115
85640
|
});
|
|
85116
85641
|
}
|
|
85117
85642
|
async function ensureV2Config(configPath) {
|
|
85118
|
-
const
|
|
85119
|
-
|
|
85643
|
+
const storagePath = await resolveConfigStoragePath(configPath);
|
|
85644
|
+
const configFile = Bun.file(join14(storagePath, "config.json"));
|
|
85645
|
+
const legacyFile = Bun.file(configPath);
|
|
85646
|
+
if (!await configFile.exists() && !await legacyFile.exists()) {
|
|
85120
85647
|
throw new ConfigError(t("init.config_not_found"));
|
|
85121
85648
|
}
|
|
85122
|
-
|
|
85123
|
-
|
|
85649
|
+
try {
|
|
85650
|
+
const raw = await (async () => {
|
|
85651
|
+
if (await configFile.exists())
|
|
85652
|
+
return JSON.parse(await configFile.text());
|
|
85653
|
+
return JSON.parse(await legacyFile.text());
|
|
85654
|
+
})();
|
|
85655
|
+
if (!raw.version || raw.version !== 2 || !raw.connections) {
|
|
85656
|
+
const v1Config = await configModule.read(configPath);
|
|
85657
|
+
return {
|
|
85658
|
+
version: 2,
|
|
85659
|
+
default: "default",
|
|
85660
|
+
connections: {
|
|
85661
|
+
default: {
|
|
85662
|
+
...v1Config.connection,
|
|
85663
|
+
permission: v1Config.permission
|
|
85664
|
+
}
|
|
85665
|
+
},
|
|
85666
|
+
schema: v1Config.schema || {},
|
|
85667
|
+
schemas: { default: v1Config.schema || {} },
|
|
85668
|
+
metadata: v1Config.metadata || { version: "1.0" },
|
|
85669
|
+
blacklist: v1Config.blacklist || { tables: [], columns: {} }
|
|
85670
|
+
};
|
|
85671
|
+
}
|
|
85672
|
+
return readV2Config(storagePath);
|
|
85673
|
+
} catch (error) {
|
|
85674
|
+
if (error instanceof ConfigError)
|
|
85675
|
+
throw error;
|
|
85124
85676
|
throw new ConfigError(t("use.requires_v2"));
|
|
85125
85677
|
}
|
|
85126
|
-
return readV2Config(configPath);
|
|
85127
85678
|
}
|
|
85128
85679
|
var useCommand = new Command("use").description("Switch or display the default database connection (v2 config)").argument("[name]", "Connection name to switch to").option("--list", "List all connections").action(async (name, options) => {
|
|
85129
85680
|
try {
|
|
@@ -85152,7 +85703,7 @@ var useCommand = new Command("use").description("Switch or display the default d
|
|
|
85152
85703
|
});
|
|
85153
85704
|
|
|
85154
85705
|
// src/cli.ts
|
|
85155
|
-
import { join as
|
|
85706
|
+
import { join as join15 } from "path";
|
|
85156
85707
|
var _bgVersionCheckResult;
|
|
85157
85708
|
var program2 = new Command().name("dbcli").description("Database CLI for AI agents").version(package_default.version).option("--no-color", "Disable colored output").option("-v, --verbose", "Increase verbosity (-v verbose, -vv debug)", (_, prev) => prev + 1, 0).option("-q, --quiet", "Suppress non-essential output").option("--config <path>", "Path to .dbcli config file", ".dbcli").option("--use <connection>", "Use a specific named connection (v2 config)");
|
|
85158
85709
|
program2.hook("preAction", (thisCommand, actionCommand) => {
|
|
@@ -85178,7 +85729,7 @@ program2.hook("preAction", (thisCommand, actionCommand) => {
|
|
|
85178
85729
|
try {
|
|
85179
85730
|
let cache = null;
|
|
85180
85731
|
try {
|
|
85181
|
-
const cacheFile = Bun.file(
|
|
85732
|
+
const cacheFile = Bun.file(join15(configPath, "version-check.json"));
|
|
85182
85733
|
if (await cacheFile.exists()) {
|
|
85183
85734
|
cache = await cacheFile.json();
|
|
85184
85735
|
}
|