dbcat 0.0.2 → 0.0.3
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 +8 -0
- package/package.json +1 -1
- package/src/index.ts +23 -83
- package/src/table.ts +2 -5
package/README.md
CHANGED
|
@@ -56,6 +56,14 @@ Connected to demo.sqlite
|
|
|
56
56
|
╰──────────────────────────────────────────────────────────────╯
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
+
### Scrollable Output
|
|
60
|
+
|
|
61
|
+
Pipe to `less -R` for scrollable output with colors:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
bunx dbcat ./data.db --full | less -R
|
|
65
|
+
```
|
|
66
|
+
|
|
59
67
|
## Requirements
|
|
60
68
|
|
|
61
69
|
[Bun](https://bun.sh) v1.3+
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
-
import { SQL } from "bun";
|
|
4
|
-
import { printTable } from "./table.ts";
|
|
5
|
-
|
|
6
3
|
if (typeof Bun !== "object") throw new Error("Please install & use bun!");
|
|
7
4
|
|
|
8
|
-
|
|
5
|
+
import { printTable } from "./table.ts";
|
|
6
|
+
|
|
7
|
+
export function createConnection(input?: string): InstanceType<typeof Bun.SQL> {
|
|
9
8
|
if (!input) {
|
|
10
|
-
return new SQL();
|
|
9
|
+
return new Bun.SQL();
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
if (
|
|
@@ -16,14 +15,14 @@ export function createConnection(input?: string): InstanceType<typeof SQL> {
|
|
|
16
15
|
input.endsWith(".sqlite") ||
|
|
17
16
|
input.endsWith(".sqlite3"))
|
|
18
17
|
) {
|
|
19
|
-
return new SQL(`sqlite://${input}`);
|
|
18
|
+
return new Bun.SQL(`sqlite://${input}`);
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
return new SQL(input);
|
|
21
|
+
return new Bun.SQL(input);
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
export async function getDatabaseName(
|
|
26
|
-
sql: InstanceType<typeof SQL>
|
|
25
|
+
sql: InstanceType<typeof Bun.SQL>
|
|
27
26
|
): Promise<string | null> {
|
|
28
27
|
const adapter = sql.options.adapter;
|
|
29
28
|
|
|
@@ -38,17 +37,17 @@ export async function getDatabaseName(
|
|
|
38
37
|
return result[0]?.name ?? null;
|
|
39
38
|
}
|
|
40
39
|
case "sqlite": {
|
|
41
|
-
const filename =
|
|
40
|
+
const filename = sql.options.filename;
|
|
42
41
|
if (!filename || filename === ":memory:") return null;
|
|
43
42
|
|
|
44
|
-
return filename.split("/").
|
|
43
|
+
return filename.toString().split("/").at(-1) ?? null;
|
|
45
44
|
}
|
|
46
45
|
default:
|
|
47
46
|
return null;
|
|
48
47
|
}
|
|
49
48
|
}
|
|
50
49
|
|
|
51
|
-
export function getAllTables(sql: InstanceType<typeof SQL>) {
|
|
50
|
+
export function getAllTables(sql: InstanceType<typeof Bun.SQL>) {
|
|
52
51
|
const adapter = sql.options.adapter;
|
|
53
52
|
|
|
54
53
|
switch (adapter) {
|
|
@@ -83,7 +82,7 @@ export function getAllTables(sql: InstanceType<typeof SQL>) {
|
|
|
83
82
|
}
|
|
84
83
|
|
|
85
84
|
export async function getTableCount(
|
|
86
|
-
sql: InstanceType<typeof SQL>,
|
|
85
|
+
sql: InstanceType<typeof Bun.SQL>,
|
|
87
86
|
tableName: string
|
|
88
87
|
): Promise<number> {
|
|
89
88
|
const result = await sql`SELECT COUNT(*) as count FROM ${sql(tableName)}`;
|
|
@@ -91,72 +90,20 @@ export async function getTableCount(
|
|
|
91
90
|
}
|
|
92
91
|
|
|
93
92
|
export function getTableData(
|
|
94
|
-
sql: InstanceType<typeof SQL>,
|
|
93
|
+
sql: InstanceType<typeof Bun.SQL>,
|
|
95
94
|
tableName: string,
|
|
96
95
|
limit?: number
|
|
97
|
-
) {
|
|
96
|
+
): Promise<Record<string, unknown>[]> {
|
|
98
97
|
if (limit === undefined) {
|
|
99
|
-
return sql`SELECT * FROM ${sql(tableName)}
|
|
100
|
-
Record<string, unknown>[]
|
|
101
|
-
>;
|
|
98
|
+
return sql`SELECT * FROM ${sql(tableName)}`;
|
|
102
99
|
}
|
|
103
|
-
return sql`SELECT * FROM ${sql(tableName)} LIMIT ${limit}
|
|
104
|
-
Record<string, unknown>[]
|
|
105
|
-
>;
|
|
100
|
+
return sql`SELECT * FROM ${sql(tableName)} LIMIT ${limit}`;
|
|
106
101
|
}
|
|
107
102
|
|
|
108
|
-
export function runQuery(sql: InstanceType<typeof SQL>, query: string) {
|
|
103
|
+
export function runQuery(sql: InstanceType<typeof Bun.SQL>, query: string) {
|
|
109
104
|
return sql.unsafe(query) as Promise<Record<string, unknown>[]>;
|
|
110
105
|
}
|
|
111
106
|
|
|
112
|
-
export function formatTableOutput(
|
|
113
|
-
tableName: string,
|
|
114
|
-
rows: Record<string, unknown>[]
|
|
115
|
-
): string {
|
|
116
|
-
const lines: string[] = [];
|
|
117
|
-
lines.push(`\n=== ${tableName} ===`);
|
|
118
|
-
|
|
119
|
-
if (rows.length === 0) {
|
|
120
|
-
lines.push("(empty table)");
|
|
121
|
-
return lines.join("\n");
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const maxRows = 100;
|
|
125
|
-
const displayRows = rows.slice(0, maxRows);
|
|
126
|
-
|
|
127
|
-
if (displayRows.length > 0) {
|
|
128
|
-
const keys = Object.keys(displayRows[0]!);
|
|
129
|
-
lines.push(keys.join(" | "));
|
|
130
|
-
lines.push("-".repeat(keys.join(" | ").length));
|
|
131
|
-
for (const row of displayRows) {
|
|
132
|
-
lines.push(keys.map((k) => String(row[k] ?? "NULL")).join(" | "));
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (rows.length > maxRows) {
|
|
137
|
-
lines.push(`... and ${rows.length - maxRows} more rows`);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return lines.join("\n");
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export function formatQueryResult(rows: Record<string, unknown>[]): string {
|
|
144
|
-
if (rows.length === 0) {
|
|
145
|
-
return "(no results)";
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const lines: string[] = [];
|
|
149
|
-
const keys = Object.keys(rows[0]!);
|
|
150
|
-
lines.push(keys.join(" | "));
|
|
151
|
-
lines.push("-".repeat(keys.join(" | ").length));
|
|
152
|
-
for (const row of rows) {
|
|
153
|
-
lines.push(keys.map((k) => String(row[k] ?? "NULL")).join(" | "));
|
|
154
|
-
}
|
|
155
|
-
lines.push(`\n${rows.length} row(s)`);
|
|
156
|
-
|
|
157
|
-
return lines.join("\n");
|
|
158
|
-
}
|
|
159
|
-
|
|
160
107
|
function displayTable(
|
|
161
108
|
tableName: string,
|
|
162
109
|
rows: Record<string, unknown>[],
|
|
@@ -184,13 +131,11 @@ async function readStdin(): Promise<string | null> {
|
|
|
184
131
|
}
|
|
185
132
|
}
|
|
186
133
|
|
|
187
|
-
type JsonMode = false | "plain" | "color";
|
|
188
|
-
|
|
189
134
|
function parseArgs() {
|
|
190
135
|
const args = process.argv.slice(2);
|
|
191
136
|
let input: string | undefined;
|
|
192
137
|
let full = false;
|
|
193
|
-
let json:
|
|
138
|
+
let json: false | "plain" | "color" = false;
|
|
194
139
|
|
|
195
140
|
for (const arg of args) {
|
|
196
141
|
if (arg === "--full" || arg === "-f") {
|
|
@@ -237,7 +182,7 @@ async function main() {
|
|
|
237
182
|
showUsageAndExit();
|
|
238
183
|
}
|
|
239
184
|
|
|
240
|
-
let sql: InstanceType<typeof SQL>;
|
|
185
|
+
let sql: InstanceType<typeof Bun.SQL>;
|
|
241
186
|
try {
|
|
242
187
|
sql = createConnection(input);
|
|
243
188
|
} catch (error) {
|
|
@@ -250,7 +195,7 @@ async function main() {
|
|
|
250
195
|
const dim = Bun.enableANSIColors ? "\x1b[2m" : "";
|
|
251
196
|
const reset = Bun.enableANSIColors ? "\x1b[0m" : "";
|
|
252
197
|
const bold = Bun.enableANSIColors ? "\x1b[1m" : "";
|
|
253
|
-
const clearLine = "\x1b[2K\r";
|
|
198
|
+
const clearLine = Bun.enableANSIColors ? "\x1b[2K\r" : "";
|
|
254
199
|
|
|
255
200
|
try {
|
|
256
201
|
const stdinQuery = await readStdin();
|
|
@@ -263,7 +208,7 @@ async function main() {
|
|
|
263
208
|
displayQueryResult(results);
|
|
264
209
|
}
|
|
265
210
|
} else {
|
|
266
|
-
if (isTTY && !json) {
|
|
211
|
+
if (Bun.enableANSIColors && isTTY && !json) {
|
|
267
212
|
process.stdout.write(
|
|
268
213
|
`${dim}Connecting to ${sql.options.adapter}...${reset}`
|
|
269
214
|
);
|
|
@@ -284,16 +229,11 @@ async function main() {
|
|
|
284
229
|
}
|
|
285
230
|
outputJson(result, json === "color");
|
|
286
231
|
} else {
|
|
232
|
+
if (Bun.enableANSIColors && isTTY) process.stdout.write(clearLine);
|
|
287
233
|
const dbDisplay = dbName
|
|
288
234
|
? `${bold}${dbName}${reset}`
|
|
289
235
|
: `${bold}${sql.options.adapter}${reset} ${dim}database${reset}`;
|
|
290
|
-
|
|
291
|
-
process.stdout.write(
|
|
292
|
-
`${clearLine}${dim}Connected to${reset} ${dbDisplay}\n`
|
|
293
|
-
);
|
|
294
|
-
} else {
|
|
295
|
-
console.log(`Connected to ${dbName || sql.options.adapter}`);
|
|
296
|
-
}
|
|
236
|
+
console.log(`${dim}Connected to${reset} ${dbDisplay}`);
|
|
297
237
|
|
|
298
238
|
if (tables.length === 0) {
|
|
299
239
|
console.log(`${dim}No tables found.${reset}`);
|
|
@@ -314,7 +254,7 @@ async function main() {
|
|
|
314
254
|
}
|
|
315
255
|
}
|
|
316
256
|
} catch (error) {
|
|
317
|
-
if (isTTY && !json) {
|
|
257
|
+
if (Bun.enableANSIColors && isTTY && !json) {
|
|
318
258
|
process.stdout.write(clearLine);
|
|
319
259
|
}
|
|
320
260
|
const message = error instanceof Error ? error.message : String(error);
|
package/src/table.ts
CHANGED
|
@@ -17,7 +17,7 @@ const BOX = {
|
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
function getTerminalWidth(): number {
|
|
20
|
-
return process.stdout.columns || 120;
|
|
20
|
+
return process.stdout.columns || process.stderr.columns || 120;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
function formatValue(value: unknown): string {
|
|
@@ -87,10 +87,7 @@ export function printTable(
|
|
|
87
87
|
|
|
88
88
|
if (rows.length === 0) {
|
|
89
89
|
if (title) {
|
|
90
|
-
const contentWidth = Math.max(
|
|
91
|
-
Bun.stringWidth("(empty)"),
|
|
92
|
-
Bun.stringWidth(title)
|
|
93
|
-
);
|
|
90
|
+
const contentWidth = Math.max("(empty)".length, Bun.stringWidth(title));
|
|
94
91
|
const innerWidth = contentWidth + 2;
|
|
95
92
|
const titleDisplay = ` ${title} `;
|
|
96
93
|
const titleWidth = Bun.stringWidth(titleDisplay);
|