@carllee1983/dbcli 1.57.0 → 2.0.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/.cursor/rules/dbcli.mdc +19 -2
- package/.cursor/skills/dbcli/reference.md +55 -4
- package/.github/skills/dbcli/SKILL.md +19 -2
- package/.github/skills/dbcli/reference.md +55 -4
- package/CHANGELOG.md +71 -0
- package/assets/SKILL.md +19 -2
- package/assets/SKILL.zh-TW.md +15 -1
- package/assets/reference.md +55 -4
- package/dist/cli-runtime.mjs +1323 -688
- package/dist/cli.mjs +4 -2
- package/dist/core.d.ts +79 -24
- package/dist/core.mjs +349 -343
- package/package.json +4 -2
- package/plugins/dbcli-agent/skills/dbcli/SKILL.md +19 -2
- package/plugins/dbcli-agent/skills/dbcli/reference.md +55 -4
- package/skills/dbcli/SKILL.md +19 -2
- package/skills/dbcli/reference.md +55 -4
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,
|
|
122
|
-
typeof L.emitWarning == "function" ? L.emitWarning(u, e,
|
|
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
|
|
129
|
-
if (!
|
|
128
|
+
let t2 = U(e);
|
|
129
|
+
if (!t2)
|
|
130
130
|
return [];
|
|
131
131
|
u.#o = true;
|
|
132
|
-
let i = new u(e,
|
|
132
|
+
let i = new u(e, t2);
|
|
133
133
|
return u.#o = false, i;
|
|
134
134
|
}
|
|
135
|
-
constructor(e,
|
|
135
|
+
constructor(e, t2) {
|
|
136
136
|
if (!u.#o)
|
|
137
137
|
throw new TypeError("instantiate Stack using Stack.create(n)");
|
|
138
|
-
this.heap = new
|
|
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: (
|
|
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:
|
|
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,
|
|
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 =
|
|
244
|
+
let E = t2 ? U(t2) : Array;
|
|
245
245
|
if (!E)
|
|
246
|
-
throw new Error("invalid max value: " +
|
|
247
|
-
if (this.#o =
|
|
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:
|
|
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),
|
|
281
|
-
this.#d = e, this.#F =
|
|
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
|
-
|
|
284
|
+
t2[h] = a !== 0 ? o : 0, e[h] = a, s(h, a);
|
|
285
285
|
}, this.#D = (h) => {
|
|
286
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 = (
|
|
336
|
-
this.#b -= e[
|
|
337
|
-
}, this.#V = (
|
|
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,
|
|
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 = (
|
|
350
|
-
if (e[
|
|
351
|
-
let n = this.#c - e[
|
|
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[
|
|
355
|
+
this.#b += e[t2], s && (s.entrySize = i, s.totalCalculatedSize = this.#b);
|
|
356
356
|
};
|
|
357
357
|
}
|
|
358
358
|
#R = (e) => {};
|
|
359
|
-
#j = (e,
|
|
360
|
-
#V = (e,
|
|
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
|
|
368
|
-
|
|
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
|
|
373
|
-
|
|
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
|
|
389
|
-
|
|
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
|
|
395
|
-
|
|
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,
|
|
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],
|
|
414
|
+
return this.#C(this.#i[i], t2);
|
|
415
415
|
}
|
|
416
416
|
}
|
|
417
|
-
forEach(e,
|
|
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(
|
|
420
|
+
n !== undefined && e.call(t2, n, this.#i[i], this);
|
|
421
421
|
}
|
|
422
422
|
}
|
|
423
|
-
rforEach(e,
|
|
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(
|
|
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
|
|
432
|
-
this.#p(
|
|
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
|
|
437
|
-
if (
|
|
436
|
+
let t2 = this.#s.get(e);
|
|
437
|
+
if (t2 === undefined)
|
|
438
438
|
return;
|
|
439
|
-
let i = this.#t[
|
|
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[
|
|
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.#_[
|
|
450
|
+
return this.#_ && (n.size = this.#_[t2]), n;
|
|
451
451
|
}
|
|
452
452
|
dump() {
|
|
453
453
|
let e = [];
|
|
454
|
-
for (let
|
|
455
|
-
let i = this.#i[
|
|
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[
|
|
461
|
-
let h = this.#m.now() - this.#F[
|
|
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.#_[
|
|
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 [
|
|
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(
|
|
475
|
+
this.#W(t2, i.value, i);
|
|
476
476
|
}
|
|
477
477
|
}
|
|
478
|
-
set(e,
|
|
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,
|
|
481
|
-
let n = this.#W(e,
|
|
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,
|
|
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 (
|
|
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(
|
|
489
|
-
o && !m && (o.value =
|
|
490
|
-
let _ = this.#V(e,
|
|
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] =
|
|
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 (
|
|
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 !==
|
|
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] =
|
|
508
|
-
let f = d && this.#e(d) ? d.__staleWhileFetching : d, y = f === undefined ? "add" :
|
|
509
|
-
o && (o.set = y, f !== undefined && (o.oldValue = f)), this.#x && this.onInsert?.(
|
|
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?.(
|
|
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,
|
|
534
|
-
for (;
|
|
535
|
-
this.#S?.(...
|
|
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
|
|
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(
|
|
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,
|
|
546
|
-
let { status: i = w.hasSubscribers ? {} : undefined } =
|
|
547
|
-
|
|
548
|
-
let s = this.#Y(e,
|
|
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,
|
|
552
|
-
let { updateAgeOnHas: i = this.updateAgeOnHas, status: s } =
|
|
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,
|
|
566
|
-
let { status: i = D() ? {} : undefined } =
|
|
567
|
-
i && (i.op = "peek", i.key = e, i.cache = this),
|
|
568
|
-
let s = this.#J(e,
|
|
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,
|
|
572
|
-
let { status: i, allowStale: s = this.allowStale } =
|
|
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,
|
|
581
|
-
let n =
|
|
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[
|
|
591
|
-
return (g === c || g === undefined && S && y) && (f === undefined ? b.__staleWhileFetching !== undefined ? this.#t[
|
|
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[
|
|
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
|
|
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
|
|
612
|
-
return !!
|
|
611
|
+
let t2 = e;
|
|
612
|
+
return !!t2 && t2 instanceof Promise && t2.hasOwnProperty("__staleWhileFetching") && t2.__abortController instanceof AbortController;
|
|
613
613
|
}
|
|
614
|
-
fetch(e,
|
|
615
|
-
let i = W.hasSubscribers, { status: s = D() ? {} : undefined } =
|
|
616
|
-
|
|
617
|
-
let n = this.#k(e,
|
|
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,
|
|
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 } =
|
|
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,
|
|
643
|
-
let i = W.hasSubscribers, { status: s = D() ? {} : undefined } =
|
|
644
|
-
|
|
645
|
-
let n = this.#K(e,
|
|
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,
|
|
649
|
-
let i = await this.#k(e,
|
|
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,
|
|
655
|
-
let { status: i = w.hasSubscribers ? {} : undefined } =
|
|
656
|
-
|
|
657
|
-
let s = this.#Q(e,
|
|
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,
|
|
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 } =
|
|
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,
|
|
673
|
-
let { status: i = w.hasSubscribers ? {} : undefined } =
|
|
674
|
-
|
|
675
|
-
let s = this.#C(e,
|
|
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,
|
|
679
|
-
let { allowStale: i = this.allowStale, updateAgeOnGet: s = this.updateAgeOnGet, noDeleteOnStaleGet: n = this.noDeleteOnStaleGet, status: r } =
|
|
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,
|
|
688
|
-
this.#u[
|
|
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,
|
|
697
|
-
w.hasSubscribers && w.publish({ op: "delete", delete:
|
|
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(
|
|
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,
|
|
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
|
|
732
|
-
let i = this.#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[
|
|
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
|
|
743
|
-
|
|
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
|
|
748
|
-
for (;i =
|
|
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",
|
|
@@ -1973,6 +1983,12 @@ var messages_default2 = {
|
|
|
1973
1983
|
invalid_config: "\u914D\u7F6E\u7121\u6548\uFF1A{field}",
|
|
1974
1984
|
connection_failed: "\u7121\u6CD5\u9023\u63A5\u5230\u8CC7\u6599\u5EAB\uFF1A{message}",
|
|
1975
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}",
|
|
1976
1992
|
table_not_found: "\u627E\u4E0D\u5230\u8868\u683C\uFF1A{table}",
|
|
1977
1993
|
unsupported_lang: "\u4E0D\u652F\u63F4\u7684\u8A9E\u8A00 '{lang}'\uFF0C\u4F7F\u7528\u82F1\u6587",
|
|
1978
1994
|
invalid_json: "\u7121\u6548\u7684 JSON\uFF1A{message}",
|
|
@@ -1994,7 +2010,8 @@ var messages_default2 = {
|
|
|
1994
2010
|
\u6216\u4F7F\u7528\u4E92\u52D5\u6A21\u5F0F\uFF1A\u57F7\u884C "dbcli init --use-env-refs"\uFF08\u4E0D\u52A0 --no-interactive\uFF09`,
|
|
1995
2011
|
env_var_not_defined: `\u7121\u6CD5\u6E2C\u8A66\u9023\u7DDA\uFF1A\u74B0\u5883\u8B8A\u6578 {envKey} \u672A\u5B9A\u7FA9\u3002
|
|
1996
2012
|
\u8ACB\u5728 .env \u6216\u74B0\u5883\u8B8A\u6578\u4E2D\u8A2D\u5B9A {envKey}\u3002
|
|
1997
|
-
\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"
|
|
1998
2015
|
},
|
|
1999
2016
|
success: {
|
|
2000
2017
|
inserted: "\u6210\u529F\u63D2\u5165 {count} \u5217",
|
|
@@ -2005,19 +2022,22 @@ var messages_default2 = {
|
|
|
2005
2022
|
insert: {
|
|
2006
2023
|
description: "\u63D2\u5165\u8CC7\u6599\u5230\u8868\u683C",
|
|
2007
2024
|
prompt_data: "\u8F38\u5165\u8981\u63D2\u5165\u7684 JSON \u8CC7\u6599\uFF1A",
|
|
2008
|
-
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"
|
|
2009
2027
|
},
|
|
2010
2028
|
update: {
|
|
2011
2029
|
description: "\u66F4\u65B0\u8868\u683C\u4E2D\u7684\u8CC7\u6599",
|
|
2012
2030
|
prompt_where: "\u8F38\u5165 WHERE \u5B50\u53E5 (\u4F8B\u5982\uFF1Aid=1)\uFF1A",
|
|
2013
2031
|
prompt_set: '\u8F38\u5165 JSON \u66F4\u65B0 (\u4F8B\u5982\uFF1A{"status": "active"})\uFF1A',
|
|
2014
|
-
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"
|
|
2015
2034
|
},
|
|
2016
2035
|
delete: {
|
|
2017
2036
|
description: "\u522A\u9664\u8868\u683C\u4E2D\u7684\u8CC7\u6599",
|
|
2018
2037
|
prompt_where: "\u8F38\u5165 WHERE \u5B50\u53E5 (\u4F8B\u5982\uFF1Aid=1)\uFF1A",
|
|
2019
2038
|
confirm: "\u522A\u9664 {table} \u4E2D\u7684\u5217\uFF1F (y/n)\uFF1A",
|
|
2020
|
-
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"
|
|
2021
2041
|
},
|
|
2022
2042
|
export: {
|
|
2023
2043
|
description: "\u532F\u51FA\u67E5\u8A62\u7D50\u679C",
|
|
@@ -2152,11 +2172,95 @@ var shell_default2 = {
|
|
|
2152
2172
|
rows_display: "{count} \u7B46\u8CC7\u6599",
|
|
2153
2173
|
unknown_command: "\u672A\u77E5\u6307\u4EE4\uFF1A'{command}'\u3002\u8F38\u5165 '.help' \u67E5\u770B\u53EF\u7528\u6307\u4EE4\u3002"
|
|
2154
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
|
+
gate_summary: "This will {operation} rows in {table}.",
|
|
2195
|
+
gate_summary_untargeted: "This will run a {operation} statement.",
|
|
2196
|
+
gate_statement: "Statement:",
|
|
2197
|
+
gate_cancelled: "Cancelled. Nothing was run.",
|
|
2198
|
+
gate_full_table_warning: "\u26A0\uFE0F This affects EVERY row in {table} and cannot be undone.",
|
|
2199
|
+
gate_ddl_warning: "\u26A0\uFE0F This destroys {table} and cannot be undone.",
|
|
2200
|
+
gate_ddl_warning_untargeted: "\u26A0\uFE0F This is a destructive schema change and cannot be undone.",
|
|
2201
|
+
gate_unparseable_warning: "\u26A0\uFE0F dbcli could not parse this statement, so it is treated as affecting everything.",
|
|
2202
|
+
gate_multiple_statements_warning: "\u26A0\uFE0F This is more than one statement, and dbcli will not judge them one at a time.",
|
|
2203
|
+
gate_typed_prompt: "Type {phrase} to run it",
|
|
2204
|
+
gate_typed_mismatch: "That did not match {phrase}. Nothing was run.",
|
|
2205
|
+
gate_refused: "Refused: this statement is not limited to specific rows and nobody is here to confirm it (reason={reason}).",
|
|
2206
|
+
gate_remedy_no_where: "Add a WHERE clause \u2014 WHERE 1=1 if you really do mean every row \u2014 or a LIMIT, then run it again.",
|
|
2207
|
+
gate_remedy_ddl_destruction: "No flag skips this. Run it from an interactive terminal, or apply the schema change through a reviewed migration.",
|
|
2208
|
+
gate_remedy_unparseable: "dbcli could not parse this statement and will not guess. Simplify it, or run it from an interactive terminal.",
|
|
2209
|
+
gate_remedy_multiple_statements: "Run one statement per command.",
|
|
2210
|
+
gate_remedy_non_unique_where: "Match on a primary key or a uniquely indexed column, or run it from an interactive terminal.",
|
|
2211
|
+
recovery_none: "This cannot be undone automatically \u2014 restore from a backup to get the previous values back.",
|
|
2212
|
+
recovery_retry: "Re-run with --recovery to write a recovery plan, then read it with: dbcli recover",
|
|
2213
|
+
blacklist_hint: "Run `dbcli blacklist list` to see what is protected"
|
|
2214
|
+
};
|
|
2215
|
+
// resources/lang/zh-TW/ceremony.json
|
|
2216
|
+
var ceremony_default2 = {
|
|
2217
|
+
updated: "\u5DF2\u66F4\u65B0 {table} \u7684 {count} \u5217",
|
|
2218
|
+
deleted: "\u5DF2\u5F9E {table} \u522A\u9664 {count} \u5217",
|
|
2219
|
+
inserted: "\u5DF2\u5BEB\u5165 {count} \u5217\u5230 {table}",
|
|
2220
|
+
matched_nothing: "{table} \u6C92\u6709\u4EFB\u4F55\u5217\u7B26\u5408\u689D\u4EF6\uFF0C\u8CC7\u6599\u672A\u8B8A\u52D5",
|
|
2221
|
+
cancelled: "\u5DF2\u53D6\u6D88\uFF0C{table} \u672A\u8B8A\u52D5",
|
|
2222
|
+
dry_run: "\u50C5\u9810\u89BD\uFF0C{table} \u672A\u8B8A\u52D5",
|
|
2223
|
+
elapsed: "\u8017\u6642 {seconds} \u79D2",
|
|
2224
|
+
failed: "\u5931\u6557\uFF1A{reason}",
|
|
2225
|
+
unknown_error: "\u672A\u77E5\u7684\u932F\u8AA4",
|
|
2226
|
+
confirm_sql: "\u7522\u751F\u7684 SQL\uFF1A",
|
|
2227
|
+
confirm_command: "\u5373\u5C07\u57F7\u884C\u7684\u6307\u4EE4\uFF1A",
|
|
2228
|
+
confirm_params: "\u53C3\u6578\uFF1A",
|
|
2229
|
+
confirm_destructive_warning: "\u26A0\uFE0F \u8B66\u544A\uFF1ADELETE \u5177\u7834\u58DE\u6027\uFF0C\u57F7\u884C\u5F8C\u7121\u6CD5\u5FA9\u539F\uFF01",
|
|
2230
|
+
confirm_destructive_prompt: "\u78BA\u5B9A\u8981\u57F7\u884C\u9019\u500B DELETE \u55CE\uFF1F\u6B64\u64CD\u4F5C\u7121\u6CD5\u5FA9\u539F\u3002",
|
|
2231
|
+
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",
|
|
2232
|
+
confirm_ddl_prompt: "\u78BA\u5B9A\u8981\u57F7\u884C\u9019\u500B {operation} \u55CE\uFF1F\u6B64\u64CD\u4F5C\u7121\u6CD5\u5FA9\u539F\u3002",
|
|
2233
|
+
confirm_prompt: "\u8981\u7E7C\u7E8C\u57F7\u884C\u9019\u500B\u64CD\u4F5C\u55CE\uFF1F",
|
|
2234
|
+
gate_summary: "\u9019\u53E5\u6703\u5C0D {table} \u57F7\u884C {operation}\u3002",
|
|
2235
|
+
gate_summary_untargeted: "\u9019\u53E5\u6703\u57F7\u884C {operation}\u3002",
|
|
2236
|
+
gate_statement: "\u8A9E\u53E5\uFF1A",
|
|
2237
|
+
gate_cancelled: "\u5DF2\u53D6\u6D88\uFF0C\u6C92\u6709\u57F7\u884C\u4EFB\u4F55\u8A9E\u53E5\u3002",
|
|
2238
|
+
gate_full_table_warning: "\u26A0\uFE0F \u9019\u53E5\u6703\u5F71\u97FF {table} \u7684\u6BCF\u4E00\u5217\uFF0C\u57F7\u884C\u5F8C\u7121\u6CD5\u5FA9\u539F\u3002",
|
|
2239
|
+
gate_ddl_warning: "\u26A0\uFE0F \u9019\u53E5\u6703\u6467\u6BC0 {table}\uFF0C\u57F7\u884C\u5F8C\u7121\u6CD5\u5FA9\u539F\u3002",
|
|
2240
|
+
gate_ddl_warning_untargeted: "\u26A0\uFE0F \u9019\u662F\u7834\u58DE\u6027\u7684 schema \u8B8A\u66F4\uFF0C\u57F7\u884C\u5F8C\u7121\u6CD5\u5FA9\u539F\u3002",
|
|
2241
|
+
gate_unparseable_warning: "\u26A0\uFE0F dbcli \u7121\u6CD5\u89E3\u6790\u9019\u53E5\uFF0C\u56E0\u6B64\u4E00\u5F8B\u8996\u70BA\u6703\u5F71\u97FF\u5168\u90E8\u8CC7\u6599\u3002",
|
|
2242
|
+
gate_multiple_statements_warning: "\u26A0\uFE0F \u9019\u88E1\u4E0D\u53EA\u4E00\u53E5\u8A9E\u53E5\uFF0Cdbcli \u4E0D\u6703\u9010\u53E5\u5224\u65B7\u3002",
|
|
2243
|
+
gate_typed_prompt: "\u8F38\u5165 {phrase} \u624D\u6703\u57F7\u884C",
|
|
2244
|
+
gate_typed_mismatch: "\u8F38\u5165\u7684\u5167\u5BB9\u8207 {phrase} \u4E0D\u7B26\uFF0C\u6C92\u6709\u57F7\u884C\u4EFB\u4F55\u8A9E\u53E5\u3002",
|
|
2245
|
+
gate_refused: "\u5DF2\u62D2\u7D55\uFF1A\u9019\u53E5\u6C92\u6709\u9650\u5B9A\u8981\u52D5\u54EA\u4E9B\u5217\uFF0C\u800C\u73FE\u5728\u6C92\u6709\u4EBA\u80FD\u78BA\u8A8D\uFF08reason={reason}\uFF09\u3002",
|
|
2246
|
+
gate_remedy_no_where: "\u88DC\u4E0A WHERE\uFF08\u771F\u7684\u8981\u5168\u8868\u5C31\u5BEB WHERE 1=1\uFF09\u6216 LIMIT\uFF0C\u7136\u5F8C\u91CD\u8DD1\u3002",
|
|
2247
|
+
gate_remedy_ddl_destruction: "\u6C92\u6709\u4EFB\u4F55\u65D7\u6A19\u53EF\u4EE5\u8DF3\u904E\u9019\u4E00\u95DC\u3002\u8ACB\u5728\u4E92\u52D5\u7D42\u7AEF\u4E0B\u57F7\u884C\uFF0C\u6216\u6539\u8D70\u7D93\u904E\u5BE9\u67E5\u7684 migration\u3002",
|
|
2248
|
+
gate_remedy_unparseable: "dbcli \u7121\u6CD5\u89E3\u6790\u9019\u53E5\uFF0C\u4E5F\u4E0D\u6703\u7528\u731C\u7684\u3002\u8ACB\u7C21\u5316\u8A9E\u53E5\uFF0C\u6216\u5728\u4E92\u52D5\u7D42\u7AEF\u4E0B\u57F7\u884C\u3002",
|
|
2249
|
+
gate_remedy_multiple_statements: "\u4E00\u6B21\u53EA\u57F7\u884C\u4E00\u53E5\u8A9E\u53E5\u3002",
|
|
2250
|
+
gate_remedy_non_unique_where: "\u6539\u7528\u4E3B\u9375\u6216\u552F\u4E00\u7D22\u5F15\u6B04\u4F4D\u7576\u689D\u4EF6\uFF0C\u6216\u5728\u4E92\u52D5\u7D42\u7AEF\u4E0B\u57F7\u884C\u3002",
|
|
2251
|
+
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",
|
|
2252
|
+
recovery_retry: "\u52A0\u4E0A --recovery \u91CD\u8DD1\u53EF\u7522\u751F\u56DE\u5FA9\u8A08\u756B\uFF0C\u518D\u7528 dbcli recover \u8B80\u53D6",
|
|
2253
|
+
blacklist_hint: "\u57F7\u884C `dbcli blacklist list` \u67E5\u770B\u53D7\u4FDD\u8B77\u7684\u9805\u76EE"
|
|
2254
|
+
};
|
|
2155
2255
|
|
|
2156
2256
|
// src/i18n/message-loader.ts
|
|
2157
2257
|
var BUNDLED_MESSAGES = {
|
|
2158
|
-
en: { ...messages_default, shell: shell_default },
|
|
2159
|
-
"zh-TW": {
|
|
2258
|
+
en: { ...messages_default, shell: shell_default, ceremony: ceremony_default },
|
|
2259
|
+
"zh-TW": {
|
|
2260
|
+
...messages_default2,
|
|
2261
|
+
shell: shell_default2,
|
|
2262
|
+
ceremony: ceremony_default2
|
|
2263
|
+
}
|
|
2160
2264
|
};
|
|
2161
2265
|
|
|
2162
2266
|
class MessageLoader {
|
|
@@ -2219,6 +2323,7 @@ class MessageLoader {
|
|
|
2219
2323
|
}
|
|
2220
2324
|
}
|
|
2221
2325
|
var messageLoader = MessageLoader.getInstance();
|
|
2326
|
+
var t = (key) => messageLoader.t(key);
|
|
2222
2327
|
var t_vars = (key, vars) => messageLoader.interpolate(key, vars);
|
|
2223
2328
|
|
|
2224
2329
|
// src/utils/colors.ts
|
|
@@ -3296,12 +3401,12 @@ function detectMongoType(v) {
|
|
|
3296
3401
|
function accumulateDocPaths(doc, prefix, acc) {
|
|
3297
3402
|
for (const [k, v] of Object.entries(doc)) {
|
|
3298
3403
|
const path = prefix === "" ? k : `${prefix}.${k}`;
|
|
3299
|
-
const
|
|
3404
|
+
const t2 = detectMongoType(v);
|
|
3300
3405
|
const slot = acc.get(path) ?? { types: new Set, count: 0 };
|
|
3301
|
-
slot.types.add(
|
|
3406
|
+
slot.types.add(t2);
|
|
3302
3407
|
slot.count += 1;
|
|
3303
3408
|
acc.set(path, slot);
|
|
3304
|
-
if (
|
|
3409
|
+
if (t2 === "object" && v && typeof v === "object") {
|
|
3305
3410
|
accumulateDocPaths(v, path, acc);
|
|
3306
3411
|
}
|
|
3307
3412
|
}
|
|
@@ -4812,18 +4917,7 @@ function continuesIdentifier(sql, index) {
|
|
|
4812
4917
|
return run.replace(/^[0-9]+(?:[eE][0-9]+)?/, "").length > 0;
|
|
4813
4918
|
}
|
|
4814
4919
|
|
|
4815
|
-
// src/core/permission-
|
|
4816
|
-
class PermissionError extends Error {
|
|
4817
|
-
classification;
|
|
4818
|
-
requiredPermission;
|
|
4819
|
-
constructor(message, classification, requiredPermission) {
|
|
4820
|
-
super(message);
|
|
4821
|
-
this.classification = classification;
|
|
4822
|
-
this.requiredPermission = requiredPermission;
|
|
4823
|
-
this.name = "PermissionError";
|
|
4824
|
-
Object.setPrototypeOf(this, PermissionError.prototype);
|
|
4825
|
-
}
|
|
4826
|
-
}
|
|
4920
|
+
// src/core/permission/sql-analysis.ts
|
|
4827
4921
|
function normalizeSQL(sql) {
|
|
4828
4922
|
return sql.replace(/--[^\n]*\n/g, `
|
|
4829
4923
|
`).replace(/\/\*[\s\S]*?\*\//g, " ").trim().replace(/\s+/g, " ");
|
|
@@ -5070,6 +5164,19 @@ function determineConfidence(type, _keyword, _sql) {
|
|
|
5070
5164
|
function removeParameterMarkers(sql) {
|
|
5071
5165
|
return sql.replace(/\$\d+/g, "").replace(/\?/g, "");
|
|
5072
5166
|
}
|
|
5167
|
+
|
|
5168
|
+
// src/core/permission-guard.ts
|
|
5169
|
+
class PermissionError extends Error {
|
|
5170
|
+
classification;
|
|
5171
|
+
requiredPermission;
|
|
5172
|
+
constructor(message, classification, requiredPermission) {
|
|
5173
|
+
super(message);
|
|
5174
|
+
this.classification = classification;
|
|
5175
|
+
this.requiredPermission = requiredPermission;
|
|
5176
|
+
this.name = "PermissionError";
|
|
5177
|
+
Object.setPrototypeOf(this, PermissionError.prototype);
|
|
5178
|
+
}
|
|
5179
|
+
}
|
|
5073
5180
|
function classifyStatement(sql) {
|
|
5074
5181
|
const normalized = normalizeSQL(sql);
|
|
5075
5182
|
const stripped = stripCommentsAndStrings(normalized);
|
|
@@ -5136,15 +5243,38 @@ function checkPermission(sql, permission, dialect) {
|
|
|
5136
5243
|
if (permission !== "admin" && containsMultipleStatements(sql, dialect)) {
|
|
5137
5244
|
return {
|
|
5138
5245
|
allowed: false,
|
|
5139
|
-
reason: "
|
|
5140
|
-
classification
|
|
5246
|
+
reason: t("errors.multiple_statements_refused"),
|
|
5247
|
+
classification,
|
|
5248
|
+
requiredPermission: "admin"
|
|
5141
5249
|
};
|
|
5142
5250
|
}
|
|
5251
|
+
return checkPermissionForClassification(classification, permission);
|
|
5252
|
+
}
|
|
5253
|
+
var TIER_GRANTS = [
|
|
5254
|
+
{ permission: "query-only", types: ["SELECT", "SHOW", "DESCRIBE", "EXPLAIN"] },
|
|
5255
|
+
{ permission: "read-write", types: ["INSERT", "UPDATE"] },
|
|
5256
|
+
{ permission: "data-admin", types: ["DELETE"] }
|
|
5257
|
+
];
|
|
5258
|
+
function minimumPermissionFor(type) {
|
|
5259
|
+
return TIER_GRANTS.find((tier) => tier.types.includes(type))?.permission ?? "admin";
|
|
5260
|
+
}
|
|
5261
|
+
function refusalReason(type, permission) {
|
|
5262
|
+
return t_vars("errors.permission_requires_level", {
|
|
5263
|
+
type,
|
|
5264
|
+
minimum: minimumPermissionFor(type),
|
|
5265
|
+
permission
|
|
5266
|
+
});
|
|
5267
|
+
}
|
|
5268
|
+
function checkPermissionForClassification(classification, permission) {
|
|
5143
5269
|
if (permission !== "admin" && classification.escalatedFrom) {
|
|
5144
5270
|
return {
|
|
5145
5271
|
allowed: false,
|
|
5146
|
-
reason:
|
|
5147
|
-
|
|
5272
|
+
reason: t_vars("errors.escalated_write_requires_admin", {
|
|
5273
|
+
keyword: classification.escalatedFrom,
|
|
5274
|
+
permission
|
|
5275
|
+
}),
|
|
5276
|
+
classification,
|
|
5277
|
+
requiredPermission: "admin"
|
|
5148
5278
|
};
|
|
5149
5279
|
}
|
|
5150
5280
|
if (permission === "admin") {
|
|
@@ -5154,62 +5284,51 @@ function checkPermission(sql, permission, dialect) {
|
|
|
5154
5284
|
classification
|
|
5155
5285
|
};
|
|
5156
5286
|
}
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
return {
|
|
5161
|
-
allowed: true,
|
|
5162
|
-
reason: `${classification.type} operation allowed in data-admin mode`,
|
|
5163
|
-
classification
|
|
5164
|
-
};
|
|
5165
|
-
}
|
|
5166
|
-
return {
|
|
5167
|
-
allowed: false,
|
|
5168
|
-
reason: `${classification.type} operation requires admin permission`,
|
|
5169
|
-
classification
|
|
5170
|
-
};
|
|
5171
|
-
}
|
|
5172
|
-
if (permission === "read-write") {
|
|
5173
|
-
const allowedTypes = ["SELECT", "INSERT", "UPDATE", "SHOW", "DESCRIBE", "EXPLAIN"];
|
|
5287
|
+
const tierIndex = TIER_GRANTS.findIndex((tier) => tier.permission === permission);
|
|
5288
|
+
if (tierIndex !== -1) {
|
|
5289
|
+
const allowedTypes = TIER_GRANTS.slice(0, tierIndex + 1).flatMap((tier) => tier.types);
|
|
5174
5290
|
if (allowedTypes.includes(classification.type)) {
|
|
5175
5291
|
return {
|
|
5176
5292
|
allowed: true,
|
|
5177
|
-
reason: `${classification.type} operation allowed in
|
|
5293
|
+
reason: `${classification.type} operation allowed in ${permission} mode`,
|
|
5178
5294
|
classification
|
|
5179
5295
|
};
|
|
5180
5296
|
}
|
|
5297
|
+
const isUnknown = permission === "query-only" && classification.type === "UNKNOWN";
|
|
5181
5298
|
return {
|
|
5182
5299
|
allowed: false,
|
|
5183
|
-
reason:
|
|
5184
|
-
classification
|
|
5185
|
-
|
|
5186
|
-
}
|
|
5187
|
-
if (permission === "query-only") {
|
|
5188
|
-
const allowedTypes = ["SELECT", "SHOW", "DESCRIBE", "EXPLAIN"];
|
|
5189
|
-
if (allowedTypes.includes(classification.type)) {
|
|
5190
|
-
return {
|
|
5191
|
-
allowed: true,
|
|
5192
|
-
reason: `${classification.type} operation allowed in query-only mode`,
|
|
5193
|
-
classification
|
|
5194
|
-
};
|
|
5195
|
-
}
|
|
5196
|
-
const isUnknown = classification.type === "UNKNOWN";
|
|
5197
|
-
return {
|
|
5198
|
-
allowed: false,
|
|
5199
|
-
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`,
|
|
5200
|
-
classification
|
|
5300
|
+
reason: isUnknown ? t("errors.unknown_statement_query_only") : refusalReason(classification.type, permission),
|
|
5301
|
+
classification,
|
|
5302
|
+
requiredPermission: isUnknown ? "read-write" : minimumPermissionFor(classification.type)
|
|
5201
5303
|
};
|
|
5202
5304
|
}
|
|
5203
5305
|
return {
|
|
5204
5306
|
allowed: false,
|
|
5205
5307
|
reason: `Unknown permission level: ${permission}`,
|
|
5206
|
-
classification
|
|
5308
|
+
classification,
|
|
5309
|
+
requiredPermission: "admin"
|
|
5207
5310
|
};
|
|
5208
5311
|
}
|
|
5312
|
+
function classificationForType(type) {
|
|
5313
|
+
return {
|
|
5314
|
+
type,
|
|
5315
|
+
isDangerous: isDestructiveOperation(type),
|
|
5316
|
+
keywords: [type],
|
|
5317
|
+
isComposite: false,
|
|
5318
|
+
confidence: "HIGH"
|
|
5319
|
+
};
|
|
5320
|
+
}
|
|
5321
|
+
function enforcePermissionForType(type, permission) {
|
|
5322
|
+
const classification = classificationForType(type);
|
|
5323
|
+
const result = checkPermissionForClassification(classification, permission);
|
|
5324
|
+
if (!result.allowed) {
|
|
5325
|
+
throw new PermissionError(result.reason, classification, minimumPermissionFor(type));
|
|
5326
|
+
}
|
|
5327
|
+
}
|
|
5209
5328
|
function enforcePermission(sql, permission, dialect) {
|
|
5210
5329
|
const result = checkPermission(sql, permission, dialect);
|
|
5211
5330
|
if (!result.allowed) {
|
|
5212
|
-
throw new PermissionError(result.reason, result.classification,
|
|
5331
|
+
throw new PermissionError(result.reason, result.classification, result.requiredPermission ?? "admin");
|
|
5213
5332
|
}
|
|
5214
5333
|
return result.classification;
|
|
5215
5334
|
}
|
|
@@ -5313,7 +5432,7 @@ function extractTableNameFromError(errorMessage) {
|
|
|
5313
5432
|
async function getAllTablesFromAdapter(adapter) {
|
|
5314
5433
|
try {
|
|
5315
5434
|
const tables = await adapter.listTables();
|
|
5316
|
-
return tables.map((
|
|
5435
|
+
return tables.map((t2) => t2.name);
|
|
5317
5436
|
} catch (error) {
|
|
5318
5437
|
console.warn("Failed to list tables for suggestions:", error);
|
|
5319
5438
|
return [];
|
|
@@ -5965,108 +6084,6 @@ function inferColumnType(value) {
|
|
|
5965
6084
|
}
|
|
5966
6085
|
return "unknown";
|
|
5967
6086
|
}
|
|
5968
|
-
// src/utils/prompts.ts
|
|
5969
|
-
var promptsUnavailableReported = false;
|
|
5970
|
-
async function loadInquirer() {
|
|
5971
|
-
try {
|
|
5972
|
-
return await import("@inquirer/prompts");
|
|
5973
|
-
} catch (error) {
|
|
5974
|
-
if (!promptsUnavailableReported) {
|
|
5975
|
-
promptsUnavailableReported = true;
|
|
5976
|
-
const reason = error instanceof Error ? error.message : String(error);
|
|
5977
|
-
process.stderr.write(`[dbcli] rich interactive prompts are unavailable (${reason}); falling back to plain-text input
|
|
5978
|
-
`);
|
|
5979
|
-
}
|
|
5980
|
-
return;
|
|
5981
|
-
}
|
|
5982
|
-
}
|
|
5983
|
-
async function readLineFromStdin(prompt = "") {
|
|
5984
|
-
return new Promise((resolve) => {
|
|
5985
|
-
if (prompt) {
|
|
5986
|
-
process.stdout.write(prompt);
|
|
5987
|
-
}
|
|
5988
|
-
let data = "";
|
|
5989
|
-
const chunks = [];
|
|
5990
|
-
const onData = (chunk) => {
|
|
5991
|
-
chunks.push(chunk);
|
|
5992
|
-
data = Buffer.concat(chunks).toString();
|
|
5993
|
-
const lines = data.split(`
|
|
5994
|
-
`);
|
|
5995
|
-
if (lines.length > 1) {
|
|
5996
|
-
process.stdin.pause();
|
|
5997
|
-
process.stdin.removeListener("data", onData);
|
|
5998
|
-
process.stdin.removeListener("end", onEnd);
|
|
5999
|
-
resolve((lines[0] ?? "").trim());
|
|
6000
|
-
}
|
|
6001
|
-
};
|
|
6002
|
-
const onEnd = () => {
|
|
6003
|
-
process.stdin.removeListener("data", onData);
|
|
6004
|
-
resolve(data.trim());
|
|
6005
|
-
};
|
|
6006
|
-
process.stdin.on("data", onData);
|
|
6007
|
-
process.stdin.on("end", onEnd);
|
|
6008
|
-
process.stdin.resume();
|
|
6009
|
-
});
|
|
6010
|
-
}
|
|
6011
|
-
async function textFallback(message, defaultValue) {
|
|
6012
|
-
const displayMessage = defaultValue ? `${message} [${defaultValue}]: ` : `${message}: `;
|
|
6013
|
-
const answer = await readLineFromStdin(displayMessage);
|
|
6014
|
-
return answer.trim() || defaultValue || "";
|
|
6015
|
-
}
|
|
6016
|
-
async function selectFallback(message, choices) {
|
|
6017
|
-
console.log(message);
|
|
6018
|
-
choices.forEach((choice, index) => {
|
|
6019
|
-
console.log(` ${index + 1}) ${choice}`);
|
|
6020
|
-
});
|
|
6021
|
-
const answer = await readLineFromStdin("Select option (number): ");
|
|
6022
|
-
const selectedIndex = parseInt(answer, 10) - 1;
|
|
6023
|
-
if (selectedIndex >= 0 && selectedIndex < choices.length) {
|
|
6024
|
-
return choices[selectedIndex] ?? choices[0] ?? "";
|
|
6025
|
-
}
|
|
6026
|
-
return choices[0] ?? "";
|
|
6027
|
-
}
|
|
6028
|
-
async function confirmFallback(message) {
|
|
6029
|
-
const answer = await readLineFromStdin(`${message} (y/n): `);
|
|
6030
|
-
return answer.toLowerCase() === "y" || answer.toLowerCase() === "yes";
|
|
6031
|
-
}
|
|
6032
|
-
async function text(message, defaultValue) {
|
|
6033
|
-
if (!process.stdin.isTTY)
|
|
6034
|
-
return textFallback(message, defaultValue);
|
|
6035
|
-
const inquirer = await loadInquirer();
|
|
6036
|
-
if (!inquirer)
|
|
6037
|
-
return textFallback(message, defaultValue);
|
|
6038
|
-
return await inquirer.input({ message, default: defaultValue });
|
|
6039
|
-
}
|
|
6040
|
-
async function select(message, choices) {
|
|
6041
|
-
if (!process.stdin.isTTY)
|
|
6042
|
-
return await selectFallback(message, choices);
|
|
6043
|
-
const inquirer = await loadInquirer();
|
|
6044
|
-
if (!inquirer)
|
|
6045
|
-
return await selectFallback(message, choices);
|
|
6046
|
-
return await inquirer.select({ message, choices });
|
|
6047
|
-
}
|
|
6048
|
-
async function secret(message) {
|
|
6049
|
-
const inquirer = await loadInquirer();
|
|
6050
|
-
if (!inquirer) {
|
|
6051
|
-
throw new Error("Masked input is unavailable; pass the value with --stdin or --password instead.");
|
|
6052
|
-
}
|
|
6053
|
-
return await inquirer.password({ message, mask: "*" });
|
|
6054
|
-
}
|
|
6055
|
-
async function confirm(message) {
|
|
6056
|
-
if (!process.stdin.isTTY)
|
|
6057
|
-
return await confirmFallback(message);
|
|
6058
|
-
const inquirer = await loadInquirer();
|
|
6059
|
-
if (!inquirer)
|
|
6060
|
-
return await confirmFallback(message);
|
|
6061
|
-
return await inquirer.confirm({ message });
|
|
6062
|
-
}
|
|
6063
|
-
var promptUser = {
|
|
6064
|
-
text,
|
|
6065
|
-
select,
|
|
6066
|
-
confirm,
|
|
6067
|
-
secret
|
|
6068
|
-
};
|
|
6069
|
-
|
|
6070
6087
|
// src/types/blacklist.ts
|
|
6071
6088
|
class BlacklistError extends Error {
|
|
6072
6089
|
tableName;
|
|
@@ -6114,8 +6131,8 @@ class DataExecutor {
|
|
|
6114
6131
|
const timestamp = new Date().toISOString();
|
|
6115
6132
|
try {
|
|
6116
6133
|
this.checkBlacklist("INSERT", tableName);
|
|
6117
|
-
|
|
6118
|
-
return await this.executeMutation("insert", this.buildInsertSql(tableName, data, schema), timestamp, options, {
|
|
6134
|
+
enforcePermissionForType("INSERT", this.permission);
|
|
6135
|
+
return await this.executeMutation("insert", this.buildInsertSql(tableName, data, schema), timestamp, options, { destructive: false });
|
|
6119
6136
|
} catch (error) {
|
|
6120
6137
|
return this.handleMutationError("insert", timestamp, error);
|
|
6121
6138
|
}
|
|
@@ -6124,8 +6141,8 @@ class DataExecutor {
|
|
|
6124
6141
|
const timestamp = new Date().toISOString();
|
|
6125
6142
|
try {
|
|
6126
6143
|
this.checkBlacklist("UPDATE", tableName);
|
|
6127
|
-
|
|
6128
|
-
return await this.executeMutation("update", this.buildUpdateSql(tableName, data, where, schema), timestamp, options, {
|
|
6144
|
+
enforcePermissionForType("UPDATE", this.permission);
|
|
6145
|
+
return await this.executeMutation("update", this.buildUpdateSql(tableName, data, where, schema), timestamp, options, { destructive: false });
|
|
6129
6146
|
} catch (error) {
|
|
6130
6147
|
return this.handleMutationError("update", timestamp, error);
|
|
6131
6148
|
}
|
|
@@ -6134,19 +6151,8 @@ class DataExecutor {
|
|
|
6134
6151
|
const timestamp = new Date().toISOString();
|
|
6135
6152
|
try {
|
|
6136
6153
|
this.checkBlacklist("DELETE", tableName);
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
status: "error",
|
|
6140
|
-
operation: "delete",
|
|
6141
|
-
rows_affected: 0,
|
|
6142
|
-
timestamp,
|
|
6143
|
-
error: "Permission denied: DELETE operation requires Data-Admin or Admin permission."
|
|
6144
|
-
};
|
|
6145
|
-
}
|
|
6146
|
-
return await this.executeMutation("delete", this.buildDeleteSql(tableName, where, schema), timestamp, options, {
|
|
6147
|
-
warning: "\u26A0\uFE0F Warning: DELETE operation is destructive and cannot be undone!",
|
|
6148
|
-
prompt: "Are you sure you want to execute this DELETE operation? This cannot be undone."
|
|
6149
|
-
});
|
|
6154
|
+
enforcePermissionForType("DELETE", this.permission);
|
|
6155
|
+
return await this.executeMutation("delete", this.buildDeleteSql(tableName, where, schema), timestamp, options, { destructive: true });
|
|
6150
6156
|
} catch (error) {
|
|
6151
6157
|
return this.handleMutationError("delete", timestamp, error);
|
|
6152
6158
|
}
|
|
@@ -6160,31 +6166,31 @@ class DataExecutor {
|
|
|
6160
6166
|
checkBlacklist(operation, tableName) {
|
|
6161
6167
|
this.blacklistValidator?.checkTableBlacklist(operation, tableName, []);
|
|
6162
6168
|
}
|
|
6163
|
-
async executeMutation(operation, statement, timestamp, options,
|
|
6169
|
+
async executeMutation(operation, statement, timestamp, options, { destructive }) {
|
|
6164
6170
|
if (options?.dryRun) {
|
|
6165
|
-
return this.
|
|
6171
|
+
return this.outcomeResult("dry_run", operation, 0, timestamp, statement.sql);
|
|
6166
6172
|
}
|
|
6167
6173
|
if (!options?.force) {
|
|
6168
|
-
if (
|
|
6169
|
-
|
|
6170
|
-
${confirmation.warning}`);
|
|
6174
|
+
if (!options?.confirm) {
|
|
6175
|
+
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.");
|
|
6171
6176
|
}
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6177
|
+
const proceed = await options.confirm({
|
|
6178
|
+
operation,
|
|
6179
|
+
engine: "sql",
|
|
6180
|
+
sql: statement.sql,
|
|
6181
|
+
params: statement.params,
|
|
6182
|
+
destructive
|
|
6183
|
+
});
|
|
6184
|
+
if (!proceed) {
|
|
6185
|
+
return this.outcomeResult("cancelled", operation, 0, timestamp, statement.sql);
|
|
6180
6186
|
}
|
|
6181
6187
|
}
|
|
6182
6188
|
const result = await this.adapter.execute(statement.sql, statement.params);
|
|
6183
|
-
return this.
|
|
6189
|
+
return this.outcomeResult("success", operation, result.affectedRows, timestamp, statement.sql);
|
|
6184
6190
|
}
|
|
6185
|
-
|
|
6191
|
+
outcomeResult(status, operation, rowsAffected, timestamp, sql) {
|
|
6186
6192
|
return {
|
|
6187
|
-
status
|
|
6193
|
+
status,
|
|
6188
6194
|
operation,
|
|
6189
6195
|
rows_affected: rowsAffected,
|
|
6190
6196
|
timestamp,
|
|
@@ -6195,13 +6201,13 @@ Parameters:`);
|
|
|
6195
6201
|
if (error instanceof BlacklistError) {
|
|
6196
6202
|
throw error;
|
|
6197
6203
|
}
|
|
6198
|
-
if (error instanceof PermissionError
|
|
6204
|
+
if (error instanceof PermissionError) {
|
|
6199
6205
|
return {
|
|
6200
6206
|
status: "error",
|
|
6201
6207
|
operation,
|
|
6202
6208
|
rows_affected: 0,
|
|
6203
6209
|
timestamp,
|
|
6204
|
-
error:
|
|
6210
|
+
error: t_vars("errors.permission_denied_reason", { reason: error.message })
|
|
6205
6211
|
};
|
|
6206
6212
|
}
|
|
6207
6213
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -6463,8 +6469,8 @@ var ZodParsedType = util.arrayToEnum([
|
|
|
6463
6469
|
"set"
|
|
6464
6470
|
]);
|
|
6465
6471
|
var getParsedType = (data) => {
|
|
6466
|
-
const
|
|
6467
|
-
switch (
|
|
6472
|
+
const t2 = typeof data;
|
|
6473
|
+
switch (t2) {
|
|
6468
6474
|
case "undefined":
|
|
6469
6475
|
return ZodParsedType.undefined;
|
|
6470
6476
|
case "string":
|