adb-sqlite-viewer 1.0.5 → 1.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 +52 -117
- package/bridge/package.json +13 -0
- package/cli/ensure-adb.cjs +150 -0
- package/cli/server.cjs +7 -6
- package/electron/main.cjs +9 -0
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -1,151 +1,86 @@
|
|
|
1
|
-
# SQLite DevTools
|
|
1
|
+
# ADB SQLite DevTools
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Inspect SQLite databases on Android devices. Browse tables, view schemas, and run SQL queries — all from your browser.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Quick Start (npm)
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
**Requirements:**
|
|
12
|
-
- Windows (NSIS installer)
|
|
13
|
-
- `adb` on your PATH (Android SDK Platform-Tools)
|
|
14
|
-
- Android device with USB debugging enabled
|
|
15
|
-
|
|
16
|
-
### Option 2: Hosted Version + ADB Bridge (Best for React Native Developers)
|
|
7
|
+
```bash
|
|
8
|
+
npm install --save-dev adb-sqlite-viewer
|
|
9
|
+
npx sqlite-viewer
|
|
10
|
+
```
|
|
17
11
|
|
|
18
|
-
|
|
12
|
+
Opens a local server at `http://127.0.0.1:8085` with the full UI and ADB bridge built in. One command, no extra downloads.
|
|
19
13
|
|
|
20
|
-
|
|
14
|
+
```bash
|
|
15
|
+
# Custom port
|
|
16
|
+
npx sqlite-viewer --port 3000
|
|
17
|
+
```
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
cd bridge
|
|
25
|
-
npm install
|
|
26
|
-
npm run build # produces adb-bridge.exe
|
|
27
|
-
```
|
|
19
|
+
**Requirements:** `adb` on your PATH ([Android SDK Platform-Tools](https://developer.android.com/tools/releases/platform-tools)) and a USB-connected Android device with debugging enabled.
|
|
28
20
|
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
# Either run the exe directly:
|
|
32
|
-
adb-bridge.exe
|
|
21
|
+
## All Options
|
|
33
22
|
|
|
34
|
-
|
|
35
|
-
cd bridge && node server.js
|
|
36
|
-
```
|
|
23
|
+
### npm Package (Recommended for dev workflows)
|
|
37
24
|
|
|
38
|
-
|
|
25
|
+
Install into any project and run alongside your app:
|
|
39
26
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
Hosted website (HTTPS) ──HTTP──> localhost:15555 (bridge) ──> adb shell ──> Device
|
|
27
|
+
```bash
|
|
28
|
+
npm install --save-dev adb-sqlite-viewer
|
|
43
29
|
```
|
|
44
|
-
The website detects the bridge on startup and routes all commands through HTTP instead of WebUSB. No need to kill ADB.
|
|
45
|
-
|
|
46
|
-
### Option 3: Hosted Version with WebUSB (No Setup Required)
|
|
47
30
|
|
|
48
|
-
|
|
31
|
+
Add to your `package.json` scripts:
|
|
49
32
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
-
|
|
54
|
-
|
|
55
|
-
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"scripts": {
|
|
36
|
+
"sqlite-viewer": "sqlite-viewer"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
56
40
|
|
|
57
|
-
|
|
41
|
+
Then `npm run sqlite-viewer` opens the viewer. Works great alongside React Native, Flutter, or any Android project.
|
|
58
42
|
|
|
59
|
-
|
|
60
|
-
1. Run `adb kill-server` in your terminal
|
|
61
|
-
2. Open the hosted URL in Chrome/Edge
|
|
62
|
-
3. Click **Connect Device** and select your phone from the USB picker
|
|
63
|
-
4. Approve the USB debugging prompt on your phone (first time only)
|
|
64
|
-
5. Select a package and database, then start querying
|
|
43
|
+
### Desktop App
|
|
65
44
|
|
|
66
|
-
|
|
45
|
+
Download the Windows installer from [Releases](https://github.com/amitwinit/SQLite-DevTools-Mobile-ReactNative/releases). Double-click to launch — the bridge server starts automatically.
|
|
67
46
|
|
|
68
|
-
|
|
47
|
+
### Hosted Version + ADB Bridge
|
|
69
48
|
|
|
70
|
-
**
|
|
49
|
+
Use the deployed version at **[amitwinit.github.io/SQLite-DevTools-Mobile-ReactNative](https://amitwinit.github.io/SQLite-DevTools-Mobile-ReactNative/)** together with the standalone ADB Bridge.
|
|
71
50
|
|
|
72
|
-
1.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
```
|
|
51
|
+
1. Download `adb-bridge.exe` from [Releases](https://github.com/amitwinit/SQLite-DevTools-Mobile-ReactNative/releases)
|
|
52
|
+
2. Run `adb-bridge.exe`
|
|
53
|
+
3. Open the hosted website — it auto-detects the bridge
|
|
76
54
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
```
|
|
55
|
+
```
|
|
56
|
+
Website (HTTPS) ──HTTP──> localhost:15555 (bridge) ──> adb shell ──> Device
|
|
57
|
+
```
|
|
81
58
|
|
|
82
|
-
|
|
83
|
-
- `DEVICE_SERIAL` — run `adb devices` to find it
|
|
84
|
-
- `PACKAGE_NAME` — your app's package name
|
|
85
|
-
- `DB_NAME` — the SQLite database filename
|
|
86
|
-
- `PYTHON_TOOLS_PATH` — path to the python_tools directory
|
|
59
|
+
### Hosted Version with WebUSB (No install required)
|
|
87
60
|
|
|
88
|
-
|
|
89
|
-
```bash
|
|
90
|
-
python app.py
|
|
91
|
-
```
|
|
61
|
+
Open **[amitwinit.github.io/SQLite-DevTools-Mobile-ReactNative](https://amitwinit.github.io/SQLite-DevTools-Mobile-ReactNative/)** in Chrome/Edge. Uses WebUSB to talk directly to the device — no server needed.
|
|
92
62
|
|
|
93
|
-
|
|
63
|
+
**Note:** Requires `adb kill-server` first (WebUSB and ADB can't share the USB interface). Not suitable when you need ADB running for development.
|
|
94
64
|
|
|
95
65
|
## When to Use Which
|
|
96
66
|
|
|
97
|
-
| Scenario |
|
|
98
|
-
|
|
99
|
-
|
|
|
100
|
-
|
|
|
101
|
-
|
|
|
102
|
-
|
|
|
103
|
-
| Need ADB for other tools simultaneously | Desktop App (Option 1) or ADB Bridge (Option 2) |
|
|
104
|
-
|
|
105
|
-
## Environment Variables (Option 4)
|
|
106
|
-
|
|
107
|
-
### Application Configuration
|
|
108
|
-
- `PACKAGE_NAME`: Android app package name
|
|
109
|
-
- `DB_NAME`: Database name on the device
|
|
110
|
-
- `DEVICE_SERIAL`: ADB device serial number
|
|
111
|
-
- `PYTHON_TOOLS_PATH`: Path to python_tools directory
|
|
112
|
-
|
|
113
|
-
### Flask Server Configuration
|
|
114
|
-
- `FLASK_HOST`: Flask server host (default: 0.0.0.0)
|
|
115
|
-
- `FLASK_PORT`: Flask server port (default: 5001)
|
|
116
|
-
- `FLASK_DEBUG`: Enable debug mode (default: True)
|
|
117
|
-
|
|
118
|
-
### Cache Configuration
|
|
119
|
-
- `USE_CACHE`: Enable database caching (default: True)
|
|
120
|
-
- `FORCE_LOCAL`: Force local database operations (default: False)
|
|
67
|
+
| Scenario | Recommended |
|
|
68
|
+
|----------|-------------|
|
|
69
|
+
| Active development (React Native, Flutter, etc.) | `npx sqlite-viewer` or Desktop App |
|
|
70
|
+
| Quick one-off DB inspection | WebUSB (hosted version) |
|
|
71
|
+
| CI or shared dev environment | `npx sqlite-viewer` |
|
|
72
|
+
| No Node.js installed | Desktop App or WebUSB |
|
|
121
73
|
|
|
122
74
|
## Development
|
|
123
75
|
|
|
124
|
-
To work on the WebUSB frontend:
|
|
125
|
-
|
|
126
76
|
```bash
|
|
127
77
|
npm install
|
|
128
|
-
npm run dev
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
```bash
|
|
134
|
-
npm run build
|
|
78
|
+
npm run dev # Vite dev server
|
|
79
|
+
npm run build # Build for GitHub Pages
|
|
80
|
+
npm run electron:dev # Build + launch Electron app
|
|
81
|
+
npm run electron:build # Build Electron installer
|
|
135
82
|
```
|
|
136
83
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
To run the Electron desktop app in development:
|
|
140
|
-
|
|
141
|
-
```bash
|
|
142
|
-
npm run electron:dev
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
To build the Electron installer:
|
|
146
|
-
|
|
147
|
-
```bash
|
|
148
|
-
npm run electron:build
|
|
149
|
-
```
|
|
84
|
+
## License
|
|
150
85
|
|
|
151
|
-
|
|
86
|
+
MIT
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "adb-bridge",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "Localhost HTTP bridge that wraps adb shell commands for the SQLite DevTools website",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "node server.js",
|
|
8
|
+
"build": "pkg server.js --target node20-win-x64 --output adb-bridge.exe"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"@yao-pkg/pkg": "^5.11.0"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { execFile } = require("child_process");
|
|
4
|
+
const https = require("https");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const os = require("os");
|
|
8
|
+
|
|
9
|
+
const CACHE_DIR = path.join(os.homedir(), ".adb-sqlite-viewer");
|
|
10
|
+
const PLATFORM_TOOLS_DIR = path.join(CACHE_DIR, "platform-tools");
|
|
11
|
+
|
|
12
|
+
const DOWNLOAD_URLS = {
|
|
13
|
+
win32: "https://dl.google.com/android/repository/platform-tools-latest-windows.zip",
|
|
14
|
+
darwin: "https://dl.google.com/android/repository/platform-tools-latest-darwin.zip",
|
|
15
|
+
linux: "https://dl.google.com/android/repository/platform-tools-latest-linux.zip",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const ADB_BIN = process.platform === "win32" ? "adb.exe" : "adb";
|
|
19
|
+
|
|
20
|
+
/** Check if adb works at the given path. Returns version string or null. */
|
|
21
|
+
function tryAdb(adbPath) {
|
|
22
|
+
return new Promise((resolve) => {
|
|
23
|
+
execFile(adbPath, ["version"], { timeout: 5000 }, (err, stdout) => {
|
|
24
|
+
if (err) return resolve(null);
|
|
25
|
+
resolve(stdout.split("\n")[0].trim());
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Download a file via HTTPS, following redirects. */
|
|
31
|
+
function download(url, dest) {
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
const file = fs.createWriteStream(dest);
|
|
34
|
+
const request = (u) => {
|
|
35
|
+
https.get(u, (res) => {
|
|
36
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
37
|
+
file.close();
|
|
38
|
+
request(res.headers.location);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (res.statusCode !== 200) {
|
|
42
|
+
file.close();
|
|
43
|
+
fs.unlinkSync(dest);
|
|
44
|
+
reject(new Error(`Download failed: HTTP ${res.statusCode}`));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const total = parseInt(res.headers["content-length"], 10) || 0;
|
|
48
|
+
let downloaded = 0;
|
|
49
|
+
res.on("data", (chunk) => {
|
|
50
|
+
downloaded += chunk.length;
|
|
51
|
+
if (total > 0) {
|
|
52
|
+
const pct = Math.round((downloaded / total) * 100);
|
|
53
|
+
process.stdout.write(`\r Downloading... ${pct}%`);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
res.pipe(file);
|
|
57
|
+
file.on("finish", () => {
|
|
58
|
+
file.close();
|
|
59
|
+
if (total > 0) process.stdout.write("\n");
|
|
60
|
+
resolve();
|
|
61
|
+
});
|
|
62
|
+
}).on("error", (err) => {
|
|
63
|
+
file.close();
|
|
64
|
+
fs.unlinkSync(dest);
|
|
65
|
+
reject(err);
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
request(url);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Extract a zip file using OS tools. */
|
|
73
|
+
function extractZip(zipPath, destDir) {
|
|
74
|
+
return new Promise((resolve, reject) => {
|
|
75
|
+
const cmd = process.platform === "win32"
|
|
76
|
+
? `tar -xf "${zipPath}" -C "${destDir}"`
|
|
77
|
+
: `unzip -q -o "${zipPath}" -d "${destDir}"`;
|
|
78
|
+
execFile(cmd.split(" ")[0], cmd.split(" ").slice(1), { shell: true, timeout: 60000 }, (err) => {
|
|
79
|
+
if (err) reject(new Error(`Extract failed: ${err.message}`));
|
|
80
|
+
else resolve();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Ensure adb is available. Checks PATH, then cached download, then downloads.
|
|
87
|
+
* Prepends the adb directory to process.env.PATH if needed.
|
|
88
|
+
* Returns the adb version string.
|
|
89
|
+
*/
|
|
90
|
+
async function ensureAdb() {
|
|
91
|
+
// 1. Check system PATH
|
|
92
|
+
const systemVersion = await tryAdb("adb");
|
|
93
|
+
if (systemVersion) {
|
|
94
|
+
return systemVersion;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 2. Check cached download
|
|
98
|
+
const cachedAdb = path.join(PLATFORM_TOOLS_DIR, ADB_BIN);
|
|
99
|
+
if (fs.existsSync(cachedAdb)) {
|
|
100
|
+
const cachedVersion = await tryAdb(cachedAdb);
|
|
101
|
+
if (cachedVersion) {
|
|
102
|
+
prependToPath(PLATFORM_TOOLS_DIR);
|
|
103
|
+
return cachedVersion;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 3. Download from Google
|
|
108
|
+
const url = DOWNLOAD_URLS[process.platform];
|
|
109
|
+
if (!url) {
|
|
110
|
+
throw new Error(`Unsupported platform: ${process.platform}. Install adb manually.`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
console.log(" adb not found. Downloading Android Platform-Tools...");
|
|
114
|
+
|
|
115
|
+
fs.mkdirSync(CACHE_DIR, { recursive: true });
|
|
116
|
+
const zipPath = path.join(CACHE_DIR, "platform-tools.zip");
|
|
117
|
+
|
|
118
|
+
await download(url, zipPath);
|
|
119
|
+
console.log(" Extracting...");
|
|
120
|
+
await extractZip(zipPath, CACHE_DIR);
|
|
121
|
+
|
|
122
|
+
// Clean up zip
|
|
123
|
+
try { fs.unlinkSync(zipPath); } catch {}
|
|
124
|
+
|
|
125
|
+
// Verify
|
|
126
|
+
if (!fs.existsSync(cachedAdb)) {
|
|
127
|
+
throw new Error("Download succeeded but adb binary not found in extracted files.");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Make executable on Unix
|
|
131
|
+
if (process.platform !== "win32") {
|
|
132
|
+
fs.chmodSync(cachedAdb, 0o755);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const version = await tryAdb(cachedAdb);
|
|
136
|
+
if (!version) {
|
|
137
|
+
throw new Error("Downloaded adb binary is not working.");
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
prependToPath(PLATFORM_TOOLS_DIR);
|
|
141
|
+
console.log(` Downloaded: ${version}`);
|
|
142
|
+
return version;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function prependToPath(dir) {
|
|
146
|
+
const sep = process.platform === "win32" ? ";" : ":";
|
|
147
|
+
process.env.PATH = dir + sep + (process.env.PATH || "");
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
module.exports = { ensureAdb };
|
package/cli/server.cjs
CHANGED
|
@@ -4,7 +4,8 @@ const http = require("http");
|
|
|
4
4
|
const path = require("path");
|
|
5
5
|
const fs = require("fs");
|
|
6
6
|
const { exec } = require("child_process");
|
|
7
|
-
const { handleRequest: bridgeHandler
|
|
7
|
+
const { handleRequest: bridgeHandler } = require("../bridge/server.js");
|
|
8
|
+
const { ensureAdb } = require("./ensure-adb.cjs");
|
|
8
9
|
|
|
9
10
|
const DIST_DIR = path.join(__dirname, "..", "dist");
|
|
10
11
|
|
|
@@ -86,13 +87,13 @@ async function start(port) {
|
|
|
86
87
|
process.exit(1);
|
|
87
88
|
}
|
|
88
89
|
|
|
89
|
-
//
|
|
90
|
+
// Ensure adb is available (downloads if needed)
|
|
90
91
|
try {
|
|
91
|
-
const version = await
|
|
92
|
-
console.log(`
|
|
92
|
+
const version = await ensureAdb();
|
|
93
|
+
console.log(` adb: ${version}`);
|
|
93
94
|
} catch (err) {
|
|
94
|
-
console.warn(`WARNING: ${err.message}`);
|
|
95
|
-
console.warn("ADB bridge features will not work.");
|
|
95
|
+
console.warn(` WARNING: ${err.message}`);
|
|
96
|
+
console.warn(" ADB bridge features will not work.");
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
const server = http.createServer(requestHandler);
|
package/electron/main.cjs
CHANGED
|
@@ -5,6 +5,14 @@ const path = require("path");
|
|
|
5
5
|
let bridge = null;
|
|
6
6
|
let mainWindow = null;
|
|
7
7
|
|
|
8
|
+
function setupBundledAdb() {
|
|
9
|
+
if (app.isPackaged) {
|
|
10
|
+
const toolsDir = path.join(process.resourcesPath, "tools");
|
|
11
|
+
const sep = process.platform === "win32" ? ";" : ":";
|
|
12
|
+
process.env.PATH = toolsDir + sep + (process.env.PATH || "");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
8
16
|
function getBridgePath() {
|
|
9
17
|
if (app.isPackaged) {
|
|
10
18
|
return path.join(process.resourcesPath, "bridge", "server.js");
|
|
@@ -73,6 +81,7 @@ function createWindow() {
|
|
|
73
81
|
}
|
|
74
82
|
|
|
75
83
|
app.whenReady().then(async () => {
|
|
84
|
+
setupBundledAdb();
|
|
76
85
|
try {
|
|
77
86
|
console.log("Starting ADB bridge server...");
|
|
78
87
|
await startBridge();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adb-sqlite-viewer",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "ADB SQLite database viewer for Android — inspect tables, schemas, and run queries on-device",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "electron/main.cjs",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"files": [
|
|
11
11
|
"cli/",
|
|
12
12
|
"bridge/server.js",
|
|
13
|
+
"bridge/package.json",
|
|
13
14
|
"dist/"
|
|
14
15
|
],
|
|
15
16
|
"scripts": {
|
|
@@ -66,6 +67,10 @@
|
|
|
66
67
|
{
|
|
67
68
|
"from": "bridge/package.json",
|
|
68
69
|
"to": "bridge/package.json"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"from": "tools/",
|
|
73
|
+
"to": "tools/"
|
|
69
74
|
}
|
|
70
75
|
],
|
|
71
76
|
"win": {
|