admindb 1.0.3 → 1.2.0
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 +151 -47
- package/dist/app.d.ts +12 -0
- package/dist/app.js +7 -0
- package/dist/app.js.map +1 -1
- package/dist/args.d.ts +28 -0
- package/dist/args.js +187 -0
- package/dist/args.js.map +1 -0
- package/dist/cli.js +85 -15
- package/dist/cli.js.map +1 -1
- package/dist/db/database.d.ts +58 -37
- package/dist/db/database.js +239 -42
- package/dist/db/database.js.map +1 -1
- package/dist/db/manager.d.ts +8 -2
- package/dist/db/manager.js +33 -1
- package/dist/db/manager.js.map +1 -1
- package/dist/public/css/app.css +1 -1
- package/dist/public/css/input.css +53 -0
- package/dist/public/js/browse.js +847 -86
- package/dist/public/js/databases.js +99 -1
- package/dist/routes/api.js +261 -97
- package/dist/routes/api.js.map +1 -1
- package/dist/routes/databases.d.ts +10 -0
- package/dist/routes/databases.js +97 -0
- package/dist/routes/databases.js.map +1 -1
- package/dist/routes/pages.js +50 -30
- package/dist/routes/pages.js.map +1 -1
- package/dist/sql/generator.d.ts +0 -22
- package/dist/sql/generator.js +0 -48
- package/dist/sql/generator.js.map +1 -1
- package/dist/test/database.test.js +241 -63
- package/dist/test/database.test.js.map +1 -1
- package/dist/test/generator.test.js +0 -32
- package/dist/test/generator.test.js.map +1 -1
- package/dist/util.d.ts +18 -1
- package/dist/util.js +37 -2
- package/dist/util.js.map +1 -1
- package/dist/views/layouts/main.hbs +1 -1
- package/dist/views/pages/databases.hbs +41 -0
- package/dist/views/pages/table.hbs +81 -28
- package/dist/views/partials/sidebar.hbs +0 -12
- package/package.json +1 -1
- package/dist/public/js/triggers.js +0 -155
- package/dist/public/js/views.js +0 -176
- package/dist/views/pages/triggers.hbs +0 -162
- package/dist/views/pages/views.hbs +0 -134
package/README.md
CHANGED
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
A browser-based SQLite database administration tool. Manage a SQLite database
|
|
12
|
-
entirely from the browser: browse tables
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
entirely from the browser: browse tables with full CRUD, inline
|
|
13
|
+
spreadsheet-style grid editing, type-aware filters, bulk row operations, a
|
|
14
|
+
visual table designer, an arbitrary SQL query runner, saved named queries,
|
|
15
|
+
SQL-dump export, a "generate SQL" preview mode that never executes, a schema
|
|
16
|
+
editor, and multi-database support.
|
|
16
17
|
|
|
17
18
|
- **Backend:** Node.js + TypeScript (compiled to plain JS) on Express.
|
|
18
19
|
- **Frontend:** Handlebars server-rendered templates, Tailwind CSS + DaisyUI,
|
|
@@ -22,9 +23,11 @@ multi-database support.
|
|
|
22
23
|
|
|
23
24
|
> ## ⚠️ Security warning — read first
|
|
24
25
|
>
|
|
25
|
-
> **This tool exposes full, unauthenticated database access.**
|
|
26
|
-
> API route (browse, edit, delete, run arbitrary SQL, change the
|
|
27
|
-
> the whole database
|
|
26
|
+
> **This tool exposes full, unauthenticated database AND filesystem access.**
|
|
27
|
+
> Every page and API route (browse, edit, delete, run arbitrary SQL, change the
|
|
28
|
+
> schema, export the whole database, and — in manager mode — browse the
|
|
29
|
+
> filesystem to open database files) is available to **anyone who can reach the
|
|
30
|
+
> server**.
|
|
28
31
|
>
|
|
29
32
|
> - **No authentication or authorization is built in.** The routes are **not
|
|
30
33
|
> protected**.
|
|
@@ -48,6 +51,26 @@ npm install admindb
|
|
|
48
51
|
|
|
49
52
|
Requires **Node.js ≥ 20**.
|
|
50
53
|
|
|
54
|
+
### Use as a standalone CLI tool
|
|
55
|
+
|
|
56
|
+
AdminDB ships a command-line server. Install it globally (or just run it with
|
|
57
|
+
`npx` — no install needed):
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npm install -g admindb
|
|
61
|
+
admindb # starts the server → open http://localhost:3000
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Run it without installing anything:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npx admindb -p 8080 # run on port 8080
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The `admindb` command starts the built-in server and opens the web UI in your
|
|
71
|
+
browser. See [Run the built-in server](#run-the-built-in-server) for all the
|
|
72
|
+
flags — `--port`, `--open <file>`, `--dir <folder>`, `--readonly`, and more.
|
|
73
|
+
|
|
51
74
|
## Using as an npm package
|
|
52
75
|
|
|
53
76
|
AdminDB is an Express app you can mount inside your own application, under
|
|
@@ -82,6 +105,8 @@ static assets + view engine). Mounting it is just `app.use('/path', router)`.
|
|
|
82
105
|
| `basePath` | `string` | URL prefix used by templates/assets (e.g. `/admin`). Pass the same prefix you mount at |
|
|
83
106
|
| `logger` | `Logger` | Custom logger (see `createLogger`) |
|
|
84
107
|
| `logLevel` | `'debug'\|'info'\|'warn'\|'error'` | Log verbosity (used when no logger is passed) |
|
|
108
|
+
| `allowBrowse` | `boolean` | Manager mode: show the filesystem file-browser on the databases page. Set `false` to disable it (e.g. when the server was started with specific database files). Default: `true` |
|
|
109
|
+
| `browseRoot` | `string` | Manager mode: restrict the file-browser to this folder (absolute path) — it cannot navigate above it and only databases inside it can be opened |
|
|
85
110
|
| `readonly` | `boolean` | Open the database(s) **read-only**: every write is rejected (403), write controls are disabled in the UI, and a banner is shown. The DB file is opened with `SQLITE_OPEN_READONLY` + `PRAGMA query_only` as a belt-and-suspenders guard. Default: `false` |
|
|
86
111
|
|
|
87
112
|
Example with a custom logger and prefix:
|
|
@@ -132,10 +157,18 @@ In multi-db mode:
|
|
|
132
157
|
## Features
|
|
133
158
|
|
|
134
159
|
- Browse every table and its rows (paginated, with primary-key awareness).
|
|
135
|
-
- **Filter rows by column** —
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
160
|
+
- **Filter rows by column** — type-aware, per-column filter controls: foreign-key
|
|
161
|
+
dropdowns, boolean toggles, date and numeric range inputs, plus the exact
|
|
162
|
+
(`=value`), comparison (`>5`, `<=10`), prefix (`pre*`) and substring (plain
|
|
163
|
+
text) operators on text columns. Filters survive sorting and pagination.
|
|
164
|
+
- **Inline (spreadsheet-style) editing** — double-click any cell to edit it in
|
|
165
|
+
place with a type-aware control (FK dropdown, boolean toggle, date picker,
|
|
166
|
+
number/text input). Changes are staged and highlighted in the grid, then
|
|
167
|
+
applied all at once in a single transaction, or discarded.
|
|
168
|
+
- Insert and delete rows (full CRUD). FK columns become dropdowns.
|
|
169
|
+
- **Bulk row operations** — select rows with checkboxes (or "select all"), then
|
|
170
|
+
**delete** them in one transaction (with a warning listing how many rows in
|
|
171
|
+
other tables reference them) or **export** only the selected rows as CSV/JSON.
|
|
139
172
|
- **Export** table rows or query results as **CSV or JSON**, and **import a CSV
|
|
140
173
|
file** (or pasted CSV) into a table.
|
|
141
174
|
- Create tables visually: name, type, primary key, not-null / unique,
|
|
@@ -151,14 +184,17 @@ In multi-db mode:
|
|
|
151
184
|
- **Indexes:** create indexes (plain or unique, on one or many columns — pick
|
|
152
185
|
columns in order, with a live `CREATE INDEX` SQL preview) and drop them from
|
|
153
186
|
the schema editor; automatic SQLite indexes are protected.
|
|
154
|
-
- **
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
inspect existing trigger SQL — from a dedicated Triggers page.
|
|
187
|
+
- **Related rows:** every table that has a foreign key pointing at a table gets
|
|
188
|
+
its own column at the end of that table's grid — each cell shows how many of
|
|
189
|
+
its rows reference that record; click it to open a nested table with all of
|
|
190
|
+
the referencing table's columns and data for that specific record.
|
|
159
191
|
- **Read-only mode:** open the database(s) without write access — the file is
|
|
160
192
|
opened `SQLITE_OPEN_READONLY` + `query_only`, every write route returns `403`,
|
|
161
193
|
and the UI hides/disables all write controls and shows a banner.
|
|
194
|
+
- **Standalone CLI / file browser:** `admindb` runs as a full web app — with no
|
|
195
|
+
arguments it opens a **Databases** landing page where you can browse the
|
|
196
|
+
filesystem and open any SQLite database file, or create new ones. Flags set
|
|
197
|
+
the port, open a file, manage a folder, and more (`admindb --help`).
|
|
162
198
|
- **Multiple databases:** directory scanning and/or explicit file lists, each
|
|
163
199
|
with its own workspace under `/{db}/…`.
|
|
164
200
|
|
|
@@ -202,26 +238,70 @@ npm run build
|
|
|
202
238
|
npm start # open http://localhost:3000
|
|
203
239
|
```
|
|
204
240
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
|
213
|
-
|
|
|
214
|
-
|
|
|
215
|
-
|
|
|
216
|
-
|
|
|
241
|
+
The server is a full standalone web app. With no arguments it runs in
|
|
242
|
+
**manager mode**: a **Databases** landing page where you can browse the
|
|
243
|
+
filesystem and open any SQLite database file (`.db` / `.sqlite` / `.sqlite3`),
|
|
244
|
+
or create new ones.
|
|
245
|
+
|
|
246
|
+
### CLI flags
|
|
247
|
+
|
|
248
|
+
| Flag | Description |
|
|
249
|
+
| -------------------- | -------------------------------------------------------- |
|
|
250
|
+
| `-p, --port <port>` | Port to listen on (default `3000`) |
|
|
251
|
+
| `-H, --host <host>` | Host / interface to bind (default `0.0.0.0`) |
|
|
252
|
+
| `-o, --open <file>` | Open a single database file directly |
|
|
253
|
+
| `-d, --dir <dir>` | Manage a folder of database files |
|
|
254
|
+
| `--files <list>` | Comma-separated database file paths to manage |
|
|
255
|
+
| `-b, --base-path <p>`| URL prefix to serve under (default `/`) |
|
|
256
|
+
| `-r, --readonly` | Open databases read-only (all writes disabled) |
|
|
257
|
+
| `-l, --log-level <l>`| `debug` \| `info` \| `warn` \| `error` (default `info`) |
|
|
258
|
+
| `-h, --help` | Show help |
|
|
259
|
+
| `-v, --version` | Show the version |
|
|
260
|
+
|
|
261
|
+
A positional `path` argument opens a database file directly, or manages a
|
|
262
|
+
folder when it is a directory. Flags override the environment variables below:
|
|
263
|
+
|
|
264
|
+
| Variable | Default | Description |
|
|
265
|
+
| ----------- | ------- | ------------------------------------ |
|
|
266
|
+
| `PORT` | `3000` | Port to listen on |
|
|
267
|
+
| `HOST` | `0.0.0.0` | Host / interface to bind |
|
|
268
|
+
| `DB_PATH` | — | Single SQLite database file |
|
|
269
|
+
| `DB_DIR` | — | Folder of `.db`/`.sqlite` files |
|
|
270
|
+
| `DB_FILES` | — | Comma-separated explicit database file paths |
|
|
271
|
+
| `READONLY` | — | `1` / `true` / `yes` / `on` opens the database(s) read-only |
|
|
272
|
+
| `BASE_PATH` | `''` | URL prefix (e.g. `/admin`) |
|
|
273
|
+
| `LOG_LEVEL` | `info` | `debug` \| `info` \| `warn` \| `error` |
|
|
274
|
+
|
|
275
|
+
Examples:
|
|
217
276
|
|
|
218
|
-
|
|
277
|
+
```bash
|
|
278
|
+
admindb # manager UI on http://localhost:3000
|
|
279
|
+
admindb -p 8080 # same, on port 8080
|
|
280
|
+
admindb ./data/app.db # open a single database file
|
|
281
|
+
admindb --open ~/notes.sqlite # open a file directly
|
|
282
|
+
admindb -d ./dbs # manage a folder of databases
|
|
283
|
+
admindb --files a.db,b.db -r # open two files read-only
|
|
284
|
+
```
|
|
219
285
|
|
|
220
286
|
```powershell
|
|
221
|
-
$env:DB_DIR='./db'; npm start
|
|
287
|
+
$env:DB_DIR='./db'; npm start # PowerShell
|
|
222
288
|
# bash/zsh: DB_DIR=./db npm start
|
|
223
289
|
```
|
|
224
290
|
|
|
291
|
+
When the server runs without an explicit single file, the **Databases** landing
|
|
292
|
+
page lists the managed databases and includes an **"Open an existing
|
|
293
|
+
database"** file browser: navigate folders, pick a database file, and open it.
|
|
294
|
+
Opened files are added to the list so you can switch between databases freely.
|
|
295
|
+
|
|
296
|
+
File-browser policy:
|
|
297
|
+
- When a **folder** is given (`--dir`, a directory path, or `DB_DIR`), browsing
|
|
298
|
+
is limited to that folder — it cannot navigate above it and only databases
|
|
299
|
+
inside it can be opened.
|
|
300
|
+
- When specific **files** are given (`--files`, or `DB_FILES`) without a folder,
|
|
301
|
+
file browsing is **disabled** entirely; only the configured databases are
|
|
302
|
+
listed.
|
|
303
|
+
- With no folder or files, browsing is unrestricted.
|
|
304
|
+
|
|
225
305
|
## The JSON REST API (under `basePath`)
|
|
226
306
|
|
|
227
307
|
| Method | Path | Purpose |
|
|
@@ -229,15 +309,19 @@ $env:DB_DIR='./db'; npm start # PowerShell
|
|
|
229
309
|
| GET | `/api/tables` | List tables |
|
|
230
310
|
| GET | `/api/tables/:table/info` | Column + FK metadata, PK columns |
|
|
231
311
|
| GET | `/api/tables/:table/fk-options` | Values for FK dropdowns |
|
|
232
|
-
| GET | `/api/tables/:table/rows?page&limit&f` | Paginated rows (`f` = URL-encoded JSON filters
|
|
312
|
+
| GET | `/api/tables/:table/rows?page&limit&f` | Paginated rows (`f` = URL-encoded JSON filters — legacy strings like `{"age":">35"}` or structured conditions like `{"balance":{"op":"gte","value":"100"}}`) |
|
|
233
313
|
| GET | `/api/tables/:table/row/:id` | Single row by (encoded) PK |
|
|
234
314
|
| POST | `/api/tables/:table/rows` | Insert row |
|
|
235
315
|
| POST | `/api/tables/:table/rows/generate` | Generate INSERT SQL (no execute) |
|
|
236
316
|
| POST | `/api/tables/:table/rows/import` | Import CSV (`{ csv }`, header row must match columns) |
|
|
237
317
|
| GET | `/api/tables/:table/export?format=` | Download all rows as `csv` or `json` |
|
|
238
|
-
| PUT | `/api/tables/:table/row/:id` | Update row
|
|
318
|
+
| PUT | `/api/tables/:table/row/:id` | Update row (`{ values, nulls? }` — `nulls` explicitly sets columns to NULL) |
|
|
239
319
|
| PUT | `/api/tables/:table/row/:id/generate` | Generate UPDATE SQL (no execute) |
|
|
240
320
|
| DELETE | `/api/tables/:table/row/:id` | Delete row |
|
|
321
|
+
| POST | `/api/tables/:table/rows/bulk-impact` | FK-impact preview: how many rows in other tables reference the selected rows |
|
|
322
|
+
| POST | `/api/tables/:table/rows/bulk-delete` | Delete selected rows (`{ ids, confirmImpact }`; transactional) |
|
|
323
|
+
| POST | `/api/tables/:table/rows/bulk-export` | Export only the selected rows as `csv`/`json` (`{ ids, format }`) |
|
|
324
|
+
| POST | `/api/tables/:table/rows/bulk-update` | Apply staged inline edits (`{ updates: [{ id, values?, nulls? }] }`; transactional) |
|
|
241
325
|
| POST | `/api/tables` | Create table |
|
|
242
326
|
| POST | `/api/tables/generate` | Generate CREATE SQL (no execute) |
|
|
243
327
|
| GET | `/api/tables/:table/schema` | Full schema (constraints, indexes, FK refs) |
|
|
@@ -248,15 +332,6 @@ $env:DB_DIR='./db'; npm start # PowerShell
|
|
|
248
332
|
| DELETE | `/api/tables/:table` | Drop the table (safety-checked) |
|
|
249
333
|
| POST | `/api/tables/:table/indexes` | Create an index (`{ name?, columns[], unique? }`) |
|
|
250
334
|
| DELETE | `/api/tables/:table/indexes/:index` | Drop an index (auto indexes refused) |
|
|
251
|
-
| GET | `/api/views` | List views |
|
|
252
|
-
| GET | `/api/views/:name/rows` | Preview a view's rows |
|
|
253
|
-
| POST | `/api/views/generate` | Generate CREATE VIEW SQL (no execute) |
|
|
254
|
-
| POST | `/api/views` | Create a view (`{ name, sql }`) |
|
|
255
|
-
| DELETE | `/api/views/:name` | Drop a view |
|
|
256
|
-
| GET | `/api/triggers` | List triggers |
|
|
257
|
-
| POST | `/api/triggers/generate` | Generate CREATE TRIGGER SQL (no execute) |
|
|
258
|
-
| POST | `/api/triggers` | Create a trigger (`{ name, table, timing, event, when?, body }`) |
|
|
259
|
-
| DELETE | `/api/triggers/:name` | Drop a trigger |
|
|
260
335
|
| POST | `/api/query` | Run arbitrary SQL |
|
|
261
336
|
| POST | `/api/query/export` | Run a SELECT and download as `csv`/`json` |
|
|
262
337
|
| GET | `/api/queries` | List saved queries |
|
|
@@ -267,6 +342,17 @@ In multi-db mode, every route is scoped under the database, e.g.
|
|
|
267
342
|
`/api/app.db/tables`. Every API response uses the consistent shape
|
|
268
343
|
`{ success, data?, error? }`.
|
|
269
344
|
|
|
345
|
+
In manager mode (the databases landing page), these extra endpoints manage
|
|
346
|
+
database files and power the filesystem browser:
|
|
347
|
+
|
|
348
|
+
| Method | Path | Purpose |
|
|
349
|
+
| ------ | ----------------------- | ------------------------------------------- |
|
|
350
|
+
| GET | `/api/databases` | List managed databases |
|
|
351
|
+
| POST | `/api/databases` | Create a new database (`{ name }`) |
|
|
352
|
+
| DELETE | `/api/databases/:id` | Delete a database |
|
|
353
|
+
| GET | `/api/fs/list?path=` | List subfolders + SQLite files under a path (file browser) |
|
|
354
|
+
| POST | `/api/databases/open` | Open/register an existing database file by path (`{ path }`) |
|
|
355
|
+
|
|
270
356
|
## Behaviour notes
|
|
271
357
|
|
|
272
358
|
- **Empty input = "not set".** Empty form fields are omitted so DB defaults
|
|
@@ -274,10 +360,26 @@ In multi-db mode, every route is scoped under the database, e.g.
|
|
|
274
360
|
- **Insert forms pre-fill defaults.** On the "new row" form, columns that have
|
|
275
361
|
a schema default are pre-filled (string/number/boolean literals and
|
|
276
362
|
`CURRENT_TIMESTAMP`-style defaults) so you can see and adjust them.
|
|
277
|
-
- **Row filters.**
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
363
|
+
- **Row filters.** The filter panel adapts to each column's type: foreign keys
|
|
364
|
+
become dropdowns (with a "not set / NULL" option), booleans become
|
|
365
|
+
any/true/false toggles, and dates and numbers become min/max range inputs.
|
|
366
|
+
Text columns keep the operator syntax: exact match (`=value`), comparison
|
|
367
|
+
(`>5`, `>=5`, `<5`, `<=5`, `!=value`), prefix (`pre*`) and case-insensitive
|
|
368
|
+
substring (plain text). Filters are carried in the URL (as legacy strings or
|
|
369
|
+
structured conditions) and survive sorting and pagination.
|
|
370
|
+
- **Inline editing is staged, not instant.** Double-click a cell to edit it in
|
|
371
|
+
place; edits are buffered locally and highlighted in the grid rather than
|
|
372
|
+
written immediately. Press **Apply** to write every pending change to the
|
|
373
|
+
database in a single transaction (the page then reloads so related-row counts
|
|
374
|
+
stay accurate), or **Discard** to revert everything back to the saved values.
|
|
375
|
+
Clearing a text/date/number field stages a `NULL`.
|
|
376
|
+
- **Bulk operations.** Checkboxes select rows on the current page; "select all"
|
|
377
|
+
checks every visible row. **Delete** first shows a warning listing each table
|
|
378
|
+
that references the selected rows and how many rows point at them (these may
|
|
379
|
+
be cascaded away or orphaned depending on the foreign-key action, and the
|
|
380
|
+
delete can fail if a constraint blocks it). **Export CSV / JSON** downloads
|
|
381
|
+
only the selected rows. Both delete and export are capped at 1000 rows per
|
|
382
|
+
batch.
|
|
281
383
|
- **CSV import.** The first row must be a header whose names match existing
|
|
282
384
|
columns (unknown or duplicate names are rejected). Empty cells are treated as
|
|
283
385
|
"not set" so database defaults apply. The whole import runs in a single
|
|
@@ -311,8 +413,10 @@ npm test # builds and runs the unit tests
|
|
|
311
413
|
|
|
312
414
|
`npm test` compiles TypeScript to `dist/` and runs the `node:test` suite
|
|
313
415
|
covering the SQL generator (INSERT / UPDATE / CREATE output, type mapping,
|
|
314
|
-
quoting, rejection of unsupported types), the SQL classifier,
|
|
315
|
-
|
|
416
|
+
quoting, rejection of unsupported types), the SQL classifier, CSV parsing and
|
|
417
|
+
serialization, row filters (legacy and structured conditions), the database
|
|
418
|
+
layer (pagination, transactions, bulk update/delete, read-only enforcement),
|
|
419
|
+
and the database manager.
|
|
316
420
|
|
|
317
421
|
## Publishing to npm
|
|
318
422
|
|
package/dist/app.d.ts
CHANGED
|
@@ -15,6 +15,18 @@ export interface AppOptions {
|
|
|
15
15
|
manager?: DbManager;
|
|
16
16
|
/** Open the database read-only — all write routes are rejected with 403. */
|
|
17
17
|
readonly?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Manager mode: show the filesystem file-browser on the databases landing
|
|
20
|
+
* page. Defaults to `true`. Set to `false` to disable browsing (e.g. when the
|
|
21
|
+
* server was started with specific database files only).
|
|
22
|
+
*/
|
|
23
|
+
allowBrowse?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Manager mode: restrict the file-browser to this folder (absolute path).
|
|
26
|
+
* When set, the browser cannot navigate above it and only databases inside it
|
|
27
|
+
* can be opened.
|
|
28
|
+
*/
|
|
29
|
+
browseRoot?: string;
|
|
18
30
|
/** Internal: URL of the databases list (used by per-db apps to link "switch database"). */
|
|
19
31
|
databasesUrl?: string;
|
|
20
32
|
/** Internal: current database id (for locals/display). */
|
package/dist/app.js
CHANGED
|
@@ -12,7 +12,10 @@ const logger_1 = require("./logger");
|
|
|
12
12
|
const pages_1 = require("./routes/pages");
|
|
13
13
|
const api_1 = require("./routes/api");
|
|
14
14
|
const databases_1 = require("./routes/databases");
|
|
15
|
+
const args_1 = require("./args");
|
|
15
16
|
const util_1 = require("./util");
|
|
17
|
+
/** Installed package version, exposed to every template as `{{version}}`. */
|
|
18
|
+
const APP_VERSION = (0, args_1.getPackageVersion)();
|
|
16
19
|
/**
|
|
17
20
|
* Build a fully configured, mountable Express app (pages + JSON API + static
|
|
18
21
|
* assets + view engine).
|
|
@@ -94,6 +97,7 @@ function createSingleDbApp(options) {
|
|
|
94
97
|
res.locals.databasesUrl = databasesUrl ?? null;
|
|
95
98
|
res.locals.databasesMode = false;
|
|
96
99
|
res.locals.readonly = db.isReadOnly;
|
|
100
|
+
res.locals.version = APP_VERSION;
|
|
97
101
|
if (!req.path.startsWith('/api/')) {
|
|
98
102
|
const all = await db.listTables();
|
|
99
103
|
const names = (all.data ?? []).map((t) => t.name);
|
|
@@ -133,6 +137,7 @@ function createManagerApp(options) {
|
|
|
133
137
|
res.locals.databasesUrl = null;
|
|
134
138
|
res.locals.databasesMode = true;
|
|
135
139
|
res.locals.readonly = readonly;
|
|
140
|
+
res.locals.version = APP_VERSION;
|
|
136
141
|
if (!req.path.startsWith('/api/')) {
|
|
137
142
|
res.locals.tables = [];
|
|
138
143
|
res.locals.internalTables = [];
|
|
@@ -150,6 +155,8 @@ function createManagerApp(options) {
|
|
|
150
155
|
logger,
|
|
151
156
|
basePath,
|
|
152
157
|
readonly,
|
|
158
|
+
allowBrowse: options.allowBrowse,
|
|
159
|
+
browseRoot: options.browseRoot,
|
|
153
160
|
invalidate: (id) => subApps.delete(id),
|
|
154
161
|
});
|
|
155
162
|
app.use('/:dbId', (req, res, next) => {
|
package/dist/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
|
package/dist/args.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { LogLevel } from './logger';
|
|
2
|
+
export interface CliArgs {
|
|
3
|
+
help: boolean;
|
|
4
|
+
version: boolean;
|
|
5
|
+
/** Bind host/interface. */
|
|
6
|
+
host?: string;
|
|
7
|
+
/** Port to listen on. */
|
|
8
|
+
port?: number;
|
|
9
|
+
/** A single database file to open directly (`--open`/`--db`/`--file`). */
|
|
10
|
+
dbPath?: string;
|
|
11
|
+
/** Directory of database files to manage (`--dir`). */
|
|
12
|
+
dbDir?: string;
|
|
13
|
+
/** Explicit database file paths (`--files a.db,b.db`). */
|
|
14
|
+
dbFiles?: string[];
|
|
15
|
+
/** URL prefix to serve under (`--base-path`). */
|
|
16
|
+
basePath?: string;
|
|
17
|
+
logLevel?: LogLevel;
|
|
18
|
+
/** Open databases read-only (`--readonly`). */
|
|
19
|
+
readonly: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function helpText(): string;
|
|
22
|
+
/** The installed `admindb` package version (from package.json), or '' when unknown. */
|
|
23
|
+
export declare function getPackageVersion(): string;
|
|
24
|
+
export declare function versionText(): string;
|
|
25
|
+
export declare function parseArgs(argv: string[]): {
|
|
26
|
+
args: CliArgs;
|
|
27
|
+
error?: string;
|
|
28
|
+
};
|
package/dist/args.js
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.helpText = helpText;
|
|
7
|
+
exports.getPackageVersion = getPackageVersion;
|
|
8
|
+
exports.versionText = versionText;
|
|
9
|
+
exports.parseArgs = parseArgs;
|
|
10
|
+
/**
|
|
11
|
+
* Command-line argument parsing for the standalone `admindb` server.
|
|
12
|
+
*
|
|
13
|
+
* The CLI supports flags to pick the port/host, open a single database file,
|
|
14
|
+
* manage a folder of databases, and more. Every flag has a matching
|
|
15
|
+
* environment variable; flags always win over the environment.
|
|
16
|
+
*/
|
|
17
|
+
const node_fs_1 = require("node:fs");
|
|
18
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
19
|
+
const LOG_LEVELS = ['debug', 'info', 'warn', 'error'];
|
|
20
|
+
function helpText() {
|
|
21
|
+
return [
|
|
22
|
+
'AdminDB — browser-based SQLite administration tool.',
|
|
23
|
+
'',
|
|
24
|
+
'Usage:',
|
|
25
|
+
' admindb [options] [path]',
|
|
26
|
+
'',
|
|
27
|
+
'Starts a local server and opens a web UI where you can browse, select and',
|
|
28
|
+
'manage SQLite databases (.db / .sqlite / .sqlite3).',
|
|
29
|
+
'',
|
|
30
|
+
'With no path or options it runs in "manager" mode: the landing page lets',
|
|
31
|
+
'you browse the filesystem and open any database file, or create new ones.',
|
|
32
|
+
'',
|
|
33
|
+
'Arguments:',
|
|
34
|
+
' path Path to a database file (opens it directly) or to a',
|
|
35
|
+
' folder of databases (lists them). Default: the',
|
|
36
|
+
' current directory.',
|
|
37
|
+
'',
|
|
38
|
+
'Options:',
|
|
39
|
+
' -p, --port <port> Port to listen on (default: 3000)',
|
|
40
|
+
' -H, --host <host> Host/interface to bind (default: 0.0.0.0)',
|
|
41
|
+
' -o, --open <file> Open a single database file',
|
|
42
|
+
' -d, --dir <dir> Folder of database files to manage',
|
|
43
|
+
' --files <list> Comma-separated database file paths',
|
|
44
|
+
' -b, --base-path <p> URL prefix to serve under (default: /)',
|
|
45
|
+
' -r, --readonly Open databases read-only (all writes disabled)',
|
|
46
|
+
' -l, --log-level <l> debug | info | warn | error (default: info)',
|
|
47
|
+
' -h, --help Show this help',
|
|
48
|
+
' -v, --version Show the version',
|
|
49
|
+
'',
|
|
50
|
+
'Environment variables (used when the matching flag is not given):',
|
|
51
|
+
' PORT, HOST, DB_PATH, DB_DIR, DB_FILES, BASE_PATH, READONLY, LOG_LEVEL',
|
|
52
|
+
'',
|
|
53
|
+
'Examples:',
|
|
54
|
+
' admindb # manager UI on http://localhost:3000',
|
|
55
|
+
' admindb -p 8080 # same, on port 8080',
|
|
56
|
+
' admindb ./data/app.db # open a single database file',
|
|
57
|
+
' admindb --open ~/notes.sqlite # open a file (direct)',
|
|
58
|
+
' admindb -d ./dbs # manage a folder of databases',
|
|
59
|
+
' admindb --files a.db,b.db -r # open two files read-only',
|
|
60
|
+
].join('\n');
|
|
61
|
+
}
|
|
62
|
+
function packageVersion() {
|
|
63
|
+
try {
|
|
64
|
+
const raw = (0, node_fs_1.readFileSync)(node_path_1.default.join(__dirname, '..', 'package.json'), 'utf8');
|
|
65
|
+
const pkg = JSON.parse(raw);
|
|
66
|
+
return pkg.version ?? '';
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return '';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** The installed `admindb` package version (from package.json), or '' when unknown. */
|
|
73
|
+
function getPackageVersion() {
|
|
74
|
+
return packageVersion();
|
|
75
|
+
}
|
|
76
|
+
function versionText() {
|
|
77
|
+
const v = packageVersion();
|
|
78
|
+
return v ? `admindb v${v}` : 'admindb';
|
|
79
|
+
}
|
|
80
|
+
/** True when a token is exactly a flag or `flag=value` (for long flags). */
|
|
81
|
+
function isFlag(tok, ...names) {
|
|
82
|
+
return names.includes(tok) || names.some((n) => n.length > 2 && tok.startsWith(n + '='));
|
|
83
|
+
}
|
|
84
|
+
function parseArgs(argv) {
|
|
85
|
+
const args = { help: false, version: false, readonly: false };
|
|
86
|
+
const positional = [];
|
|
87
|
+
let i = 0;
|
|
88
|
+
const invalid = (error) => ({ args, error });
|
|
89
|
+
// Read the value for the current flag token; supports `--flag=value` and
|
|
90
|
+
// `--flag value`. Leaves `i` pointing at the value token so the loop can
|
|
91
|
+
// advance past it.
|
|
92
|
+
const takeValue = (flag) => {
|
|
93
|
+
const eq = argv[i].indexOf('=');
|
|
94
|
+
if (eq !== -1)
|
|
95
|
+
return argv[i].slice(eq + 1);
|
|
96
|
+
i += 1;
|
|
97
|
+
return argv[i];
|
|
98
|
+
};
|
|
99
|
+
while (i < argv.length) {
|
|
100
|
+
const tok = argv[i];
|
|
101
|
+
if (tok === '-h' || tok === '--help') {
|
|
102
|
+
args.help = true;
|
|
103
|
+
}
|
|
104
|
+
else if (tok === '-v' || tok === '--version') {
|
|
105
|
+
args.version = true;
|
|
106
|
+
}
|
|
107
|
+
else if (isFlag(tok, '-p', '--port')) {
|
|
108
|
+
const v = takeValue('--port');
|
|
109
|
+
if (v === undefined)
|
|
110
|
+
return invalid('Missing value for --port.');
|
|
111
|
+
const n = Number.parseInt(v, 10);
|
|
112
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
113
|
+
return invalid(`Invalid port: "${v}".`);
|
|
114
|
+
args.port = n;
|
|
115
|
+
}
|
|
116
|
+
else if (isFlag(tok, '-H', '--host')) {
|
|
117
|
+
const v = takeValue('--host');
|
|
118
|
+
if (v === undefined)
|
|
119
|
+
return invalid('Missing value for --host.');
|
|
120
|
+
args.host = v;
|
|
121
|
+
}
|
|
122
|
+
else if (isFlag(tok, '-o', '--open', '--db', '-f', '--file')) {
|
|
123
|
+
const v = takeValue('--open');
|
|
124
|
+
if (v === undefined)
|
|
125
|
+
return invalid('Missing value for --open.');
|
|
126
|
+
args.dbPath = v;
|
|
127
|
+
}
|
|
128
|
+
else if (isFlag(tok, '-d', '--dir', '--folder')) {
|
|
129
|
+
const v = takeValue('--dir');
|
|
130
|
+
if (v === undefined)
|
|
131
|
+
return invalid('Missing value for --dir.');
|
|
132
|
+
args.dbDir = v;
|
|
133
|
+
}
|
|
134
|
+
else if (isFlag(tok, '--files')) {
|
|
135
|
+
const v = takeValue('--files');
|
|
136
|
+
if (v === undefined)
|
|
137
|
+
return invalid('Missing value for --files.');
|
|
138
|
+
args.dbFiles = v
|
|
139
|
+
.split(',')
|
|
140
|
+
.map((s) => s.trim())
|
|
141
|
+
.filter(Boolean);
|
|
142
|
+
}
|
|
143
|
+
else if (isFlag(tok, '-b', '--base-path', '--base')) {
|
|
144
|
+
const v = takeValue('--base-path');
|
|
145
|
+
if (v === undefined)
|
|
146
|
+
return invalid('Missing value for --base-path.');
|
|
147
|
+
args.basePath = v;
|
|
148
|
+
}
|
|
149
|
+
else if (isFlag(tok, '-l', '--log-level')) {
|
|
150
|
+
const v = takeValue('--log-level');
|
|
151
|
+
if (v === undefined)
|
|
152
|
+
return invalid('Missing value for --log-level.');
|
|
153
|
+
if (!LOG_LEVELS.includes(v)) {
|
|
154
|
+
return invalid(`Invalid log level: "${v}". Expected one of: ${LOG_LEVELS.join(', ')}.`);
|
|
155
|
+
}
|
|
156
|
+
args.logLevel = v;
|
|
157
|
+
}
|
|
158
|
+
else if (tok === '-r' || tok === '--readonly') {
|
|
159
|
+
args.readonly = true;
|
|
160
|
+
}
|
|
161
|
+
else if (tok.startsWith('-') && tok.length > 1) {
|
|
162
|
+
return invalid(`Unknown option: "${tok}".`);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
positional.push(tok);
|
|
166
|
+
}
|
|
167
|
+
i += 1;
|
|
168
|
+
}
|
|
169
|
+
if (positional.length > 1) {
|
|
170
|
+
return invalid(`Unexpected extra arguments: ${positional.slice(1).join(' ')}.`);
|
|
171
|
+
}
|
|
172
|
+
const p = positional[0];
|
|
173
|
+
if (p) {
|
|
174
|
+
const abs = node_path_1.default.resolve(p);
|
|
175
|
+
try {
|
|
176
|
+
if ((0, node_fs_1.statSync)(abs).isDirectory())
|
|
177
|
+
args.dbDir = p;
|
|
178
|
+
else
|
|
179
|
+
args.dbPath = p;
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
args.dbPath = p;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return { args };
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=args.js.map
|
package/dist/args.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"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"}
|