dbcat 0.0.10 → 0.0.12
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 +5 -5
- package/package.json +1 -1
- package/src/index.ts +8 -3
- package/src/table.ts +80 -12
package/README.md
CHANGED
|
@@ -33,11 +33,11 @@ echo "SELECT * FROM users" | bunx dbcat ./data.db
|
|
|
33
33
|
|
|
34
34
|
### Options
|
|
35
35
|
|
|
36
|
-
| Flag | Description
|
|
37
|
-
|
|
38
|
-
| `--full`, `-f` | Show all rows when browsing tables (default: 100) |
|
|
39
|
-
| `--json` | Output as JSON (indented if TTY)
|
|
40
|
-
| `--json=color` | Output as normal object console.log
|
|
36
|
+
| Flag | Description |
|
|
37
|
+
|----------------|---------------------------------------------------------------|
|
|
38
|
+
| `--full`, `-f` | Show all rows & data when browsing tables (default: 100 rows) |
|
|
39
|
+
| `--json` | Output as JSON (indented if TTY) |
|
|
40
|
+
| `--json=color` | Output as normal object console.log |
|
|
41
41
|
|
|
42
42
|
Piped queries always return all rows.
|
|
43
43
|
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -137,7 +137,7 @@ function displayTable(
|
|
|
137
137
|
totalRows?: number,
|
|
138
138
|
maxRows?: number
|
|
139
139
|
) {
|
|
140
|
-
console.log();
|
|
140
|
+
console.log("");
|
|
141
141
|
printTable(rows, { title: tableName, totalRows, maxRows });
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -146,7 +146,7 @@ function displayQueryResult(rows: Record<string, unknown>[]) {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
async function readStdin(): Promise<string | null> {
|
|
149
|
-
if (process.stdin.isTTY
|
|
149
|
+
if (process.stdin.isTTY) {
|
|
150
150
|
return null;
|
|
151
151
|
}
|
|
152
152
|
|
|
@@ -194,6 +194,11 @@ function showUsageAndExit(): never {
|
|
|
194
194
|
console.error(" dbcat https://example.com/data.db");
|
|
195
195
|
console.error("");
|
|
196
196
|
console.error("Or set DATABASE_URL environment variable.");
|
|
197
|
+
console.error("");
|
|
198
|
+
console.error("Flags:");
|
|
199
|
+
console.error(" --full : Show the entire table and wrap cell values to fit column widths");
|
|
200
|
+
console.error(" --json : Output as JSON instead of a visual table");
|
|
201
|
+
console.error(" --help : Show this help message");
|
|
197
202
|
process.exit(1);
|
|
198
203
|
}
|
|
199
204
|
|
|
@@ -246,7 +251,7 @@ async function main() {
|
|
|
246
251
|
|
|
247
252
|
let sql: InstanceType<typeof Bun.SQL>;
|
|
248
253
|
try {
|
|
249
|
-
sql = createConnection(connectionInput, { readonly:
|
|
254
|
+
sql = createConnection(connectionInput, { readonly: process.stdin.isTTY });
|
|
250
255
|
} catch (error) {
|
|
251
256
|
console.error("Failed to connect:");
|
|
252
257
|
console.error(error instanceof Error ? error.message : String(error));
|
package/src/table.ts
CHANGED
|
@@ -76,6 +76,48 @@ export interface TableOptions {
|
|
|
76
76
|
totalRows?: number;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
function wrapLines(str: string, maxWidth: number): string[] {
|
|
80
|
+
// Split input into logical words, wrap to fit maxWidth
|
|
81
|
+
const raw = str.split(/\n/g).join(" ");
|
|
82
|
+
if (raw === "") return [""];
|
|
83
|
+
|
|
84
|
+
let lines: string[] = [];
|
|
85
|
+
let current = "";
|
|
86
|
+
|
|
87
|
+
const tokens = raw.split(/([ ]+)/);
|
|
88
|
+
for (const token of tokens) {
|
|
89
|
+
let fragment = token;
|
|
90
|
+
while (fragment.length > 0) {
|
|
91
|
+
const width = Bun.stringWidth(current + fragment);
|
|
92
|
+
if (width > maxWidth) {
|
|
93
|
+
if (current.length > 0) {
|
|
94
|
+
lines.push(current);
|
|
95
|
+
current = "";
|
|
96
|
+
} else {
|
|
97
|
+
let cutPoint = 1;
|
|
98
|
+
while (cutPoint < fragment.length && Bun.stringWidth(fragment.slice(0, cutPoint)) < maxWidth) {
|
|
99
|
+
cutPoint++;
|
|
100
|
+
}
|
|
101
|
+
lines.push(fragment.slice(0, cutPoint));
|
|
102
|
+
fragment = fragment.slice(cutPoint);
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
current += fragment;
|
|
106
|
+
fragment = "";
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (Bun.stringWidth(current) >= maxWidth) {
|
|
110
|
+
lines.push(current);
|
|
111
|
+
current = "";
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (current.length > 0) {
|
|
115
|
+
lines.push(current);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return lines;
|
|
119
|
+
}
|
|
120
|
+
|
|
79
121
|
export function printTable(
|
|
80
122
|
rows: Record<string, unknown>[],
|
|
81
123
|
options: TableOptions = {},
|
|
@@ -261,18 +303,44 @@ export function printTable(
|
|
|
261
303
|
`${dim}${BOX.headerLeft}${BOX.horizontal}${headerSep}${BOX.horizontal}${BOX.headerRight}${reset}`,
|
|
262
304
|
);
|
|
263
305
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
306
|
+
// If in --full mode, apply smart multiline rendering:
|
|
307
|
+
if (maxRows === Infinity) {
|
|
308
|
+
for (let rowIdx = 0; rowIdx < visibleFormattedRows.length; rowIdx++) {
|
|
309
|
+
const row = visibleFormattedRows[rowIdx] ?? [];
|
|
310
|
+
const wrapped = row.map((val, i) => wrapLines(val, visibleColWidths[i]!));
|
|
311
|
+
const rowHeight = Math.max(...wrapped.map(x => x.length));
|
|
312
|
+
for (let lineIdx = 0; lineIdx < rowHeight; lineIdx++) {
|
|
313
|
+
const pieces = wrapped.map((cellLines, i) => {
|
|
314
|
+
const part: string = typeof cellLines[lineIdx] === "string" ? cellLines[lineIdx]! : "";
|
|
315
|
+
return visibleIsNumeric[i]
|
|
316
|
+
? padLeft(truncate(part, visibleColWidths[i]!), visibleColWidths[i]!)
|
|
317
|
+
: padRight(truncate(part, visibleColWidths[i]!), visibleColWidths[i]!);
|
|
318
|
+
});
|
|
319
|
+
const line = pieces.join(` ${dim}${BOX.vertical}${reset} `);
|
|
320
|
+
console.log(`${dim}${BOX.vertical}${reset} ${line} ${dim}${BOX.vertical}${reset}`);
|
|
321
|
+
}
|
|
322
|
+
if (rowIdx < visibleFormattedRows.length - 1) {
|
|
323
|
+
const rowSep = visibleColWidths
|
|
324
|
+
.map((w) => BOX.horizontal.repeat(w))
|
|
325
|
+
.join(`${BOX.horizontal}${BOX.headerCross}${BOX.horizontal}`);
|
|
326
|
+
console.log(`${dim}${BOX.headerLeft}${BOX.horizontal}${rowSep}${BOX.horizontal}${BOX.headerRight}${reset}`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
} else {
|
|
330
|
+
// Legacy single-line row rendering
|
|
331
|
+
for (const row of visibleFormattedRows) {
|
|
332
|
+
const line = row
|
|
333
|
+
.map((val, i) => {
|
|
334
|
+
const truncated = truncate(val, visibleColWidths[i]!);
|
|
335
|
+
return visibleIsNumeric[i]
|
|
336
|
+
? padLeft(truncated, visibleColWidths[i]!)
|
|
337
|
+
: padRight(truncated, visibleColWidths[i]!);
|
|
338
|
+
})
|
|
339
|
+
.join(` ${dim}${BOX.vertical}${reset} `);
|
|
340
|
+
console.log(
|
|
341
|
+
`${dim}${BOX.vertical}${reset} ${line} ${dim}${BOX.vertical}${reset}`,
|
|
342
|
+
);
|
|
343
|
+
}
|
|
276
344
|
}
|
|
277
345
|
|
|
278
346
|
if (infoText) {
|