dbcat 0.0.11 → 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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbcat",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "description": "A simple CLI to view database tables. Supports PostgreSQL, MySQL, and SQLite.",
5
5
  "author": "RiskyMH",
6
6
  "license": "MIT",
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
 
@@ -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
 
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
- for (const row of visibleFormattedRows) {
265
- const line = row
266
- .map((val, i) => {
267
- const truncated = truncate(val, visibleColWidths[i]!);
268
- return visibleIsNumeric[i]
269
- ? padLeft(truncated, visibleColWidths[i]!)
270
- : padRight(truncated, visibleColWidths[i]!);
271
- })
272
- .join(` ${dim}${BOX.vertical}${reset} `);
273
- console.log(
274
- `${dim}${BOX.vertical}${reset} ${line} ${dim}${BOX.vertical}${reset}`,
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) {