@bungres/kit 0.6.1 → 0.7.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/README.md +12 -3
- package/dist/cli.js +2508 -1151
- package/dist/commands/drop.d.ts.map +1 -1
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/push.d.ts.map +1 -1
- package/dist/commands/rollback.d.ts +3 -0
- package/dist/commands/rollback.d.ts.map +1 -0
- package/dist/commands/seed.d.ts.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/studio.d.ts.map +1 -1
- package/dist/commands/template.d.ts +2 -0
- package/dist/commands/template.d.ts.map +1 -0
- package/dist/commands/tusky.d.ts.map +1 -1
- package/dist/index.js +1754 -145
- package/package.json +4 -2
- package/dist/utils/colors.d.ts +0 -2
- package/dist/utils/colors.d.ts.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,165 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
function __accessProp(key) {
|
|
9
|
+
return this[key];
|
|
10
|
+
}
|
|
11
|
+
var __toESMCache_node;
|
|
12
|
+
var __toESMCache_esm;
|
|
13
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
14
|
+
var canCache = mod != null && typeof mod === "object";
|
|
15
|
+
if (canCache) {
|
|
16
|
+
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
17
|
+
var cached = cache.get(mod);
|
|
18
|
+
if (cached)
|
|
19
|
+
return cached;
|
|
20
|
+
}
|
|
21
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
22
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
23
|
+
for (let key of __getOwnPropNames(mod))
|
|
24
|
+
if (!__hasOwnProp.call(to, key))
|
|
25
|
+
__defProp(to, key, {
|
|
26
|
+
get: __accessProp.bind(mod, key),
|
|
27
|
+
enumerable: true
|
|
28
|
+
});
|
|
29
|
+
if (canCache)
|
|
30
|
+
cache.set(mod, to);
|
|
31
|
+
return to;
|
|
32
|
+
};
|
|
33
|
+
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
34
|
+
var __require = import.meta.require;
|
|
35
|
+
|
|
36
|
+
// ../../node_modules/.bun/sisteransi@1.0.5/node_modules/sisteransi/src/index.js
|
|
37
|
+
var require_src = __commonJS((exports, module) => {
|
|
38
|
+
var ESC2 = "\x1B";
|
|
39
|
+
var CSI2 = `${ESC2}[`;
|
|
40
|
+
var beep = "\x07";
|
|
41
|
+
var cursor = {
|
|
42
|
+
to(x, y) {
|
|
43
|
+
if (!y)
|
|
44
|
+
return `${CSI2}${x + 1}G`;
|
|
45
|
+
return `${CSI2}${y + 1};${x + 1}H`;
|
|
46
|
+
},
|
|
47
|
+
move(x, y) {
|
|
48
|
+
let ret = "";
|
|
49
|
+
if (x < 0)
|
|
50
|
+
ret += `${CSI2}${-x}D`;
|
|
51
|
+
else if (x > 0)
|
|
52
|
+
ret += `${CSI2}${x}C`;
|
|
53
|
+
if (y < 0)
|
|
54
|
+
ret += `${CSI2}${-y}A`;
|
|
55
|
+
else if (y > 0)
|
|
56
|
+
ret += `${CSI2}${y}B`;
|
|
57
|
+
return ret;
|
|
58
|
+
},
|
|
59
|
+
up: (count2 = 1) => `${CSI2}${count2}A`,
|
|
60
|
+
down: (count2 = 1) => `${CSI2}${count2}B`,
|
|
61
|
+
forward: (count2 = 1) => `${CSI2}${count2}C`,
|
|
62
|
+
backward: (count2 = 1) => `${CSI2}${count2}D`,
|
|
63
|
+
nextLine: (count2 = 1) => `${CSI2}E`.repeat(count2),
|
|
64
|
+
prevLine: (count2 = 1) => `${CSI2}F`.repeat(count2),
|
|
65
|
+
left: `${CSI2}G`,
|
|
66
|
+
hide: `${CSI2}?25l`,
|
|
67
|
+
show: `${CSI2}?25h`,
|
|
68
|
+
save: `${ESC2}7`,
|
|
69
|
+
restore: `${ESC2}8`
|
|
70
|
+
};
|
|
71
|
+
var scroll = {
|
|
72
|
+
up: (count2 = 1) => `${CSI2}S`.repeat(count2),
|
|
73
|
+
down: (count2 = 1) => `${CSI2}T`.repeat(count2)
|
|
74
|
+
};
|
|
75
|
+
var erase = {
|
|
76
|
+
screen: `${CSI2}2J`,
|
|
77
|
+
up: (count2 = 1) => `${CSI2}1J`.repeat(count2),
|
|
78
|
+
down: (count2 = 1) => `${CSI2}J`.repeat(count2),
|
|
79
|
+
line: `${CSI2}2K`,
|
|
80
|
+
lineEnd: `${CSI2}K`,
|
|
81
|
+
lineStart: `${CSI2}1K`,
|
|
82
|
+
lines(count2) {
|
|
83
|
+
let clear = "";
|
|
84
|
+
for (let i = 0;i < count2; i++)
|
|
85
|
+
clear += this.line + (i < count2 - 1 ? cursor.up() : "");
|
|
86
|
+
if (count2)
|
|
87
|
+
clear += cursor.left;
|
|
88
|
+
return clear;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
module.exports = { cursor, scroll, erase, beep };
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// ../../node_modules/.bun/picocolors@1.1.1/node_modules/picocolors/picocolors.js
|
|
95
|
+
var require_picocolors = __commonJS((exports, module) => {
|
|
96
|
+
var p2 = process || {};
|
|
97
|
+
var argv = p2.argv || [];
|
|
98
|
+
var env = p2.env || {};
|
|
99
|
+
var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p2.platform === "win32" || (p2.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
|
|
100
|
+
var formatter = (open, close, replace = open) => (input2) => {
|
|
101
|
+
let string = "" + input2, index2 = string.indexOf(close, open.length);
|
|
102
|
+
return ~index2 ? open + replaceClose(string, close, replace, index2) + close : open + string + close;
|
|
103
|
+
};
|
|
104
|
+
var replaceClose = (string, close, replace, index2) => {
|
|
105
|
+
let result2 = "", cursor3 = 0;
|
|
106
|
+
do {
|
|
107
|
+
result2 += string.substring(cursor3, index2) + replace;
|
|
108
|
+
cursor3 = index2 + close.length;
|
|
109
|
+
index2 = string.indexOf(close, cursor3);
|
|
110
|
+
} while (~index2);
|
|
111
|
+
return result2 + string.substring(cursor3);
|
|
112
|
+
};
|
|
113
|
+
var createColors = (enabled = isColorSupported) => {
|
|
114
|
+
let f2 = enabled ? formatter : () => String;
|
|
115
|
+
return {
|
|
116
|
+
isColorSupported: enabled,
|
|
117
|
+
reset: f2("\x1B[0m", "\x1B[0m"),
|
|
118
|
+
bold: f2("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
|
|
119
|
+
dim: f2("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
|
|
120
|
+
italic: f2("\x1B[3m", "\x1B[23m"),
|
|
121
|
+
underline: f2("\x1B[4m", "\x1B[24m"),
|
|
122
|
+
inverse: f2("\x1B[7m", "\x1B[27m"),
|
|
123
|
+
hidden: f2("\x1B[8m", "\x1B[28m"),
|
|
124
|
+
strikethrough: f2("\x1B[9m", "\x1B[29m"),
|
|
125
|
+
black: f2("\x1B[30m", "\x1B[39m"),
|
|
126
|
+
red: f2("\x1B[31m", "\x1B[39m"),
|
|
127
|
+
green: f2("\x1B[32m", "\x1B[39m"),
|
|
128
|
+
yellow: f2("\x1B[33m", "\x1B[39m"),
|
|
129
|
+
blue: f2("\x1B[34m", "\x1B[39m"),
|
|
130
|
+
magenta: f2("\x1B[35m", "\x1B[39m"),
|
|
131
|
+
cyan: f2("\x1B[36m", "\x1B[39m"),
|
|
132
|
+
white: f2("\x1B[37m", "\x1B[39m"),
|
|
133
|
+
gray: f2("\x1B[90m", "\x1B[39m"),
|
|
134
|
+
bgBlack: f2("\x1B[40m", "\x1B[49m"),
|
|
135
|
+
bgRed: f2("\x1B[41m", "\x1B[49m"),
|
|
136
|
+
bgGreen: f2("\x1B[42m", "\x1B[49m"),
|
|
137
|
+
bgYellow: f2("\x1B[43m", "\x1B[49m"),
|
|
138
|
+
bgBlue: f2("\x1B[44m", "\x1B[49m"),
|
|
139
|
+
bgMagenta: f2("\x1B[45m", "\x1B[49m"),
|
|
140
|
+
bgCyan: f2("\x1B[46m", "\x1B[49m"),
|
|
141
|
+
bgWhite: f2("\x1B[47m", "\x1B[49m"),
|
|
142
|
+
blackBright: f2("\x1B[90m", "\x1B[39m"),
|
|
143
|
+
redBright: f2("\x1B[91m", "\x1B[39m"),
|
|
144
|
+
greenBright: f2("\x1B[92m", "\x1B[39m"),
|
|
145
|
+
yellowBright: f2("\x1B[93m", "\x1B[39m"),
|
|
146
|
+
blueBright: f2("\x1B[94m", "\x1B[39m"),
|
|
147
|
+
magentaBright: f2("\x1B[95m", "\x1B[39m"),
|
|
148
|
+
cyanBright: f2("\x1B[96m", "\x1B[39m"),
|
|
149
|
+
whiteBright: f2("\x1B[97m", "\x1B[39m"),
|
|
150
|
+
bgBlackBright: f2("\x1B[100m", "\x1B[49m"),
|
|
151
|
+
bgRedBright: f2("\x1B[101m", "\x1B[49m"),
|
|
152
|
+
bgGreenBright: f2("\x1B[102m", "\x1B[49m"),
|
|
153
|
+
bgYellowBright: f2("\x1B[103m", "\x1B[49m"),
|
|
154
|
+
bgBlueBright: f2("\x1B[104m", "\x1B[49m"),
|
|
155
|
+
bgMagentaBright: f2("\x1B[105m", "\x1B[49m"),
|
|
156
|
+
bgCyanBright: f2("\x1B[106m", "\x1B[49m"),
|
|
157
|
+
bgWhiteBright: f2("\x1B[107m", "\x1B[49m")
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
module.exports = createColors();
|
|
161
|
+
module.exports.createColors = createColors;
|
|
162
|
+
});
|
|
3
163
|
|
|
4
164
|
// src/schema-loader.ts
|
|
5
165
|
import { resolve, join } from "path";
|
|
@@ -1361,203 +1521,1588 @@ function isTable(value) {
|
|
|
1361
1521
|
return typeof value === "object" && value !== null && TableConfigSymbol in value;
|
|
1362
1522
|
}
|
|
1363
1523
|
|
|
1364
|
-
//
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1524
|
+
// ../../node_modules/.bun/@clack+core@1.4.3/node_modules/@clack/core/dist/index.mjs
|
|
1525
|
+
import { styleText } from "util";
|
|
1526
|
+
import { stdout, stdin } from "process";
|
|
1527
|
+
import * as l from "readline";
|
|
1528
|
+
import l__default from "readline";
|
|
1369
1529
|
|
|
1370
|
-
//
|
|
1371
|
-
|
|
1372
|
-
const
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1530
|
+
// ../../node_modules/.bun/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
|
|
1531
|
+
var getCodePointsLength = (() => {
|
|
1532
|
+
const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
|
|
1533
|
+
return (input2) => {
|
|
1534
|
+
let surrogatePairsNr = 0;
|
|
1535
|
+
SURROGATE_PAIR_RE.lastIndex = 0;
|
|
1536
|
+
while (SURROGATE_PAIR_RE.test(input2)) {
|
|
1537
|
+
surrogatePairsNr += 1;
|
|
1538
|
+
}
|
|
1539
|
+
return input2.length - surrogatePairsNr;
|
|
1540
|
+
};
|
|
1541
|
+
})();
|
|
1542
|
+
var isFullWidth = (x) => {
|
|
1543
|
+
return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
|
|
1544
|
+
};
|
|
1545
|
+
var isWideNotCJKTNotEmoji = (x) => {
|
|
1546
|
+
return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
|
|
1547
|
+
};
|
|
1548
|
+
|
|
1549
|
+
// ../../node_modules/.bun/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
|
|
1550
|
+
var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
|
|
1551
|
+
var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
|
|
1552
|
+
var CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu;
|
|
1553
|
+
var TAB_RE = /\t{1,1000}/y;
|
|
1554
|
+
var EMOJI_RE = /[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/yu;
|
|
1555
|
+
var LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
|
|
1556
|
+
var MODIFIER_RE = /\p{M}+/gu;
|
|
1557
|
+
var NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
|
|
1558
|
+
var getStringTruncatedWidth = (input2, truncationOptions = {}, widthOptions = {}) => {
|
|
1559
|
+
const LIMIT = truncationOptions.limit ?? Infinity;
|
|
1560
|
+
const ELLIPSIS = truncationOptions.ellipsis ?? "";
|
|
1561
|
+
const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
|
|
1562
|
+
const ANSI_WIDTH = 0;
|
|
1563
|
+
const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
|
|
1564
|
+
const TAB_WIDTH = widthOptions.tabWidth ?? 8;
|
|
1565
|
+
const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
|
|
1566
|
+
const FULL_WIDTH_WIDTH = 2;
|
|
1567
|
+
const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
|
|
1568
|
+
const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
|
|
1569
|
+
const PARSE_BLOCKS = [
|
|
1570
|
+
[LATIN_RE, REGULAR_WIDTH],
|
|
1571
|
+
[ANSI_RE, ANSI_WIDTH],
|
|
1572
|
+
[CONTROL_RE, CONTROL_WIDTH],
|
|
1573
|
+
[TAB_RE, TAB_WIDTH],
|
|
1574
|
+
[EMOJI_RE, EMOJI_WIDTH],
|
|
1575
|
+
[CJKT_WIDE_RE, WIDE_WIDTH]
|
|
1576
|
+
];
|
|
1577
|
+
let indexPrev = 0;
|
|
1578
|
+
let index2 = 0;
|
|
1579
|
+
let length = input2.length;
|
|
1580
|
+
let lengthExtra = 0;
|
|
1581
|
+
let truncationEnabled = false;
|
|
1582
|
+
let truncationIndex = length;
|
|
1583
|
+
let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
|
|
1584
|
+
let unmatchedStart = 0;
|
|
1585
|
+
let unmatchedEnd = 0;
|
|
1586
|
+
let width = 0;
|
|
1587
|
+
let widthExtra = 0;
|
|
1588
|
+
outer:
|
|
1589
|
+
while (true) {
|
|
1590
|
+
if (unmatchedEnd > unmatchedStart || index2 >= length && index2 > indexPrev) {
|
|
1591
|
+
const unmatched = input2.slice(unmatchedStart, unmatchedEnd) || input2.slice(indexPrev, index2);
|
|
1592
|
+
lengthExtra = 0;
|
|
1593
|
+
for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
|
|
1594
|
+
const codePoint = char.codePointAt(0) || 0;
|
|
1595
|
+
if (isFullWidth(codePoint)) {
|
|
1596
|
+
widthExtra = FULL_WIDTH_WIDTH;
|
|
1597
|
+
} else if (isWideNotCJKTNotEmoji(codePoint)) {
|
|
1598
|
+
widthExtra = WIDE_WIDTH;
|
|
1599
|
+
} else {
|
|
1600
|
+
widthExtra = REGULAR_WIDTH;
|
|
1601
|
+
}
|
|
1602
|
+
if (width + widthExtra > truncationLimit) {
|
|
1603
|
+
truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
|
|
1604
|
+
}
|
|
1605
|
+
if (width + widthExtra > LIMIT) {
|
|
1606
|
+
truncationEnabled = true;
|
|
1607
|
+
break outer;
|
|
1608
|
+
}
|
|
1609
|
+
lengthExtra += char.length;
|
|
1610
|
+
width += widthExtra;
|
|
1611
|
+
}
|
|
1612
|
+
unmatchedStart = unmatchedEnd = 0;
|
|
1613
|
+
}
|
|
1614
|
+
if (index2 >= length) {
|
|
1615
|
+
break outer;
|
|
1616
|
+
}
|
|
1617
|
+
for (let i = 0, l = PARSE_BLOCKS.length;i < l; i++) {
|
|
1618
|
+
const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
|
|
1619
|
+
BLOCK_RE.lastIndex = index2;
|
|
1620
|
+
if (BLOCK_RE.test(input2)) {
|
|
1621
|
+
lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input2.slice(index2, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index2;
|
|
1622
|
+
widthExtra = lengthExtra * BLOCK_WIDTH;
|
|
1623
|
+
if (width + widthExtra > truncationLimit) {
|
|
1624
|
+
truncationIndex = Math.min(truncationIndex, index2 + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
|
|
1625
|
+
}
|
|
1626
|
+
if (width + widthExtra > LIMIT) {
|
|
1627
|
+
truncationEnabled = true;
|
|
1628
|
+
break outer;
|
|
1629
|
+
}
|
|
1630
|
+
width += widthExtra;
|
|
1631
|
+
unmatchedStart = indexPrev;
|
|
1632
|
+
unmatchedEnd = index2;
|
|
1633
|
+
index2 = indexPrev = BLOCK_RE.lastIndex;
|
|
1634
|
+
continue outer;
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
index2 += 1;
|
|
1638
|
+
}
|
|
1639
|
+
return {
|
|
1640
|
+
width: truncationEnabled ? truncationLimit : width,
|
|
1641
|
+
index: truncationEnabled ? truncationIndex : length,
|
|
1642
|
+
truncated: truncationEnabled,
|
|
1643
|
+
ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
|
|
1644
|
+
};
|
|
1645
|
+
};
|
|
1646
|
+
var dist_default = getStringTruncatedWidth;
|
|
1647
|
+
|
|
1648
|
+
// ../../node_modules/.bun/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
|
|
1649
|
+
var NO_TRUNCATION2 = {
|
|
1650
|
+
limit: Infinity,
|
|
1651
|
+
ellipsis: "",
|
|
1652
|
+
ellipsisWidth: 0
|
|
1653
|
+
};
|
|
1654
|
+
var fastStringWidth = (input2, options = {}) => {
|
|
1655
|
+
return dist_default(input2, NO_TRUNCATION2, options).width;
|
|
1656
|
+
};
|
|
1657
|
+
var dist_default2 = fastStringWidth;
|
|
1658
|
+
|
|
1659
|
+
// ../../node_modules/.bun/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
|
|
1660
|
+
var ESC = "\x1B";
|
|
1661
|
+
var CSI = "\x9B";
|
|
1662
|
+
var END_CODE = 39;
|
|
1663
|
+
var ANSI_ESCAPE_BELL = "\x07";
|
|
1664
|
+
var ANSI_CSI = "[";
|
|
1665
|
+
var ANSI_OSC = "]";
|
|
1666
|
+
var ANSI_SGR_TERMINATOR = "m";
|
|
1667
|
+
var ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
|
|
1668
|
+
var GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
|
|
1669
|
+
var getClosingCode = (openingCode) => {
|
|
1670
|
+
if (openingCode >= 30 && openingCode <= 37)
|
|
1671
|
+
return 39;
|
|
1672
|
+
if (openingCode >= 90 && openingCode <= 97)
|
|
1673
|
+
return 39;
|
|
1674
|
+
if (openingCode >= 40 && openingCode <= 47)
|
|
1675
|
+
return 49;
|
|
1676
|
+
if (openingCode >= 100 && openingCode <= 107)
|
|
1677
|
+
return 49;
|
|
1678
|
+
if (openingCode === 1 || openingCode === 2)
|
|
1679
|
+
return 22;
|
|
1680
|
+
if (openingCode === 3)
|
|
1681
|
+
return 23;
|
|
1682
|
+
if (openingCode === 4)
|
|
1683
|
+
return 24;
|
|
1684
|
+
if (openingCode === 7)
|
|
1685
|
+
return 27;
|
|
1686
|
+
if (openingCode === 8)
|
|
1687
|
+
return 28;
|
|
1688
|
+
if (openingCode === 9)
|
|
1689
|
+
return 29;
|
|
1690
|
+
if (openingCode === 0)
|
|
1691
|
+
return 0;
|
|
1692
|
+
return;
|
|
1693
|
+
};
|
|
1694
|
+
var wrapAnsiCode = (code2) => `${ESC}${ANSI_CSI}${code2}${ANSI_SGR_TERMINATOR}`;
|
|
1695
|
+
var wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
|
|
1696
|
+
var wrapWord = (rows, word, columns2) => {
|
|
1697
|
+
const characters = word[Symbol.iterator]();
|
|
1698
|
+
let isInsideEscape = false;
|
|
1699
|
+
let isInsideLinkEscape = false;
|
|
1700
|
+
let lastRow = rows.at(-1);
|
|
1701
|
+
let visible = lastRow === undefined ? 0 : dist_default2(lastRow);
|
|
1702
|
+
let currentCharacter = characters.next();
|
|
1703
|
+
let nextCharacter = characters.next();
|
|
1704
|
+
let rawCharacterIndex = 0;
|
|
1705
|
+
while (!currentCharacter.done) {
|
|
1706
|
+
const character = currentCharacter.value;
|
|
1707
|
+
const characterLength = dist_default2(character);
|
|
1708
|
+
if (visible + characterLength <= columns2) {
|
|
1709
|
+
rows[rows.length - 1] += character;
|
|
1710
|
+
} else {
|
|
1711
|
+
rows.push(character);
|
|
1712
|
+
visible = 0;
|
|
1713
|
+
}
|
|
1714
|
+
if (character === ESC || character === CSI) {
|
|
1715
|
+
isInsideEscape = true;
|
|
1716
|
+
isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
|
|
1717
|
+
}
|
|
1718
|
+
if (isInsideEscape) {
|
|
1719
|
+
if (isInsideLinkEscape) {
|
|
1720
|
+
if (character === ANSI_ESCAPE_BELL) {
|
|
1721
|
+
isInsideEscape = false;
|
|
1722
|
+
isInsideLinkEscape = false;
|
|
1723
|
+
}
|
|
1724
|
+
} else if (character === ANSI_SGR_TERMINATOR) {
|
|
1725
|
+
isInsideEscape = false;
|
|
1726
|
+
}
|
|
1727
|
+
} else {
|
|
1728
|
+
visible += characterLength;
|
|
1729
|
+
if (visible === columns2 && !nextCharacter.done) {
|
|
1730
|
+
rows.push("");
|
|
1731
|
+
visible = 0;
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
currentCharacter = nextCharacter;
|
|
1735
|
+
nextCharacter = characters.next();
|
|
1736
|
+
rawCharacterIndex += character.length;
|
|
1376
1737
|
}
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
SELECT 1 FROM information_schema.tables
|
|
1389
|
-
WHERE table_schema = $1 AND table_name = $2
|
|
1390
|
-
) AS exists`, [config2.migrationsSchema, "__bungres_push"]);
|
|
1391
|
-
const pushTableExists = pushTableCheck[0]?.exists ?? false;
|
|
1392
|
-
const tablesToDrop = schemas2.filter((s) => existingTableNames.has(s.config.name));
|
|
1393
|
-
if (tablesToDrop.length === 0 && !migrationTableExists && !pushTableExists) {
|
|
1394
|
-
console.log("No tables to drop (they either don't exist or were already dropped).");
|
|
1395
|
-
return;
|
|
1738
|
+
lastRow = rows.at(-1);
|
|
1739
|
+
if (!visible && lastRow !== undefined && lastRow.length && rows.length > 1) {
|
|
1740
|
+
rows[rows.length - 2] += rows.pop();
|
|
1741
|
+
}
|
|
1742
|
+
};
|
|
1743
|
+
var stringVisibleTrimSpacesRight = (string) => {
|
|
1744
|
+
const words = string.split(" ");
|
|
1745
|
+
let last = words.length;
|
|
1746
|
+
while (last) {
|
|
1747
|
+
if (dist_default2(words[last - 1])) {
|
|
1748
|
+
break;
|
|
1396
1749
|
}
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1750
|
+
last--;
|
|
1751
|
+
}
|
|
1752
|
+
if (last === words.length) {
|
|
1753
|
+
return string;
|
|
1754
|
+
}
|
|
1755
|
+
return words.slice(0, last).join(" ") + words.slice(last).join("");
|
|
1756
|
+
};
|
|
1757
|
+
var exec = (string, columns2, options = {}) => {
|
|
1758
|
+
if (options.trim !== false && string.trim() === "") {
|
|
1759
|
+
return "";
|
|
1760
|
+
}
|
|
1761
|
+
let returnValue = "";
|
|
1762
|
+
let escapeCode;
|
|
1763
|
+
let escapeUrl;
|
|
1764
|
+
const words = string.split(" ");
|
|
1765
|
+
let rows = [""];
|
|
1766
|
+
let rowLength = 0;
|
|
1767
|
+
for (let index2 = 0;index2 < words.length; index2++) {
|
|
1768
|
+
const word = words[index2];
|
|
1769
|
+
if (options.trim !== false) {
|
|
1770
|
+
const row = rows.at(-1) ?? "";
|
|
1771
|
+
const trimmed = row.trimStart();
|
|
1772
|
+
if (row.length !== trimmed.length) {
|
|
1773
|
+
rows[rows.length - 1] = trimmed;
|
|
1774
|
+
rowLength = dist_default2(trimmed);
|
|
1775
|
+
}
|
|
1400
1776
|
}
|
|
1401
|
-
if (
|
|
1402
|
-
|
|
1777
|
+
if (index2 !== 0) {
|
|
1778
|
+
if (rowLength >= columns2 && (options.wordWrap === false || options.trim === false)) {
|
|
1779
|
+
rows.push("");
|
|
1780
|
+
rowLength = 0;
|
|
1781
|
+
}
|
|
1782
|
+
if (rowLength || options.trim === false) {
|
|
1783
|
+
rows[rows.length - 1] += " ";
|
|
1784
|
+
rowLength++;
|
|
1785
|
+
}
|
|
1403
1786
|
}
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
Are you sure? Type YES to continue: `, "cyan"));
|
|
1412
|
-
for await (const line2 of console) {
|
|
1413
|
-
if (line2.trim().toLowerCase() !== "yes") {
|
|
1414
|
-
console.log("Aborted.");
|
|
1415
|
-
return;
|
|
1416
|
-
}
|
|
1417
|
-
break;
|
|
1787
|
+
const wordLength = dist_default2(word);
|
|
1788
|
+
if (options.hard && wordLength > columns2) {
|
|
1789
|
+
const remainingColumns = columns2 - rowLength;
|
|
1790
|
+
const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns2);
|
|
1791
|
+
const breaksStartingNextLine = Math.floor((wordLength - 1) / columns2);
|
|
1792
|
+
if (breaksStartingNextLine < breaksStartingThisLine) {
|
|
1793
|
+
rows.push("");
|
|
1418
1794
|
}
|
|
1795
|
+
wrapWord(rows, word, columns2);
|
|
1796
|
+
rowLength = dist_default2(rows.at(-1) ?? "");
|
|
1797
|
+
continue;
|
|
1419
1798
|
}
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1799
|
+
if (rowLength + wordLength > columns2 && rowLength && wordLength) {
|
|
1800
|
+
if (options.wordWrap === false && rowLength < columns2) {
|
|
1801
|
+
wrapWord(rows, word, columns2);
|
|
1802
|
+
rowLength = dist_default2(rows.at(-1) ?? "");
|
|
1803
|
+
continue;
|
|
1804
|
+
}
|
|
1805
|
+
rows.push("");
|
|
1806
|
+
rowLength = 0;
|
|
1424
1807
|
}
|
|
1425
|
-
if (
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1808
|
+
if (rowLength + wordLength > columns2 && options.wordWrap === false) {
|
|
1809
|
+
wrapWord(rows, word, columns2);
|
|
1810
|
+
rowLength = dist_default2(rows.at(-1) ?? "");
|
|
1811
|
+
continue;
|
|
1429
1812
|
}
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1813
|
+
rows[rows.length - 1] += word;
|
|
1814
|
+
rowLength += wordLength;
|
|
1815
|
+
}
|
|
1816
|
+
if (options.trim !== false) {
|
|
1817
|
+
rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
|
|
1818
|
+
}
|
|
1819
|
+
const preString = rows.join(`
|
|
1820
|
+
`);
|
|
1821
|
+
let inSurrogate = false;
|
|
1822
|
+
for (let i = 0;i < preString.length; i++) {
|
|
1823
|
+
const character = preString[i];
|
|
1824
|
+
returnValue += character;
|
|
1825
|
+
if (!inSurrogate) {
|
|
1826
|
+
inSurrogate = character >= "\uD800" && character <= "\uDBFF";
|
|
1827
|
+
if (inSurrogate) {
|
|
1828
|
+
continue;
|
|
1829
|
+
}
|
|
1830
|
+
} else {
|
|
1831
|
+
inSurrogate = false;
|
|
1832
|
+
}
|
|
1833
|
+
if (character === ESC || character === CSI) {
|
|
1834
|
+
GROUP_REGEX.lastIndex = i + 1;
|
|
1835
|
+
const groupsResult = GROUP_REGEX.exec(preString);
|
|
1836
|
+
const groups = groupsResult?.groups;
|
|
1837
|
+
if (groups?.code !== undefined) {
|
|
1838
|
+
const code2 = Number.parseFloat(groups.code);
|
|
1839
|
+
escapeCode = code2 === END_CODE ? undefined : code2;
|
|
1840
|
+
} else if (groups?.uri !== undefined) {
|
|
1841
|
+
escapeUrl = groups.uri.length === 0 ? undefined : groups.uri;
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
if (preString[i + 1] === `
|
|
1845
|
+
`) {
|
|
1846
|
+
if (escapeUrl) {
|
|
1847
|
+
returnValue += wrapAnsiHyperlink("");
|
|
1848
|
+
}
|
|
1849
|
+
const closingCode = escapeCode ? getClosingCode(escapeCode) : undefined;
|
|
1850
|
+
if (escapeCode && closingCode) {
|
|
1851
|
+
returnValue += wrapAnsiCode(closingCode);
|
|
1852
|
+
}
|
|
1853
|
+
} else if (character === `
|
|
1854
|
+
`) {
|
|
1855
|
+
if (escapeCode && getClosingCode(escapeCode)) {
|
|
1856
|
+
returnValue += wrapAnsiCode(escapeCode);
|
|
1857
|
+
}
|
|
1858
|
+
if (escapeUrl) {
|
|
1859
|
+
returnValue += wrapAnsiHyperlink(escapeUrl);
|
|
1860
|
+
}
|
|
1433
1861
|
}
|
|
1434
|
-
console.log(colorize(`
|
|
1435
|
-
Drop complete.`, "green"));
|
|
1436
|
-
} finally {
|
|
1437
|
-
await sql2.end();
|
|
1438
1862
|
}
|
|
1863
|
+
return returnValue;
|
|
1864
|
+
};
|
|
1865
|
+
var CRLF_OR_LF = /\r?\n/;
|
|
1866
|
+
function wrapAnsi(string, columns2, options) {
|
|
1867
|
+
return String(string).normalize().split(CRLF_OR_LF).map((line2) => exec(line2, columns2, options)).join(`
|
|
1868
|
+
`);
|
|
1439
1869
|
}
|
|
1440
1870
|
|
|
1441
|
-
//
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
const
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1871
|
+
// ../../node_modules/.bun/@clack+core@1.4.3/node_modules/@clack/core/dist/index.mjs
|
|
1872
|
+
var import_sisteransi = __toESM(require_src(), 1);
|
|
1873
|
+
import { ReadStream } from "tty";
|
|
1874
|
+
function findCursor(s, o, l2) {
|
|
1875
|
+
if (!l2.some((r) => !r.disabled))
|
|
1876
|
+
return s;
|
|
1877
|
+
const t = s + o, n = Math.max(l2.length - 1, 0), e = t < 0 ? n : t > n ? 0 : t;
|
|
1878
|
+
return l2[e]?.disabled ? findCursor(e, o < 0 ? -1 : 1, l2) : e;
|
|
1879
|
+
}
|
|
1880
|
+
function findTextCursor(s, o, l2, i) {
|
|
1881
|
+
const t = i.split(`
|
|
1882
|
+
`);
|
|
1883
|
+
let n = 0, e = s;
|
|
1884
|
+
for (const r of t) {
|
|
1885
|
+
if (e <= r.length)
|
|
1886
|
+
break;
|
|
1887
|
+
e -= r.length + 1, n++;
|
|
1888
|
+
}
|
|
1889
|
+
for (n = Math.max(0, Math.min(t.length - 1, n + l2)), e = Math.min(e, t[n].length) + o;e < 0 && n > 0; )
|
|
1890
|
+
n--, e += t[n].length + 1;
|
|
1891
|
+
for (;e > t[n].length && n < t.length - 1; )
|
|
1892
|
+
e -= t[n].length + 1, n++;
|
|
1893
|
+
e = Math.max(0, Math.min(t[n].length, e));
|
|
1894
|
+
let h = 0;
|
|
1895
|
+
for (let r = 0;r < n; r++)
|
|
1896
|
+
h += t[r].length + 1;
|
|
1897
|
+
return h + e;
|
|
1898
|
+
}
|
|
1899
|
+
var a$1 = ["up", "down", "left", "right", "space", "enter", "cancel"];
|
|
1900
|
+
var t = [
|
|
1901
|
+
"January",
|
|
1902
|
+
"February",
|
|
1903
|
+
"March",
|
|
1904
|
+
"April",
|
|
1905
|
+
"May",
|
|
1906
|
+
"June",
|
|
1907
|
+
"July",
|
|
1908
|
+
"August",
|
|
1909
|
+
"September",
|
|
1910
|
+
"October",
|
|
1911
|
+
"November",
|
|
1912
|
+
"December"
|
|
1913
|
+
];
|
|
1914
|
+
var settings = {
|
|
1915
|
+
actions: new Set(a$1),
|
|
1916
|
+
aliases: /* @__PURE__ */ new Map([
|
|
1917
|
+
["k", "up"],
|
|
1918
|
+
["j", "down"],
|
|
1919
|
+
["h", "left"],
|
|
1920
|
+
["l", "right"],
|
|
1921
|
+
["\x03", "cancel"],
|
|
1922
|
+
["escape", "cancel"]
|
|
1923
|
+
]),
|
|
1924
|
+
messages: {
|
|
1925
|
+
cancel: "Canceled",
|
|
1926
|
+
error: "Something went wrong"
|
|
1927
|
+
},
|
|
1928
|
+
withGuide: true,
|
|
1929
|
+
date: {
|
|
1930
|
+
monthNames: [...t],
|
|
1931
|
+
messages: {
|
|
1932
|
+
required: "Please enter a valid date",
|
|
1933
|
+
invalidMonth: "There are only 12 months in a year",
|
|
1934
|
+
invalidDay: (n, e) => `There are only ${n} days in ${e}`,
|
|
1935
|
+
afterMin: (n) => `Date must be on or after ${n.toISOString().slice(0, 10)}`,
|
|
1936
|
+
beforeMax: (n) => `Date must be on or before ${n.toISOString().slice(0, 10)}`
|
|
1463
1937
|
}
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1938
|
+
}
|
|
1939
|
+
};
|
|
1940
|
+
function isActionKey(n, e) {
|
|
1941
|
+
if (typeof n == "string")
|
|
1942
|
+
return settings.aliases.get(n) === e;
|
|
1943
|
+
for (const s of n)
|
|
1944
|
+
if (s !== undefined && isActionKey(s, e))
|
|
1945
|
+
return true;
|
|
1946
|
+
return false;
|
|
1947
|
+
}
|
|
1948
|
+
function diffLines(i, s) {
|
|
1949
|
+
if (i === s)
|
|
1950
|
+
return;
|
|
1951
|
+
const e = i.split(`
|
|
1952
|
+
`), t2 = s.split(`
|
|
1953
|
+
`), r = Math.max(e.length, t2.length), f = [];
|
|
1954
|
+
for (let n = 0;n < r; n++)
|
|
1955
|
+
e[n] !== t2[n] && f.push(n);
|
|
1956
|
+
return {
|
|
1957
|
+
lines: f,
|
|
1958
|
+
numLinesBefore: e.length,
|
|
1959
|
+
numLinesAfter: t2.length,
|
|
1960
|
+
numLines: r
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1963
|
+
var R = globalThis.process.platform.startsWith("win");
|
|
1964
|
+
var CANCEL_SYMBOL = Symbol("clack:cancel");
|
|
1965
|
+
function isCancel(e) {
|
|
1966
|
+
return e === CANCEL_SYMBOL;
|
|
1967
|
+
}
|
|
1968
|
+
function setRawMode(e, r) {
|
|
1969
|
+
const o = e;
|
|
1970
|
+
o.isTTY && o.setRawMode(r);
|
|
1971
|
+
}
|
|
1972
|
+
function block({
|
|
1973
|
+
input: e = stdin,
|
|
1974
|
+
output: r = stdout,
|
|
1975
|
+
overwrite: o = true,
|
|
1976
|
+
hideCursor: t2 = true
|
|
1977
|
+
} = {}) {
|
|
1978
|
+
const s = l.createInterface({
|
|
1979
|
+
input: e,
|
|
1980
|
+
output: r,
|
|
1981
|
+
prompt: "",
|
|
1982
|
+
tabSize: 1
|
|
1983
|
+
});
|
|
1984
|
+
l.emitKeypressEvents(e, s), e instanceof ReadStream && e.isTTY && e.setRawMode(true);
|
|
1985
|
+
const n = (f, { name: a, sequence: p }) => {
|
|
1986
|
+
const c = String(f);
|
|
1987
|
+
if (isActionKey([c, a, p], "cancel")) {
|
|
1988
|
+
t2 && r.write(import_sisteransi.cursor.show), process.exit(0);
|
|
1468
1989
|
return;
|
|
1469
1990
|
}
|
|
1470
|
-
|
|
1471
|
-
const appliedSet = new Set(applied.map((r) => r.name));
|
|
1472
|
-
const pending = files.filter((f) => !appliedSet.has(f));
|
|
1473
|
-
if (pending.length === 0) {
|
|
1474
|
-
console.log(colorize("Everything is up to date.", "green"));
|
|
1991
|
+
if (!o)
|
|
1475
1992
|
return;
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1993
|
+
const i = a === "return" ? 0 : -1, m = a === "return" ? -1 : 0;
|
|
1994
|
+
l.moveCursor(r, i, m, () => {
|
|
1995
|
+
l.clearLine(r, 1, () => {
|
|
1996
|
+
e.once("keypress", n);
|
|
1997
|
+
});
|
|
1998
|
+
});
|
|
1999
|
+
};
|
|
2000
|
+
return t2 && r.write(import_sisteransi.cursor.hide), e.once("keypress", n), () => {
|
|
2001
|
+
e.off("keypress", n), t2 && r.write(import_sisteransi.cursor.show), e instanceof ReadStream && e.isTTY && !R && e.setRawMode(false), s.terminal = false, s.close();
|
|
2002
|
+
};
|
|
2003
|
+
}
|
|
2004
|
+
var getColumns = (e) => ("columns" in e) && typeof e.columns == "number" ? e.columns : 80;
|
|
2005
|
+
var getRows = (e) => ("rows" in e) && typeof e.rows == "number" ? e.rows : 20;
|
|
2006
|
+
function wrapTextWithPrefix(e, r, o, t2 = o, s = o, n) {
|
|
2007
|
+
const f = getColumns(e ?? stdout);
|
|
2008
|
+
return wrapAnsi(r, f - o.length, {
|
|
2009
|
+
hard: true,
|
|
2010
|
+
trim: false
|
|
2011
|
+
}).split(`
|
|
2012
|
+
`).map((c, i, m) => {
|
|
2013
|
+
const d = n ? n(c, i) : c;
|
|
2014
|
+
return i === 0 ? `${t2}${d}` : i === m.length - 1 ? `${s}${d}` : `${o}${d}`;
|
|
2015
|
+
}).join(`
|
|
1485
2016
|
`);
|
|
2017
|
+
}
|
|
2018
|
+
function runValidation(e, n) {
|
|
2019
|
+
if ("~standard" in e) {
|
|
2020
|
+
const a = e["~standard"].validate(n);
|
|
2021
|
+
if (a instanceof Promise)
|
|
2022
|
+
throw new TypeError("Schema validation must be synchronous. Update `validate()` and remove any asynchronous logic.");
|
|
2023
|
+
return a.issues?.at(0)?.message;
|
|
2024
|
+
}
|
|
2025
|
+
return e(n);
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
class V {
|
|
2029
|
+
input;
|
|
2030
|
+
output;
|
|
2031
|
+
_abortSignal;
|
|
2032
|
+
rl;
|
|
2033
|
+
opts;
|
|
2034
|
+
_render;
|
|
2035
|
+
_track = false;
|
|
2036
|
+
_prevFrame = "";
|
|
2037
|
+
_subscribers = /* @__PURE__ */ new Map;
|
|
2038
|
+
_cursor = 0;
|
|
2039
|
+
state = "initial";
|
|
2040
|
+
error = "";
|
|
2041
|
+
value;
|
|
2042
|
+
userInput = "";
|
|
2043
|
+
constructor(t2, e = true) {
|
|
2044
|
+
const { input: i = stdin, output: n = stdout, render: s, signal: r, ...o } = t2;
|
|
2045
|
+
this.opts = o, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = s.bind(this), this._track = e, this._abortSignal = r, this.input = i, this.output = n;
|
|
2046
|
+
}
|
|
2047
|
+
unsubscribe() {
|
|
2048
|
+
this._subscribers.clear();
|
|
2049
|
+
}
|
|
2050
|
+
setSubscriber(t2, e) {
|
|
2051
|
+
const i = this._subscribers.get(t2) ?? [];
|
|
2052
|
+
i.push(e), this._subscribers.set(t2, i);
|
|
2053
|
+
}
|
|
2054
|
+
on(t2, e) {
|
|
2055
|
+
this.setSubscriber(t2, { cb: e });
|
|
2056
|
+
}
|
|
2057
|
+
once(t2, e) {
|
|
2058
|
+
this.setSubscriber(t2, { cb: e, once: true });
|
|
2059
|
+
}
|
|
2060
|
+
emit(t2, ...e) {
|
|
2061
|
+
const i = this._subscribers.get(t2) ?? [], n = [];
|
|
2062
|
+
for (const s of i)
|
|
2063
|
+
s.cb(...e), s.once && n.push(() => i.splice(i.indexOf(s), 1));
|
|
2064
|
+
for (const s of n)
|
|
2065
|
+
s();
|
|
2066
|
+
}
|
|
2067
|
+
prompt() {
|
|
2068
|
+
return new Promise((t2) => {
|
|
2069
|
+
if (this._abortSignal) {
|
|
2070
|
+
if (this._abortSignal.aborted)
|
|
2071
|
+
return this.state = "cancel", this.close(), t2(CANCEL_SYMBOL);
|
|
2072
|
+
this._abortSignal.addEventListener("abort", () => {
|
|
2073
|
+
this.state = "cancel", this.close();
|
|
2074
|
+
}, { once: true });
|
|
1486
2075
|
}
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
2076
|
+
this.rl = l__default.createInterface({
|
|
2077
|
+
input: this.input,
|
|
2078
|
+
tabSize: 2,
|
|
2079
|
+
prompt: "",
|
|
2080
|
+
escapeCodeTimeout: 50,
|
|
2081
|
+
terminal: true
|
|
2082
|
+
}), this.rl.prompt(), this.opts.initialUserInput !== undefined && this._setUserInput(this.opts.initialUserInput, true), this.input.on("keypress", this.onKeypress), setRawMode(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
|
|
2083
|
+
this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t2(this.value);
|
|
2084
|
+
}), this.once("cancel", () => {
|
|
2085
|
+
this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t2(CANCEL_SYMBOL);
|
|
1493
2086
|
});
|
|
1494
|
-
|
|
2087
|
+
});
|
|
2088
|
+
}
|
|
2089
|
+
_isActionKey(t2, e) {
|
|
2090
|
+
return t2 === "\t";
|
|
2091
|
+
}
|
|
2092
|
+
_shouldSubmit(t2, e) {
|
|
2093
|
+
return true;
|
|
2094
|
+
}
|
|
2095
|
+
_setValue(t2) {
|
|
2096
|
+
this.value = t2, this.emit("value", this.value);
|
|
2097
|
+
}
|
|
2098
|
+
_setUserInput(t2, e) {
|
|
2099
|
+
this.userInput = t2 ?? "", this.emit("userInput", this.userInput), e && this._track && this.rl && (this.rl.write(this.userInput), this._cursor = this.rl.cursor);
|
|
2100
|
+
}
|
|
2101
|
+
_clearUserInput() {
|
|
2102
|
+
this.rl?.write(null, { ctrl: true, name: "u" }), this._setUserInput("");
|
|
2103
|
+
}
|
|
2104
|
+
onKeypress(t2, e) {
|
|
2105
|
+
if (this._track && e.name !== "return" && (e.name && this._isActionKey(t2, e) && this.rl?.write(null, { ctrl: true, name: "h" }), this._cursor = this.rl?.cursor ?? 0, this._setUserInput(this.rl?.line)), this.state === "error" && (this.state = "active"), e?.name && (!this._track && settings.aliases.has(e.name) && this.emit("cursor", settings.aliases.get(e.name)), settings.actions.has(e.name) && this.emit("cursor", e.name)), t2 && (t2.toLowerCase() === "y" || t2.toLowerCase() === "n") && this.emit("confirm", t2.toLowerCase() === "y"), this.emit("key", t2, e), e?.name === "return" && this._shouldSubmit(t2, e)) {
|
|
2106
|
+
if (this.opts.validate) {
|
|
2107
|
+
const i = runValidation(this.opts.validate, this.value);
|
|
2108
|
+
i && (this.error = i instanceof Error ? i.message : i, this.state = "error", this.rl?.write(this.userInput));
|
|
2109
|
+
}
|
|
2110
|
+
this.state !== "error" && (this.state = "submit");
|
|
2111
|
+
}
|
|
2112
|
+
isActionKey([t2, e?.name, e?.sequence], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
|
|
2113
|
+
}
|
|
2114
|
+
close() {
|
|
2115
|
+
this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
|
|
2116
|
+
`), setRawMode(this.input, false), this.rl?.close(), this.rl = undefined, this.emit(`${this.state}`, this.value), this.unsubscribe();
|
|
2117
|
+
}
|
|
2118
|
+
restoreCursor() {
|
|
2119
|
+
const t2 = wrapAnsi(this._prevFrame, process.stdout.columns, { hard: true, trim: false }).split(`
|
|
2120
|
+
`).length - 1;
|
|
2121
|
+
this.output.write(import_sisteransi.cursor.move(-999, t2 * -1));
|
|
2122
|
+
}
|
|
2123
|
+
render() {
|
|
2124
|
+
const t2 = wrapAnsi(this._render(this) ?? "", process.stdout.columns, {
|
|
2125
|
+
hard: true,
|
|
2126
|
+
trim: false
|
|
2127
|
+
});
|
|
2128
|
+
if (t2 !== this._prevFrame) {
|
|
2129
|
+
if (this.state === "initial")
|
|
2130
|
+
this.output.write(import_sisteransi.cursor.hide);
|
|
2131
|
+
else {
|
|
2132
|
+
const e = diffLines(this._prevFrame, t2), i = getRows(this.output);
|
|
2133
|
+
if (this.restoreCursor(), e) {
|
|
2134
|
+
const n = Math.max(0, e.numLinesAfter - i), s = Math.max(0, e.numLinesBefore - i);
|
|
2135
|
+
let r = e.lines.find((o) => o >= n);
|
|
2136
|
+
if (r === undefined) {
|
|
2137
|
+
this._prevFrame = t2;
|
|
2138
|
+
return;
|
|
2139
|
+
}
|
|
2140
|
+
if (e.lines.length === 1) {
|
|
2141
|
+
this.output.write(import_sisteransi.cursor.move(0, r - s)), this.output.write(import_sisteransi.erase.lines(1));
|
|
2142
|
+
const o = t2.split(`
|
|
2143
|
+
`);
|
|
2144
|
+
this.output.write(o[r]), this._prevFrame = t2, this.output.write(import_sisteransi.cursor.move(0, o.length - r - 1));
|
|
2145
|
+
return;
|
|
2146
|
+
} else if (e.lines.length > 1) {
|
|
2147
|
+
if (n < s)
|
|
2148
|
+
r = n;
|
|
2149
|
+
else {
|
|
2150
|
+
const h = r - s;
|
|
2151
|
+
h > 0 && this.output.write(import_sisteransi.cursor.move(0, h));
|
|
2152
|
+
}
|
|
2153
|
+
this.output.write(import_sisteransi.erase.down());
|
|
2154
|
+
const f = t2.split(`
|
|
2155
|
+
`).slice(r);
|
|
2156
|
+
this.output.write(f.join(`
|
|
2157
|
+
`)), this._prevFrame = t2;
|
|
2158
|
+
return;
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
this.output.write(import_sisteransi.erase.down());
|
|
2162
|
+
}
|
|
2163
|
+
this.output.write(t2), this.state === "initial" && (this.state = "active"), this._prevFrame = t2;
|
|
1495
2164
|
}
|
|
1496
|
-
console.log(colorize(`
|
|
1497
|
-
Done.`, "green"));
|
|
1498
|
-
} finally {
|
|
1499
|
-
await sql2.end();
|
|
1500
2165
|
}
|
|
1501
2166
|
}
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
console.log(`
|
|
1508
|
-
Re-running migrations...`);
|
|
1509
|
-
await runMigrate(config2);
|
|
1510
|
-
console.log(`
|
|
1511
|
-
Fresh complete.`);
|
|
2167
|
+
function p$1(l2, e) {
|
|
2168
|
+
if (l2 === undefined || e.length === 0)
|
|
2169
|
+
return 0;
|
|
2170
|
+
const i = e.findIndex((s) => s.value === l2);
|
|
2171
|
+
return i !== -1 ? i : 0;
|
|
1512
2172
|
}
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
2173
|
+
function g(l2, e) {
|
|
2174
|
+
return (e.label ?? String(e.value)).toLowerCase().includes(l2.toLowerCase());
|
|
2175
|
+
}
|
|
2176
|
+
function m(l2, e) {
|
|
2177
|
+
if (e)
|
|
2178
|
+
return l2 ? e : e[0];
|
|
2179
|
+
}
|
|
2180
|
+
var T$1 = class T extends V {
|
|
2181
|
+
filteredOptions;
|
|
2182
|
+
multiple;
|
|
2183
|
+
isNavigating = false;
|
|
2184
|
+
selectedValues = [];
|
|
2185
|
+
focusedValue;
|
|
2186
|
+
#e = 0;
|
|
2187
|
+
#s = "";
|
|
2188
|
+
#t;
|
|
2189
|
+
#i;
|
|
2190
|
+
#n;
|
|
2191
|
+
get cursor() {
|
|
2192
|
+
return this.#e;
|
|
2193
|
+
}
|
|
2194
|
+
get userInputWithCursor() {
|
|
2195
|
+
if (!this.userInput)
|
|
2196
|
+
return styleText(["inverse", "hidden"], "_");
|
|
2197
|
+
if (this._cursor >= this.userInput.length)
|
|
2198
|
+
return `${this.userInput}\u2588`;
|
|
2199
|
+
const e = this.userInput.slice(0, this.cursor), t2 = this.userInput.slice(this.cursor, this.cursor + 1), i = this.userInput.slice(this.cursor + 1);
|
|
2200
|
+
return `${e}${styleText("inverse", t2)}${i}`;
|
|
2201
|
+
}
|
|
2202
|
+
get options() {
|
|
2203
|
+
return typeof this.#i == "function" ? this.#i() : this.#i;
|
|
2204
|
+
}
|
|
2205
|
+
constructor(e) {
|
|
2206
|
+
super(e), this.#i = e.options, this.#n = e.placeholder;
|
|
2207
|
+
const t2 = this.options;
|
|
2208
|
+
this.filteredOptions = [...t2], this.multiple = e.multiple === true, this.#t = typeof e.options == "function" ? e.filter : e.filter ?? g;
|
|
2209
|
+
let i;
|
|
2210
|
+
if (e.initialValue && Array.isArray(e.initialValue) ? this.multiple ? i = e.initialValue : i = e.initialValue.slice(0, 1) : !this.multiple && this.options.length > 0 && (i = [this.options[0]?.value]), i)
|
|
2211
|
+
for (const s of i) {
|
|
2212
|
+
const n = t2.findIndex((o) => o.value === s);
|
|
2213
|
+
n !== -1 && (this.toggleSelected(s), this.#e = n);
|
|
2214
|
+
}
|
|
2215
|
+
this.focusedValue = this.options[this.#e]?.value, this.on("key", (s, n) => this.#l(s, n)), this.on("userInput", (s) => this.#u(s));
|
|
1529
2216
|
}
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
summary.push(`CREATE TABLE ${config2.name}`);
|
|
2217
|
+
_isActionKey(e, t2) {
|
|
2218
|
+
return e === "\t" || this.multiple && this.isNavigating && t2.name === "space" && e !== undefined && e !== "";
|
|
1533
2219
|
}
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
summary.push(`DROP TABLE ${tableName}`);
|
|
1540
|
-
warnings.push(`Data loss warning: Table '${tableName}' will be permanently deleted.`);
|
|
2220
|
+
#l(e, t2) {
|
|
2221
|
+
const i = t2.name === "up", s = t2.name === "down", n = t2.name === "return", o = this.userInput === "" || this.userInput === "\t", u = this.#n, a = this.options, f = u !== undefined && u !== "" && a.some((r) => !r.disabled && (this.#t ? this.#t(u, r) : true));
|
|
2222
|
+
if (t2.name === "tab" && o && f) {
|
|
2223
|
+
this.userInput === "\t" && this._clearUserInput(), this._setUserInput(u, true), this.isNavigating = false;
|
|
2224
|
+
return;
|
|
1541
2225
|
}
|
|
2226
|
+
i || s ? (this.#e = findCursor(this.#e, i ? -1 : 1, this.filteredOptions), this.focusedValue = this.filteredOptions[this.#e]?.value, this.multiple || (this.selectedValues = [this.focusedValue]), this.isNavigating = true) : n ? this.value = m(this.multiple, this.selectedValues) : this.multiple ? this.focusedValue !== undefined && (t2.name === "tab" || this.isNavigating && t2.name === "space") ? this.toggleSelected(this.focusedValue) : this.isNavigating = false : (this.focusedValue && (this.selectedValues = [this.focusedValue]), this.isNavigating = false);
|
|
1542
2227
|
}
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
2228
|
+
deselectAll() {
|
|
2229
|
+
this.selectedValues = [];
|
|
2230
|
+
}
|
|
2231
|
+
toggleSelected(e) {
|
|
2232
|
+
this.filteredOptions.length !== 0 && (this.multiple ? this.selectedValues.includes(e) ? this.selectedValues = this.selectedValues.filter((t2) => t2 !== e) : this.selectedValues = [...this.selectedValues, e] : this.selectedValues = [e]);
|
|
2233
|
+
}
|
|
2234
|
+
#u(e) {
|
|
2235
|
+
if (e !== this.#s) {
|
|
2236
|
+
this.#s = e;
|
|
2237
|
+
const t2 = this.options;
|
|
2238
|
+
e && this.#t ? this.filteredOptions = t2.filter((n) => this.#t?.(e, n)) : this.filteredOptions = [...t2];
|
|
2239
|
+
const i = p$1(this.focusedValue, this.filteredOptions);
|
|
2240
|
+
this.#e = findCursor(i, 0, this.filteredOptions);
|
|
2241
|
+
const s = this.filteredOptions[this.#e];
|
|
2242
|
+
s && !s.disabled ? this.focusedValue = s.value : this.focusedValue = undefined, this.multiple || (this.focusedValue !== undefined ? this.toggleSelected(this.focusedValue) : this.deselectAll());
|
|
1558
2243
|
}
|
|
1559
|
-
|
|
1560
|
-
|
|
2244
|
+
}
|
|
2245
|
+
};
|
|
2246
|
+
|
|
2247
|
+
class r extends V {
|
|
2248
|
+
get cursor() {
|
|
2249
|
+
return this.value ? 0 : 1;
|
|
2250
|
+
}
|
|
2251
|
+
get _value() {
|
|
2252
|
+
return this.cursor === 0;
|
|
2253
|
+
}
|
|
2254
|
+
constructor(t2) {
|
|
2255
|
+
super(t2, false), this.value = !!t2.initialValue, this.on("userInput", () => {
|
|
2256
|
+
this.value = this._value;
|
|
2257
|
+
}), this.on("confirm", (i) => {
|
|
2258
|
+
this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = i, this.state = "submit", this.close();
|
|
2259
|
+
}), this.on("cursor", () => {
|
|
2260
|
+
this.value = !this.value;
|
|
2261
|
+
});
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
var _ = {
|
|
2265
|
+
Y: { type: "year", len: 4 },
|
|
2266
|
+
M: { type: "month", len: 2 },
|
|
2267
|
+
D: { type: "day", len: 2 }
|
|
2268
|
+
};
|
|
2269
|
+
function M(r2) {
|
|
2270
|
+
return [...r2].map((t2) => _[t2]);
|
|
2271
|
+
}
|
|
2272
|
+
function P(r2) {
|
|
2273
|
+
const i = new Intl.DateTimeFormat(r2, {
|
|
2274
|
+
year: "numeric",
|
|
2275
|
+
month: "2-digit",
|
|
2276
|
+
day: "2-digit"
|
|
2277
|
+
}).formatToParts(new Date(2000, 0, 15)), s = [];
|
|
2278
|
+
let n = "/";
|
|
2279
|
+
for (const e of i)
|
|
2280
|
+
e.type === "literal" ? n = e.value.trim() || e.value : (e.type === "year" || e.type === "month" || e.type === "day") && s.push({ type: e.type, len: e.type === "year" ? 4 : 2 });
|
|
2281
|
+
return { segments: s, separator: n };
|
|
2282
|
+
}
|
|
2283
|
+
function p(r2) {
|
|
2284
|
+
return Number.parseInt((r2 || "0").replace(/_/g, "0"), 10) || 0;
|
|
2285
|
+
}
|
|
2286
|
+
function f(r2) {
|
|
2287
|
+
return {
|
|
2288
|
+
year: p(r2.year),
|
|
2289
|
+
month: p(r2.month),
|
|
2290
|
+
day: p(r2.day)
|
|
2291
|
+
};
|
|
2292
|
+
}
|
|
2293
|
+
function c(r2, t2) {
|
|
2294
|
+
return new Date(r2 || 2001, t2 || 1, 0).getDate();
|
|
2295
|
+
}
|
|
2296
|
+
function b(r2) {
|
|
2297
|
+
const { year: t2, month: i, day: s } = f(r2);
|
|
2298
|
+
if (!t2 || t2 < 0 || t2 > 9999 || !i || i < 1 || i > 12 || !s || s < 1)
|
|
2299
|
+
return;
|
|
2300
|
+
const n = new Date(Date.UTC(t2, i - 1, s));
|
|
2301
|
+
if (!(n.getUTCFullYear() !== t2 || n.getUTCMonth() !== i - 1 || n.getUTCDate() !== s))
|
|
2302
|
+
return { year: t2, month: i, day: s };
|
|
2303
|
+
}
|
|
2304
|
+
function C(r2) {
|
|
2305
|
+
const t2 = b(r2);
|
|
2306
|
+
return t2 ? new Date(Date.UTC(t2.year, t2.month - 1, t2.day)) : undefined;
|
|
2307
|
+
}
|
|
2308
|
+
function T2(r2, t2, i, s) {
|
|
2309
|
+
const n = i ? {
|
|
2310
|
+
year: i.getUTCFullYear(),
|
|
2311
|
+
month: i.getUTCMonth() + 1,
|
|
2312
|
+
day: i.getUTCDate()
|
|
2313
|
+
} : null, e = s ? {
|
|
2314
|
+
year: s.getUTCFullYear(),
|
|
2315
|
+
month: s.getUTCMonth() + 1,
|
|
2316
|
+
day: s.getUTCDate()
|
|
2317
|
+
} : null;
|
|
2318
|
+
return r2 === "year" ? { min: n?.year ?? 1, max: e?.year ?? 9999 } : r2 === "month" ? {
|
|
2319
|
+
min: n && t2.year === n.year ? n.month : 1,
|
|
2320
|
+
max: e && t2.year === e.year ? e.month : 12
|
|
2321
|
+
} : {
|
|
2322
|
+
min: n && t2.year === n.year && t2.month === n.month ? n.day : 1,
|
|
2323
|
+
max: e && t2.year === e.year && t2.month === e.month ? e.day : c(t2.year, t2.month)
|
|
2324
|
+
};
|
|
2325
|
+
}
|
|
2326
|
+
|
|
2327
|
+
class U extends V {
|
|
2328
|
+
#i;
|
|
2329
|
+
#o;
|
|
2330
|
+
#t;
|
|
2331
|
+
#h;
|
|
2332
|
+
#u;
|
|
2333
|
+
#e = { segmentIndex: 0, positionInSegment: 0 };
|
|
2334
|
+
#n = true;
|
|
2335
|
+
#s = null;
|
|
2336
|
+
inlineError = "";
|
|
2337
|
+
get segmentCursor() {
|
|
2338
|
+
return { ...this.#e };
|
|
2339
|
+
}
|
|
2340
|
+
get segmentValues() {
|
|
2341
|
+
return { ...this.#t };
|
|
2342
|
+
}
|
|
2343
|
+
get segments() {
|
|
2344
|
+
return this.#i;
|
|
2345
|
+
}
|
|
2346
|
+
get separator() {
|
|
2347
|
+
return this.#o;
|
|
2348
|
+
}
|
|
2349
|
+
get formattedValue() {
|
|
2350
|
+
return this.#l(this.#t);
|
|
2351
|
+
}
|
|
2352
|
+
#l(t2) {
|
|
2353
|
+
return this.#i.map((i) => t2[i.type]).join(this.#o);
|
|
2354
|
+
}
|
|
2355
|
+
#r() {
|
|
2356
|
+
this._setUserInput(this.#l(this.#t)), this._setValue(C(this.#t) ?? undefined);
|
|
2357
|
+
}
|
|
2358
|
+
constructor(t2) {
|
|
2359
|
+
const i = t2.format ? { segments: M(t2.format), separator: t2.separator ?? "/" } : P(t2.locale), s = t2.separator ?? i.separator, n = t2.format ? M(t2.format) : i.segments, e = t2.initialValue ?? t2.defaultValue, m2 = e ? {
|
|
2360
|
+
year: String(e.getUTCFullYear()).padStart(4, "0"),
|
|
2361
|
+
month: String(e.getUTCMonth() + 1).padStart(2, "0"),
|
|
2362
|
+
day: String(e.getUTCDate()).padStart(2, "0")
|
|
2363
|
+
} : { year: "____", month: "__", day: "__" }, o = n.map((a) => m2[a.type]).join(s);
|
|
2364
|
+
super({ ...t2, initialUserInput: o }, false), this.#i = n, this.#o = s, this.#t = m2, this.#h = t2.minDate, this.#u = t2.maxDate, this.#r(), this.on("cursor", (a) => this.#f(a)), this.on("key", (a, u) => this.#y(a, u)), this.on("finalize", () => this.#p(t2));
|
|
2365
|
+
}
|
|
2366
|
+
#a() {
|
|
2367
|
+
const t2 = Math.max(0, Math.min(this.#e.segmentIndex, this.#i.length - 1)), i = this.#i[t2];
|
|
2368
|
+
if (i)
|
|
2369
|
+
return this.#e.positionInSegment = Math.max(0, Math.min(this.#e.positionInSegment, i.len - 1)), { segment: i, index: t2 };
|
|
2370
|
+
}
|
|
2371
|
+
#m(t2) {
|
|
2372
|
+
this.inlineError = "", this.#s = null;
|
|
2373
|
+
const i = this.#a();
|
|
2374
|
+
i && (this.#e.segmentIndex = Math.max(0, Math.min(this.#i.length - 1, i.index + t2)), this.#e.positionInSegment = 0, this.#n = true);
|
|
2375
|
+
}
|
|
2376
|
+
#d(t2) {
|
|
2377
|
+
const i = this.#a();
|
|
2378
|
+
if (!i)
|
|
2379
|
+
return;
|
|
2380
|
+
const { segment: s } = i, n = this.#t[s.type], e = !n || n.replace(/_/g, "") === "", m2 = Number.parseInt((n || "0").replace(/_/g, "0"), 10) || 0, o = T2(s.type, f(this.#t), this.#h, this.#u);
|
|
2381
|
+
let a;
|
|
2382
|
+
e ? a = t2 === 1 ? o.min : o.max : a = Math.max(Math.min(o.max, m2 + t2), o.min), this.#t = {
|
|
2383
|
+
...this.#t,
|
|
2384
|
+
[s.type]: a.toString().padStart(s.len, "0")
|
|
2385
|
+
}, this.#n = true, this.#s = null, this.#r();
|
|
2386
|
+
}
|
|
2387
|
+
#f(t2) {
|
|
2388
|
+
if (t2)
|
|
2389
|
+
switch (t2) {
|
|
2390
|
+
case "right":
|
|
2391
|
+
return this.#m(1);
|
|
2392
|
+
case "left":
|
|
2393
|
+
return this.#m(-1);
|
|
2394
|
+
case "up":
|
|
2395
|
+
return this.#d(1);
|
|
2396
|
+
case "down":
|
|
2397
|
+
return this.#d(-1);
|
|
2398
|
+
}
|
|
2399
|
+
}
|
|
2400
|
+
#y(t2, i) {
|
|
2401
|
+
if (i?.name === "backspace" || i?.sequence === "\x7F" || i?.sequence === "\b" || t2 === "\x7F" || t2 === "\b") {
|
|
2402
|
+
this.inlineError = "";
|
|
2403
|
+
const n = this.#a();
|
|
2404
|
+
if (!n)
|
|
2405
|
+
return;
|
|
2406
|
+
if (!this.#t[n.segment.type].replace(/_/g, "")) {
|
|
2407
|
+
this.#m(-1);
|
|
2408
|
+
return;
|
|
2409
|
+
}
|
|
2410
|
+
this.#t[n.segment.type] = "_".repeat(n.segment.len), this.#n = true, this.#e.positionInSegment = 0, this.#r();
|
|
2411
|
+
return;
|
|
2412
|
+
}
|
|
2413
|
+
if (i?.name === "tab") {
|
|
2414
|
+
this.inlineError = "";
|
|
2415
|
+
const n = this.#a();
|
|
2416
|
+
if (!n)
|
|
2417
|
+
return;
|
|
2418
|
+
const e = i.shift ? -1 : 1, m2 = n.index + e;
|
|
2419
|
+
m2 >= 0 && m2 < this.#i.length && (this.#e.segmentIndex = m2, this.#e.positionInSegment = 0, this.#n = true);
|
|
2420
|
+
return;
|
|
2421
|
+
}
|
|
2422
|
+
if (t2 && /^[0-9]$/.test(t2)) {
|
|
2423
|
+
const n = this.#a();
|
|
2424
|
+
if (!n)
|
|
2425
|
+
return;
|
|
2426
|
+
const { segment: e } = n, m2 = !this.#t[e.type].replace(/_/g, "");
|
|
2427
|
+
if (this.#n && this.#s !== null && !m2) {
|
|
2428
|
+
const h = this.#s + t2, d = { ...this.#t, [e.type]: h }, g2 = this.#g(d, e);
|
|
2429
|
+
if (g2) {
|
|
2430
|
+
this.inlineError = g2, this.#s = null, this.#n = false;
|
|
2431
|
+
return;
|
|
2432
|
+
}
|
|
2433
|
+
this.inlineError = "", this.#t[e.type] = h, this.#s = null, this.#n = false, this.#r(), n.index < this.#i.length - 1 && (this.#e.segmentIndex = n.index + 1, this.#e.positionInSegment = 0, this.#n = true);
|
|
2434
|
+
return;
|
|
2435
|
+
}
|
|
2436
|
+
this.#n && !m2 && (this.#t[e.type] = "_".repeat(e.len), this.#e.positionInSegment = 0), this.#n = false, this.#s = null;
|
|
2437
|
+
const o = this.#t[e.type], a = o.indexOf("_"), u = a >= 0 ? a : Math.min(this.#e.positionInSegment, e.len - 1);
|
|
2438
|
+
if (u < 0 || u >= e.len)
|
|
2439
|
+
return;
|
|
2440
|
+
let l2 = o.slice(0, u) + t2 + o.slice(u + 1), D = false;
|
|
2441
|
+
if (u === 0 && o === "__" && (e.type === "month" || e.type === "day")) {
|
|
2442
|
+
const h = Number.parseInt(t2, 10);
|
|
2443
|
+
l2 = `0${t2}`, D = h <= (e.type === "month" ? 1 : 2);
|
|
2444
|
+
}
|
|
2445
|
+
if (e.type === "year" && (l2 = (o.replace(/_/g, "") + t2).padStart(e.len, "_")), !l2.includes("_")) {
|
|
2446
|
+
const h = { ...this.#t, [e.type]: l2 }, d = this.#g(h, e);
|
|
2447
|
+
if (d) {
|
|
2448
|
+
this.inlineError = d;
|
|
2449
|
+
return;
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
this.inlineError = "", this.#t[e.type] = l2;
|
|
2453
|
+
const y = l2.includes("_") ? undefined : b(this.#t);
|
|
2454
|
+
if (y) {
|
|
2455
|
+
const { year: h, month: d } = y, g2 = c(h, d);
|
|
2456
|
+
this.#t = {
|
|
2457
|
+
year: String(Math.max(0, Math.min(9999, h))).padStart(4, "0"),
|
|
2458
|
+
month: String(Math.max(1, Math.min(12, d))).padStart(2, "0"),
|
|
2459
|
+
day: String(Math.max(1, Math.min(g2, y.day))).padStart(2, "0")
|
|
2460
|
+
};
|
|
2461
|
+
}
|
|
2462
|
+
this.#r();
|
|
2463
|
+
const S = l2.indexOf("_");
|
|
2464
|
+
D ? (this.#n = true, this.#s = t2) : S >= 0 ? this.#e.positionInSegment = S : a >= 0 && n.index < this.#i.length - 1 ? (this.#e.segmentIndex = n.index + 1, this.#e.positionInSegment = 0, this.#n = true) : this.#e.positionInSegment = Math.min(u + 1, e.len - 1);
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
#g(t2, i) {
|
|
2468
|
+
const { month: s, day: n } = f(t2);
|
|
2469
|
+
if (i.type === "month" && (s < 0 || s > 12))
|
|
2470
|
+
return settings.date.messages.invalidMonth;
|
|
2471
|
+
if (i.type === "day" && (n < 0 || n > 31))
|
|
2472
|
+
return settings.date.messages.invalidDay(31, "any month");
|
|
2473
|
+
}
|
|
2474
|
+
#p(t2) {
|
|
2475
|
+
const { year: i, month: s, day: n } = f(this.#t);
|
|
2476
|
+
if (i && s && n) {
|
|
2477
|
+
const e = c(i, s);
|
|
2478
|
+
this.#t = {
|
|
2479
|
+
...this.#t,
|
|
2480
|
+
day: String(Math.min(n, e)).padStart(2, "0")
|
|
2481
|
+
};
|
|
2482
|
+
}
|
|
2483
|
+
this.value = C(this.#t) ?? t2.defaultValue ?? undefined;
|
|
2484
|
+
}
|
|
2485
|
+
}
|
|
2486
|
+
var u$2 = class u extends V {
|
|
2487
|
+
options;
|
|
2488
|
+
cursor = 0;
|
|
2489
|
+
#t;
|
|
2490
|
+
getGroupItems(t2) {
|
|
2491
|
+
return this.options.filter((r2) => r2.group === t2);
|
|
2492
|
+
}
|
|
2493
|
+
isGroupSelected(t2) {
|
|
2494
|
+
const r2 = this.getGroupItems(t2), e = this.value;
|
|
2495
|
+
return e === undefined ? false : r2.every((s) => e.includes(s.value));
|
|
2496
|
+
}
|
|
2497
|
+
toggleValue() {
|
|
2498
|
+
const t2 = this.options[this.cursor];
|
|
2499
|
+
if (t2 !== undefined)
|
|
2500
|
+
if (this.value === undefined && (this.value = []), t2.group === true) {
|
|
2501
|
+
const r2 = t2.value, e = this.getGroupItems(r2);
|
|
2502
|
+
this.isGroupSelected(r2) ? this.value = this.value.filter((s) => e.findIndex((i) => i.value === s) === -1) : this.value = [...this.value, ...e.map((s) => s.value)], this.value = Array.from(new Set(this.value));
|
|
2503
|
+
} else {
|
|
2504
|
+
const r2 = this.value.includes(t2.value);
|
|
2505
|
+
this.value = r2 ? this.value.filter((e) => e !== t2.value) : [...this.value, t2.value];
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
constructor(t2) {
|
|
2509
|
+
super(t2, false);
|
|
2510
|
+
const { options: r2 } = t2;
|
|
2511
|
+
this.#t = t2.selectableGroups !== false, this.options = Object.entries(r2).flatMap(([e, s]) => [
|
|
2512
|
+
{ value: e, group: true, label: e },
|
|
2513
|
+
...s.map((i) => ({ ...i, group: e }))
|
|
2514
|
+
]), this.value = [...t2.initialValues ?? []], this.cursor = Math.max(this.options.findIndex(({ value: e }) => e === t2.cursorAt), this.#t ? 0 : 1), this.on("cursor", (e) => {
|
|
2515
|
+
switch (e) {
|
|
2516
|
+
case "left":
|
|
2517
|
+
case "up": {
|
|
2518
|
+
this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
|
|
2519
|
+
const s = this.options[this.cursor]?.group === true;
|
|
2520
|
+
!this.#t && s && (this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1);
|
|
2521
|
+
break;
|
|
2522
|
+
}
|
|
2523
|
+
case "down":
|
|
2524
|
+
case "right": {
|
|
2525
|
+
this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
|
|
2526
|
+
const s = this.options[this.cursor]?.group === true;
|
|
2527
|
+
!this.#t && s && (this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1);
|
|
2528
|
+
break;
|
|
2529
|
+
}
|
|
2530
|
+
case "space":
|
|
2531
|
+
this.toggleValue();
|
|
2532
|
+
break;
|
|
2533
|
+
}
|
|
2534
|
+
});
|
|
2535
|
+
}
|
|
2536
|
+
};
|
|
2537
|
+
var o = /* @__PURE__ */ new Set(["up", "down", "left", "right"]);
|
|
2538
|
+
|
|
2539
|
+
class h extends V {
|
|
2540
|
+
#t = false;
|
|
2541
|
+
#s;
|
|
2542
|
+
focused = "editor";
|
|
2543
|
+
get userInputWithCursor() {
|
|
2544
|
+
if (this.state === "submit")
|
|
2545
|
+
return this.userInput;
|
|
2546
|
+
const t2 = this.userInput;
|
|
2547
|
+
if (this.cursor >= t2.length)
|
|
2548
|
+
return `${t2}\u2588`;
|
|
2549
|
+
const s = t2.slice(0, this.cursor), r2 = t2.slice(this.cursor, this.cursor + 1), i = t2.slice(this.cursor + 1);
|
|
2550
|
+
return r2 === `
|
|
2551
|
+
` ? `${s}\u2588
|
|
2552
|
+
${i}` : `${s}${styleText("inverse", r2)}${i}`;
|
|
2553
|
+
}
|
|
2554
|
+
get cursor() {
|
|
2555
|
+
return this._cursor;
|
|
2556
|
+
}
|
|
2557
|
+
#r(t2) {
|
|
2558
|
+
if (this.userInput.length === 0) {
|
|
2559
|
+
this._setUserInput(t2);
|
|
2560
|
+
return;
|
|
2561
|
+
}
|
|
2562
|
+
this._setUserInput(this.userInput.slice(0, this.cursor) + t2 + this.userInput.slice(this.cursor));
|
|
2563
|
+
}
|
|
2564
|
+
#i(t2) {
|
|
2565
|
+
const s = this.value ?? "";
|
|
2566
|
+
switch (t2) {
|
|
2567
|
+
case "up":
|
|
2568
|
+
this._cursor = findTextCursor(this._cursor, 0, -1, s);
|
|
2569
|
+
return;
|
|
2570
|
+
case "down":
|
|
2571
|
+
this._cursor = findTextCursor(this._cursor, 0, 1, s);
|
|
2572
|
+
return;
|
|
2573
|
+
case "left":
|
|
2574
|
+
this._cursor = findTextCursor(this._cursor, -1, 0, s);
|
|
2575
|
+
return;
|
|
2576
|
+
case "right":
|
|
2577
|
+
this._cursor = findTextCursor(this._cursor, 1, 0, s);
|
|
2578
|
+
return;
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
_shouldSubmit(t2, s) {
|
|
2582
|
+
if (this.#s)
|
|
2583
|
+
return this.focused === "submit" ? true : (this.#r(`
|
|
2584
|
+
`), this._cursor++, false);
|
|
2585
|
+
const r2 = this.#t;
|
|
2586
|
+
return this.#t = true, r2 && this.cursor === this.userInput.length ? (this.userInput[this.cursor - 1] === `
|
|
2587
|
+
` && (this._setUserInput(this.userInput.slice(0, this.cursor - 1) + this.userInput.slice(this.cursor)), this._cursor--), true) : (this.#r(`
|
|
2588
|
+
`), this._cursor++, false);
|
|
2589
|
+
}
|
|
2590
|
+
constructor(t2) {
|
|
2591
|
+
const s = t2.initialUserInput ?? t2.initialValue;
|
|
2592
|
+
super({
|
|
2593
|
+
...t2,
|
|
2594
|
+
initialUserInput: s
|
|
2595
|
+
}, false), s !== undefined && (this._cursor = s.length), this.#s = t2.showSubmit ?? false, this.on("key", (r2, i) => {
|
|
2596
|
+
if (i?.name && o.has(i.name)) {
|
|
2597
|
+
this.#t = false, this.#i(i.name);
|
|
2598
|
+
return;
|
|
2599
|
+
}
|
|
2600
|
+
if (r2 === "\t" && this.#s) {
|
|
2601
|
+
this.focused = this.focused === "editor" ? "submit" : "editor";
|
|
2602
|
+
return;
|
|
2603
|
+
}
|
|
2604
|
+
if (i?.name !== "return") {
|
|
2605
|
+
if (this.#t = false, i?.name === "backspace" && this.cursor > 0) {
|
|
2606
|
+
this._setUserInput(this.userInput.slice(0, this.cursor - 1) + this.userInput.slice(this.cursor)), this._cursor--;
|
|
2607
|
+
return;
|
|
2608
|
+
}
|
|
2609
|
+
if (i?.name === "delete" && this.cursor < this.userInput.length) {
|
|
2610
|
+
this._setUserInput(this.userInput.slice(0, this.cursor) + this.userInput.slice(this.cursor + 1));
|
|
2611
|
+
return;
|
|
2612
|
+
}
|
|
2613
|
+
r2 && (this.#s && this.focused === "submit" && (this.focused = "editor"), this.#r(r2 ?? ""), this._cursor++);
|
|
2614
|
+
}
|
|
2615
|
+
}), this.on("userInput", (r2) => {
|
|
2616
|
+
this._setValue(r2);
|
|
2617
|
+
}), this.on("finalize", () => {
|
|
2618
|
+
this.value || (this.value = t2.defaultValue), this.value === undefined && (this.value = "");
|
|
2619
|
+
});
|
|
2620
|
+
}
|
|
2621
|
+
}
|
|
2622
|
+
|
|
2623
|
+
// ../../node_modules/.bun/@clack+prompts@1.7.0/node_modules/@clack/prompts/dist/index.mjs
|
|
2624
|
+
import { styleText as styleText2, stripVTControlCharacters } from "util";
|
|
2625
|
+
import process$1 from "process";
|
|
2626
|
+
var import_sisteransi2 = __toESM(require_src(), 1);
|
|
2627
|
+
function isUnicodeSupported() {
|
|
2628
|
+
if (process$1.platform !== "win32") {
|
|
2629
|
+
return process$1.env.TERM !== "linux";
|
|
2630
|
+
}
|
|
2631
|
+
return Boolean(process$1.env.CI) || Boolean(process$1.env.WT_SESSION) || Boolean(process$1.env.TERMINUS_SUBLIME) || process$1.env.ConEmuTask === "{cmd::Cmder}" || process$1.env.TERM_PROGRAM === "Terminus-Sublime" || process$1.env.TERM_PROGRAM === "vscode" || process$1.env.TERM === "xterm-256color" || process$1.env.TERM === "alacritty" || process$1.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
2632
|
+
}
|
|
2633
|
+
var unicode = isUnicodeSupported();
|
|
2634
|
+
var isCI = () => process.env.CI === "true";
|
|
2635
|
+
var unicodeOr = (o2, e) => unicode ? o2 : e;
|
|
2636
|
+
var S_STEP_ACTIVE = unicodeOr("\u25C6", "*");
|
|
2637
|
+
var S_STEP_CANCEL = unicodeOr("\u25A0", "x");
|
|
2638
|
+
var S_STEP_ERROR = unicodeOr("\u25B2", "x");
|
|
2639
|
+
var S_STEP_SUBMIT = unicodeOr("\u25C7", "o");
|
|
2640
|
+
var S_BAR_START = unicodeOr("\u250C", "T");
|
|
2641
|
+
var S_BAR = unicodeOr("\u2502", "|");
|
|
2642
|
+
var S_BAR_END = unicodeOr("\u2514", "\u2014");
|
|
2643
|
+
var S_BAR_START_RIGHT = unicodeOr("\u2510", "T");
|
|
2644
|
+
var S_BAR_END_RIGHT = unicodeOr("\u2518", "\u2014");
|
|
2645
|
+
var S_RADIO_ACTIVE = unicodeOr("\u25CF", ">");
|
|
2646
|
+
var S_RADIO_INACTIVE = unicodeOr("\u25CB", " ");
|
|
2647
|
+
var S_CHECKBOX_ACTIVE = unicodeOr("\u25FB", "[\u2022]");
|
|
2648
|
+
var S_CHECKBOX_SELECTED = unicodeOr("\u25FC", "[+]");
|
|
2649
|
+
var S_CHECKBOX_INACTIVE = unicodeOr("\u25FB", "[ ]");
|
|
2650
|
+
var S_PASSWORD_MASK = unicodeOr("\u25AA", "\u2022");
|
|
2651
|
+
var S_BAR_H = unicodeOr("\u2500", "-");
|
|
2652
|
+
var S_CORNER_TOP_RIGHT = unicodeOr("\u256E", "+");
|
|
2653
|
+
var S_CONNECT_LEFT = unicodeOr("\u251C", "+");
|
|
2654
|
+
var S_CORNER_BOTTOM_RIGHT = unicodeOr("\u256F", "+");
|
|
2655
|
+
var S_CORNER_BOTTOM_LEFT = unicodeOr("\u2570", "+");
|
|
2656
|
+
var S_CORNER_TOP_LEFT = unicodeOr("\u256D", "+");
|
|
2657
|
+
var S_INFO = unicodeOr("\u25CF", "\u2022");
|
|
2658
|
+
var S_SUCCESS = unicodeOr("\u25C6", "*");
|
|
2659
|
+
var S_WARN = unicodeOr("\u25B2", "!");
|
|
2660
|
+
var S_ERROR = unicodeOr("\u25A0", "x");
|
|
2661
|
+
var symbol = (o2) => {
|
|
2662
|
+
switch (o2) {
|
|
2663
|
+
case "initial":
|
|
2664
|
+
case "active":
|
|
2665
|
+
return styleText2("cyan", S_STEP_ACTIVE);
|
|
2666
|
+
case "cancel":
|
|
2667
|
+
return styleText2("red", S_STEP_CANCEL);
|
|
2668
|
+
case "error":
|
|
2669
|
+
return styleText2("yellow", S_STEP_ERROR);
|
|
2670
|
+
case "submit":
|
|
2671
|
+
return styleText2("green", S_STEP_SUBMIT);
|
|
2672
|
+
}
|
|
2673
|
+
};
|
|
2674
|
+
var confirm = (i) => {
|
|
2675
|
+
const a2 = i.active ?? "Yes", s = i.inactive ?? "No";
|
|
2676
|
+
return new r({
|
|
2677
|
+
active: a2,
|
|
2678
|
+
inactive: s,
|
|
2679
|
+
signal: i.signal,
|
|
2680
|
+
input: i.input,
|
|
2681
|
+
output: i.output,
|
|
2682
|
+
initialValue: i.initialValue ?? true,
|
|
2683
|
+
render() {
|
|
2684
|
+
const e = i.withGuide ?? settings.withGuide, u3 = `${symbol(this.state)} `, l2 = e ? `${styleText2("gray", S_BAR)} ` : "", f2 = wrapTextWithPrefix(i.output, i.message, l2, u3), o2 = `${e ? `${styleText2("gray", S_BAR)}
|
|
2685
|
+
` : ""}${f2}
|
|
2686
|
+
`, c2 = this.value ? a2 : s;
|
|
2687
|
+
switch (this.state) {
|
|
2688
|
+
case "submit": {
|
|
2689
|
+
const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
|
|
2690
|
+
return `${o2}${r2}${styleText2("dim", c2)}`;
|
|
2691
|
+
}
|
|
2692
|
+
case "cancel": {
|
|
2693
|
+
const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
|
|
2694
|
+
return `${o2}${r2}${styleText2(["strikethrough", "dim"], c2)}${e ? `
|
|
2695
|
+
${styleText2("gray", S_BAR)}` : ""}`;
|
|
2696
|
+
}
|
|
2697
|
+
default: {
|
|
2698
|
+
const r2 = e ? `${styleText2("cyan", S_BAR)} ` : "", g2 = e ? styleText2("cyan", S_BAR_END) : "";
|
|
2699
|
+
return `${o2}${r2}${this.value ? `${styleText2("green", S_RADIO_ACTIVE)} ${a2}` : `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", a2)}`}${i.vertical ? e ? `
|
|
2700
|
+
${styleText2("cyan", S_BAR)} ` : `
|
|
2701
|
+
` : ` ${styleText2("dim", "/")} `}${this.value ? `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", s)}` : `${styleText2("green", S_RADIO_ACTIVE)} ${s}`}
|
|
2702
|
+
${g2}
|
|
2703
|
+
`;
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
2707
|
+
}).prompt();
|
|
2708
|
+
};
|
|
2709
|
+
var MULTISELECT_INSTRUCTIONS = [
|
|
2710
|
+
`${styleText2("dim", "\u2191/\u2193")} to navigate`,
|
|
2711
|
+
`${styleText2("dim", "Space:")} select`,
|
|
2712
|
+
`${styleText2("dim", "Enter:")} confirm`
|
|
2713
|
+
];
|
|
2714
|
+
var log = {
|
|
2715
|
+
message: (s = [], {
|
|
2716
|
+
symbol: e = styleText2("gray", S_BAR),
|
|
2717
|
+
secondarySymbol: r2 = styleText2("gray", S_BAR),
|
|
2718
|
+
output: m2 = process.stdout,
|
|
2719
|
+
spacing: l2 = 1,
|
|
2720
|
+
withGuide: c2
|
|
2721
|
+
} = {}) => {
|
|
2722
|
+
const t2 = [], o2 = c2 ?? settings.withGuide, f2 = o2 ? r2 : "", O = o2 ? `${e} ` : "", u3 = o2 ? `${r2} ` : "";
|
|
2723
|
+
for (let i = 0;i < l2; i++)
|
|
2724
|
+
t2.push(f2);
|
|
2725
|
+
const g2 = Array.isArray(s) ? s : s.split(`
|
|
2726
|
+
`);
|
|
2727
|
+
if (g2.length > 0) {
|
|
2728
|
+
const [i, ...y] = g2;
|
|
2729
|
+
i.length > 0 ? t2.push(`${O}${i}`) : t2.push(o2 ? e : "");
|
|
2730
|
+
for (const p2 of y)
|
|
2731
|
+
p2.length > 0 ? t2.push(`${u3}${p2}`) : t2.push(o2 ? r2 : "");
|
|
2732
|
+
}
|
|
2733
|
+
m2.write(`${t2.join(`
|
|
2734
|
+
`)}
|
|
2735
|
+
`);
|
|
2736
|
+
},
|
|
2737
|
+
info: (s, e) => {
|
|
2738
|
+
log.message(s, { ...e, symbol: styleText2("blue", S_INFO) });
|
|
2739
|
+
},
|
|
2740
|
+
success: (s, e) => {
|
|
2741
|
+
log.message(s, { ...e, symbol: styleText2("green", S_SUCCESS) });
|
|
2742
|
+
},
|
|
2743
|
+
step: (s, e) => {
|
|
2744
|
+
log.message(s, { ...e, symbol: styleText2("green", S_STEP_SUBMIT) });
|
|
2745
|
+
},
|
|
2746
|
+
warn: (s, e) => {
|
|
2747
|
+
log.message(s, { ...e, symbol: styleText2("yellow", S_WARN) });
|
|
2748
|
+
},
|
|
2749
|
+
warning: (s, e) => {
|
|
2750
|
+
log.warn(s, e);
|
|
2751
|
+
},
|
|
2752
|
+
error: (s, e) => {
|
|
2753
|
+
log.message(s, { ...e, symbol: styleText2("red", S_ERROR) });
|
|
2754
|
+
}
|
|
2755
|
+
};
|
|
2756
|
+
var intro = (o2 = "", t2) => {
|
|
2757
|
+
const i = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_START)} ` : "";
|
|
2758
|
+
i.write(`${e}${o2}
|
|
2759
|
+
`);
|
|
2760
|
+
};
|
|
2761
|
+
var outro = (o2 = "", t2) => {
|
|
2762
|
+
const i = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR)}
|
|
2763
|
+
${styleText2("gray", S_BAR_END)} ` : "";
|
|
2764
|
+
i.write(`${e}${o2}
|
|
2765
|
+
|
|
2766
|
+
`);
|
|
2767
|
+
};
|
|
2768
|
+
var W$1 = (o2) => o2;
|
|
2769
|
+
var C2 = (o2, e, s) => {
|
|
2770
|
+
const a2 = {
|
|
2771
|
+
hard: true,
|
|
2772
|
+
trim: false
|
|
2773
|
+
}, i = wrapAnsi(o2, e, a2).split(`
|
|
2774
|
+
`), c2 = i.reduce((n2, t2) => Math.max(dist_default2(t2), n2), 0), u3 = i.map(s).reduce((n2, t2) => Math.max(dist_default2(t2), n2), 0), g2 = e - (u3 - c2);
|
|
2775
|
+
return wrapAnsi(o2, g2, a2);
|
|
2776
|
+
};
|
|
2777
|
+
var note = (o2 = "", e = "", s) => {
|
|
2778
|
+
const a2 = s?.output ?? process$1.stdout, i = s?.withGuide ?? settings.withGuide, c2 = s?.format ?? W$1, g2 = ["", ...C2(o2, getColumns(a2) - 6, c2).split(`
|
|
2779
|
+
`).map(c2), ""], n2 = dist_default2(e), t2 = Math.max(g2.reduce((m2, F) => {
|
|
2780
|
+
const O = dist_default2(F);
|
|
2781
|
+
return O > m2 ? O : m2;
|
|
2782
|
+
}, 0), n2) + 2, h2 = g2.map((m2) => `${styleText2("gray", S_BAR)} ${m2}${" ".repeat(t2 - dist_default2(m2))}${styleText2("gray", S_BAR)}`).join(`
|
|
2783
|
+
`), T3 = i ? `${styleText2("gray", S_BAR)}
|
|
2784
|
+
` : "", l$1 = i ? S_CONNECT_LEFT : S_CORNER_BOTTOM_LEFT;
|
|
2785
|
+
a2.write(`${T3}${styleText2("green", S_STEP_SUBMIT)} ${styleText2("reset", e)} ${styleText2("gray", S_BAR_H.repeat(Math.max(t2 - n2 - 1, 1)) + S_CORNER_TOP_RIGHT)}
|
|
2786
|
+
${h2}
|
|
2787
|
+
${styleText2("gray", l$1 + S_BAR_H.repeat(t2 + 2) + S_CORNER_BOTTOM_RIGHT)}
|
|
2788
|
+
`);
|
|
2789
|
+
};
|
|
2790
|
+
var W = (l2) => styleText2("magenta", l2);
|
|
2791
|
+
var spinner = ({
|
|
2792
|
+
indicator: l2 = "dots",
|
|
2793
|
+
onCancel: h2,
|
|
2794
|
+
output: n2 = process.stdout,
|
|
2795
|
+
cancelMessage: G,
|
|
2796
|
+
errorMessage: O,
|
|
2797
|
+
frames: E = unicode ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"],
|
|
2798
|
+
delay: F = unicode ? 80 : 120,
|
|
2799
|
+
signal: m2,
|
|
2800
|
+
...I
|
|
2801
|
+
} = {}) => {
|
|
2802
|
+
const u3 = isCI();
|
|
2803
|
+
let M2, T3, d = false, S = false, s = "", p2, w = performance.now();
|
|
2804
|
+
const x = getColumns(n2), k = I?.styleFrame ?? W, g2 = (e) => {
|
|
2805
|
+
const r2 = e > 1 ? O ?? settings.messages.error : G ?? settings.messages.cancel;
|
|
2806
|
+
S = e === 1, d && (a2(r2, e), S && typeof h2 == "function" && h2());
|
|
2807
|
+
}, f2 = () => g2(2), i = () => g2(1), A = () => {
|
|
2808
|
+
process.on("uncaughtExceptionMonitor", f2), process.on("unhandledRejection", f2), process.on("SIGINT", i), process.on("SIGTERM", i), process.on("exit", g2), m2 && m2.addEventListener("abort", i);
|
|
2809
|
+
}, H = () => {
|
|
2810
|
+
process.removeListener("uncaughtExceptionMonitor", f2), process.removeListener("unhandledRejection", f2), process.removeListener("SIGINT", i), process.removeListener("SIGTERM", i), process.removeListener("exit", g2), m2 && m2.removeEventListener("abort", i);
|
|
2811
|
+
}, y = () => {
|
|
2812
|
+
if (p2 === undefined)
|
|
2813
|
+
return;
|
|
2814
|
+
u3 && n2.write(`
|
|
2815
|
+
`);
|
|
2816
|
+
const r2 = wrapAnsi(p2, x, {
|
|
2817
|
+
hard: true,
|
|
2818
|
+
trim: false
|
|
2819
|
+
}).split(`
|
|
2820
|
+
`);
|
|
2821
|
+
r2.length > 1 && n2.write(import_sisteransi2.cursor.up(r2.length - 1)), n2.write(import_sisteransi2.cursor.to(0)), n2.write(import_sisteransi2.erase.down());
|
|
2822
|
+
}, C3 = (e) => e.replace(/\.+$/, ""), _2 = (e) => {
|
|
2823
|
+
const r2 = (performance.now() - e) / 1000, t2 = Math.floor(r2 / 60), o2 = Math.floor(r2 % 60);
|
|
2824
|
+
return t2 > 0 ? `[${t2}m ${o2}s]` : `[${o2}s]`;
|
|
2825
|
+
}, N = I.withGuide ?? settings.withGuide, P2 = (e = "") => {
|
|
2826
|
+
d = true, M2 = block({ output: n2 }), s = C3(e), w = performance.now(), N && n2.write(`${styleText2("gray", S_BAR)}
|
|
2827
|
+
`);
|
|
2828
|
+
let r2 = 0, t2 = 0;
|
|
2829
|
+
A(), T3 = setInterval(() => {
|
|
2830
|
+
if (u3 && s === p2)
|
|
2831
|
+
return;
|
|
2832
|
+
y(), p2 = s;
|
|
2833
|
+
const o2 = k(E[r2]);
|
|
2834
|
+
let v;
|
|
2835
|
+
if (u3)
|
|
2836
|
+
v = `${o2} ${s}...`;
|
|
2837
|
+
else if (l2 === "timer")
|
|
2838
|
+
v = `${o2} ${s} ${_2(w)}`;
|
|
2839
|
+
else {
|
|
2840
|
+
const B = ".".repeat(Math.floor(t2)).slice(0, 3);
|
|
2841
|
+
v = `${o2} ${s}${B}`;
|
|
2842
|
+
}
|
|
2843
|
+
const j = wrapAnsi(v, x, {
|
|
2844
|
+
hard: true,
|
|
2845
|
+
trim: false
|
|
2846
|
+
});
|
|
2847
|
+
n2.write(j), r2 = r2 + 1 < E.length ? r2 + 1 : 0, t2 = t2 < 4 ? t2 + 0.125 : 0;
|
|
2848
|
+
}, F);
|
|
2849
|
+
}, a2 = (e = "", r2 = 0, t2 = false) => {
|
|
2850
|
+
if (!d)
|
|
2851
|
+
return;
|
|
2852
|
+
d = false, clearInterval(T3), y();
|
|
2853
|
+
const o2 = r2 === 0 ? styleText2("green", S_STEP_SUBMIT) : r2 === 1 ? styleText2("red", S_STEP_CANCEL) : styleText2("red", S_STEP_ERROR);
|
|
2854
|
+
s = e ?? s, t2 || (l2 === "timer" ? n2.write(`${o2} ${s} ${_2(w)}
|
|
2855
|
+
`) : n2.write(`${o2} ${s}
|
|
2856
|
+
`)), H(), M2();
|
|
2857
|
+
};
|
|
2858
|
+
return {
|
|
2859
|
+
start: P2,
|
|
2860
|
+
stop: (e = "") => a2(e, 0),
|
|
2861
|
+
message: (e = "") => {
|
|
2862
|
+
s = C3(e ?? s);
|
|
2863
|
+
},
|
|
2864
|
+
cancel: (e = "") => a2(e, 1),
|
|
2865
|
+
error: (e = "") => a2(e, 2),
|
|
2866
|
+
clear: () => a2("", 0, true),
|
|
2867
|
+
get isCancelled() {
|
|
2868
|
+
return S;
|
|
2869
|
+
}
|
|
2870
|
+
};
|
|
2871
|
+
};
|
|
2872
|
+
var u3 = {
|
|
2873
|
+
light: unicodeOr("\u2500", "-"),
|
|
2874
|
+
heavy: unicodeOr("\u2501", "="),
|
|
2875
|
+
block: unicodeOr("\u2588", "#")
|
|
2876
|
+
};
|
|
2877
|
+
var SELECT_INSTRUCTIONS = [
|
|
2878
|
+
`${styleText2("dim", "\u2191/\u2193")} to navigate`,
|
|
2879
|
+
`${styleText2("dim", "Enter:")} confirm`
|
|
2880
|
+
];
|
|
2881
|
+
var i = `${styleText2("gray", S_BAR)} `;
|
|
2882
|
+
|
|
2883
|
+
// src/commands/drop.ts
|
|
2884
|
+
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
2885
|
+
async function runDrop(config2, opts = {}) {
|
|
2886
|
+
intro(import_picocolors.default.bgCyan(import_picocolors.default.black(" @bungres/kit drop ")));
|
|
2887
|
+
const s = spinner();
|
|
2888
|
+
s.start("Loading schemas...");
|
|
2889
|
+
const schemas2 = await loadSchemas(config2.schema);
|
|
2890
|
+
if (schemas2.length === 0) {
|
|
2891
|
+
s.stop("No schemas found.");
|
|
2892
|
+
log.warn(import_picocolors.default.yellow("No table definitions found in schema files."));
|
|
2893
|
+
outro("Failed.");
|
|
2894
|
+
return;
|
|
2895
|
+
}
|
|
2896
|
+
s.stop(`Loaded ${schemas2.length} schemas.`);
|
|
2897
|
+
const ms = spinner();
|
|
2898
|
+
ms.start("Checking database tables...");
|
|
2899
|
+
const sql2 = new Bun.SQL(config2.dbUrl);
|
|
2900
|
+
try {
|
|
2901
|
+
const userSchema = config2.dbSchema;
|
|
2902
|
+
const existingUserTablesResult = await sql2.unsafe(`SELECT table_name FROM information_schema.tables WHERE table_schema = $1`, [userSchema]);
|
|
2903
|
+
const existingTableNames = new Set(existingUserTablesResult.map((r2) => r2.table_name));
|
|
2904
|
+
const migTableCheck = await sql2.unsafe(`SELECT EXISTS (
|
|
2905
|
+
SELECT 1 FROM information_schema.tables
|
|
2906
|
+
WHERE table_schema = $1 AND table_name = $2
|
|
2907
|
+
) AS exists`, [config2.migrationsSchema, config2.migrationsTable]);
|
|
2908
|
+
const migrationTableExists = migTableCheck[0]?.exists ?? false;
|
|
2909
|
+
const pushTableCheck = await sql2.unsafe(`SELECT EXISTS (
|
|
2910
|
+
SELECT 1 FROM information_schema.tables
|
|
2911
|
+
WHERE table_schema = $1 AND table_name = $2
|
|
2912
|
+
) AS exists`, [config2.migrationsSchema, "__bungres_push"]);
|
|
2913
|
+
const pushTableExists = pushTableCheck[0]?.exists ?? false;
|
|
2914
|
+
const tablesToDrop = schemas2.filter((sch) => existingTableNames.has(sch.config.name));
|
|
2915
|
+
if (tablesToDrop.length === 0 && !migrationTableExists && !pushTableExists) {
|
|
2916
|
+
ms.stop("Nothing to do.");
|
|
2917
|
+
log.success(import_picocolors.default.green("No tables to drop (they either don't exist or were already dropped)."));
|
|
2918
|
+
outro("Done.");
|
|
2919
|
+
return;
|
|
2920
|
+
}
|
|
2921
|
+
ms.stop("Database check complete.");
|
|
2922
|
+
const tableNamesToPrint = tablesToDrop.map((sch) => (sch.config.schema ? sch.config.schema + "." : "") + sch.config.name);
|
|
2923
|
+
if (migrationTableExists) {
|
|
2924
|
+
tableNamesToPrint.push(`${config2.migrationsSchema}.${config2.migrationsTable}`);
|
|
2925
|
+
}
|
|
2926
|
+
if (pushTableExists) {
|
|
2927
|
+
tableNamesToPrint.push(`${config2.migrationsSchema}.__bungres_push`);
|
|
2928
|
+
}
|
|
2929
|
+
if (!opts.force) {
|
|
2930
|
+
log.warn(import_picocolors.default.bgRed(import_picocolors.default.white(" \u26A0\uFE0F WARNING ")));
|
|
2931
|
+
log.message(import_picocolors.default.bold(import_picocolors.default.red("This will drop the following tables and ALL their data:")));
|
|
2932
|
+
for (const name of tableNamesToPrint) {
|
|
2933
|
+
log.info(import_picocolors.default.yellow(` - ${name}`));
|
|
2934
|
+
}
|
|
2935
|
+
const confirm2 = await confirm({
|
|
2936
|
+
message: "Are you sure you want to proceed?",
|
|
2937
|
+
initialValue: false
|
|
2938
|
+
});
|
|
2939
|
+
if (isCancel(confirm2) || !confirm2) {
|
|
2940
|
+
outro(import_picocolors.default.gray("Drop aborted."));
|
|
2941
|
+
return;
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
const exSpinner = spinner();
|
|
2945
|
+
exSpinner.start("Dropping tables...");
|
|
2946
|
+
for (const entry of tablesToDrop) {
|
|
2947
|
+
const ddl = `DROP TABLE IF EXISTS "${entry.config.name}" CASCADE;`;
|
|
2948
|
+
await sql2.unsafe(ddl);
|
|
2949
|
+
log.step(import_picocolors.default.gray(`Dropped ${entry.config.name}`));
|
|
2950
|
+
}
|
|
2951
|
+
if (migrationTableExists) {
|
|
2952
|
+
const qualifiedMigTable = `"${config2.migrationsSchema}"."${config2.migrationsTable}"`;
|
|
2953
|
+
await sql2.unsafe(`DROP TABLE IF EXISTS ${qualifiedMigTable} CASCADE`);
|
|
2954
|
+
log.step(import_picocolors.default.gray(`Dropped ${config2.migrationsSchema}.${config2.migrationsTable}`));
|
|
2955
|
+
}
|
|
2956
|
+
if (pushTableExists) {
|
|
2957
|
+
await sql2.unsafe(`DROP TABLE IF EXISTS "${config2.migrationsSchema}"."__bungres_push" CASCADE`);
|
|
2958
|
+
log.step(import_picocolors.default.gray(`Dropped ${config2.migrationsSchema}.__bungres_push`));
|
|
2959
|
+
}
|
|
2960
|
+
exSpinner.stop("Tables dropped.");
|
|
2961
|
+
outro(import_picocolors.default.cyan("\u2728 Drop complete."));
|
|
2962
|
+
} catch (err) {
|
|
2963
|
+
log.error(import_picocolors.default.red(`Drop failed: ${err.message}`));
|
|
2964
|
+
outro("Failed.");
|
|
2965
|
+
} finally {
|
|
2966
|
+
await sql2.end();
|
|
2967
|
+
}
|
|
2968
|
+
}
|
|
2969
|
+
|
|
2970
|
+
// src/commands/migrate.ts
|
|
2971
|
+
import { join as join2, resolve as resolve2 } from "path";
|
|
2972
|
+
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
2973
|
+
async function runMigrate(config2) {
|
|
2974
|
+
intro(import_picocolors2.default.bgCyan(import_picocolors2.default.black(" @bungres/kit migrate ")));
|
|
2975
|
+
const migrationsDir = resolve2(config2.out);
|
|
2976
|
+
const sql2 = new Bun.SQL(config2.dbUrl);
|
|
2977
|
+
const table2 = config2.migrationsTable;
|
|
2978
|
+
const schema = config2.migrationsSchema;
|
|
2979
|
+
const qualifiedTable = `"${schema}"."${table2}"`;
|
|
2980
|
+
const createSchema = `CREATE SCHEMA IF NOT EXISTS "${schema}";`;
|
|
2981
|
+
const createMigrationsTable = `
|
|
2982
|
+
CREATE TABLE IF NOT EXISTS ${qualifiedTable} (
|
|
2983
|
+
id SERIAL PRIMARY KEY,
|
|
2984
|
+
name TEXT NOT NULL UNIQUE,
|
|
2985
|
+
applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
2986
|
+
);`.trim();
|
|
2987
|
+
const s = spinner();
|
|
2988
|
+
s.start("Checking pending migrations...");
|
|
2989
|
+
try {
|
|
2990
|
+
await sql2.unsafe(createSchema);
|
|
2991
|
+
await sql2.unsafe(createMigrationsTable);
|
|
2992
|
+
const glob = new Bun.Glob("*.sql");
|
|
2993
|
+
const files = [];
|
|
2994
|
+
for await (const file of glob.scan({ cwd: migrationsDir, absolute: false })) {
|
|
2995
|
+
files.push(file);
|
|
2996
|
+
}
|
|
2997
|
+
files.sort();
|
|
2998
|
+
if (files.length === 0) {
|
|
2999
|
+
s.stop("No files found.");
|
|
3000
|
+
log.warn(import_picocolors2.default.yellow(`No migration files found in ${migrationsDir}`));
|
|
3001
|
+
log.info(`Run ${import_picocolors2.default.green("bungres generate")} first.`);
|
|
3002
|
+
outro("Done.");
|
|
3003
|
+
return;
|
|
3004
|
+
}
|
|
3005
|
+
const applied = await sql2.unsafe(`SELECT name FROM ${qualifiedTable}`);
|
|
3006
|
+
const appliedSet = new Set(applied.map((r2) => r2.name));
|
|
3007
|
+
const pending = files.filter((f2) => !appliedSet.has(f2));
|
|
3008
|
+
if (pending.length === 0) {
|
|
3009
|
+
s.stop("Up to date.");
|
|
3010
|
+
log.success(import_picocolors2.default.green("Everything is up to date."));
|
|
3011
|
+
outro("Done.");
|
|
3012
|
+
return;
|
|
3013
|
+
}
|
|
3014
|
+
s.stop(`Found ${pending.length} pending migration(s).`);
|
|
3015
|
+
for (const file of pending) {
|
|
3016
|
+
const ms = spinner();
|
|
3017
|
+
ms.start(`Applying ${file}...`);
|
|
3018
|
+
const content = await Bun.file(join2(migrationsDir, file)).text();
|
|
3019
|
+
let upContent = content;
|
|
3020
|
+
const upMatch = content.match(/-- ==== UP ====([\s\S]*?)(?:-- ==== DOWN ====|$)/i);
|
|
3021
|
+
if (upMatch) {
|
|
3022
|
+
upContent = upMatch[1].trim();
|
|
3023
|
+
}
|
|
3024
|
+
if (config2.verbose) {
|
|
3025
|
+
log.info(import_picocolors2.default.gray(`-- ${file} --
|
|
3026
|
+
${upContent}
|
|
3027
|
+
`));
|
|
3028
|
+
}
|
|
3029
|
+
await sql2.transaction(async (txSql) => {
|
|
3030
|
+
const statements = config2.breakpoints ? upContent.split(/-->statement-breakpoint/g).flatMap((chunk) => chunk.split(";").map((s2) => s2.trim()).filter(Boolean)) : upContent.split(";").map((s2) => s2.trim()).filter(Boolean);
|
|
3031
|
+
for (const stmt of statements) {
|
|
3032
|
+
await txSql.unsafe(stmt + ";");
|
|
3033
|
+
}
|
|
3034
|
+
await txSql.unsafe(`INSERT INTO ${qualifiedTable} (name) VALUES ($1)`, [file]);
|
|
3035
|
+
});
|
|
3036
|
+
ms.stop(import_picocolors2.default.green(`\u2713 Applied ${file}`));
|
|
3037
|
+
}
|
|
3038
|
+
outro(import_picocolors2.default.cyan("\u2728 All migrations applied successfully."));
|
|
3039
|
+
} catch (err) {
|
|
3040
|
+
log.error(import_picocolors2.default.red(`Migration failed: ${err.message}`));
|
|
3041
|
+
outro("Failed.");
|
|
3042
|
+
} finally {
|
|
3043
|
+
await sql2.end();
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
|
|
3047
|
+
// src/commands/fresh.ts
|
|
3048
|
+
async function runFresh(config2) {
|
|
3049
|
+
console.log("Dropping all tables...");
|
|
3050
|
+
await runDrop(config2, { force: true });
|
|
3051
|
+
console.log(`
|
|
3052
|
+
Re-running migrations...`);
|
|
3053
|
+
await runMigrate(config2);
|
|
3054
|
+
console.log(`
|
|
3055
|
+
Fresh complete.`);
|
|
3056
|
+
}
|
|
3057
|
+
|
|
3058
|
+
// src/commands/generate.ts
|
|
3059
|
+
import { join as join3, resolve as resolve3 } from "path";
|
|
3060
|
+
import { readdirSync } from "fs";
|
|
3061
|
+
|
|
3062
|
+
// src/differ.ts
|
|
3063
|
+
function diffSchemas(prev, next) {
|
|
3064
|
+
const statements = [];
|
|
3065
|
+
const summary = [];
|
|
3066
|
+
const warnings = [];
|
|
3067
|
+
const prevTables = new Set(Object.keys(prev));
|
|
3068
|
+
const nextTables = new Set(Object.keys(next));
|
|
3069
|
+
const newTableConfigs = [];
|
|
3070
|
+
for (const tableName of nextTables) {
|
|
3071
|
+
if (!prevTables.has(tableName)) {
|
|
3072
|
+
newTableConfigs.push(next[tableName]);
|
|
3073
|
+
}
|
|
3074
|
+
}
|
|
3075
|
+
for (const config2 of topoSortConfigs(newTableConfigs)) {
|
|
3076
|
+
statements.push(generateCreateTable(config2, true));
|
|
3077
|
+
summary.push(`CREATE TABLE ${config2.name}`);
|
|
3078
|
+
}
|
|
3079
|
+
for (const tableName of prevTables) {
|
|
3080
|
+
if (!nextTables.has(tableName)) {
|
|
3081
|
+
const config2 = prev[tableName];
|
|
3082
|
+
const tbl = config2.schema ? `"${config2.schema}"."${tableName}"` : `"${tableName}"`;
|
|
3083
|
+
statements.push(`DROP TABLE IF EXISTS ${tbl};`);
|
|
3084
|
+
summary.push(`DROP TABLE ${tableName}`);
|
|
3085
|
+
warnings.push(`Data loss warning: Table '${tableName}' will be permanently deleted.`);
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
for (const tableName of nextTables) {
|
|
3089
|
+
if (!prevTables.has(tableName))
|
|
3090
|
+
continue;
|
|
3091
|
+
const prevConfig = prev[tableName];
|
|
3092
|
+
const nextConfig = next[tableName];
|
|
3093
|
+
const prevCols = prevConfig.columns;
|
|
3094
|
+
const nextCols = nextConfig.columns;
|
|
3095
|
+
const prevColNames = new Set(Object.keys(prevCols));
|
|
3096
|
+
const nextColNames = new Set(Object.keys(nextCols));
|
|
3097
|
+
for (const key of nextColNames) {
|
|
3098
|
+
if (!prevColNames.has(key)) {
|
|
3099
|
+
const col2 = nextCols[key];
|
|
3100
|
+
statements.push(generateAddColumn(tableName, nextConfig.schema, key, col2));
|
|
3101
|
+
summary.push(`ALTER TABLE ${tableName} ADD COLUMN ${col2.name}`);
|
|
3102
|
+
}
|
|
3103
|
+
}
|
|
3104
|
+
for (const key of prevColNames) {
|
|
3105
|
+
if (!nextColNames.has(key)) {
|
|
1561
3106
|
const col2 = prevCols[key];
|
|
1562
3107
|
statements.push(generateDropColumn(tableName, prevConfig.schema, col2.name));
|
|
1563
3108
|
summary.push(`ALTER TABLE ${tableName} DROP COLUMN ${col2.name}`);
|
|
@@ -1594,20 +3139,20 @@ function diffSchemas(prev, next) {
|
|
|
1594
3139
|
}
|
|
1595
3140
|
}
|
|
1596
3141
|
}
|
|
1597
|
-
const prevIdxNames = new Set((prevConfig.indexes ?? []).map((
|
|
3142
|
+
const prevIdxNames = new Set((prevConfig.indexes ?? []).map((i2) => i2.name ?? `idx_${tableName}_${i2.columns.join("_")}`));
|
|
1598
3143
|
for (const idx of nextConfig.indexes ?? []) {
|
|
1599
3144
|
const idxName = idx.name ?? `idx_${tableName}_${idx.columns.join("_")}`;
|
|
1600
3145
|
if (!prevIdxNames.has(idxName)) {
|
|
1601
3146
|
const tbl = nextConfig.schema ? `"${nextConfig.schema}"."${tableName}"` : `"${tableName}"`;
|
|
1602
3147
|
const unique2 = idx.unique ? "UNIQUE " : "";
|
|
1603
3148
|
const using = idx.using ? ` USING ${idx.using.toUpperCase()}` : "";
|
|
1604
|
-
const cols = idx.columns.map((
|
|
3149
|
+
const cols = idx.columns.map((c2) => `"${c2}"`).join(", ");
|
|
1605
3150
|
const where = idx.where ? ` WHERE ${idx.where}` : "";
|
|
1606
3151
|
statements.push(`CREATE ${unique2}INDEX IF NOT EXISTS "${idxName}" ON ${tbl}${using} (${cols})${where};`);
|
|
1607
3152
|
summary.push(`CREATE INDEX ${idxName} ON ${tableName}`);
|
|
1608
3153
|
}
|
|
1609
3154
|
}
|
|
1610
|
-
const nextIdxNames = new Set((nextConfig.indexes ?? []).map((
|
|
3155
|
+
const nextIdxNames = new Set((nextConfig.indexes ?? []).map((i2) => i2.name ?? `idx_${tableName}_${i2.columns.join("_")}`));
|
|
1611
3156
|
for (const idx of prevConfig.indexes ?? []) {
|
|
1612
3157
|
const idxName = idx.name ?? `idx_${tableName}_${idx.columns.join("_")}`;
|
|
1613
3158
|
if (!nextIdxNames.has(idxName)) {
|
|
@@ -1619,11 +3164,11 @@ function diffSchemas(prev, next) {
|
|
|
1619
3164
|
return { statements, summary, warnings };
|
|
1620
3165
|
}
|
|
1621
3166
|
function topoSortConfigs(tables) {
|
|
1622
|
-
const byName = new Map(tables.map((
|
|
3167
|
+
const byName = new Map(tables.map((t2) => [t2.name, t2]));
|
|
1623
3168
|
const visited = new Set;
|
|
1624
3169
|
const result2 = [];
|
|
1625
3170
|
function deps(config2) {
|
|
1626
|
-
return Object.values(config2.columns).map((col2) => col2.references?.table).filter((
|
|
3171
|
+
return Object.values(config2.columns).map((col2) => col2.references?.table).filter((t2) => t2 !== undefined && byName.has(t2) && t2 !== config2.name);
|
|
1627
3172
|
}
|
|
1628
3173
|
function visit(name) {
|
|
1629
3174
|
if (visited.has(name))
|
|
@@ -1688,21 +3233,40 @@ function formatDefault(value, dataType) {
|
|
|
1688
3233
|
}
|
|
1689
3234
|
|
|
1690
3235
|
// src/commands/generate.ts
|
|
1691
|
-
var
|
|
3236
|
+
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
1692
3237
|
async function runGenerate(config2, name) {
|
|
1693
|
-
|
|
3238
|
+
intro(import_picocolors3.default.bgCyan(import_picocolors3.default.black(" @bungres/kit generate ")));
|
|
3239
|
+
const s = spinner();
|
|
3240
|
+
s.start("Loading schemas...");
|
|
1694
3241
|
const schemas2 = await loadSchemas(config2.schema);
|
|
1695
3242
|
if (schemas2.length === 0) {
|
|
1696
|
-
|
|
3243
|
+
s.stop("No table definitions found.");
|
|
3244
|
+
log.warn(import_picocolors3.default.yellow("Check your schema glob pattern."));
|
|
3245
|
+
outro("Failed.");
|
|
1697
3246
|
return;
|
|
1698
3247
|
}
|
|
3248
|
+
s.stop(`Loaded ${schemas2.length} schemas.`);
|
|
1699
3249
|
const migrationsDir = resolve3(config2.out);
|
|
3250
|
+
const metaDir = join3(migrationsDir, "meta");
|
|
1700
3251
|
await Bun.$`mkdir -p ${migrationsDir}`.quiet();
|
|
1701
|
-
|
|
1702
|
-
const
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
3252
|
+
await Bun.$`mkdir -p ${metaDir}`.quiet();
|
|
3253
|
+
const currentSnapshot = Object.fromEntries(schemas2.map((s2) => [s2.config.name, s2.config]));
|
|
3254
|
+
let prevSnapshot = {};
|
|
3255
|
+
let isFirstMigration = true;
|
|
3256
|
+
try {
|
|
3257
|
+
const files = readdirSync(metaDir).filter((f2) => f2.endsWith("_snapshot.json")).sort();
|
|
3258
|
+
if (files.length > 0) {
|
|
3259
|
+
const latest = files[files.length - 1];
|
|
3260
|
+
prevSnapshot = JSON.parse(await Bun.file(join3(metaDir, latest)).text());
|
|
3261
|
+
isFirstMigration = false;
|
|
3262
|
+
} else {
|
|
3263
|
+
const legacyFile2 = Bun.file(join3(migrationsDir, ".snapshot.json"));
|
|
3264
|
+
if (await legacyFile2.exists()) {
|
|
3265
|
+
prevSnapshot = JSON.parse(await legacyFile2.text());
|
|
3266
|
+
isFirstMigration = false;
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
} catch (e) {}
|
|
1706
3270
|
const now = new Date;
|
|
1707
3271
|
const yyyy = now.getUTCFullYear();
|
|
1708
3272
|
const mm = String(now.getUTCMonth() + 1).padStart(2, "0");
|
|
@@ -1713,60 +3277,86 @@ async function runGenerate(config2, name) {
|
|
|
1713
3277
|
const prefix = `${yyyy}_${mm}_${dd}_${HH}${MM}${SS}`;
|
|
1714
3278
|
const filename = name ? `${prefix}_${name}.sql` : `${prefix}.sql`;
|
|
1715
3279
|
const outPath = join3(migrationsDir, filename);
|
|
1716
|
-
let
|
|
3280
|
+
let upStatements;
|
|
3281
|
+
let downStatements;
|
|
1717
3282
|
let summary;
|
|
1718
3283
|
let warnings = [];
|
|
1719
3284
|
if (isFirstMigration) {
|
|
1720
3285
|
const sorted = topoSort(schemas2);
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
3286
|
+
upStatements = sorted.flatMap((entry) => [
|
|
3287
|
+
`-- ${entry.exportName}`,
|
|
3288
|
+
generateCreateTable(entry.config, true),
|
|
3289
|
+
``
|
|
3290
|
+
]);
|
|
3291
|
+
downStatements = [...sorted].reverse().flatMap((entry) => {
|
|
3292
|
+
const tbl = entry.config.schema ? `"${entry.config.schema}"."${entry.config.name}"` : `"${entry.config.name}"`;
|
|
3293
|
+
return [`DROP TABLE IF EXISTS ${tbl};`];
|
|
3294
|
+
});
|
|
3295
|
+
summary = sorted.map((s2) => `CREATE TABLE ${s2.config.name}`);
|
|
1729
3296
|
} else {
|
|
1730
|
-
const
|
|
1731
|
-
if (
|
|
1732
|
-
|
|
1733
|
-
|
|
3297
|
+
const upDiff = diffSchemas(prevSnapshot, currentSnapshot);
|
|
3298
|
+
if (upDiff.statements.length === 0) {
|
|
3299
|
+
log.warn(import_picocolors3.default.yellow("No schema changes detected. Nothing to generate."));
|
|
3300
|
+
outro("Done.");
|
|
1734
3301
|
return;
|
|
1735
3302
|
}
|
|
1736
|
-
|
|
1737
|
-
summary =
|
|
1738
|
-
warnings =
|
|
3303
|
+
upStatements = upDiff.statements;
|
|
3304
|
+
summary = upDiff.summary;
|
|
3305
|
+
warnings = upDiff.warnings;
|
|
3306
|
+
const downDiff = diffSchemas(currentSnapshot, prevSnapshot);
|
|
3307
|
+
downStatements = downDiff.statements;
|
|
3308
|
+
}
|
|
3309
|
+
log.message(import_picocolors3.default.bold("Schema changes detected:"));
|
|
3310
|
+
for (const s2 of summary) {
|
|
3311
|
+
if (s2.startsWith("CREATE") || s2.startsWith("ALTER TABLE") && s2.includes("ADD")) {
|
|
3312
|
+
log.success(import_picocolors3.default.green(` + ${s2}`));
|
|
3313
|
+
} else if (s2.startsWith("DROP") || s2.startsWith("ALTER TABLE") && s2.includes("DROP")) {
|
|
3314
|
+
log.error(import_picocolors3.default.red(` - ${s2}`));
|
|
3315
|
+
} else {
|
|
3316
|
+
log.info(import_picocolors3.default.blue(` ~ ${s2}`));
|
|
3317
|
+
}
|
|
1739
3318
|
}
|
|
3319
|
+
if (warnings.length > 0) {
|
|
3320
|
+
log.warn(import_picocolors3.default.bgRed(import_picocolors3.default.white(" \u26A0\uFE0F DATA LOSS DETECTED ")));
|
|
3321
|
+
for (const w of warnings)
|
|
3322
|
+
log.warn(import_picocolors3.default.red(` ! ${w}`));
|
|
3323
|
+
}
|
|
3324
|
+
const shouldGenerate = await confirm({
|
|
3325
|
+
message: "Generate this migration?",
|
|
3326
|
+
initialValue: true
|
|
3327
|
+
});
|
|
3328
|
+
if (isCancel(shouldGenerate) || !shouldGenerate) {
|
|
3329
|
+
outro(import_picocolors3.default.gray("Generation cancelled."));
|
|
3330
|
+
return;
|
|
3331
|
+
}
|
|
3332
|
+
s.start("Writing files...");
|
|
1740
3333
|
const lines = [
|
|
1741
3334
|
`-- Migration: ${filename}`,
|
|
1742
3335
|
`-- Generated by @bungres/kit at ${new Date().toISOString()}`,
|
|
1743
3336
|
`-- Changes: ${summary.join(", ")}`,
|
|
1744
3337
|
``,
|
|
1745
|
-
|
|
3338
|
+
`-- ==== UP ====`,
|
|
3339
|
+
...upStatements,
|
|
3340
|
+
``,
|
|
3341
|
+
`-- ==== DOWN ====`,
|
|
3342
|
+
...downStatements,
|
|
3343
|
+
``
|
|
1746
3344
|
];
|
|
1747
3345
|
await Bun.write(outPath, lines.join(`
|
|
1748
3346
|
`));
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
\u26A0\uFE0F WARNING: Data Loss Detected!`, "red"));
|
|
1758
|
-
for (const w of warnings)
|
|
1759
|
-
console.warn(colorize(` ! ${w}`, "red"));
|
|
1760
|
-
console.warn(colorize(` Please review the generated migration carefully before applying it.
|
|
1761
|
-
`, "yellow"));
|
|
1762
|
-
}
|
|
1763
|
-
console.log(colorize(`
|
|
1764
|
-
Run \`bungres migrate\` to apply it.`, "cyan"));
|
|
3347
|
+
const metaPath = join3(metaDir, `${prefix}_snapshot.json`);
|
|
3348
|
+
await Bun.write(metaPath, JSON.stringify(currentSnapshot, null, 2));
|
|
3349
|
+
const legacyFile = Bun.file(join3(migrationsDir, ".snapshot.json"));
|
|
3350
|
+
if (await legacyFile.exists()) {
|
|
3351
|
+
await Bun.$`rm ${legacyFile.name}`.quiet();
|
|
3352
|
+
}
|
|
3353
|
+
s.stop(`Generated ${import_picocolors3.default.cyan(filename)}`);
|
|
3354
|
+
outro(`Run ${import_picocolors3.default.green("bungres migrate")} to apply it.`);
|
|
1765
3355
|
}
|
|
1766
3356
|
function topoSort(schemas2) {
|
|
1767
3357
|
const byName = new Map(schemas2.map((s) => [s.config.name, s]));
|
|
1768
3358
|
function deps(config2) {
|
|
1769
|
-
return Object.values(config2.columns).map((col2) => col2.references?.table).filter((
|
|
3359
|
+
return Object.values(config2.columns).map((col2) => col2.references?.table).filter((t2) => t2 !== undefined && byName.has(t2) && t2 !== config2.name);
|
|
1770
3360
|
}
|
|
1771
3361
|
const visited = new Set;
|
|
1772
3362
|
const result2 = [];
|
|
@@ -1790,18 +3380,25 @@ function topoSort(schemas2) {
|
|
|
1790
3380
|
import { existsSync } from "fs";
|
|
1791
3381
|
import { mkdir } from "fs/promises";
|
|
1792
3382
|
import { join as join4 } from "path";
|
|
3383
|
+
var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
1793
3384
|
async function runInit(cwd = process.cwd()) {
|
|
3385
|
+
intro(import_picocolors4.default.bgCyan(import_picocolors4.default.black(" @bungres/kit init ")));
|
|
1794
3386
|
const configPath = join4(cwd, "bungres.config.ts");
|
|
1795
3387
|
const dbDir = join4(cwd, "src", "db");
|
|
1796
3388
|
if (existsSync(configPath)) {
|
|
1797
|
-
|
|
3389
|
+
log.warn(import_picocolors4.default.yellow("Config file already exists at bungres.config.ts"));
|
|
3390
|
+
outro("Failed.");
|
|
1798
3391
|
return;
|
|
1799
3392
|
}
|
|
3393
|
+
const s = spinner();
|
|
3394
|
+
s.start("Creating project structure...");
|
|
1800
3395
|
try {
|
|
1801
3396
|
await mkdir(dbDir, { recursive: true });
|
|
1802
|
-
|
|
3397
|
+
log.step(`Created ${import_picocolors4.default.cyan("src/db")} directory`);
|
|
1803
3398
|
} catch (e) {
|
|
1804
|
-
|
|
3399
|
+
s.stop("Failed");
|
|
3400
|
+
log.error(`Failed to create src/db directory: ${e}`);
|
|
3401
|
+
outro("Failed.");
|
|
1805
3402
|
return;
|
|
1806
3403
|
}
|
|
1807
3404
|
const configContent = `import { defineConfig } from "@bungres/kit";
|
|
@@ -1816,9 +3413,11 @@ export default defineConfig({
|
|
|
1816
3413
|
`;
|
|
1817
3414
|
try {
|
|
1818
3415
|
await Bun.write(configPath, configContent);
|
|
1819
|
-
|
|
3416
|
+
log.step(`Created ${import_picocolors4.default.cyan("bungres.config.ts")}`);
|
|
1820
3417
|
} catch (e) {
|
|
1821
|
-
|
|
3418
|
+
s.stop("Failed");
|
|
3419
|
+
log.error(`Failed to create config file: ${e}`);
|
|
3420
|
+
outro("Failed.");
|
|
1822
3421
|
return;
|
|
1823
3422
|
}
|
|
1824
3423
|
const schemaContent = `import {
|
|
@@ -1842,9 +3441,9 @@ export const users = table("users", {
|
|
|
1842
3441
|
`;
|
|
1843
3442
|
try {
|
|
1844
3443
|
await Bun.write(join4(dbDir, "schema.ts"), schemaContent);
|
|
1845
|
-
|
|
3444
|
+
log.step(`Created ${import_picocolors4.default.cyan("src/db/schema.ts")} with example table`);
|
|
1846
3445
|
} catch (e) {
|
|
1847
|
-
|
|
3446
|
+
log.error(`Failed to create schema file: ${e}`);
|
|
1848
3447
|
}
|
|
1849
3448
|
const clientContent = `import { bungres } from "@bungres/orm";
|
|
1850
3449
|
import * as schema from "./schema";
|
|
@@ -1855,18 +3454,17 @@ export const db = bungres({ url, schema });
|
|
|
1855
3454
|
`;
|
|
1856
3455
|
try {
|
|
1857
3456
|
await Bun.write(join4(dbDir, "client.ts"), clientContent);
|
|
1858
|
-
|
|
3457
|
+
log.step(`Created ${import_picocolors4.default.cyan("src/db/client.ts")}`);
|
|
1859
3458
|
} catch (e) {
|
|
1860
|
-
|
|
1861
|
-
}
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
console.log(" 4. Run 'bungres migrate' to apply migrations");
|
|
3459
|
+
log.error(`Failed to create client file: ${e}`);
|
|
3460
|
+
}
|
|
3461
|
+
s.stop("Project initialized.");
|
|
3462
|
+
const nextSteps = `1. Set DATABASE_URL in your .env file
|
|
3463
|
+
2. Edit src/db/schema.ts to define your tables
|
|
3464
|
+
3. Run ${import_picocolors4.default.green("bungres generate")} to create migrations
|
|
3465
|
+
4. Run ${import_picocolors4.default.green("bungres migrate")} to apply migrations`;
|
|
3466
|
+
note(nextSteps, "Next steps");
|
|
3467
|
+
outro(import_picocolors4.default.cyan("\u2728 Bungres project initialized!"));
|
|
1870
3468
|
}
|
|
1871
3469
|
|
|
1872
3470
|
// src/commands/pull.ts
|
|
@@ -1936,13 +3534,13 @@ function groupByTable(columns2, constraints, indexes) {
|
|
|
1936
3534
|
map.set(col2.table_name, {
|
|
1937
3535
|
tableName: col2.table_name,
|
|
1938
3536
|
columns: [],
|
|
1939
|
-
indexes: indexes.filter((
|
|
3537
|
+
indexes: indexes.filter((i2) => i2.tablename === col2.table_name)
|
|
1940
3538
|
});
|
|
1941
3539
|
}
|
|
1942
|
-
const tableConstraints = constraints.filter((
|
|
1943
|
-
const pkConstraint = tableConstraints.find((
|
|
1944
|
-
const uniqueConstraint = tableConstraints.find((
|
|
1945
|
-
const fkConstraint = tableConstraints.find((
|
|
3540
|
+
const tableConstraints = constraints.filter((c2) => c2.table_name === col2.table_name && c2.column_name === col2.column_name);
|
|
3541
|
+
const pkConstraint = tableConstraints.find((c2) => c2.constraint_type === "PRIMARY KEY");
|
|
3542
|
+
const uniqueConstraint = tableConstraints.find((c2) => c2.constraint_type === "UNIQUE");
|
|
3543
|
+
const fkConstraint = tableConstraints.find((c2) => c2.constraint_type === "FOREIGN KEY");
|
|
1946
3544
|
map.get(col2.table_name).columns.push({
|
|
1947
3545
|
name: col2.column_name,
|
|
1948
3546
|
dataType: col2.data_type,
|
|
@@ -1991,19 +3589,19 @@ function generateSchemaTS(tableMap, dbSchema) {
|
|
|
1991
3589
|
if (table2.indexes.length > 0) {
|
|
1992
3590
|
const idxLines = [];
|
|
1993
3591
|
for (const idx of table2.indexes) {
|
|
1994
|
-
const
|
|
1995
|
-
if (
|
|
1996
|
-
const isUnique = !!
|
|
1997
|
-
const name =
|
|
3592
|
+
const m2 = idx.indexdef.match(/CREATE (UNIQUE )?INDEX (.+) ON (.+) USING (\w+) \((.+)\)(?: WHERE (.+))?/i);
|
|
3593
|
+
if (m2) {
|
|
3594
|
+
const isUnique = !!m2[1];
|
|
3595
|
+
const name = m2[2].trim().replace(/^"|"$/g, "");
|
|
1998
3596
|
if (name.endsWith("_pkey") || name.endsWith("_key"))
|
|
1999
3597
|
continue;
|
|
2000
|
-
const using =
|
|
2001
|
-
const cols =
|
|
3598
|
+
const using = m2[4].toLowerCase();
|
|
3599
|
+
const cols = m2[5].split(",").map((c2) => `"${c2.trim().replace(/^"|"$/g, "")}"`);
|
|
2002
3600
|
let idxStr = `{ name: "${name}", columns: [${cols.join(", ")}], using: "${using}"`;
|
|
2003
3601
|
if (isUnique)
|
|
2004
3602
|
idxStr += `, unique: true`;
|
|
2005
|
-
if (
|
|
2006
|
-
idxStr += `, where: \`${
|
|
3603
|
+
if (m2[6])
|
|
3604
|
+
idxStr += `, where: \`${m2[6].trim()}\``;
|
|
2007
3605
|
idxStr += ` }`;
|
|
2008
3606
|
idxLines.push(idxStr);
|
|
2009
3607
|
}
|
|
@@ -2122,19 +3720,26 @@ function pgTypeToBungresBuilderName(col2) {
|
|
|
2122
3720
|
return "text";
|
|
2123
3721
|
}
|
|
2124
3722
|
function toCamelCase(str) {
|
|
2125
|
-
return str.replace(/_([a-z])/g, (
|
|
3723
|
+
return str.replace(/_([a-z])/g, (_2, c2) => c2.toUpperCase());
|
|
2126
3724
|
}
|
|
2127
3725
|
|
|
2128
3726
|
// src/commands/push.ts
|
|
2129
|
-
|
|
3727
|
+
var import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
2130
3728
|
async function runPush(config2, opts = {}) {
|
|
2131
|
-
|
|
3729
|
+
intro(import_picocolors5.default.bgCyan(import_picocolors5.default.black(" @bungres/kit push ")));
|
|
3730
|
+
const s = spinner();
|
|
3731
|
+
s.start("Loading schemas...");
|
|
2132
3732
|
const schemas2 = await loadSchemas(config2.schema);
|
|
2133
3733
|
if (schemas2.length === 0) {
|
|
2134
|
-
|
|
3734
|
+
s.stop("No schemas found.");
|
|
3735
|
+
log.warn(import_picocolors5.default.yellow("No table definitions found. Check your schema glob pattern."));
|
|
3736
|
+
outro("Failed.");
|
|
2135
3737
|
return;
|
|
2136
3738
|
}
|
|
3739
|
+
s.stop(`Loaded ${schemas2.length} schemas.`);
|
|
2137
3740
|
const sql2 = new Bun.SQL(config2.dbUrl);
|
|
3741
|
+
const ms = spinner();
|
|
3742
|
+
ms.start("Computing diff from database...");
|
|
2138
3743
|
try {
|
|
2139
3744
|
await sql2.unsafe(`CREATE SCHEMA IF NOT EXISTS "${config2.migrationsSchema}";`);
|
|
2140
3745
|
const qualifiedPush = `"${config2.migrationsSchema}"."__bungres_push"`;
|
|
@@ -2149,56 +3754,62 @@ async function runPush(config2, opts = {}) {
|
|
|
2149
3754
|
if (rows.length > 0) {
|
|
2150
3755
|
prevSnapshot = typeof rows[0].snapshot === "string" ? JSON.parse(rows[0].snapshot) : rows[0].snapshot;
|
|
2151
3756
|
}
|
|
2152
|
-
const currentSnapshot = Object.fromEntries(schemas2.map((
|
|
3757
|
+
const currentSnapshot = Object.fromEntries(schemas2.map((schemaEntry) => [schemaEntry.config.name, schemaEntry.config]));
|
|
2153
3758
|
const diff = diffSchemas(prevSnapshot, currentSnapshot);
|
|
2154
3759
|
if (diff.statements.length === 0) {
|
|
2155
|
-
|
|
2156
|
-
No schema changes detected. Database is up to date
|
|
3760
|
+
ms.stop("Up to date.");
|
|
3761
|
+
log.success(import_picocolors5.default.green("No schema changes detected. Database is up to date."));
|
|
3762
|
+
outro("Done.");
|
|
2157
3763
|
return;
|
|
2158
3764
|
}
|
|
2159
|
-
|
|
2160
|
-
Changes to apply
|
|
2161
|
-
for (const
|
|
2162
|
-
|
|
3765
|
+
ms.stop(`Computed ${diff.statements.length} statements.`);
|
|
3766
|
+
log.message(import_picocolors5.default.bold("Changes to apply:"));
|
|
3767
|
+
for (const change of diff.summary) {
|
|
3768
|
+
if (change.startsWith("CREATE") || change.startsWith("ALTER TABLE") && change.includes("ADD")) {
|
|
3769
|
+
log.success(import_picocolors5.default.green(` + ${change}`));
|
|
3770
|
+
} else if (change.startsWith("DROP") || change.startsWith("ALTER TABLE") && change.includes("DROP")) {
|
|
3771
|
+
log.error(import_picocolors5.default.red(` - ${change}`));
|
|
3772
|
+
} else {
|
|
3773
|
+
log.info(import_picocolors5.default.blue(` ~ ${change}`));
|
|
3774
|
+
}
|
|
3775
|
+
}
|
|
2163
3776
|
if (diff.warnings && diff.warnings.length > 0) {
|
|
2164
|
-
|
|
2165
|
-
\u26A0\uFE0F WARNING: Data Loss Detected!`);
|
|
3777
|
+
log.warn(import_picocolors5.default.bgRed(import_picocolors5.default.white(" \u26A0\uFE0F DATA LOSS DETECTED ")));
|
|
2166
3778
|
for (const w of diff.warnings)
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
These changes will be immediately executed against the database!`);
|
|
3779
|
+
log.warn(import_picocolors5.default.red(` ! ${w}`));
|
|
3780
|
+
log.warn(import_picocolors5.default.yellow("These changes will be immediately executed against the database!"));
|
|
2170
3781
|
}
|
|
2171
3782
|
if (!opts.force) {
|
|
2172
|
-
|
|
2173
|
-
Are you sure you want to push these changes?
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
3783
|
+
const confirm2 = await confirm({
|
|
3784
|
+
message: "Are you sure you want to push these changes?",
|
|
3785
|
+
initialValue: true
|
|
3786
|
+
});
|
|
3787
|
+
if (isCancel(confirm2) || !confirm2) {
|
|
3788
|
+
outro(import_picocolors5.default.gray("Push aborted."));
|
|
2177
3789
|
return;
|
|
2178
3790
|
}
|
|
2179
3791
|
}
|
|
2180
|
-
|
|
2181
|
-
Pushing changes
|
|
3792
|
+
const exSpinner = spinner();
|
|
3793
|
+
exSpinner.start("Pushing changes...");
|
|
2182
3794
|
for (const stmt of diff.statements) {
|
|
2183
3795
|
if (config2.verbose) {
|
|
2184
|
-
|
|
3796
|
+
log.info(import_picocolors5.default.gray(`-- ${stmt}`));
|
|
2185
3797
|
}
|
|
2186
3798
|
await sql2.unsafe(stmt);
|
|
2187
3799
|
}
|
|
2188
3800
|
await sql2.unsafe(`INSERT INTO ${qualifiedPush} (snapshot) VALUES ($1);`, [JSON.stringify(currentSnapshot)]);
|
|
2189
|
-
|
|
2190
|
-
Push complete
|
|
3801
|
+
exSpinner.stop(import_picocolors5.default.green("Changes applied successfully."));
|
|
3802
|
+
outro(import_picocolors5.default.cyan("\u2728 Push complete."));
|
|
3803
|
+
} catch (err) {
|
|
3804
|
+
log.error(import_picocolors5.default.red(`Push failed: ${err.message}`));
|
|
3805
|
+
outro("Failed.");
|
|
2191
3806
|
} finally {
|
|
2192
3807
|
await sql2.end();
|
|
2193
3808
|
}
|
|
2194
3809
|
}
|
|
2195
|
-
async function readLine() {
|
|
2196
|
-
const buf = Buffer.alloc(256);
|
|
2197
|
-
const n = fs.readSync(0, buf, 0, 256, null);
|
|
2198
|
-
return buf.subarray(0, n).toString().trim();
|
|
2199
|
-
}
|
|
2200
3810
|
|
|
2201
3811
|
// src/commands/refresh.ts
|
|
3812
|
+
var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
2202
3813
|
async function runRefresh(config2) {
|
|
2203
3814
|
const schemas2 = await loadSchemas(config2.schema);
|
|
2204
3815
|
if (schemas2.length === 0) {
|
|
@@ -2212,55 +3823,210 @@ async function runRefresh(config2) {
|
|
|
2212
3823
|
for (const entry of schemas2) {
|
|
2213
3824
|
const ddl = `TRUNCATE TABLE "${entry.config.name}" CASCADE;`;
|
|
2214
3825
|
await sql2.unsafe(ddl);
|
|
2215
|
-
console.log(
|
|
3826
|
+
console.log(import_picocolors6.default.green(` \u2713 truncated ${entry.config.name}`));
|
|
3827
|
+
}
|
|
3828
|
+
console.log(import_picocolors6.default.green(`
|
|
3829
|
+
Refresh complete. All tables are now empty.`));
|
|
3830
|
+
} finally {
|
|
3831
|
+
await sql2.end();
|
|
3832
|
+
}
|
|
3833
|
+
}
|
|
3834
|
+
|
|
3835
|
+
// src/commands/rollback.ts
|
|
3836
|
+
import { join as join6, resolve as resolve5 } from "path";
|
|
3837
|
+
var import_picocolors7 = __toESM(require_picocolors(), 1);
|
|
3838
|
+
async function runRollback(config2) {
|
|
3839
|
+
intro(import_picocolors7.default.bgCyan(import_picocolors7.default.black(" @bungres/kit rollback ")));
|
|
3840
|
+
const migrationsDir = resolve5(config2.out);
|
|
3841
|
+
const sql2 = new Bun.SQL(config2.dbUrl);
|
|
3842
|
+
const table2 = config2.migrationsTable;
|
|
3843
|
+
const schema = config2.migrationsSchema;
|
|
3844
|
+
const qualifiedTable = `"${schema}"."${table2}"`;
|
|
3845
|
+
const s = spinner();
|
|
3846
|
+
s.start("Checking applied migrations...");
|
|
3847
|
+
try {
|
|
3848
|
+
const applied = await sql2.unsafe(`SELECT name FROM ${qualifiedTable} ORDER BY name DESC LIMIT 1`);
|
|
3849
|
+
if (applied.length === 0) {
|
|
3850
|
+
s.stop("No migrations to rollback.");
|
|
3851
|
+
log.warn(import_picocolors7.default.yellow("No applied migrations found in the database."));
|
|
3852
|
+
outro("Done.");
|
|
3853
|
+
return;
|
|
2216
3854
|
}
|
|
2217
|
-
|
|
2218
|
-
|
|
3855
|
+
const lastMigration = applied[0].name;
|
|
3856
|
+
s.stop(`Found migration to rollback: ${import_picocolors7.default.cyan(lastMigration)}`);
|
|
3857
|
+
const shouldRollback = await confirm({
|
|
3858
|
+
message: `Are you sure you want to rollback ${import_picocolors7.default.cyan(lastMigration)}?`,
|
|
3859
|
+
initialValue: true
|
|
3860
|
+
});
|
|
3861
|
+
if (isCancel(shouldRollback) || !shouldRollback) {
|
|
3862
|
+
outro(import_picocolors7.default.gray("Rollback cancelled."));
|
|
3863
|
+
return;
|
|
3864
|
+
}
|
|
3865
|
+
const ms = spinner();
|
|
3866
|
+
ms.start(`Rolling back ${lastMigration}...`);
|
|
3867
|
+
const content = await Bun.file(join6(migrationsDir, lastMigration)).text();
|
|
3868
|
+
let downContent = "";
|
|
3869
|
+
const downMatch = content.match(/-- ==== DOWN ====([\s\S]*)/i);
|
|
3870
|
+
if (downMatch) {
|
|
3871
|
+
downContent = downMatch[1].trim();
|
|
3872
|
+
} else {
|
|
3873
|
+
ms.stop("Failed.");
|
|
3874
|
+
log.error(import_picocolors7.default.red(`No '-- ==== DOWN ====' section found in ${lastMigration}. Cannot rollback safely.`));
|
|
3875
|
+
outro("Failed.");
|
|
3876
|
+
return;
|
|
3877
|
+
}
|
|
3878
|
+
if (!downContent) {
|
|
3879
|
+
log.warn(import_picocolors7.default.yellow(`Down section is empty in ${lastMigration}. Nothing to execute.`));
|
|
3880
|
+
}
|
|
3881
|
+
if (config2.verbose) {
|
|
3882
|
+
log.info(import_picocolors7.default.gray(`-- ${lastMigration} (DOWN) --
|
|
3883
|
+
${downContent}
|
|
3884
|
+
`));
|
|
3885
|
+
}
|
|
3886
|
+
await sql2.transaction(async (txSql) => {
|
|
3887
|
+
if (downContent) {
|
|
3888
|
+
const statements = config2.breakpoints ? downContent.split(/-->statement-breakpoint/g).flatMap((chunk) => chunk.split(";").map((s2) => s2.trim()).filter(Boolean)) : downContent.split(";").map((s2) => s2.trim()).filter(Boolean);
|
|
3889
|
+
for (const stmt of statements) {
|
|
3890
|
+
await txSql.unsafe(stmt + ";");
|
|
3891
|
+
}
|
|
3892
|
+
}
|
|
3893
|
+
await txSql.unsafe(`DELETE FROM ${qualifiedTable} WHERE name = $1`, [lastMigration]);
|
|
3894
|
+
});
|
|
3895
|
+
ms.stop(import_picocolors7.default.green(`\u2713 Rolled back ${lastMigration}`));
|
|
3896
|
+
outro(import_picocolors7.default.cyan("\u2728 Rollback successful."));
|
|
3897
|
+
} catch (err) {
|
|
3898
|
+
log.error(import_picocolors7.default.red(`Rollback failed: ${err.message}`));
|
|
3899
|
+
outro("Failed.");
|
|
2219
3900
|
} finally {
|
|
2220
3901
|
await sql2.end();
|
|
2221
3902
|
}
|
|
2222
3903
|
}
|
|
2223
3904
|
|
|
2224
3905
|
// src/commands/seed.ts
|
|
2225
|
-
import { resolve as
|
|
3906
|
+
import { resolve as resolve6 } from "path";
|
|
3907
|
+
var import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
2226
3908
|
async function runSeed(config2) {
|
|
2227
|
-
|
|
2228
|
-
|
|
3909
|
+
intro(import_picocolors8.default.bgCyan(import_picocolors8.default.black(" @bungres/kit seed ")));
|
|
3910
|
+
if (config2.seed) {
|
|
3911
|
+
const seedPath = resolve6(process.cwd(), config2.seed);
|
|
3912
|
+
const file = Bun.file(seedPath);
|
|
3913
|
+
if (await file.exists()) {
|
|
3914
|
+
const s2 = spinner();
|
|
3915
|
+
s2.start(`Running seeder: ${config2.seed}...`);
|
|
3916
|
+
const proc = Bun.spawn(["bun", "run", seedPath], {
|
|
3917
|
+
cwd: process.cwd(),
|
|
3918
|
+
stdout: "inherit",
|
|
3919
|
+
stderr: "inherit",
|
|
3920
|
+
env: { ...Bun.env, DATABASE_URL: config2.dbUrl }
|
|
3921
|
+
});
|
|
3922
|
+
const exitCode = await proc.exited;
|
|
3923
|
+
if (exitCode === 0) {
|
|
3924
|
+
s2.stop("Seed complete.");
|
|
3925
|
+
outro(import_picocolors8.default.cyan("\u2728 Seeding successful."));
|
|
3926
|
+
} else {
|
|
3927
|
+
s2.stop("Seed failed.");
|
|
3928
|
+
log.error(import_picocolors8.default.red(`Seed failed with exit code ${exitCode}.`));
|
|
3929
|
+
outro("Failed.");
|
|
3930
|
+
process.exit(exitCode);
|
|
3931
|
+
}
|
|
3932
|
+
return;
|
|
3933
|
+
}
|
|
3934
|
+
}
|
|
3935
|
+
log.info(import_picocolors8.default.blue("No custom seed script found. Initiating Auto-Seeder..."));
|
|
3936
|
+
let faker;
|
|
3937
|
+
try {
|
|
3938
|
+
const fakerModule = await import("@faker-js/faker");
|
|
3939
|
+
faker = fakerModule.faker;
|
|
3940
|
+
} catch (err) {
|
|
3941
|
+
log.error(import_picocolors8.default.red("Auto-seeder requires @faker-js/faker."));
|
|
3942
|
+
log.message(`Please install it: ${import_picocolors8.default.green("bun add -d @faker-js/faker")}`);
|
|
3943
|
+
outro("Failed.");
|
|
2229
3944
|
return;
|
|
2230
3945
|
}
|
|
2231
|
-
const
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
3946
|
+
const s = spinner();
|
|
3947
|
+
s.start("Loading schemas for auto-seeding...");
|
|
3948
|
+
const schemas2 = await loadSchemas(config2.schema);
|
|
3949
|
+
if (schemas2.length === 0) {
|
|
3950
|
+
s.stop("No schemas.");
|
|
3951
|
+
outro("Nothing to seed.");
|
|
3952
|
+
return;
|
|
2236
3953
|
}
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
3954
|
+
const tableConfigs = schemas2.map((s2) => s2.config);
|
|
3955
|
+
const sorted = topoSortConfigs(tableConfigs);
|
|
3956
|
+
s.stop(`Loaded ${sorted.length} tables in topological order.`);
|
|
3957
|
+
const sql2 = new Bun.SQL(config2.dbUrl);
|
|
3958
|
+
const insertedData = {};
|
|
3959
|
+
try {
|
|
3960
|
+
for (const table2 of sorted) {
|
|
3961
|
+
const ms = spinner();
|
|
3962
|
+
ms.start(`Seeding ${table2.name}...`);
|
|
3963
|
+
const rowsToInsert = 10;
|
|
3964
|
+
const rows = [];
|
|
3965
|
+
for (let i2 = 0;i2 < rowsToInsert; i2++) {
|
|
3966
|
+
const row = {};
|
|
3967
|
+
for (const [colName2, col2] of Object.entries(table2.columns)) {
|
|
3968
|
+
if (col2.references) {
|
|
3969
|
+
const parentTable = col2.references.table;
|
|
3970
|
+
const parentRows = insertedData[parentTable];
|
|
3971
|
+
if (parentRows && parentRows.length > 0) {
|
|
3972
|
+
const parentRow = parentRows[Math.floor(Math.random() * parentRows.length)];
|
|
3973
|
+
row[col2.name] = parentRow[col2.references.column];
|
|
3974
|
+
continue;
|
|
3975
|
+
}
|
|
3976
|
+
}
|
|
3977
|
+
if (col2.dataType === "uuid")
|
|
3978
|
+
row[col2.name] = faker.string.uuid();
|
|
3979
|
+
else if (col2.dataType === "varchar" || col2.dataType === "text")
|
|
3980
|
+
row[col2.name] = faker.lorem.word();
|
|
3981
|
+
else if (col2.dataType === "integer")
|
|
3982
|
+
row[col2.name] = faker.number.int({ min: 1, max: 1000 });
|
|
3983
|
+
else if (col2.dataType === "boolean")
|
|
3984
|
+
row[col2.name] = faker.datatype.boolean();
|
|
3985
|
+
else if (col2.dataType === "timestamptz" || col2.dataType === "timestamp")
|
|
3986
|
+
row[col2.name] = faker.date.recent().toISOString();
|
|
3987
|
+
else if (col2.dataType === "jsonb" || col2.dataType === "json")
|
|
3988
|
+
row[col2.name] = JSON.stringify({ key: faker.lorem.word() });
|
|
3989
|
+
else
|
|
3990
|
+
row[col2.name] = null;
|
|
3991
|
+
}
|
|
3992
|
+
rows.push(row);
|
|
3993
|
+
}
|
|
3994
|
+
const insertedRows = await sql2.transaction(async (tx) => {
|
|
3995
|
+
const results = [];
|
|
3996
|
+
for (const row of rows) {
|
|
3997
|
+
const keys = Object.keys(row).map((k) => `"${k}"`);
|
|
3998
|
+
const values = Object.values(row);
|
|
3999
|
+
const placeholders = values.map((_2, i2) => `$${i2 + 1}`);
|
|
4000
|
+
const q = `INSERT INTO "${table2.schema || "public"}"."${table2.name}" (${keys.join(", ")}) VALUES (${placeholders.join(", ")}) RETURNING *`;
|
|
4001
|
+
const res = await tx.unsafe(q, values);
|
|
4002
|
+
results.push(res[0]);
|
|
4003
|
+
}
|
|
4004
|
+
return results;
|
|
4005
|
+
});
|
|
4006
|
+
insertedData[table2.name] = insertedRows;
|
|
4007
|
+
ms.stop(import_picocolors8.default.green(`\u2713 Seeded ${rowsToInsert} rows into ${table2.name}`));
|
|
4008
|
+
}
|
|
4009
|
+
outro(import_picocolors8.default.cyan("\u2728 Auto-seeding complete."));
|
|
4010
|
+
} catch (err) {
|
|
4011
|
+
log.error(import_picocolors8.default.red(`Auto-seeding failed: ${err.message}`));
|
|
4012
|
+
outro("Failed.");
|
|
4013
|
+
} finally {
|
|
4014
|
+
await sql2.end();
|
|
2253
4015
|
}
|
|
2254
4016
|
}
|
|
2255
4017
|
|
|
2256
4018
|
// src/commands/status.ts
|
|
2257
|
-
import { resolve as
|
|
4019
|
+
import { resolve as resolve7 } from "path";
|
|
4020
|
+
var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
2258
4021
|
async function runStatus(config2) {
|
|
2259
|
-
|
|
4022
|
+
intro(import_picocolors9.default.bgCyan(import_picocolors9.default.black(" @bungres/kit status ")));
|
|
4023
|
+
const migrationsDir = resolve7(config2.out);
|
|
2260
4024
|
const sql2 = new Bun.SQL(config2.dbUrl);
|
|
2261
4025
|
const table2 = config2.migrationsTable;
|
|
2262
4026
|
const schema = config2.migrationsSchema;
|
|
2263
4027
|
const qualifiedTable = `"${schema}"."${table2}"`;
|
|
4028
|
+
const s = spinner();
|
|
4029
|
+
s.start("Checking migration status...");
|
|
2264
4030
|
try {
|
|
2265
4031
|
const tableCheck = await sql2.unsafe(`SELECT EXISTS (
|
|
2266
4032
|
SELECT 1 FROM information_schema.tables
|
|
@@ -2274,33 +4040,247 @@ async function runStatus(config2) {
|
|
|
2274
4040
|
}
|
|
2275
4041
|
files.sort();
|
|
2276
4042
|
if (files.length === 0) {
|
|
2277
|
-
|
|
4043
|
+
s.stop("No files found.");
|
|
4044
|
+
log.warn(import_picocolors9.default.yellow("No migration files found."));
|
|
4045
|
+
log.info(`Run ${import_picocolors9.default.green("bungres generate")} first.`);
|
|
4046
|
+
outro("Done.");
|
|
2278
4047
|
return;
|
|
2279
4048
|
}
|
|
2280
4049
|
let appliedSet = new Set;
|
|
2281
4050
|
if (trackingExists) {
|
|
2282
4051
|
const applied = await sql2.unsafe(`SELECT name FROM ${qualifiedTable} ORDER BY applied_at`);
|
|
2283
|
-
appliedSet = new Set(applied.map((
|
|
4052
|
+
appliedSet = new Set(applied.map((r2) => r2.name));
|
|
2284
4053
|
}
|
|
2285
|
-
|
|
2286
|
-
Migration status:
|
|
2287
|
-
`, "cyan"));
|
|
4054
|
+
s.stop("Status check complete.");
|
|
4055
|
+
log.message(import_picocolors9.default.bold("Migration status:"));
|
|
2288
4056
|
let pendingCount = 0;
|
|
2289
4057
|
for (const file of files) {
|
|
2290
4058
|
const isApplied = appliedSet.has(file);
|
|
2291
|
-
|
|
2292
|
-
|
|
4059
|
+
if (isApplied) {
|
|
4060
|
+
log.success(`${import_picocolors9.default.green("\u2713 applied ")} ${file}`);
|
|
4061
|
+
} else {
|
|
2293
4062
|
pendingCount++;
|
|
2294
|
-
|
|
4063
|
+
log.warn(`${import_picocolors9.default.yellow("\u2717 pending ")} ${file}`);
|
|
4064
|
+
}
|
|
2295
4065
|
}
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
4066
|
+
log.info(`${import_picocolors9.default.green(appliedSet.size.toString())} applied, ${import_picocolors9.default.yellow(pendingCount.toString())} pending.`);
|
|
4067
|
+
outro("Done.");
|
|
4068
|
+
} catch (err) {
|
|
4069
|
+
log.error(import_picocolors9.default.red(`Status check failed: ${err.message}`));
|
|
4070
|
+
outro("Failed.");
|
|
2299
4071
|
} finally {
|
|
2300
4072
|
await sql2.end();
|
|
2301
4073
|
}
|
|
2302
4074
|
}
|
|
2303
4075
|
|
|
4076
|
+
// src/commands/studio.ts
|
|
4077
|
+
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
4078
|
+
|
|
4079
|
+
// src/commands/template.ts
|
|
4080
|
+
var indexHtml = `<!DOCTYPE html>
|
|
4081
|
+
<html lang="en">
|
|
4082
|
+
<head>
|
|
4083
|
+
<meta charset="UTF-8">
|
|
4084
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
4085
|
+
<title>Bungres Studio</title>
|
|
4086
|
+
|
|
4087
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
4088
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
4089
|
+
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
|
4090
|
+
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500&display=swap" rel="stylesheet">
|
|
4091
|
+
|
|
4092
|
+
<script src="https://unpkg.com/htmx.org@2.0.0" defer></script>
|
|
4093
|
+
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
|
4094
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
4095
|
+
|
|
4096
|
+
<script>
|
|
4097
|
+
tailwind.config = {
|
|
4098
|
+
darkMode: "class",
|
|
4099
|
+
theme: {
|
|
4100
|
+
extend: {
|
|
4101
|
+
fontFamily: {
|
|
4102
|
+
sans: ['Outfit', 'sans-serif'],
|
|
4103
|
+
mono: ['"Fira Code"', 'monospace'],
|
|
4104
|
+
},
|
|
4105
|
+
colors: {
|
|
4106
|
+
background: 'var(--background)',
|
|
4107
|
+
foreground: 'var(--foreground)',
|
|
4108
|
+
card: 'var(--card)',
|
|
4109
|
+
'card-foreground': 'var(--card-foreground)',
|
|
4110
|
+
popover: 'var(--popover)',
|
|
4111
|
+
'popover-foreground': 'var(--popover-foreground)',
|
|
4112
|
+
primary: 'var(--primary)',
|
|
4113
|
+
'primary-foreground': 'var(--primary-foreground)',
|
|
4114
|
+
secondary: 'var(--secondary)',
|
|
4115
|
+
'secondary-foreground': 'var(--secondary-foreground)',
|
|
4116
|
+
muted: 'var(--muted)',
|
|
4117
|
+
'muted-foreground': 'var(--muted-foreground)',
|
|
4118
|
+
accent: 'var(--accent)',
|
|
4119
|
+
'accent-foreground': 'var(--accent-foreground)',
|
|
4120
|
+
destructive: 'var(--destructive)',
|
|
4121
|
+
border: 'var(--border)',
|
|
4122
|
+
input: 'var(--input)',
|
|
4123
|
+
ring: 'var(--ring)',
|
|
4124
|
+
sidebar: {
|
|
4125
|
+
DEFAULT: 'var(--sidebar)',
|
|
4126
|
+
foreground: 'var(--sidebar-foreground)',
|
|
4127
|
+
primary: 'var(--sidebar-primary)',
|
|
4128
|
+
'primary-foreground': 'var(--sidebar-primary-foreground)',
|
|
4129
|
+
accent: 'var(--sidebar-accent)',
|
|
4130
|
+
'accent-foreground': 'var(--sidebar-accent-foreground)',
|
|
4131
|
+
border: 'var(--sidebar-border)',
|
|
4132
|
+
ring: 'var(--sidebar-ring)',
|
|
4133
|
+
}
|
|
4134
|
+
}
|
|
4135
|
+
}
|
|
4136
|
+
}
|
|
4137
|
+
}
|
|
4138
|
+
</script>
|
|
4139
|
+
|
|
4140
|
+
<style>
|
|
4141
|
+
:root {
|
|
4142
|
+
--background: oklch(1 0 0);
|
|
4143
|
+
--foreground: oklch(0.148 0.004 228.8);
|
|
4144
|
+
--card: oklch(1 0 0);
|
|
4145
|
+
--card-foreground: oklch(0.148 0.004 228.8);
|
|
4146
|
+
--popover: oklch(1 0 0);
|
|
4147
|
+
--popover-foreground: oklch(0.148 0.004 228.8);
|
|
4148
|
+
--primary: oklch(0.508 0.118 165.612);
|
|
4149
|
+
--primary-foreground: oklch(0.979 0.021 166.113);
|
|
4150
|
+
--secondary: oklch(0.967 0.001 286.375);
|
|
4151
|
+
--secondary-foreground: oklch(0.21 0.006 285.885);
|
|
4152
|
+
--muted: oklch(0.963 0.002 197.1);
|
|
4153
|
+
--muted-foreground: oklch(0.56 0.021 213.5);
|
|
4154
|
+
--accent: oklch(0.963 0.002 197.1);
|
|
4155
|
+
--accent-foreground: oklch(0.218 0.008 223.9);
|
|
4156
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
4157
|
+
--border: oklch(0.925 0.005 214.3);
|
|
4158
|
+
--input: oklch(0.925 0.005 214.3);
|
|
4159
|
+
--ring: oklch(0.723 0.014 214.4);
|
|
4160
|
+
--chart-1: oklch(0.845 0.143 164.978);
|
|
4161
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
4162
|
+
--chart-3: oklch(0.596 0.145 163.225);
|
|
4163
|
+
--chart-4: oklch(0.508 0.118 165.612);
|
|
4164
|
+
--chart-5: oklch(0.432 0.095 166.913);
|
|
4165
|
+
--radius: 0.625rem;
|
|
4166
|
+
--sidebar: oklch(0.987 0.002 197.1);
|
|
4167
|
+
--sidebar-foreground: oklch(0.148 0.004 228.8);
|
|
4168
|
+
--sidebar-primary: oklch(0.596 0.145 163.225);
|
|
4169
|
+
--sidebar-primary-foreground: oklch(0.979 0.021 166.113);
|
|
4170
|
+
--sidebar-accent: oklch(0.963 0.002 197.1);
|
|
4171
|
+
--sidebar-accent-foreground: oklch(0.218 0.008 223.9);
|
|
4172
|
+
--sidebar-border: oklch(0.925 0.005 214.3);
|
|
4173
|
+
--sidebar-ring: oklch(0.723 0.014 214.4);
|
|
4174
|
+
}
|
|
4175
|
+
|
|
4176
|
+
.dark {
|
|
4177
|
+
--background: oklch(0.148 0.004 228.8);
|
|
4178
|
+
--foreground: oklch(0.987 0.002 197.1);
|
|
4179
|
+
--card: oklch(0.218 0.008 223.9);
|
|
4180
|
+
--card-foreground: oklch(0.987 0.002 197.1);
|
|
4181
|
+
--popover: oklch(0.218 0.008 223.9);
|
|
4182
|
+
--popover-foreground: oklch(0.987 0.002 197.1);
|
|
4183
|
+
--primary: oklch(0.432 0.095 166.913);
|
|
4184
|
+
--primary-foreground: oklch(0.979 0.021 166.113);
|
|
4185
|
+
--secondary: oklch(0.274 0.006 286.033);
|
|
4186
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
4187
|
+
--muted: oklch(0.275 0.011 216.9);
|
|
4188
|
+
--muted-foreground: oklch(0.723 0.014 214.4);
|
|
4189
|
+
--accent: oklch(0.275 0.011 216.9);
|
|
4190
|
+
--accent-foreground: oklch(0.987 0.002 197.1);
|
|
4191
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
4192
|
+
--border: oklch(1 0 0 / 10%);
|
|
4193
|
+
--input: oklch(1 0 0 / 15%);
|
|
4194
|
+
--ring: oklch(0.56 0.021 213.5);
|
|
4195
|
+
--chart-1: oklch(0.845 0.143 164.978);
|
|
4196
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
4197
|
+
--chart-3: oklch(0.596 0.145 163.225);
|
|
4198
|
+
--chart-4: oklch(0.508 0.118 165.612);
|
|
4199
|
+
--chart-5: oklch(0.432 0.095 166.913);
|
|
4200
|
+
--sidebar: oklch(0.218 0.008 223.9);
|
|
4201
|
+
--sidebar-foreground: oklch(0.987 0.002 197.1);
|
|
4202
|
+
--sidebar-primary: oklch(0.696 0.17 162.48);
|
|
4203
|
+
--sidebar-primary-foreground: oklch(0.262 0.051 172.552);
|
|
4204
|
+
--sidebar-accent: oklch(0.275 0.011 216.9);
|
|
4205
|
+
--sidebar-accent-foreground: oklch(0.987 0.002 197.1);
|
|
4206
|
+
--sidebar-border: oklch(1 0 0 / 10%);
|
|
4207
|
+
--sidebar-ring: oklch(0.56 0.021 213.5);
|
|
4208
|
+
}
|
|
4209
|
+
|
|
4210
|
+
::-webkit-scrollbar { width: 6px; height: 6px; }
|
|
4211
|
+
::-webkit-scrollbar-track { background: transparent; }
|
|
4212
|
+
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
|
|
4213
|
+
::-webkit-scrollbar-thumb:hover { background: var(--muted-foreground); }
|
|
4214
|
+
::-webkit-scrollbar-corner { background: transparent; }
|
|
4215
|
+
[x-cloak] { display: none !important; }
|
|
4216
|
+
.htmx-indicator { opacity: 0; transition: opacity 200ms ease-in; }
|
|
4217
|
+
.htmx-request .htmx-indicator { opacity: 1; }
|
|
4218
|
+
.htmx-request.htmx-indicator { opacity: 1; }
|
|
4219
|
+
</style>
|
|
4220
|
+
</head>
|
|
4221
|
+
<body class="dark bg-background text-foreground font-sans h-screen flex overflow-hidden selection:bg-primary/30">
|
|
4222
|
+
<div x-data="{ currentTable: null, pageSize: 25 }" class="flex h-screen w-full">
|
|
4223
|
+
<aside class="w-64 bg-sidebar border-r border-sidebar-border flex flex-col z-20 shrink-0 text-sidebar-foreground">
|
|
4224
|
+
<div class="p-4 border-b border-sidebar-border flex items-center gap-3 bg-sidebar">
|
|
4225
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-primary">
|
|
4226
|
+
<ellipse cx="12" cy="5" rx="9" ry="3"></ellipse>
|
|
4227
|
+
<path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"></path>
|
|
4228
|
+
<path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"></path>
|
|
4229
|
+
</svg>
|
|
4230
|
+
<h1 class="text-sm font-semibold tracking-tight m-0">Bungres Studio</h1>
|
|
4231
|
+
</div>
|
|
4232
|
+
<div class="flex-1 overflow-y-auto p-2" hx-get="/htmx/sidebar" hx-trigger="load">
|
|
4233
|
+
<div class="p-4 text-xs text-muted-foreground animate-pulse text-center">Loading schemas...</div>
|
|
4234
|
+
</div>
|
|
4235
|
+
</aside>
|
|
4236
|
+
<main class="flex-1 flex flex-col relative w-[calc(100vw-16rem)]">
|
|
4237
|
+
<header class="h-14 px-4 border-b border-border flex items-center justify-between bg-card z-10 shrink-0 text-card-foreground">
|
|
4238
|
+
<h2 class="text-sm font-semibold tracking-tight flex items-center gap-2">
|
|
4239
|
+
<template x-if="currentTable">
|
|
4240
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="text-primary">
|
|
4241
|
+
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
|
4242
|
+
<line x1="3" y1="9" x2="21" y2="9"></line>
|
|
4243
|
+
<line x1="9" y1="21" x2="9" y2="9"></line>
|
|
4244
|
+
</svg>
|
|
4245
|
+
</template>
|
|
4246
|
+
<template x-if="!currentTable">
|
|
4247
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="text-muted-foreground">
|
|
4248
|
+
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
|
4249
|
+
<line x1="3" y1="9" x2="21" y2="9"></line>
|
|
4250
|
+
<line x1="9" y1="21" x2="9" y2="9"></line>
|
|
4251
|
+
</svg>
|
|
4252
|
+
</template>
|
|
4253
|
+
<span x-text="currentTable ? currentTable : 'Select a table'"></span>
|
|
4254
|
+
</h2>
|
|
4255
|
+
<button x-bind:disabled="!currentTable" class="bg-card border border-border text-card-foreground px-3 py-1.5 rounded-md text-xs font-medium cursor-pointer transition-all hover:bg-accent hover:text-accent-foreground active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-1.5 group" x-on:click="$dispatch('refresh-table')">
|
|
4256
|
+
<svg class="w-4 h-4 group-hover:rotate-180 transition-transform duration-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
4257
|
+
<polyline points="23 4 23 10 17 10"></polyline>
|
|
4258
|
+
<polyline points="1 20 1 14 7 14"></polyline>
|
|
4259
|
+
<path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path>
|
|
4260
|
+
</svg>
|
|
4261
|
+
Refresh
|
|
4262
|
+
</button>
|
|
4263
|
+
</header>
|
|
4264
|
+
<div class="flex-1 overflow-auto relative z-[1] text-left bg-background">
|
|
4265
|
+
<div id="data-container" class="h-full w-full flex flex-col" x-on:refresh-table.window="if(currentTable) htmx.ajax('GET', '/htmx/tables/' + currentTable + '?limit=' + pageSize, {target: '#data-container'})">
|
|
4266
|
+
<div class="flex flex-col items-center justify-center h-full w-full text-muted-foreground animate-[fadeIn_0.5s_ease-out]">
|
|
4267
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="w-16 h-16 mb-4 text-muted">
|
|
4268
|
+
<path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path>
|
|
4269
|
+
<polyline points="14 2 14 8 20 8"></polyline>
|
|
4270
|
+
</svg>
|
|
4271
|
+
<h3 class="text-foreground m-0 mb-2 text-lg">No Table Selected</h3>
|
|
4272
|
+
<p class="text-sm">Choose a table from the sidebar to view its data</p>
|
|
4273
|
+
</div>
|
|
4274
|
+
</div>
|
|
4275
|
+
</div>
|
|
4276
|
+
</main>
|
|
4277
|
+
</div>
|
|
4278
|
+
<script>
|
|
4279
|
+
document.addEventListener('alpine:init', () => {})
|
|
4280
|
+
</script>
|
|
4281
|
+
</body>
|
|
4282
|
+
</html>`;
|
|
4283
|
+
|
|
2304
4284
|
// src/commands/studio.ts
|
|
2305
4285
|
async function runStudio(config2) {
|
|
2306
4286
|
const schemas2 = await loadSchemas(config2.schema);
|
|
@@ -2398,804 +4378,181 @@ async function runStudio(config2) {
|
|
|
2398
4378
|
return new Response("Invalid request", { status: 400 });
|
|
2399
4379
|
}
|
|
2400
4380
|
}
|
|
2401
|
-
if (req.method === "GET" && url.pathname === "/") {
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
<
|
|
2417
|
-
<
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
:root {
|
|
2424
|
-
--bg-color: #09090b;
|
|
2425
|
-
--panel-bg: #18181b;
|
|
2426
|
-
--border-color: #27272a;
|
|
2427
|
-
--text-main: #fafafa;
|
|
2428
|
-
--text-muted: #a1a1aa;
|
|
2429
|
-
--accent-color: #8b5cf6;
|
|
2430
|
-
--accent-hover: #7c3aed;
|
|
2431
|
-
--header-bg: #09090b;
|
|
2432
|
-
--row-hover: #27272a;
|
|
2433
|
-
--input-bg: #18181b;
|
|
2434
|
-
--muted-bg: #27272a;
|
|
2435
|
-
|
|
2436
|
-
--type-number: #f472b6;
|
|
2437
|
-
--type-string: #60a5fa;
|
|
2438
|
-
--type-boolean: #34d399;
|
|
2439
|
-
--type-date: #c084fc;
|
|
2440
|
-
--type-json: #fbbf24;
|
|
2441
|
-
--type-null: #71717a;
|
|
2442
|
-
}
|
|
2443
|
-
|
|
2444
|
-
* { box-sizing: border-box; }
|
|
2445
|
-
|
|
2446
|
-
body {
|
|
2447
|
-
margin: 0;
|
|
2448
|
-
padding: 0;
|
|
2449
|
-
font-family: 'Outfit', -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
|
|
2450
|
-
background-color: var(--bg-color);
|
|
2451
|
-
color: var(--text-main);
|
|
2452
|
-
display: flex;
|
|
2453
|
-
height: 100vh;
|
|
2454
|
-
overflow: hidden;
|
|
2455
|
-
}
|
|
2456
|
-
|
|
2457
|
-
/* Sidebar */
|
|
2458
|
-
.sidebar {
|
|
2459
|
-
width: 240px;
|
|
2460
|
-
background-color: var(--panel-bg);
|
|
2461
|
-
border-right: 1px solid var(--border-color);
|
|
2462
|
-
display: flex;
|
|
2463
|
-
flex-direction: column;
|
|
2464
|
-
z-index: 20;
|
|
2465
|
-
}
|
|
2466
|
-
|
|
2467
|
-
.sidebar-header {
|
|
2468
|
-
padding: 16px;
|
|
2469
|
-
border-bottom: 1px solid var(--border-color);
|
|
2470
|
-
display: flex;
|
|
2471
|
-
align-items: center;
|
|
2472
|
-
gap: 8px;
|
|
2473
|
-
background-color: var(--panel-bg);
|
|
2474
|
-
}
|
|
2475
|
-
|
|
2476
|
-
.sidebar-header h1 {
|
|
2477
|
-
margin: 0;
|
|
2478
|
-
font-size: 14px;
|
|
2479
|
-
font-weight: 600;
|
|
2480
|
-
color: var(--text-main);
|
|
2481
|
-
letter-spacing: -0.25px;
|
|
2482
|
-
}
|
|
2483
|
-
|
|
2484
|
-
.sidebar-header svg {
|
|
2485
|
-
color: var(--accent-color);
|
|
2486
|
-
}
|
|
2487
|
-
|
|
2488
|
-
.table-list {
|
|
2489
|
-
flex: 1;
|
|
2490
|
-
overflow-y: auto;
|
|
2491
|
-
padding: 8px;
|
|
2492
|
-
list-style: none;
|
|
2493
|
-
margin: 0;
|
|
2494
|
-
}
|
|
2495
|
-
|
|
2496
|
-
.table-list::-webkit-scrollbar {
|
|
2497
|
-
width: 6px;
|
|
2498
|
-
}
|
|
2499
|
-
.table-list::-webkit-scrollbar-thumb {
|
|
2500
|
-
background: #3f3f46;
|
|
2501
|
-
border-radius: 4px;
|
|
2502
|
-
}
|
|
2503
|
-
|
|
2504
|
-
.table-item {
|
|
2505
|
-
padding: 8px 12px;
|
|
2506
|
-
cursor: pointer;
|
|
2507
|
-
font-size: 13px;
|
|
2508
|
-
font-weight: 500;
|
|
2509
|
-
color: var(--text-muted);
|
|
2510
|
-
border-radius: 6px;
|
|
2511
|
-
transition: all 0.15s ease;
|
|
2512
|
-
display: flex;
|
|
2513
|
-
align-items: center;
|
|
2514
|
-
gap: 8px;
|
|
2515
|
-
margin-bottom: 2px;
|
|
2516
|
-
border: 1px solid transparent;
|
|
2517
|
-
}
|
|
2518
|
-
|
|
2519
|
-
.table-item:hover {
|
|
2520
|
-
background-color: var(--muted-bg);
|
|
2521
|
-
color: var(--text-main);
|
|
2522
|
-
}
|
|
2523
|
-
|
|
2524
|
-
.table-item.active {
|
|
2525
|
-
background-color: var(--accent-color);
|
|
2526
|
-
color: #fff;
|
|
2527
|
-
border-color: var(--accent-color);
|
|
2528
|
-
}
|
|
2529
|
-
|
|
2530
|
-
.table-item svg {
|
|
2531
|
-
flex-shrink: 0;
|
|
2532
|
-
}
|
|
2533
|
-
.table-item.active svg {
|
|
2534
|
-
color: #fff;
|
|
2535
|
-
}
|
|
2536
|
-
|
|
2537
|
-
/* Main Content */
|
|
2538
|
-
.main {
|
|
2539
|
-
flex: 1;
|
|
2540
|
-
display: flex;
|
|
2541
|
-
flex-direction: column;
|
|
2542
|
-
position: relative;
|
|
2543
|
-
}
|
|
2544
|
-
|
|
2545
|
-
.main-header {
|
|
2546
|
-
height: 56px;
|
|
2547
|
-
padding: 0 16px;
|
|
2548
|
-
border-bottom: 1px solid var(--border-color);
|
|
2549
|
-
display: flex;
|
|
2550
|
-
align-items: center;
|
|
2551
|
-
justify-content: space-between;
|
|
2552
|
-
background-color: var(--header-bg);
|
|
2553
|
-
z-index: 10;
|
|
2554
|
-
}
|
|
2555
|
-
|
|
2556
|
-
.main-header h2 {
|
|
2557
|
-
margin: 0;
|
|
2558
|
-
font-size: 14px;
|
|
2559
|
-
font-weight: 600;
|
|
2560
|
-
color: var(--text-main);
|
|
2561
|
-
letter-spacing: -0.25px;
|
|
2562
|
-
display: flex;
|
|
2563
|
-
align-items: center;
|
|
2564
|
-
gap: 8px;
|
|
2565
|
-
}
|
|
2566
|
-
|
|
2567
|
-
.btn {
|
|
2568
|
-
background-color: var(--input-bg);
|
|
2569
|
-
border: 1px solid var(--border-color);
|
|
2570
|
-
color: var(--text-main);
|
|
2571
|
-
padding: 6px 12px;
|
|
2572
|
-
border-radius: 6px;
|
|
2573
|
-
font-size: 13px;
|
|
2574
|
-
font-weight: 500;
|
|
2575
|
-
font-family: 'Outfit', sans-serif;
|
|
2576
|
-
cursor: pointer;
|
|
2577
|
-
transition: all 0.15s ease;
|
|
2578
|
-
display: flex;
|
|
2579
|
-
align-items: center;
|
|
2580
|
-
gap: 6px;
|
|
2581
|
-
}
|
|
2582
|
-
|
|
2583
|
-
.btn:hover:not(:disabled) {
|
|
2584
|
-
background-color: var(--muted-bg);
|
|
2585
|
-
}
|
|
2586
|
-
|
|
2587
|
-
.btn:active:not(:disabled) {
|
|
2588
|
-
transform: translateY(1px);
|
|
2589
|
-
}
|
|
2590
|
-
|
|
2591
|
-
.btn:disabled {
|
|
2592
|
-
opacity: 0.5;
|
|
2593
|
-
cursor: not-allowed;
|
|
2594
|
-
}
|
|
2595
|
-
|
|
2596
|
-
.content-area {
|
|
2597
|
-
flex: 1;
|
|
2598
|
-
overflow: auto;
|
|
2599
|
-
padding: 0;
|
|
2600
|
-
position: relative;
|
|
2601
|
-
z-index: 1;
|
|
2602
|
-
text-align: left;
|
|
2603
|
-
}
|
|
2604
|
-
|
|
2605
|
-
/* Data Table */
|
|
2606
|
-
.data-grid-container {
|
|
2607
|
-
background-color: var(--bg-color);
|
|
2608
|
-
border: 1px solid var(--border-color);
|
|
2609
|
-
border-radius: 0;
|
|
2610
|
-
overflow: hidden;
|
|
2611
|
-
height: 100%;
|
|
2612
|
-
width: 100%;
|
|
2613
|
-
display: flex;
|
|
2614
|
-
flex-direction: column;
|
|
2615
|
-
}
|
|
2616
|
-
|
|
2617
|
-
.data-grid-container > .table-wrapper {
|
|
2618
|
-
flex: 1;
|
|
2619
|
-
overflow: auto;
|
|
2620
|
-
min-height: 0;
|
|
2621
|
-
}
|
|
2622
|
-
|
|
2623
|
-
.data-grid-container::-webkit-scrollbar {
|
|
2624
|
-
width: 8px;
|
|
2625
|
-
height: 8px;
|
|
2626
|
-
}
|
|
2627
|
-
.data-grid-container::-webkit-scrollbar-corner {
|
|
2628
|
-
background: transparent;
|
|
2629
|
-
}
|
|
2630
|
-
.data-grid-container::-webkit-scrollbar-thumb {
|
|
2631
|
-
background: #3f3f46;
|
|
2632
|
-
border-radius: 4px;
|
|
2633
|
-
}
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
table {
|
|
2637
|
-
width: auto;
|
|
2638
|
-
border-collapse: separate;
|
|
2639
|
-
border-spacing: 0;
|
|
2640
|
-
text-align: left;
|
|
2641
|
-
font-size: 14px;
|
|
2642
|
-
table-layout: auto;
|
|
2643
|
-
}
|
|
2644
|
-
|
|
2645
|
-
th {
|
|
2646
|
-
background-color: var(--panel-bg);
|
|
2647
|
-
color: var(--text-main);
|
|
2648
|
-
font-weight: 500;
|
|
2649
|
-
font-size: 12px;
|
|
2650
|
-
padding: 10px 16px;
|
|
2651
|
-
border-bottom: 1px solid var(--border-color);
|
|
2652
|
-
border-right: 1px solid var(--border-color);
|
|
2653
|
-
white-space: nowrap;
|
|
2654
|
-
position: sticky;
|
|
2655
|
-
top: 0;
|
|
2656
|
-
z-index: 10;
|
|
2657
|
-
}
|
|
2658
|
-
|
|
2659
|
-
.col-header {
|
|
2660
|
-
display: flex;
|
|
2661
|
-
flex-direction: column;
|
|
2662
|
-
gap: 2px;
|
|
2663
|
-
}
|
|
2664
|
-
|
|
2665
|
-
.col-name {
|
|
2666
|
-
font-weight: 600;
|
|
2667
|
-
font-size: 13px;
|
|
2668
|
-
display: flex;
|
|
2669
|
-
align-items: center;
|
|
2670
|
-
gap: 6px;
|
|
2671
|
-
}
|
|
2672
|
-
|
|
2673
|
-
.pk-badge {
|
|
2674
|
-
font-size: 10px;
|
|
2675
|
-
background: rgba(251, 191, 36, 0.15);
|
|
2676
|
-
color: #fbbf24;
|
|
2677
|
-
padding: 2px 5px;
|
|
2678
|
-
border-radius: 4px;
|
|
2679
|
-
font-weight: 500;
|
|
2680
|
-
letter-spacing: 0.25px;
|
|
2681
|
-
border: 1px solid rgba(251, 191, 36, 0.3);
|
|
2682
|
-
}
|
|
2683
|
-
|
|
2684
|
-
.fk-badge {
|
|
2685
|
-
font-size: 10px;
|
|
2686
|
-
background: rgba(96, 165, 250, 0.15);
|
|
2687
|
-
color: #60a5fa;
|
|
2688
|
-
padding: 2px 5px;
|
|
2689
|
-
border-radius: 4px;
|
|
2690
|
-
font-weight: 500;
|
|
2691
|
-
letter-spacing: 0.25px;
|
|
2692
|
-
border: 1px solid rgba(96, 165, 250, 0.3);
|
|
2693
|
-
}
|
|
2694
|
-
|
|
2695
|
-
.col-type {
|
|
2696
|
-
font-size: 11px;
|
|
2697
|
-
color: var(--text-muted);
|
|
2698
|
-
font-family: 'JetBrains Mono', 'Fira Code', monospace;
|
|
2699
|
-
text-transform: uppercase;
|
|
2700
|
-
}
|
|
2701
|
-
|
|
2702
|
-
td {
|
|
2703
|
-
padding: 10px 16px;
|
|
2704
|
-
border-bottom: 1px solid var(--border-color);
|
|
2705
|
-
border-right: 1px solid var(--border-color);
|
|
2706
|
-
color: var(--text-main);
|
|
2707
|
-
max-width: 300px;
|
|
2708
|
-
overflow: hidden;
|
|
2709
|
-
text-overflow: ellipsis;
|
|
2710
|
-
white-space: nowrap;
|
|
2711
|
-
transition: background-color 0.15s ease;
|
|
2712
|
-
font-size: 13px;
|
|
2713
|
-
}
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
tr:hover td {
|
|
2718
|
-
background-color: var(--row-hover);
|
|
2719
|
-
}
|
|
2720
|
-
|
|
2721
|
-
.type-number { color: var(--type-number); }
|
|
2722
|
-
.type-string { color: var(--type-string); }
|
|
2723
|
-
.type-boolean { color: var(--type-boolean); }
|
|
2724
|
-
.type-date { color: var(--type-date); }
|
|
2725
|
-
.type-json { color: var(--type-json); font-family: monospace; }
|
|
2726
|
-
.type-null { color: var(--type-null); font-style: italic; }
|
|
2727
|
-
|
|
2728
|
-
.cell-value {
|
|
2729
|
-
font-family: 'JetBrains Mono', 'Fira Code', monospace;
|
|
2730
|
-
font-size: 13px;
|
|
2731
|
-
}
|
|
2732
|
-
|
|
2733
|
-
.empty-state {
|
|
2734
|
-
display: flex;
|
|
2735
|
-
flex-direction: column;
|
|
2736
|
-
align-items: center;
|
|
2737
|
-
justify-content: center;
|
|
2738
|
-
height: 100%;
|
|
2739
|
-
width: 100%;
|
|
2740
|
-
color: var(--text-muted);
|
|
2741
|
-
animation: fadeIn 0.5s ease-out;
|
|
2742
|
-
}
|
|
2743
|
-
|
|
2744
|
-
.empty-state svg {
|
|
2745
|
-
margin-bottom: 16px;
|
|
2746
|
-
color: #3f3f46;
|
|
2747
|
-
width: 64px;
|
|
2748
|
-
height: 64px;
|
|
2749
|
-
}
|
|
2750
|
-
|
|
2751
|
-
.empty-state h3 {
|
|
2752
|
-
color: var(--text-main);
|
|
2753
|
-
margin: 0 0 8px 0;
|
|
2754
|
-
font-size: 18px;
|
|
2755
|
-
}
|
|
2756
|
-
|
|
2757
|
-
@keyframes fadeIn {
|
|
2758
|
-
from { opacity: 0; transform: translateY(10px); }
|
|
2759
|
-
to { opacity: 1; transform: translateY(0); }
|
|
2760
|
-
}
|
|
2761
|
-
|
|
2762
|
-
@keyframes spin {
|
|
2763
|
-
from { transform: rotate(0deg); }
|
|
2764
|
-
to { transform: rotate(360deg); }
|
|
2765
|
-
}
|
|
2766
|
-
.spinning {
|
|
2767
|
-
animation: spin 1s linear infinite;
|
|
2768
|
-
}
|
|
2769
|
-
|
|
2770
|
-
/* Pagination */
|
|
2771
|
-
.pagination {
|
|
2772
|
-
display: flex;
|
|
2773
|
-
align-items: center;
|
|
2774
|
-
justify-content: space-between;
|
|
2775
|
-
padding: 12px 16px;
|
|
2776
|
-
background-color: var(--panel-bg);
|
|
2777
|
-
border-top: 1px solid var(--border-color);
|
|
2778
|
-
font-size: 13px;
|
|
2779
|
-
color: var(--text-muted);
|
|
2780
|
-
width: fit-content;
|
|
2781
|
-
min-width: 100%;
|
|
2782
|
-
flex-shrink: 0;
|
|
2783
|
-
}
|
|
2784
|
-
|
|
2785
|
-
.pagination-info {
|
|
2786
|
-
display: flex;
|
|
2787
|
-
align-items: center;
|
|
2788
|
-
gap: 12px;
|
|
2789
|
-
}
|
|
2790
|
-
|
|
2791
|
-
.pagination-controls {
|
|
2792
|
-
display: flex;
|
|
2793
|
-
align-items: center;
|
|
2794
|
-
gap: 6px;
|
|
2795
|
-
}
|
|
2796
|
-
|
|
2797
|
-
.pagination-btn {
|
|
2798
|
-
background-color: var(--input-bg);
|
|
2799
|
-
border: 1px solid var(--border-color);
|
|
2800
|
-
color: var(--text-main);
|
|
2801
|
-
padding: 6px 12px;
|
|
2802
|
-
border-radius: 6px;
|
|
2803
|
-
cursor: pointer;
|
|
2804
|
-
font-size: 13px;
|
|
2805
|
-
transition: all 0.15s ease;
|
|
2806
|
-
}
|
|
2807
|
-
|
|
2808
|
-
.pagination-btn:hover:not(:disabled) {
|
|
2809
|
-
background-color: var(--muted-bg);
|
|
2810
|
-
}
|
|
2811
|
-
|
|
2812
|
-
.pagination-btn:disabled {
|
|
2813
|
-
opacity: 0.5;
|
|
2814
|
-
cursor: not-allowed;
|
|
2815
|
-
}
|
|
2816
|
-
|
|
2817
|
-
.pagination-btn.active {
|
|
2818
|
-
background-color: var(--accent-color);
|
|
2819
|
-
border-color: var(--accent-color);
|
|
2820
|
-
}
|
|
2821
|
-
|
|
2822
|
-
.page-input {
|
|
2823
|
-
background-color: var(--input-bg);
|
|
2824
|
-
border: 1px solid var(--border-color);
|
|
2825
|
-
color: var(--text-main);
|
|
2826
|
-
padding: 6px 8px;
|
|
2827
|
-
border-radius: 6px;
|
|
2828
|
-
width: 50px;
|
|
2829
|
-
text-align: center;
|
|
2830
|
-
font-size: 13px;
|
|
2831
|
-
}
|
|
2832
|
-
|
|
2833
|
-
.page-size-select {
|
|
2834
|
-
background-color: var(--input-bg);
|
|
2835
|
-
border: 1px solid var(--border-color);
|
|
2836
|
-
color: var(--text-main);
|
|
2837
|
-
padding: 6px 8px;
|
|
2838
|
-
border-radius: 6px;
|
|
2839
|
-
font-size: 13px;
|
|
2840
|
-
cursor: pointer;
|
|
2841
|
-
}
|
|
2842
|
-
|
|
2843
|
-
.page-size-select:hover {
|
|
2844
|
-
background-color: var(--muted-bg);
|
|
2845
|
-
}
|
|
2846
|
-
</style>
|
|
2847
|
-
</head>
|
|
2848
|
-
<body>
|
|
2849
|
-
|
|
2850
|
-
<div class="sidebar">
|
|
2851
|
-
<div class="sidebar-header">
|
|
2852
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2853
|
-
<ellipse cx="12" cy="5" rx="9" ry="3"></ellipse>
|
|
2854
|
-
<path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"></path>
|
|
2855
|
-
<path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"></path>
|
|
2856
|
-
</svg>
|
|
2857
|
-
<h1>Bungres Studio</h1>
|
|
2858
|
-
</div>
|
|
2859
|
-
<ul class="table-list" id="table-list">
|
|
2860
|
-
<!-- Populated by JS -->
|
|
2861
|
-
</ul>
|
|
2862
|
-
</div>
|
|
2863
|
-
|
|
2864
|
-
<div class="main">
|
|
2865
|
-
<div class="main-header">
|
|
2866
|
-
<h2 id="current-table-name">
|
|
2867
|
-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="color: var(--text-muted);">
|
|
2868
|
-
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
|
2869
|
-
<line x1="3" y1="9" x2="21" y2="9"></line>
|
|
2870
|
-
<line x1="9" y1="21" x2="9" y2="9"></line>
|
|
2871
|
-
</svg>
|
|
2872
|
-
Select a table
|
|
2873
|
-
</h2>
|
|
2874
|
-
<button id="refresh-btn" class="btn" disabled>
|
|
2875
|
-
<svg id="refresh-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2876
|
-
<polyline points="23 4 23 10 17 10"></polyline>
|
|
2877
|
-
<polyline points="1 20 1 14 7 14"></polyline>
|
|
2878
|
-
<path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path>
|
|
2879
|
-
</svg>
|
|
2880
|
-
Refresh
|
|
2881
|
-
</button>
|
|
2882
|
-
</div>
|
|
2883
|
-
<div class="content-area">
|
|
2884
|
-
<div id="data-container" class="empty-state">
|
|
2885
|
-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
2886
|
-
<path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path>
|
|
2887
|
-
<polyline points="14 2 14 8 20 8"></polyline>
|
|
2888
|
-
</svg>
|
|
2889
|
-
<h3>No Table Selected</h3>
|
|
2890
|
-
<p>Choose a table from the sidebar to view its data</p>
|
|
2891
|
-
</div>
|
|
2892
|
-
</div>
|
|
2893
|
-
</div>
|
|
2894
|
-
|
|
2895
|
-
<script>
|
|
2896
|
-
let currentTable = null;
|
|
2897
|
-
let tablesData = [];
|
|
2898
|
-
let tableSchemas = {};
|
|
2899
|
-
let currentPage = 1;
|
|
2900
|
-
let totalPages = 1;
|
|
2901
|
-
let totalRecords = 0;
|
|
2902
|
-
let pageSize = 25;
|
|
2903
|
-
|
|
2904
|
-
// Format values for the data grid
|
|
2905
|
-
function formatValue(val) {
|
|
2906
|
-
if (val === null || val === undefined) return 'null';
|
|
2907
|
-
|
|
2908
|
-
if (typeof val === 'object') {
|
|
2909
|
-
if (val instanceof Date) {
|
|
2910
|
-
return val.toISOString();
|
|
2911
|
-
}
|
|
2912
|
-
// Handle JSON objects
|
|
2913
|
-
const safeJson = JSON.stringify(val)
|
|
2914
|
-
.replace(/&/g, "&")
|
|
2915
|
-
.replace(/</g, "<")
|
|
2916
|
-
.replace(/>/g, ">");
|
|
2917
|
-
return safeJson;
|
|
2918
|
-
}
|
|
2919
|
-
|
|
2920
|
-
if (typeof val === 'string') {
|
|
2921
|
-
// Escape HTML to prevent XSS
|
|
2922
|
-
const safeStr = String(val)
|
|
2923
|
-
.replace(/&/g, "&")
|
|
2924
|
-
.replace(/</g, "<")
|
|
2925
|
-
.replace(/>/g, ">");
|
|
2926
|
-
return safeStr;
|
|
2927
|
-
}
|
|
2928
|
-
|
|
2929
|
-
return String(val);
|
|
2930
|
-
}
|
|
2931
|
-
|
|
2932
|
-
async function loadTables() {
|
|
2933
|
-
try {
|
|
2934
|
-
const res = await fetch('/api/tables');
|
|
2935
|
-
tablesData = await res.json();
|
|
2936
|
-
|
|
2937
|
-
const list = document.getElementById('table-list');
|
|
2938
|
-
list.innerHTML = '';
|
|
2939
|
-
tableSchemas = {};
|
|
2940
|
-
|
|
2941
|
-
tablesData.forEach(t => {
|
|
2942
|
-
tableSchemas[t.name] = t;
|
|
2943
|
-
const li = document.createElement('li');
|
|
2944
|
-
li.className = 'table-item';
|
|
2945
|
-
li.innerHTML = \`
|
|
2946
|
-
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
2947
|
-
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
|
2948
|
-
<line x1="3" y1="9" x2="21" y2="9"></line>
|
|
2949
|
-
<line x1="9" y1="21" x2="9" y2="9"></line>
|
|
2950
|
-
</svg>
|
|
2951
|
-
\${t.name}
|
|
2952
|
-
\`;
|
|
2953
|
-
li.onclick = () => selectTable(t.name);
|
|
2954
|
-
list.appendChild(li);
|
|
4381
|
+
if (req.method === "GET" && url.pathname === "/htmx/sidebar") {
|
|
4382
|
+
let html = '<ul class="flex flex-col gap-0.5 p-2 m-0 list-none">';
|
|
4383
|
+
schemas2.forEach((s) => {
|
|
4384
|
+
const tableName = s.config.name;
|
|
4385
|
+
html += `
|
|
4386
|
+
<li>
|
|
4387
|
+
<button
|
|
4388
|
+
hx-get="/htmx/tables/${tableName}?page=1&limit=25"
|
|
4389
|
+
hx-target="#data-container"
|
|
4390
|
+
@click="currentTable = '${tableName}'; pageSize = 25"
|
|
4391
|
+
:class="currentTable === '${tableName}' ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground'"
|
|
4392
|
+
class="w-full text-left px-3 py-2 rounded-md text-sm font-medium flex items-center gap-2 transition-colors focus:outline-none"
|
|
4393
|
+
>
|
|
4394
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
4395
|
+
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
|
4396
|
+
<line x1="3" y1="9" x2="21" y2="9"></line>
|
|
4397
|
+
<line x1="9" y1="21" x2="9" y2="9"></line>
|
|
4398
|
+
</svg>
|
|
4399
|
+
${tableName}
|
|
4400
|
+
</button>
|
|
4401
|
+
</li>
|
|
4402
|
+
`;
|
|
2955
4403
|
});
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
}
|
|
2959
|
-
}
|
|
2960
|
-
|
|
2961
|
-
async function selectTable(name, page = 1) {
|
|
2962
|
-
currentTable = name;
|
|
2963
|
-
currentPage = page;
|
|
2964
|
-
|
|
2965
|
-
// Update UI active state
|
|
2966
|
-
document.querySelectorAll('.table-item').forEach(el => {
|
|
2967
|
-
if (el.textContent.trim() === name) el.classList.add('active');
|
|
2968
|
-
else el.classList.remove('active');
|
|
2969
|
-
});
|
|
2970
|
-
|
|
2971
|
-
document.getElementById('current-table-name').innerHTML = \`
|
|
2972
|
-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="color: var(--accent-color);">
|
|
2973
|
-
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
|
2974
|
-
<line x1="3" y1="9" x2="21" y2="9"></line>
|
|
2975
|
-
<line x1="9" y1="21" x2="9" y2="9"></line>
|
|
2976
|
-
</svg>
|
|
2977
|
-
\${name}
|
|
2978
|
-
\`;
|
|
2979
|
-
document.getElementById('refresh-btn').disabled = false;
|
|
2980
|
-
|
|
2981
|
-
const container = document.getElementById('data-container');
|
|
2982
|
-
const existingTable = container.querySelector('.data-grid-container');
|
|
2983
|
-
|
|
2984
|
-
if (existingTable) {
|
|
2985
|
-
// Show loading overlay instead of replacing content
|
|
2986
|
-
existingTable.style.opacity = '0.5';
|
|
2987
|
-
existingTable.style.pointerEvents = 'none';
|
|
2988
|
-
} else {
|
|
2989
|
-
container.innerHTML = \`
|
|
2990
|
-
<div class="empty-state">
|
|
2991
|
-
<svg class="spinning" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2992
|
-
<line x1="12" y1="2" x2="12" y2="6"></line>
|
|
2993
|
-
<line x1="12" y1="18" x2="12" y2="22"></line>
|
|
2994
|
-
<line x1="4.93" y1="4.93" x2="7.76" y2="7.76"></line>
|
|
2995
|
-
<line x1="16.24" y1="16.24" x2="19.07" y2="19.07"></line>
|
|
2996
|
-
<line x1="2" y1="12" x2="6" y2="12"></line>
|
|
2997
|
-
<line x1="18" y1="12" x2="22" y2="12"></line>
|
|
2998
|
-
<line x1="4.93" y1="19.07" x2="7.76" y2="16.24"></line>
|
|
2999
|
-
<line x1="16.24" y1="7.76" x2="19.07" y2="4.93"></line>
|
|
3000
|
-
</svg>
|
|
3001
|
-
<p>Loading data...</p>
|
|
3002
|
-
</div>
|
|
3003
|
-
\`;
|
|
4404
|
+
html += "</ul>";
|
|
4405
|
+
return new Response(html, { headers: { "Content-Type": "text/html" } });
|
|
3004
4406
|
}
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
const
|
|
3008
|
-
if (!
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
const rows = response.data || response;
|
|
3012
|
-
totalRecords = response.total || 0;
|
|
3013
|
-
totalPages = response.totalPages || 1;
|
|
3014
|
-
|
|
3015
|
-
const tableSchema = tableSchemas[name];
|
|
3016
|
-
|
|
3017
|
-
if (rows.length === 0) {
|
|
3018
|
-
container.innerHTML = \`
|
|
3019
|
-
<div class="empty-state">
|
|
3020
|
-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
3021
|
-
<circle cx="12" cy="12" r="10"></circle>
|
|
3022
|
-
<line x1="12" y1="8" x2="12" y2="12"></line>
|
|
3023
|
-
<line x1="12" y1="16" x2="12.01" y2="16"></line>
|
|
3024
|
-
</svg>
|
|
3025
|
-
<h3>Table is Empty</h3>
|
|
3026
|
-
<p>No records found in "\${name}"</p>
|
|
3027
|
-
</div>
|
|
3028
|
-
\`;
|
|
3029
|
-
return;
|
|
3030
|
-
}
|
|
3031
|
-
|
|
3032
|
-
// Use all columns from the actual data to ensure foreign keys and all data are shown
|
|
3033
|
-
let columns = [];
|
|
3034
|
-
const allKeys = new Set();
|
|
3035
|
-
rows.forEach(row => {
|
|
3036
|
-
Object.keys(row).forEach(key => allKeys.add(key));
|
|
3037
|
-
});
|
|
3038
|
-
|
|
3039
|
-
// Try to get type info from schema if available
|
|
3040
|
-
const schemaColMap = {};
|
|
3041
|
-
if (tableSchema && tableSchema.columns && tableSchema.columns.length > 0) {
|
|
3042
|
-
tableSchema.columns.forEach(col => {
|
|
3043
|
-
schemaColMap[col.name] = col;
|
|
3044
|
-
});
|
|
4407
|
+
if (req.method === "GET" && url.pathname.startsWith("/htmx/tables/")) {
|
|
4408
|
+
const tableName = url.pathname.split("/")[3];
|
|
4409
|
+
const schema = schemas2.find((s) => s.config.name === tableName);
|
|
4410
|
+
if (!schema) {
|
|
4411
|
+
return new Response(`<div class="p-4 text-red-500">Table not found</div>`, { status: 404, headers: { "Content-Type": "text/html" } });
|
|
3045
4412
|
}
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
const
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
if (typeof val ===
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
type,
|
|
3067
|
-
primaryKey: schemaCol ? schemaCol.primaryKey : false,
|
|
3068
|
-
foreignKey: schemaCol ? schemaCol.foreignKey : null
|
|
4413
|
+
try {
|
|
4414
|
+
const page = parseInt(url.searchParams.get("page") || "1", 10);
|
|
4415
|
+
const limit = parseInt(url.searchParams.get("limit") || "25", 10);
|
|
4416
|
+
const offset = (page - 1) * limit;
|
|
4417
|
+
const countResult = await db2.select({ count: schema.table }).from(schema.table);
|
|
4418
|
+
const total = Array.isArray(countResult) ? countResult.length : 0;
|
|
4419
|
+
const totalPages = Math.ceil(total / limit) || 1;
|
|
4420
|
+
const data = await db2.select().from(schema.table).limit(limit).offset(offset);
|
|
4421
|
+
const formatValue = (val) => {
|
|
4422
|
+
if (val === null || val === undefined)
|
|
4423
|
+
return '<span class="italic text-muted-foreground">null</span>';
|
|
4424
|
+
if (typeof val === "number")
|
|
4425
|
+
return `<span class="text-foreground">${val}</span>`;
|
|
4426
|
+
if (typeof val === "boolean")
|
|
4427
|
+
return `<span class="text-foreground">${val}</span>`;
|
|
4428
|
+
if (val instanceof Date)
|
|
4429
|
+
return `<span class="text-foreground">${val.toISOString()}</span>`;
|
|
4430
|
+
if (typeof val === "object")
|
|
4431
|
+
return `<span class="text-foreground font-mono text-xs">${JSON.stringify(val).replace(/&/g, "&").replace(/</g, "<")}</span>`;
|
|
4432
|
+
return `<span class="text-foreground">${String(val).replace(/&/g, "&").replace(/</g, "<")}</span>`;
|
|
3069
4433
|
};
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
4434
|
+
if (data.length === 0) {
|
|
4435
|
+
return new Response(`
|
|
4436
|
+
<div class="flex flex-col items-center justify-center h-full w-full text-muted-foreground animate-[fadeIn_0.5s_ease-out]">
|
|
4437
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="w-16 h-16 mb-4 text-muted">
|
|
4438
|
+
<circle cx="12" cy="12" r="10"></circle>
|
|
4439
|
+
<line x1="12" y1="8" x2="12" y2="12"></line>
|
|
4440
|
+
<line x1="12" y1="16" x2="12.01" y2="16"></line>
|
|
4441
|
+
</svg>
|
|
4442
|
+
<h3 class="text-foreground m-0 mb-2 text-lg">Table is Empty</h3>
|
|
4443
|
+
<p class="text-sm">No records found in "${tableName}"</p>
|
|
4444
|
+
</div>
|
|
4445
|
+
`, { headers: { "Content-Type": "text/html" } });
|
|
4446
|
+
}
|
|
4447
|
+
const columns2 = Object.keys(data[0] || {});
|
|
4448
|
+
let html = '<div class="flex flex-col h-full w-full bg-background">';
|
|
4449
|
+
html += '<div class="flex-1 overflow-auto">';
|
|
4450
|
+
html += '<table class="text-left border-collapse text-sm whitespace-nowrap">';
|
|
4451
|
+
html += "<thead><tr>";
|
|
4452
|
+
columns2.forEach((col2) => {
|
|
4453
|
+
const colConfig = schema.config.columns ? schema.config.columns[col2] : null;
|
|
4454
|
+
let typeLabel = colConfig ? colConfig.dataType : "unknown";
|
|
4455
|
+
let indexLabel = "";
|
|
4456
|
+
if (colConfig?.primaryKey) {
|
|
4457
|
+
indexLabel += '<span class="ml-1 text-[10px] bg-emerald-500/20 text-emerald-500 px-1 rounded uppercase" title="Primary Key">PK</span>';
|
|
4458
|
+
}
|
|
4459
|
+
if (colConfig?.unique) {
|
|
4460
|
+
indexLabel += '<span class="ml-1 text-[10px] bg-amber-500/20 text-amber-500 px-1 rounded uppercase" title="Unique">UQ</span>';
|
|
4461
|
+
}
|
|
4462
|
+
if (colConfig?.references) {
|
|
4463
|
+
indexLabel += '<span class="ml-1 text-[10px] bg-yellow-500/20 text-yellow-500 px-1 rounded uppercase" title="Foreign Key">FK</span>';
|
|
4464
|
+
}
|
|
4465
|
+
if (schema.config.indexes) {
|
|
4466
|
+
const isIndexed = schema.config.indexes.some((idx) => idx.columns.includes(col2));
|
|
4467
|
+
if (isIndexed) {
|
|
4468
|
+
indexLabel += '<span class="ml-1 text-[10px] bg-blue-500/20 text-blue-500 px-1 rounded uppercase" title="Indexed">IDX</span>';
|
|
4469
|
+
}
|
|
4470
|
+
}
|
|
4471
|
+
html += `<th class="bg-card border-b border-r border-border px-4 py-2.5 font-medium text-muted-foreground sticky top-0 z-10">
|
|
4472
|
+
<div class="flex flex-col gap-0.5">
|
|
4473
|
+
<span class="text-foreground">${col2}</span>
|
|
4474
|
+
<div class="flex items-center flex-wrap gap-1 mt-0.5">
|
|
4475
|
+
<span class="text-[10px] font-mono text-muted-foreground/70 mr-1">${typeLabel}</span>
|
|
4476
|
+
${indexLabel}
|
|
3081
4477
|
</div>
|
|
3082
|
-
<div class="col-type">\${col.type}</div>
|
|
3083
4478
|
</div>
|
|
3084
|
-
</th
|
|
3085
|
-
\`;
|
|
3086
|
-
});
|
|
3087
|
-
html += '</tr></thead><tbody>';
|
|
3088
|
-
|
|
3089
|
-
rows.forEach(row => {
|
|
3090
|
-
html += '<tr>';
|
|
3091
|
-
columns.forEach(col => {
|
|
3092
|
-
html += \`<td>\${formatValue(row[col.name])}</td>\`;
|
|
4479
|
+
</th>`;
|
|
3093
4480
|
});
|
|
3094
|
-
html +=
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
html += '</div></div>';
|
|
3103
|
-
container.innerHTML = html;
|
|
3104
|
-
|
|
3105
|
-
// Fade in the new content
|
|
3106
|
-
const newTable = container.querySelector('.data-grid-container');
|
|
3107
|
-
if (newTable) {
|
|
3108
|
-
newTable.style.opacity = '0';
|
|
3109
|
-
requestAnimationFrame(() => {
|
|
3110
|
-
newTable.style.transition = 'opacity 0.15s ease';
|
|
3111
|
-
newTable.style.opacity = '1';
|
|
4481
|
+
html += "</tr></thead><tbody>";
|
|
4482
|
+
data.forEach((row) => {
|
|
4483
|
+
html += '<tr class="hover:bg-muted/50 transition-colors">';
|
|
4484
|
+
columns2.forEach((col2) => {
|
|
4485
|
+
html += `<td class="border-b border-r border-border px-4 py-2 max-w-[300px] overflow-hidden text-ellipsis">${formatValue(row[col2])}</td>`;
|
|
4486
|
+
});
|
|
4487
|
+
html += "</tr>";
|
|
3112
4488
|
});
|
|
4489
|
+
html += "</tbody></table></div>";
|
|
4490
|
+
const startRecord = (page - 1) * limit + 1;
|
|
4491
|
+
const endRecord = Math.min(page * limit, total);
|
|
4492
|
+
html += `
|
|
4493
|
+
<div class="flex items-center justify-between px-4 py-3 bg-card border-t border-border text-xs text-muted-foreground shrink-0 sticky bottom-0 z-10 w-full">
|
|
4494
|
+
<div class="flex items-center gap-4">
|
|
4495
|
+
<span>${total} records</span>
|
|
4496
|
+
<span>${startRecord}-${endRecord}</span>
|
|
4497
|
+
</div>
|
|
4498
|
+
<div class="flex items-center gap-2">
|
|
4499
|
+
<select
|
|
4500
|
+
name="limit"
|
|
4501
|
+
class="bg-background border border-border text-foreground px-2 py-1.5 rounded-md focus:outline-none focus:ring-1 focus:ring-ring cursor-pointer"
|
|
4502
|
+
@change="pageSize = $event.target.value; htmx.ajax('GET', '/htmx/tables/${tableName}?page=1&limit=' + pageSize, {target: '#data-container'})"
|
|
4503
|
+
>
|
|
4504
|
+
<option value="10" ${limit === 10 ? "selected" : ""}>10</option>
|
|
4505
|
+
<option value="25" ${limit === 25 ? "selected" : ""}>25</option>
|
|
4506
|
+
<option value="50" ${limit === 50 ? "selected" : ""}>50</option>
|
|
4507
|
+
<option value="100" ${limit === 100 ? "selected" : ""}>100</option>
|
|
4508
|
+
</select>
|
|
4509
|
+
|
|
4510
|
+
<button
|
|
4511
|
+
${page <= 1 ? "disabled" : ""}
|
|
4512
|
+
hx-get="/htmx/tables/${tableName}?page=${page - 1}&limit=${limit}"
|
|
4513
|
+
hx-target="#data-container"
|
|
4514
|
+
class="bg-background border border-border text-foreground px-3 py-1.5 rounded-md hover:bg-accent hover:text-accent-foreground disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
|
4515
|
+
>←</button>
|
|
4516
|
+
|
|
4517
|
+
<span class="min-w-[40px] text-center">${page} / ${totalPages}</span>
|
|
4518
|
+
|
|
4519
|
+
<button
|
|
4520
|
+
${page >= totalPages ? "disabled" : ""}
|
|
4521
|
+
hx-get="/htmx/tables/${tableName}?page=${page + 1}&limit=${limit}"
|
|
4522
|
+
hx-target="#data-container"
|
|
4523
|
+
class="bg-background border border-border text-foreground px-3 py-1.5 rounded-md hover:bg-accent hover:text-accent-foreground disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
|
4524
|
+
>→</button>
|
|
4525
|
+
</div>
|
|
4526
|
+
</div>
|
|
4527
|
+
`;
|
|
4528
|
+
html += "</div>";
|
|
4529
|
+
return new Response(html, { headers: { "Content-Type": "text/html" } });
|
|
4530
|
+
} catch (e) {
|
|
4531
|
+
return new Response(`
|
|
4532
|
+
<div class="p-6">
|
|
4533
|
+
<div class="bg-red-500/10 border border-red-500/20 text-red-400 p-4 rounded-lg">
|
|
4534
|
+
<h3 class="font-semibold mb-1">Error Loading Data</h3>
|
|
4535
|
+
<p class="text-sm opacity-80">${e.message}</p>
|
|
4536
|
+
</div>
|
|
4537
|
+
</div>
|
|
4538
|
+
`, { headers: { "Content-Type": "text/html" } });
|
|
3113
4539
|
}
|
|
3114
|
-
|
|
3115
|
-
} catch (e) {
|
|
3116
|
-
container.innerHTML = \`
|
|
3117
|
-
<div class="empty-state">
|
|
3118
|
-
<svg viewBox="0 0 24 24" fill="none" stroke="#ef4444" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
3119
|
-
<circle cx="12" cy="12" r="10"></circle>
|
|
3120
|
-
<line x1="12" y1="8" x2="12" y2="12"></line>
|
|
3121
|
-
<line x1="12" y1="16" x2="12.01" y2="16"></line>
|
|
3122
|
-
</svg>
|
|
3123
|
-
<h3 style="color: #ef4444;">Error Loading Data</h3>
|
|
3124
|
-
<p>\${e.message}</p>
|
|
3125
|
-
</div>
|
|
3126
|
-
\`;
|
|
3127
4540
|
}
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
const endRecord = Math.min(currentPage * pageSize, totalRecords);
|
|
3133
|
-
|
|
3134
|
-
let html = '<div class="pagination">';
|
|
3135
|
-
html += '<div class="pagination-info">';
|
|
3136
|
-
html += \`<span>\${totalRecords} records</span>\`;
|
|
3137
|
-
html += \`<span>\${startRecord}-\${endRecord}</span>\`;
|
|
3138
|
-
html += '</div>';
|
|
3139
|
-
|
|
3140
|
-
html += '<div class="pagination-controls">';
|
|
3141
|
-
|
|
3142
|
-
// Page size selector
|
|
3143
|
-
html += '<select class="page-size-select" onchange="changePageSize(this.value)">';
|
|
3144
|
-
[10, 25, 50, 100].forEach(size => {
|
|
3145
|
-
html += \`<option value="\${size}" \${pageSize === size ? 'selected' : ''}>\${size}</option>\`;
|
|
3146
|
-
});
|
|
3147
|
-
html += '</select>';
|
|
3148
|
-
|
|
3149
|
-
// Previous button
|
|
3150
|
-
html += \`<button class="pagination-btn" onclick="changePage(\${currentPage - 1})" \${currentPage === 1 ? 'disabled' : ''}>\u2190</button>\`;
|
|
3151
|
-
|
|
3152
|
-
// Page indicator
|
|
3153
|
-
html += \`<span style="min-width: 60px; text-align: center;">\${currentPage} / \${totalPages}</span>\`;
|
|
3154
|
-
|
|
3155
|
-
// Next button
|
|
3156
|
-
html += \`<button class="pagination-btn" onclick="changePage(\${currentPage + 1})" \${currentPage === totalPages ? 'disabled' : ''}>\u2192</button>\`;
|
|
3157
|
-
|
|
3158
|
-
html += '</div>';
|
|
3159
|
-
html += '</div>';
|
|
3160
|
-
|
|
3161
|
-
return html;
|
|
3162
|
-
}
|
|
3163
|
-
|
|
3164
|
-
function changePageSize(newSize) {
|
|
3165
|
-
pageSize = parseInt(newSize, 10);
|
|
3166
|
-
currentPage = 1;
|
|
3167
|
-
selectTable(currentTable, currentPage);
|
|
3168
|
-
}
|
|
3169
|
-
|
|
3170
|
-
function changePage(page) {
|
|
3171
|
-
if (page < 1 || page > totalPages) return;
|
|
3172
|
-
selectTable(currentTable, page);
|
|
3173
|
-
}
|
|
3174
|
-
|
|
3175
|
-
document.getElementById('refresh-btn').addEventListener('click', async () => {
|
|
3176
|
-
if (!currentTable) return;
|
|
3177
|
-
|
|
3178
|
-
const icon = document.getElementById('refresh-icon');
|
|
3179
|
-
icon.classList.add('spinning');
|
|
3180
|
-
|
|
3181
|
-
try {
|
|
3182
|
-
await selectTable(currentTable);
|
|
3183
|
-
} catch (e) {
|
|
3184
|
-
console.error("Failed to refresh data", e);
|
|
3185
|
-
} finally {
|
|
3186
|
-
setTimeout(() => { icon.classList.remove('spinning'); }, 500);
|
|
4541
|
+
if (req.method === "GET" && url.pathname === "/") {
|
|
4542
|
+
return new Response(indexHtml, {
|
|
4543
|
+
headers: { "Content-Type": "text/html" }
|
|
4544
|
+
});
|
|
3187
4545
|
}
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
`;
|
|
4546
|
+
return new Response("Not found", { status: 404 });
|
|
4547
|
+
}
|
|
4548
|
+
});
|
|
4549
|
+
intro(import_picocolors10.default.bgCyan(import_picocolors10.default.black(" \uD83D\uDC18 Bungres Studio ")));
|
|
4550
|
+
log.success(`Studio is running at ${import_picocolors10.default.green(`http://localhost:${server.port}`)}`);
|
|
4551
|
+
outro(import_picocolors10.default.gray("Press Ctrl+C to stop"));
|
|
4552
|
+
}
|
|
3196
4553
|
|
|
3197
4554
|
// src/commands/tusky.ts
|
|
3198
|
-
|
|
4555
|
+
var import_picocolors11 = __toESM(require_picocolors(), 1);
|
|
3199
4556
|
async function runTusky(config) {
|
|
3200
4557
|
const schemas = await loadSchemas(config.schema);
|
|
3201
4558
|
const schemaObj = {};
|
|
@@ -3203,40 +4560,23 @@ async function runTusky(config) {
|
|
|
3203
4560
|
schemaObj[s.exportName] = s.table;
|
|
3204
4561
|
}
|
|
3205
4562
|
const db = bungres({ url: config.dbUrl, schema: schemaObj });
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
Database connection established.`);
|
|
3211
|
-
console.log(`
|
|
3212
|
-
Pre-loaded Context:`);
|
|
3213
|
-
console.log(" - db (Bungres Database Client)");
|
|
3214
|
-
for (const s of schemas) {
|
|
3215
|
-
console.log(` - ${s.exportName} (Table)`);
|
|
3216
|
-
}
|
|
3217
|
-
console.log(`
|
|
3218
|
-
Example query: await db.select().from(users)`);
|
|
3219
|
-
console.log(`Type .exit to quit.
|
|
3220
|
-
`);
|
|
3221
|
-
const rl = readline.createInterface({
|
|
3222
|
-
input: process.stdin,
|
|
3223
|
-
output: process.stdout,
|
|
3224
|
-
prompt: "bungres> "
|
|
3225
|
-
});
|
|
4563
|
+
intro(import_picocolors11.default.bgCyan(import_picocolors11.default.black(" \uD83D\uDC18 Bungres REPL (Tusky) ")));
|
|
4564
|
+
log.success(import_picocolors11.default.green("Database connection established."));
|
|
4565
|
+
note(`Example: ${import_picocolors11.default.cyan("db.select().from(users);")}
|
|
4566
|
+
Exit: ${import_picocolors11.default.cyan("exit")}`, "Commands");
|
|
3226
4567
|
globalThis.db = db;
|
|
3227
4568
|
for (const s of schemas) {
|
|
3228
4569
|
globalThis[s.exportName] = s.table;
|
|
3229
4570
|
}
|
|
3230
|
-
|
|
3231
|
-
|
|
4571
|
+
process.stdout.write("bungres> ");
|
|
4572
|
+
for await (const line of console) {
|
|
3232
4573
|
const input = line.trim();
|
|
3233
|
-
if (
|
|
3234
|
-
|
|
3235
|
-
return;
|
|
4574
|
+
if (["exit", ".exit", "quit", ".quit", "exit()", "quit()"].includes(input.toLowerCase())) {
|
|
4575
|
+
break;
|
|
3236
4576
|
}
|
|
3237
4577
|
if (!input) {
|
|
3238
|
-
|
|
3239
|
-
|
|
4578
|
+
process.stdout.write("bungres> ");
|
|
4579
|
+
continue;
|
|
3240
4580
|
}
|
|
3241
4581
|
try {
|
|
3242
4582
|
let code = input;
|
|
@@ -3245,22 +4585,32 @@ Example query: await db.select().from(users)`);
|
|
|
3245
4585
|
console.log(`(Running as raw SQL: await db.raw(\`${input}\`))`);
|
|
3246
4586
|
code = `(async () => { return await db.raw(\`${input}\`); })()`;
|
|
3247
4587
|
} else if (input.includes("await ")) {
|
|
3248
|
-
code = `(async () => { return ${input}; })()`;
|
|
4588
|
+
code = `(async () => { return await ${input}; })()`;
|
|
3249
4589
|
}
|
|
4590
|
+
const start = performance.now();
|
|
3250
4591
|
const result = await eval(code);
|
|
3251
|
-
|
|
4592
|
+
const end = performance.now();
|
|
4593
|
+
const duration = (end - start).toFixed(2);
|
|
4594
|
+
if (Array.isArray(result) && result.length > 0 && typeof result[0] === "object") {
|
|
4595
|
+
console.table(result);
|
|
4596
|
+
} else {
|
|
4597
|
+
console.log(result);
|
|
4598
|
+
}
|
|
4599
|
+
console.log(`
|
|
4600
|
+
(Execution time: ${duration}ms)`);
|
|
3252
4601
|
} catch (err) {
|
|
3253
4602
|
console.error(err.message || err);
|
|
3254
4603
|
}
|
|
3255
|
-
|
|
3256
|
-
}
|
|
3257
|
-
|
|
3258
|
-
process.exit(0);
|
|
3259
|
-
});
|
|
4604
|
+
process.stdout.write("bungres> ");
|
|
4605
|
+
}
|
|
4606
|
+
process.exit(0);
|
|
3260
4607
|
}
|
|
3261
4608
|
|
|
4609
|
+
// src/cli.ts
|
|
4610
|
+
var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
4611
|
+
|
|
3262
4612
|
// src/config.ts
|
|
3263
|
-
import { join as
|
|
4613
|
+
import { join as join7, resolve as resolve8 } from "path";
|
|
3264
4614
|
var CONFIG_FILES = [
|
|
3265
4615
|
"bungres.config.ts",
|
|
3266
4616
|
"bungres.config.js",
|
|
@@ -3270,9 +4620,9 @@ var CONFIG_FILES = [
|
|
|
3270
4620
|
async function loadConfig(cwd = process.cwd()) {
|
|
3271
4621
|
let userConfig = {};
|
|
3272
4622
|
for (const file of CONFIG_FILES) {
|
|
3273
|
-
const configPath =
|
|
4623
|
+
const configPath = join7(cwd, file);
|
|
3274
4624
|
if (await Bun.file(configPath).exists()) {
|
|
3275
|
-
const mod = await import(
|
|
4625
|
+
const mod = await import(resolve8(configPath));
|
|
3276
4626
|
userConfig = mod.default ?? mod;
|
|
3277
4627
|
break;
|
|
3278
4628
|
}
|
|
@@ -3334,7 +4684,7 @@ async function ensureDatabase2(dbUrl) {
|
|
|
3334
4684
|
// package.json
|
|
3335
4685
|
var package_default = {
|
|
3336
4686
|
name: "@bungres/kit",
|
|
3337
|
-
version: "0.
|
|
4687
|
+
version: "0.7.0",
|
|
3338
4688
|
description: "CLI toolkit for @bungres/orm \u2014 migrate, push, generate, pull",
|
|
3339
4689
|
license: "MIT",
|
|
3340
4690
|
engines: {
|
|
@@ -3384,7 +4734,9 @@ var package_default = {
|
|
|
3384
4734
|
test: "bun test"
|
|
3385
4735
|
},
|
|
3386
4736
|
dependencies: {
|
|
3387
|
-
"@bungres/orm": "
|
|
4737
|
+
"@bungres/orm": "^0.6.0",
|
|
4738
|
+
"@clack/prompts": "^1.7.0",
|
|
4739
|
+
picocolors: "^1.1.1"
|
|
3388
4740
|
},
|
|
3389
4741
|
devDependencies: {
|
|
3390
4742
|
"bun-types": "latest",
|
|
@@ -3395,15 +4747,16 @@ var package_default = {
|
|
|
3395
4747
|
// src/cli.ts
|
|
3396
4748
|
var VERSION = package_default.version;
|
|
3397
4749
|
var HELP = `
|
|
3398
|
-
${
|
|
4750
|
+
${import_picocolors12.default.cyan("\uD83D\uDC18 Bungres ORM CLI")} v${VERSION}
|
|
3399
4751
|
|
|
3400
|
-
${
|
|
4752
|
+
${import_picocolors12.default.yellow("Usage:")}
|
|
3401
4753
|
bungres <command> [options]
|
|
3402
4754
|
|
|
3403
|
-
${
|
|
4755
|
+
${import_picocolors12.default.yellow("Commands:")}
|
|
3404
4756
|
init Initialize bungres project with config file and db folder structure
|
|
3405
4757
|
generate Generate SQL migration files from your schema definitions
|
|
3406
4758
|
migrate Run pending migration files against the database
|
|
4759
|
+
rollback Revert the last applied migration
|
|
3407
4760
|
push Apply schema directly to the DB (no migration files, dev mode)
|
|
3408
4761
|
pull Introspect the database and generate TypeScript schema
|
|
3409
4762
|
status Show applied vs. pending migrations
|
|
@@ -3414,17 +4767,18 @@ ${colorize("Commands:", "yellow")}
|
|
|
3414
4767
|
tusky Boot up a Node REPL connected to the database with schema loaded
|
|
3415
4768
|
drop Drop all tables defined in the schema (dev only)
|
|
3416
4769
|
|
|
3417
|
-
${
|
|
4770
|
+
${import_picocolors12.default.yellow("Options:")}
|
|
3418
4771
|
--config Path to config file (default: bungres.config.ts)
|
|
3419
4772
|
--verbose Enable verbose SQL logging
|
|
3420
4773
|
--force Skip confirmation prompts (use with drop)
|
|
3421
4774
|
--version Show version
|
|
3422
4775
|
--help Show this help
|
|
3423
4776
|
|
|
3424
|
-
${
|
|
4777
|
+
${import_picocolors12.default.yellow("Examples:")}
|
|
3425
4778
|
bungres init
|
|
3426
4779
|
bungres generate
|
|
3427
4780
|
bungres migrate
|
|
4781
|
+
bungres rollback
|
|
3428
4782
|
bungres push
|
|
3429
4783
|
bungres pull
|
|
3430
4784
|
bungres status
|
|
@@ -3454,7 +4808,7 @@ async function main() {
|
|
|
3454
4808
|
const config2 = await loadConfig(process.cwd());
|
|
3455
4809
|
if (flags.verbose)
|
|
3456
4810
|
config2.verbose = true;
|
|
3457
|
-
if (command && ["migrate", "push", "drop", "status", "fresh", "refresh"].includes(command)) {
|
|
4811
|
+
if (command && ["migrate", "rollback", "push", "drop", "status", "fresh", "refresh"].includes(command)) {
|
|
3458
4812
|
await ensureDatabase2(config2.dbUrl);
|
|
3459
4813
|
}
|
|
3460
4814
|
switch (command) {
|
|
@@ -3464,6 +4818,9 @@ async function main() {
|
|
|
3464
4818
|
case "migrate":
|
|
3465
4819
|
await runMigrate(config2);
|
|
3466
4820
|
break;
|
|
4821
|
+
case "rollback":
|
|
4822
|
+
await runRollback(config2);
|
|
4823
|
+
break;
|
|
3467
4824
|
case "push":
|
|
3468
4825
|
await runPush(config2, { force: !!flags.force });
|
|
3469
4826
|
break;
|
|
@@ -3500,14 +4857,14 @@ async function main() {
|
|
|
3500
4857
|
}
|
|
3501
4858
|
function parseFlags(args) {
|
|
3502
4859
|
const flags = {};
|
|
3503
|
-
for (let
|
|
3504
|
-
const arg = args[
|
|
4860
|
+
for (let i2 = 0;i2 < args.length; i2++) {
|
|
4861
|
+
const arg = args[i2];
|
|
3505
4862
|
if (arg?.startsWith("--")) {
|
|
3506
4863
|
const key = arg.slice(2);
|
|
3507
|
-
const next = args[
|
|
4864
|
+
const next = args[i2 + 1];
|
|
3508
4865
|
if (next && !next.startsWith("--")) {
|
|
3509
4866
|
flags[key] = next;
|
|
3510
|
-
|
|
4867
|
+
i2++;
|
|
3511
4868
|
} else {
|
|
3512
4869
|
flags[key] = true;
|
|
3513
4870
|
}
|