dbcat 0.0.4 → 0.0.6
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 +10 -9
- package/package.json +5 -1
- package/src/index.ts +56 -11
package/README.md
CHANGED
|
@@ -11,32 +11,33 @@ bunx dbcat ./data.db
|
|
|
11
11
|
Connect to a database to browse all tables:
|
|
12
12
|
|
|
13
13
|
```sh
|
|
14
|
-
#
|
|
14
|
+
# No argument - uses DATABASE_URL environment variable
|
|
15
|
+
bunx dbcat
|
|
16
|
+
|
|
17
|
+
# SQLite
|
|
15
18
|
bunx dbcat ./database.sqlite
|
|
19
|
+
bunx dbcat https://example.com/data.db
|
|
16
20
|
|
|
17
21
|
# PostgreSQL
|
|
18
22
|
bunx dbcat postgres://user:pass@localhost:5432/mydb
|
|
19
23
|
|
|
20
24
|
# MySQL
|
|
21
25
|
bunx dbcat mysql://user:pass@localhost:3306/mydb
|
|
22
|
-
|
|
23
|
-
# No argument - uses DATABASE_URL environment variable
|
|
24
|
-
bunx dbcat
|
|
25
26
|
```
|
|
26
27
|
|
|
27
28
|
Run a query by piping SQL:
|
|
28
29
|
|
|
29
30
|
```sh
|
|
30
|
-
echo "SELECT * FROM users
|
|
31
|
+
echo "SELECT * FROM users" | bunx dbcat ./data.db
|
|
31
32
|
```
|
|
32
33
|
|
|
33
34
|
### Options
|
|
34
35
|
|
|
35
|
-
| Flag
|
|
36
|
-
|
|
36
|
+
| Flag | Description |
|
|
37
|
+
|----------------|---------------------------------------------------|
|
|
37
38
|
| `--full`, `-f` | Show all rows when browsing tables (default: 100) |
|
|
38
|
-
| `--json`
|
|
39
|
-
| `--json=color` | Output as normal object console.log
|
|
39
|
+
| `--json` | Output as JSON (indented if TTY) |
|
|
40
|
+
| `--json=color` | Output as normal object console.log |
|
|
40
41
|
|
|
41
42
|
Piped queries always return all rows.
|
|
42
43
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dbcat",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "A simple CLI to view database tables. Supports PostgreSQL, MySQL, and SQLite.",
|
|
5
5
|
"author": "RiskyMH",
|
|
6
6
|
"license": "MIT",
|
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
"bugs": {
|
|
13
13
|
"url": "https://github.com/RiskyMH/dbcat/issues"
|
|
14
14
|
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"bun": ">=1.0.0"
|
|
17
|
+
},
|
|
18
|
+
"sideEffects": false,
|
|
15
19
|
"keywords": [
|
|
16
20
|
"database",
|
|
17
21
|
"cli",
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
if (typeof Bun !== "object") throw new Error("Please install & use bun!");
|
|
4
4
|
|
|
5
5
|
import { printTable } from "./table.ts";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
|
|
9
|
+
const SQLITE_EXTENSIONS = [".db", ".sqlite", ".sqlite3", ".db3", ".s3db"];
|
|
10
|
+
const REMOTE_PROTOCOLS = ["http://", "https://", "s3://"];
|
|
6
11
|
|
|
7
12
|
export function createConnection(input?: string): InstanceType<typeof Bun.SQL> {
|
|
8
13
|
if (!input) {
|
|
@@ -11,9 +16,7 @@ export function createConnection(input?: string): InstanceType<typeof Bun.SQL> {
|
|
|
11
16
|
|
|
12
17
|
if (
|
|
13
18
|
!input.includes("://") &&
|
|
14
|
-
(input.endsWith(
|
|
15
|
-
input.endsWith(".sqlite") ||
|
|
16
|
-
input.endsWith(".sqlite3"))
|
|
19
|
+
SQLITE_EXTENSIONS.some((ext) => input.endsWith(ext))
|
|
17
20
|
) {
|
|
18
21
|
return new Bun.SQL(`sqlite://${input}`);
|
|
19
22
|
}
|
|
@@ -21,6 +24,22 @@ export function createConnection(input?: string): InstanceType<typeof Bun.SQL> {
|
|
|
21
24
|
return new Bun.SQL(input);
|
|
22
25
|
}
|
|
23
26
|
|
|
27
|
+
async function downloadToTmp(url: string): Promise<string> {
|
|
28
|
+
const response = await fetch(url);
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
`Failed to download: ${response.status} ${response.statusText}`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const urlPath = new URL(url).pathname;
|
|
36
|
+
const filename = urlPath.split("/").at(-1) || "downloaded.db";
|
|
37
|
+
const tmpPath = join(tmpdir(), `dbcat-${Bun.hash(url)}-${filename}`);
|
|
38
|
+
await Bun.write(tmpPath, response);
|
|
39
|
+
|
|
40
|
+
return tmpPath;
|
|
41
|
+
}
|
|
42
|
+
|
|
24
43
|
export async function getDatabaseName(
|
|
25
44
|
sql: InstanceType<typeof Bun.SQL>
|
|
26
45
|
): Promise<string | null> {
|
|
@@ -164,6 +183,7 @@ function showUsageAndExit(): never {
|
|
|
164
183
|
console.error(" dbcat ./data.db");
|
|
165
184
|
console.error(" dbcat postgres://user:pass@localhost/mydb");
|
|
166
185
|
console.error(" dbcat mysql://user:pass@localhost/mydb");
|
|
186
|
+
console.error(" dbcat https://example.com/data.db");
|
|
167
187
|
console.error("");
|
|
168
188
|
console.error("Or set DATABASE_URL environment variable.");
|
|
169
189
|
process.exit(1);
|
|
@@ -185,21 +205,46 @@ async function main() {
|
|
|
185
205
|
showUsageAndExit();
|
|
186
206
|
}
|
|
187
207
|
|
|
208
|
+
const isTTY = process.stdout.isTTY;
|
|
209
|
+
const dim = Bun.enableANSIColors ? "\x1b[2m" : "";
|
|
210
|
+
const reset = Bun.enableANSIColors ? "\x1b[0m" : "";
|
|
211
|
+
const bold = Bun.enableANSIColors ? "\x1b[1m" : "";
|
|
212
|
+
const clearLine = Bun.enableANSIColors ? "\x1b[2K\r" : "";
|
|
213
|
+
|
|
214
|
+
// Handle remote URLs pointing to SQLite files
|
|
215
|
+
let connectionInput = input;
|
|
216
|
+
if (
|
|
217
|
+
input &&
|
|
218
|
+
REMOTE_PROTOCOLS.some((p) => input.startsWith(p)) &&
|
|
219
|
+
SQLITE_EXTENSIONS.some((ext) => input.endsWith(ext))
|
|
220
|
+
) {
|
|
221
|
+
if (Bun.enableANSIColors && isTTY && !json) {
|
|
222
|
+
process.stdout.write(`${dim}Downloading SQLite database...${reset}`);
|
|
223
|
+
}
|
|
224
|
+
try {
|
|
225
|
+
connectionInput = `sqlite://${await downloadToTmp(input)}`;
|
|
226
|
+
} catch (error) {
|
|
227
|
+
if (Bun.enableANSIColors && isTTY && !json) {
|
|
228
|
+
process.stdout.write("\n");
|
|
229
|
+
}
|
|
230
|
+
console.error("Failed to download:");
|
|
231
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
232
|
+
process.exit(1);
|
|
233
|
+
}
|
|
234
|
+
if (Bun.enableANSIColors && isTTY && !json) {
|
|
235
|
+
process.stdout.write(clearLine);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
188
239
|
let sql: InstanceType<typeof Bun.SQL>;
|
|
189
240
|
try {
|
|
190
|
-
sql = createConnection(
|
|
241
|
+
sql = createConnection(connectionInput);
|
|
191
242
|
} catch (error) {
|
|
192
243
|
console.error("Failed to connect:");
|
|
193
244
|
console.error(error instanceof Error ? error.message : String(error));
|
|
194
245
|
process.exit(1);
|
|
195
246
|
}
|
|
196
247
|
|
|
197
|
-
const isTTY = process.stdout.isTTY;
|
|
198
|
-
const dim = Bun.enableANSIColors ? "\x1b[2m" : "";
|
|
199
|
-
const reset = Bun.enableANSIColors ? "\x1b[0m" : "";
|
|
200
|
-
const bold = Bun.enableANSIColors ? "\x1b[1m" : "";
|
|
201
|
-
const clearLine = Bun.enableANSIColors ? "\x1b[2K\r" : "";
|
|
202
|
-
|
|
203
248
|
try {
|
|
204
249
|
const stdinQuery = await readStdin();
|
|
205
250
|
|
|
@@ -258,7 +303,7 @@ async function main() {
|
|
|
258
303
|
}
|
|
259
304
|
} catch (error) {
|
|
260
305
|
if (Bun.enableANSIColors && isTTY && !json) {
|
|
261
|
-
process.stdout.write(
|
|
306
|
+
process.stdout.write("\n");
|
|
262
307
|
}
|
|
263
308
|
const message = error instanceof Error ? error.message : String(error);
|
|
264
309
|
|