midql-cli 0.1.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/LICENSE +21 -0
- package/README.md +152 -0
- package/dist/App-W6AAY42M.js +568 -0
- package/dist/chunk-3CIK5I4M.js +396 -0
- package/dist/chunk-3FPZQHHV.js +77 -0
- package/dist/chunk-3QAR6XBK.js +200 -0
- package/dist/chunk-7WNCISNV.js +106 -0
- package/dist/chunk-ATZPL4EX.js +35 -0
- package/dist/chunk-BAAEZXFH.js +73 -0
- package/dist/chunk-GWY47EDH.js +11 -0
- package/dist/chunk-NCN3ZBOJ.js +93 -0
- package/dist/chunk-PXDMSYWH.js +18 -0
- package/dist/chunk-TLTYYFT5.js +237 -0
- package/dist/chunk-VFC3HWTF.js +52 -0
- package/dist/chunk-WN6T44OZ.js +1643 -0
- package/dist/chunk-XJAN6OQ7.js +25 -0
- package/dist/cli.js +101 -0
- package/dist/controller-HDNDKU6K.js +18 -0
- package/dist/csv-F2MFR3XB.js +7 -0
- package/dist/dump-LQ7ULAAL.js +11 -0
- package/dist/execute-E45HSHNE.js +155 -0
- package/dist/humanize-UG6KBAFO.js +100 -0
- package/dist/index.d.ts +185 -0
- package/dist/index.js +55 -0
- package/dist/json-Z56V7OEB.js +7 -0
- package/dist/maintenance-QHIUTVV3.js +49 -0
- package/dist/meta-NZ5Z6NYN.js +369 -0
- package/dist/mysql-GQSXUUEK.js +204 -0
- package/dist/profiles-4QGMCJAO.js +67 -0
- package/dist/query-RCUXCOAF.js +122 -0
- package/dist/restore-4QXG2WRR.js +9 -0
- package/package.json +74 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Eser Sariyar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# MidQL
|
|
2
|
+
|
|
3
|
+
Fast, safety-first PostgreSQL/MySQL CLI for developers — schema-aware autocomplete, natural-language shortcuts, and previews before anything destructive runs.
|
|
4
|
+
|
|
5
|
+
MidQL is a modern alternative to `psql`/`mysql` built around two ideas:
|
|
6
|
+
|
|
7
|
+
- **Speed** — raw SQL is first-class with schema-aware tab completion, and a rule-based natural-language layer turns `show users where rank 20` into SQL faster than you can type the full SELECT. Cross-table filters like `select users which has money > 20` discover the JOIN path from foreign keys automatically.
|
|
8
|
+
- **Control** — DELETE/UPDATE/DROP show the affected rows and ask for confirmation before running, production connections are visually distinct and can be locked read-only, and every statement is written to a local audit history.
|
|
9
|
+
|
|
10
|
+
Everything runs offline: the natural-language engine is rule-based and schema-driven. No API keys, no telemetry.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install -g midql-cli
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Requires Node 18+. The installed command is `midql`.
|
|
19
|
+
|
|
20
|
+
## Quickstart
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
midql postgres://user:pass@localhost:5432/mydb
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
midql (mydb:mydb)> show users where rank > 10
|
|
28
|
+
→ SELECT * FROM "users" WHERE "rank" > $1 $1=10
|
|
29
|
+
┌────┬───────┬───────────────────┬──────┐
|
|
30
|
+
│ id │ name │ email │ rank │
|
|
31
|
+
...
|
|
32
|
+
|
|
33
|
+
midql (mydb:mydb)> SELECT count(*) FROM orders JOIN users ON users.id = orders.user_id;
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Plain English and raw SQL work side by side — input that starts with a SQL keyword and looks like SQL runs as-is; everything else goes through the natural-language engine. The generated SQL is always previewed under the input line before you press Enter, and echoed with the results after.
|
|
37
|
+
|
|
38
|
+
## Natural language cookbook
|
|
39
|
+
|
|
40
|
+
| You type | MidQL runs |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `show all users` | `SELECT * FROM users` |
|
|
43
|
+
| `search users which has rank 20` | `SELECT * FROM users WHERE rank = 20` |
|
|
44
|
+
| `show name and email of users` | `SELECT name, email FROM users` |
|
|
45
|
+
| `select users which has money > 20` | `SELECT users.* FROM users JOIN accounts ON … WHERE accounts.money > 20` (join inferred from foreign keys) |
|
|
46
|
+
| `show users whose email contains gmail` | `… WHERE email ILIKE '%gmail%'` |
|
|
47
|
+
| `show orders where status in pending, paid` | `… WHERE status IN (…)` |
|
|
48
|
+
| `show users where rank between 5 and 10` | `… WHERE rank BETWEEN 5 AND 10` |
|
|
49
|
+
| `show users sorted by rank descending first 10` | `… ORDER BY rank DESC LIMIT 10` |
|
|
50
|
+
| `show user john` / `show user 42` | name / primary-key lookup |
|
|
51
|
+
| `count users` / `how many users have rank 20` | `SELECT COUNT(*) …` |
|
|
52
|
+
| `average money of users` | `SELECT AVG(accounts.money) FROM users JOIN accounts …` |
|
|
53
|
+
| `add user with name john and rank 5` | `INSERT INTO users (name, rank) VALUES (…)` |
|
|
54
|
+
| `update users set rank to 10 where name is john` | `UPDATE users SET rank = … WHERE …` |
|
|
55
|
+
| `change rank of user john to 10` | same as above |
|
|
56
|
+
| `delete users which has rank 0` | `DELETE FROM users WHERE …` (with preview + confirmation) |
|
|
57
|
+
| `create table pets with name text, age number, owner references users` | `CREATE TABLE pets (id SERIAL PRIMARY KEY, …)` |
|
|
58
|
+
| `drop table pets` | `DROP TABLE pets` (typed-name confirmation) |
|
|
59
|
+
| `describe users` / `what is in users` | table structure |
|
|
60
|
+
| `show tables` | table list |
|
|
61
|
+
|
|
62
|
+
Operator words: `is`, `is not`, `greater than` / `more than` / `over` / `above`, `less than` / `under` / `below`, `at least`, `at most`, `contains`, `starts with`, `ends with`, `between … and …`, `in a, b or c`, `is null`, `is not null`. Combine with `and`/`or` (`and` binds tighter).
|
|
63
|
+
|
|
64
|
+
Table and column names are matched fuzzily against the live schema — singular/plural (`user` → `users`), underscores (`firstname` → `first_name`), and small typos (`usres` → `users`) all resolve. When a reference is genuinely ambiguous, MidQL lists the candidates instead of guessing; qualify with `table.column` to be explicit.
|
|
65
|
+
|
|
66
|
+
All values are sent as bound parameters — never interpolated into SQL — so injection through the natural-language layer is structurally impossible.
|
|
67
|
+
|
|
68
|
+
## Safety model
|
|
69
|
+
|
|
70
|
+
- **destructive** (DELETE/UPDATE with WHERE): MidQL first runs a count and a 10-row sample of the affected rows, shows them, and asks `Proceed? [y/N]` (default No).
|
|
71
|
+
- **catastrophic** (DROP TABLE, TRUNCATE, DELETE/UPDATE without WHERE): confirmation requires typing the table name. Statements without a WHERE clause are called out explicitly.
|
|
72
|
+
- `\safe off` reduces checks to a one-line warning — except on connections tagged `prod`, where safety is always enforced and the prompt turns red (`midql (prod:mydb)!>`).
|
|
73
|
+
- `\readonly on` (or `readonly: true` in the profile) blocks every write before it reaches the driver.
|
|
74
|
+
- One-shot mode (`midql query`) refuses destructive statements without `--yes` and prints the row count it would have affected.
|
|
75
|
+
- Every input is appended to `~/.midql/history.jsonl` with timestamp, connection, generated SQL, and outcome — a local audit trail.
|
|
76
|
+
|
|
77
|
+
## REPL reference
|
|
78
|
+
|
|
79
|
+
- Input starting with a SQL keyword runs as raw SQL on a **pinned session connection**, so `BEGIN` / `COMMIT` / `ROLLBACK` work naturally; an open transaction shows a `[tx]` badge in the prompt.
|
|
80
|
+
- **Tab** accepts the top completion (verbs → tables → columns → operators, context-aware in both NL and SQL modes). Columns reachable through a foreign key are annotated `(accounts, joined)`.
|
|
81
|
+
- **↑/↓** history, **Ctrl+R** history search, **Ctrl+C** clear line (twice to exit), **Ctrl+A/E** home/end, **Esc** dismiss.
|
|
82
|
+
|
|
83
|
+
| Command | Description |
|
|
84
|
+
|---|---|
|
|
85
|
+
| `\c <profile\|url> [alias]` | connect (multiple connections at once) |
|
|
86
|
+
| `\use <alias>` | switch the active connection |
|
|
87
|
+
| `\connections` | list open connections |
|
|
88
|
+
| `\disconnect <alias>` | close a connection |
|
|
89
|
+
| `\tables`, `\d <table>` | list tables / describe a table |
|
|
90
|
+
| `\refresh` | reload the schema cache |
|
|
91
|
+
| `\sql` | lock raw SQL mode (skip NL parsing) |
|
|
92
|
+
| `\safe on\|off`, `\readonly on\|off` | toggle safety / read-only |
|
|
93
|
+
| `\history [search]` | show recent inputs |
|
|
94
|
+
| `\export csv\|json <file>` | export the last result |
|
|
95
|
+
| `\backup [file] [sql]` | pg_dump / mysqldump the active database |
|
|
96
|
+
| `\restore <file>` | restore from a backup (typed confirmation) |
|
|
97
|
+
| `\explain` | re-run the last SELECT with EXPLAIN, summarized in plain English |
|
|
98
|
+
| `\help`, `\q` | help / quit |
|
|
99
|
+
|
|
100
|
+
## Profiles and one-shot commands
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
midql profiles add main --dialect postgres --host db.example.com --database app \
|
|
104
|
+
--user deploy --password-env PGPASSWORD --env prod --readonly
|
|
105
|
+
|
|
106
|
+
midql profiles list
|
|
107
|
+
midql main # open the REPL on a saved profile
|
|
108
|
+
|
|
109
|
+
midql query "count users" --db main
|
|
110
|
+
midql query "delete users which has rank 0" --db dev --yes
|
|
111
|
+
midql query "show users" --db main --format json > users.json
|
|
112
|
+
|
|
113
|
+
midql backup --db main # pg_dump -Fc → midql-app-<timestamp>.dump
|
|
114
|
+
midql restore backup.dump --db dev --yes
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Environment tags (`--env dev|staging|prod`) color the prompt and harden confirmations on prod. Backup/restore shells out to `pg_dump`/`pg_restore`/`psql`/`mysqldump`/`mysql`; if a tool is missing MidQL tells you how to install it or set an explicit path in the config.
|
|
118
|
+
|
|
119
|
+
## Configuration
|
|
120
|
+
|
|
121
|
+
`~/.midql/config.json`:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"profiles": [],
|
|
126
|
+
"safety": "on",
|
|
127
|
+
"maxJoinDepth": 3,
|
|
128
|
+
"tools": { "pgDumpPath": null, "pgRestorePath": null, "psqlPath": null, "mysqldumpPath": null, "mysqlPath": null }
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Set `MIDQL_HOME` to relocate the config directory.
|
|
133
|
+
|
|
134
|
+
### Credential storage
|
|
135
|
+
|
|
136
|
+
Saved passwords are encrypted with AES-256-GCM using a random key generated at first run into `~/.midql/.key` (file mode 600). This protects against casual disclosure of the config file — it is not a defense against an attacker with full access to your OS account. Prefer `--password-env` to reference an environment variable, or omit the password entirely for URL-based ad-hoc connections.
|
|
137
|
+
|
|
138
|
+
## Development
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
npm install
|
|
142
|
+
npm test # unit tests (no database needed)
|
|
143
|
+
docker compose -f docker/docker-compose.yml up -d --wait
|
|
144
|
+
npm run test:int # integration tests against seeded PG 16 + MySQL 8
|
|
145
|
+
npm run build
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The natural-language engine is pure functions over a schema snapshot — see `test/fixtures/` for the schemas the unit tests run against.
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
MIT © [Eser Sariyar](https://github.com/esersariyar)
|