@carllee1983/dbcli 1.5.2 → 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 +16 -0
- package/README.dev.md +51 -54
- package/README.md +27 -17
- package/README.zh-TW.md +25 -15
- package/assets/SKILL.md +63 -510
- package/assets/reference.md +371 -0
- package/dist/cli.mjs +797 -400
- 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
|
}
|
|
@@ -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,
|
|
@@ -79145,6 +79263,40 @@ class MongoDBAdapter {
|
|
|
79145
79263
|
}));
|
|
79146
79264
|
return results;
|
|
79147
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
|
+
}
|
|
79148
79300
|
async testConnection() {
|
|
79149
79301
|
if (!this.client)
|
|
79150
79302
|
return false;
|
|
@@ -79155,6 +79307,31 @@ class MongoDBAdapter {
|
|
|
79155
79307
|
const info = await this.getDatabase().admin().serverInfo();
|
|
79156
79308
|
return info.version ?? "unknown";
|
|
79157
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
|
+
}
|
|
79158
79335
|
}
|
|
79159
79336
|
|
|
79160
79337
|
// src/adapters/factory.ts
|
|
@@ -79166,6 +79343,8 @@ class AdapterFactory {
|
|
|
79166
79343
|
case "mysql":
|
|
79167
79344
|
case "mariadb":
|
|
79168
79345
|
return new MySQLAdapter(options);
|
|
79346
|
+
case "mongodb":
|
|
79347
|
+
return new MongoDBAdapter(options);
|
|
79169
79348
|
default:
|
|
79170
79349
|
throw new Error(`Unsupported database system: ${options.system}`);
|
|
79171
79350
|
}
|
|
@@ -79197,9 +79376,11 @@ function resolveConfigPath(command, options, fallback = ".dbcli") {
|
|
|
79197
79376
|
// src/commands/init.ts
|
|
79198
79377
|
var VALID_PERMISSIONS = ["query-only", "read-write", "data-admin", "admin"];
|
|
79199
79378
|
async function checkOverwrite(configPath, shouldPrompt, force) {
|
|
79379
|
+
const storagePath = await resolveConfigStoragePath(configPath);
|
|
79200
79380
|
const fileExists = await Bun.file(configPath).exists();
|
|
79201
|
-
const dirConfigExists = await Bun.file(
|
|
79202
|
-
|
|
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)
|
|
79203
79384
|
return true;
|
|
79204
79385
|
if (shouldPrompt) {
|
|
79205
79386
|
const overwrite = await promptUser.confirm(t("init.config_exists_overwrite"));
|
|
@@ -79212,7 +79393,8 @@ async function checkOverwrite(configPath, shouldPrompt, force) {
|
|
|
79212
79393
|
throw new Error(t("init.config_exists_use_force"));
|
|
79213
79394
|
}
|
|
79214
79395
|
async function handleRemove(configPath, name) {
|
|
79215
|
-
const
|
|
79396
|
+
const storagePath = await resolveConfigStoragePath(configPath);
|
|
79397
|
+
const configFile = Bun.file(join8(storagePath, "config.json"));
|
|
79216
79398
|
if (!await configFile.exists()) {
|
|
79217
79399
|
throw new Error(t("init.config_not_found"));
|
|
79218
79400
|
}
|
|
@@ -79220,7 +79402,7 @@ async function handleRemove(configPath, name) {
|
|
|
79220
79402
|
if (detectConfigVersion(raw) !== 2) {
|
|
79221
79403
|
throw new Error(t("init.requires_v2_remove"));
|
|
79222
79404
|
}
|
|
79223
|
-
const config = await readV2Config(
|
|
79405
|
+
const config = await readV2Config(storagePath);
|
|
79224
79406
|
if (!config.connections[name]) {
|
|
79225
79407
|
throw new Error(t_vars("init.connection_not_found", { name }));
|
|
79226
79408
|
}
|
|
@@ -79228,14 +79410,14 @@ async function handleRemove(configPath, name) {
|
|
|
79228
79410
|
if (connectionCount <= 1) {
|
|
79229
79411
|
throw new Error(t("init.cannot_remove_last"));
|
|
79230
79412
|
}
|
|
79231
|
-
const
|
|
79413
|
+
const remaining = Object.fromEntries(Object.entries(config.connections).filter(([connectionName]) => connectionName !== name));
|
|
79232
79414
|
const newDefault = config.default === name ? Object.keys(remaining)[0] : config.default;
|
|
79233
79415
|
const updated = {
|
|
79234
79416
|
...config,
|
|
79235
79417
|
default: newDefault,
|
|
79236
79418
|
connections: remaining
|
|
79237
79419
|
};
|
|
79238
|
-
await writeV2Config(
|
|
79420
|
+
await writeV2Config(storagePath, updated);
|
|
79239
79421
|
if (config.default === name) {
|
|
79240
79422
|
console.log(t_vars("init.connection_removed_switched", { name, newDefault }));
|
|
79241
79423
|
} else {
|
|
@@ -79247,7 +79429,8 @@ async function handleRename(configPath, renameArg) {
|
|
|
79247
79429
|
if (!oldName || !newName) {
|
|
79248
79430
|
throw new Error(t("init.rename_invalid_format"));
|
|
79249
79431
|
}
|
|
79250
|
-
const
|
|
79432
|
+
const storagePath = await resolveConfigStoragePath(configPath);
|
|
79433
|
+
const configFile = Bun.file(join8(storagePath, "config.json"));
|
|
79251
79434
|
if (!await configFile.exists()) {
|
|
79252
79435
|
throw new Error(t("init.config_not_found"));
|
|
79253
79436
|
}
|
|
@@ -79255,7 +79438,7 @@ async function handleRename(configPath, renameArg) {
|
|
|
79255
79438
|
if (detectConfigVersion(raw) !== 2) {
|
|
79256
79439
|
throw new Error(t("init.requires_v2_rename"));
|
|
79257
79440
|
}
|
|
79258
|
-
const config = await readV2Config(
|
|
79441
|
+
const config = await readV2Config(storagePath);
|
|
79259
79442
|
if (!config.connections[oldName]) {
|
|
79260
79443
|
throw new Error(t_vars("init.connection_not_found", { name: oldName }));
|
|
79261
79444
|
}
|
|
@@ -79268,17 +79451,54 @@ async function handleRename(configPath, renameArg) {
|
|
|
79268
79451
|
default: config.default === oldName ? newName : config.default,
|
|
79269
79452
|
connections: Object.fromEntries(entries)
|
|
79270
79453
|
};
|
|
79271
|
-
await writeV2Config(
|
|
79454
|
+
await writeV2Config(storagePath, updated);
|
|
79272
79455
|
console.log(t_vars("init.connection_renamed", { oldName, newName }));
|
|
79273
79456
|
}
|
|
79274
79457
|
async function writeV2InitConfig(configPath, connectionName, connection, permission, envFile) {
|
|
79275
|
-
const
|
|
79458
|
+
const storagePath = getProjectStoragePath(configPath);
|
|
79459
|
+
const configJsonPath = join8(storagePath, "config.json");
|
|
79276
79460
|
const configFile = Bun.file(configJsonPath);
|
|
79461
|
+
const projectConfigFile = Bun.file(join8(configPath, "config.json"));
|
|
79277
79462
|
let existingV2 = null;
|
|
79278
79463
|
if (await configFile.exists()) {
|
|
79279
79464
|
const raw = JSON.parse(await configFile.text());
|
|
79280
79465
|
if (detectConfigVersion(raw) === 2) {
|
|
79281
|
-
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
|
+
};
|
|
79282
79502
|
} else {
|
|
79283
79503
|
const v1Config = await configModule.read(configPath);
|
|
79284
79504
|
existingV2 = {
|
|
@@ -79291,16 +79511,17 @@ async function writeV2InitConfig(configPath, connectionName, connection, permiss
|
|
|
79291
79511
|
}
|
|
79292
79512
|
},
|
|
79293
79513
|
schema: v1Config.schema || {},
|
|
79514
|
+
schemas: { default: v1Config.schema || {} },
|
|
79294
79515
|
metadata: v1Config.metadata || { version: "1.0" },
|
|
79295
79516
|
blacklist: v1Config.blacklist || { tables: [], columns: {} }
|
|
79296
79517
|
};
|
|
79297
79518
|
}
|
|
79298
79519
|
} else {
|
|
79299
|
-
const legacyFile = Bun.file(
|
|
79520
|
+
const legacyFile = Bun.file(storagePath);
|
|
79300
79521
|
if (await legacyFile.exists()) {
|
|
79301
79522
|
const raw = JSON.parse(await legacyFile.text());
|
|
79302
79523
|
if (detectConfigVersion(raw) !== 2) {
|
|
79303
|
-
const v1Config = await configModule.read(
|
|
79524
|
+
const v1Config = await configModule.read(storagePath);
|
|
79304
79525
|
existingV2 = {
|
|
79305
79526
|
version: 2,
|
|
79306
79527
|
default: "default",
|
|
@@ -79311,6 +79532,7 @@ async function writeV2InitConfig(configPath, connectionName, connection, permiss
|
|
|
79311
79532
|
}
|
|
79312
79533
|
},
|
|
79313
79534
|
schema: v1Config.schema || {},
|
|
79535
|
+
schemas: { default: v1Config.schema || {} },
|
|
79314
79536
|
metadata: v1Config.metadata || { version: "1.0" },
|
|
79315
79537
|
blacklist: v1Config.blacklist || { tables: [], columns: {} }
|
|
79316
79538
|
};
|
|
@@ -79337,11 +79559,13 @@ async function writeV2InitConfig(configPath, connectionName, connection, permiss
|
|
|
79337
79559
|
[connectionName]: connEntry
|
|
79338
79560
|
},
|
|
79339
79561
|
schema: {},
|
|
79562
|
+
schemas: {},
|
|
79340
79563
|
metadata: { version: "1.0", createdAt: new Date().toISOString() },
|
|
79341
79564
|
blacklist: { tables: [], columns: {} }
|
|
79342
79565
|
};
|
|
79343
|
-
await
|
|
79344
|
-
await
|
|
79566
|
+
await writeV2Config(storagePath, v2Config);
|
|
79567
|
+
await migrateLegacyProjectEnvLocal(configPath, storagePath);
|
|
79568
|
+
await writeProjectBinding(configPath, storagePath);
|
|
79345
79569
|
console.log(t("init.config_saved"));
|
|
79346
79570
|
}
|
|
79347
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) => {
|
|
@@ -79380,7 +79604,8 @@ async function initCommandHandler(options, command) {
|
|
|
79380
79604
|
console.log(t("init.env_parse_note"));
|
|
79381
79605
|
}
|
|
79382
79606
|
}
|
|
79383
|
-
|
|
79607
|
+
const systemFromCli = typeof options.system === "string" ? options.system : undefined;
|
|
79608
|
+
let system = systemFromCli ?? envConfig?.system ?? "postgresql";
|
|
79384
79609
|
if (shouldPrompt && !options.system && !envConfig?.system) {
|
|
79385
79610
|
system = await promptUser.select(t("init.select_system"), [
|
|
79386
79611
|
"postgresql",
|
|
@@ -79409,11 +79634,11 @@ async function initCommandHandler(options, command) {
|
|
|
79409
79634
|
};
|
|
79410
79635
|
let configForWrite;
|
|
79411
79636
|
if (options.useEnvRefs && shouldPrompt) {
|
|
79412
|
-
|
|
79413
|
-
|
|
79414
|
-
|
|
79415
|
-
|
|
79416
|
-
|
|
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");
|
|
79417
79642
|
configForWrite = {
|
|
79418
79643
|
system: connection.system,
|
|
79419
79644
|
host: { $env: envHost },
|
|
@@ -79422,7 +79647,8 @@ async function initCommandHandler(options, command) {
|
|
|
79422
79647
|
password: { $env: envPassword },
|
|
79423
79648
|
database: { $env: envDatabase }
|
|
79424
79649
|
};
|
|
79425
|
-
|
|
79650
|
+
const permissionFromCli2 = typeof options.permission === "string" ? options.permission : undefined;
|
|
79651
|
+
let permission2 = permissionFromCli2 ?? "query-only";
|
|
79426
79652
|
if (!options.permission) {
|
|
79427
79653
|
permission2 = await promptUser.select(t("init.prompt_permission"), [
|
|
79428
79654
|
"query-only",
|
|
@@ -79446,27 +79672,36 @@ async function initCommandHandler(options, command) {
|
|
|
79446
79672
|
await writeV2InitConfig(configPath, connectionName, configForWrite, permission2, options.envFile);
|
|
79447
79673
|
return;
|
|
79448
79674
|
}
|
|
79449
|
-
|
|
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);
|
|
79450
79680
|
console.log(t("init.config_saved"));
|
|
79451
79681
|
return;
|
|
79452
79682
|
}
|
|
79453
|
-
|
|
79454
|
-
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));
|
|
79455
79689
|
const port = parseInt(portStr, 10);
|
|
79456
79690
|
if (isNaN(port) || port < 1 || port > 65535) {
|
|
79457
79691
|
throw new Error(t_vars("errors.invalid_port", { port: portStr }));
|
|
79458
79692
|
}
|
|
79459
79693
|
connection.port = port;
|
|
79460
|
-
connection.user = options.user
|
|
79694
|
+
connection.user = strOpt(options.user) ?? envConfig?.user ?? (shouldPrompt ? await promptUser.text(t("init.prompt_user")) : "");
|
|
79461
79695
|
if (!connection.user && !shouldPrompt && !options.useEnvRefs) {
|
|
79462
79696
|
throw new Error(t("errors.require_user"));
|
|
79463
79697
|
}
|
|
79464
|
-
connection.password = options.password
|
|
79465
|
-
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")) : "");
|
|
79466
79700
|
if (!connection.database && !shouldPrompt && !options.useEnvRefs) {
|
|
79467
79701
|
throw new Error(t("errors.require_name"));
|
|
79468
79702
|
}
|
|
79469
|
-
|
|
79703
|
+
const permissionFromCli = typeof options.permission === "string" ? options.permission : undefined;
|
|
79704
|
+
let permission = permissionFromCli ?? "query-only";
|
|
79470
79705
|
if (shouldPrompt && !options.permission) {
|
|
79471
79706
|
permission = await promptUser.select(t("init.prompt_permission"), [
|
|
79472
79707
|
"query-only",
|
|
@@ -79551,7 +79786,11 @@ async function initCommandHandler(options, command) {
|
|
|
79551
79786
|
await writeV2InitConfig(configPath, connectionName, configForWrite, permission, options.envFile);
|
|
79552
79787
|
return;
|
|
79553
79788
|
}
|
|
79554
|
-
|
|
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);
|
|
79555
79794
|
console.log(t("init.config_saved"));
|
|
79556
79795
|
}
|
|
79557
79796
|
async function handleMongoDBInit(ctx) {
|
|
@@ -79632,7 +79871,11 @@ async function handleMongoDBInit(ctx) {
|
|
|
79632
79871
|
connection: mongoConfig,
|
|
79633
79872
|
permission
|
|
79634
79873
|
});
|
|
79635
|
-
|
|
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);
|
|
79636
79879
|
console.log(t("init.config_saved"));
|
|
79637
79880
|
}
|
|
79638
79881
|
|
|
@@ -79653,13 +79896,7 @@ class TableFormatter {
|
|
|
79653
79896
|
} else if (col.foreignKey) {
|
|
79654
79897
|
keyType = `FK \u2192 ${col.foreignKey.table}.${col.foreignKey.column}`;
|
|
79655
79898
|
}
|
|
79656
|
-
table.push([
|
|
79657
|
-
col.name,
|
|
79658
|
-
col.type,
|
|
79659
|
-
col.nullable ? "YES" : "NO",
|
|
79660
|
-
col.default || "NULL",
|
|
79661
|
-
keyType
|
|
79662
|
-
]);
|
|
79899
|
+
table.push([col.name, col.type, col.nullable ? "YES" : "NO", col.default || "NULL", keyType]);
|
|
79663
79900
|
});
|
|
79664
79901
|
return table.toString();
|
|
79665
79902
|
}
|
|
@@ -79975,7 +80212,7 @@ init_schema_cache();
|
|
|
79975
80212
|
|
|
79976
80213
|
// src/core/schema-writer.ts
|
|
79977
80214
|
init_schema_index();
|
|
79978
|
-
import { join as
|
|
80215
|
+
import { join as join9 } from "path";
|
|
79979
80216
|
|
|
79980
80217
|
// src/core/atomic-writer.ts
|
|
79981
80218
|
class AtomicFileWriter {
|
|
@@ -80108,7 +80345,7 @@ class SchemaWriter {
|
|
|
80108
80345
|
for (const item of mapping.hot) {
|
|
80109
80346
|
hotSchemas[item.table] = schema[item.table];
|
|
80110
80347
|
}
|
|
80111
|
-
await this.writer.writeJSON(
|
|
80348
|
+
await this.writer.writeJSON(join9(schemaRoot, "hot-schemas.json"), hotSchemas);
|
|
80112
80349
|
const coldGroups = {};
|
|
80113
80350
|
for (const item of mapping.cold) {
|
|
80114
80351
|
if (!coldGroups[item.file]) {
|
|
@@ -80116,10 +80353,10 @@ class SchemaWriter {
|
|
|
80116
80353
|
}
|
|
80117
80354
|
coldGroups[item.file][item.table] = schema[item.table];
|
|
80118
80355
|
}
|
|
80119
|
-
const coldDir =
|
|
80356
|
+
const coldDir = join9(schemaRoot, "cold");
|
|
80120
80357
|
await this.ensureDir(coldDir);
|
|
80121
80358
|
for (const [fileName, tables] of Object.entries(coldGroups)) {
|
|
80122
|
-
const filePath =
|
|
80359
|
+
const filePath = join9(schemaRoot, fileName);
|
|
80123
80360
|
await this.writer.writeJSON(filePath, tables);
|
|
80124
80361
|
}
|
|
80125
80362
|
}
|
|
@@ -80551,20 +80788,17 @@ var schemaCommand = new Command().name("schema").description("Display table sche
|
|
|
80551
80788
|
async function schemaAction(table, options) {
|
|
80552
80789
|
try {
|
|
80553
80790
|
validateFormat(options.format, ALLOWED_FORMATS2, "schema");
|
|
80791
|
+
const storagePath = await resolveConfigStoragePath(options.config);
|
|
80554
80792
|
const config = await configModule.read(options.config);
|
|
80555
80793
|
if (!config.connection) {
|
|
80556
80794
|
console.error("Database not configured. Run: dbcli init");
|
|
80557
80795
|
process.exit(1);
|
|
80558
80796
|
}
|
|
80559
|
-
if (config.connection?.system === "mongodb") {
|
|
80560
|
-
console.error("\u6B64\u547D\u4EE4\u76EE\u524D\u4E0D\u652F\u63F4 MongoDB");
|
|
80561
|
-
process.exit(1);
|
|
80562
|
-
}
|
|
80563
80797
|
const connectionName = await getSchemaIsolationConnectionName(options.config);
|
|
80564
80798
|
let existingSchemaCount;
|
|
80565
80799
|
if (connectionName !== undefined) {
|
|
80566
80800
|
try {
|
|
80567
|
-
const v2Raw = await readV2Config(
|
|
80801
|
+
const v2Raw = await readV2Config(storagePath);
|
|
80568
80802
|
existingSchemaCount = Object.keys(v2Raw.schemas?.[connectionName] ?? {}).length;
|
|
80569
80803
|
} catch {
|
|
80570
80804
|
existingSchemaCount = 0;
|
|
@@ -80576,13 +80810,13 @@ async function schemaAction(table, options) {
|
|
|
80576
80810
|
await adapter.connect();
|
|
80577
80811
|
try {
|
|
80578
80812
|
if (options.reset) {
|
|
80579
|
-
await handleSchemaReset(adapter, config, options, connectionName, existingSchemaCount);
|
|
80813
|
+
await handleSchemaReset(adapter, config, options, connectionName, existingSchemaCount, storagePath);
|
|
80580
80814
|
} else if (options.refresh) {
|
|
80581
|
-
await handleSchemaRefresh(adapter, config, options, connectionName);
|
|
80815
|
+
await handleSchemaRefresh(adapter, config, options, connectionName, storagePath);
|
|
80582
80816
|
} else if (table) {
|
|
80583
80817
|
await handleSingleTableSchema(adapter, table, options.format);
|
|
80584
80818
|
} else {
|
|
80585
|
-
await handleFullDatabaseScan(adapter, config, options, connectionName, existingSchemaCount);
|
|
80819
|
+
await handleFullDatabaseScan(adapter, config, options, connectionName, existingSchemaCount, storagePath);
|
|
80586
80820
|
}
|
|
80587
80821
|
} finally {
|
|
80588
80822
|
await adapter.disconnect();
|
|
@@ -80642,7 +80876,7 @@ Indexes:`);
|
|
|
80642
80876
|
}
|
|
80643
80877
|
}
|
|
80644
80878
|
}
|
|
80645
|
-
async function handleSchemaRefresh(adapter, config, options, connectionName) {
|
|
80879
|
+
async function handleSchemaRefresh(adapter, config, options, connectionName, storagePath) {
|
|
80646
80880
|
const diffEngine = new SchemaDiffEngine(adapter, config);
|
|
80647
80881
|
const report = await diffEngine.diff();
|
|
80648
80882
|
if (report.tablesAdded.length === 0 && report.tablesRemoved.length === 0 && Object.keys(report.tablesModified).length === 0) {
|
|
@@ -80653,7 +80887,7 @@ async function handleSchemaRefresh(adapter, config, options, connectionName) {
|
|
|
80653
80887
|
schemaTableCount: Object.keys(config.schema || {}).length
|
|
80654
80888
|
}
|
|
80655
80889
|
});
|
|
80656
|
-
await writeSchema(
|
|
80890
|
+
await writeSchema(storagePath, updatedConfig2, connectionName);
|
|
80657
80891
|
console.log("\u2705 Schema is up-to-date (no changes detected)");
|
|
80658
80892
|
return;
|
|
80659
80893
|
}
|
|
@@ -80677,16 +80911,16 @@ async function handleSchemaRefresh(adapter, config, options, connectionName) {
|
|
|
80677
80911
|
schemaTableCount: Object.keys(newSchema).length
|
|
80678
80912
|
}
|
|
80679
80913
|
});
|
|
80680
|
-
const writer = new SchemaWriter(
|
|
80914
|
+
const writer = new SchemaWriter(storagePath);
|
|
80681
80915
|
await writer.save(newSchema, connectionName);
|
|
80682
80916
|
console.log(`\u2705 Schema persisted to layered storage (.dbcli/schemas/${connectionName || ""})`);
|
|
80683
|
-
await writeSchema(
|
|
80917
|
+
await writeSchema(storagePath, updatedConfig, connectionName);
|
|
80684
80918
|
console.log(`\u2705 Schema updated in .dbcli`);
|
|
80685
80919
|
}
|
|
80686
|
-
async function handleSchemaReset(adapter, config, options, connectionName, existingCount) {
|
|
80920
|
+
async function handleSchemaReset(adapter, config, options, connectionName, existingCount, storagePath) {
|
|
80687
80921
|
if (existingCount > 0 && !options.force) {
|
|
80688
80922
|
const { SchemaLayeredLoader: SchemaLayeredLoader3 } = await Promise.resolve().then(() => (init_schema_loader(), exports_schema_loader));
|
|
80689
|
-
const loader = new SchemaLayeredLoader3(
|
|
80923
|
+
const loader = new SchemaLayeredLoader3(storagePath, { connectionName });
|
|
80690
80924
|
const { index } = await loader.initialize();
|
|
80691
80925
|
if (!index || Object.keys(index.tables).length === 0) {
|
|
80692
80926
|
console.log(`\u26A0 This will clear ${existingCount} existing table schemas and re-fetch from database.`);
|
|
@@ -80705,8 +80939,8 @@ async function handleSchemaReset(adapter, config, options, connectionName, exist
|
|
|
80705
80939
|
schema: {},
|
|
80706
80940
|
metadata: { ...config.metadata, ...emptyMeta }
|
|
80707
80941
|
};
|
|
80708
|
-
await writeSchema(
|
|
80709
|
-
const writer = new SchemaWriter(
|
|
80942
|
+
await writeSchema(storagePath, configWithoutSchema, connectionName);
|
|
80943
|
+
const writer = new SchemaWriter(storagePath);
|
|
80710
80944
|
await writer.clear(connectionName);
|
|
80711
80945
|
console.log(t("schema.scanning_database"));
|
|
80712
80946
|
const tables = await adapter.listTables();
|
|
@@ -80742,7 +80976,7 @@ async function handleSchemaReset(adapter, config, options, connectionName, exist
|
|
|
80742
80976
|
};
|
|
80743
80977
|
await writer.save(schemaData, connectionName);
|
|
80744
80978
|
console.log(`\u2705 Schema persisted to layered storage (.dbcli/schemas/${connectionName || ""})`);
|
|
80745
|
-
await writeSchema(
|
|
80979
|
+
await writeSchema(storagePath, updatedConfig, connectionName);
|
|
80746
80980
|
if (existingCount > 0) {
|
|
80747
80981
|
console.log(`
|
|
80748
80982
|
\u2705 Schema reset complete \u2014 cleared ${existingCount} old tables, fetched ${tables.length} tables from database`);
|
|
@@ -80751,7 +80985,7 @@ async function handleSchemaReset(adapter, config, options, connectionName, exist
|
|
|
80751
80985
|
\u2705 Schema fetched \u2014 ${tables.length} tables from database`);
|
|
80752
80986
|
}
|
|
80753
80987
|
}
|
|
80754
|
-
async function handleFullDatabaseScan(adapter, config, options, connectionName, existingSchemaCount) {
|
|
80988
|
+
async function handleFullDatabaseScan(adapter, config, options, connectionName, existingSchemaCount, storagePath) {
|
|
80755
80989
|
console.log(t("schema.scanning_database"));
|
|
80756
80990
|
const tables = await adapter.listTables();
|
|
80757
80991
|
console.log(t_vars("schema.tables_found", { count: tables.length }));
|
|
@@ -80777,7 +81011,7 @@ async function handleFullDatabaseScan(adapter, config, options, connectionName,
|
|
|
80777
81011
|
}
|
|
80778
81012
|
if (existingSchemaCount > 0 && !options.force) {
|
|
80779
81013
|
const { SchemaLayeredLoader: SchemaLayeredLoader3 } = await Promise.resolve().then(() => (init_schema_loader(), exports_schema_loader));
|
|
80780
|
-
const loader = new SchemaLayeredLoader3(
|
|
81014
|
+
const loader = new SchemaLayeredLoader3(storagePath, { connectionName });
|
|
80781
81015
|
const { index } = await loader.initialize();
|
|
80782
81016
|
if (!index || Object.keys(index.tables).length === 0) {
|
|
80783
81017
|
console.log(`
|
|
@@ -80801,10 +81035,10 @@ async function handleFullDatabaseScan(adapter, config, options, connectionName,
|
|
|
80801
81035
|
schemaTableCount: tables.length
|
|
80802
81036
|
}
|
|
80803
81037
|
};
|
|
80804
|
-
const writer = new SchemaWriter(
|
|
81038
|
+
const writer = new SchemaWriter(storagePath);
|
|
80805
81039
|
await writer.save(schemaData, connectionName);
|
|
80806
81040
|
console.log(`\u2705 Schema persisted to layered storage (.dbcli/schemas/${connectionName || ""})`);
|
|
80807
|
-
await writeSchema(
|
|
81041
|
+
await writeSchema(storagePath, updatedConfig, connectionName);
|
|
80808
81042
|
console.log(`
|
|
80809
81043
|
\u2705 Schema updated in .dbcli`);
|
|
80810
81044
|
console.log(` ${tables.length} tables with full column details and relationships`);
|
|
@@ -81003,12 +81237,7 @@ function determineConfidence(type, keyword, sql) {
|
|
|
81003
81237
|
if (highConfidenceTypes.includes(type)) {
|
|
81004
81238
|
return "HIGH";
|
|
81005
81239
|
}
|
|
81006
|
-
const mediumConfidenceTypes = [
|
|
81007
|
-
"CREATE",
|
|
81008
|
-
"ALTER",
|
|
81009
|
-
"DROP",
|
|
81010
|
-
"TRUNCATE"
|
|
81011
|
-
];
|
|
81240
|
+
const mediumConfidenceTypes = ["CREATE", "ALTER", "DROP", "TRUNCATE"];
|
|
81012
81241
|
if (mediumConfidenceTypes.includes(type)) {
|
|
81013
81242
|
return "MEDIUM";
|
|
81014
81243
|
}
|
|
@@ -81042,15 +81271,7 @@ function checkPermission(sql, permission) {
|
|
|
81042
81271
|
};
|
|
81043
81272
|
}
|
|
81044
81273
|
if (permission === "data-admin") {
|
|
81045
|
-
const allowedTypes = [
|
|
81046
|
-
"SELECT",
|
|
81047
|
-
"INSERT",
|
|
81048
|
-
"UPDATE",
|
|
81049
|
-
"DELETE",
|
|
81050
|
-
"SHOW",
|
|
81051
|
-
"DESCRIBE",
|
|
81052
|
-
"EXPLAIN"
|
|
81053
|
-
];
|
|
81274
|
+
const allowedTypes = ["SELECT", "INSERT", "UPDATE", "DELETE", "SHOW", "DESCRIBE", "EXPLAIN"];
|
|
81054
81275
|
if (allowedTypes.includes(classification.type)) {
|
|
81055
81276
|
return {
|
|
81056
81277
|
allowed: true,
|
|
@@ -81065,14 +81286,7 @@ function checkPermission(sql, permission) {
|
|
|
81065
81286
|
};
|
|
81066
81287
|
}
|
|
81067
81288
|
if (permission === "read-write") {
|
|
81068
|
-
const allowedTypes = [
|
|
81069
|
-
"SELECT",
|
|
81070
|
-
"INSERT",
|
|
81071
|
-
"UPDATE",
|
|
81072
|
-
"SHOW",
|
|
81073
|
-
"DESCRIBE",
|
|
81074
|
-
"EXPLAIN"
|
|
81075
|
-
];
|
|
81289
|
+
const allowedTypes = ["SELECT", "INSERT", "UPDATE", "SHOW", "DESCRIBE", "EXPLAIN"];
|
|
81076
81290
|
if (allowedTypes.includes(classification.type)) {
|
|
81077
81291
|
return {
|
|
81078
81292
|
allowed: true,
|
|
@@ -81363,7 +81577,7 @@ async function queryCommand(sql, options, command) {
|
|
|
81363
81577
|
throw new Error('Run "dbcli init" first');
|
|
81364
81578
|
}
|
|
81365
81579
|
if (config.connection.system === "mongodb") {
|
|
81366
|
-
return mongoQueryBranch(sql, options
|
|
81580
|
+
return mongoQueryBranch(sql, options, config);
|
|
81367
81581
|
}
|
|
81368
81582
|
const mainTable = extractMainTable(sql);
|
|
81369
81583
|
if (mainTable && config.schema && !options.noLimit) {
|
|
@@ -81417,10 +81631,12 @@ async function queryCommand(sql, options, command) {
|
|
|
81417
81631
|
}
|
|
81418
81632
|
function extractMainTable(sql) {
|
|
81419
81633
|
const match = sql.match(/\bFROM\s+[`"']?(\w+)[`"']?/i);
|
|
81420
|
-
return match
|
|
81634
|
+
return match?.[1] ?? null;
|
|
81421
81635
|
}
|
|
81422
81636
|
var SQL_PATTERN = /^\s*(SELECT|INSERT|UPDATE|DELETE|CREATE|DROP|ALTER|SHOW|DESCRIBE)\b/i;
|
|
81423
|
-
async function mongoQueryBranch(queryStr,
|
|
81637
|
+
async function mongoQueryBranch(queryStr, options, config) {
|
|
81638
|
+
const collection = options.collection;
|
|
81639
|
+
const format = options.format ?? "table";
|
|
81424
81640
|
if (SQL_PATTERN.test(queryStr)) {
|
|
81425
81641
|
console.error("\u9019\u662F MongoDB \u9023\u7DDA\uFF0C\u8ACB\u4F7F\u7528 JSON filter \u8A9E\u6CD5\u3002");
|
|
81426
81642
|
console.error(`\u7BC4\u4F8B\uFF1Adbcli query '{"field": "value"}' --collection <name>`);
|
|
@@ -81436,19 +81652,50 @@ async function mongoQueryBranch(queryStr, collection, config, format) {
|
|
|
81436
81652
|
console.error("MongoDB \u67E5\u8A62\u5FC5\u9808\u662F\u6709\u6548\u7684 JSON\uFF08object filter \u6216 array pipeline\uFF09");
|
|
81437
81653
|
process.exit(1);
|
|
81438
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
|
+
}
|
|
81439
81680
|
const mongoAdapter = AdapterFactory.createMongoDBAdapter(config.connection);
|
|
81440
81681
|
await mongoAdapter.connect();
|
|
81441
81682
|
try {
|
|
81442
81683
|
const result = await mongoAdapter.execute(queryStr, [collection]);
|
|
81443
|
-
const columnNames = result.rows
|
|
81684
|
+
const columnNames = result.rows[0] ? Object.keys(result.rows[0]) : [];
|
|
81685
|
+
const filterResult = blacklistValidator.filterColumns(collection, result.rows, columnNames);
|
|
81444
81686
|
const queryResult = {
|
|
81445
|
-
rows:
|
|
81446
|
-
rowCount:
|
|
81447
|
-
columnNames
|
|
81687
|
+
rows: filterResult.filteredRows,
|
|
81688
|
+
rowCount: filterResult.filteredRows.length,
|
|
81689
|
+
columnNames: columnNames.filter((col) => !filterResult.omittedColumns.includes(col))
|
|
81448
81690
|
};
|
|
81449
81691
|
const formatter = new QueryResultFormatter;
|
|
81450
81692
|
const output = formatter.format(queryResult, { format });
|
|
81693
|
+
const securityNote = blacklistValidator.buildSecurityNotification(collection, filterResult.omittedColumns);
|
|
81451
81694
|
console.log(output);
|
|
81695
|
+
if (securityNote) {
|
|
81696
|
+
console.log(`
|
|
81697
|
+
\u2139 ${securityNote}`);
|
|
81698
|
+
}
|
|
81452
81699
|
} finally {
|
|
81453
81700
|
await mongoAdapter.disconnect();
|
|
81454
81701
|
}
|
|
@@ -81786,8 +82033,23 @@ async function insertCommand(table, options, command) {
|
|
|
81786
82033
|
throw new Error('Run "dbcli init" to configure database connection');
|
|
81787
82034
|
}
|
|
81788
82035
|
if (config.connection.system === "mongodb") {
|
|
81789
|
-
|
|
81790
|
-
|
|
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
|
+
}
|
|
81791
82053
|
}
|
|
81792
82054
|
const adapter = AdapterFactory.createAdapter(config.connection);
|
|
81793
82055
|
await adapter.connect();
|
|
@@ -81860,7 +82122,11 @@ function parseWhereClause(whereClause) {
|
|
|
81860
82122
|
if (!match) {
|
|
81861
82123
|
throw new Error(`Cannot parse WHERE clause: "${part}". Use format "column=value" or "col1=val1 AND col2=val2"`);
|
|
81862
82124
|
}
|
|
81863
|
-
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
|
+
}
|
|
81864
82130
|
let value = valueStr.trim();
|
|
81865
82131
|
if (value.startsWith("'") && value.endsWith("'") || value.startsWith('"') && value.endsWith('"')) {
|
|
81866
82132
|
value = value.slice(1, -1);
|
|
@@ -81890,11 +82156,10 @@ async function updateCommand(table, options, command) {
|
|
|
81890
82156
|
if (!options.set || options.set.trim() === "") {
|
|
81891
82157
|
throw new Error(`UPDATE requires --set flag with JSON data (e.g. --set '{"name":"Bob"}')`);
|
|
81892
82158
|
}
|
|
81893
|
-
|
|
81894
|
-
|
|
81895
|
-
|
|
81896
|
-
|
|
81897
|
-
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');
|
|
81898
82163
|
}
|
|
81899
82164
|
let setData;
|
|
81900
82165
|
try {
|
|
@@ -81905,14 +82170,36 @@ async function updateCommand(table, options, command) {
|
|
|
81905
82170
|
if (!setData || typeof setData !== "object" || Array.isArray(setData)) {
|
|
81906
82171
|
throw new Error('JSON in --set must be an object (e.g. {"name":"Bob","email":"b@example.com"})');
|
|
81907
82172
|
}
|
|
81908
|
-
const configPath = resolveConfigPath(command, options);
|
|
81909
|
-
const config = await configModule.read(configPath);
|
|
81910
|
-
if (!config.connection) {
|
|
81911
|
-
throw new Error('Run "dbcli init" to configure database connection');
|
|
81912
|
-
}
|
|
81913
82173
|
if (config.connection?.system === "mongodb") {
|
|
81914
|
-
|
|
81915
|
-
|
|
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}`);
|
|
81916
82203
|
}
|
|
81917
82204
|
const adapter = AdapterFactory.createAdapter(config.connection);
|
|
81918
82205
|
await adapter.connect();
|
|
@@ -82013,23 +82300,48 @@ async function deleteCommand(table, options, command) {
|
|
|
82013
82300
|
if (!options.where || options.where.trim() === "") {
|
|
82014
82301
|
throw new Error('DELETE requires --where clause (e.g. --where "id=1")');
|
|
82015
82302
|
}
|
|
82016
|
-
let whereConditions;
|
|
82017
|
-
try {
|
|
82018
|
-
whereConditions = parseWhereClause2(options.where);
|
|
82019
|
-
} catch (error) {
|
|
82020
|
-
throw new Error(`WHERE clause parsing failed: ${error.message}`);
|
|
82021
|
-
}
|
|
82022
82303
|
const configPath = resolveConfigPath(command, options);
|
|
82023
82304
|
const config = await configModule.read(configPath);
|
|
82024
82305
|
if (!config.connection) {
|
|
82025
82306
|
throw new Error('Run "dbcli init" to configure database connection');
|
|
82026
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
|
+
}
|
|
82027
82317
|
if (config.connection?.system === "mongodb") {
|
|
82028
|
-
|
|
82029
|
-
|
|
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
|
+
}
|
|
82030
82339
|
}
|
|
82031
|
-
|
|
82032
|
-
|
|
82340
|
+
let whereConditions;
|
|
82341
|
+
try {
|
|
82342
|
+
whereConditions = parseWhereClause2(options.where);
|
|
82343
|
+
} catch (error) {
|
|
82344
|
+
throw new Error(`WHERE clause parsing failed: ${error.message}`);
|
|
82033
82345
|
}
|
|
82034
82346
|
const adapter = AdapterFactory.createAdapter(config.connection);
|
|
82035
82347
|
await adapter.connect();
|
|
@@ -82157,7 +82469,7 @@ async function exportCommand(sql, options, command) {
|
|
|
82157
82469
|
// src/commands/skill.ts
|
|
82158
82470
|
var {$ } = globalThis.Bun;
|
|
82159
82471
|
import * as path from "path";
|
|
82160
|
-
import { homedir } from "os";
|
|
82472
|
+
import { homedir as homedir2 } from "os";
|
|
82161
82473
|
function findPackageRoot() {
|
|
82162
82474
|
let dir = import.meta.dir;
|
|
82163
82475
|
for (let i = 0;i < 5; i++) {
|
|
@@ -82169,6 +82481,7 @@ function findPackageRoot() {
|
|
|
82169
82481
|
return path.resolve(import.meta.dir, "../..");
|
|
82170
82482
|
}
|
|
82171
82483
|
var SKILL_SOURCE_PATH = path.join(findPackageRoot(), "assets", "SKILL.md");
|
|
82484
|
+
var REFERENCE_SOURCE_PATH = path.join(findPackageRoot(), "assets", "reference.md");
|
|
82172
82485
|
var SUPPORTED_PLATFORMS = ["claude", "gemini", "copilot", "cursor"];
|
|
82173
82486
|
async function skillCommand(_program, options) {
|
|
82174
82487
|
try {
|
|
@@ -82176,7 +82489,12 @@ async function skillCommand(_program, options) {
|
|
|
82176
82489
|
if (!await skillFile.exists()) {
|
|
82177
82490
|
throw new Error(`Skill source not found: ${SKILL_SOURCE_PATH}`);
|
|
82178
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
|
+
}
|
|
82179
82496
|
const skillMarkdown = await skillFile.text();
|
|
82497
|
+
const referenceMarkdown = await refFile.text();
|
|
82180
82498
|
if (options.output) {
|
|
82181
82499
|
await Bun.file(options.output).write(skillMarkdown);
|
|
82182
82500
|
console.error(`Skill written to ${options.output}`);
|
|
@@ -82184,9 +82502,8 @@ async function skillCommand(_program, options) {
|
|
|
82184
82502
|
}
|
|
82185
82503
|
if (options.install) {
|
|
82186
82504
|
const installPath = getInstallPath(options.install);
|
|
82187
|
-
await
|
|
82188
|
-
|
|
82189
|
-
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 ?? "" }));
|
|
82190
82507
|
return;
|
|
82191
82508
|
}
|
|
82192
82509
|
console.log(skillMarkdown);
|
|
@@ -82219,7 +82536,7 @@ async function checkSkillUpdates() {
|
|
|
82219
82536
|
return outdated;
|
|
82220
82537
|
}
|
|
82221
82538
|
function getInstallPath(platform) {
|
|
82222
|
-
const home = process.env.HOME ||
|
|
82539
|
+
const home = process.env.HOME || homedir2();
|
|
82223
82540
|
const platformLower = platform.toLowerCase();
|
|
82224
82541
|
switch (platformLower) {
|
|
82225
82542
|
case "claude":
|
|
@@ -82234,6 +82551,20 @@ function getInstallPath(platform) {
|
|
|
82234
82551
|
throw new Error(`Unknown platform: ${platform}. Supported platforms: ${SUPPORTED_PLATFORMS.join(", ")}`);
|
|
82235
82552
|
}
|
|
82236
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
|
+
}
|
|
82237
82568
|
async function ensureDir(dirPath) {
|
|
82238
82569
|
try {
|
|
82239
82570
|
await $`mkdir -p ${dirPath}`.quiet();
|
|
@@ -82326,7 +82657,7 @@ async function blacklistTableRemove(tableName, configPath) {
|
|
|
82326
82657
|
}
|
|
82327
82658
|
const newBlacklist = {
|
|
82328
82659
|
...blacklist,
|
|
82329
|
-
tables: blacklist.tables.filter((
|
|
82660
|
+
tables: blacklist.tables.filter((t6) => t6 !== tableName)
|
|
82330
82661
|
};
|
|
82331
82662
|
await configModule.write(configPath, { ...config, blacklist: newBlacklist });
|
|
82332
82663
|
console.log(t_vars("blacklist.table_removed", { table: tableName }));
|
|
@@ -82461,21 +82792,21 @@ async function checkAction(table, options) {
|
|
|
82461
82792
|
const tables = await adapter.listTables();
|
|
82462
82793
|
const reports = [];
|
|
82463
82794
|
const skipped = [];
|
|
82464
|
-
for (const
|
|
82465
|
-
if (blacklistedTables.has(
|
|
82466
|
-
skipped.push(`${
|
|
82795
|
+
for (const t6 of tables) {
|
|
82796
|
+
if (blacklistedTables.has(t6.name.toLowerCase())) {
|
|
82797
|
+
skipped.push(`${t6.name} (blacklisted)`);
|
|
82467
82798
|
continue;
|
|
82468
82799
|
}
|
|
82469
|
-
if (
|
|
82470
|
-
skipped.push(`${
|
|
82800
|
+
if (t6.tableType === "view") {
|
|
82801
|
+
skipped.push(`${t6.name} (view)`);
|
|
82471
82802
|
continue;
|
|
82472
82803
|
}
|
|
82473
|
-
const category = getSizeCategory(
|
|
82804
|
+
const category = getSizeCategory(t6.estimatedRowCount);
|
|
82474
82805
|
if (category === "huge" && !options.includeLarge) {
|
|
82475
|
-
skipped.push(`${
|
|
82806
|
+
skipped.push(`${t6.name} (~${(t6.estimatedRowCount || 0).toLocaleString()} rows, huge)`);
|
|
82476
82807
|
continue;
|
|
82477
82808
|
}
|
|
82478
|
-
const schema = await adapter.getTableSchema(
|
|
82809
|
+
const schema = await adapter.getTableSchema(t6.name);
|
|
82479
82810
|
const report = await checker.check(schema, {
|
|
82480
82811
|
checks: checkTypes,
|
|
82481
82812
|
sample: sampleSize,
|
|
@@ -82559,31 +82890,49 @@ var ALLOWED_FORMATS5 = ["json", "table"];
|
|
|
82559
82890
|
function compareSnapshots(before, after) {
|
|
82560
82891
|
const beforeTables = new Set(Object.keys(before.tables));
|
|
82561
82892
|
const afterTables = new Set(Object.keys(after.tables));
|
|
82562
|
-
const addedTables = Array.from(afterTables).filter((
|
|
82563
|
-
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));
|
|
82564
82895
|
const addedColumns = [];
|
|
82565
82896
|
const removedColumns = [];
|
|
82566
82897
|
const modifiedColumns = [];
|
|
82567
82898
|
const indexChanges = [];
|
|
82568
82899
|
for (const tableName of addedTables) {
|
|
82569
|
-
|
|
82570
|
-
|
|
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
|
+
});
|
|
82571
82910
|
}
|
|
82572
82911
|
}
|
|
82573
82912
|
for (const tableName of removedTables) {
|
|
82574
|
-
|
|
82913
|
+
const removed = before.tables[tableName];
|
|
82914
|
+
if (!removed)
|
|
82915
|
+
continue;
|
|
82916
|
+
for (const col of removed.columns) {
|
|
82575
82917
|
removedColumns.push({ table: tableName, column: col.name, type: col.type });
|
|
82576
82918
|
}
|
|
82577
82919
|
}
|
|
82578
|
-
const commonTables = Array.from(afterTables).filter((
|
|
82920
|
+
const commonTables = Array.from(afterTables).filter((t6) => beforeTables.has(t6));
|
|
82579
82921
|
for (const tableName of commonTables) {
|
|
82580
82922
|
const beforeTable = before.tables[tableName];
|
|
82581
82923
|
const afterTable = after.tables[tableName];
|
|
82924
|
+
if (!beforeTable || !afterTable)
|
|
82925
|
+
continue;
|
|
82582
82926
|
const beforeColMap = new Map(beforeTable.columns.map((c) => [c.name, c]));
|
|
82583
82927
|
const afterColMap = new Map(afterTable.columns.map((c) => [c.name, c]));
|
|
82584
82928
|
for (const [name, col] of afterColMap) {
|
|
82585
82929
|
if (!beforeColMap.has(name)) {
|
|
82586
|
-
addedColumns.push({
|
|
82930
|
+
addedColumns.push({
|
|
82931
|
+
table: tableName,
|
|
82932
|
+
column: name,
|
|
82933
|
+
type: col.type,
|
|
82934
|
+
nullable: col.nullable
|
|
82935
|
+
});
|
|
82587
82936
|
}
|
|
82588
82937
|
}
|
|
82589
82938
|
for (const [name, col] of beforeColMap) {
|
|
@@ -82653,11 +83002,11 @@ async function diffAction(options) {
|
|
|
82653
83002
|
tables: {},
|
|
82654
83003
|
createdAt: new Date().toISOString()
|
|
82655
83004
|
};
|
|
82656
|
-
for (const
|
|
82657
|
-
if (
|
|
83005
|
+
for (const t6 of tables) {
|
|
83006
|
+
if (t6.tableType === "view")
|
|
82658
83007
|
continue;
|
|
82659
|
-
const schema = await adapter.getTableSchema(
|
|
82660
|
-
currentSnapshot.tables[
|
|
83008
|
+
const schema = await adapter.getTableSchema(t6.name);
|
|
83009
|
+
currentSnapshot.tables[t6.name] = {
|
|
82661
83010
|
name: schema.name,
|
|
82662
83011
|
columns: schema.columns,
|
|
82663
83012
|
indexes: schema.indexes || []
|
|
@@ -82770,7 +83119,7 @@ var statusCommand = new Command("status").description("Show current configuratio
|
|
|
82770
83119
|
// src/commands/doctor.ts
|
|
82771
83120
|
init_validation();
|
|
82772
83121
|
init_schema_path();
|
|
82773
|
-
import { join as
|
|
83122
|
+
import { join as join11 } from "path";
|
|
82774
83123
|
import { resolveSrv as resolveSrv2 } from "dns/promises";
|
|
82775
83124
|
var ALLOWED_FORMATS7 = ["text", "json"];
|
|
82776
83125
|
var SENSITIVE_PATTERNS = [
|
|
@@ -82820,7 +83169,9 @@ var runDoctorChecks = {
|
|
|
82820
83169
|
},
|
|
82821
83170
|
async checkLatestVersion(currentVersion) {
|
|
82822
83171
|
try {
|
|
82823
|
-
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
|
+
});
|
|
82824
83175
|
if (!response.ok)
|
|
82825
83176
|
throw new Error(`HTTP ${response.status}`);
|
|
82826
83177
|
const data = await response.json();
|
|
@@ -82842,7 +83193,7 @@ var runDoctorChecks = {
|
|
|
82842
83193
|
}
|
|
82843
83194
|
},
|
|
82844
83195
|
async checkConfigExists(configPath, existsFn) {
|
|
82845
|
-
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();
|
|
82846
83197
|
return {
|
|
82847
83198
|
group: "Configuration",
|
|
82848
83199
|
label: "Config exists",
|
|
@@ -82979,7 +83330,7 @@ var runDoctorChecks = {
|
|
|
82979
83330
|
}
|
|
82980
83331
|
},
|
|
82981
83332
|
checkLargeTables(tables) {
|
|
82982
|
-
const large = tables.filter((
|
|
83333
|
+
const large = tables.filter((t6) => (t6.estimatedRowCount ?? 0) > 1e6);
|
|
82983
83334
|
if (large.length === 0) {
|
|
82984
83335
|
return {
|
|
82985
83336
|
group: "Connection & Data",
|
|
@@ -82988,7 +83339,7 @@ var runDoctorChecks = {
|
|
|
82988
83339
|
message: "No tables exceed 1M rows"
|
|
82989
83340
|
};
|
|
82990
83341
|
}
|
|
82991
|
-
const list = large.map((
|
|
83342
|
+
const list = large.map((t6) => `${t6.name} (${((t6.estimatedRowCount ?? 0) / 1e6).toFixed(1)}M rows)`).join(", ");
|
|
82992
83343
|
return {
|
|
82993
83344
|
group: "Connection & Data",
|
|
82994
83345
|
label: "Large tables",
|
|
@@ -82998,7 +83349,8 @@ var runDoctorChecks = {
|
|
|
82998
83349
|
},
|
|
82999
83350
|
async checkV2Config(configPath) {
|
|
83000
83351
|
const results = [];
|
|
83001
|
-
const
|
|
83352
|
+
const storagePath = await resolveConfigStoragePath(configPath);
|
|
83353
|
+
const configFile = Bun.file(join11(storagePath, "config.json"));
|
|
83002
83354
|
if (!await configFile.exists())
|
|
83003
83355
|
return results;
|
|
83004
83356
|
let raw;
|
|
@@ -83038,7 +83390,7 @@ var runDoctorChecks = {
|
|
|
83038
83390
|
}
|
|
83039
83391
|
for (const [name, conn] of Object.entries(config.connections)) {
|
|
83040
83392
|
if (conn.envFile) {
|
|
83041
|
-
const envPath =
|
|
83393
|
+
const envPath = join11(storagePath, conn.envFile);
|
|
83042
83394
|
const exists = await Bun.file(envPath).exists();
|
|
83043
83395
|
results.push({
|
|
83044
83396
|
group: "Configuration",
|
|
@@ -83074,7 +83426,9 @@ var runDoctorChecks = {
|
|
|
83074
83426
|
};
|
|
83075
83427
|
async function collectMongoDoctorResults(config) {
|
|
83076
83428
|
const results = [];
|
|
83077
|
-
const
|
|
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);
|
|
83078
83432
|
if (srvCheck) {
|
|
83079
83433
|
results.push(srvCheck);
|
|
83080
83434
|
if (srvCheck.status === "error") {
|
|
@@ -83082,8 +83436,8 @@ async function collectMongoDoctorResults(config) {
|
|
|
83082
83436
|
}
|
|
83083
83437
|
}
|
|
83084
83438
|
const adapter = AdapterFactory.createMongoDBAdapter(config.connection);
|
|
83085
|
-
await adapter.connect();
|
|
83086
83439
|
try {
|
|
83440
|
+
await adapter.connect();
|
|
83087
83441
|
results.push({
|
|
83088
83442
|
group: "Connection & Data",
|
|
83089
83443
|
label: "Connection",
|
|
@@ -83099,10 +83453,20 @@ async function collectMongoDoctorResults(config) {
|
|
|
83099
83453
|
message: `MongoDB ${version}`
|
|
83100
83454
|
});
|
|
83101
83455
|
} catch {}
|
|
83102
|
-
const collections = await adapter.
|
|
83103
|
-
|
|
83104
|
-
|
|
83105
|
-
|
|
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
|
|
83106
83470
|
}))));
|
|
83107
83471
|
results.push({
|
|
83108
83472
|
group: "Connection & Data",
|
|
@@ -83110,11 +83474,18 @@ async function collectMongoDoctorResults(config) {
|
|
|
83110
83474
|
status: "pass",
|
|
83111
83475
|
message: collections.length === 0 ? "No collections found" : `Found ${collections.length} collection(s)`
|
|
83112
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) {
|
|
83113
83484
|
results.push({
|
|
83114
83485
|
group: "Connection & Data",
|
|
83115
|
-
label: "
|
|
83116
|
-
status: "
|
|
83117
|
-
message:
|
|
83486
|
+
label: "Connection",
|
|
83487
|
+
status: "error",
|
|
83488
|
+
message: `Connection failed: ${error.message}`
|
|
83118
83489
|
});
|
|
83119
83490
|
} finally {
|
|
83120
83491
|
await adapter.disconnect();
|
|
@@ -83126,11 +83497,12 @@ var doctorCommand = new Command("doctor").description("Run diagnostic checks on
|
|
|
83126
83497
|
const logger = getLogger();
|
|
83127
83498
|
const results = [];
|
|
83128
83499
|
const configPath = resolveConfigPath(doctorCommand);
|
|
83500
|
+
const storagePath = await resolveConfigStoragePath(configPath);
|
|
83129
83501
|
const bunVersion = process.versions.bun ?? "unknown";
|
|
83130
83502
|
const requiredBun = package_default.engines?.bun?.replace(">=", "") ?? "1.3.3";
|
|
83131
83503
|
results.push(runDoctorChecks.checkBunVersion(bunVersion, requiredBun));
|
|
83132
83504
|
results.push(await runDoctorChecks.checkLatestVersion(package_default.version));
|
|
83133
|
-
const configExists = await runDoctorChecks.checkConfigExists(
|
|
83505
|
+
const configExists = await runDoctorChecks.checkConfigExists(storagePath);
|
|
83134
83506
|
results.push(configExists);
|
|
83135
83507
|
if (configExists.status !== "error") {
|
|
83136
83508
|
try {
|
|
@@ -83157,7 +83529,10 @@ var doctorCommand = new Command("doctor").description("Run diagnostic checks on
|
|
|
83157
83529
|
}
|
|
83158
83530
|
try {
|
|
83159
83531
|
if (config.connection.system === "mongodb") {
|
|
83160
|
-
results.push(...await collectMongoDoctorResults(
|
|
83532
|
+
results.push(...await collectMongoDoctorResults({
|
|
83533
|
+
...config,
|
|
83534
|
+
blacklistedColumns
|
|
83535
|
+
}));
|
|
83161
83536
|
} else {
|
|
83162
83537
|
const adapter = AdapterFactory.createAdapter(config.connection);
|
|
83163
83538
|
await adapter.connect();
|
|
@@ -83177,8 +83552,8 @@ var doctorCommand = new Command("doctor").description("Run diagnostic checks on
|
|
|
83177
83552
|
try {
|
|
83178
83553
|
const tables = await adapter.listTables();
|
|
83179
83554
|
const tableColumns = new Map;
|
|
83180
|
-
for (const
|
|
83181
|
-
tableColumns.set(
|
|
83555
|
+
for (const t6 of tables) {
|
|
83556
|
+
tableColumns.set(t6.name, t6.columns.map((c) => c.name));
|
|
83182
83557
|
}
|
|
83183
83558
|
results.push(runDoctorChecks.checkBlacklistCompleteness(tableColumns, blacklistedColumns));
|
|
83184
83559
|
results.push(runDoctorChecks.checkLargeTables(tables));
|
|
@@ -83187,7 +83562,7 @@ var doctorCommand = new Command("doctor").description("Run diagnostic checks on
|
|
|
83187
83562
|
}
|
|
83188
83563
|
try {
|
|
83189
83564
|
const schemaConnName = await getSchemaIsolationConnectionName(configPath);
|
|
83190
|
-
const indexPath =
|
|
83565
|
+
const indexPath = join11(resolveSchemaPath(storagePath, schemaConnName), "index.json");
|
|
83191
83566
|
const indexFile = Bun.file(indexPath);
|
|
83192
83567
|
let indexParsed = null;
|
|
83193
83568
|
if (await indexFile.exists()) {
|
|
@@ -83229,8 +83604,8 @@ var doctorCommand = new Command("doctor").description("Run diagnostic checks on
|
|
|
83229
83604
|
});
|
|
83230
83605
|
|
|
83231
83606
|
// src/commands/completion.ts
|
|
83232
|
-
import { join as
|
|
83233
|
-
import { homedir as
|
|
83607
|
+
import { join as join12 } from "path";
|
|
83608
|
+
import { homedir as homedir3 } from "os";
|
|
83234
83609
|
function extractCommands(program2) {
|
|
83235
83610
|
return program2.commands.map((cmd) => ({
|
|
83236
83611
|
name: cmd.name(),
|
|
@@ -83309,10 +83684,7 @@ _dbcli
|
|
|
83309
83684
|
`;
|
|
83310
83685
|
}
|
|
83311
83686
|
function generateFishCompletion(commands, globalOptions) {
|
|
83312
|
-
const lines2 = [
|
|
83313
|
-
"# dbcli fish completion \u2014 auto-generated, do not edit",
|
|
83314
|
-
""
|
|
83315
|
-
];
|
|
83687
|
+
const lines2 = ["# dbcli fish completion \u2014 auto-generated, do not edit", ""];
|
|
83316
83688
|
for (const opt of globalOptions) {
|
|
83317
83689
|
const longName = opt.replace(/^--/, "");
|
|
83318
83690
|
lines2.push(`complete -c dbcli -n '__fish_use_subcommand' -l ${longName} -d '${opt}'`);
|
|
@@ -83331,14 +83703,14 @@ function generateFishCompletion(commands, globalOptions) {
|
|
|
83331
83703
|
`;
|
|
83332
83704
|
}
|
|
83333
83705
|
function getInstallPath2(shell) {
|
|
83334
|
-
const home =
|
|
83706
|
+
const home = homedir3();
|
|
83335
83707
|
switch (shell) {
|
|
83336
83708
|
case "bash":
|
|
83337
|
-
return
|
|
83709
|
+
return join12(home, ".bashrc");
|
|
83338
83710
|
case "zsh":
|
|
83339
|
-
return
|
|
83711
|
+
return join12(home, ".zshrc");
|
|
83340
83712
|
case "fish":
|
|
83341
|
-
return
|
|
83713
|
+
return join12(home, ".config", "fish", "completions", "dbcli.fish");
|
|
83342
83714
|
default:
|
|
83343
83715
|
throw new Error(`Unsupported shell: ${shell}. Supported: bash, zsh, fish`);
|
|
83344
83716
|
}
|
|
@@ -83358,7 +83730,7 @@ var MARKER_END = "# <<< dbcli completion <<<";
|
|
|
83358
83730
|
async function installCompletion(shell, script) {
|
|
83359
83731
|
const targetPath = getInstallPath2(shell);
|
|
83360
83732
|
if (shell === "fish") {
|
|
83361
|
-
const dir =
|
|
83733
|
+
const dir = join12(homedir3(), ".config", "fish", "completions");
|
|
83362
83734
|
await Bun.$`mkdir -p ${dir}`.quiet();
|
|
83363
83735
|
await Bun.file(targetPath).write(script);
|
|
83364
83736
|
console.log(colors.success(`\u2713 Fish completion installed to ${targetPath}`));
|
|
@@ -83585,8 +83957,8 @@ ${t("upgrade.failed")}`));
|
|
|
83585
83957
|
|
|
83586
83958
|
// src/commands/shell.ts
|
|
83587
83959
|
import { createInterface as createInterface2 } from "readline";
|
|
83588
|
-
import { join as
|
|
83589
|
-
import { homedir as
|
|
83960
|
+
import { join as join13 } from "path";
|
|
83961
|
+
import { homedir as homedir4 } from "os";
|
|
83590
83962
|
|
|
83591
83963
|
// src/core/repl/types.ts
|
|
83592
83964
|
var SQL_KEYWORDS_FOR_DETECTION = [
|
|
@@ -84106,7 +84478,7 @@ class ReplEngine {
|
|
|
84106
84478
|
const tableName = this.extractTableName(sql);
|
|
84107
84479
|
if (tableName) {
|
|
84108
84480
|
const blacklistedTables = this.config.blacklist.tables ?? [];
|
|
84109
|
-
const isBlacklisted = blacklistedTables.some((
|
|
84481
|
+
const isBlacklisted = blacklistedTables.some((t6) => t6.toLowerCase() === tableName.toLowerCase());
|
|
84110
84482
|
if (isBlacklisted) {
|
|
84111
84483
|
return {
|
|
84112
84484
|
action: "continue",
|
|
@@ -84181,13 +84553,7 @@ var TABLE_POSITION_KEYWORDS = new Set([
|
|
|
84181
84553
|
"UPDATE",
|
|
84182
84554
|
"TABLE"
|
|
84183
84555
|
]);
|
|
84184
|
-
var COMMANDS_TAKING_TABLE_ARG = new Set([
|
|
84185
|
-
"schema",
|
|
84186
|
-
"insert",
|
|
84187
|
-
"update",
|
|
84188
|
-
"delete",
|
|
84189
|
-
"check"
|
|
84190
|
-
]);
|
|
84556
|
+
var COMMANDS_TAKING_TABLE_ARG = new Set(["schema", "insert", "update", "delete", "check"]);
|
|
84191
84557
|
function createCompleter(ctx) {
|
|
84192
84558
|
const allTableNames = ctx.tableNames;
|
|
84193
84559
|
const allColumns = Object.values(ctx.columnsByTable).flat();
|
|
@@ -84261,7 +84627,7 @@ function extractTableFromLine(line, tableNames) {
|
|
|
84261
84627
|
if (fromIdx >= 0) {
|
|
84262
84628
|
const afterFrom = line.slice(fromIdx + 5).trim().split(/\s+/)[0];
|
|
84263
84629
|
const candidate = afterFrom.replace(/[;,]/g, "").toLowerCase();
|
|
84264
|
-
return tableNames.find((
|
|
84630
|
+
return tableNames.find((t6) => t6.toLowerCase() === candidate);
|
|
84265
84631
|
}
|
|
84266
84632
|
return;
|
|
84267
84633
|
}
|
|
@@ -84311,7 +84677,7 @@ class MongoShellAdapter {
|
|
|
84311
84677
|
}
|
|
84312
84678
|
|
|
84313
84679
|
// src/commands/shell.ts
|
|
84314
|
-
var HISTORY_PATH =
|
|
84680
|
+
var HISTORY_PATH = join13(homedir4(), ".dbcli_history");
|
|
84315
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) => {
|
|
84316
84682
|
const configPath = resolveConfigPath(command);
|
|
84317
84683
|
await runShell(options, configPath);
|
|
@@ -84325,7 +84691,8 @@ async function runShell(options, configPath) {
|
|
|
84325
84691
|
process.exit(1);
|
|
84326
84692
|
}
|
|
84327
84693
|
const isMongoDB = config.connection.system === "mongodb";
|
|
84328
|
-
const
|
|
84694
|
+
const connectionOpts = config.connection;
|
|
84695
|
+
const adapter = isMongoDB ? new MongoShellAdapter(AdapterFactory.createMongoDBAdapter(connectionOpts)) : AdapterFactory.createAdapter(connectionOpts);
|
|
84329
84696
|
try {
|
|
84330
84697
|
await adapter.connect();
|
|
84331
84698
|
} catch (error) {
|
|
@@ -84333,7 +84700,7 @@ async function runShell(options, configPath) {
|
|
|
84333
84700
|
process.exit(1);
|
|
84334
84701
|
}
|
|
84335
84702
|
let tableNames = [];
|
|
84336
|
-
|
|
84703
|
+
const columnsByTable = {};
|
|
84337
84704
|
if (isMongoDB) {
|
|
84338
84705
|
const collections = await adapter.listTables();
|
|
84339
84706
|
tableNames = collections.map((collection) => collection.name);
|
|
@@ -84503,25 +84870,25 @@ class PostgreSQLDDLGenerator {
|
|
|
84503
84870
|
alterColumn(options) {
|
|
84504
84871
|
const statements = [];
|
|
84505
84872
|
const warnings = [];
|
|
84506
|
-
const
|
|
84873
|
+
const t6 = q(options.table);
|
|
84507
84874
|
const c = q(options.column);
|
|
84508
84875
|
if (options.type) {
|
|
84509
|
-
statements.push(`ALTER TABLE ${
|
|
84876
|
+
statements.push(`ALTER TABLE ${t6} ALTER COLUMN ${c} TYPE ${options.type.toUpperCase()};`);
|
|
84510
84877
|
}
|
|
84511
84878
|
if (options.rename) {
|
|
84512
|
-
statements.push(`ALTER TABLE ${
|
|
84879
|
+
statements.push(`ALTER TABLE ${t6} RENAME COLUMN ${c} TO ${q(options.rename)};`);
|
|
84513
84880
|
}
|
|
84514
84881
|
if (options.setDefault !== undefined) {
|
|
84515
|
-
statements.push(`ALTER TABLE ${
|
|
84882
|
+
statements.push(`ALTER TABLE ${t6} ALTER COLUMN ${c} SET DEFAULT ${options.setDefault};`);
|
|
84516
84883
|
}
|
|
84517
84884
|
if (options.dropDefault) {
|
|
84518
|
-
statements.push(`ALTER TABLE ${
|
|
84885
|
+
statements.push(`ALTER TABLE ${t6} ALTER COLUMN ${c} DROP DEFAULT;`);
|
|
84519
84886
|
}
|
|
84520
84887
|
if (options.setNullable) {
|
|
84521
|
-
statements.push(`ALTER TABLE ${
|
|
84888
|
+
statements.push(`ALTER TABLE ${t6} ALTER COLUMN ${c} DROP NOT NULL;`);
|
|
84522
84889
|
}
|
|
84523
84890
|
if (options.dropNullable) {
|
|
84524
|
-
statements.push(`ALTER TABLE ${
|
|
84891
|
+
statements.push(`ALTER TABLE ${t6} ALTER COLUMN ${c} SET NOT NULL;`);
|
|
84525
84892
|
}
|
|
84526
84893
|
if (statements.length === 0) {
|
|
84527
84894
|
warnings.push("No alter operations specified");
|
|
@@ -84543,14 +84910,14 @@ class PostgreSQLDDLGenerator {
|
|
|
84543
84910
|
return { sql: `DROP INDEX ${q(indexName)};`, warnings: [] };
|
|
84544
84911
|
}
|
|
84545
84912
|
addConstraint(constraint) {
|
|
84546
|
-
const
|
|
84913
|
+
const t6 = q(constraint.table);
|
|
84547
84914
|
const warnings = [];
|
|
84548
84915
|
switch (constraint.type) {
|
|
84549
84916
|
case "foreign_key": {
|
|
84550
84917
|
const name = constraint.name || `fk_${constraint.table}_${constraint.column}`;
|
|
84551
84918
|
const onDelete = constraint.onDelete ? ` ON DELETE ${constraint.onDelete.toUpperCase().replace("_", " ")}` : "";
|
|
84552
84919
|
return {
|
|
84553
|
-
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};`,
|
|
84554
84921
|
warnings
|
|
84555
84922
|
};
|
|
84556
84923
|
}
|
|
@@ -84558,14 +84925,14 @@ class PostgreSQLDDLGenerator {
|
|
|
84558
84925
|
const name = constraint.name || `uq_${constraint.table}_${constraint.columns.join("_")}`;
|
|
84559
84926
|
const cols = constraint.columns.map(q).join(", ");
|
|
84560
84927
|
return {
|
|
84561
|
-
sql: `ALTER TABLE ${
|
|
84928
|
+
sql: `ALTER TABLE ${t6} ADD CONSTRAINT ${q(name)} UNIQUE (${cols});`,
|
|
84562
84929
|
warnings
|
|
84563
84930
|
};
|
|
84564
84931
|
}
|
|
84565
84932
|
case "check": {
|
|
84566
84933
|
const name = constraint.name || `ck_${constraint.table}`;
|
|
84567
84934
|
return {
|
|
84568
|
-
sql: `ALTER TABLE ${
|
|
84935
|
+
sql: `ALTER TABLE ${t6} ADD CONSTRAINT ${q(name)} CHECK (${constraint.expression});`,
|
|
84569
84936
|
warnings
|
|
84570
84937
|
};
|
|
84571
84938
|
}
|
|
@@ -84668,19 +85035,19 @@ class MySQLDDLGenerator {
|
|
|
84668
85035
|
alterColumn(options) {
|
|
84669
85036
|
const statements = [];
|
|
84670
85037
|
const warnings = [];
|
|
84671
|
-
const
|
|
85038
|
+
const t6 = q2(options.table);
|
|
84672
85039
|
const c = q2(options.column);
|
|
84673
85040
|
if (options.type) {
|
|
84674
85041
|
const nullable = options.dropNullable ? " NOT NULL" : "";
|
|
84675
85042
|
const def = options.setDefault !== undefined ? ` DEFAULT ${options.setDefault}` : "";
|
|
84676
|
-
statements.push(`ALTER TABLE ${
|
|
85043
|
+
statements.push(`ALTER TABLE ${t6} MODIFY COLUMN ${c} ${options.type.toUpperCase()}${nullable}${def};`);
|
|
84677
85044
|
warnings.push("MySQL MODIFY COLUMN resets column attributes not explicitly specified");
|
|
84678
85045
|
} else {
|
|
84679
85046
|
if (options.setDefault !== undefined) {
|
|
84680
|
-
statements.push(`ALTER TABLE ${
|
|
85047
|
+
statements.push(`ALTER TABLE ${t6} ALTER COLUMN ${c} SET DEFAULT ${options.setDefault};`);
|
|
84681
85048
|
}
|
|
84682
85049
|
if (options.dropDefault) {
|
|
84683
|
-
statements.push(`ALTER TABLE ${
|
|
85050
|
+
statements.push(`ALTER TABLE ${t6} ALTER COLUMN ${c} DROP DEFAULT;`);
|
|
84684
85051
|
}
|
|
84685
85052
|
if (options.setNullable) {
|
|
84686
85053
|
warnings.push("MySQL requires MODIFY COLUMN with full type to change nullability \u2014 use --type to specify");
|
|
@@ -84690,7 +85057,7 @@ class MySQLDDLGenerator {
|
|
|
84690
85057
|
}
|
|
84691
85058
|
}
|
|
84692
85059
|
if (options.rename) {
|
|
84693
|
-
statements.push(`ALTER TABLE ${
|
|
85060
|
+
statements.push(`ALTER TABLE ${t6} RENAME COLUMN ${c} TO ${q2(options.rename)};`);
|
|
84694
85061
|
}
|
|
84695
85062
|
if (statements.length === 0 && warnings.length === 0) {
|
|
84696
85063
|
warnings.push("No alter operations specified");
|
|
@@ -84716,14 +85083,14 @@ class MySQLDDLGenerator {
|
|
|
84716
85083
|
};
|
|
84717
85084
|
}
|
|
84718
85085
|
addConstraint(constraint) {
|
|
84719
|
-
const
|
|
85086
|
+
const t6 = q2(constraint.table);
|
|
84720
85087
|
const warnings = [];
|
|
84721
85088
|
switch (constraint.type) {
|
|
84722
85089
|
case "foreign_key": {
|
|
84723
85090
|
const name = constraint.name || `fk_${constraint.table}_${constraint.column}`;
|
|
84724
85091
|
const onDelete = constraint.onDelete ? ` ON DELETE ${constraint.onDelete.toUpperCase().replace("_", " ")}` : "";
|
|
84725
85092
|
return {
|
|
84726
|
-
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};`,
|
|
84727
85094
|
warnings
|
|
84728
85095
|
};
|
|
84729
85096
|
}
|
|
@@ -84731,14 +85098,14 @@ class MySQLDDLGenerator {
|
|
|
84731
85098
|
const name = constraint.name || `uq_${constraint.table}_${constraint.columns.join("_")}`;
|
|
84732
85099
|
const cols = constraint.columns.map(q2).join(", ");
|
|
84733
85100
|
return {
|
|
84734
|
-
sql: `ALTER TABLE ${
|
|
85101
|
+
sql: `ALTER TABLE ${t6} ADD CONSTRAINT ${q2(name)} UNIQUE (${cols});`,
|
|
84735
85102
|
warnings
|
|
84736
85103
|
};
|
|
84737
85104
|
}
|
|
84738
85105
|
case "check": {
|
|
84739
85106
|
const name = constraint.name || `ck_${constraint.table}`;
|
|
84740
85107
|
return {
|
|
84741
|
-
sql: `ALTER TABLE ${
|
|
85108
|
+
sql: `ALTER TABLE ${t6} ADD CONSTRAINT ${q2(name)} CHECK (${constraint.expression});`,
|
|
84742
85109
|
warnings: ["CHECK constraints enforced in MySQL 8.0.16+ and MariaDB 10.2.1+ only"]
|
|
84743
85110
|
};
|
|
84744
85111
|
}
|
|
@@ -84753,13 +85120,17 @@ class MySQLDDLGenerator {
|
|
|
84753
85120
|
addEnum(_definition) {
|
|
84754
85121
|
return {
|
|
84755
85122
|
sql: "",
|
|
84756
|
-
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
|
+
]
|
|
84757
85126
|
};
|
|
84758
85127
|
}
|
|
84759
85128
|
alterEnum(_name, _addValue) {
|
|
84760
85129
|
return {
|
|
84761
85130
|
sql: "",
|
|
84762
|
-
warnings: [
|
|
85131
|
+
warnings: [
|
|
85132
|
+
"MySQL has no standalone ENUM type \u2014 use ALTER TABLE MODIFY COLUMN to change enum values"
|
|
85133
|
+
]
|
|
84763
85134
|
};
|
|
84764
85135
|
}
|
|
84765
85136
|
dropEnum(_name) {
|
|
@@ -85247,7 +85618,7 @@ addExecOpts(migrateCommand.command("drop-enum <name>").description(t("migrate.dr
|
|
|
85247
85618
|
});
|
|
85248
85619
|
|
|
85249
85620
|
// src/commands/use.ts
|
|
85250
|
-
import { join as
|
|
85621
|
+
import { join as join14 } from "path";
|
|
85251
85622
|
async function switchDefault(configPath, name, config) {
|
|
85252
85623
|
if (!config.connections[name]) {
|
|
85253
85624
|
const available = Object.keys(config.connections).join(", ");
|
|
@@ -85269,15 +85640,41 @@ function listConnectionsForDisplay(config) {
|
|
|
85269
85640
|
});
|
|
85270
85641
|
}
|
|
85271
85642
|
async function ensureV2Config(configPath) {
|
|
85272
|
-
const
|
|
85273
|
-
|
|
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()) {
|
|
85274
85647
|
throw new ConfigError(t("init.config_not_found"));
|
|
85275
85648
|
}
|
|
85276
|
-
|
|
85277
|
-
|
|
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;
|
|
85278
85676
|
throw new ConfigError(t("use.requires_v2"));
|
|
85279
85677
|
}
|
|
85280
|
-
return readV2Config(configPath);
|
|
85281
85678
|
}
|
|
85282
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) => {
|
|
85283
85680
|
try {
|
|
@@ -85306,7 +85703,7 @@ var useCommand = new Command("use").description("Switch or display the default d
|
|
|
85306
85703
|
});
|
|
85307
85704
|
|
|
85308
85705
|
// src/cli.ts
|
|
85309
|
-
import { join as
|
|
85706
|
+
import { join as join15 } from "path";
|
|
85310
85707
|
var _bgVersionCheckResult;
|
|
85311
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)");
|
|
85312
85709
|
program2.hook("preAction", (thisCommand, actionCommand) => {
|
|
@@ -85332,7 +85729,7 @@ program2.hook("preAction", (thisCommand, actionCommand) => {
|
|
|
85332
85729
|
try {
|
|
85333
85730
|
let cache = null;
|
|
85334
85731
|
try {
|
|
85335
|
-
const cacheFile = Bun.file(
|
|
85732
|
+
const cacheFile = Bun.file(join15(configPath, "version-check.json"));
|
|
85336
85733
|
if (await cacheFile.exists()) {
|
|
85337
85734
|
cache = await cacheFile.json();
|
|
85338
85735
|
}
|