dbcat 0.0.7 → 0.0.9
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/package.json +2 -2
- package/src/index.ts +11 -6
- package/src/table.ts +26 -24
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dbcat",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "A simple CLI to view database tables. Supports PostgreSQL, MySQL, and SQLite.",
|
|
5
5
|
"author": "RiskyMH",
|
|
6
6
|
"license": "MIT",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"url": "https://github.com/RiskyMH/dbcat/issues"
|
|
14
14
|
},
|
|
15
15
|
"engines": {
|
|
16
|
-
"bun": ">=1.
|
|
16
|
+
"bun": ">=1.3.0"
|
|
17
17
|
},
|
|
18
18
|
"sideEffects": false,
|
|
19
19
|
"keywords": [
|
package/src/index.ts
CHANGED
|
@@ -9,19 +9,24 @@ import { join } from "node:path";
|
|
|
9
9
|
const SQLITE_EXTENSIONS = [".db", ".sqlite", ".sqlite3", ".db3", ".s3db"];
|
|
10
10
|
const REMOTE_PROTOCOLS = ["http://", "https://", "s3://"];
|
|
11
11
|
|
|
12
|
-
export function createConnection(
|
|
12
|
+
export function createConnection(
|
|
13
|
+
input?: string,
|
|
14
|
+
options?: { readonly?: boolean }
|
|
15
|
+
): InstanceType<typeof Bun.SQL> {
|
|
16
|
+
const opts = { readonly: true, ...options };
|
|
17
|
+
|
|
13
18
|
if (!input) {
|
|
14
|
-
return new Bun.SQL();
|
|
19
|
+
return new Bun.SQL(opts);
|
|
15
20
|
}
|
|
16
21
|
|
|
17
22
|
if (
|
|
18
23
|
!input.includes("://") &&
|
|
19
24
|
SQLITE_EXTENSIONS.some((ext) => input.endsWith(ext))
|
|
20
25
|
) {
|
|
21
|
-
return new Bun.SQL(`sqlite://${input}
|
|
26
|
+
return new Bun.SQL(`sqlite://${input}`, opts);
|
|
22
27
|
}
|
|
23
28
|
|
|
24
|
-
return new Bun.SQL(input);
|
|
29
|
+
return new Bun.SQL(input, opts);
|
|
25
30
|
}
|
|
26
31
|
|
|
27
32
|
async function downloadToTmp(url: string): Promise<string> {
|
|
@@ -141,7 +146,7 @@ function displayQueryResult(rows: Record<string, unknown>[]) {
|
|
|
141
146
|
}
|
|
142
147
|
|
|
143
148
|
async function readStdin(): Promise<string | null> {
|
|
144
|
-
if (process.stdin.isTTY) {
|
|
149
|
+
if (process.stdin.isTTY || Bun.stdin.size === 0) {
|
|
145
150
|
return null;
|
|
146
151
|
}
|
|
147
152
|
|
|
@@ -238,7 +243,7 @@ async function main() {
|
|
|
238
243
|
|
|
239
244
|
let sql: InstanceType<typeof Bun.SQL>;
|
|
240
245
|
try {
|
|
241
|
-
sql = createConnection(connectionInput);
|
|
246
|
+
sql = createConnection(connectionInput, { readonly: Bun.stdin.size == 0 });
|
|
242
247
|
} catch (error) {
|
|
243
248
|
console.error("Failed to connect:");
|
|
244
249
|
console.error(error instanceof Error ? error.message : String(error));
|
package/src/table.ts
CHANGED
|
@@ -78,7 +78,7 @@ export interface TableOptions {
|
|
|
78
78
|
|
|
79
79
|
export function printTable(
|
|
80
80
|
rows: Record<string, unknown>[],
|
|
81
|
-
options: TableOptions = {}
|
|
81
|
+
options: TableOptions = {},
|
|
82
82
|
): void {
|
|
83
83
|
const { maxRows = 100, title, totalRows } = options;
|
|
84
84
|
const dim = Bun.enableANSIColors ? DIM : "";
|
|
@@ -87,28 +87,30 @@ export function printTable(
|
|
|
87
87
|
|
|
88
88
|
if (rows.length === 0) {
|
|
89
89
|
if (title) {
|
|
90
|
-
const
|
|
91
|
-
const
|
|
90
|
+
const emptyText = "(empty)";
|
|
91
|
+
const contentWidth = Math.max(
|
|
92
|
+
Bun.stringWidth(emptyText),
|
|
93
|
+
Bun.stringWidth(title),
|
|
94
|
+
);
|
|
92
95
|
const titleDisplay = ` ${title} `;
|
|
93
96
|
const titleWidth = Bun.stringWidth(titleDisplay);
|
|
94
|
-
const
|
|
97
|
+
const innerWidth = contentWidth + 2;
|
|
98
|
+
const remainingWidth = innerWidth - titleWidth - 1;
|
|
95
99
|
console.log(
|
|
96
|
-
`${dim}${BOX.topLeft}${
|
|
97
|
-
|
|
98
|
-
}${
|
|
99
|
-
Math.max(0, remainingWidth)
|
|
100
|
-
)}${BOX.topRight}${reset}`
|
|
100
|
+
`${dim}${BOX.topLeft}${BOX.horizontal}${reset}${bold}${titleDisplay}${reset}${dim}${BOX.horizontal.repeat(
|
|
101
|
+
Math.max(0, remainingWidth),
|
|
102
|
+
)}${BOX.topRight}${reset}`,
|
|
101
103
|
);
|
|
102
104
|
console.log(
|
|
103
105
|
`${dim}${BOX.vertical}${reset} ${padRight(
|
|
104
|
-
|
|
105
|
-
contentWidth
|
|
106
|
-
)} ${dim}${BOX.vertical}${reset}
|
|
106
|
+
emptyText,
|
|
107
|
+
contentWidth,
|
|
108
|
+
)} ${dim}${BOX.vertical}${reset}`,
|
|
107
109
|
);
|
|
108
110
|
console.log(
|
|
109
111
|
`${dim}${BOX.bottomLeft}${BOX.horizontal.repeat(innerWidth)}${
|
|
110
112
|
BOX.bottomRight
|
|
111
|
-
}${reset}
|
|
113
|
+
}${reset}`,
|
|
112
114
|
);
|
|
113
115
|
} else {
|
|
114
116
|
console.log("(empty)");
|
|
@@ -139,7 +141,7 @@ export function printTable(
|
|
|
139
141
|
const formatted = formatValue(row[col]).replace(/\n/g, " ");
|
|
140
142
|
colWidths[i] = Math.max(colWidths[i]!, Bun.stringWidth(formatted));
|
|
141
143
|
return formatted;
|
|
142
|
-
})
|
|
144
|
+
}),
|
|
143
145
|
);
|
|
144
146
|
|
|
145
147
|
const minColWidth = 3;
|
|
@@ -160,7 +162,7 @@ export function printTable(
|
|
|
160
162
|
|
|
161
163
|
const visibleColWidths = colWidths.slice(0, columns.length);
|
|
162
164
|
const visibleFormattedRows = formattedRows.map((row) =>
|
|
163
|
-
row.slice(0, columns.length)
|
|
165
|
+
row.slice(0, columns.length),
|
|
164
166
|
);
|
|
165
167
|
const visibleIsNumeric = isNumericCol.slice(0, columns.length);
|
|
166
168
|
|
|
@@ -168,14 +170,14 @@ export function printTable(
|
|
|
168
170
|
|
|
169
171
|
if (totalWidth > availableForColumns) {
|
|
170
172
|
const headerWidths = columns.map((col) =>
|
|
171
|
-
Math.max(minColWidth, Bun.stringWidth(col))
|
|
173
|
+
Math.max(minColWidth, Bun.stringWidth(col)),
|
|
172
174
|
);
|
|
173
175
|
const sqrtWidths = visibleColWidths.map((w) => Math.sqrt(w));
|
|
174
176
|
const sqrtTotal = sqrtWidths.reduce((a, b) => a + b, 0);
|
|
175
177
|
|
|
176
178
|
for (let i = 0; i < visibleColWidths.length; i++) {
|
|
177
179
|
const fair = Math.floor(
|
|
178
|
-
(sqrtWidths[i]! / sqrtTotal) * availableForColumns
|
|
180
|
+
(sqrtWidths[i]! / sqrtTotal) * availableForColumns,
|
|
179
181
|
);
|
|
180
182
|
visibleColWidths[i] = Math.max(headerWidths[i]!, fair);
|
|
181
183
|
}
|
|
@@ -214,7 +216,7 @@ export function printTable(
|
|
|
214
216
|
const maxInnerWidth = termWidth - 4;
|
|
215
217
|
const innerWidth = Math.min(
|
|
216
218
|
Math.max(contentWidth, titleWidth),
|
|
217
|
-
maxInnerWidth
|
|
219
|
+
maxInnerWidth,
|
|
218
220
|
);
|
|
219
221
|
|
|
220
222
|
const totalInnerWidth = innerWidth + 2;
|
|
@@ -234,7 +236,7 @@ export function printTable(
|
|
|
234
236
|
const beforeTitle = fullTopBorder.slice(0, 2);
|
|
235
237
|
const afterTitle = fullTopBorder.slice(2 + titleDisplayWidth);
|
|
236
238
|
console.log(
|
|
237
|
-
`${dim}${beforeTitle}${reset}${bold}${titleDisplay}${reset}${dim}${afterTitle}${reset}
|
|
239
|
+
`${dim}${beforeTitle}${reset}${bold}${titleDisplay}${reset}${dim}${afterTitle}${reset}`,
|
|
238
240
|
);
|
|
239
241
|
} else {
|
|
240
242
|
console.log(`${dim}${fullTopBorder}${reset}`);
|
|
@@ -249,14 +251,14 @@ export function printTable(
|
|
|
249
251
|
})
|
|
250
252
|
.join(` ${dim}${BOX.vertical}${reset} `);
|
|
251
253
|
console.log(
|
|
252
|
-
`${dim}${BOX.vertical}${reset} ${header} ${dim}${BOX.vertical}${reset}
|
|
254
|
+
`${dim}${BOX.vertical}${reset} ${header} ${dim}${BOX.vertical}${reset}`,
|
|
253
255
|
);
|
|
254
256
|
|
|
255
257
|
const headerSep = visibleColWidths
|
|
256
258
|
.map((w) => BOX.horizontal.repeat(w))
|
|
257
259
|
.join(`${BOX.horizontal}${BOX.headerCross}${BOX.horizontal}`);
|
|
258
260
|
console.log(
|
|
259
|
-
`${dim}${BOX.headerLeft}${BOX.horizontal}${headerSep}${BOX.horizontal}${BOX.headerRight}${reset}
|
|
261
|
+
`${dim}${BOX.headerLeft}${BOX.horizontal}${headerSep}${BOX.horizontal}${BOX.headerRight}${reset}`,
|
|
260
262
|
);
|
|
261
263
|
|
|
262
264
|
for (const row of visibleFormattedRows) {
|
|
@@ -269,7 +271,7 @@ export function printTable(
|
|
|
269
271
|
})
|
|
270
272
|
.join(` ${dim}${BOX.vertical}${reset} `);
|
|
271
273
|
console.log(
|
|
272
|
-
`${dim}${BOX.vertical}${reset} ${line} ${dim}${BOX.vertical}${reset}
|
|
274
|
+
`${dim}${BOX.vertical}${reset} ${line} ${dim}${BOX.vertical}${reset}`,
|
|
273
275
|
);
|
|
274
276
|
}
|
|
275
277
|
|
|
@@ -281,14 +283,14 @@ export function printTable(
|
|
|
281
283
|
console.log(
|
|
282
284
|
`${dim}${BOX.bottomLeft}${BOX.horizontal.repeat(totalInnerWidth)}${
|
|
283
285
|
BOX.bottomRight
|
|
284
|
-
}${reset}
|
|
286
|
+
}${reset}`,
|
|
285
287
|
);
|
|
286
288
|
} else {
|
|
287
289
|
const bottomBorder = visibleColWidths
|
|
288
290
|
.map((w) => BOX.horizontal.repeat(w))
|
|
289
291
|
.join(`${BOX.horizontal}${BOX.bottomCross}${BOX.horizontal}`);
|
|
290
292
|
console.log(
|
|
291
|
-
`${dim}${BOX.bottomLeft}${BOX.horizontal}${bottomBorder}${BOX.horizontal}${BOX.bottomRight}${reset}
|
|
293
|
+
`${dim}${BOX.bottomLeft}${BOX.horizontal}${bottomBorder}${BOX.horizontal}${BOX.bottomRight}${reset}`,
|
|
292
294
|
);
|
|
293
295
|
}
|
|
294
296
|
}
|