admindb 1.2.0 → 2.0.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.
Files changed (202) hide show
  1. package/README.md +250 -352
  2. package/dist/app.d.ts +25 -4
  3. package/dist/app.js +79 -15
  4. package/dist/app.js.map +1 -1
  5. package/dist/auth/config.d.ts +19 -0
  6. package/dist/auth/config.js +147 -0
  7. package/dist/auth/config.js.map +1 -0
  8. package/dist/auth/crypto.d.ts +27 -0
  9. package/dist/auth/crypto.js +133 -0
  10. package/dist/auth/crypto.js.map +1 -0
  11. package/dist/auth/index.d.ts +5 -0
  12. package/dist/auth/index.js +22 -0
  13. package/dist/auth/index.js.map +1 -0
  14. package/dist/auth/middleware.d.ts +14 -0
  15. package/dist/auth/middleware.js +100 -0
  16. package/dist/auth/middleware.js.map +1 -0
  17. package/dist/auth/routes.d.ts +7 -0
  18. package/dist/auth/routes.js +78 -0
  19. package/dist/auth/routes.js.map +1 -0
  20. package/dist/auth/types.d.ts +35 -0
  21. package/dist/auth/types.js +11 -0
  22. package/dist/auth/types.js.map +1 -0
  23. package/dist/cli/args.d.ts +45 -0
  24. package/dist/cli/args.js +328 -0
  25. package/dist/cli/args.js.map +1 -0
  26. package/dist/cli/config.d.ts +56 -0
  27. package/dist/cli/config.js +133 -0
  28. package/dist/cli/config.js.map +1 -0
  29. package/dist/cli/index.d.ts +4 -0
  30. package/dist/cli/index.js +21 -0
  31. package/dist/cli/index.js.map +1 -0
  32. package/dist/cli/runner.d.ts +1 -0
  33. package/dist/cli/runner.js +222 -0
  34. package/dist/cli/runner.js.map +1 -0
  35. package/dist/cli.js +2 -127
  36. package/dist/cli.js.map +1 -1
  37. package/dist/data/datasets.d.ts +17 -0
  38. package/dist/data/datasets.js +133 -0
  39. package/dist/data/datasets.js.map +1 -0
  40. package/dist/data/detector.d.ts +30 -0
  41. package/dist/data/detector.js +472 -0
  42. package/dist/data/detector.js.map +1 -0
  43. package/dist/data/engine.d.ts +10 -0
  44. package/dist/data/engine.js +211 -0
  45. package/dist/data/engine.js.map +1 -0
  46. package/dist/data/index.d.ts +5 -0
  47. package/dist/data/index.js +22 -0
  48. package/dist/data/index.js.map +1 -0
  49. package/dist/data/strategies.d.ts +30 -0
  50. package/dist/data/strategies.js +343 -0
  51. package/dist/data/strategies.js.map +1 -0
  52. package/dist/data/types.d.ts +73 -0
  53. package/dist/data/types.js +8 -0
  54. package/dist/data/types.js.map +1 -0
  55. package/dist/db/database.d.ts +14 -142
  56. package/dist/db/database.js +209 -435
  57. package/dist/db/database.js.map +1 -1
  58. package/dist/db/export.d.ts +2 -2
  59. package/dist/db/export.js +7 -2
  60. package/dist/db/export.js.map +1 -1
  61. package/dist/db/filters.d.ts +22 -0
  62. package/dist/db/filters.js +158 -0
  63. package/dist/db/filters.js.map +1 -0
  64. package/dist/db/index.d.ts +8 -0
  65. package/dist/db/index.js +25 -0
  66. package/dist/db/index.js.map +1 -0
  67. package/dist/db/introspection.d.ts +6 -0
  68. package/dist/db/introspection.js +172 -0
  69. package/dist/db/introspection.js.map +1 -0
  70. package/dist/db/manager.d.ts +32 -19
  71. package/dist/db/manager.js +203 -44
  72. package/dist/db/manager.js.map +1 -1
  73. package/dist/db/migrations.d.ts +5 -0
  74. package/dist/db/migrations.js +110 -0
  75. package/dist/db/migrations.js.map +1 -0
  76. package/dist/db/postgres.d.ts +85 -0
  77. package/dist/db/postgres.js +745 -0
  78. package/dist/db/postgres.js.map +1 -0
  79. package/dist/db/types.d.ts +206 -0
  80. package/dist/db/types.js +7 -0
  81. package/dist/db/types.js.map +1 -0
  82. package/dist/index.d.ts +9 -2
  83. package/dist/index.js +46 -4
  84. package/dist/index.js.map +1 -1
  85. package/dist/public/css/app.css +1 -1
  86. package/dist/public/css/input.css +83 -13
  87. package/dist/public/js/app.js +142 -0
  88. package/dist/public/js/browse.js +591 -104
  89. package/dist/public/js/databases.js +105 -13
  90. package/dist/public/js/designer.js +40 -2
  91. package/dist/public/js/forms.js +610 -28
  92. package/dist/public/js/icons.js +51 -0
  93. package/dist/public/js/inspector.js +638 -0
  94. package/dist/public/js/query.js +93 -3
  95. package/dist/public/js/schema.js +170 -52
  96. package/dist/public/js/seed.js +1090 -0
  97. package/dist/routes/api/helpers.d.ts +42 -0
  98. package/dist/routes/api/helpers.js +133 -0
  99. package/dist/routes/api/helpers.js.map +1 -0
  100. package/dist/routes/api/import-export.d.ts +3 -0
  101. package/dist/routes/api/import-export.js +85 -0
  102. package/dist/routes/api/import-export.js.map +1 -0
  103. package/dist/routes/api/index.d.ts +4 -0
  104. package/dist/routes/api/index.js +37 -0
  105. package/dist/routes/api/index.js.map +1 -0
  106. package/dist/routes/api/query.d.ts +3 -0
  107. package/dist/routes/api/query.js +76 -0
  108. package/dist/routes/api/query.js.map +1 -0
  109. package/dist/routes/api/rows.d.ts +3 -0
  110. package/dist/routes/api/rows.js +373 -0
  111. package/dist/routes/api/rows.js.map +1 -0
  112. package/dist/routes/api/seed.d.ts +3 -0
  113. package/dist/routes/api/seed.js +82 -0
  114. package/dist/routes/api/seed.js.map +1 -0
  115. package/dist/routes/api/tables.d.ts +3 -0
  116. package/dist/routes/api/tables.js +160 -0
  117. package/dist/routes/api/tables.js.map +1 -0
  118. package/dist/routes/databases.d.ts +8 -11
  119. package/dist/routes/databases.js +100 -66
  120. package/dist/routes/databases.js.map +1 -1
  121. package/dist/routes/index.d.ts +3 -0
  122. package/dist/routes/index.js +20 -0
  123. package/dist/routes/index.js.map +1 -0
  124. package/dist/routes/pages.d.ts +3 -3
  125. package/dist/routes/pages.js +163 -54
  126. package/dist/routes/pages.js.map +1 -1
  127. package/dist/serverless.d.ts +40 -0
  128. package/dist/serverless.js +210 -0
  129. package/dist/serverless.js.map +1 -0
  130. package/dist/sql/generator.d.ts +4 -3
  131. package/dist/sql/generator.js +103 -6
  132. package/dist/sql/generator.js.map +1 -1
  133. package/dist/sql/index.d.ts +2 -0
  134. package/dist/sql/index.js +19 -0
  135. package/dist/sql/index.js.map +1 -0
  136. package/dist/types/api.d.ts +412 -0
  137. package/dist/types/api.js +9 -0
  138. package/dist/types/api.js.map +1 -0
  139. package/dist/utils/colors.d.ts +40 -0
  140. package/dist/utils/colors.js +64 -0
  141. package/dist/utils/colors.js.map +1 -0
  142. package/dist/{util.d.ts → utils/common.d.ts} +10 -6
  143. package/dist/{util.js → utils/common.js} +80 -13
  144. package/dist/utils/common.js.map +1 -0
  145. package/dist/utils/csv.js.map +1 -0
  146. package/dist/utils/datatype.d.ts +49 -0
  147. package/dist/utils/datatype.js +222 -0
  148. package/dist/utils/datatype.js.map +1 -0
  149. package/dist/utils/icons.d.ts +11 -0
  150. package/dist/utils/icons.js +72 -0
  151. package/dist/utils/icons.js.map +1 -0
  152. package/dist/utils/index.d.ts +4 -0
  153. package/dist/utils/index.js +21 -0
  154. package/dist/utils/index.js.map +1 -0
  155. package/dist/{logger.d.ts → utils/logger.d.ts} +1 -1
  156. package/dist/utils/logger.js +40 -0
  157. package/dist/utils/logger.js.map +1 -0
  158. package/dist/views/layouts/main.hbs +33 -11
  159. package/dist/views/pages/databases.hbs +182 -74
  160. package/dist/views/pages/designer.hbs +9 -6
  161. package/dist/views/pages/error.hbs +3 -3
  162. package/dist/views/pages/form.hbs +5 -3
  163. package/dist/views/pages/home.hbs +22 -13
  164. package/dist/views/pages/login.hbs +111 -0
  165. package/dist/views/pages/query.hbs +10 -8
  166. package/dist/views/pages/schema.hbs +41 -13
  167. package/dist/views/pages/seed.hbs +232 -0
  168. package/dist/views/pages/table.hbs +155 -70
  169. package/dist/views/partials/icon.hbs +2 -0
  170. package/dist/views/partials/navbar.hbs +70 -31
  171. package/dist/views/partials/sidebar.hbs +108 -99
  172. package/package.json +12 -5
  173. package/dist/args.d.ts +0 -28
  174. package/dist/args.js +0 -187
  175. package/dist/args.js.map +0 -1
  176. package/dist/config.d.ts +0 -17
  177. package/dist/config.js +0 -23
  178. package/dist/config.js.map +0 -1
  179. package/dist/csv.js.map +0 -1
  180. package/dist/logger.js +0 -25
  181. package/dist/logger.js.map +0 -1
  182. package/dist/routes/api.d.ts +0 -9
  183. package/dist/routes/api.js +0 -786
  184. package/dist/routes/api.js.map +0 -1
  185. package/dist/test/classifier.test.d.ts +0 -1
  186. package/dist/test/classifier.test.js +0 -44
  187. package/dist/test/classifier.test.js.map +0 -1
  188. package/dist/test/csv.test.d.ts +0 -1
  189. package/dist/test/csv.test.js +0 -64
  190. package/dist/test/csv.test.js.map +0 -1
  191. package/dist/test/database.test.d.ts +0 -1
  192. package/dist/test/database.test.js +0 -402
  193. package/dist/test/database.test.js.map +0 -1
  194. package/dist/test/generator.test.d.ts +0 -1
  195. package/dist/test/generator.test.js +0 -132
  196. package/dist/test/generator.test.js.map +0 -1
  197. package/dist/test/manager.test.d.ts +0 -1
  198. package/dist/test/manager.test.js +0 -146
  199. package/dist/test/manager.test.js.map +0 -1
  200. package/dist/util.js.map +0 -1
  201. /package/dist/{csv.d.ts → utils/csv.d.ts} +0 -0
  202. /package/dist/{csv.js → utils/csv.js} +0 -0
package/README.md CHANGED
@@ -1,437 +1,335 @@
1
1
  # AdminDB
2
2
 
3
-
4
3
  [![Version](https://img.shields.io/npm/v/admindb.svg)](https://www.npmjs.com/package/admindb)
5
4
  [![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
5
  [![Node.js](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen.svg)](https://nodejs.org/)
7
- [![Publish](https://github.com/MIbnEKhalid/admindb/actions/workflows/publish.yml/badge.svg?branch=main)](https://github.com/MIbnEKhalid/admindb/actions/workflows/publish.yml)
8
6
  [![Downloads](https://img.shields.io/npm/dm/admindb.svg)](https://www.npmjs.com/package/admindb)
7
+ [![Publish](https://github.com/MIbnEKhalid/admindb/actions/workflows/publish.yml/badge.svg?branch=main)](https://github.com/MIbnEKhalid/admindb/actions/workflows/publish.yml)
9
8
 
9
+ **A modern, browser-based SQLite and PostgreSQL database administration tool.** Manage SQLite and PostgreSQL databases entirely from your browser — browse and edit rows, run arbitrary SQL queries, design schemas visually, seed realistic test data, inspect complex data types, and import/export CSV/JSON — with zero frontend build step.
10
10
 
11
- A browser-based SQLite database administration tool. Manage a SQLite database
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.
17
-
18
- - **Backend:** Node.js + TypeScript (compiled to plain JS) on Express.
19
- - **Frontend:** Handlebars server-rendered templates, Tailwind CSS + DaisyUI,
20
- plain JavaScript (no frontend framework).
21
- - **Database:** SQLite via [better-sqlite3](https://github.com/WiseLibs/better-sqlite3). Requires
22
- **Node.js ≥ 20**.
23
-
24
- > ## ⚠️ Security warning — read first
25
- >
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**.
31
- >
32
- > - **No authentication or authorization is built in.** The routes are **not
33
- > protected**.
34
- > - **It is your responsibility to protect access.** Do **not** expose
35
- > AdminDB to the public internet or to untrusted networks.
36
- > - Recommended ways to protect it:
37
- > - bind the standalone server to `127.0.0.1` (`HOST=127.0.0.1`) and use it
38
- > only from your own machine, and/or
39
- > - run it behind a reverse proxy that requires authentication (Basic auth,
40
- > OAuth, mTLS, …) or inside a VPN / private network.
41
- >
42
- > Treat AdminDB as if it were a remote `sqlite3` shell with write access.
11
+ - **SQLite & PostgreSQL Multi-Engine:** Seamlessly manage local SQLite files, remote PostgreSQL connections, or multi-database environments with distinct engine badges and credentials protection.
12
+ - **Secure JSON Config Files:** Pass database credentials securely in `.json` files (`name.postgres.json`) without exposing secrets on the CLI.
13
+ - **Zero frontend build step:** Server-rendered Handlebars UI + vanilla JS + Tailwind/DaisyUI; a single lightweight Express process serves pages, static assets, and the REST API.
14
+ - **Standalone CLI or embeddable library:** Run instantly via `npx admindb` or mount it directly into your existing Express application under any subpath.
15
+ - **Modern terminal experience:** Clean, colorized startup banner with auto-detected local/network URLs and streamlined runtime logs.
16
+ - **Rich Data Types & Calendar Controls:** In-place calendar pickers with presets (`Now`, `Yesterday`, `Tomorrow`, `+7 Days`, `+30 Days`), PostgreSQL Array chip managers, JSON modal inspector, UUID generators, and byte dump inspector.
17
+ - **Safe SQL by construction:** Quoted identifiers, escaped literals, parameterized queries, and non-executing SQL preview modes.
43
18
 
44
19
  ---
45
20
 
46
- ## Install
21
+ ![Home dashboard](docs/screenshots/home.png)
22
+
23
+ > 📸 **Visual Tour:** See [`docs/screenshots/`](docs/screenshots/) for screenshots of the Table Browser, Query Editor, Visual Schema Designer, Inline Grid Editor, and Multi-Database Manager.
24
+
25
+ ---
26
+
27
+ ## ⚡ 30-Second Quickstart
28
+
29
+ No installation required:
47
30
 
48
31
  ```bash
49
- npm install admindb
32
+ npx admindb
50
33
  ```
51
34
 
52
- Requires **Node.js ≥ 20**.
35
+ By default, AdminDB opens in **Manager Mode** on `http://localhost:45531`, allowing you to browse the filesystem, create new SQLite databases, or open existing `.db` / `.sqlite` / `.sqlite3` files.
53
36
 
54
- ### Use as a standalone CLI tool
37
+ ### 1. Load database connections securely from a JSON file:
55
38
 
56
- AdminDB ships a command-line server. Install it globally (or just run it with
57
- `npx` — no install needed):
39
+ Create `name.postgres.json`:
40
+ ```json
41
+ {
42
+ "prod": "postgresql://postgres:secret@localhost:5432/prod_db",
43
+ "staging": "postgresql://postgres:secret@localhost:5432/staging_db",
44
+ "local": "./data/local.db"
45
+ }
46
+ ```
58
47
 
48
+ Run:
59
49
  ```bash
60
- npm install -g admindb
61
- admindb # starts the server → open http://localhost:3000
50
+ npx admindb name.postgres.json
62
51
  ```
63
52
 
64
- Run it without installing anything:
53
+ ### 2. Point directly to a database file or PostgreSQL URI:
65
54
 
66
55
  ```bash
67
- npx admindb -p 8080 # run on port 8080
56
+ npx admindb ./data/app.db # Open a single SQLite database directly
57
+ npx admindb postgresql://postgres:secret@localhost:5432/mydb # Open a PostgreSQL database directly
58
+ npx admindb -d ./databases # Manage a folder of SQLite databases
59
+ npx admindb -p 8080 -r # Run on port 8080 in read-only mode
68
60
  ```
69
61
 
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.
62
+ ### Install globally:
73
63
 
74
- ## Using as an npm package
64
+ ```bash
65
+ npm install -g admindb
66
+ admindb
67
+ ```
75
68
 
76
- AdminDB is an Express app you can mount inside your own application, under
77
- your own path, on the same port as the rest of your server.
69
+ ---
78
70
 
79
- ### Minimal example
71
+ ## 🖥️ Modern Terminal Experience
80
72
 
81
- ```ts
82
- import express from 'express';
83
- import { createRouter } from 'admindb';
73
+ AdminDB features a clean, colorized CLI startup banner and streamlined, low-noise runtime logging:
84
74
 
85
- const app = express();
75
+ ```text
76
+ ⚡ AdminDB v2.0.0
86
77
 
87
- app.get('/', (_req, res) => res.send('My main app'));
78
+ ➜ Local: http://localhost:45531/
79
+ ➜ Network: http://192.168.1.15:45531/
80
+ ➜ Mode: Manager
81
+ ➜ Config: name.postgres.json (2 connection(s))
82
+ • prod: PostgreSQL postgresql://postgres:****@localhost:5432/prod_db
83
+ • staging: PostgreSQL postgresql://postgres:****@localhost:5432/staging_db
84
+ ➜ Auth: User: admin (default password)
88
85
 
89
- // All AdminDB routes live under /admin on the same port.
90
- app.use('/admin', createRouter({ dbPath: '/data/my.db', basePath: '/admin' }));
86
+ ⚠ Default password in use (admin). Generate a secure hash with:
87
+ npm run generatehash and set ADMINDB_PASSWORD or -P <hash>
88
+ ```
91
89
 
92
- app.listen(3000);
90
+ Runtime operations produce crisp, color-coded status logs:
91
+
92
+ ```text
93
+ 16:38:13 [info] Initialized PostgreSQL pool for postgresql://postgres:****@localhost:5432/prod_db
94
+ 16:38:15 [info] Executed query in 2.4ms (42 rows returned)
95
+ 16:38:18 [warn] Failed login attempt for user "unknown"
93
96
  ```
94
97
 
95
- `createRouter(options)` returns a fully wired Express app (pages + JSON API +
96
- static assets + view engine). Mounting it is just `app.use('/path', router)`.
98
+ ---
97
99
 
98
- ### Options
100
+ ## 🌟 Core Features
101
+
102
+ ### 🔍 Browse & Edit Rows
103
+ * **Table Browser:** High-density compact grid by default, column-header sorting, sticky headers, and pinned right-aligned action columns. Composite primary keys are fully supported.
104
+ * **Spreadsheet-Style Inline Editing & Keyboard Navigation:**
105
+ * **Full Grid Navigation:** Navigate cells with <kbd>↑</kbd> <kbd>↓</kbd> <kbd>←</kbd> <kbd>→</kbd> or <kbd>Tab</kbd> / <kbd>Shift+Tab</kbd>.
106
+ * **In-Place Type-Aware Controls:** Double-click or press <kbd>Enter</kbd> to edit in place (FK dropdowns, boolean toggles, date/time pickers with instant calendar triggers, array tags, numeric inputs). Pressing <kbd>Enter</kbd> commits and shifts focus to the cell below. Pressing <kbd>Space</kbd> on boolean cells toggles immediately.
107
+ * **Interactive Date & Time Presets:** Calendar widget with quick shortcuts (`Now / Today`, `Yesterday`, `Tomorrow`, `+7 Days`, `+30 Days`, `Start of Day`, `End of Day`, `Clear`).
108
+ * **PostgreSQL Array Tag Manager:** Interactive chip manager with Enter key chip addition, removal, and `{item1,item2}` array serialization.
109
+ * **Quick Copy Shortcut:** Press <kbd>Ctrl+C</kbd> / <kbd>Cmd+C</kbd> on any focused cell to copy its raw value to the clipboard.
110
+ * **Granular Staging & Single-Cell Revert:** Staged edits are marked with amber indicators (`.cell-dirty`). Hovering reveals an individual undo button (`↺`) to revert a single field without losing the rest of your pending batch.
111
+ * **Staged Changes Diff & Review Drawer:** Floating dock displays pending edit count; click **Review Diff** to inspect a side-by-side comparison of original vs staged values across all modified rows before applying atomically in a single transaction.
112
+ * **Universal Data Inspector:** Rich interactive modal for deep data inspection:
113
+ * **JSON / JSONB Viewer & Editor:** Interactive syntax-highlighted tree viewer, expandable nodes, real-time JSON editor, and format **Beautify** & **Minify** tools.
114
+ * **BLOB / BYTEA & Media Previews:** Automatic MIME sniffing (PNG, JPEG, WebP, GIF, SVG, PDF, audio/video), inline image thumbnails, direct binary download, and drag-and-drop file upload. Supports PostgreSQL `\x...` and `0x...` hex strings.
115
+ * **3-Column Hex Dump:** Professional byte offset, hexadecimal, and printable ASCII viewer for raw binary blobs.
116
+ * **Text & Code Inspector:** Full-height editor for lengthy text fields, SQL strings, markdown, UUIDs, and config blobs with copy shortcuts.
117
+ * **Row Quick Actions:** 3-dots dropdown menu on each row for *Edit*, *Duplicate Row*, *Copy as JSON*, *Copy SQL INSERT*, and *Delete Row*.
118
+ * **Type-Aware Filters:** Filter by exact match, comparison (`>5`, `<=10`), prefix (`pre*`), substring, boolean state, or date/numeric ranges.
119
+ * **Bulk Operations:** Select rows to delete in one transaction (with foreign-key impact previews) or export selected rows as CSV/JSON.
120
+ * **Related Rows:** Cross-table foreign key indicators show how many child records reference each row, with one-click nested table exploration.
121
+
122
+ ### ⚡ Query Runner & SQL Tools
123
+ * **Arbitrary SQL Runner:** Execute queries with results formatted as clean tables; `COUNT` queries display a concise summary, and mutations report affected row counts. Double-click or click inspect on any cell in query results to open the universal inspector.
124
+ * **Saved Named Queries:** Save frequently used queries in the database and reload them from a dropdown menu.
125
+ * **Safe SQL Preview:** Generate `CREATE`, `INSERT`, or `UPDATE` SQL without executing it.
126
+ * **Full Database Dump:** Download the entire database as a standard SQL file (`CREATE TABLE` + `INSERT` statements).
127
+
128
+ ### 🗂️ Visual Schema Designer & Indexes
129
+ * **Visual Table Designer:** Create tables interactively with column types (including `UUID`, `JSONB`, `TIMESTAMP`, `TIMESTAMPTZ`, `INTERVAL`, `BYTEA`, `INET`, `SERIAL`, `BIGINT`), primary keys, autoincrement, nullable/unique constraints, default values, and foreign keys.
130
+ * **Relationship-Safe Schema Editor:** Rename tables, add columns, modify column types, rename columns, and drop columns/tables with safety checks to protect active foreign keys and unique constraints.
131
+ * **Index Manager:** Create single or multi-column indexes (plain or unique) with live SQL previews, and drop existing indexes safely.
132
+
133
+ ### 🔄 Import, Export & Seed Data Generation
134
+ * **CSV Import:** Upload or paste CSV files with column matching, executed transactionally.
135
+ * **Data Export:** Download table data or arbitrary SQL query results as CSV or JSON.
136
+ * **Intelligent Seed Generator:** Populate tables with up to 5,000 realistic rows using intelligent heuristic strategy detection (names, emails, phones, addresses, dates, UUIDs, custom templates, or sampled foreign keys). Includes live table preview before execution.
137
+
138
+ ### 📁 Multi-Database Manager
139
+ * Manage directories of SQLite files, explicit file lists, or named JSON connections.
140
+ * Dedicated landing page with engine badges (`PostgreSQL` / `SQLite`), table counts, connection paths, and seamless database switching.
141
+
142
+ ### 🛡️ Strict Read-Only & Serverless Mode
143
+ * **Serverless Ready:** Auto-detects ephemeral serverless environments (Vercel, AWS Lambda, Cloudflare Pages, Netlify, GCP Cloud Functions).
144
+ * **Smart Serverless Editability Rule:**
145
+ * **SQLite** defaults to **read-only** in serverless mode to prevent data loss on ephemeral filesystems.
146
+ * **PostgreSQL** is **fully editable and writable** in serverless mode because it connects to persistent remote database services.
147
+ * Includes ready-to-use `createServerlessHandler` and `createLambdaHandler` wrappers.
99
148
 
100
- | Option | Type | Description |
101
- | ---------- | -------------------- | -------------------------------------------------------------- |
102
- | `dbPath` | `string` | Path to a single SQLite file (single-db mode). Default: `admindb.db` |
103
- | `db` | `SqliteDatabase` | An already-open database instance (advanced embedding) |
104
- | `manager` | `DbManager` | Enables multi-database mode (see below) |
105
- | `basePath` | `string` | URL prefix used by templates/assets (e.g. `/admin`). Pass the same prefix you mount at |
106
- | `logger` | `Logger` | Custom logger (see `createLogger`) |
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 |
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` |
149
+ ---
150
+
151
+ ## 🚀 Embed AdminDB in Express
111
152
 
112
- Example with a custom logger and prefix:
153
+ AdminDB can be mounted directly into any existing Express application under any subpath on the same port:
113
154
 
114
155
  ```ts
115
156
  import express from 'express';
116
- import { createRouter, createLogger } from 'admindb';
157
+ import { createRouter } from 'admindb';
117
158
 
118
159
  const app = express();
119
- app.use('/tools/db', createRouter({
160
+
161
+ app.get('/', (_req, res) => res.send('Main App'));
162
+
163
+ // Mount AdminDB for SQLite
164
+ app.use('/admin', createRouter({
120
165
  dbPath: './data/app.db',
121
- basePath: '/tools/db',
122
- logLevel: 'info',
166
+ basePath: '/admin',
167
+ }));
168
+
169
+ // Or mount AdminDB for PostgreSQL
170
+ app.use('/admin-pg', createRouter({
171
+ connection: 'postgresql://postgres:secret@localhost:5432/mydb',
172
+ basePath: '/admin-pg',
123
173
  }));
124
- app.listen(3000);
174
+
175
+ app.listen(45531, () => {
176
+ console.log('App running on http://localhost:45531 (Admin: http://localhost:45531/admin)');
177
+ });
125
178
  ```
126
179
 
127
- ### Multiple databases
180
+ > 📖 **Full Options & Advanced Embedding Recipes:**
181
+ > See [**`docs/EXAMPLES.md`**](docs/EXAMPLES.md#-part-2-programmatic-code-examples-express--typescript) for the complete `createRouter` options reference, multi-database management (`DbManager`), custom loggers, read-only mode, and custom authentication configurations.
128
182
 
129
- Pass a `DbManager` to manage several database files — either from a directory,
130
- from an explicit list of file paths, or both:
183
+ ---
131
184
 
132
- ```ts
133
- import express from 'express';
134
- import { createRouter, DbManager, createLogger } from 'admindb';
185
+ ## ⚙️ CLI & Environment Variables
186
+
187
+ Every setting can be configured via **CLI flags**, **Environment Variables**, or **JSON Configuration Files** (CLI flags override JSON config, which overrides environment variables):
188
+
189
+ | Setting | CLI Flag & Aliases | Environment Variable & Aliases | Default | Description |
190
+ | :--- | :--- | :--- | :--- | :--- |
191
+ | **Config File** | `-C, --config <file.json>` | `ADMINDB_CONFIG` | — | Path to a JSON configuration file containing database credentials & settings |
192
+ | **Port** | `-p, --port <port>` | `PORT`, `ADMINDB_PORT` | `45531` | Port to listen on |
193
+ | **Host** | `-H, --host <host>` | `HOST`, `ADMINDB_HOST` | `0.0.0.0` | Host / interface to bind |
194
+ | **Connection URI** | `-c, --connection, --pg <uri>` | `DATABASE_URL`, `ADMINDB_CONNECTION`, `PG_CONNECTION` | — | PostgreSQL connection URI or path |
195
+ | **Single DB** | `-o, --open, --db-path <file>` | `DB_PATH`, `ADMINDB_DB_PATH`, `ADMINDB_PATH` | — | Open a single database file directly |
196
+ | **Database Dir** | `-d, --dir, --db-dir <dir>` | `DB_DIR`, `ADMINDB_DB_DIR`, `ADMINDB_DIR` | — | Folder of database files to manage |
197
+ | **Explicit Files** | `--files, --db-files <list>` | `DB_FILES`, `ADMINDB_DB_FILES` | — | Comma-separated database file paths |
198
+ | **Base Path** | `-b, --base-path, --base <p>` | `BASE_PATH`, `ADMINDB_BASE_PATH` | `''` (`/`) | URL prefix to serve under (e.g. `/admin`) |
199
+ | **Read-Only** | `-r, --readonly, --read-only`| `READONLY`, `ADMINDB_READONLY` | `false` | Open databases read-only (writes disabled) |
200
+ | **Serverless**| `--serverless` | `SERVERLESS`, `ADMINDB_SERVERLESS` | `false` *(auto)* | Serverless mode (SQLite read-only, Postgres editable) |
201
+ | **Auth** | `--auth` / `--no-auth` | `ADMINDB_AUTH`, `ADMINDB_NO_AUTH` | `true` | Enable or disable built-in authentication |
202
+ | **Username** | `-u, --username, --user <user>` | `ADMINDB_USERNAME`, `ADMINDB_USER` | `admin` | Admin username |
203
+ | **Password** | `-P, --password, --pass <pass>` | `ADMINDB_PASSWORD`, `ADMINDB_PASS` | `admin` *(hash)* | Admin password or salted `scrypt:...` hash |
204
+ | **Session Secret**| `--auth-secret, --secret <sec>` | `ADMINDB_SECRET`, `SESSION_SECRET` | *(auto)* | Secret key for signing session cookies |
205
+ | **Log Level** | `-l, --log-level <level>` | `LOG_LEVEL`, `ADMINDB_LOG_LEVEL` | `info` | `debug` \| `info` \| `warn` \| `error` |
206
+ | **Help** | `-h, --help` | — | — | Show CLI help |
207
+ | **Version** | `-v, --version` | — | — | Show version |
208
+
209
+ Quick CLI examples:
135
210
 
136
- const app = express();
137
- app.use('/admin', createRouter({
138
- manager: new DbManager(
139
- {
140
- dir: './data', // scan a directory
141
- files: ['/srv/legacy/app.db', './shared.sqlite'], // and/or explicit paths
142
- readonly: true, // open all databases read-only
143
- },
144
- createLogger('info'),
145
- ),
146
- basePath: '/admin',
147
- }));
211
+ ```bash
212
+ admindb name.postgres.json # Load credentials from JSON file
213
+ admindb postgresql://user:pass@host:5432/db # Open PostgreSQL database
214
+ admindb ./data/app.db # Open SQLite database
215
+ admindb -d ./databases # Manage a folder of databases
216
+ admindb -p 8080 # Run on port 8080
217
+ admindb --no-auth # Authentication disabled
148
218
  ```
149
219
 
150
- In multi-db mode:
151
-
152
- - a **"Databases" landing page** lets you open, create, and delete database files,
153
- - every database is scoped under its file name, e.g.
154
- `/admin/app.db/tables/users` and `/admin/app.db/api/tables`,
155
- - file names that collide across sources are deduped (`name__2.db`).
156
-
157
- ## Features
158
-
159
- - Browse every table and its rows (paginated, with primary-key awareness).
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.
172
- - **Export** table rows or query results as **CSV or JSON**, and **import a CSV
173
- file** (or pasted CSV) into a table.
174
- - Create tables visually: name, type, primary key, not-null / unique,
175
- default value, and foreign-key references.
176
- - Write and run arbitrary SQL — SELECTs render as a table, `COUNT` queries show
177
- a readable summary, write statements execute and report affected rows.
178
- - Save named queries and reload them from a dropdown.
179
- - Export the whole database as a downloadable SQL dump (`CREATE` + `INSERT`).
180
- - **Get query / preview mode:** generate `CREATE` / `INSERT` / `UPDATE` SQL from
181
- the UI without executing it.
182
- - **Edit schema:** rename the table, add / rename / drop columns (with
183
- relationship-safety checks), and drop tables.
184
- - **Indexes:** create indexes (plain or unique, on one or many columns — pick
185
- columns in order, with a live `CREATE INDEX` SQL preview) and drop them from
186
- the schema editor; automatic SQLite indexes are protected.
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.
191
- - **Read-only mode:** open the database(s) without write access — the file is
192
- opened `SQLITE_OPEN_READONLY` + `query_only`, every write route returns `403`,
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`).
198
- - **Multiple databases:** directory scanning and/or explicit file lists, each
199
- with its own workspace under `/{db}/…`.
200
-
201
- ## Screenshots
202
-
203
- Home dashboard — stat cards and the table list.
220
+ > 📖 **Full Configuration Reference & Deployment Recipes:**
221
+ > See [**`docs/EXAMPLES.md`**](docs/EXAMPLES.md) for detailed variable explanations, reasons/use cases, and ready-to-run recipes for Bash, PowerShell, Docker, Docker Compose, and Nginx.
204
222
 
205
- ![Home dashboard](docs/screenshots/home.png)
223
+ ---
206
224
 
207
- Table browser — sortable columns, sticky header, and per-row actions.
225
+ ## 🔒 Authentication & Security
208
226
 
209
- ![Table browser](docs/screenshots/table.png)
227
+ > [!WARNING]
228
+ > **Important Security Notice:**
229
+ > AdminDB's built-in native authentication provides **basic single-user access control** for local development and private internal tools.
230
+ > For production environments and internet-facing networks, **it is entirely the user's responsibility to protect AdminDB** by placing it behind your own web application's authentication (e.g. NextAuth, Passport, OAuth2/OIDC middleware), an IP-restricted VPN, or a secure reverse proxy with TLS/HTTPS.
210
231
 
211
- Query editor — line-numbered editor with a results table.
232
+ ### Generate a Secure Password Hash
212
233
 
213
- ![Query editor](docs/screenshots/query.png)
234
+ To configure custom credentials with a salted cryptographic `scrypt` hash:
214
235
 
215
- Table designer — visual columns with a live SQL preview.
236
+ ```bash
237
+ npm run generatehash
238
+ ```
239
+
240
+ Paste the resulting hash into `ADMINDB_PASSWORD`, CLI `-P`, or your Express configuration:
216
241
 
217
- ![Table designer](docs/screenshots/designer.png)
242
+ ```bash
243
+ ADMINDB_USERNAME="ops" ADMINDB_PASSWORD="scrypt:8011bcda...:85465796..." npx admindb
244
+ ```
218
245
 
219
- Insert / edit form — column defaults are pre-filled.
246
+ ### Wrapping with Your Own Express Authentication (Recommended for Production)
220
247
 
221
- ![Insert form](docs/screenshots/form.png)
248
+ When embedding AdminDB in your Express application, turn off built-in auth (`auth: false`) and protect the route with your existing auth middleware:
222
249
 
223
- Schema editor — rename the table, add / rename / drop columns safely.
250
+ ```ts
251
+ import express from 'express';
252
+ import { createRouter } from 'admindb';
224
253
 
225
- ![Schema editor](docs/screenshots/schema.png)
254
+ const app = express();
226
255
 
227
- Databases landing page (multi-db mode) — manage multiple SQLite files.
256
+ app.use('/admin', requireYourAppAuth, createRouter({
257
+ connection: process.env.DATABASE_URL,
258
+ basePath: '/admin',
259
+ auth: false, // Turn off built-in login form; rely on requireYourAppAuth
260
+ }));
228
261
 
229
- ![Databases](docs/screenshots/databases.png)
262
+ app.listen(45531);
263
+ ```
230
264
 
231
- ## Run the built-in server
265
+ ### Disabling Built-in Authentication
232
266
 
233
- For convenience a standalone server is included. From a clone of the repo:
267
+ When deploying behind an external gateway (Cloudflare Zero Trust, OAuth2 Proxy, Authelia):
234
268
 
235
269
  ```bash
236
- npm install
237
- npm run build
238
- npm start # open http://localhost:3000
270
+ admindb --no-auth
271
+ # or
272
+ ADMINDB_AUTH=false npx admindb
239
273
  ```
240
274
 
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:
275
+ > 📖 **Full Security Guide:** See [**`docs/SECURITY.md`**](docs/SECURITY.md) for the shared security model, filesystem sandboxing, PostgreSQL remote protection, and production deployment checklists.
276
276
 
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
- ```
285
277
 
286
- ```powershell
287
- $env:DB_DIR='./db'; npm start # PowerShell
288
- # bash/zsh: DB_DIR=./db npm start
278
+ ---
279
+
280
+ ## 📡 REST API
281
+
282
+ AdminDB exposes a comprehensive REST API under `basePath` returning `{ success, data?, error? }`:
283
+
284
+ ```text
285
+ GET /api/tables List tables
286
+ GET /api/tables/:table/rows Paginated rows (with filtering & sorting)
287
+ GET /api/tables/:table/row/:id Get a single row
288
+ GET /api/tables/:table/row/:id/blob/:column Stream raw BLOB / BYTEA binary data
289
+ GET /api/tables/:table/row/:id/blob/:col/meta BLOB / BYTEA metadata, MIME analysis & hex dump
290
+ PUT /api/tables/:table/row/:id/blob/:column Upload / update binary content
291
+ POST /api/tables/:table/rows Insert row (single or batch)
292
+ PUT /api/tables/:table/row/:id Update row
293
+ DELETE /api/tables/:table/row/:id Delete row
294
+ POST /api/tables/:table/rows/bulk-update Apply staged inline edits atomically
295
+ POST /api/tables/:table/rows/bulk-delete Delete selected rows atomically
296
+ POST /api/tables/:table/seed Generate & insert realistic seed rows
297
+ POST /api/tables Create a new table
298
+ GET /api/tables/:table/schema Inspect table schema & constraints
299
+ GET /api/tables/:table/ddl Get table CREATE SQL & indexes
300
+ POST /api/query Execute arbitrary SQL
301
+ GET /api/databases List managed database connections & files
289
302
  ```
290
303
 
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
-
305
- ## The JSON REST API (under `basePath`)
306
-
307
- | Method | Path | Purpose |
308
- | ------ | ---------------------------------------- | -------------------------------- |
309
- | GET | `/api/tables` | List tables |
310
- | GET | `/api/tables/:table/info` | Column + FK metadata, PK columns |
311
- | GET | `/api/tables/:table/fk-options` | Values for FK dropdowns |
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"}}`) |
313
- | GET | `/api/tables/:table/row/:id` | Single row by (encoded) PK |
314
- | POST | `/api/tables/:table/rows` | Insert row |
315
- | POST | `/api/tables/:table/rows/generate` | Generate INSERT SQL (no execute) |
316
- | POST | `/api/tables/:table/rows/import` | Import CSV (`{ csv }`, header row must match columns) |
317
- | GET | `/api/tables/:table/export?format=` | Download all rows as `csv` or `json` |
318
- | PUT | `/api/tables/:table/row/:id` | Update row (`{ values, nulls? }` — `nulls` explicitly sets columns to NULL) |
319
- | PUT | `/api/tables/:table/row/:id/generate` | Generate UPDATE SQL (no execute) |
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) |
325
- | POST | `/api/tables` | Create table |
326
- | POST | `/api/tables/generate` | Generate CREATE SQL (no execute) |
327
- | GET | `/api/tables/:table/schema` | Full schema (constraints, indexes, FK refs) |
328
- | POST | `/api/tables/:table/rename` | Rename the table |
329
- | POST | `/api/tables/:table/columns` | Add a column |
330
- | PUT | `/api/tables/:table/columns/:column` | Rename a column |
331
- | DELETE | `/api/tables/:table/columns/:column` | Drop a column (safety-checked) |
332
- | DELETE | `/api/tables/:table` | Drop the table (safety-checked) |
333
- | POST | `/api/tables/:table/indexes` | Create an index (`{ name?, columns[], unique? }`) |
334
- | DELETE | `/api/tables/:table/indexes/:index` | Drop an index (auto indexes refused) |
335
- | POST | `/api/query` | Run arbitrary SQL |
336
- | POST | `/api/query/export` | Run a SELECT and download as `csv`/`json` |
337
- | GET | `/api/queries` | List saved queries |
338
- | POST | `/api/queries` | Save a named query |
339
- | DELETE | `/api/queries/:id` | Delete a saved query |
340
-
341
- In multi-db mode, every route is scoped under the database, e.g.
342
- `/api/app.db/tables`. Every API response uses the consistent shape
343
- `{ success, data?, error? }`.
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
-
356
- ## Behaviour notes
357
-
358
- - **Empty input = "not set".** Empty form fields are omitted so DB defaults
359
- apply; `0` is a valid value and is never treated as empty.
360
- - **Insert forms pre-fill defaults.** On the "new row" form, columns that have
361
- a schema default are pre-filled (string/number/boolean literals and
362
- `CURRENT_TIMESTAMP`-style defaults) so you can see and adjust them.
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.
383
- - **CSV import.** The first row must be a header whose names match existing
384
- columns (unknown or duplicate names are rejected). Empty cells are treated as
385
- "not set" so database defaults apply. The whole import runs in a single
386
- transaction — a failed row rolls everything back.
387
- - **Indexes.** Creating an index takes one or more columns and an optional
388
- unique flag (the index name is optional too). Only explicitly created indexes
389
- (`origin = 'c'`) can be dropped from the UI — automatic primary-key/unique
390
- indexes are protected.
391
- - **Schema editor.** Drops are refused when the column is a primary key, has a
392
- UNIQUE constraint, is used by an index, is part of a foreign key, or is
393
- referenced by another table's foreign key. Tables referenced by other tables
394
- cannot be dropped. Internal (`_`-prefixed) tables cannot be renamed or dropped.
395
- - **Identifiers are quoted and string values escaped** everywhere SQL is built,
396
- so generated SQL is correct and safe.
397
- - **`COUNT` queries** return a readable summary message instead of a table.
398
- - **"Get query" never executes** — it only returns the generated SQL string.
399
- - **Internal table** `_saved_queries` stores saved queries and is kept out of
400
- user-facing FK pickers. Schema initialization is idempotent and safe to run
401
- repeatedly.
402
- - Composite primary keys are supported (values are URL-encoded and comma-joined
403
- in the row endpoints).
404
-
405
- ## Development
304
+ > 📖 **Full API Reference:** See [**`docs/API.md`**](docs/API.md) for detailed documentation of all 30+ endpoints, query parameters, payload schemas, and TypeScript types.
406
305
 
407
- ```bash
408
- npm install
409
- npm run build # TypeScript → dist + Tailwind CSS
410
- npm run dev # tsx watch server + Tailwind watch
411
- npm test # builds and runs the unit tests
412
- ```
306
+ ---
307
+
308
+ ## 📚 Documentation Index
413
309
 
414
- `npm test` compiles TypeScript to `dist/` and runs the `node:test` suite
415
- covering the SQL generator (INSERT / UPDATE / CREATE output, type mapping,
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.
310
+ | Document | Description |
311
+ | :--- | :--- |
312
+ | [**`docs/EXAMPLES.md`**](docs/EXAMPLES.md) | Comprehensive Environment Variables reference, JSON configs, Express code examples, and deployment recipes. |
313
+ | [**`docs/SECURITY.md`**](docs/SECURITY.md) | Authentication architecture, password hashing, reverse proxy setup, and security checklist. |
314
+ | [**`docs/API.md`**](docs/API.md) | Complete REST API endpoint reference and TypeScript type exports. |
315
+ | [**`CONTRIBUTING.md`**](CONTRIBUTING.md) | Development workflow, running tests, project layout, and contribution guidelines. |
420
316
 
421
- ## Publishing to npm
317
+ ---
318
+
319
+ ## 🤝 Contributing
422
320
 
423
- The package ships the compiled `dist/` (with type declarations), this `README`,
424
- and the `LICENSE`. When you are ready to publish:
321
+ Contributions are welcome! Please check out [**`CONTRIBUTING.md`**](CONTRIBUTING.md) for development setup and testing instructions.
425
322
 
426
323
  ```bash
427
- npm run build # happens automatically via the prepack script
428
- npm login
429
- npm publish
324
+ git clone https://github.com/MIbnEKhalid/admindb.git
325
+ cd admindb
326
+ npm install
327
+ npm run dev # Live reload development server
328
+ npm test # Run comprehensive unit test suite
430
329
  ```
431
330
 
432
- Update `name`/`version` in `package.json` to match your intended package name
433
- and add an `author`/`repository` if desired.
331
+ ---
434
332
 
435
- ## License
333
+ ## 📄 License
436
334
 
437
- [MIT](./LICENSE) — see the [LICENSE](LICENSE) file.
335
+ [MIT](./LICENSE) © MIbnEKhalid