@carllee1983/dbcli 1.56.0 → 1.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/core.mjs CHANGED
@@ -118,24 +118,24 @@ var require_picocolors = __commonJS((exports, module) => {
118
118
 
119
119
  // node_modules/lru-cache/dist/esm/node/index.min.js
120
120
  import { tracingChannel as j, channel as G } from "diagnostics_channel";
121
- var w, W, C, D = () => w.hasSubscribers || W.hasSubscribers, I, L, P = (u, e, t, i) => {
122
- typeof L.emitWarning == "function" ? L.emitWarning(u, e, t, i) : console.error(`[${t}] ${e}: ${u}`);
121
+ var w, W, C, D = () => w.hasSubscribers || W.hasSubscribers, I, L, P = (u, e, t2, i) => {
122
+ typeof L.emitWarning == "function" ? L.emitWarning(u, e, t2, i) : console.error(`[${t2}] ${e}: ${u}`);
123
123
  }, H = (u) => !I.has(u), T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), U = (u) => T(u) ? u <= Math.pow(2, 8) ? Uint8Array : u <= Math.pow(2, 16) ? Uint16Array : u <= Math.pow(2, 32) ? Uint32Array : u <= Number.MAX_SAFE_INTEGER ? O : null : null, O, R = class u {
124
124
  heap;
125
125
  length;
126
126
  static #o = false;
127
127
  static create(e) {
128
- let t = U(e);
129
- if (!t)
128
+ let t2 = U(e);
129
+ if (!t2)
130
130
  return [];
131
131
  u.#o = true;
132
- let i = new u(e, t);
132
+ let i = new u(e, t2);
133
133
  return u.#o = false, i;
134
134
  }
135
- constructor(e, t) {
135
+ constructor(e, t2) {
136
136
  if (!u.#o)
137
137
  throw new TypeError("instantiate Stack using Stack.create(n)");
138
- this.heap = new t(e), this.length = 0;
138
+ this.heap = new t2(e), this.length = 0;
139
139
  }
140
140
  push(e) {
141
141
  this.heap[this.length++] = e;
@@ -206,7 +206,7 @@ var init_index_min = __esm(() => {
206
206
  return e.#a;
207
207
  }, get tail() {
208
208
  return e.#h;
209
- }, free: e.#y, isBackgroundFetch: (t) => e.#e(t), backgroundFetch: (t, i, s, n) => e.#P(t, i, s, n), moveToTail: (t) => e.#L(t), indexes: (t) => e.#A(t), rindexes: (t) => e.#z(t), isStale: (t) => e.#p(t) };
209
+ }, free: e.#y, isBackgroundFetch: (t2) => e.#e(t2), backgroundFetch: (t2, i, s, n) => e.#P(t2, i, s, n), moveToTail: (t2) => e.#L(t2), indexes: (t2) => e.#A(t2), rindexes: (t2) => e.#z(t2), isStale: (t2) => e.#p(t2) };
210
210
  }
211
211
  get max() {
212
212
  return this.#o;
@@ -236,15 +236,15 @@ var init_index_min = __esm(() => {
236
236
  return this.#S;
237
237
  }
238
238
  constructor(e) {
239
- let { max: t = 0, ttl: i, ttlResolution: s = 1, ttlAutopurge: n, updateAgeOnGet: r, updateAgeOnHas: h, allowStale: a, dispose: o, onInsert: p, disposeAfter: m, noDisposeOnSet: _, noUpdateTTL: c, maxSize: d = 0, maxEntrySize: f = 0, sizeCalculation: y, fetchMethod: l, memoMethod: S, noDeleteOnFetchRejection: F, noDeleteOnStaleGet: b, allowStaleOnFetchRejection: g, allowStaleOnFetchAbort: A, ignoreFetchAbort: z, perf: x } = e;
239
+ let { max: t2 = 0, ttl: i, ttlResolution: s = 1, ttlAutopurge: n, updateAgeOnGet: r, updateAgeOnHas: h, allowStale: a, dispose: o, onInsert: p, disposeAfter: m, noDisposeOnSet: _, noUpdateTTL: c, maxSize: d = 0, maxEntrySize: f = 0, sizeCalculation: y, fetchMethod: l, memoMethod: S, noDeleteOnFetchRejection: F, noDeleteOnStaleGet: b, allowStaleOnFetchRejection: g, allowStaleOnFetchAbort: A, ignoreFetchAbort: z, perf: x } = e;
240
240
  if (x !== undefined && typeof x?.now != "function")
241
241
  throw new TypeError("perf option must have a now() method if specified");
242
- if (this.#m = x ?? C, t !== 0 && !T(t))
242
+ if (this.#m = x ?? C, t2 !== 0 && !T(t2))
243
243
  throw new TypeError("max option must be a nonnegative integer");
244
- let E = t ? U(t) : Array;
244
+ let E = t2 ? U(t2) : Array;
245
245
  if (!E)
246
- throw new Error("invalid max value: " + t);
247
- if (this.#o = t, this.#c = d, this.maxEntrySize = f || this.#c, this.sizeCalculation = y, this.sizeCalculation) {
246
+ throw new Error("invalid max value: " + t2);
247
+ if (this.#o = t2, this.#c = d, this.maxEntrySize = f || this.#c, this.sizeCalculation = y, this.sizeCalculation) {
248
248
  if (!this.#c && !this.maxEntrySize)
249
249
  throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");
250
250
  if (typeof this.sizeCalculation != "function")
@@ -254,7 +254,7 @@ var init_index_min = __esm(() => {
254
254
  throw new TypeError("memoMethod must be a function if defined");
255
255
  if (this.#I = S, l !== undefined && typeof l != "function")
256
256
  throw new TypeError("fetchMethod must be a function if specified");
257
- if (this.#M = l, this.#U = !!l, this.#s = new Map, this.#i = Array.from({ length: t }).fill(undefined), this.#t = Array.from({ length: t }).fill(undefined), this.#l = new E(t), this.#u = new E(t), this.#a = 0, this.#h = 0, this.#y = R.create(t), this.#n = 0, this.#b = 0, typeof o == "function" && (this.#w = o), typeof p == "function" && (this.#O = p), typeof m == "function" ? (this.#S = m, this.#r = []) : (this.#S = undefined, this.#r = undefined), this.#T = !!this.#w, this.#x = !!this.#O, this.#f = !!this.#S, this.noDisposeOnSet = !!_, this.noUpdateTTL = !!c, this.noDeleteOnFetchRejection = !!F, this.allowStaleOnFetchRejection = !!g, this.allowStaleOnFetchAbort = !!A, this.ignoreFetchAbort = !!z, this.maxEntrySize !== 0) {
257
+ if (this.#M = l, this.#U = !!l, this.#s = new Map, this.#i = Array.from({ length: t2 }).fill(undefined), this.#t = Array.from({ length: t2 }).fill(undefined), this.#l = new E(t2), this.#u = new E(t2), this.#a = 0, this.#h = 0, this.#y = R.create(t2), this.#n = 0, this.#b = 0, typeof o == "function" && (this.#w = o), typeof p == "function" && (this.#O = p), typeof m == "function" ? (this.#S = m, this.#r = []) : (this.#S = undefined, this.#r = undefined), this.#T = !!this.#w, this.#x = !!this.#O, this.#f = !!this.#S, this.noDisposeOnSet = !!_, this.noUpdateTTL = !!c, this.noDeleteOnFetchRejection = !!F, this.allowStaleOnFetchRejection = !!g, this.allowStaleOnFetchAbort = !!A, this.ignoreFetchAbort = !!z, this.maxEntrySize !== 0) {
258
258
  if (this.#c !== 0 && !T(this.#c))
259
259
  throw new TypeError("maxSize must be a positive integer if specified");
260
260
  if (!T(this.maxEntrySize))
@@ -277,13 +277,13 @@ var init_index_min = __esm(() => {
277
277
  return this.#s.has(e) ? 1 / 0 : 0;
278
278
  }
279
279
  #H() {
280
- let e = new O(this.#o), t = new O(this.#o);
281
- this.#d = e, this.#F = t;
280
+ let e = new O(this.#o), t2 = new O(this.#o);
281
+ this.#d = e, this.#F = t2;
282
282
  let i = this.ttlAutopurge ? Array.from({ length: this.#o }) : undefined;
283
283
  this.#g = i, this.#N = (h, a, o = this.#m.now()) => {
284
- t[h] = a !== 0 ? o : 0, e[h] = a, s(h, a);
284
+ t2[h] = a !== 0 ? o : 0, e[h] = a, s(h, a);
285
285
  }, this.#D = (h) => {
286
- t[h] = e[h] !== 0 ? this.#m.now() : 0, s(h, e[h]);
286
+ t2[h] = e[h] !== 0 ? this.#m.now() : 0, s(h, e[h]);
287
287
  };
288
288
  let s = this.ttlAutopurge ? (h, a) => {
289
289
  if (i?.[h] && (clearTimeout(i[h]), i[h] = undefined), a && a !== 0 && i) {
@@ -295,7 +295,7 @@ var init_index_min = __esm(() => {
295
295
  } : () => {};
296
296
  this.#v = (h, a) => {
297
297
  if (e[a]) {
298
- let o = e[a], p = t[a];
298
+ let o = e[a], p = t2[a];
299
299
  if (!o || !p)
300
300
  return;
301
301
  h.ttl = o, h.start = p, h.now = n || r();
@@ -316,13 +316,13 @@ var init_index_min = __esm(() => {
316
316
  let a = this.#s.get(h);
317
317
  if (a === undefined)
318
318
  return 0;
319
- let o = e[a], p = t[a];
319
+ let o = e[a], p = t2[a];
320
320
  if (!o || !p)
321
321
  return 1 / 0;
322
322
  let m = (n || r()) - p;
323
323
  return o - m;
324
324
  }, this.#p = (h) => {
325
- let a = t[h], o = e[h];
325
+ let a = t2[h], o = e[h];
326
326
  return !!o && !!a && (n || r()) - a > o;
327
327
  };
328
328
  }
@@ -332,45 +332,45 @@ var init_index_min = __esm(() => {
332
332
  #p = () => false;
333
333
  #X() {
334
334
  let e = new O(this.#o);
335
- this.#b = 0, this.#_ = e, this.#R = (t) => {
336
- this.#b -= e[t], e[t] = 0;
337
- }, this.#V = (t, i, s, n) => {
335
+ this.#b = 0, this.#_ = e, this.#R = (t2) => {
336
+ this.#b -= e[t2], e[t2] = 0;
337
+ }, this.#V = (t2, i, s, n) => {
338
338
  if (this.#e(i))
339
339
  return 0;
340
340
  if (!T(s))
341
341
  if (n) {
342
342
  if (typeof n != "function")
343
343
  throw new TypeError("sizeCalculation must be a function");
344
- if (s = n(i, t), !T(s))
344
+ if (s = n(i, t2), !T(s))
345
345
  throw new TypeError("sizeCalculation return invalid (expect positive integer)");
346
346
  } else
347
347
  throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.");
348
348
  return s;
349
- }, this.#j = (t, i, s) => {
350
- if (e[t] = i, this.#c) {
351
- let n = this.#c - e[t];
349
+ }, this.#j = (t2, i, s) => {
350
+ if (e[t2] = i, this.#c) {
351
+ let n = this.#c - e[t2];
352
352
  for (;this.#b > n; )
353
353
  this.#G(true);
354
354
  }
355
- this.#b += e[t], s && (s.entrySize = i, s.totalCalculatedSize = this.#b);
355
+ this.#b += e[t2], s && (s.entrySize = i, s.totalCalculatedSize = this.#b);
356
356
  };
357
357
  }
358
358
  #R = (e) => {};
359
- #j = (e, t, i) => {};
360
- #V = (e, t, i, s) => {
359
+ #j = (e, t2, i) => {};
360
+ #V = (e, t2, i, s) => {
361
361
  if (i || s)
362
362
  throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");
363
363
  return 0;
364
364
  };
365
365
  *#A({ allowStale: e = this.allowStale } = {}) {
366
366
  if (this.#n)
367
- for (let t = this.#h;this.#B(t) && ((e || !this.#p(t)) && (yield t), t !== this.#a); )
368
- t = this.#u[t];
367
+ for (let t2 = this.#h;this.#B(t2) && ((e || !this.#p(t2)) && (yield t2), t2 !== this.#a); )
368
+ t2 = this.#u[t2];
369
369
  }
370
370
  *#z({ allowStale: e = this.allowStale } = {}) {
371
371
  if (this.#n)
372
- for (let t = this.#a;this.#B(t) && ((e || !this.#p(t)) && (yield t), t !== this.#h); )
373
- t = this.#l[t];
372
+ for (let t2 = this.#a;this.#B(t2) && ((e || !this.#p(t2)) && (yield t2), t2 !== this.#h); )
373
+ t2 = this.#l[t2];
374
374
  }
375
375
  #B(e) {
376
376
  return e !== undefined && this.#s.get(this.#i[e]) === e;
@@ -385,14 +385,14 @@ var init_index_min = __esm(() => {
385
385
  }
386
386
  *keys() {
387
387
  for (let e of this.#A()) {
388
- let t = this.#i[e];
389
- t !== undefined && !this.#e(this.#t[e]) && (yield t);
388
+ let t2 = this.#i[e];
389
+ t2 !== undefined && !this.#e(this.#t[e]) && (yield t2);
390
390
  }
391
391
  }
392
392
  *rkeys() {
393
393
  for (let e of this.#z()) {
394
- let t = this.#i[e];
395
- t !== undefined && !this.#e(this.#t[e]) && (yield t);
394
+ let t2 = this.#i[e];
395
+ t2 !== undefined && !this.#e(this.#t[e]) && (yield t2);
396
396
  }
397
397
  }
398
398
  *values() {
@@ -407,109 +407,109 @@ var init_index_min = __esm(() => {
407
407
  return this.entries();
408
408
  }
409
409
  [Symbol.toStringTag] = "LRUCache";
410
- find(e, t = {}) {
410
+ find(e, t2 = {}) {
411
411
  for (let i of this.#A()) {
412
412
  let s = this.#t[i], n = this.#e(s) ? s.__staleWhileFetching : s;
413
413
  if (n !== undefined && e(n, this.#i[i], this))
414
- return this.#C(this.#i[i], t);
414
+ return this.#C(this.#i[i], t2);
415
415
  }
416
416
  }
417
- forEach(e, t = this) {
417
+ forEach(e, t2 = this) {
418
418
  for (let i of this.#A()) {
419
419
  let s = this.#t[i], n = this.#e(s) ? s.__staleWhileFetching : s;
420
- n !== undefined && e.call(t, n, this.#i[i], this);
420
+ n !== undefined && e.call(t2, n, this.#i[i], this);
421
421
  }
422
422
  }
423
- rforEach(e, t = this) {
423
+ rforEach(e, t2 = this) {
424
424
  for (let i of this.#z()) {
425
425
  let s = this.#t[i], n = this.#e(s) ? s.__staleWhileFetching : s;
426
- n !== undefined && e.call(t, n, this.#i[i], this);
426
+ n !== undefined && e.call(t2, n, this.#i[i], this);
427
427
  }
428
428
  }
429
429
  purgeStale() {
430
430
  let e = false;
431
- for (let t of this.#z({ allowStale: true }))
432
- this.#p(t) && (this.#E(this.#i[t], "expire"), e = true);
431
+ for (let t2 of this.#z({ allowStale: true }))
432
+ this.#p(t2) && (this.#E(this.#i[t2], "expire"), e = true);
433
433
  return e;
434
434
  }
435
435
  info(e) {
436
- let t = this.#s.get(e);
437
- if (t === undefined)
436
+ let t2 = this.#s.get(e);
437
+ if (t2 === undefined)
438
438
  return;
439
- let i = this.#t[t], s = this.#e(i) ? i.__staleWhileFetching : i;
439
+ let i = this.#t[t2], s = this.#e(i) ? i.__staleWhileFetching : i;
440
440
  if (s === undefined)
441
441
  return;
442
442
  let n = { value: s };
443
443
  if (this.#d && this.#F) {
444
- let r = this.#d[t], h = this.#F[t];
444
+ let r = this.#d[t2], h = this.#F[t2];
445
445
  if (r && h) {
446
446
  let a = r - (this.#m.now() - h);
447
447
  n.ttl = a, n.start = Date.now();
448
448
  }
449
449
  }
450
- return this.#_ && (n.size = this.#_[t]), n;
450
+ return this.#_ && (n.size = this.#_[t2]), n;
451
451
  }
452
452
  dump() {
453
453
  let e = [];
454
- for (let t of this.#A({ allowStale: true })) {
455
- let i = this.#i[t], s = this.#t[t], n = this.#e(s) ? s.__staleWhileFetching : s;
454
+ for (let t2 of this.#A({ allowStale: true })) {
455
+ let i = this.#i[t2], s = this.#t[t2], n = this.#e(s) ? s.__staleWhileFetching : s;
456
456
  if (n === undefined || i === undefined)
457
457
  continue;
458
458
  let r = { value: n };
459
459
  if (this.#d && this.#F) {
460
- r.ttl = this.#d[t];
461
- let h = this.#m.now() - this.#F[t];
460
+ r.ttl = this.#d[t2];
461
+ let h = this.#m.now() - this.#F[t2];
462
462
  r.start = Math.floor(Date.now() - h);
463
463
  }
464
- this.#_ && (r.size = this.#_[t]), e.unshift([i, r]);
464
+ this.#_ && (r.size = this.#_[t2]), e.unshift([i, r]);
465
465
  }
466
466
  return e;
467
467
  }
468
468
  load(e) {
469
469
  this.clear();
470
- for (let [t, i] of e) {
470
+ for (let [t2, i] of e) {
471
471
  if (i.start) {
472
472
  let s = Date.now() - i.start;
473
473
  i.start = this.#m.now() - s;
474
474
  }
475
- this.#W(t, i.value, i);
475
+ this.#W(t2, i.value, i);
476
476
  }
477
477
  }
478
- set(e, t, i = {}) {
478
+ set(e, t2, i = {}) {
479
479
  let { status: s = w.hasSubscribers ? {} : undefined } = i;
480
- i.status = s, s && (s.op = "set", s.key = e, t !== undefined && (s.value = t), s.cache = this);
481
- let n = this.#W(e, t, i);
480
+ i.status = s, s && (s.op = "set", s.key = e, t2 !== undefined && (s.value = t2), s.cache = this);
481
+ let n = this.#W(e, t2, i);
482
482
  return s && w.hasSubscribers && w.publish(s), n;
483
483
  }
484
- #W(e, t, i, s) {
484
+ #W(e, t2, i, s) {
485
485
  let { ttl: n = this.ttl, start: r, noDisposeOnSet: h = this.noDisposeOnSet, sizeCalculation: a = this.sizeCalculation, status: o } = i;
486
- if (t === undefined)
486
+ if (t2 === undefined)
487
487
  return o && (o.set = "deleted"), this.delete(e), this;
488
- let { noUpdateTTL: p = this.noUpdateTTL } = i, m = this.#e(t);
489
- o && !m && (o.value = t);
490
- let _ = this.#V(e, t, i.size || 0, a, o);
488
+ let { noUpdateTTL: p = this.noUpdateTTL } = i, m = this.#e(t2);
489
+ o && !m && (o.value = t2);
490
+ let _ = this.#V(e, t2, i.size || 0, a, o);
491
491
  if (this.maxEntrySize && _ > this.maxEntrySize)
492
492
  return this.#E(e, "set"), o && (o.set = "miss", o.maxEntrySizeExceeded = true), this;
493
493
  let c = this.#n === 0 ? undefined : this.#s.get(e);
494
494
  if (c === undefined)
495
- c = this.#n === 0 ? this.#h : this.#y.length !== 0 ? this.#y.pop() : this.#n === this.#o ? this.#G(false) : this.#n, this.#i[c] = e, this.#t[c] = t, this.#s.set(e, c), this.#l[this.#h] = c, this.#u[c] = this.#h, this.#h = c, this.#n++, this.#j(c, _, o), o && (o.set = "add"), p = false, this.#x && !m && this.#O?.(t, e, "add");
495
+ c = this.#n === 0 ? this.#h : this.#y.length !== 0 ? this.#y.pop() : this.#n === this.#o ? this.#G(false) : this.#n, this.#i[c] = e, this.#t[c] = t2, this.#s.set(e, c), this.#l[this.#h] = c, this.#u[c] = this.#h, this.#h = c, this.#n++, this.#j(c, _, o), o && (o.set = "add"), p = false, this.#x && !m && this.#O?.(t2, e, "add");
496
496
  else {
497
497
  this.#L(c);
498
498
  let d = this.#t[c];
499
- if (t !== d) {
499
+ if (t2 !== d) {
500
500
  if (!h)
501
501
  if (this.#e(d)) {
502
502
  d !== s && d.__abortController.abort(new Error("replaced"));
503
503
  let { __staleWhileFetching: f } = d;
504
- f !== undefined && f !== t && (this.#T && this.#w?.(f, e, "set"), this.#f && this.#r?.push([f, e, "set"]));
504
+ f !== undefined && f !== t2 && (this.#T && this.#w?.(f, e, "set"), this.#f && this.#r?.push([f, e, "set"]));
505
505
  } else
506
506
  this.#T && this.#w?.(d, e, "set"), this.#f && this.#r?.push([d, e, "set"]);
507
- if (this.#R(c), this.#j(c, _, o), this.#t[c] = t, !m) {
508
- let f = d && this.#e(d) ? d.__staleWhileFetching : d, y = f === undefined ? "add" : t !== f ? "replace" : "update";
509
- o && (o.set = y, f !== undefined && (o.oldValue = f)), this.#x && this.onInsert?.(t, e, y);
507
+ if (this.#R(c), this.#j(c, _, o), this.#t[c] = t2, !m) {
508
+ let f = d && this.#e(d) ? d.__staleWhileFetching : d, y = f === undefined ? "add" : t2 !== f ? "replace" : "update";
509
+ o && (o.set = y, f !== undefined && (o.oldValue = f)), this.#x && this.onInsert?.(t2, e, y);
510
510
  }
511
511
  } else
512
- m || (o && (o.set = "update"), this.#x && this.onInsert?.(t, e, "update"));
512
+ m || (o && (o.set = "update"), this.#x && this.onInsert?.(t2, e, "update"));
513
513
  }
514
514
  if (n !== 0 && !this.#d && this.#H(), this.#d && (p || this.#N(c, n, r), o && this.#v(o, c)), !h && this.#f && this.#r) {
515
515
  let d = this.#r, f;
@@ -530,26 +530,26 @@ var init_index_min = __esm(() => {
530
530
  }
531
531
  } finally {
532
532
  if (this.#f && this.#r) {
533
- let e = this.#r, t;
534
- for (;t = e?.shift(); )
535
- this.#S?.(...t);
533
+ let e = this.#r, t2;
534
+ for (;t2 = e?.shift(); )
535
+ this.#S?.(...t2);
536
536
  }
537
537
  }
538
538
  }
539
539
  #G(e) {
540
- let t = this.#a, i = this.#i[t], s = this.#t[t], n = this.#e(s);
540
+ let t2 = this.#a, i = this.#i[t2], s = this.#t[t2], n = this.#e(s);
541
541
  n && s.__abortController.abort(new Error("evicted"));
542
542
  let r = n ? s.__staleWhileFetching : s;
543
- return (this.#T || this.#f) && r !== undefined && (this.#T && this.#w?.(r, i, "evict"), this.#f && this.#r?.push([r, i, "evict"])), this.#R(t), this.#g?.[t] && (clearTimeout(this.#g[t]), this.#g[t] = undefined), e && (this.#i[t] = undefined, this.#t[t] = undefined, this.#y.push(t)), this.#n === 1 ? (this.#a = this.#h = 0, this.#y.length = 0) : this.#a = this.#l[t], this.#s.delete(i), this.#n--, t;
543
+ return (this.#T || this.#f) && r !== undefined && (this.#T && this.#w?.(r, i, "evict"), this.#f && this.#r?.push([r, i, "evict"])), this.#R(t2), this.#g?.[t2] && (clearTimeout(this.#g[t2]), this.#g[t2] = undefined), e && (this.#i[t2] = undefined, this.#t[t2] = undefined, this.#y.push(t2)), this.#n === 1 ? (this.#a = this.#h = 0, this.#y.length = 0) : this.#a = this.#l[t2], this.#s.delete(i), this.#n--, t2;
544
544
  }
545
- has(e, t = {}) {
546
- let { status: i = w.hasSubscribers ? {} : undefined } = t;
547
- t.status = i, i && (i.op = "has", i.key = e, i.cache = this);
548
- let s = this.#Y(e, t);
545
+ has(e, t2 = {}) {
546
+ let { status: i = w.hasSubscribers ? {} : undefined } = t2;
547
+ t2.status = i, i && (i.op = "has", i.key = e, i.cache = this);
548
+ let s = this.#Y(e, t2);
549
549
  return w.hasSubscribers && w.publish(i), s;
550
550
  }
551
- #Y(e, t = {}) {
552
- let { updateAgeOnHas: i = this.updateAgeOnHas, status: s } = t, n = this.#s.get(e);
551
+ #Y(e, t2 = {}) {
552
+ let { updateAgeOnHas: i = this.updateAgeOnHas, status: s } = t2, n = this.#s.get(e);
553
553
  if (n !== undefined) {
554
554
  let r = this.#t[n];
555
555
  if (this.#e(r) && r.__staleWhileFetching === undefined)
@@ -562,14 +562,14 @@ var init_index_min = __esm(() => {
562
562
  s && (s.has = "miss");
563
563
  return false;
564
564
  }
565
- peek(e, t = {}) {
566
- let { status: i = D() ? {} : undefined } = t;
567
- i && (i.op = "peek", i.key = e, i.cache = this), t.status = i;
568
- let s = this.#J(e, t);
565
+ peek(e, t2 = {}) {
566
+ let { status: i = D() ? {} : undefined } = t2;
567
+ i && (i.op = "peek", i.key = e, i.cache = this), t2.status = i;
568
+ let s = this.#J(e, t2);
569
569
  return w.hasSubscribers && w.publish(i), s;
570
570
  }
571
- #J(e, t) {
572
- let { status: i, allowStale: s = this.allowStale } = t, n = this.#s.get(e);
571
+ #J(e, t2) {
572
+ let { status: i, allowStale: s = this.allowStale } = t2, n = this.#s.get(e);
573
573
  if (n === undefined || !s && this.#p(n)) {
574
574
  i && (i.peek = n === undefined ? "miss" : "stale");
575
575
  return;
@@ -577,8 +577,8 @@ var init_index_min = __esm(() => {
577
577
  let r = this.#t[n], h = this.#e(r) ? r.__staleWhileFetching : r;
578
578
  return i && (h !== undefined ? (i.peek = "hit", i.value = h) : i.peek = "miss"), h;
579
579
  }
580
- #P(e, t, i, s) {
581
- let n = t === undefined ? undefined : this.#t[t];
580
+ #P(e, t2, i, s) {
581
+ let n = t2 === undefined ? undefined : this.#t[t2];
582
582
  if (this.#e(n))
583
583
  return n;
584
584
  let r = new AbortController, { signal: h } = i;
@@ -587,11 +587,11 @@ var init_index_min = __esm(() => {
587
587
  let { aborted: l } = r.signal, S = i.ignoreFetchAbort && f !== undefined, F = i.ignoreFetchAbort || !!(i.allowStaleOnFetchAbort && f !== undefined);
588
588
  if (i.status && (l && !y ? (i.status.fetchAborted = true, i.status.fetchError = r.signal.reason, S && (i.status.fetchAbortIgnored = true)) : i.status.fetchResolved = true), l && !S && !y)
589
589
  return m(r.signal.reason, F);
590
- let b = c, g = this.#t[t];
591
- return (g === c || g === undefined && S && y) && (f === undefined ? b.__staleWhileFetching !== undefined ? this.#t[t] = b.__staleWhileFetching : this.#E(e, "fetch") : (i.status && (i.status.fetchUpdated = true), this.#W(e, f, a.options, b))), f;
590
+ let b = c, g = this.#t[t2];
591
+ return (g === c || g === undefined && S && y) && (f === undefined ? b.__staleWhileFetching !== undefined ? this.#t[t2] = b.__staleWhileFetching : this.#E(e, "fetch") : (i.status && (i.status.fetchUpdated = true), this.#W(e, f, a.options, b))), f;
592
592
  }, p = (f) => (i.status && (i.status.fetchRejected = true, i.status.fetchError = f), m(f, false)), m = (f, y) => {
593
593
  let { aborted: l } = r.signal, S = l && i.allowStaleOnFetchAbort, F = S || i.allowStaleOnFetchRejection, b = F || i.noDeleteOnFetchRejection, g = c;
594
- if (this.#t[t] === c && (!b || !y && g.__staleWhileFetching === undefined ? this.#E(e, "fetch") : S || (this.#t[t] = g.__staleWhileFetching)), F)
594
+ if (this.#t[t2] === c && (!b || !y && g.__staleWhileFetching === undefined ? this.#E(e, "fetch") : S || (this.#t[t2] = g.__staleWhileFetching)), F)
595
595
  return i.status && g.__staleWhileFetching !== undefined && (i.status.returnedStale = true), g.__staleWhileFetching;
596
596
  if (g.__returned === g)
597
597
  throw f;
@@ -603,22 +603,22 @@ var init_index_min = __esm(() => {
603
603
  };
604
604
  i.status && (i.status.fetchDispatched = true);
605
605
  let c = new Promise(_).then(o, p), d = Object.assign(c, { __abortController: r, __staleWhileFetching: n, __returned: undefined });
606
- return t === undefined ? (this.#W(e, d, { ...a.options, status: undefined }), t = this.#s.get(e)) : this.#t[t] = d, d;
606
+ return t2 === undefined ? (this.#W(e, d, { ...a.options, status: undefined }), t2 = this.#s.get(e)) : this.#t[t2] = d, d;
607
607
  }
608
608
  #e(e) {
609
609
  if (!this.#U)
610
610
  return false;
611
- let t = e;
612
- return !!t && t instanceof Promise && t.hasOwnProperty("__staleWhileFetching") && t.__abortController instanceof AbortController;
611
+ let t2 = e;
612
+ return !!t2 && t2 instanceof Promise && t2.hasOwnProperty("__staleWhileFetching") && t2.__abortController instanceof AbortController;
613
613
  }
614
- fetch(e, t = {}) {
615
- let i = W.hasSubscribers, { status: s = D() ? {} : undefined } = t;
616
- t.status = s, s && t.context && (s.context = t.context);
617
- let n = this.#k(e, t);
614
+ fetch(e, t2 = {}) {
615
+ let i = W.hasSubscribers, { status: s = D() ? {} : undefined } = t2;
616
+ t2.status = s, s && t2.context && (s.context = t2.context);
617
+ let n = this.#k(e, t2);
618
618
  return s && i && (s.trace = true, W.tracePromise(() => n, s).catch(() => {})), n;
619
619
  }
620
- async#k(e, t = {}) {
621
- let { allowStale: i = this.allowStale, updateAgeOnGet: s = this.updateAgeOnGet, noDeleteOnStaleGet: n = this.noDeleteOnStaleGet, ttl: r = this.ttl, noDisposeOnSet: h = this.noDisposeOnSet, size: a = 0, sizeCalculation: o = this.sizeCalculation, noUpdateTTL: p = this.noUpdateTTL, noDeleteOnFetchRejection: m = this.noDeleteOnFetchRejection, allowStaleOnFetchRejection: _ = this.allowStaleOnFetchRejection, ignoreFetchAbort: c = this.ignoreFetchAbort, allowStaleOnFetchAbort: d = this.allowStaleOnFetchAbort, context: f, forceRefresh: y = false, status: l, signal: S } = t;
620
+ async#k(e, t2 = {}) {
621
+ let { allowStale: i = this.allowStale, updateAgeOnGet: s = this.updateAgeOnGet, noDeleteOnStaleGet: n = this.noDeleteOnStaleGet, ttl: r = this.ttl, noDisposeOnSet: h = this.noDisposeOnSet, size: a = 0, sizeCalculation: o = this.sizeCalculation, noUpdateTTL: p = this.noUpdateTTL, noDeleteOnFetchRejection: m = this.noDeleteOnFetchRejection, allowStaleOnFetchRejection: _ = this.allowStaleOnFetchRejection, ignoreFetchAbort: c = this.ignoreFetchAbort, allowStaleOnFetchAbort: d = this.allowStaleOnFetchAbort, context: f, forceRefresh: y = false, status: l, signal: S } = t2;
622
622
  if (l && (l.op = "fetch", l.key = e, y && (l.forceRefresh = true), l.cache = this), !this.#U)
623
623
  return l && (l.fetch = "get"), this.#C(e, { allowStale: i, updateAgeOnGet: s, noDeleteOnStaleGet: n, status: l });
624
624
  let F = { allowStale: i, updateAgeOnGet: s, noDeleteOnStaleGet: n, ttl: r, noDisposeOnSet: h, size: a, sizeCalculation: o, noUpdateTTL: p, noDeleteOnFetchRejection: m, allowStaleOnFetchRejection: _, allowStaleOnFetchAbort: d, ignoreFetchAbort: c, status: l, signal: S }, b = this.#s.get(e);
@@ -639,29 +639,29 @@ var init_index_min = __esm(() => {
639
639
  return l && (l.fetch = A ? "stale" : "refresh", E && A && (l.returnedStale = true)), E ? z.__staleWhileFetching : z.__returned = z;
640
640
  }
641
641
  }
642
- forceFetch(e, t = {}) {
643
- let i = W.hasSubscribers, { status: s = D() ? {} : undefined } = t;
644
- t.status = s, s && t.context && (s.context = t.context);
645
- let n = this.#K(e, t);
642
+ forceFetch(e, t2 = {}) {
643
+ let i = W.hasSubscribers, { status: s = D() ? {} : undefined } = t2;
644
+ t2.status = s, s && t2.context && (s.context = t2.context);
645
+ let n = this.#K(e, t2);
646
646
  return s && i && (s.trace = true, W.tracePromise(() => n, s).catch(() => {})), n;
647
647
  }
648
- async#K(e, t = {}) {
649
- let i = await this.#k(e, t);
648
+ async#K(e, t2 = {}) {
649
+ let i = await this.#k(e, t2);
650
650
  if (i === undefined)
651
651
  throw new Error("fetch() returned undefined");
652
652
  return i;
653
653
  }
654
- memo(e, t = {}) {
655
- let { status: i = w.hasSubscribers ? {} : undefined } = t;
656
- t.status = i, i && (i.op = "memo", i.key = e, t.context && (i.context = t.context), i.cache = this);
657
- let s = this.#Q(e, t);
654
+ memo(e, t2 = {}) {
655
+ let { status: i = w.hasSubscribers ? {} : undefined } = t2;
656
+ t2.status = i, i && (i.op = "memo", i.key = e, t2.context && (i.context = t2.context), i.cache = this);
657
+ let s = this.#Q(e, t2);
658
658
  return i && (i.value = s), w.hasSubscribers && w.publish(i), s;
659
659
  }
660
- #Q(e, t = {}) {
660
+ #Q(e, t2 = {}) {
661
661
  let i = this.#I;
662
662
  if (!i)
663
663
  throw new Error("no memoMethod provided to constructor");
664
- let { context: s, status: n, forceRefresh: r, ...h } = t;
664
+ let { context: s, status: n, forceRefresh: r, ...h } = t2;
665
665
  n && r && (n.forceRefresh = true);
666
666
  let a = this.#C(e, h), o = r || a === undefined;
667
667
  if (n && (n.memo = o ? "miss" : "hit", o || (n.value = a)), !o)
@@ -669,14 +669,14 @@ var init_index_min = __esm(() => {
669
669
  let p = i(e, a, { options: h, context: s });
670
670
  return n && (n.value = p), this.#W(e, p, h), p;
671
671
  }
672
- get(e, t = {}) {
673
- let { status: i = w.hasSubscribers ? {} : undefined } = t;
674
- t.status = i, i && (i.op = "get", i.key = e, i.cache = this);
675
- let s = this.#C(e, t);
672
+ get(e, t2 = {}) {
673
+ let { status: i = w.hasSubscribers ? {} : undefined } = t2;
674
+ t2.status = i, i && (i.op = "get", i.key = e, i.cache = this);
675
+ let s = this.#C(e, t2);
676
676
  return i && (s !== undefined && (i.value = s), w.hasSubscribers && w.publish(i)), s;
677
677
  }
678
- #C(e, t = {}) {
679
- let { allowStale: i = this.allowStale, updateAgeOnGet: s = this.updateAgeOnGet, noDeleteOnStaleGet: n = this.noDeleteOnStaleGet, status: r } = t, h = this.#s.get(e);
678
+ #C(e, t2 = {}) {
679
+ let { allowStale: i = this.allowStale, updateAgeOnGet: s = this.updateAgeOnGet, noDeleteOnStaleGet: n = this.noDeleteOnStaleGet, status: r } = t2, h = this.#s.get(e);
680
680
  if (h === undefined) {
681
681
  r && (r.get = "miss");
682
682
  return;
@@ -684,8 +684,8 @@ var init_index_min = __esm(() => {
684
684
  let a = this.#t[h], o = this.#e(a);
685
685
  return r && this.#v(r, h), this.#p(h) ? o ? (r && (r.get = "stale-fetching"), i && a.__staleWhileFetching !== undefined ? (r && (r.returnedStale = true), a.__staleWhileFetching) : undefined) : (n || this.#E(e, "expire"), r && (r.get = "stale"), i ? (r && (r.returnedStale = true), a) : undefined) : (r && (r.get = o ? "fetching" : "hit"), this.#L(h), s && this.#D(h), o ? a.__staleWhileFetching : a);
686
686
  }
687
- #$(e, t) {
688
- this.#u[t] = e, this.#l[e] = t;
687
+ #$(e, t2) {
688
+ this.#u[t2] = e, this.#l[e] = t2;
689
689
  }
690
690
  #L(e) {
691
691
  e !== this.#h && (e === this.#a ? this.#a = this.#l[e] : this.#$(this.#u[e], this.#l[e]), this.#$(this.#h, e), this.#h = e);
@@ -693,18 +693,18 @@ var init_index_min = __esm(() => {
693
693
  delete(e) {
694
694
  return this.#E(e, "delete");
695
695
  }
696
- #E(e, t) {
697
- w.hasSubscribers && w.publish({ op: "delete", delete: t, key: e, cache: this });
696
+ #E(e, t2) {
697
+ w.hasSubscribers && w.publish({ op: "delete", delete: t2, key: e, cache: this });
698
698
  let i = false;
699
699
  if (this.#n !== 0) {
700
700
  let s = this.#s.get(e);
701
701
  if (s !== undefined)
702
702
  if (this.#g?.[s] && (clearTimeout(this.#g?.[s]), this.#g[s] = undefined), i = true, this.#n === 1)
703
- this.#q(t);
703
+ this.#q(t2);
704
704
  else {
705
705
  this.#R(s);
706
706
  let n = this.#t[s];
707
- if (this.#e(n) ? n.__abortController.abort(new Error("deleted")) : (this.#T || this.#f) && (this.#T && this.#w?.(n, e, t), this.#f && this.#r?.push([n, e, t])), this.#s.delete(e), this.#i[s] = undefined, this.#t[s] = undefined, s === this.#h)
707
+ if (this.#e(n) ? n.__abortController.abort(new Error("deleted")) : (this.#T || this.#f) && (this.#T && this.#w?.(n, e, t2), this.#f && this.#r?.push([n, e, t2])), this.#s.delete(e), this.#i[s] = undefined, this.#t[s] = undefined, s === this.#h)
708
708
  this.#h = this.#u[s];
709
709
  else if (s === this.#a)
710
710
  this.#a = this.#l[s];
@@ -728,24 +728,24 @@ var init_index_min = __esm(() => {
728
728
  return this.#q("delete");
729
729
  }
730
730
  #q(e) {
731
- for (let t of this.#z({ allowStale: true })) {
732
- let i = this.#t[t];
731
+ for (let t2 of this.#z({ allowStale: true })) {
732
+ let i = this.#t[t2];
733
733
  if (this.#e(i))
734
734
  i.__abortController.abort(new Error("deleted"));
735
735
  else {
736
- let s = this.#i[t];
736
+ let s = this.#i[t2];
737
737
  this.#T && this.#w?.(i, s, e), this.#f && this.#r?.push([i, s, e]);
738
738
  }
739
739
  }
740
740
  if (this.#s.clear(), this.#t.fill(undefined), this.#i.fill(undefined), this.#d && this.#F) {
741
741
  this.#d.fill(0), this.#F.fill(0);
742
- for (let t of this.#g ?? [])
743
- t !== undefined && clearTimeout(t);
742
+ for (let t2 of this.#g ?? [])
743
+ t2 !== undefined && clearTimeout(t2);
744
744
  this.#g?.fill(undefined);
745
745
  }
746
746
  if (this.#_ && this.#_.fill(0), this.#a = 0, this.#h = 0, this.#y.length = 0, this.#b = 0, this.#n = 0, this.#f && this.#r) {
747
- let t = this.#r, i;
748
- for (;i = t?.shift(); )
747
+ let t2 = this.#r, i;
748
+ for (;i = t2?.shift(); )
749
749
  this.#S?.(...i);
750
750
  }
751
751
  }
@@ -1679,6 +1679,12 @@ var messages_default = {
1679
1679
  invalid_config: "Invalid configuration: {field}",
1680
1680
  connection_failed: "Failed to connect to database: {message}",
1681
1681
  permission_denied: "Permission denied (required: {required})",
1682
+ permission_requires_level: "{type} operation requires {minimum} permission or higher (current level: {permission})",
1683
+ elasticsearch_requires_level: "Elasticsearch {type} operation requires {minimum} permission or higher (current level: {permission})",
1684
+ escalated_write_requires_admin: "This statement opens as a read but contains an executable {keyword}. A write hidden inside a read statement requires admin permission (current level: {permission}).",
1685
+ multiple_statements_refused: "SQL containing multiple statements is refused below admin permission, because only the first statement determines the permission check. Run each statement separately.",
1686
+ unknown_statement_query_only: "Unrecognised SQL statement (current level: query-only). Security policy requires read-write+ for unknown statements. If this is a legitimate read-only statement, please open an issue at https://github.com/CarlLee1983/dbcli/issues.",
1687
+ permission_denied_reason: "Permission denied: {reason}",
1682
1688
  table_not_found: "Table not found: {table}",
1683
1689
  unsupported_lang: "Language '{lang}' not supported, using English",
1684
1690
  invalid_json: "Invalid JSON: {message}",
@@ -1700,7 +1706,8 @@ Provide options: --env-host, --env-port, --env-user, --env-password, --env-datab
1700
1706
  Or use interactive mode: run "dbcli init --use-env-refs" without --no-interactive`,
1701
1707
  env_var_not_defined: `Cannot test connection: environment variable {envKey} is not defined.
1702
1708
  Set {envKey} in .env or environment variables.
1703
- Hint: run 'export {envKey}=<value>' and retry`
1709
+ Hint: run 'export {envKey}=<value>' and retry`,
1710
+ invalid_output_format: "--format {format} is not supported here \u2014 use text or json"
1704
1711
  },
1705
1712
  success: {
1706
1713
  inserted: "Successfully inserted {count} row(s)",
@@ -1711,19 +1718,22 @@ Hint: run 'export {envKey}=<value>' and retry`
1711
1718
  insert: {
1712
1719
  description: "Insert data into a table",
1713
1720
  prompt_data: "Enter JSON data to insert: ",
1714
- confirm: "Insert {count} row(s) into {table}? (y/n): "
1721
+ confirm: "Insert {count} row(s) into {table}? (y/n): ",
1722
+ elasticsearch_unsupported: "Elasticsearch does not support the insert command; for now, use an external tool (e.g. curl or Kibana DevTools) to write documents"
1715
1723
  },
1716
1724
  update: {
1717
1725
  description: "Update data in a table",
1718
1726
  prompt_where: "Enter WHERE clause (e.g., id=1): ",
1719
1727
  prompt_set: 'Enter JSON updates (e.g., {"status": "active"}): ',
1720
- confirm: "Update rows in {table}? (y/n): "
1728
+ confirm: "Update rows in {table}? (y/n): ",
1729
+ elasticsearch_unsupported: "Elasticsearch does not support the update command; for now, use an external tool (e.g. curl or Kibana DevTools) to update documents"
1721
1730
  },
1722
1731
  delete: {
1723
1732
  description: "Delete data from a table",
1724
1733
  prompt_where: "Enter WHERE clause (e.g., id=1): ",
1725
1734
  confirm: "Delete rows from {table}? (y/n): ",
1726
- admin_only: "Delete command requires data-admin or admin permission"
1735
+ admin_only: "Delete command requires data-admin or admin permission",
1736
+ elasticsearch_unsupported: "Elasticsearch does not support the delete command; for now, use an external tool (e.g. curl or Kibana DevTools) to delete documents"
1727
1737
  },
1728
1738
  export: {
1729
1739
  description: "Export query results",
@@ -1798,6 +1808,20 @@ Reference: {referencePath}`,
1798
1808
  add_enum_description: "Create an enum type (PostgreSQL only)",
1799
1809
  alter_enum_description: "Add a value to an enum type",
1800
1810
  drop_enum_description: "Drop an enum type"
1811
+ },
1812
+ password: {
1813
+ description: "Change the password of a single connection, leaving every other setting untouched",
1814
+ arg_connection: "Connection name (defaults to the current default connection)",
1815
+ opt_stdin: "Read the new password from stdin (for rotation scripts)",
1816
+ opt_password: "New password given inline (visible in shell history and process list)",
1817
+ opt_skip_test: "Skip verifying the new password against the database before saving",
1818
+ prompt: "New password for connection '{name}'",
1819
+ source_conflict: "--password and --stdin cannot be used together; pick one source.",
1820
+ needs_source: "No terminal available for a masked prompt. Pass the value with --stdin or --password.",
1821
+ empty: "The new password is empty; nothing was changed.",
1822
+ updated: "Password for connection '{name}' updated \u2192 {envFile} ({varName})",
1823
+ converted: 'The literal password in config.json was replaced by a {{ "$env": "{varName}" }} reference; later rotations only touch the env file.',
1824
+ skipped_test: "Verification skipped (--skip-test): the new password was not checked against the database."
1801
1825
  }
1802
1826
  };
1803
1827
  // resources/lang/zh-TW/messages.json
@@ -1959,6 +1983,12 @@ var messages_default2 = {
1959
1983
  invalid_config: "\u914D\u7F6E\u7121\u6548\uFF1A{field}",
1960
1984
  connection_failed: "\u7121\u6CD5\u9023\u63A5\u5230\u8CC7\u6599\u5EAB\uFF1A{message}",
1961
1985
  permission_denied: "\u6B0A\u9650\u88AB\u62D2\uFF08\u9700\u8981\uFF1A{required}\uFF09",
1986
+ permission_requires_level: "{type} \u64CD\u4F5C\u9700\u8981 {minimum} \u4EE5\u4E0A\u7684\u6B0A\u9650\uFF08\u76EE\u524D\u5C64\u7D1A\uFF1A{permission}\uFF09",
1987
+ elasticsearch_requires_level: "Elasticsearch {type} \u64CD\u4F5C\u9700\u8981 {minimum} \u4EE5\u4E0A\u7684\u6B0A\u9650\uFF08\u76EE\u524D\u5C64\u7D1A\uFF1A{permission}\uFF09",
1988
+ escalated_write_requires_admin: "\u6B64\u8A9E\u53E5\u8868\u9762\u4E0A\u662F\u8B80\u53D6\uFF0C\u4F46\u5BE6\u969B\u5305\u542B\u53EF\u57F7\u884C\u7684 {keyword}\u3002\u8B80\u53D6\u8A9E\u53E5\u4E2D\u96B1\u85CF\u5BEB\u5165\u64CD\u4F5C\u9700\u8981 admin \u6B0A\u9650\uFF08\u76EE\u524D\u5C64\u7D1A\uFF1A{permission}\uFF09\u3002",
1989
+ multiple_statements_refused: "\u4F4E\u65BC admin \u6B0A\u9650\u6642\u62D2\u7D55\u57F7\u884C\u5305\u542B\u591A\u500B\u8A9E\u53E5\u7684 SQL\uFF0C\u56E0\u70BA\u6B0A\u9650\u6AA2\u67E5\u53EA\u6703\u4F9D\u64DA\u7B2C\u4E00\u500B\u8A9E\u53E5\u5224\u65B7\u3002\u8ACB\u5C07\u5404\u8A9E\u53E5\u5206\u958B\u57F7\u884C\u3002",
1990
+ unknown_statement_query_only: "\u7121\u6CD5\u8FA8\u8B58\u7684 SQL \u8A9E\u53E5\uFF08\u76EE\u524D\u5C64\u7D1A\uFF1Aquery-only\uFF09\u3002\u5B89\u5168\u653F\u7B56\u8981\u6C42\u672A\u77E5\u8A9E\u53E5\u81F3\u5C11\u9700\u8981 read-write \u4EE5\u4E0A\u6B0A\u9650\u3002\u82E5\u9019\u5176\u5BE6\u662F\u5408\u6CD5\u7684\u552F\u8B80\u8A9E\u53E5\uFF0C\u8ACB\u81F3 https://github.com/CarlLee1983/dbcli/issues \u63D0\u51FA\u8B70\u984C\u3002",
1991
+ permission_denied_reason: "\u6B0A\u9650\u88AB\u62D2\uFF1A{reason}",
1962
1992
  table_not_found: "\u627E\u4E0D\u5230\u8868\u683C\uFF1A{table}",
1963
1993
  unsupported_lang: "\u4E0D\u652F\u63F4\u7684\u8A9E\u8A00 '{lang}'\uFF0C\u4F7F\u7528\u82F1\u6587",
1964
1994
  invalid_json: "\u7121\u6548\u7684 JSON\uFF1A{message}",
@@ -1980,7 +2010,8 @@ var messages_default2 = {
1980
2010
  \u6216\u4F7F\u7528\u4E92\u52D5\u6A21\u5F0F\uFF1A\u57F7\u884C "dbcli init --use-env-refs"\uFF08\u4E0D\u52A0 --no-interactive\uFF09`,
1981
2011
  env_var_not_defined: `\u7121\u6CD5\u6E2C\u8A66\u9023\u7DDA\uFF1A\u74B0\u5883\u8B8A\u6578 {envKey} \u672A\u5B9A\u7FA9\u3002
1982
2012
  \u8ACB\u5728 .env \u6216\u74B0\u5883\u8B8A\u6578\u4E2D\u8A2D\u5B9A {envKey}\u3002
1983
- \u63D0\u793A\uFF1A\u57F7\u884C 'export {envKey}=<value>' \u5F8C\u91CD\u8A66`
2013
+ \u63D0\u793A\uFF1A\u57F7\u884C 'export {envKey}=<value>' \u5F8C\u91CD\u8A66`,
2014
+ invalid_output_format: "\u7121\u6CD5\u4F7F\u7528 --format {format}\uFF0C\u8ACB\u4F7F\u7528 text \u6216 json"
1984
2015
  },
1985
2016
  success: {
1986
2017
  inserted: "\u6210\u529F\u63D2\u5165 {count} \u5217",
@@ -1991,19 +2022,22 @@ var messages_default2 = {
1991
2022
  insert: {
1992
2023
  description: "\u63D2\u5165\u8CC7\u6599\u5230\u8868\u683C",
1993
2024
  prompt_data: "\u8F38\u5165\u8981\u63D2\u5165\u7684 JSON \u8CC7\u6599\uFF1A",
1994
- confirm: "\u5C07 {count} \u5217\u63D2\u5165\u5230 {table}\uFF1F (y/n)\uFF1A"
2025
+ confirm: "\u5C07 {count} \u5217\u63D2\u5165\u5230 {table}\uFF1F (y/n)\uFF1A",
2026
+ elasticsearch_unsupported: "Elasticsearch \u4E0D\u652F\u63F4 insert \u6307\u4EE4\uFF1B\u76EE\u524D\u8ACB\u4F7F\u7528\u5916\u90E8\u5DE5\u5177\uFF08\u5982 curl \u6216 Kibana DevTools\uFF09\u9032\u884C\u6587\u4EF6\u5BEB\u5165"
1995
2027
  },
1996
2028
  update: {
1997
2029
  description: "\u66F4\u65B0\u8868\u683C\u4E2D\u7684\u8CC7\u6599",
1998
2030
  prompt_where: "\u8F38\u5165 WHERE \u5B50\u53E5 (\u4F8B\u5982\uFF1Aid=1)\uFF1A",
1999
2031
  prompt_set: '\u8F38\u5165 JSON \u66F4\u65B0 (\u4F8B\u5982\uFF1A{"status": "active"})\uFF1A',
2000
- confirm: "\u66F4\u65B0 {table} \u4E2D\u7684\u5217\uFF1F (y/n)\uFF1A"
2032
+ confirm: "\u66F4\u65B0 {table} \u4E2D\u7684\u5217\uFF1F (y/n)\uFF1A",
2033
+ elasticsearch_unsupported: "Elasticsearch \u4E0D\u652F\u63F4 update \u6307\u4EE4\uFF1B\u76EE\u524D\u8ACB\u4F7F\u7528\u5916\u90E8\u5DE5\u5177\uFF08\u5982 curl \u6216 Kibana DevTools\uFF09\u9032\u884C\u6587\u4EF6\u66F4\u65B0"
2001
2034
  },
2002
2035
  delete: {
2003
2036
  description: "\u522A\u9664\u8868\u683C\u4E2D\u7684\u8CC7\u6599",
2004
2037
  prompt_where: "\u8F38\u5165 WHERE \u5B50\u53E5 (\u4F8B\u5982\uFF1Aid=1)\uFF1A",
2005
2038
  confirm: "\u522A\u9664 {table} \u4E2D\u7684\u5217\uFF1F (y/n)\uFF1A",
2006
- admin_only: "\u522A\u9664\u547D\u4EE4\u9700\u8981 data-admin \u6216 admin \u6B0A\u9650"
2039
+ admin_only: "\u522A\u9664\u547D\u4EE4\u9700\u8981 data-admin \u6216 admin \u6B0A\u9650",
2040
+ elasticsearch_unsupported: "Elasticsearch \u4E0D\u652F\u63F4 delete \u6307\u4EE4\uFF1B\u76EE\u524D\u8ACB\u4F7F\u7528\u5916\u90E8\u5DE5\u5177\uFF08\u5982 curl \u6216 Kibana DevTools\uFF09\u9032\u884C\u6587\u4EF6\u522A\u9664"
2007
2041
  },
2008
2042
  export: {
2009
2043
  description: "\u532F\u51FA\u67E5\u8A62\u7D50\u679C",
@@ -2078,6 +2112,20 @@ var messages_default2 = {
2078
2112
  add_enum_description: "\u5EFA\u7ACB\u5217\u8209\u578B\u5225\uFF08\u50C5 PostgreSQL\uFF09",
2079
2113
  alter_enum_description: "\u65B0\u589E\u5217\u8209\u503C",
2080
2114
  drop_enum_description: "\u522A\u9664\u5217\u8209\u578B\u5225"
2115
+ },
2116
+ password: {
2117
+ description: "\u53EA\u8B8A\u66F4\u55AE\u4E00\u9023\u7DDA\u7684\u5BC6\u78BC\uFF0C\u5176\u9918\u8A2D\u5B9A\u539F\u5C01\u4E0D\u52D5",
2118
+ arg_connection: "\u9023\u7DDA\u540D\u7A31\uFF08\u7701\u7565\u6642\u6539\u9810\u8A2D\u9023\u7DDA\uFF09",
2119
+ opt_stdin: "\u5F9E stdin \u8B80\u53D6\u65B0\u5BC6\u78BC\uFF08\u4F9B\u8F2A\u66FF\u8173\u672C\u4F7F\u7528\uFF09",
2120
+ opt_password: "\u76F4\u63A5\u5E36\u5165\u65B0\u5BC6\u78BC\uFF08\u6703\u7559\u5728 shell \u6B77\u53F2\u8207\u884C\u7A0B\u5217\u8868\uFF09",
2121
+ opt_skip_test: "\u5B58\u6A94\u524D\u4E0D\u5148\u7528\u65B0\u5BC6\u78BC\u9023\u7DDA\u9A57\u8B49",
2122
+ prompt: "\u9023\u7DDA '{name}' \u7684\u65B0\u5BC6\u78BC",
2123
+ source_conflict: "--password \u8207 --stdin \u53EA\u80FD\u64C7\u4E00\u3002",
2124
+ needs_source: "\u6C92\u6709\u7D42\u7AEF\u6A5F\u53EF\u505A\u906E\u853D\u8F38\u5165\uFF0C\u8ACB\u6539\u7528 --stdin \u6216 --password \u50B3\u5165\u3002",
2125
+ empty: "\u65B0\u5BC6\u78BC\u662F\u7A7A\u7684\uFF0C\u672A\u505A\u4EFB\u4F55\u8B8A\u66F4\u3002",
2126
+ updated: "\u5DF2\u66F4\u65B0\u9023\u7DDA '{name}' \u7684\u5BC6\u78BC \u2192 {envFile}\uFF08{varName}\uFF09",
2127
+ converted: 'config.json \u88E1\u7684\u660E\u6587\u5BC6\u78BC\u5DF2\u6539\u6210 {{ "$env": "{varName}" }} \u53C3\u7167\uFF0C\u4E4B\u5F8C\u8F2A\u66FF\u53EA\u6703\u52D5 env \u6A94\u3002',
2128
+ skipped_test: "\u5DF2\u8DF3\u904E\u9A57\u8B49\uFF08--skip-test\uFF09\uFF1A\u65B0\u5BC6\u78BC\u672A\u7D93\u8CC7\u6599\u5EAB\u78BA\u8A8D\u3002"
2081
2129
  }
2082
2130
  };
2083
2131
  // resources/lang/en/shell.json
@@ -2124,11 +2172,61 @@ var shell_default2 = {
2124
2172
  rows_display: "{count} \u7B46\u8CC7\u6599",
2125
2173
  unknown_command: "\u672A\u77E5\u6307\u4EE4\uFF1A'{command}'\u3002\u8F38\u5165 '.help' \u67E5\u770B\u53EF\u7528\u6307\u4EE4\u3002"
2126
2174
  };
2175
+ // resources/lang/en/ceremony.json
2176
+ var ceremony_default = {
2177
+ updated: "Updated {count} row(s) in {table}",
2178
+ deleted: "Deleted {count} row(s) from {table}",
2179
+ inserted: "Inserted {count} row(s) into {table}",
2180
+ matched_nothing: "No rows matched in {table} \u2014 nothing changed",
2181
+ cancelled: "Cancelled. {table} was not changed",
2182
+ dry_run: "Preview only. {table} was not changed",
2183
+ elapsed: "Took {seconds}s",
2184
+ failed: "Failed: {reason}",
2185
+ unknown_error: "unknown error",
2186
+ confirm_sql: "Generated SQL:",
2187
+ confirm_command: "Command to run:",
2188
+ confirm_params: "Parameters:",
2189
+ confirm_destructive_warning: "\u26A0\uFE0F Warning: DELETE operation is destructive and cannot be undone!",
2190
+ confirm_destructive_prompt: "Are you sure you want to execute this DELETE operation? This cannot be undone.",
2191
+ confirm_destructive_warning_ddl: "\u26A0\uFE0F Warning: this schema change is destructive and cannot be undone!",
2192
+ confirm_ddl_prompt: "Are you sure you want to run this {operation}? This cannot be undone.",
2193
+ confirm_prompt: "Proceed with this operation?",
2194
+ recovery_none: "This cannot be undone automatically \u2014 restore from a backup to get the previous values back.",
2195
+ recovery_retry: "Re-run with --recovery to write a recovery plan, then read it with: dbcli recover",
2196
+ blacklist_hint: "Run `dbcli blacklist list` to see what is protected"
2197
+ };
2198
+ // resources/lang/zh-TW/ceremony.json
2199
+ var ceremony_default2 = {
2200
+ updated: "\u5DF2\u66F4\u65B0 {table} \u7684 {count} \u5217",
2201
+ deleted: "\u5DF2\u5F9E {table} \u522A\u9664 {count} \u5217",
2202
+ inserted: "\u5DF2\u5BEB\u5165 {count} \u5217\u5230 {table}",
2203
+ matched_nothing: "{table} \u6C92\u6709\u4EFB\u4F55\u5217\u7B26\u5408\u689D\u4EF6\uFF0C\u8CC7\u6599\u672A\u8B8A\u52D5",
2204
+ cancelled: "\u5DF2\u53D6\u6D88\uFF0C{table} \u672A\u8B8A\u52D5",
2205
+ dry_run: "\u50C5\u9810\u89BD\uFF0C{table} \u672A\u8B8A\u52D5",
2206
+ elapsed: "\u8017\u6642 {seconds} \u79D2",
2207
+ failed: "\u5931\u6557\uFF1A{reason}",
2208
+ unknown_error: "\u672A\u77E5\u7684\u932F\u8AA4",
2209
+ confirm_sql: "\u7522\u751F\u7684 SQL\uFF1A",
2210
+ confirm_command: "\u5373\u5C07\u57F7\u884C\u7684\u6307\u4EE4\uFF1A",
2211
+ confirm_params: "\u53C3\u6578\uFF1A",
2212
+ confirm_destructive_warning: "\u26A0\uFE0F \u8B66\u544A\uFF1ADELETE \u5177\u7834\u58DE\u6027\uFF0C\u57F7\u884C\u5F8C\u7121\u6CD5\u5FA9\u539F\uFF01",
2213
+ confirm_destructive_prompt: "\u78BA\u5B9A\u8981\u57F7\u884C\u9019\u500B DELETE \u55CE\uFF1F\u6B64\u64CD\u4F5C\u7121\u6CD5\u5FA9\u539F\u3002",
2214
+ confirm_destructive_warning_ddl: "\u26A0\uFE0F \u8B66\u544A\uFF1A\u9019\u500B schema \u8B8A\u66F4\u5177\u7834\u58DE\u6027\uFF0C\u57F7\u884C\u5F8C\u7121\u6CD5\u5FA9\u539F\uFF01",
2215
+ confirm_ddl_prompt: "\u78BA\u5B9A\u8981\u57F7\u884C\u9019\u500B {operation} \u55CE\uFF1F\u6B64\u64CD\u4F5C\u7121\u6CD5\u5FA9\u539F\u3002",
2216
+ confirm_prompt: "\u8981\u7E7C\u7E8C\u57F7\u884C\u9019\u500B\u64CD\u4F5C\u55CE\uFF1F",
2217
+ recovery_none: "\u6B64\u64CD\u4F5C\u7121\u6CD5\u81EA\u52D5\u9084\u539F\uFF0C\u8981\u53D6\u56DE\u5148\u524D\u7684\u8CC7\u6599\u8ACB\u5F9E\u5099\u4EFD\u56DE\u5FA9\u3002",
2218
+ recovery_retry: "\u52A0\u4E0A --recovery \u91CD\u8DD1\u53EF\u7522\u751F\u56DE\u5FA9\u8A08\u756B\uFF0C\u518D\u7528 dbcli recover \u8B80\u53D6",
2219
+ blacklist_hint: "\u57F7\u884C `dbcli blacklist list` \u67E5\u770B\u53D7\u4FDD\u8B77\u7684\u9805\u76EE"
2220
+ };
2127
2221
 
2128
2222
  // src/i18n/message-loader.ts
2129
2223
  var BUNDLED_MESSAGES = {
2130
- en: { ...messages_default, shell: shell_default },
2131
- "zh-TW": { ...messages_default2, shell: shell_default2 }
2224
+ en: { ...messages_default, shell: shell_default, ceremony: ceremony_default },
2225
+ "zh-TW": {
2226
+ ...messages_default2,
2227
+ shell: shell_default2,
2228
+ ceremony: ceremony_default2
2229
+ }
2132
2230
  };
2133
2231
 
2134
2232
  class MessageLoader {
@@ -2191,6 +2289,7 @@ class MessageLoader {
2191
2289
  }
2192
2290
  }
2193
2291
  var messageLoader = MessageLoader.getInstance();
2292
+ var t = (key) => messageLoader.t(key);
2194
2293
  var t_vars = (key, vars) => messageLoader.interpolate(key, vars);
2195
2294
 
2196
2295
  // src/utils/colors.ts
@@ -3268,12 +3367,12 @@ function detectMongoType(v) {
3268
3367
  function accumulateDocPaths(doc, prefix, acc) {
3269
3368
  for (const [k, v] of Object.entries(doc)) {
3270
3369
  const path = prefix === "" ? k : `${prefix}.${k}`;
3271
- const t = detectMongoType(v);
3370
+ const t2 = detectMongoType(v);
3272
3371
  const slot = acc.get(path) ?? { types: new Set, count: 0 };
3273
- slot.types.add(t);
3372
+ slot.types.add(t2);
3274
3373
  slot.count += 1;
3275
3374
  acc.set(path, slot);
3276
- if (t === "object" && v && typeof v === "object") {
3375
+ if (t2 === "object" && v && typeof v === "object") {
3277
3376
  accumulateDocPaths(v, path, acc);
3278
3377
  }
3279
3378
  }
@@ -4784,18 +4883,7 @@ function continuesIdentifier(sql, index) {
4784
4883
  return run.replace(/^[0-9]+(?:[eE][0-9]+)?/, "").length > 0;
4785
4884
  }
4786
4885
 
4787
- // src/core/permission-guard.ts
4788
- class PermissionError extends Error {
4789
- classification;
4790
- requiredPermission;
4791
- constructor(message, classification, requiredPermission) {
4792
- super(message);
4793
- this.classification = classification;
4794
- this.requiredPermission = requiredPermission;
4795
- this.name = "PermissionError";
4796
- Object.setPrototypeOf(this, PermissionError.prototype);
4797
- }
4798
- }
4886
+ // src/core/permission/sql-analysis.ts
4799
4887
  function normalizeSQL(sql) {
4800
4888
  return sql.replace(/--[^\n]*\n/g, `
4801
4889
  `).replace(/\/\*[\s\S]*?\*\//g, " ").trim().replace(/\s+/g, " ");
@@ -5042,6 +5130,19 @@ function determineConfidence(type, _keyword, _sql) {
5042
5130
  function removeParameterMarkers(sql) {
5043
5131
  return sql.replace(/\$\d+/g, "").replace(/\?/g, "");
5044
5132
  }
5133
+
5134
+ // src/core/permission-guard.ts
5135
+ class PermissionError extends Error {
5136
+ classification;
5137
+ requiredPermission;
5138
+ constructor(message, classification, requiredPermission) {
5139
+ super(message);
5140
+ this.classification = classification;
5141
+ this.requiredPermission = requiredPermission;
5142
+ this.name = "PermissionError";
5143
+ Object.setPrototypeOf(this, PermissionError.prototype);
5144
+ }
5145
+ }
5045
5146
  function classifyStatement(sql) {
5046
5147
  const normalized = normalizeSQL(sql);
5047
5148
  const stripped = stripCommentsAndStrings(normalized);
@@ -5108,15 +5209,38 @@ function checkPermission(sql, permission, dialect) {
5108
5209
  if (permission !== "admin" && containsMultipleStatements(sql, dialect)) {
5109
5210
  return {
5110
5211
  allowed: false,
5111
- reason: "SQL containing multiple statements is refused below admin permission, because only " + "the first statement determines the permission check. Run each statement separately.",
5112
- classification
5212
+ reason: t("errors.multiple_statements_refused"),
5213
+ classification,
5214
+ requiredPermission: "admin"
5113
5215
  };
5114
5216
  }
5217
+ return checkPermissionForClassification(classification, permission);
5218
+ }
5219
+ var TIER_GRANTS = [
5220
+ { permission: "query-only", types: ["SELECT", "SHOW", "DESCRIBE", "EXPLAIN"] },
5221
+ { permission: "read-write", types: ["INSERT", "UPDATE"] },
5222
+ { permission: "data-admin", types: ["DELETE"] }
5223
+ ];
5224
+ function minimumPermissionFor(type) {
5225
+ return TIER_GRANTS.find((tier) => tier.types.includes(type))?.permission ?? "admin";
5226
+ }
5227
+ function refusalReason(type, permission) {
5228
+ return t_vars("errors.permission_requires_level", {
5229
+ type,
5230
+ minimum: minimumPermissionFor(type),
5231
+ permission
5232
+ });
5233
+ }
5234
+ function checkPermissionForClassification(classification, permission) {
5115
5235
  if (permission !== "admin" && classification.escalatedFrom) {
5116
5236
  return {
5117
5237
  allowed: false,
5118
- reason: `This statement opens as a read but contains an executable ` + `${classification.escalatedFrom}. A write hidden inside a read statement ` + `requires admin permission (current level: ${permission}).`,
5119
- classification
5238
+ reason: t_vars("errors.escalated_write_requires_admin", {
5239
+ keyword: classification.escalatedFrom,
5240
+ permission
5241
+ }),
5242
+ classification,
5243
+ requiredPermission: "admin"
5120
5244
  };
5121
5245
  }
5122
5246
  if (permission === "admin") {
@@ -5126,62 +5250,51 @@ function checkPermission(sql, permission, dialect) {
5126
5250
  classification
5127
5251
  };
5128
5252
  }
5129
- if (permission === "data-admin") {
5130
- const allowedTypes = ["SELECT", "INSERT", "UPDATE", "DELETE", "SHOW", "DESCRIBE", "EXPLAIN"];
5131
- if (allowedTypes.includes(classification.type)) {
5132
- return {
5133
- allowed: true,
5134
- reason: `${classification.type} operation allowed in data-admin mode`,
5135
- classification
5136
- };
5137
- }
5138
- return {
5139
- allowed: false,
5140
- reason: `${classification.type} operation requires admin permission`,
5141
- classification
5142
- };
5143
- }
5144
- if (permission === "read-write") {
5145
- const allowedTypes = ["SELECT", "INSERT", "UPDATE", "SHOW", "DESCRIBE", "EXPLAIN"];
5146
- if (allowedTypes.includes(classification.type)) {
5147
- return {
5148
- allowed: true,
5149
- reason: `${classification.type} operation allowed in read-write mode`,
5150
- classification
5151
- };
5152
- }
5153
- return {
5154
- allowed: false,
5155
- reason: `${classification.type} operation requires data-admin or admin permission`,
5156
- classification
5157
- };
5158
- }
5159
- if (permission === "query-only") {
5160
- const allowedTypes = ["SELECT", "SHOW", "DESCRIBE", "EXPLAIN"];
5253
+ const tierIndex = TIER_GRANTS.findIndex((tier) => tier.permission === permission);
5254
+ if (tierIndex !== -1) {
5255
+ const allowedTypes = TIER_GRANTS.slice(0, tierIndex + 1).flatMap((tier) => tier.types);
5161
5256
  if (allowedTypes.includes(classification.type)) {
5162
5257
  return {
5163
5258
  allowed: true,
5164
- reason: `${classification.type} operation allowed in query-only mode`,
5259
+ reason: `${classification.type} operation allowed in ${permission} mode`,
5165
5260
  classification
5166
5261
  };
5167
5262
  }
5168
- const isUnknown = classification.type === "UNKNOWN";
5263
+ const isUnknown = permission === "query-only" && classification.type === "UNKNOWN";
5169
5264
  return {
5170
5265
  allowed: false,
5171
- reason: isUnknown ? `Unrecognised SQL statement (current level: query-only). Security policy requires read-write+ for unknown statements. If this is a legitimate read-only statement, please open an issue at https://github.com/CarlLee1983/dbcli/issues.` : `${classification.type} operation requires read-write or admin permission`,
5172
- classification
5266
+ reason: isUnknown ? t("errors.unknown_statement_query_only") : refusalReason(classification.type, permission),
5267
+ classification,
5268
+ requiredPermission: isUnknown ? "read-write" : minimumPermissionFor(classification.type)
5173
5269
  };
5174
5270
  }
5175
5271
  return {
5176
5272
  allowed: false,
5177
5273
  reason: `Unknown permission level: ${permission}`,
5178
- classification
5274
+ classification,
5275
+ requiredPermission: "admin"
5276
+ };
5277
+ }
5278
+ function classificationForType(type) {
5279
+ return {
5280
+ type,
5281
+ isDangerous: isDestructiveOperation(type),
5282
+ keywords: [type],
5283
+ isComposite: false,
5284
+ confidence: "HIGH"
5179
5285
  };
5180
5286
  }
5287
+ function enforcePermissionForType(type, permission) {
5288
+ const classification = classificationForType(type);
5289
+ const result = checkPermissionForClassification(classification, permission);
5290
+ if (!result.allowed) {
5291
+ throw new PermissionError(result.reason, classification, minimumPermissionFor(type));
5292
+ }
5293
+ }
5181
5294
  function enforcePermission(sql, permission, dialect) {
5182
5295
  const result = checkPermission(sql, permission, dialect);
5183
5296
  if (!result.allowed) {
5184
- throw new PermissionError(result.reason, result.classification, permission);
5297
+ throw new PermissionError(result.reason, result.classification, result.requiredPermission ?? "admin");
5185
5298
  }
5186
5299
  return result.classification;
5187
5300
  }
@@ -5285,7 +5398,7 @@ function extractTableNameFromError(errorMessage) {
5285
5398
  async function getAllTablesFromAdapter(adapter) {
5286
5399
  try {
5287
5400
  const tables = await adapter.listTables();
5288
- return tables.map((t) => t.name);
5401
+ return tables.map((t2) => t2.name);
5289
5402
  } catch (error) {
5290
5403
  console.warn("Failed to list tables for suggestions:", error);
5291
5404
  return [];
@@ -5937,100 +6050,6 @@ function inferColumnType(value) {
5937
6050
  }
5938
6051
  return "unknown";
5939
6052
  }
5940
- // src/utils/prompts.ts
5941
- var promptsUnavailableReported = false;
5942
- async function loadInquirer() {
5943
- try {
5944
- return await import("@inquirer/prompts");
5945
- } catch (error) {
5946
- if (!promptsUnavailableReported) {
5947
- promptsUnavailableReported = true;
5948
- const reason = error instanceof Error ? error.message : String(error);
5949
- process.stderr.write(`[dbcli] rich interactive prompts are unavailable (${reason}); falling back to plain-text input
5950
- `);
5951
- }
5952
- return;
5953
- }
5954
- }
5955
- async function readLineFromStdin(prompt = "") {
5956
- return new Promise((resolve) => {
5957
- if (prompt) {
5958
- process.stdout.write(prompt);
5959
- }
5960
- let data = "";
5961
- const chunks = [];
5962
- const onData = (chunk) => {
5963
- chunks.push(chunk);
5964
- data = Buffer.concat(chunks).toString();
5965
- const lines = data.split(`
5966
- `);
5967
- if (lines.length > 1) {
5968
- process.stdin.pause();
5969
- process.stdin.removeListener("data", onData);
5970
- process.stdin.removeListener("end", onEnd);
5971
- resolve((lines[0] ?? "").trim());
5972
- }
5973
- };
5974
- const onEnd = () => {
5975
- process.stdin.removeListener("data", onData);
5976
- resolve(data.trim());
5977
- };
5978
- process.stdin.on("data", onData);
5979
- process.stdin.on("end", onEnd);
5980
- process.stdin.resume();
5981
- });
5982
- }
5983
- async function textFallback(message, defaultValue) {
5984
- const displayMessage = defaultValue ? `${message} [${defaultValue}]: ` : `${message}: `;
5985
- const answer = await readLineFromStdin(displayMessage);
5986
- return answer.trim() || defaultValue || "";
5987
- }
5988
- async function selectFallback(message, choices) {
5989
- console.log(message);
5990
- choices.forEach((choice, index) => {
5991
- console.log(` ${index + 1}) ${choice}`);
5992
- });
5993
- const answer = await readLineFromStdin("Select option (number): ");
5994
- const selectedIndex = parseInt(answer, 10) - 1;
5995
- if (selectedIndex >= 0 && selectedIndex < choices.length) {
5996
- return choices[selectedIndex] ?? choices[0] ?? "";
5997
- }
5998
- return choices[0] ?? "";
5999
- }
6000
- async function confirmFallback(message) {
6001
- const answer = await readLineFromStdin(`${message} (y/n): `);
6002
- return answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
6003
- }
6004
- async function text(message, defaultValue) {
6005
- if (!process.stdin.isTTY)
6006
- return textFallback(message, defaultValue);
6007
- const inquirer = await loadInquirer();
6008
- if (!inquirer)
6009
- return textFallback(message, defaultValue);
6010
- return await inquirer.input({ message, default: defaultValue });
6011
- }
6012
- async function select(message, choices) {
6013
- if (!process.stdin.isTTY)
6014
- return await selectFallback(message, choices);
6015
- const inquirer = await loadInquirer();
6016
- if (!inquirer)
6017
- return await selectFallback(message, choices);
6018
- return await inquirer.select({ message, choices });
6019
- }
6020
- async function confirm(message) {
6021
- if (!process.stdin.isTTY)
6022
- return await confirmFallback(message);
6023
- const inquirer = await loadInquirer();
6024
- if (!inquirer)
6025
- return await confirmFallback(message);
6026
- return await inquirer.confirm({ message });
6027
- }
6028
- var promptUser = {
6029
- text,
6030
- select,
6031
- confirm
6032
- };
6033
-
6034
6053
  // src/types/blacklist.ts
6035
6054
  class BlacklistError extends Error {
6036
6055
  tableName;
@@ -6078,8 +6097,8 @@ class DataExecutor {
6078
6097
  const timestamp = new Date().toISOString();
6079
6098
  try {
6080
6099
  this.checkBlacklist("INSERT", tableName);
6081
- enforcePermission("INSERT INTO dummy", this.permission);
6082
- return await this.executeMutation("insert", this.buildInsertSql(tableName, data, schema), timestamp, options, { prompt: "Proceed with this operation?" });
6100
+ enforcePermissionForType("INSERT", this.permission);
6101
+ return await this.executeMutation("insert", this.buildInsertSql(tableName, data, schema), timestamp, options, { destructive: false });
6083
6102
  } catch (error) {
6084
6103
  return this.handleMutationError("insert", timestamp, error);
6085
6104
  }
@@ -6088,8 +6107,8 @@ class DataExecutor {
6088
6107
  const timestamp = new Date().toISOString();
6089
6108
  try {
6090
6109
  this.checkBlacklist("UPDATE", tableName);
6091
- enforcePermission("UPDATE dummy", this.permission);
6092
- return await this.executeMutation("update", this.buildUpdateSql(tableName, data, where, schema), timestamp, options, { prompt: "Proceed with this operation?" });
6110
+ enforcePermissionForType("UPDATE", this.permission);
6111
+ return await this.executeMutation("update", this.buildUpdateSql(tableName, data, where, schema), timestamp, options, { destructive: false });
6093
6112
  } catch (error) {
6094
6113
  return this.handleMutationError("update", timestamp, error);
6095
6114
  }
@@ -6098,19 +6117,8 @@ class DataExecutor {
6098
6117
  const timestamp = new Date().toISOString();
6099
6118
  try {
6100
6119
  this.checkBlacklist("DELETE", tableName);
6101
- if (this.permission !== "data-admin" && this.permission !== "admin") {
6102
- return {
6103
- status: "error",
6104
- operation: "delete",
6105
- rows_affected: 0,
6106
- timestamp,
6107
- error: "Permission denied: DELETE operation requires Data-Admin or Admin permission."
6108
- };
6109
- }
6110
- return await this.executeMutation("delete", this.buildDeleteSql(tableName, where, schema), timestamp, options, {
6111
- warning: "\u26A0\uFE0F Warning: DELETE operation is destructive and cannot be undone!",
6112
- prompt: "Are you sure you want to execute this DELETE operation? This cannot be undone."
6113
- });
6120
+ enforcePermissionForType("DELETE", this.permission);
6121
+ return await this.executeMutation("delete", this.buildDeleteSql(tableName, where, schema), timestamp, options, { destructive: true });
6114
6122
  } catch (error) {
6115
6123
  return this.handleMutationError("delete", timestamp, error);
6116
6124
  }
@@ -6124,31 +6132,31 @@ class DataExecutor {
6124
6132
  checkBlacklist(operation, tableName) {
6125
6133
  this.blacklistValidator?.checkTableBlacklist(operation, tableName, []);
6126
6134
  }
6127
- async executeMutation(operation, statement, timestamp, options, confirmation) {
6135
+ async executeMutation(operation, statement, timestamp, options, { destructive }) {
6128
6136
  if (options?.dryRun) {
6129
- return this.successResult(operation, 0, timestamp, statement.sql);
6137
+ return this.outcomeResult("dry_run", operation, 0, timestamp, statement.sql);
6130
6138
  }
6131
6139
  if (!options?.force) {
6132
- if (confirmation.warning) {
6133
- console.log(`
6134
- ${confirmation.warning}`);
6140
+ if (!options?.confirm) {
6141
+ throw new Error(`Refusing to ${operation} without confirmation: no confirmation handler was supplied. ` + "Pass options.confirm to ask the user, or options.force to proceed unattended.");
6135
6142
  }
6136
- console.log(`
6137
- Generated SQL:`);
6138
- console.log(` ${statement.sql}`);
6139
- console.log(`
6140
- Parameters:`);
6141
- console.log(` ${JSON.stringify(statement.params, null, 2)}`);
6142
- if (!await promptUser.confirm(confirmation.prompt)) {
6143
- return this.successResult(operation, 0, timestamp, statement.sql);
6143
+ const proceed = await options.confirm({
6144
+ operation,
6145
+ engine: "sql",
6146
+ sql: statement.sql,
6147
+ params: statement.params,
6148
+ destructive
6149
+ });
6150
+ if (!proceed) {
6151
+ return this.outcomeResult("cancelled", operation, 0, timestamp, statement.sql);
6144
6152
  }
6145
6153
  }
6146
6154
  const result = await this.adapter.execute(statement.sql, statement.params);
6147
- return this.successResult(operation, result.affectedRows, timestamp, statement.sql);
6155
+ return this.outcomeResult("success", operation, result.affectedRows, timestamp, statement.sql);
6148
6156
  }
6149
- successResult(operation, rowsAffected, timestamp, sql) {
6157
+ outcomeResult(status, operation, rowsAffected, timestamp, sql) {
6150
6158
  return {
6151
- status: "success",
6159
+ status,
6152
6160
  operation,
6153
6161
  rows_affected: rowsAffected,
6154
6162
  timestamp,
@@ -6159,13 +6167,13 @@ Parameters:`);
6159
6167
  if (error instanceof BlacklistError) {
6160
6168
  throw error;
6161
6169
  }
6162
- if (error instanceof PermissionError && operation !== "delete") {
6170
+ if (error instanceof PermissionError) {
6163
6171
  return {
6164
6172
  status: "error",
6165
6173
  operation,
6166
6174
  rows_affected: 0,
6167
6175
  timestamp,
6168
- error: `Permission denied: Query-only mode only allows SELECT. Use Read-Write or Admin mode to execute ${operation.toUpperCase()}.`
6176
+ error: t_vars("errors.permission_denied_reason", { reason: error.message })
6169
6177
  };
6170
6178
  }
6171
6179
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -6427,8 +6435,8 @@ var ZodParsedType = util.arrayToEnum([
6427
6435
  "set"
6428
6436
  ]);
6429
6437
  var getParsedType = (data) => {
6430
- const t = typeof data;
6431
- switch (t) {
6438
+ const t2 = typeof data;
6439
+ switch (t2) {
6432
6440
  case "undefined":
6433
6441
  return ZodParsedType.undefined;
6434
6442
  case "string":
@@ -10755,43 +10763,11 @@ function listConnections(config) {
10755
10763
  });
10756
10764
  }
10757
10765
  // src/core/config-v2-mutations.ts
10758
- import { join as join8 } from "path";
10759
10766
  var SQL_SYSTEMS = ["postgresql", "mysql", "mariadb"];
10760
10767
  function envVarNameFor(connName, field) {
10761
10768
  const slug = connName.toUpperCase().replace(/[^A-Z0-9]+/g, "_").replace(/^_+|_+$/g, "");
10762
10769
  return `DBCLI_${slug}_${field.toUpperCase()}`;
10763
10770
  }
10764
- async function writeConnectionSecret(projectPath, connName, field, value) {
10765
- assertConfigMutationApproved();
10766
- if (value.includes(`
10767
- `) || value.includes("\r")) {
10768
- throw new Error("secret value \u4E0D\u53EF\u5305\u542B\u63DB\u884C\u5B57\u5143");
10769
- }
10770
- const config = await readV2Config(projectPath);
10771
- const conn = config.connections[connName];
10772
- if (!conn)
10773
- throw new Error(`\u9023\u7DDA '${connName}' \u4E0D\u5B58\u5728`);
10774
- const storagePath = await resolveConfigStoragePath(projectPath);
10775
- const envFile = conn.envFile ?? `.env.${connName}`;
10776
- const envPath = join8(storagePath, envFile);
10777
- const varName = envVarNameFor(connName, field);
10778
- let content = "";
10779
- const file = Bun.file(envPath);
10780
- if (await file.exists())
10781
- content = await file.text();
10782
- const line = `${varName}=${value}`;
10783
- const re = new RegExp(`^${varName}=.*$`, "m");
10784
- if (re.test(content)) {
10785
- content = content.replace(re, line);
10786
- } else {
10787
- content = content.length && !content.endsWith(`
10788
- `) ? `${content}
10789
- ${line}
10790
- ` : `${content}${line}
10791
- `;
10792
- }
10793
- await Bun.write(envPath, content);
10794
- }
10795
10771
  function removeConnection(config, name) {
10796
10772
  if (!(name in config.connections))
10797
10773
  throw new Error(`\u9023\u7DDA '${name}' \u4E0D\u5B58\u5728`);
@@ -10853,6 +10829,135 @@ function upsertConnection(config, input) {
10853
10829
  connections: { ...config.connections, [input.name]: connection }
10854
10830
  };
10855
10831
  }
10832
+ // src/core/connection-credential.ts
10833
+ import { join as join8 } from "path";
10834
+
10835
+ // src/core/env-file-writer.ts
10836
+ import { chmod as chmod2, mkdir as mkdir3, readFile as readFile2, writeFile } from "fs/promises";
10837
+ import { dirname as dirname2 } from "path";
10838
+ var SECRET_FILE_MODE = 384;
10839
+ function escapeForRegExp(value) {
10840
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
10841
+ }
10842
+ async function upsertEnvVar(envPath, varName, value) {
10843
+ let content = "";
10844
+ try {
10845
+ content = await readFile2(envPath, "utf8");
10846
+ } catch (cause) {
10847
+ const code = cause.code;
10848
+ if (code !== "ENOENT")
10849
+ throw cause;
10850
+ await mkdir3(dirname2(envPath), { recursive: true });
10851
+ }
10852
+ const line = `${varName}="${value}"`;
10853
+ const existing = new RegExp(`^${escapeForRegExp(varName)}=.*$`, "m");
10854
+ if (existing.test(content)) {
10855
+ content = content.replace(existing, () => line);
10856
+ } else {
10857
+ content = content.length && !content.endsWith(`
10858
+ `) ? `${content}
10859
+ ${line}
10860
+ ` : `${content}${line}
10861
+ `;
10862
+ }
10863
+ await writeFile(envPath, content, { mode: SECRET_FILE_MODE });
10864
+ await chmod2(envPath, SECRET_FILE_MODE);
10865
+ }
10866
+
10867
+ // src/core/connection-credential.ts
10868
+ var DEFAULT_ENV_FILE = ".env.local";
10869
+ var V1_VAR_NAME = "DBCLI_PASSWORD";
10870
+ var V1_CONNECTION_NAME = "default";
10871
+ async function readRawConfig(storagePath) {
10872
+ const configPath = join8(storagePath, "config.json");
10873
+ const file = Bun.file(configPath);
10874
+ if (!await file.exists()) {
10875
+ throw new ConfigError(`\u627E\u4E0D\u5230\u8A2D\u5B9A\u6A94\uFF1A${configPath}`);
10876
+ }
10877
+ return JSON.parse(await file.text());
10878
+ }
10879
+ function envRefName(value) {
10880
+ if (typeof value === "object" && value !== null && "$env" in value) {
10881
+ return String(value.$env);
10882
+ }
10883
+ return;
10884
+ }
10885
+ async function resolvePasswordTarget(projectPath, connectionName) {
10886
+ const storagePath = await resolveConfigStoragePath(projectPath);
10887
+ const raw = await readRawConfig(storagePath);
10888
+ if (detectConfigVersion(raw) !== 2) {
10889
+ if (connectionName && connectionName !== V1_CONNECTION_NAME) {
10890
+ throw new ConfigError(`\u9019\u662F v1 \u8A2D\u5B9A\uFF0C\u53EA\u6709\u4E00\u689D\u9023\u7DDA\uFF0C\u7121\u6CD5\u6307\u5B9A\u9023\u7DDA\u540D\u7A31 '${connectionName}'\u3002` + `\u9700\u8981\u591A\u9023\u7DDA\u8ACB\u5148\u7528 dbcli init --conn-name <name> \u5347\u7D1A\u5230 v2\u3002`);
10891
+ }
10892
+ const connection2 = raw.connection ?? {};
10893
+ const customRef = envRefName(connection2.password);
10894
+ if (customRef !== undefined && customRef !== V1_VAR_NAME) {
10895
+ throw new ConfigError(`\u9019\u500B v1 \u8A2D\u5B9A\u7684\u5BC6\u78BC\u4F86\u81EA\u74B0\u5883\u8B8A\u6578 '${customRef}'\uFF0Cdbcli \u7121\u6CD5\u4EE3\u70BA\u8F2A\u66FF\u3002` + `\u8ACB\u76F4\u63A5\u66F4\u65B0\u8A72\u74B0\u5883\u8B8A\u6578\uFF0C\u6216\u7528 dbcli init --conn-name <name> \u5347\u7D1A\u5230 v2 \u5F8C\u518D\u8F2A\u66FF\u3002`);
10896
+ }
10897
+ return {
10898
+ connection: V1_CONNECTION_NAME,
10899
+ envFile: DEFAULT_ENV_FILE,
10900
+ varName: V1_VAR_NAME,
10901
+ convertedToEnvRef: false
10902
+ };
10903
+ }
10904
+ const config = await readV2Config(projectPath);
10905
+ const targetName = connectionName ?? config.default;
10906
+ const connection = config.connections[targetName];
10907
+ if (!connection) {
10908
+ throw new ConfigError(connectionNotFoundMessage(targetName, Object.keys(config.connections)));
10909
+ }
10910
+ const referencedVar = envRefName(connection.password);
10911
+ return {
10912
+ connection: targetName,
10913
+ envFile: connection.envFile ?? DEFAULT_ENV_FILE,
10914
+ varName: referencedVar ?? envVarNameFor(targetName, "password"),
10915
+ convertedToEnvRef: referencedVar === undefined
10916
+ };
10917
+ }
10918
+ function assertSingleLine(value) {
10919
+ if (value.includes(`
10920
+ `) || value.includes("\r")) {
10921
+ throw new ConfigError("\u5BC6\u78BC\u4E0D\u53EF\u5305\u542B\u63DB\u884C\u5B57\u5143");
10922
+ }
10923
+ }
10924
+ async function stripV1LiteralPassword(storagePath, raw) {
10925
+ const connection = raw.connection ?? {};
10926
+ if (typeof connection.password !== "string")
10927
+ return;
10928
+ const stripped = { ...raw, connection: { ...connection } };
10929
+ delete stripped.connection.password;
10930
+ await writeConfigWithIntegrity(storagePath, JSON.stringify(stripped, null, 2));
10931
+ }
10932
+ async function setConnectionPassword(projectPath, connectionName, password) {
10933
+ assertConfigMutationApproved();
10934
+ assertSingleLine(password);
10935
+ const target = await resolvePasswordTarget(projectPath, connectionName);
10936
+ const storagePath = await resolveConfigStoragePath(projectPath);
10937
+ const raw = await readRawConfig(storagePath);
10938
+ await upsertEnvVar(join8(storagePath, target.envFile), target.varName, password);
10939
+ if (detectConfigVersion(raw) !== 2) {
10940
+ await stripV1LiteralPassword(storagePath, raw);
10941
+ return target;
10942
+ }
10943
+ const config = await readV2Config(projectPath);
10944
+ const connection = config.connections[target.connection];
10945
+ const needsEnvFile = connection.envFile === undefined;
10946
+ if (target.convertedToEnvRef || needsEnvFile) {
10947
+ await writeV2Config(projectPath, {
10948
+ ...config,
10949
+ connections: {
10950
+ ...config.connections,
10951
+ [target.connection]: {
10952
+ ...connection,
10953
+ envFile: target.envFile,
10954
+ ...target.convertedToEnvRef && { password: { $env: target.varName } }
10955
+ }
10956
+ }
10957
+ });
10958
+ }
10959
+ return target;
10960
+ }
10856
10961
  // src/utils/config-error-format.ts
10857
10962
  var SUPPORTED_SYSTEMS = [
10858
10963
  "postgresql",
@@ -10938,7 +11043,7 @@ function isZodError(error) {
10938
11043
 
10939
11044
  // src/core/config.ts
10940
11045
  import { join as join9 } from "path";
10941
- import { mkdir as mkdir3 } from "fs/promises";
11046
+ import { mkdir as mkdir4 } from "fs/promises";
10942
11047
  // src/agent-core/env-ref.ts
10943
11048
  function resolveEnvRef(value, fieldName, env = process.env) {
10944
11049
  if (typeof value === "string")
@@ -11008,7 +11113,11 @@ function resolveEnvReferences(config, env, parentKey) {
11008
11113
  }
11009
11114
  function parseEnvPassword(content) {
11010
11115
  const match = content.match(/^DBCLI_PASSWORD=(.+)$/m);
11011
- return match?.[1] != null ? match[1].trim() : null;
11116
+ if (match?.[1] == null)
11117
+ return null;
11118
+ const raw = match[1].trim();
11119
+ const quoted = raw.startsWith('"') && raw.endsWith('"') || raw.startsWith("'") && raw.endsWith("'");
11120
+ return quoted && raw.length >= 2 ? raw.slice(1, -1) : raw;
11012
11121
  }
11013
11122
  var configModule = {
11014
11123
  async read(path, connectionName, options = {}) {
@@ -11187,7 +11296,7 @@ ${formatConfigValidationError(error, raw)}`);
11187
11296
  isDirectory = false;
11188
11297
  }
11189
11298
  if (isDirectory || path.endsWith(".dbcli") || path === storagePath && isDirectory) {
11190
- await mkdir3(storagePath, { recursive: true });
11299
+ await mkdir4(storagePath, { recursive: true });
11191
11300
  const hasEnvReferences = isEnvReference(config.connection.password);
11192
11301
  if (hasEnvReferences) {
11193
11302
  const configJson = JSON.stringify(config, null, 2);
@@ -11543,9 +11652,10 @@ var readConfig = (path, connectionName) => configModule.read(path, connectionNam
11543
11652
  export {
11544
11653
  writeV2Config,
11545
11654
  writeProjectBinding,
11546
- writeConnectionSecret,
11547
11655
  upsertConnection,
11548
11656
  setDefaultConnection,
11657
+ setConnectionPassword,
11658
+ resolvePasswordTarget,
11549
11659
  resolveConnection,
11550
11660
  resolveConfigStoragePath,
11551
11661
  removeConnection,