@carllee1983/dbcli 0.4.0-beta → 0.5.2-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +53 -0
- package/LICENSE +21 -0
- package/README.md +97 -1
- package/README.zh-TW.md +77 -4
- package/assets/SKILL.md +52 -1
- package/dist/cli.mjs +1037 -145
- package/package.json +23 -1
package/dist/cli.mjs
CHANGED
|
@@ -2064,6 +2064,76 @@ var require_commander = __commonJS((exports) => {
|
|
|
2064
2064
|
exports.InvalidOptionArgumentError = InvalidArgumentError;
|
|
2065
2065
|
});
|
|
2066
2066
|
|
|
2067
|
+
// node_modules/picocolors/picocolors.js
|
|
2068
|
+
var require_picocolors = __commonJS((exports, module) => {
|
|
2069
|
+
var p = process || {};
|
|
2070
|
+
var argv = p.argv || [];
|
|
2071
|
+
var env = p.env || {};
|
|
2072
|
+
var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
|
|
2073
|
+
var formatter = (open, close, replace = open) => (input) => {
|
|
2074
|
+
let string = "" + input, index = string.indexOf(close, open.length);
|
|
2075
|
+
return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
|
|
2076
|
+
};
|
|
2077
|
+
var replaceClose = (string, close, replace, index) => {
|
|
2078
|
+
let result = "", cursor = 0;
|
|
2079
|
+
do {
|
|
2080
|
+
result += string.substring(cursor, index) + replace;
|
|
2081
|
+
cursor = index + close.length;
|
|
2082
|
+
index = string.indexOf(close, cursor);
|
|
2083
|
+
} while (~index);
|
|
2084
|
+
return result + string.substring(cursor);
|
|
2085
|
+
};
|
|
2086
|
+
var createColors = (enabled = isColorSupported) => {
|
|
2087
|
+
let f = enabled ? formatter : () => String;
|
|
2088
|
+
return {
|
|
2089
|
+
isColorSupported: enabled,
|
|
2090
|
+
reset: f("\x1B[0m", "\x1B[0m"),
|
|
2091
|
+
bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
|
|
2092
|
+
dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
|
|
2093
|
+
italic: f("\x1B[3m", "\x1B[23m"),
|
|
2094
|
+
underline: f("\x1B[4m", "\x1B[24m"),
|
|
2095
|
+
inverse: f("\x1B[7m", "\x1B[27m"),
|
|
2096
|
+
hidden: f("\x1B[8m", "\x1B[28m"),
|
|
2097
|
+
strikethrough: f("\x1B[9m", "\x1B[29m"),
|
|
2098
|
+
black: f("\x1B[30m", "\x1B[39m"),
|
|
2099
|
+
red: f("\x1B[31m", "\x1B[39m"),
|
|
2100
|
+
green: f("\x1B[32m", "\x1B[39m"),
|
|
2101
|
+
yellow: f("\x1B[33m", "\x1B[39m"),
|
|
2102
|
+
blue: f("\x1B[34m", "\x1B[39m"),
|
|
2103
|
+
magenta: f("\x1B[35m", "\x1B[39m"),
|
|
2104
|
+
cyan: f("\x1B[36m", "\x1B[39m"),
|
|
2105
|
+
white: f("\x1B[37m", "\x1B[39m"),
|
|
2106
|
+
gray: f("\x1B[90m", "\x1B[39m"),
|
|
2107
|
+
bgBlack: f("\x1B[40m", "\x1B[49m"),
|
|
2108
|
+
bgRed: f("\x1B[41m", "\x1B[49m"),
|
|
2109
|
+
bgGreen: f("\x1B[42m", "\x1B[49m"),
|
|
2110
|
+
bgYellow: f("\x1B[43m", "\x1B[49m"),
|
|
2111
|
+
bgBlue: f("\x1B[44m", "\x1B[49m"),
|
|
2112
|
+
bgMagenta: f("\x1B[45m", "\x1B[49m"),
|
|
2113
|
+
bgCyan: f("\x1B[46m", "\x1B[49m"),
|
|
2114
|
+
bgWhite: f("\x1B[47m", "\x1B[49m"),
|
|
2115
|
+
blackBright: f("\x1B[90m", "\x1B[39m"),
|
|
2116
|
+
redBright: f("\x1B[91m", "\x1B[39m"),
|
|
2117
|
+
greenBright: f("\x1B[92m", "\x1B[39m"),
|
|
2118
|
+
yellowBright: f("\x1B[93m", "\x1B[39m"),
|
|
2119
|
+
blueBright: f("\x1B[94m", "\x1B[39m"),
|
|
2120
|
+
magentaBright: f("\x1B[95m", "\x1B[39m"),
|
|
2121
|
+
cyanBright: f("\x1B[96m", "\x1B[39m"),
|
|
2122
|
+
whiteBright: f("\x1B[97m", "\x1B[39m"),
|
|
2123
|
+
bgBlackBright: f("\x1B[100m", "\x1B[49m"),
|
|
2124
|
+
bgRedBright: f("\x1B[101m", "\x1B[49m"),
|
|
2125
|
+
bgGreenBright: f("\x1B[102m", "\x1B[49m"),
|
|
2126
|
+
bgYellowBright: f("\x1B[103m", "\x1B[49m"),
|
|
2127
|
+
bgBlueBright: f("\x1B[104m", "\x1B[49m"),
|
|
2128
|
+
bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
|
|
2129
|
+
bgCyanBright: f("\x1B[106m", "\x1B[49m"),
|
|
2130
|
+
bgWhiteBright: f("\x1B[107m", "\x1B[49m")
|
|
2131
|
+
};
|
|
2132
|
+
};
|
|
2133
|
+
module.exports = createColors();
|
|
2134
|
+
module.exports.createColors = createColors;
|
|
2135
|
+
});
|
|
2136
|
+
|
|
2067
2137
|
// node_modules/@inquirer/core/dist/esm/lib/key.mjs
|
|
2068
2138
|
var isUpKey = (key) => key.name === "up" || key.name === "k" || key.ctrl && key.name === "p", isDownKey = (key) => key.name === "down" || key.name === "j" || key.ctrl && key.name === "n", isSpaceKey = (key) => key.name === "space", isBackspaceKey = (key) => key.name === "backspace", isNumberKey = (key) => "123456789".includes(key.name), isEnterKey = (key) => key.name === "enter" || key.name === "return";
|
|
2069
2139
|
|
|
@@ -2267,49 +2337,49 @@ var require_yoctocolors_cjs = __commonJS((exports, module) => {
|
|
|
2267
2337
|
return result;
|
|
2268
2338
|
};
|
|
2269
2339
|
};
|
|
2270
|
-
var
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
module.exports =
|
|
2340
|
+
var colors2 = {};
|
|
2341
|
+
colors2.reset = format(0, 0);
|
|
2342
|
+
colors2.bold = format(1, 22);
|
|
2343
|
+
colors2.dim = format(2, 22);
|
|
2344
|
+
colors2.italic = format(3, 23);
|
|
2345
|
+
colors2.underline = format(4, 24);
|
|
2346
|
+
colors2.overline = format(53, 55);
|
|
2347
|
+
colors2.inverse = format(7, 27);
|
|
2348
|
+
colors2.hidden = format(8, 28);
|
|
2349
|
+
colors2.strikethrough = format(9, 29);
|
|
2350
|
+
colors2.black = format(30, 39);
|
|
2351
|
+
colors2.red = format(31, 39);
|
|
2352
|
+
colors2.green = format(32, 39);
|
|
2353
|
+
colors2.yellow = format(33, 39);
|
|
2354
|
+
colors2.blue = format(34, 39);
|
|
2355
|
+
colors2.magenta = format(35, 39);
|
|
2356
|
+
colors2.cyan = format(36, 39);
|
|
2357
|
+
colors2.white = format(37, 39);
|
|
2358
|
+
colors2.gray = format(90, 39);
|
|
2359
|
+
colors2.bgBlack = format(40, 49);
|
|
2360
|
+
colors2.bgRed = format(41, 49);
|
|
2361
|
+
colors2.bgGreen = format(42, 49);
|
|
2362
|
+
colors2.bgYellow = format(43, 49);
|
|
2363
|
+
colors2.bgBlue = format(44, 49);
|
|
2364
|
+
colors2.bgMagenta = format(45, 49);
|
|
2365
|
+
colors2.bgCyan = format(46, 49);
|
|
2366
|
+
colors2.bgWhite = format(47, 49);
|
|
2367
|
+
colors2.bgGray = format(100, 49);
|
|
2368
|
+
colors2.redBright = format(91, 39);
|
|
2369
|
+
colors2.greenBright = format(92, 39);
|
|
2370
|
+
colors2.yellowBright = format(93, 39);
|
|
2371
|
+
colors2.blueBright = format(94, 39);
|
|
2372
|
+
colors2.magentaBright = format(95, 39);
|
|
2373
|
+
colors2.cyanBright = format(96, 39);
|
|
2374
|
+
colors2.whiteBright = format(97, 39);
|
|
2375
|
+
colors2.bgRedBright = format(101, 49);
|
|
2376
|
+
colors2.bgGreenBright = format(102, 49);
|
|
2377
|
+
colors2.bgYellowBright = format(103, 49);
|
|
2378
|
+
colors2.bgBlueBright = format(104, 49);
|
|
2379
|
+
colors2.bgMagentaBright = format(105, 49);
|
|
2380
|
+
colors2.bgCyanBright = format(106, 49);
|
|
2381
|
+
colors2.bgWhiteBright = format(107, 49);
|
|
2382
|
+
module.exports = colors2;
|
|
2313
2383
|
});
|
|
2314
2384
|
|
|
2315
2385
|
// node_modules/@inquirer/figures/dist/esm/index.js
|
|
@@ -41827,17 +41897,17 @@ var require_zalgo = __commonJS((exports, module) => {
|
|
|
41827
41897
|
|
|
41828
41898
|
// node_modules/@colors/colors/lib/maps/america.js
|
|
41829
41899
|
var require_america = __commonJS((exports, module) => {
|
|
41830
|
-
module["exports"] = function(
|
|
41900
|
+
module["exports"] = function(colors9) {
|
|
41831
41901
|
return function(letter, i, exploded) {
|
|
41832
41902
|
if (letter === " ")
|
|
41833
41903
|
return letter;
|
|
41834
41904
|
switch (i % 3) {
|
|
41835
41905
|
case 0:
|
|
41836
|
-
return
|
|
41906
|
+
return colors9.red(letter);
|
|
41837
41907
|
case 1:
|
|
41838
|
-
return
|
|
41908
|
+
return colors9.white(letter);
|
|
41839
41909
|
case 2:
|
|
41840
|
-
return
|
|
41910
|
+
return colors9.blue(letter);
|
|
41841
41911
|
}
|
|
41842
41912
|
};
|
|
41843
41913
|
};
|
|
@@ -41845,22 +41915,22 @@ var require_america = __commonJS((exports, module) => {
|
|
|
41845
41915
|
|
|
41846
41916
|
// node_modules/@colors/colors/lib/maps/zebra.js
|
|
41847
41917
|
var require_zebra = __commonJS((exports, module) => {
|
|
41848
|
-
module["exports"] = function(
|
|
41918
|
+
module["exports"] = function(colors9) {
|
|
41849
41919
|
return function(letter, i, exploded) {
|
|
41850
|
-
return i % 2 === 0 ? letter :
|
|
41920
|
+
return i % 2 === 0 ? letter : colors9.inverse(letter);
|
|
41851
41921
|
};
|
|
41852
41922
|
};
|
|
41853
41923
|
});
|
|
41854
41924
|
|
|
41855
41925
|
// node_modules/@colors/colors/lib/maps/rainbow.js
|
|
41856
41926
|
var require_rainbow = __commonJS((exports, module) => {
|
|
41857
|
-
module["exports"] = function(
|
|
41927
|
+
module["exports"] = function(colors9) {
|
|
41858
41928
|
var rainbowColors = ["red", "yellow", "green", "blue", "magenta"];
|
|
41859
41929
|
return function(letter, i, exploded) {
|
|
41860
41930
|
if (letter === " ") {
|
|
41861
41931
|
return letter;
|
|
41862
41932
|
} else {
|
|
41863
|
-
return
|
|
41933
|
+
return colors9[rainbowColors[i++ % rainbowColors.length]](letter);
|
|
41864
41934
|
}
|
|
41865
41935
|
};
|
|
41866
41936
|
};
|
|
@@ -41868,7 +41938,7 @@ var require_rainbow = __commonJS((exports, module) => {
|
|
|
41868
41938
|
|
|
41869
41939
|
// node_modules/@colors/colors/lib/maps/random.js
|
|
41870
41940
|
var require_random = __commonJS((exports, module) => {
|
|
41871
|
-
module["exports"] = function(
|
|
41941
|
+
module["exports"] = function(colors9) {
|
|
41872
41942
|
var available = [
|
|
41873
41943
|
"underline",
|
|
41874
41944
|
"inverse",
|
|
@@ -41889,40 +41959,40 @@ var require_random = __commonJS((exports, module) => {
|
|
|
41889
41959
|
"brightMagenta"
|
|
41890
41960
|
];
|
|
41891
41961
|
return function(letter, i, exploded) {
|
|
41892
|
-
return letter === " " ? letter :
|
|
41962
|
+
return letter === " " ? letter : colors9[available[Math.round(Math.random() * (available.length - 2))]](letter);
|
|
41893
41963
|
};
|
|
41894
41964
|
};
|
|
41895
41965
|
});
|
|
41896
41966
|
|
|
41897
41967
|
// node_modules/@colors/colors/lib/colors.js
|
|
41898
41968
|
var require_colors = __commonJS((exports, module) => {
|
|
41899
|
-
var
|
|
41900
|
-
module["exports"] =
|
|
41901
|
-
|
|
41969
|
+
var colors9 = {};
|
|
41970
|
+
module["exports"] = colors9;
|
|
41971
|
+
colors9.themes = {};
|
|
41902
41972
|
var util3 = __require("util");
|
|
41903
|
-
var ansiStyles =
|
|
41973
|
+
var ansiStyles = colors9.styles = require_styles();
|
|
41904
41974
|
var defineProps = Object.defineProperties;
|
|
41905
41975
|
var newLineRegex = new RegExp(/[\r\n]+/g);
|
|
41906
|
-
|
|
41907
|
-
if (typeof
|
|
41908
|
-
|
|
41976
|
+
colors9.supportsColor = require_supports_colors().supportsColor;
|
|
41977
|
+
if (typeof colors9.enabled === "undefined") {
|
|
41978
|
+
colors9.enabled = colors9.supportsColor() !== false;
|
|
41909
41979
|
}
|
|
41910
|
-
|
|
41911
|
-
|
|
41980
|
+
colors9.enable = function() {
|
|
41981
|
+
colors9.enabled = true;
|
|
41912
41982
|
};
|
|
41913
|
-
|
|
41914
|
-
|
|
41983
|
+
colors9.disable = function() {
|
|
41984
|
+
colors9.enabled = false;
|
|
41915
41985
|
};
|
|
41916
|
-
|
|
41986
|
+
colors9.stripColors = colors9.strip = function(str) {
|
|
41917
41987
|
return ("" + str).replace(/\x1B\[\d+m/g, "");
|
|
41918
41988
|
};
|
|
41919
|
-
var stylize =
|
|
41920
|
-
if (!
|
|
41989
|
+
var stylize = colors9.stylize = function stylize2(str, style) {
|
|
41990
|
+
if (!colors9.enabled) {
|
|
41921
41991
|
return str + "";
|
|
41922
41992
|
}
|
|
41923
41993
|
var styleMap = ansiStyles[style];
|
|
41924
|
-
if (!styleMap && style in
|
|
41925
|
-
return
|
|
41994
|
+
if (!styleMap && style in colors9) {
|
|
41995
|
+
return colors9[style](str);
|
|
41926
41996
|
}
|
|
41927
41997
|
return styleMap.open + str + styleMap.close;
|
|
41928
41998
|
};
|
|
@@ -41954,7 +42024,7 @@ var require_colors = __commonJS((exports, module) => {
|
|
|
41954
42024
|
});
|
|
41955
42025
|
return ret;
|
|
41956
42026
|
}();
|
|
41957
|
-
var proto = defineProps(function
|
|
42027
|
+
var proto = defineProps(function colors10() {}, styles);
|
|
41958
42028
|
function applyStyle() {
|
|
41959
42029
|
var args = Array.prototype.slice.call(arguments);
|
|
41960
42030
|
var str = args.map(function(arg) {
|
|
@@ -41964,7 +42034,7 @@ var require_colors = __commonJS((exports, module) => {
|
|
|
41964
42034
|
return util3.inspect(arg);
|
|
41965
42035
|
}
|
|
41966
42036
|
}).join(" ");
|
|
41967
|
-
if (!
|
|
42037
|
+
if (!colors9.enabled || !str) {
|
|
41968
42038
|
return str;
|
|
41969
42039
|
}
|
|
41970
42040
|
var newLinesPresent = str.indexOf(`
|
|
@@ -41982,22 +42052,22 @@ var require_colors = __commonJS((exports, module) => {
|
|
|
41982
42052
|
}
|
|
41983
42053
|
return str;
|
|
41984
42054
|
}
|
|
41985
|
-
|
|
42055
|
+
colors9.setTheme = function(theme) {
|
|
41986
42056
|
if (typeof theme === "string") {
|
|
41987
42057
|
console.log("colors.setTheme now only accepts an object, not a string. " + "If you are trying to set a theme from a file, it is now your (the " + "caller's) responsibility to require the file. The old syntax " + "looked like colors.setTheme(__dirname + " + "'/../themes/generic-logging.js'); The new syntax looks like " + "colors.setTheme(require(__dirname + " + "'/../themes/generic-logging.js'));");
|
|
41988
42058
|
return;
|
|
41989
42059
|
}
|
|
41990
42060
|
for (var style in theme) {
|
|
41991
42061
|
(function(style2) {
|
|
41992
|
-
|
|
42062
|
+
colors9[style2] = function(str) {
|
|
41993
42063
|
if (typeof theme[style2] === "object") {
|
|
41994
42064
|
var out = str;
|
|
41995
42065
|
for (var i in theme[style2]) {
|
|
41996
|
-
out =
|
|
42066
|
+
out = colors9[theme[style2][i]](out);
|
|
41997
42067
|
}
|
|
41998
42068
|
return out;
|
|
41999
42069
|
}
|
|
42000
|
-
return
|
|
42070
|
+
return colors9[theme[style2]](str);
|
|
42001
42071
|
};
|
|
42002
42072
|
})(style);
|
|
42003
42073
|
}
|
|
@@ -42018,28 +42088,28 @@ var require_colors = __commonJS((exports, module) => {
|
|
|
42018
42088
|
exploded = exploded.map(map2);
|
|
42019
42089
|
return exploded.join("");
|
|
42020
42090
|
};
|
|
42021
|
-
|
|
42022
|
-
|
|
42023
|
-
|
|
42024
|
-
|
|
42025
|
-
|
|
42026
|
-
|
|
42027
|
-
|
|
42028
|
-
for (map in
|
|
42091
|
+
colors9.trap = require_trap();
|
|
42092
|
+
colors9.zalgo = require_zalgo();
|
|
42093
|
+
colors9.maps = {};
|
|
42094
|
+
colors9.maps.america = require_america()(colors9);
|
|
42095
|
+
colors9.maps.zebra = require_zebra()(colors9);
|
|
42096
|
+
colors9.maps.rainbow = require_rainbow()(colors9);
|
|
42097
|
+
colors9.maps.random = require_random()(colors9);
|
|
42098
|
+
for (map in colors9.maps) {
|
|
42029
42099
|
(function(map2) {
|
|
42030
|
-
|
|
42031
|
-
return sequencer(
|
|
42100
|
+
colors9[map2] = function(str) {
|
|
42101
|
+
return sequencer(colors9.maps[map2], str);
|
|
42032
42102
|
};
|
|
42033
42103
|
})(map);
|
|
42034
42104
|
}
|
|
42035
42105
|
var map;
|
|
42036
|
-
defineProps(
|
|
42106
|
+
defineProps(colors9, init());
|
|
42037
42107
|
});
|
|
42038
42108
|
|
|
42039
42109
|
// node_modules/@colors/colors/safe.js
|
|
42040
42110
|
var require_safe = __commonJS((exports, module) => {
|
|
42041
|
-
var
|
|
42042
|
-
module["exports"] =
|
|
42111
|
+
var colors9 = require_colors();
|
|
42112
|
+
module["exports"] = colors9;
|
|
42043
42113
|
});
|
|
42044
42114
|
|
|
42045
42115
|
// node_modules/cli-table3/src/cell.js
|
|
@@ -42209,11 +42279,11 @@ var require_cell = __commonJS((exports, module) => {
|
|
|
42209
42279
|
wrapWithStyleColors(styleProperty, content) {
|
|
42210
42280
|
if (this[styleProperty] && this[styleProperty].length) {
|
|
42211
42281
|
try {
|
|
42212
|
-
let
|
|
42282
|
+
let colors9 = require_safe();
|
|
42213
42283
|
for (let i = this[styleProperty].length - 1;i >= 0; i--) {
|
|
42214
|
-
|
|
42284
|
+
colors9 = colors9[this[styleProperty][i]];
|
|
42215
42285
|
}
|
|
42216
|
-
return
|
|
42286
|
+
return colors9(content);
|
|
42217
42287
|
} catch (e) {
|
|
42218
42288
|
return content;
|
|
42219
42289
|
}
|
|
@@ -42758,7 +42828,7 @@ var {
|
|
|
42758
42828
|
// package.json
|
|
42759
42829
|
var package_default = {
|
|
42760
42830
|
name: "@carllee1983/dbcli",
|
|
42761
|
-
version: "0.
|
|
42831
|
+
version: "0.5.2-beta",
|
|
42762
42832
|
description: "Database CLI for AI agents",
|
|
42763
42833
|
type: "module",
|
|
42764
42834
|
publishConfig: {
|
|
@@ -42767,6 +42837,27 @@ var package_default = {
|
|
|
42767
42837
|
bin: {
|
|
42768
42838
|
dbcli: "./dist/cli.mjs"
|
|
42769
42839
|
},
|
|
42840
|
+
license: "MIT",
|
|
42841
|
+
author: "Carl Lee",
|
|
42842
|
+
repository: {
|
|
42843
|
+
type: "git",
|
|
42844
|
+
url: "git+https://github.com/CarlLee1983/dbcli.git"
|
|
42845
|
+
},
|
|
42846
|
+
homepage: "https://github.com/CarlLee1983/dbcli#readme",
|
|
42847
|
+
bugs: {
|
|
42848
|
+
url: "https://github.com/CarlLee1983/dbcli/issues"
|
|
42849
|
+
},
|
|
42850
|
+
keywords: [
|
|
42851
|
+
"database",
|
|
42852
|
+
"cli",
|
|
42853
|
+
"ai",
|
|
42854
|
+
"agent",
|
|
42855
|
+
"postgresql",
|
|
42856
|
+
"mysql",
|
|
42857
|
+
"mariadb",
|
|
42858
|
+
"permissions",
|
|
42859
|
+
"blacklist"
|
|
42860
|
+
],
|
|
42770
42861
|
engines: {
|
|
42771
42862
|
node: ">=18.0.0",
|
|
42772
42863
|
bun: ">=1.3.3"
|
|
@@ -42796,6 +42887,7 @@ var package_default = {
|
|
|
42796
42887
|
dotenv: "^16.3.1",
|
|
42797
42888
|
mysql2: "^3.20.0",
|
|
42798
42889
|
pg: "^8.20.0",
|
|
42890
|
+
picocolors: "^1.1.1",
|
|
42799
42891
|
zod: "^3.22.4"
|
|
42800
42892
|
},
|
|
42801
42893
|
devDependencies: {
|
|
@@ -42831,7 +42923,11 @@ var messages_default = {
|
|
|
42831
42923
|
connection_failed: "\u2717 Database connection failed",
|
|
42832
42924
|
config_saved: "Configuration saved to .dbcli",
|
|
42833
42925
|
config_exists_overwrite: "Configuration file .dbcli already exists. Overwrite? (y/n): ",
|
|
42834
|
-
cancelled: "Cancelled. Configuration not changed."
|
|
42926
|
+
cancelled: "Cancelled. Configuration not changed.",
|
|
42927
|
+
skip_test_env_ref: "Skipping connection test in env-ref mode",
|
|
42928
|
+
skip_test: "Skipping connection test (--skip-test)",
|
|
42929
|
+
connection_hints: "Hints:",
|
|
42930
|
+
config_exists_use_force: ".dbcli exists. Use --force option to overwrite."
|
|
42835
42931
|
},
|
|
42836
42932
|
schema: {
|
|
42837
42933
|
description: "Retrieve table structure or list all tables",
|
|
@@ -42870,7 +42966,18 @@ var messages_default = {
|
|
|
42870
42966
|
column_already_blacklisted: "Error: Column '{table}.{column}' is already blacklisted",
|
|
42871
42967
|
column_not_in_blacklist: "Error: Column '{table}.{column}' is not in the blacklist",
|
|
42872
42968
|
invalid_table_name: "Error: Invalid table name: {table}",
|
|
42873
|
-
invalid_column_format: "Error: Invalid column format. Use 'table.column'"
|
|
42969
|
+
invalid_column_format: "Error: Invalid column format. Use 'table.column'",
|
|
42970
|
+
invalid_system: "Invalid database system: {system}",
|
|
42971
|
+
invalid_permission: "Invalid permission level: {permission}",
|
|
42972
|
+
invalid_port: "Invalid port: {port}",
|
|
42973
|
+
require_user: "Non-interactive mode requires --user option",
|
|
42974
|
+
require_name: "Non-interactive mode requires --name option",
|
|
42975
|
+
env_refs_missing_options: `When using --use-env-refs, environment variable names must be specified.
|
|
42976
|
+
Provide options: --env-host, --env-port, --env-user, --env-password, --env-database
|
|
42977
|
+
Or use interactive mode: run "dbcli init --use-env-refs" without --no-interactive`,
|
|
42978
|
+
env_var_not_defined: `Cannot test connection: environment variable {envKey} is not defined.
|
|
42979
|
+
Set {envKey} in .env or environment variables.
|
|
42980
|
+
Hint: run 'export {envKey}=<value>' and retry`
|
|
42874
42981
|
},
|
|
42875
42982
|
success: {
|
|
42876
42983
|
inserted: "Successfully inserted {count} row(s)",
|
|
@@ -42920,6 +43027,11 @@ var messages_default = {
|
|
|
42920
43027
|
},
|
|
42921
43028
|
warnings: {
|
|
42922
43029
|
blacklist_override_used: "Warning: Blacklist override enabled (DBCLI_OVERRIDE_BLACKLIST=true). Executing {operation} on blacklisted table '{table}'"
|
|
43030
|
+
},
|
|
43031
|
+
version: {
|
|
43032
|
+
unsupported_warning: "{system} {version} is below minimum supported version {minVersion}. Some features may not work correctly.",
|
|
43033
|
+
doctor_pass: "{system} {version} (meets >= {minVersion})",
|
|
43034
|
+
doctor_warn: "{system} {version} is below supported >= {minVersion}"
|
|
42923
43035
|
}
|
|
42924
43036
|
};
|
|
42925
43037
|
// resources/lang/zh-TW/messages.json
|
|
@@ -42940,7 +43052,11 @@ var messages_default2 = {
|
|
|
42940
43052
|
connection_failed: "\u2717 \u8CC7\u6599\u5EAB\u9023\u63A5\u5931\u6557",
|
|
42941
43053
|
config_saved: "\u914D\u7F6E\u5DF2\u4FDD\u5B58\u81F3 .dbcli",
|
|
42942
43054
|
config_exists_overwrite: "\u914D\u7F6E\u6A94\u6848 .dbcli \u5DF2\u5B58\u5728\u3002\u662F\u5426\u8986\u84CB\uFF1F (y/n)\uFF1A",
|
|
42943
|
-
cancelled: "\u5DF2\u53D6\u6D88\u3002\u914D\u7F6E\u672A\u66F4\u6539\u3002"
|
|
43055
|
+
cancelled: "\u5DF2\u53D6\u6D88\u3002\u914D\u7F6E\u672A\u66F4\u6539\u3002",
|
|
43056
|
+
skip_test_env_ref: "\u8DF3\u904E\u9023\u7DDA\u6E2C\u8A66\uFF08\u74B0\u5883\u8B8A\u6578\u53C3\u7167\u6A21\u5F0F\uFF09",
|
|
43057
|
+
skip_test: "\u8DF3\u904E\u9023\u7DDA\u6E2C\u8A66\uFF08--skip-test\uFF09",
|
|
43058
|
+
connection_hints: "\u63D0\u793A\uFF1A",
|
|
43059
|
+
config_exists_use_force: ".dbcli \u5DF2\u5B58\u5728\u3002\u4F7F\u7528 --force \u9078\u9805\u8986\u84CB\u3002"
|
|
42944
43060
|
},
|
|
42945
43061
|
schema: {
|
|
42946
43062
|
description: "\u6AA2\u7D22\u8868\u683C\u7D50\u69CB\u6216\u5217\u51FA\u6240\u6709\u8868\u683C",
|
|
@@ -42979,7 +43095,18 @@ var messages_default2 = {
|
|
|
42979
43095
|
column_already_blacklisted: "\u932F\u8AA4: \u6B04\u4F4D '{table}.{column}' \u5DF2\u5728\u9ED1\u540D\u55AE\u4E2D",
|
|
42980
43096
|
column_not_in_blacklist: "\u932F\u8AA4: \u6B04\u4F4D '{table}.{column}' \u4E0D\u5728\u9ED1\u540D\u55AE\u4E2D",
|
|
42981
43097
|
invalid_table_name: "\u932F\u8AA4: \u7121\u6548\u7684\u8868\u683C\u540D\u7A31: {table}",
|
|
42982
|
-
invalid_column_format: "\u932F\u8AA4: \u7121\u6548\u7684\u6B04\u4F4D\u683C\u5F0F\u3002\u4F7F\u7528 'table.column'"
|
|
43098
|
+
invalid_column_format: "\u932F\u8AA4: \u7121\u6548\u7684\u6B04\u4F4D\u683C\u5F0F\u3002\u4F7F\u7528 'table.column'",
|
|
43099
|
+
invalid_system: "\u7121\u6548\u7684\u8CC7\u6599\u5EAB\u7CFB\u7D71\uFF1A{system}",
|
|
43100
|
+
invalid_permission: "\u7121\u6548\u7684\u6B0A\u9650\u7B49\u7D1A\uFF1A{permission}",
|
|
43101
|
+
invalid_port: "\u7121\u6548\u7684\u57E0\u865F\uFF1A{port}",
|
|
43102
|
+
require_user: "\u975E\u4E92\u52D5\u6A21\u5F0F\u9700\u8981 --user \u9078\u9805",
|
|
43103
|
+
require_name: "\u975E\u4E92\u52D5\u6A21\u5F0F\u9700\u8981 --name \u9078\u9805",
|
|
43104
|
+
env_refs_missing_options: `\u4F7F\u7528 --use-env-refs \u6642\uFF0C\u5FC5\u9808\u6307\u5B9A\u74B0\u5883\u8B8A\u6578\u540D\u7A31\u3002
|
|
43105
|
+
\u8ACB\u63D0\u4F9B\u9078\u9805\uFF1A--env-host\u3001--env-port\u3001--env-user\u3001--env-password\u3001--env-database
|
|
43106
|
+
\u6216\u4F7F\u7528\u4E92\u52D5\u6A21\u5F0F\uFF1A\u57F7\u884C "dbcli init --use-env-refs"\uFF08\u4E0D\u52A0 --no-interactive\uFF09`,
|
|
43107
|
+
env_var_not_defined: `\u7121\u6CD5\u6E2C\u8A66\u9023\u7DDA\uFF1A\u74B0\u5883\u8B8A\u6578 {envKey} \u672A\u5B9A\u7FA9\u3002
|
|
43108
|
+
\u8ACB\u5728 .env \u6216\u74B0\u5883\u8B8A\u6578\u4E2D\u8A2D\u5B9A {envKey}\u3002
|
|
43109
|
+
\u63D0\u793A\uFF1A\u57F7\u884C 'export {envKey}=<value>' \u5F8C\u91CD\u8A66`
|
|
42983
43110
|
},
|
|
42984
43111
|
success: {
|
|
42985
43112
|
inserted: "\u6210\u529F\u63D2\u5165 {count} \u5217",
|
|
@@ -43029,6 +43156,11 @@ var messages_default2 = {
|
|
|
43029
43156
|
},
|
|
43030
43157
|
warnings: {
|
|
43031
43158
|
blacklist_override_used: "\u8B66\u544A: \u5DF2\u555F\u7528\u9ED1\u540D\u55AE\u8986\u84CB (DBCLI_OVERRIDE_BLACKLIST=true)\u3002\u57F7\u884C {operation} \u5728\u5DF2\u9ED1\u540D\u55AE\u7684\u8868\u683C '{table}' \u4E0A"
|
|
43159
|
+
},
|
|
43160
|
+
version: {
|
|
43161
|
+
unsupported_warning: "{system} {version} \u4F4E\u65BC\u6700\u4F4E\u652F\u63F4\u7248\u672C {minVersion}\u3002\u90E8\u5206\u529F\u80FD\u53EF\u80FD\u7121\u6CD5\u6B63\u5E38\u904B\u4F5C\u3002",
|
|
43162
|
+
doctor_pass: "{system} {version}\uFF08\u7B26\u5408 >= {minVersion}\uFF09",
|
|
43163
|
+
doctor_warn: "{system} {version} \u4F4E\u65BC\u652F\u63F4\u7248\u672C >= {minVersion}"
|
|
43032
43164
|
}
|
|
43033
43165
|
};
|
|
43034
43166
|
|
|
@@ -43101,6 +43233,47 @@ var messageLoader = MessageLoader.getInstance();
|
|
|
43101
43233
|
var t = (key) => messageLoader.t(key);
|
|
43102
43234
|
var t_vars = (key, vars) => messageLoader.interpolate(key, vars);
|
|
43103
43235
|
|
|
43236
|
+
// src/utils/colors.ts
|
|
43237
|
+
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
43238
|
+
var colors = {
|
|
43239
|
+
success: (text) => import_picocolors.default.green(text),
|
|
43240
|
+
error: (text) => import_picocolors.default.red(text),
|
|
43241
|
+
warn: (text) => import_picocolors.default.yellow(text),
|
|
43242
|
+
info: (text) => import_picocolors.default.blue(text),
|
|
43243
|
+
dim: (text) => import_picocolors.default.dim(text),
|
|
43244
|
+
bold: (text) => import_picocolors.default.bold(text),
|
|
43245
|
+
keyword: (text) => import_picocolors.default.blue(import_picocolors.default.bold(text))
|
|
43246
|
+
};
|
|
43247
|
+
|
|
43248
|
+
// src/utils/logger.ts
|
|
43249
|
+
function formatArgs(args) {
|
|
43250
|
+
return args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
|
|
43251
|
+
}
|
|
43252
|
+
function createLogger(level = 1 /* NORMAL */) {
|
|
43253
|
+
const write = (minLevel, prefix, args) => {
|
|
43254
|
+
if (level < minLevel)
|
|
43255
|
+
return;
|
|
43256
|
+
const message = `${prefix} ${formatArgs(args)}
|
|
43257
|
+
`;
|
|
43258
|
+
process.stderr.write(message);
|
|
43259
|
+
};
|
|
43260
|
+
return {
|
|
43261
|
+
error: (...args) => write(0 /* QUIET */, colors.error("[ERROR]"), args),
|
|
43262
|
+
warn: (...args) => write(1 /* NORMAL */, colors.warn("[WARN]"), args),
|
|
43263
|
+
info: (...args) => write(1 /* NORMAL */, colors.info("[INFO]"), args),
|
|
43264
|
+
verbose: (...args) => write(2 /* VERBOSE */, colors.dim("[VERBOSE]"), args),
|
|
43265
|
+
debug: (...args) => write(3 /* DEBUG */, colors.dim("[DEBUG]"), args),
|
|
43266
|
+
level
|
|
43267
|
+
};
|
|
43268
|
+
}
|
|
43269
|
+
var globalLogger = createLogger(1 /* NORMAL */);
|
|
43270
|
+
function setGlobalLogger(logger) {
|
|
43271
|
+
globalLogger = logger;
|
|
43272
|
+
}
|
|
43273
|
+
function getLogger() {
|
|
43274
|
+
return globalLogger;
|
|
43275
|
+
}
|
|
43276
|
+
|
|
43104
43277
|
// src/utils/errors.ts
|
|
43105
43278
|
class EnvParseError extends Error {
|
|
43106
43279
|
constructor(message) {
|
|
@@ -47546,6 +47719,61 @@ var Result = import_lib.default.Result;
|
|
|
47546
47719
|
var TypeOverrides = import_lib.default.TypeOverrides;
|
|
47547
47720
|
var defaults = import_lib.default.defaults;
|
|
47548
47721
|
|
|
47722
|
+
// src/utils/db-version-check.ts
|
|
47723
|
+
var MIN_SUPPORTED_VERSIONS = {
|
|
47724
|
+
postgresql: "12.0",
|
|
47725
|
+
mysql: "8.0",
|
|
47726
|
+
mariadb: "10.5"
|
|
47727
|
+
};
|
|
47728
|
+
function parseVersionSegments(version) {
|
|
47729
|
+
const match = version.match(/^(\d+(?:\.\d+)*)/);
|
|
47730
|
+
if (!match)
|
|
47731
|
+
return [];
|
|
47732
|
+
return match[1].split(".").map(Number);
|
|
47733
|
+
}
|
|
47734
|
+
function isMariaDBVersion(versionString) {
|
|
47735
|
+
return /mariadb/i.test(versionString);
|
|
47736
|
+
}
|
|
47737
|
+
function extractMariaDBVersion(versionString) {
|
|
47738
|
+
const match = versionString.match(/(\d+\.\d+\.\d+)-MariaDB/i);
|
|
47739
|
+
if (match)
|
|
47740
|
+
return match[1];
|
|
47741
|
+
const prefixMatch = versionString.match(/^5\.5\.5-(\d+\.\d+\.\d+)/);
|
|
47742
|
+
if (prefixMatch)
|
|
47743
|
+
return prefixMatch[1];
|
|
47744
|
+
return versionString;
|
|
47745
|
+
}
|
|
47746
|
+
function compareVersions(a, b) {
|
|
47747
|
+
const segA = parseVersionSegments(a);
|
|
47748
|
+
const segB = parseVersionSegments(b);
|
|
47749
|
+
const len = Math.max(segA.length, segB.length);
|
|
47750
|
+
for (let i = 0;i < len; i++) {
|
|
47751
|
+
const diff = (segA[i] ?? 0) - (segB[i] ?? 0);
|
|
47752
|
+
if (diff !== 0)
|
|
47753
|
+
return diff;
|
|
47754
|
+
}
|
|
47755
|
+
return 0;
|
|
47756
|
+
}
|
|
47757
|
+
function checkDbVersion(rawVersion, declaredSystem) {
|
|
47758
|
+
const isMariaDB = isMariaDBVersion(rawVersion);
|
|
47759
|
+
const system = isMariaDB ? "mariadb" : declaredSystem;
|
|
47760
|
+
const serverVersion = isMariaDB ? extractMariaDBVersion(rawVersion) : rawVersion;
|
|
47761
|
+
const minVersion = MIN_SUPPORTED_VERSIONS[system];
|
|
47762
|
+
const supported = compareVersions(serverVersion, minVersion) >= 0;
|
|
47763
|
+
return { serverVersion, system, supported, minVersion };
|
|
47764
|
+
}
|
|
47765
|
+
function warnIfUnsupported(result) {
|
|
47766
|
+
if (result.supported)
|
|
47767
|
+
return;
|
|
47768
|
+
const message = t_vars("version.unsupported_warning", {
|
|
47769
|
+
system: result.system,
|
|
47770
|
+
version: result.serverVersion,
|
|
47771
|
+
minVersion: result.minVersion
|
|
47772
|
+
});
|
|
47773
|
+
process.stderr.write(colors.warn(`\u26A0 ${message}`) + `
|
|
47774
|
+
`);
|
|
47775
|
+
}
|
|
47776
|
+
|
|
47549
47777
|
// src/adapters/postgresql-adapter.ts
|
|
47550
47778
|
class PostgreSQLAdapter {
|
|
47551
47779
|
pool = null;
|
|
@@ -47569,6 +47797,11 @@ class PostgreSQLAdapter {
|
|
|
47569
47797
|
statement_timeout: this.options.timeout || 5000
|
|
47570
47798
|
});
|
|
47571
47799
|
await this.testConnection();
|
|
47800
|
+
try {
|
|
47801
|
+
const rawVersion = await this.getServerVersion();
|
|
47802
|
+
const result = checkDbVersion(rawVersion, "postgresql");
|
|
47803
|
+
warnIfUnsupported(result);
|
|
47804
|
+
} catch {}
|
|
47572
47805
|
} catch (error) {
|
|
47573
47806
|
throw mapError(error, "postgresql", this.options);
|
|
47574
47807
|
}
|
|
@@ -47607,6 +47840,10 @@ class PostgreSQLAdapter {
|
|
|
47607
47840
|
throw mapError(error, "postgresql", this.options);
|
|
47608
47841
|
}
|
|
47609
47842
|
}
|
|
47843
|
+
async getServerVersion() {
|
|
47844
|
+
const rows = await this.execute("SHOW server_version");
|
|
47845
|
+
return rows[0]?.server_version ?? "unknown";
|
|
47846
|
+
}
|
|
47610
47847
|
async listTables() {
|
|
47611
47848
|
if (!this.pool) {
|
|
47612
47849
|
throw new ConnectionError("UNKNOWN", "Database connection not established", ["Call connect() to establish a connection"]);
|
|
@@ -47817,6 +48054,11 @@ class MySQLAdapter {
|
|
|
47817
48054
|
database: this.options.database
|
|
47818
48055
|
});
|
|
47819
48056
|
await this.testConnection();
|
|
48057
|
+
try {
|
|
48058
|
+
const rawVersion = await this.getServerVersion();
|
|
48059
|
+
const result = checkDbVersion(rawVersion, this.system);
|
|
48060
|
+
warnIfUnsupported(result);
|
|
48061
|
+
} catch {}
|
|
47820
48062
|
} catch (error) {
|
|
47821
48063
|
throw mapError(error, this.system, this.options);
|
|
47822
48064
|
}
|
|
@@ -47851,6 +48093,10 @@ class MySQLAdapter {
|
|
|
47851
48093
|
throw mapError(error, this.system, this.options);
|
|
47852
48094
|
}
|
|
47853
48095
|
}
|
|
48096
|
+
async getServerVersion() {
|
|
48097
|
+
const rows = await this.execute("SELECT VERSION() as version");
|
|
48098
|
+
return rows[0]?.version ?? "unknown";
|
|
48099
|
+
}
|
|
47854
48100
|
async listTables() {
|
|
47855
48101
|
if (!this.db) {
|
|
47856
48102
|
throw new ConnectionError("UNKNOWN", "Database connection not established", ["Call connect() to establish a connection"]);
|
|
@@ -48002,7 +48248,23 @@ class AdapterFactory {
|
|
|
48002
48248
|
}
|
|
48003
48249
|
}
|
|
48004
48250
|
// src/commands/init.ts
|
|
48005
|
-
var
|
|
48251
|
+
var VALID_PERMISSIONS = ["query-only", "read-write", "data-admin", "admin"];
|
|
48252
|
+
async function checkOverwrite(shouldPrompt, force) {
|
|
48253
|
+
const configFile = Bun.file(".dbcli");
|
|
48254
|
+
const fileExists = await configFile.exists();
|
|
48255
|
+
if (!fileExists || force)
|
|
48256
|
+
return true;
|
|
48257
|
+
if (shouldPrompt) {
|
|
48258
|
+
const overwrite = await promptUser.confirm(t("init.config_exists_overwrite"));
|
|
48259
|
+
if (!overwrite) {
|
|
48260
|
+
console.log(t("init.cancelled"));
|
|
48261
|
+
return false;
|
|
48262
|
+
}
|
|
48263
|
+
return true;
|
|
48264
|
+
}
|
|
48265
|
+
throw new Error(t("init.config_exists_use_force"));
|
|
48266
|
+
}
|
|
48267
|
+
var initCommand = new Command("init").description("Initialize dbcli configuration with .env parsing and interactive prompts").option("--host <host>", "Database host").option("--port <port>", "Database port").option("--user <user>", "Database user").option("--password <password>", "Database password").option("--name <name>", "Database name").option("--system <system>", "Database system (postgresql, mysql, mariadb)").option("--permission <permission>", "Permission level (query-only, read-write, data-admin, admin)", "query-only").option("--use-env-refs", "Store env var references in config instead of actual values (for CI/CD or multi-env)", false).option("--env-host <var>", "Env var name for host (with --use-env-refs)").option("--env-port <var>", "Env var name for port (with --use-env-refs)").option("--env-user <var>", "Env var name for user (with --use-env-refs)").option("--env-password <var>", "Env var name for password (with --use-env-refs)").option("--env-database <var>", "Env var name for database (with --use-env-refs)").option("--skip-test", "Skip database connection test").option("--no-interactive", "Non-interactive mode (requires all values via flags)").option("--force", "Skip overwrite confirmation if .dbcli exists").action(async (options) => {
|
|
48006
48268
|
try {
|
|
48007
48269
|
await initCommandHandler(options);
|
|
48008
48270
|
} catch (error) {
|
|
@@ -48036,7 +48298,7 @@ async function initCommandHandler(options) {
|
|
|
48036
48298
|
]);
|
|
48037
48299
|
}
|
|
48038
48300
|
if (!["postgresql", "mysql", "mariadb"].includes(system)) {
|
|
48039
|
-
throw new Error(
|
|
48301
|
+
throw new Error(t_vars("errors.invalid_system", { system }));
|
|
48040
48302
|
}
|
|
48041
48303
|
const defaults2 = getDefaultsForSystem(system);
|
|
48042
48304
|
const connection = {
|
|
@@ -48058,34 +48320,25 @@ async function initCommandHandler(options) {
|
|
|
48058
48320
|
database: { $env: envDatabase }
|
|
48059
48321
|
};
|
|
48060
48322
|
let permission2 = options.permission || "query-only";
|
|
48061
|
-
if (
|
|
48323
|
+
if (!options.permission) {
|
|
48062
48324
|
permission2 = await promptUser.select(t("init.prompt_permission"), [
|
|
48063
48325
|
"query-only",
|
|
48064
48326
|
"read-write",
|
|
48327
|
+
"data-admin",
|
|
48065
48328
|
"admin"
|
|
48066
48329
|
]);
|
|
48067
48330
|
}
|
|
48068
|
-
if (!
|
|
48069
|
-
throw new Error(
|
|
48331
|
+
if (!VALID_PERMISSIONS.includes(permission2)) {
|
|
48332
|
+
throw new Error(t_vars("errors.invalid_permission", { permission: permission2 }));
|
|
48070
48333
|
}
|
|
48071
48334
|
const newConfig2 = configModule.merge(existingConfig, {
|
|
48072
48335
|
connection: configForWrite,
|
|
48073
48336
|
permission: permission2
|
|
48074
48337
|
});
|
|
48075
|
-
const
|
|
48076
|
-
|
|
48077
|
-
|
|
48078
|
-
|
|
48079
|
-
const overwrite = await promptUser.confirm(t("init.config_exists_overwrite"));
|
|
48080
|
-
if (!overwrite) {
|
|
48081
|
-
console.log(t("init.cancelled"));
|
|
48082
|
-
return;
|
|
48083
|
-
}
|
|
48084
|
-
} else {
|
|
48085
|
-
throw new Error(".dbcli exists. Use --force option to overwrite.");
|
|
48086
|
-
}
|
|
48087
|
-
}
|
|
48088
|
-
console.log("\u23ED\uFE0F Skipping connection test in env-ref mode");
|
|
48338
|
+
const canProceed2 = await checkOverwrite(shouldPrompt, !!options.force);
|
|
48339
|
+
if (!canProceed2)
|
|
48340
|
+
return;
|
|
48341
|
+
console.log(`\u23ED\uFE0F ${t("init.skip_test_env_ref")}`);
|
|
48089
48342
|
await configModule.write(".dbcli", newConfig2);
|
|
48090
48343
|
console.log(t("init.config_saved"));
|
|
48091
48344
|
return;
|
|
@@ -48094,17 +48347,17 @@ async function initCommandHandler(options) {
|
|
|
48094
48347
|
const portStr = options.port || (envConfig?.port ? String(envConfig.port) : null) || (shouldPrompt ? await promptUser.text(t("init.prompt_port"), String(defaults2.port || 5432)) : String(defaults2.port || 5432));
|
|
48095
48348
|
const port = parseInt(portStr, 10);
|
|
48096
48349
|
if (isNaN(port) || port < 1 || port > 65535) {
|
|
48097
|
-
throw new Error(
|
|
48350
|
+
throw new Error(t_vars("errors.invalid_port", { port: portStr }));
|
|
48098
48351
|
}
|
|
48099
48352
|
connection.port = port;
|
|
48100
48353
|
connection.user = options.user || envConfig?.user || (shouldPrompt ? await promptUser.text(t("init.prompt_user")) : "");
|
|
48101
48354
|
if (!connection.user && !shouldPrompt && !options.useEnvRefs) {
|
|
48102
|
-
throw new Error("
|
|
48355
|
+
throw new Error(t("errors.require_user"));
|
|
48103
48356
|
}
|
|
48104
48357
|
connection.password = options.password || envConfig?.password || (shouldPrompt ? await promptUser.text(t("init.prompt_password")) : "");
|
|
48105
48358
|
connection.database = options.name || envConfig?.database || (shouldPrompt ? await promptUser.text(t("init.prompt_name")) : "");
|
|
48106
48359
|
if (!connection.database && !shouldPrompt && !options.useEnvRefs) {
|
|
48107
|
-
throw new Error("
|
|
48360
|
+
throw new Error(t("errors.require_name"));
|
|
48108
48361
|
}
|
|
48109
48362
|
let permission = options.permission || "query-only";
|
|
48110
48363
|
if (shouldPrompt && !options.permission) {
|
|
@@ -48115,8 +48368,8 @@ async function initCommandHandler(options) {
|
|
|
48115
48368
|
"admin"
|
|
48116
48369
|
]);
|
|
48117
48370
|
}
|
|
48118
|
-
if (!
|
|
48119
|
-
throw new Error(
|
|
48371
|
+
if (!VALID_PERMISSIONS.includes(permission)) {
|
|
48372
|
+
throw new Error(t_vars("errors.invalid_permission", { permission }));
|
|
48120
48373
|
}
|
|
48121
48374
|
configForWrite = connection;
|
|
48122
48375
|
if (options.useEnvRefs) {
|
|
@@ -48126,9 +48379,7 @@ async function initCommandHandler(options) {
|
|
|
48126
48379
|
const envPassword = options.envPassword;
|
|
48127
48380
|
const envDatabase = options.envDatabase;
|
|
48128
48381
|
if (!envHost || !envPort || !envUser || !envPassword || !envDatabase) {
|
|
48129
|
-
throw new Error(
|
|
48130
|
-
` + `Provide options: --env-host, --env-port, --env-user, --env-password, --env-database
|
|
48131
|
-
` + 'Or use interactive mode: run "bun dev init --use-env-refs" without --no-interactive');
|
|
48382
|
+
throw new Error(t("errors.env_refs_missing_options"));
|
|
48132
48383
|
}
|
|
48133
48384
|
configForWrite = {
|
|
48134
48385
|
system: connection.system,
|
|
@@ -48143,29 +48394,17 @@ async function initCommandHandler(options) {
|
|
|
48143
48394
|
connection: configForWrite,
|
|
48144
48395
|
permission
|
|
48145
48396
|
});
|
|
48146
|
-
const
|
|
48147
|
-
|
|
48148
|
-
|
|
48149
|
-
if (shouldPrompt) {
|
|
48150
|
-
const overwrite = await promptUser.confirm(t("init.config_exists_overwrite"));
|
|
48151
|
-
if (!overwrite) {
|
|
48152
|
-
console.log(t("init.cancelled"));
|
|
48153
|
-
return;
|
|
48154
|
-
}
|
|
48155
|
-
} else {
|
|
48156
|
-
throw new Error(".dbcli exists. Use --force option to overwrite.");
|
|
48157
|
-
}
|
|
48158
|
-
}
|
|
48397
|
+
const canProceed = await checkOverwrite(shouldPrompt, !!options.force);
|
|
48398
|
+
if (!canProceed)
|
|
48399
|
+
return;
|
|
48159
48400
|
if (!options.skipTest && !options.useEnvRefs) {
|
|
48160
48401
|
console.log(t("init.connection_testing"));
|
|
48161
|
-
const resolveValue = (value,
|
|
48402
|
+
const resolveValue = (value, _fieldName) => {
|
|
48162
48403
|
if (typeof value === "object" && value !== null && "$env" in value) {
|
|
48163
48404
|
const envKey = value.$env;
|
|
48164
48405
|
const envValue = process.env[envKey];
|
|
48165
48406
|
if (!envValue) {
|
|
48166
|
-
throw new Error(
|
|
48167
|
-
` + `Set ${envKey} in .env or environment variables.
|
|
48168
|
-
` + `Hint: Check .env file or run 'export ${envKey}=<value>' and retry`);
|
|
48407
|
+
throw new Error(t_vars("errors.env_var_not_defined", { envKey }));
|
|
48169
48408
|
}
|
|
48170
48409
|
return envValue;
|
|
48171
48410
|
}
|
|
@@ -48189,7 +48428,7 @@ async function initCommandHandler(options) {
|
|
|
48189
48428
|
} catch (error) {
|
|
48190
48429
|
if (error instanceof ConnectionError) {
|
|
48191
48430
|
console.error(t_vars("errors.connection_failed", { message: error.message }));
|
|
48192
|
-
console.error("
|
|
48431
|
+
console.error(t("init.connection_hints"));
|
|
48193
48432
|
error.hints.forEach((hint) => console.error(` \u2022 ${hint}`));
|
|
48194
48433
|
process.exit(1);
|
|
48195
48434
|
}
|
|
@@ -48198,7 +48437,8 @@ async function initCommandHandler(options) {
|
|
|
48198
48437
|
await adapter.disconnect();
|
|
48199
48438
|
}
|
|
48200
48439
|
} else {
|
|
48201
|
-
|
|
48440
|
+
const msgKey = options.useEnvRefs ? "init.skip_test_env_ref" : "init.skip_test";
|
|
48441
|
+
console.log(`\u23ED\uFE0F ${t(msgKey)}`);
|
|
48202
48442
|
}
|
|
48203
48443
|
await configModule.write(".dbcli", newConfig);
|
|
48204
48444
|
console.log(t("init.config_saved"));
|
|
@@ -48210,7 +48450,7 @@ var Table = require_table();
|
|
|
48210
48450
|
class TableFormatter {
|
|
48211
48451
|
format(columns) {
|
|
48212
48452
|
const table = new Table({
|
|
48213
|
-
head: ["Column", "Type", "Nullable", "Default", "Key"],
|
|
48453
|
+
head: ["Column", "Type", "Nullable", "Default", "Key"].map((h) => colors.bold(h)),
|
|
48214
48454
|
style: { compact: false, "padding-left": 1, "padding-right": 1 },
|
|
48215
48455
|
colWidths: [25, 25, 10, 25, 20]
|
|
48216
48456
|
});
|
|
@@ -48236,7 +48476,7 @@ class TableFormatter {
|
|
|
48236
48476
|
class TableListFormatter {
|
|
48237
48477
|
format(tables) {
|
|
48238
48478
|
const table = new Table({
|
|
48239
|
-
head: ["Table", "Columns", "Rows", "Engine"],
|
|
48479
|
+
head: ["Table", "Columns", "Rows", "Engine"].map((h) => colors.bold(h)),
|
|
48240
48480
|
style: { compact: false, "padding-left": 1, "padding-right": 1 },
|
|
48241
48481
|
colWidths: [30, 12, 15, 15]
|
|
48242
48482
|
});
|
|
@@ -50824,8 +51064,657 @@ var statusCommand = new Command("status").description("Show current configuratio
|
|
|
50824
51064
|
}
|
|
50825
51065
|
});
|
|
50826
51066
|
|
|
51067
|
+
// src/commands/doctor.ts
|
|
51068
|
+
import { join as join3 } from "path";
|
|
51069
|
+
var SENSITIVE_PATTERNS = [
|
|
51070
|
+
"password",
|
|
51071
|
+
"passwd",
|
|
51072
|
+
"secret",
|
|
51073
|
+
"token",
|
|
51074
|
+
"api_key",
|
|
51075
|
+
"apikey",
|
|
51076
|
+
"access_key",
|
|
51077
|
+
"private_key",
|
|
51078
|
+
"credential",
|
|
51079
|
+
"auth_token",
|
|
51080
|
+
"refresh_token",
|
|
51081
|
+
"session_token",
|
|
51082
|
+
"ssn",
|
|
51083
|
+
"credit_card"
|
|
51084
|
+
];
|
|
51085
|
+
function compareSemver(a, b) {
|
|
51086
|
+
const pa = a.split(".").map(Number);
|
|
51087
|
+
const pb = b.split(".").map(Number);
|
|
51088
|
+
for (let i = 0;i < 3; i++) {
|
|
51089
|
+
const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
51090
|
+
if (diff !== 0)
|
|
51091
|
+
return diff;
|
|
51092
|
+
}
|
|
51093
|
+
return 0;
|
|
51094
|
+
}
|
|
51095
|
+
var runDoctorChecks = {
|
|
51096
|
+
checkBunVersion(current, required) {
|
|
51097
|
+
const passes = compareSemver(current, required) >= 0;
|
|
51098
|
+
return {
|
|
51099
|
+
group: "Environment",
|
|
51100
|
+
label: "Bun version",
|
|
51101
|
+
status: passes ? "pass" : "error",
|
|
51102
|
+
message: passes ? `Bun v${current} (meets >= ${required})` : `Bun v${current} is below required >= ${required}`
|
|
51103
|
+
};
|
|
51104
|
+
},
|
|
51105
|
+
async checkLatestVersion(currentVersion) {
|
|
51106
|
+
try {
|
|
51107
|
+
const response = await fetch("https://registry.npmjs.org/@carllee1983/dbcli/latest", { signal: AbortSignal.timeout(5000) });
|
|
51108
|
+
if (!response.ok)
|
|
51109
|
+
throw new Error(`HTTP ${response.status}`);
|
|
51110
|
+
const data = await response.json();
|
|
51111
|
+
const latest = data.version;
|
|
51112
|
+
const isLatest = currentVersion === latest;
|
|
51113
|
+
return {
|
|
51114
|
+
group: "Environment",
|
|
51115
|
+
label: "dbcli version",
|
|
51116
|
+
status: isLatest ? "pass" : "warn",
|
|
51117
|
+
message: isLatest ? `dbcli v${currentVersion} (latest)` : `dbcli v${currentVersion} (latest: ${latest})`
|
|
51118
|
+
};
|
|
51119
|
+
} catch {
|
|
51120
|
+
return {
|
|
51121
|
+
group: "Environment",
|
|
51122
|
+
label: "dbcli version",
|
|
51123
|
+
status: "pass",
|
|
51124
|
+
message: `dbcli v${currentVersion} (version check skipped)`
|
|
51125
|
+
};
|
|
51126
|
+
}
|
|
51127
|
+
},
|
|
51128
|
+
async checkConfigExists(configPath, existsFn) {
|
|
51129
|
+
const exists = existsFn ? await existsFn(configPath) : await Bun.file(configPath).exists() || await Bun.file(join3(configPath, "config.json")).exists();
|
|
51130
|
+
return {
|
|
51131
|
+
group: "Configuration",
|
|
51132
|
+
label: "Config exists",
|
|
51133
|
+
status: exists ? "pass" : "error",
|
|
51134
|
+
message: exists ? `Config found: ${configPath}` : `No config found at ${configPath}. Run "dbcli init" first.`
|
|
51135
|
+
};
|
|
51136
|
+
},
|
|
51137
|
+
checkBlacklistCompleteness(tableColumns, blacklistedColumns) {
|
|
51138
|
+
const unprotected = [];
|
|
51139
|
+
for (const [table, columns] of tableColumns) {
|
|
51140
|
+
const blacklisted = blacklistedColumns.get(table) ?? new Set;
|
|
51141
|
+
for (const col of columns) {
|
|
51142
|
+
const colLower = col.toLowerCase();
|
|
51143
|
+
const isSensitive = SENSITIVE_PATTERNS.some((p) => colLower.includes(p));
|
|
51144
|
+
if (isSensitive && !blacklisted.has(col)) {
|
|
51145
|
+
unprotected.push(`${table}.${col}`);
|
|
51146
|
+
}
|
|
51147
|
+
}
|
|
51148
|
+
}
|
|
51149
|
+
if (unprotected.length === 0) {
|
|
51150
|
+
return {
|
|
51151
|
+
group: "Configuration",
|
|
51152
|
+
label: "Blacklist completeness",
|
|
51153
|
+
status: "pass",
|
|
51154
|
+
message: "All detected sensitive columns are protected"
|
|
51155
|
+
};
|
|
51156
|
+
}
|
|
51157
|
+
return {
|
|
51158
|
+
group: "Configuration",
|
|
51159
|
+
label: "Blacklist completeness",
|
|
51160
|
+
status: "warn",
|
|
51161
|
+
message: `Consider protecting: ${unprotected.join(", ")}`
|
|
51162
|
+
};
|
|
51163
|
+
},
|
|
51164
|
+
checkSchemaCacheFreshness(lastUpdated) {
|
|
51165
|
+
if (!lastUpdated) {
|
|
51166
|
+
return {
|
|
51167
|
+
group: "Connection & Data",
|
|
51168
|
+
label: "Schema cache",
|
|
51169
|
+
status: "warn",
|
|
51170
|
+
message: 'No schema cache found \u2014 run "dbcli schema --refresh"'
|
|
51171
|
+
};
|
|
51172
|
+
}
|
|
51173
|
+
const ageMs = Date.now() - new Date(lastUpdated).getTime();
|
|
51174
|
+
const ageDays = Math.floor(ageMs / (24 * 60 * 60 * 1000));
|
|
51175
|
+
if (ageDays > 7) {
|
|
51176
|
+
return {
|
|
51177
|
+
group: "Connection & Data",
|
|
51178
|
+
label: "Schema cache",
|
|
51179
|
+
status: "warn",
|
|
51180
|
+
message: `Schema cache is ${ageDays} days old \u2014 run "dbcli schema --refresh"`
|
|
51181
|
+
};
|
|
51182
|
+
}
|
|
51183
|
+
return {
|
|
51184
|
+
group: "Connection & Data",
|
|
51185
|
+
label: "Schema cache",
|
|
51186
|
+
status: "pass",
|
|
51187
|
+
message: `Schema cache is ${ageDays} day(s) old`
|
|
51188
|
+
};
|
|
51189
|
+
},
|
|
51190
|
+
checkDatabaseVersion(versionResult) {
|
|
51191
|
+
const vars = {
|
|
51192
|
+
system: versionResult.system,
|
|
51193
|
+
version: versionResult.serverVersion,
|
|
51194
|
+
minVersion: versionResult.minVersion
|
|
51195
|
+
};
|
|
51196
|
+
return {
|
|
51197
|
+
group: "Connection & Data",
|
|
51198
|
+
label: "Database version",
|
|
51199
|
+
status: versionResult.supported ? "pass" : "warn",
|
|
51200
|
+
message: versionResult.supported ? t_vars("version.doctor_pass", vars) : t_vars("version.doctor_warn", vars)
|
|
51201
|
+
};
|
|
51202
|
+
},
|
|
51203
|
+
checkLargeTables(tables) {
|
|
51204
|
+
const large = tables.filter((t7) => (t7.estimatedRowCount ?? 0) > 1e6);
|
|
51205
|
+
if (large.length === 0) {
|
|
51206
|
+
return {
|
|
51207
|
+
group: "Connection & Data",
|
|
51208
|
+
label: "Large tables",
|
|
51209
|
+
status: "pass",
|
|
51210
|
+
message: "No tables exceed 1M rows"
|
|
51211
|
+
};
|
|
51212
|
+
}
|
|
51213
|
+
const list = large.map((t7) => `${t7.name} (${((t7.estimatedRowCount ?? 0) / 1e6).toFixed(1)}M rows)`).join(", ");
|
|
51214
|
+
return {
|
|
51215
|
+
group: "Connection & Data",
|
|
51216
|
+
label: "Large tables",
|
|
51217
|
+
status: "warn",
|
|
51218
|
+
message: `Large tables: ${list}`
|
|
51219
|
+
};
|
|
51220
|
+
},
|
|
51221
|
+
formatTextOutput(results, version) {
|
|
51222
|
+
const lines2 = [`dbcli doctor v${version}`, ""];
|
|
51223
|
+
const groups = ["Environment", "Configuration", "Connection & Data"];
|
|
51224
|
+
for (const group of groups) {
|
|
51225
|
+
const groupResults = results.filter((r) => r.group === group);
|
|
51226
|
+
if (groupResults.length === 0)
|
|
51227
|
+
continue;
|
|
51228
|
+
lines2.push(group);
|
|
51229
|
+
for (const r of groupResults) {
|
|
51230
|
+
const icon = r.status === "pass" ? colors.success("\u2713") : r.status === "warn" ? colors.warn("\u26A0") : colors.error("\u2717");
|
|
51231
|
+
lines2.push(` ${icon} ${r.message}`);
|
|
51232
|
+
}
|
|
51233
|
+
lines2.push("");
|
|
51234
|
+
}
|
|
51235
|
+
const passed = results.filter((r) => r.status === "pass").length;
|
|
51236
|
+
const warnings = results.filter((r) => r.status === "warn").length;
|
|
51237
|
+
const errors3 = results.filter((r) => r.status === "error").length;
|
|
51238
|
+
lines2.push(`Summary: ${passed} passed, ${warnings} warning(s), ${errors3} error(s)`);
|
|
51239
|
+
return lines2.join(`
|
|
51240
|
+
`);
|
|
51241
|
+
}
|
|
51242
|
+
};
|
|
51243
|
+
var doctorCommand = new Command("doctor").description("Run diagnostic checks on dbcli configuration, environment, and connection").option("--format <type>", "Output format: text, json", "text").action(async (options) => {
|
|
51244
|
+
const logger = getLogger();
|
|
51245
|
+
const results = [];
|
|
51246
|
+
const configPath = doctorCommand.parent?.opts().config ?? ".dbcli";
|
|
51247
|
+
const bunVersion = process.versions.bun ?? "unknown";
|
|
51248
|
+
const requiredBun = package_default.engines?.bun?.replace(">=", "") ?? "1.3.3";
|
|
51249
|
+
results.push(runDoctorChecks.checkBunVersion(bunVersion, requiredBun));
|
|
51250
|
+
results.push(await runDoctorChecks.checkLatestVersion(package_default.version));
|
|
51251
|
+
const configExists = await runDoctorChecks.checkConfigExists(configPath);
|
|
51252
|
+
results.push(configExists);
|
|
51253
|
+
if (configExists.status !== "error") {
|
|
51254
|
+
try {
|
|
51255
|
+
const config = await configModule.read(configPath);
|
|
51256
|
+
results.push({
|
|
51257
|
+
group: "Configuration",
|
|
51258
|
+
label: "Config valid",
|
|
51259
|
+
status: "pass",
|
|
51260
|
+
message: "Config valid"
|
|
51261
|
+
});
|
|
51262
|
+
results.push({
|
|
51263
|
+
group: "Configuration",
|
|
51264
|
+
label: "Permission",
|
|
51265
|
+
status: "pass",
|
|
51266
|
+
message: `Permission: ${config.permission}`
|
|
51267
|
+
});
|
|
51268
|
+
const blacklistedColumns = new Map;
|
|
51269
|
+
if (config.blacklist?.columns) {
|
|
51270
|
+
for (const [table, cols] of Object.entries(config.blacklist.columns)) {
|
|
51271
|
+
blacklistedColumns.set(table, new Set(cols));
|
|
51272
|
+
}
|
|
51273
|
+
}
|
|
51274
|
+
try {
|
|
51275
|
+
const adapter = AdapterFactory.createAdapter(config.connection);
|
|
51276
|
+
await adapter.connect();
|
|
51277
|
+
results.push({
|
|
51278
|
+
group: "Connection & Data",
|
|
51279
|
+
label: "Connection",
|
|
51280
|
+
status: "pass",
|
|
51281
|
+
message: `Connected to ${config.connection.system} ${config.connection.database}@${config.connection.host}:${config.connection.port}`
|
|
51282
|
+
});
|
|
51283
|
+
try {
|
|
51284
|
+
const rawVersion = await adapter.getServerVersion();
|
|
51285
|
+
const versionResult = checkDbVersion(rawVersion, config.connection.system);
|
|
51286
|
+
results.push(runDoctorChecks.checkDatabaseVersion(versionResult));
|
|
51287
|
+
} catch {
|
|
51288
|
+
logger.debug("Could not retrieve database version");
|
|
51289
|
+
}
|
|
51290
|
+
try {
|
|
51291
|
+
const tables = await adapter.listTables();
|
|
51292
|
+
const tableColumns = new Map;
|
|
51293
|
+
for (const t7 of tables) {
|
|
51294
|
+
tableColumns.set(t7.name, t7.columns.map((c) => c.name));
|
|
51295
|
+
}
|
|
51296
|
+
results.push(runDoctorChecks.checkBlacklistCompleteness(tableColumns, blacklistedColumns));
|
|
51297
|
+
results.push(runDoctorChecks.checkLargeTables(tables));
|
|
51298
|
+
} catch {
|
|
51299
|
+
logger.debug("Could not list tables for blacklist/large table check");
|
|
51300
|
+
}
|
|
51301
|
+
try {
|
|
51302
|
+
const indexPath = join3(configPath, "schemas", "index.json");
|
|
51303
|
+
const indexFile = Bun.file(indexPath);
|
|
51304
|
+
if (await indexFile.exists()) {
|
|
51305
|
+
const indexContent = await indexFile.text();
|
|
51306
|
+
const index = JSON.parse(indexContent);
|
|
51307
|
+
results.push(runDoctorChecks.checkSchemaCacheFreshness(index.updatedAt ?? null));
|
|
51308
|
+
} else {
|
|
51309
|
+
results.push(runDoctorChecks.checkSchemaCacheFreshness(null));
|
|
51310
|
+
}
|
|
51311
|
+
} catch {
|
|
51312
|
+
results.push(runDoctorChecks.checkSchemaCacheFreshness(null));
|
|
51313
|
+
}
|
|
51314
|
+
await adapter.disconnect();
|
|
51315
|
+
} catch (error) {
|
|
51316
|
+
results.push({
|
|
51317
|
+
group: "Connection & Data",
|
|
51318
|
+
label: "Connection",
|
|
51319
|
+
status: "error",
|
|
51320
|
+
message: `Connection failed: ${error.message}`
|
|
51321
|
+
});
|
|
51322
|
+
}
|
|
51323
|
+
} catch (error) {
|
|
51324
|
+
results.push({
|
|
51325
|
+
group: "Configuration",
|
|
51326
|
+
label: "Config valid",
|
|
51327
|
+
status: "error",
|
|
51328
|
+
message: `Config invalid: ${error.message}`
|
|
51329
|
+
});
|
|
51330
|
+
}
|
|
51331
|
+
}
|
|
51332
|
+
const hasError = results.some((r) => r.status === "error");
|
|
51333
|
+
if (options.format === "json") {
|
|
51334
|
+
console.log(JSON.stringify({ results, hasError }, null, 2));
|
|
51335
|
+
} else {
|
|
51336
|
+
console.log(runDoctorChecks.formatTextOutput(results, package_default.version));
|
|
51337
|
+
}
|
|
51338
|
+
if (hasError) {
|
|
51339
|
+
process.exit(1);
|
|
51340
|
+
}
|
|
51341
|
+
});
|
|
51342
|
+
|
|
51343
|
+
// src/commands/completion.ts
|
|
51344
|
+
import { join as join4 } from "path";
|
|
51345
|
+
import { homedir as homedir2 } from "os";
|
|
51346
|
+
function extractCommands(program2) {
|
|
51347
|
+
return program2.commands.map((cmd) => ({
|
|
51348
|
+
name: cmd.name(),
|
|
51349
|
+
options: cmd.options.map((o) => o.long ?? o.short ?? "").filter(Boolean)
|
|
51350
|
+
}));
|
|
51351
|
+
}
|
|
51352
|
+
function extractGlobalOptions(program2) {
|
|
51353
|
+
return program2.options.map((o) => o.long ?? o.short ?? "").filter(Boolean);
|
|
51354
|
+
}
|
|
51355
|
+
function generateBashCompletion(commands, globalOptions) {
|
|
51356
|
+
const cmdNames = commands.map((c) => c.name).join(" ");
|
|
51357
|
+
const globalOpts = globalOptions.join(" ");
|
|
51358
|
+
const caseEntries = commands.map((c) => ` ${c.name})
|
|
51359
|
+
COMPREPLY=( $(compgen -W "${c.options.join(" ")}" -- "\${cur}") )
|
|
51360
|
+
;;`).join(`
|
|
51361
|
+
`);
|
|
51362
|
+
return `#!/bin/bash
|
|
51363
|
+
# dbcli bash completion \u2014 auto-generated, do not edit
|
|
51364
|
+
_dbcli_completions() {
|
|
51365
|
+
local cur prev commands
|
|
51366
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
51367
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
51368
|
+
commands="${cmdNames}"
|
|
51369
|
+
|
|
51370
|
+
if [[ \${COMP_CWORD} -eq 1 ]]; then
|
|
51371
|
+
COMPREPLY=( $(compgen -W "\${commands} ${globalOpts}" -- "\${cur}") )
|
|
51372
|
+
return 0
|
|
51373
|
+
fi
|
|
51374
|
+
|
|
51375
|
+
case "\${COMP_WORDS[1]}" in
|
|
51376
|
+
${caseEntries}
|
|
51377
|
+
*)
|
|
51378
|
+
COMPREPLY=( $(compgen -W "${globalOpts}" -- "\${cur}") )
|
|
51379
|
+
;;
|
|
51380
|
+
esac
|
|
51381
|
+
}
|
|
51382
|
+
complete -F _dbcli_completions dbcli
|
|
51383
|
+
`;
|
|
51384
|
+
}
|
|
51385
|
+
function generateZshCompletion(commands, globalOptions) {
|
|
51386
|
+
const cmdLines = commands.map((c) => ` '${c.name}:${c.name} command'`).join(`
|
|
51387
|
+
`);
|
|
51388
|
+
const subcmdCases = commands.map((c) => {
|
|
51389
|
+
const opts = c.options.map((o) => `'${o}[${o}]'`).join(" ");
|
|
51390
|
+
return ` ${c.name})
|
|
51391
|
+
_arguments ${opts}
|
|
51392
|
+
;;`;
|
|
51393
|
+
}).join(`
|
|
51394
|
+
`);
|
|
51395
|
+
const globalOpts = globalOptions.map((o) => `'${o}[${o}]'`).join(" ");
|
|
51396
|
+
return `#compdef dbcli
|
|
51397
|
+
# dbcli zsh completion \u2014 auto-generated, do not edit
|
|
51398
|
+
_dbcli() {
|
|
51399
|
+
local -a commands
|
|
51400
|
+
commands=(
|
|
51401
|
+
${cmdLines}
|
|
51402
|
+
)
|
|
51403
|
+
|
|
51404
|
+
_arguments -C \\
|
|
51405
|
+
${globalOpts} \\
|
|
51406
|
+
'1:command:->cmd' \\
|
|
51407
|
+
'*::arg:->args'
|
|
51408
|
+
|
|
51409
|
+
case "$state" in
|
|
51410
|
+
cmd)
|
|
51411
|
+
_describe 'command' commands
|
|
51412
|
+
;;
|
|
51413
|
+
args)
|
|
51414
|
+
case "$words[1]" in
|
|
51415
|
+
${subcmdCases}
|
|
51416
|
+
esac
|
|
51417
|
+
;;
|
|
51418
|
+
esac
|
|
51419
|
+
}
|
|
51420
|
+
_dbcli
|
|
51421
|
+
`;
|
|
51422
|
+
}
|
|
51423
|
+
function generateFishCompletion(commands, globalOptions) {
|
|
51424
|
+
const lines2 = [
|
|
51425
|
+
"# dbcli fish completion \u2014 auto-generated, do not edit",
|
|
51426
|
+
""
|
|
51427
|
+
];
|
|
51428
|
+
for (const opt of globalOptions) {
|
|
51429
|
+
const longName = opt.replace(/^--/, "");
|
|
51430
|
+
lines2.push(`complete -c dbcli -n '__fish_use_subcommand' -l ${longName} -d '${opt}'`);
|
|
51431
|
+
}
|
|
51432
|
+
for (const cmd of commands) {
|
|
51433
|
+
lines2.push(`complete -c dbcli -n '__fish_use_subcommand' -a ${cmd.name} -d '${cmd.name} command'`);
|
|
51434
|
+
}
|
|
51435
|
+
for (const cmd of commands) {
|
|
51436
|
+
for (const opt of cmd.options) {
|
|
51437
|
+
const longName = opt.replace(/^--/, "");
|
|
51438
|
+
lines2.push(`complete -c dbcli -n '__fish_seen_subcommand_from ${cmd.name}' -l ${longName} -d '${opt}'`);
|
|
51439
|
+
}
|
|
51440
|
+
}
|
|
51441
|
+
return lines2.join(`
|
|
51442
|
+
`) + `
|
|
51443
|
+
`;
|
|
51444
|
+
}
|
|
51445
|
+
function getInstallPath2(shell) {
|
|
51446
|
+
const home = homedir2();
|
|
51447
|
+
switch (shell) {
|
|
51448
|
+
case "bash":
|
|
51449
|
+
return join4(home, ".bashrc");
|
|
51450
|
+
case "zsh":
|
|
51451
|
+
return join4(home, ".zshrc");
|
|
51452
|
+
case "fish":
|
|
51453
|
+
return join4(home, ".config", "fish", "completions", "dbcli.fish");
|
|
51454
|
+
default:
|
|
51455
|
+
throw new Error(`Unsupported shell: ${shell}. Supported: bash, zsh, fish`);
|
|
51456
|
+
}
|
|
51457
|
+
}
|
|
51458
|
+
function detectShell() {
|
|
51459
|
+
const shellEnv = process.env.SHELL ?? "";
|
|
51460
|
+
if (shellEnv.includes("zsh"))
|
|
51461
|
+
return "zsh";
|
|
51462
|
+
if (shellEnv.includes("bash"))
|
|
51463
|
+
return "bash";
|
|
51464
|
+
if (shellEnv.includes("fish"))
|
|
51465
|
+
return "fish";
|
|
51466
|
+
return "bash";
|
|
51467
|
+
}
|
|
51468
|
+
var MARKER_START = "# >>> dbcli completion >>>";
|
|
51469
|
+
var MARKER_END = "# <<< dbcli completion <<<";
|
|
51470
|
+
async function installCompletion(shell, script) {
|
|
51471
|
+
const targetPath = getInstallPath2(shell);
|
|
51472
|
+
if (shell === "fish") {
|
|
51473
|
+
const dir = join4(homedir2(), ".config", "fish", "completions");
|
|
51474
|
+
await Bun.$`mkdir -p ${dir}`.quiet();
|
|
51475
|
+
await Bun.file(targetPath).write(script);
|
|
51476
|
+
console.log(colors.success(`\u2713 Fish completion installed to ${targetPath}`));
|
|
51477
|
+
return;
|
|
51478
|
+
}
|
|
51479
|
+
const file = Bun.file(targetPath);
|
|
51480
|
+
let content = "";
|
|
51481
|
+
if (await file.exists()) {
|
|
51482
|
+
content = await file.text();
|
|
51483
|
+
}
|
|
51484
|
+
const markerRegex = new RegExp(`${MARKER_START}[\\s\\S]*?${MARKER_END}\\n?`, "g");
|
|
51485
|
+
content = content.replace(markerRegex, "");
|
|
51486
|
+
const block = `
|
|
51487
|
+
${MARKER_START}
|
|
51488
|
+
eval "$(dbcli completion ${shell})"
|
|
51489
|
+
${MARKER_END}
|
|
51490
|
+
`;
|
|
51491
|
+
content = content.trimEnd() + `
|
|
51492
|
+
` + block;
|
|
51493
|
+
await Bun.file(targetPath).write(content);
|
|
51494
|
+
console.log(colors.success(`\u2713 Completion installed to ${targetPath}`));
|
|
51495
|
+
console.log(colors.info(` Run: source ${targetPath}`));
|
|
51496
|
+
}
|
|
51497
|
+
var completionCommand = new Command("completion").description("Generate shell completion scripts (bash, zsh, fish)").argument("[shell]", "Shell type: bash, zsh, fish").option("--install [shell]", "Auto-install completion to shell rc file").action(async (shellArg, options) => {
|
|
51498
|
+
const parentProgram = completionCommand.parent;
|
|
51499
|
+
if (!parentProgram) {
|
|
51500
|
+
console.error(colors.error("Error: completion command must be registered to a program"));
|
|
51501
|
+
process.exit(1);
|
|
51502
|
+
}
|
|
51503
|
+
const commands = extractCommands(parentProgram);
|
|
51504
|
+
const globalOptions = extractGlobalOptions(parentProgram);
|
|
51505
|
+
if (options.install !== undefined) {
|
|
51506
|
+
const shell2 = typeof options.install === "string" ? options.install : shellArg ?? detectShell();
|
|
51507
|
+
const generators2 = {
|
|
51508
|
+
bash: generateBashCompletion,
|
|
51509
|
+
zsh: generateZshCompletion,
|
|
51510
|
+
fish: generateFishCompletion
|
|
51511
|
+
};
|
|
51512
|
+
const generate2 = generators2[shell2];
|
|
51513
|
+
if (!generate2) {
|
|
51514
|
+
console.error(colors.error(`Unsupported shell: ${shell2}. Supported: bash, zsh, fish`));
|
|
51515
|
+
process.exit(1);
|
|
51516
|
+
}
|
|
51517
|
+
const script = generate2(commands, globalOptions);
|
|
51518
|
+
await installCompletion(shell2, script);
|
|
51519
|
+
return;
|
|
51520
|
+
}
|
|
51521
|
+
const shell = shellArg ?? detectShell();
|
|
51522
|
+
const generators = {
|
|
51523
|
+
bash: generateBashCompletion,
|
|
51524
|
+
zsh: generateZshCompletion,
|
|
51525
|
+
fish: generateFishCompletion
|
|
51526
|
+
};
|
|
51527
|
+
const generate = generators[shell];
|
|
51528
|
+
if (!generate) {
|
|
51529
|
+
console.error(colors.error(`Unsupported shell: ${shell}. Supported: bash, zsh, fish`));
|
|
51530
|
+
process.exit(1);
|
|
51531
|
+
}
|
|
51532
|
+
process.stdout.write(generate(commands, globalOptions));
|
|
51533
|
+
});
|
|
51534
|
+
|
|
51535
|
+
// src/utils/version-check.ts
|
|
51536
|
+
var NPM_REGISTRY_URL = "https://registry.npmjs.org/@carllee1983/dbcli/latest";
|
|
51537
|
+
var STALE_THRESHOLD_MS = 24 * 60 * 60 * 1000;
|
|
51538
|
+
var FETCH_TIMEOUT_MS = 3000;
|
|
51539
|
+
function compareVersions2(a, b) {
|
|
51540
|
+
const stripSuffix = (v) => v.replace(/-.*$/, "");
|
|
51541
|
+
const pa = stripSuffix(a).split(".").map(Number);
|
|
51542
|
+
const pb = stripSuffix(b).split(".").map(Number);
|
|
51543
|
+
for (let i = 0;i < 3; i++) {
|
|
51544
|
+
const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
51545
|
+
if (diff !== 0)
|
|
51546
|
+
return diff;
|
|
51547
|
+
}
|
|
51548
|
+
if (a === b)
|
|
51549
|
+
return 0;
|
|
51550
|
+
const aHasSuffix = a.includes("-");
|
|
51551
|
+
const bHasSuffix = b.includes("-");
|
|
51552
|
+
if (!aHasSuffix && bHasSuffix)
|
|
51553
|
+
return 1;
|
|
51554
|
+
if (aHasSuffix && !bHasSuffix)
|
|
51555
|
+
return -1;
|
|
51556
|
+
return a.localeCompare(b);
|
|
51557
|
+
}
|
|
51558
|
+
function isStale(checkedAt) {
|
|
51559
|
+
const checked = new Date(checkedAt).getTime();
|
|
51560
|
+
if (isNaN(checked))
|
|
51561
|
+
return true;
|
|
51562
|
+
return Date.now() - checked >= STALE_THRESHOLD_MS;
|
|
51563
|
+
}
|
|
51564
|
+
async function fetchLatestVersion() {
|
|
51565
|
+
try {
|
|
51566
|
+
const response = await fetch(NPM_REGISTRY_URL, {
|
|
51567
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
|
|
51568
|
+
});
|
|
51569
|
+
if (!response.ok)
|
|
51570
|
+
return null;
|
|
51571
|
+
const data = await response.json();
|
|
51572
|
+
return data.version ?? null;
|
|
51573
|
+
} catch {
|
|
51574
|
+
return null;
|
|
51575
|
+
}
|
|
51576
|
+
}
|
|
51577
|
+
async function checkForUpdate(currentVersion, cachePath, existingCache) {
|
|
51578
|
+
let cache = existingCache ?? null;
|
|
51579
|
+
if (cache === undefined && cachePath) {
|
|
51580
|
+
try {
|
|
51581
|
+
const cacheFile = Bun.file(`${cachePath}/version-check.json`);
|
|
51582
|
+
if (await cacheFile.exists()) {
|
|
51583
|
+
cache = await cacheFile.json();
|
|
51584
|
+
}
|
|
51585
|
+
} catch {
|
|
51586
|
+
cache = null;
|
|
51587
|
+
}
|
|
51588
|
+
}
|
|
51589
|
+
if (cache && !isStale(cache.checkedAt)) {
|
|
51590
|
+
return {
|
|
51591
|
+
hasUpdate: compareVersions2(cache.latestVersion, currentVersion) > 0,
|
|
51592
|
+
latestVersion: cache.latestVersion
|
|
51593
|
+
};
|
|
51594
|
+
}
|
|
51595
|
+
const latestVersion = await fetchLatestVersion();
|
|
51596
|
+
if (!latestVersion)
|
|
51597
|
+
return null;
|
|
51598
|
+
if (cachePath) {
|
|
51599
|
+
try {
|
|
51600
|
+
const newCache = {
|
|
51601
|
+
latestVersion,
|
|
51602
|
+
checkedAt: new Date().toISOString()
|
|
51603
|
+
};
|
|
51604
|
+
await Bun.write(`${cachePath}/version-check.json`, JSON.stringify(newCache, null, 2));
|
|
51605
|
+
} catch {}
|
|
51606
|
+
}
|
|
51607
|
+
return {
|
|
51608
|
+
hasUpdate: compareVersions2(latestVersion, currentVersion) > 0,
|
|
51609
|
+
latestVersion
|
|
51610
|
+
};
|
|
51611
|
+
}
|
|
51612
|
+
|
|
51613
|
+
// src/commands/upgrade.ts
|
|
51614
|
+
function formatAlreadyUpToDate(version) {
|
|
51615
|
+
return colors.success(`\u2713 Already up to date (v${version})`);
|
|
51616
|
+
}
|
|
51617
|
+
function formatUpgradeMessage(currentVersion, latestVersion) {
|
|
51618
|
+
return [
|
|
51619
|
+
colors.info(` Current version : v${currentVersion}`),
|
|
51620
|
+
colors.success(` Latest version : v${latestVersion}`)
|
|
51621
|
+
].join(`
|
|
51622
|
+
`);
|
|
51623
|
+
}
|
|
51624
|
+
function formatUpdateHint(latestVersion) {
|
|
51625
|
+
return colors.warn(`[INFO] dbcli v${latestVersion} available. Run "dbcli upgrade" to upgrade.`);
|
|
51626
|
+
}
|
|
51627
|
+
var upgradeCommand = new Command("upgrade").description("Check for updates and upgrade dbcli to the latest version").option("--check", "Only check for updates, do not upgrade").action(async (options) => {
|
|
51628
|
+
const configPath = upgradeCommand.parent?.opts().config ?? ".dbcli";
|
|
51629
|
+
const currentVersion = package_default.version;
|
|
51630
|
+
console.log(colors.bold("Checking for updates..."));
|
|
51631
|
+
let cachePath = null;
|
|
51632
|
+
try {
|
|
51633
|
+
const file = Bun.file(configPath);
|
|
51634
|
+
const isDir = !configPath.includes(".") || await file.exists() === false;
|
|
51635
|
+
if (isDir) {
|
|
51636
|
+
cachePath = configPath;
|
|
51637
|
+
}
|
|
51638
|
+
} catch {
|
|
51639
|
+
cachePath = null;
|
|
51640
|
+
}
|
|
51641
|
+
const result = await checkForUpdate(currentVersion, cachePath);
|
|
51642
|
+
if (!result) {
|
|
51643
|
+
console.error(colors.warn("\u26A0 Could not check for updates (network error or registry unavailable)"));
|
|
51644
|
+
process.exit(0);
|
|
51645
|
+
}
|
|
51646
|
+
if (!result.hasUpdate) {
|
|
51647
|
+
console.log(formatAlreadyUpToDate(currentVersion));
|
|
51648
|
+
process.exit(0);
|
|
51649
|
+
}
|
|
51650
|
+
console.log(colors.warn(`
|
|
51651
|
+
New version available: v${result.latestVersion}`));
|
|
51652
|
+
console.log(formatUpgradeMessage(currentVersion, result.latestVersion));
|
|
51653
|
+
console.log();
|
|
51654
|
+
if (options.check) {
|
|
51655
|
+
console.log(colors.dim(' Run "dbcli upgrade" to install the update.'));
|
|
51656
|
+
process.exit(0);
|
|
51657
|
+
}
|
|
51658
|
+
console.log(colors.bold("Upgrading..."));
|
|
51659
|
+
console.log(colors.dim(` bun add -g @carllee1983/dbcli@latest`));
|
|
51660
|
+
console.log();
|
|
51661
|
+
const proc = Bun.$`bun add -g @carllee1983/dbcli@latest`.nothrow();
|
|
51662
|
+
const result2 = await proc;
|
|
51663
|
+
if (result2.exitCode === 0) {
|
|
51664
|
+
console.log(colors.success(`
|
|
51665
|
+
\u2713 Successfully upgraded to v${result.latestVersion}`));
|
|
51666
|
+
} else {
|
|
51667
|
+
console.error(colors.error(`
|
|
51668
|
+
\u2717 Upgrade failed. Try running manually:`));
|
|
51669
|
+
console.error(colors.dim(" bun add -g @carllee1983/dbcli@latest"));
|
|
51670
|
+
process.exit(1);
|
|
51671
|
+
}
|
|
51672
|
+
});
|
|
51673
|
+
|
|
50827
51674
|
// src/cli.ts
|
|
50828
|
-
|
|
51675
|
+
import { join as join5 } from "path";
|
|
51676
|
+
var _bgVersionCheckResult;
|
|
51677
|
+
var program2 = new Command().name("dbcli").description("Database CLI for AI agents").version(package_default.version).option("--no-color", "Disable colored output").option("-v, --verbose", "Increase verbosity (-v verbose, -vv debug)", (_, prev) => prev + 1, 0).option("-q, --quiet", "Suppress non-essential output").option("--config <path>", "Path to .dbcli config file", ".dbcli");
|
|
51678
|
+
program2.hook("preAction", (thisCommand, actionCommand) => {
|
|
51679
|
+
const opts = thisCommand.opts();
|
|
51680
|
+
if (opts.color === false) {
|
|
51681
|
+
process.env.NO_COLOR = "1";
|
|
51682
|
+
}
|
|
51683
|
+
let level = 1 /* NORMAL */;
|
|
51684
|
+
if (opts.quiet) {
|
|
51685
|
+
level = 0 /* QUIET */;
|
|
51686
|
+
} else if (opts.verbose >= 2) {
|
|
51687
|
+
level = 3 /* DEBUG */;
|
|
51688
|
+
} else if (opts.verbose >= 1) {
|
|
51689
|
+
level = 2 /* VERBOSE */;
|
|
51690
|
+
}
|
|
51691
|
+
setGlobalLogger(createLogger(level));
|
|
51692
|
+
const isUpgradeCommand = actionCommand.name() === "upgrade";
|
|
51693
|
+
if (!opts.quiet && !isUpgradeCommand) {
|
|
51694
|
+
const configPath = opts.config ?? ".dbcli";
|
|
51695
|
+
(async () => {
|
|
51696
|
+
try {
|
|
51697
|
+
let cache = null;
|
|
51698
|
+
try {
|
|
51699
|
+
const cacheFile = Bun.file(join5(configPath, "version-check.json"));
|
|
51700
|
+
if (await cacheFile.exists()) {
|
|
51701
|
+
cache = await cacheFile.json();
|
|
51702
|
+
}
|
|
51703
|
+
} catch {}
|
|
51704
|
+
const result = await checkForUpdate(package_default.version, configPath, cache);
|
|
51705
|
+
_bgVersionCheckResult = result;
|
|
51706
|
+
} catch {
|
|
51707
|
+
_bgVersionCheckResult = null;
|
|
51708
|
+
}
|
|
51709
|
+
})();
|
|
51710
|
+
}
|
|
51711
|
+
});
|
|
51712
|
+
program2.hook("postAction", () => {
|
|
51713
|
+
if (_bgVersionCheckResult?.hasUpdate) {
|
|
51714
|
+
process.stderr.write(formatUpdateHint(_bgVersionCheckResult.latestVersion) + `
|
|
51715
|
+
`);
|
|
51716
|
+
}
|
|
51717
|
+
});
|
|
50829
51718
|
program2.addCommand(initCommand);
|
|
50830
51719
|
program2.addCommand(listCommand);
|
|
50831
51720
|
program2.addCommand(schemaCommand);
|
|
@@ -50885,6 +51774,9 @@ program2.addCommand(blacklistCommand);
|
|
|
50885
51774
|
program2.addCommand(checkCommand);
|
|
50886
51775
|
program2.addCommand(diffCommand);
|
|
50887
51776
|
program2.addCommand(statusCommand);
|
|
51777
|
+
program2.addCommand(doctorCommand);
|
|
51778
|
+
program2.addCommand(completionCommand);
|
|
51779
|
+
program2.addCommand(upgradeCommand);
|
|
50888
51780
|
if (!process.argv.slice(2).length) {
|
|
50889
51781
|
program2.outputHelp();
|
|
50890
51782
|
}
|