@farhan0431/db-snap 0.3.11 → 0.4.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 CHANGED
@@ -10,12 +10,19 @@ Supports **SQLite**, **PostgreSQL**, and **MySQL/MariaDB**. The npm package
10
10
  bundles prebuilt binaries for Windows x64, macOS Intel and Apple Silicon, and
11
11
  Linux x64 (glibc and musl) and ARM64 (glibc).
12
12
 
13
- **MySQL/MariaDB restore is available for the original database.** Stop writers and scheduled events first. Restore is not atomic and requires a pinned safety snapshot. Interrupted restores must recover that snapshot before another restore.
13
+ **MySQL/MariaDB restore works on the original database.** Stop application
14
+ connections, writers, and scheduled events first. Restore is non-atomic and
15
+ requires a pinned safety snapshot. Interrupted restores must recover that
16
+ snapshot before another restore; see the recovery steps below.
14
17
 
15
18
  ## Install
16
19
 
17
20
  Requires Node.js 16 or later.
18
21
 
22
+ The verify/doctor/recover/exec/live-diff/row-preview/sandbox additions described
23
+ below are in the current repository after v0.3.14; a new published binary is
24
+ required to use them. Check `dbsnap --help` for the commands in your installation.
25
+
19
26
  ```bash
20
27
  npm install -g @farhan0431/db-snap
21
28
  dbsnap --version
@@ -43,7 +50,8 @@ dbsnap list
43
50
  dbsnap restore "before migration" # restores the selected snapshot
44
51
  ```
45
52
 
46
- `dbsnap init` detects `DATABASE_URL` or common SQLite paths. To choose a
53
+ Target resolution is `--db`, then process `DATABASE_URL`, then project `.env`,
54
+ then common SQLite paths. To choose a
47
55
  database explicitly, use `dbsnap init --db ./prisma/dev.db`. Check the target
48
56
  with `dbsnap status` before restoring: a restore changes the live database.
49
57
 
@@ -69,15 +77,40 @@ the following to your project's `.cursor/mcp.json`:
69
77
  Restart your client and ask it to run `dbsnap_status` to confirm the database
70
78
  before making changes. The server also exposes tools to create, list, restore,
71
79
  and prune snapshots. It resolves the project from its working directory, so
72
- start it in the project you want to protect.
80
+ start it in the project you want to protect. The current source exposes ten tools:
81
+
82
+ | MCP tool | Purpose |
83
+ | --- | --- |
84
+ | `dbsnap_status` | Inspect the target, engine, and snapshot storage. |
85
+ | `dbsnap_create_snapshot` | Save a snapshot, optionally supplying `tag`. |
86
+ | `dbsnap_list_snapshots` | List available restore points. |
87
+ | `dbsnap_diff` | Compare supported snapshots using `from` and `to`. |
88
+ | `dbsnap_restore_snapshot` | Restore a selected `tag_or_id`, or the newest snapshot. |
89
+ | `dbsnap_prune` | Prune with a positive integer `keep`; pinned snapshots survive. |
90
+ | `dbsnap_verify` | Check snapshot hashes/sizes/chunks, or clone existence; no SQL replay. |
91
+ | `dbsnap_doctor` | Report connectivity, journals, pending GC and untracked files. |
92
+ | `dbsnap_diff_live` | Save and retain a live checkpoint, then compare it with `from`. |
93
+ | `dbsnap_diff_rows` | Bounded SQLite primary-key row-change counts using `from`, `to`, and `table`. |
94
+
95
+ Results include text plus structured `ok`, `message`, optional typed `data` and
96
+ broad error codes. Snapshot creation returns the exact ID in data. Annotations
97
+ describe behavior but do not replace session permissions or elicitation.
73
98
 
74
99
  Restore and prune are disabled by default in MCP. To enable them for a server
75
100
  session, start it with `dbsnap mcp --allow-destructive`. Each operation requires
76
101
  approval through an MCP client supporting elicitation; otherwise use the CLI.
77
102
 
103
+ To configure an explicitly enabled session, change the server arguments to
104
+ `["mcp", "--allow-destructive"]`. Enabling the session does not approve individual
105
+ operations. Your MCP client must still present and return the confirmation for
106
+ each restore or prune.
107
+
78
108
  `dbsnap init` also writes `.agents/skills/dbsnap/SKILL.md` in the project.
79
109
  Whether that skill is loaded automatically depends on the AI client; the skill
80
110
  file and the MCP server are separate integrations.
111
+ Initialization preserves an existing skill file instead of overwriting local
112
+ customizations. Updating the installed binary does not refresh that existing
113
+ file; review it against the repository's current skill when upgrading.
81
114
 
82
115
  ## Commands
83
116
 
@@ -90,14 +123,115 @@ file and the MCP server are separate integrations.
90
123
  | `dbsnap restore [tag-or-id]` | Restore a snapshot; omit the selector for the latest. |
91
124
  | `dbsnap rollback` | Restore the latest snapshot. |
92
125
  | `dbsnap prune --keep 5` | Remove older snapshots and retain the newest five. |
93
- | `dbsnap diff before after` | Compare SQLite snapshot schemas and table row counts. |
126
+ | `dbsnap diff before after` | Compare SQLite, PostgreSQL clone, or MySQL/MariaDB dump snapshot schemas and row counts. |
94
127
  | `dbsnap pin <tag-or-id>` | Protect a snapshot from pruning; use `unpin` to remove protection. |
95
-
96
- `dbsnap list --json` and `dbsnap status --json` provide machine-readable
97
- output. SQLite `diff` does not compare individual row contents; PostgreSQL and
98
- MySQL/MariaDB snapshot diffs are not currently supported.
128
+ | `dbsnap unpin <tag-or-id>` | Remove protection after reviewing the snapshot. |
129
+ | `dbsnap prune --all` | Delete all unpinned snapshots. |
130
+ | `dbsnap save tag --method dump` | Create a portable PostgreSQL dump snapshot. |
131
+ | `dbsnap verify [id-or-tag]` | Check one or all active snapshots; integrity/existence is not a restore test. |
132
+ | `dbsnap doctor` | Diagnose connection/recovery and report untracked files without deleting them. |
133
+ | `dbsnap recover` | Resume the recovery journal; ambiguous PostgreSQL states require inspection. |
134
+ | `dbsnap exec -- npm run db:migrate` | Checkpoint before a child command; retain it on failure, with no automatic rollback. |
135
+ | `dbsnap diff-live before` | Capture and retain the current state, then compare. |
136
+ | `dbsnap diff-rows before after --table users` | SQLite-only row-change counts by primary key, default limit 10,000 rows. |
137
+ | `dbsnap sandbox before --output experiment.db` | Fork SQLite into a new file; existing files are never overwritten. |
138
+ | `dbsnap sandbox before` | Create an independent PostgreSQL clone, recorded in `sandboxes.json`. |
139
+ | `dbsnap sandbox before --docker-image mysql:8.0` | Explicit isolated MySQL server; use `mariadb:11` for MariaDB. Docker required. |
140
+
141
+ `dbsnap list --json` and `dbsnap status --json` provide machine-readable output.
99
142
  Pinned snapshots survive `prune`, including `--all`.
100
143
 
144
+ Use the recorded ID when undoing a specific change. Duplicate tags may be
145
+ ambiguous. `rollback` and `restore` without a selector choose the newest
146
+ snapshot, which can be an automatic safety snapshot from a previous restore.
147
+
148
+ ## Snapshot diff
149
+
150
+ ```bash
151
+ dbsnap save before
152
+ # Make your development changes.
153
+ dbsnap save after
154
+ dbsnap diff before after
155
+ ```
156
+
157
+ Diff compares **snapshots**, not the current live database. SQLite compares
158
+ schema objects and row counts. PostgreSQL clone diff compares table/view
159
+ definitions and row counts. MySQL/MariaDB diff reads verified standard dumps
160
+ offline, including multiline `INSERT` data, and compares table definitions
161
+ and row counts. It does not replay SQL into the target.
162
+
163
+ Equal row counts do not mean equal data. Individual row contents are not
164
+ compared. PostgreSQL diff excludes indexes, constraints, routines and triggers;
165
+ MySQL/MariaDB diff excludes views, routines, triggers and events. Unsupported
166
+ INSERT formats produce an error. Source additions after v0.3.14 compare two
167
+ PostgreSQL dump archives offline through `pg_restore`: archive-wide schema
168
+ changes and table counts from column-list COPY data, excluding ownership,
169
+ privileges, row contents and sequence values. Mixed clone/archive diff is
170
+ unsupported. The published v0.3.14 binary does not include archive diff.
171
+
172
+ `diff-rows` additionally supports SQLite added/removed/updated counts without
173
+ printing values. It requires explicit non-NULL primary keys and matching column
174
+ layouts, refusing previews above `--limit` (maximum 100,000). Server-engine row
175
+ diff is not implemented. `diff-live` uses storage and may briefly fence
176
+ PostgreSQL connections because it creates a regular retained snapshot.
177
+
178
+ ## Checkpoints, diagnosis and sandbox experiments
179
+
180
+ `verify` and `doctor` print JSON. Verification failure exits nonzero. Doctor
181
+ reports a failed probe in its report and does not automatically repair anything.
182
+ `recover` reads the existing MySQL journal's ID or applies unambiguous PostgreSQL
183
+ journal recovery. It does not repair a stopped database server or choose an
184
+ arbitrary restore point. SQLite has no server recovery journal.
185
+
186
+ `exec` directly spawns a program without a shell, saving a checkpoint first.
187
+ Snapshot failure prevents execution. Child failure retains the checkpoint and
188
+ returns its ID, exit code and recovery command; the parent exits nonzero. Output
189
+ is returned up to 64 KiB per stream. `--db` selects the checkpoint database, not
190
+ the database your external program will use; set its environment deliberately.
191
+ Arbitrary command execution is CLI-only, not an MCP tool.
192
+
193
+ SQLite and PostgreSQL clone sandboxes let experiments target independent data.
194
+ Connect your migration/application explicitly to the returned file/database.
195
+ Cleanup is manual after closing sandbox connections. MySQL/MariaDB sandboxes
196
+ require explicit `--docker-image mysql:8.0` or `mariadb:11`: a separate Docker
197
+ server imports the verified dump with its original schema name, network disabled,
198
+ no published ports/host mounts/source credentials. Use `docker exec` for SQL
199
+ experiments and remove the returned container explicitly afterwards. Failed
200
+ imports remove only the newly created container. PostgreSQL dump sandbox and
201
+ same-server MySQL SQL rewriting are unsupported. See the workflow guide below.
202
+
203
+ Prune persists retired records in `metadata.json.pending_gc` and retries their
204
+ recorded artifact cleanup on a later prune. Shared survivor data and arbitrary
205
+ untracked files are preserved. Doctor reports pending GC and untracked staging.
206
+ Do not downgrade to an older binary unaware of `pending_gc` while it is nonempty.
207
+
208
+ ## Recovering an interrupted MySQL/MariaDB restore
209
+
210
+ A fresh restore creates, syncs and catalogs a pinned safety snapshot before
211
+ cleanup. It preserves the database itself and replaces objects inside it.
212
+ `--no-safety-snapshot` is rejected for fresh MySQL/MariaDB restores.
213
+
214
+ If restore fails after the recovery journal is written:
215
+
216
+ 1. Keep application writers/connections and scheduled events stopped.
217
+ 2. Fix the reported disk-space, connection or privilege problem. Local free
218
+ space checks do not measure the database server's storage.
219
+ 3. Read the recovery ID in the error or `.dbsnap/mysql-restore.json`, then run:
220
+
221
+ ```bash
222
+ dbsnap restore RECOVERY_ID
223
+ ```
224
+
225
+ The journal stores the recovery ID as a JSON string. Other restore IDs and
226
+ unpinning are refused while recovery is pending. Recovery uses the existing
227
+ pinned snapshot; it does not snapshot the partially restored target.
228
+ If the journal is malformed or the recovery copy is missing/corrupt, preserve
229
+ the files and investigate. Do not delete the journal to bypass recovery.
230
+
231
+ After success, safety snapshots remain pinned until you review and explicitly
232
+ unpin them. Restore remains non-atomic and requires trusted dumps; preflight
233
+ checks do not prevent another application from reconnecting during replay.
234
+
101
235
  ## Database requirements
102
236
 
103
237
  | Database | Snapshot method | Requirements |
@@ -110,6 +244,9 @@ PostgreSQL server-side clones are stored on the database server. Use dump mode
110
244
  when the snapshot needs to survive removal of that server's data volume.
111
245
  For dump save and restore, install `pg_dump` and `pg_restore` matching the
112
246
  PostgreSQL server's major version. Mismatched tools are rejected before restore.
247
+ The SQLite database file must already exist. MySQL/MariaDB snapshots retain
248
+ routines, triggers and events, although diff does not compare those objects.
249
+ Snapshot runtime and connection disruption depend on the engine and data size.
113
250
 
114
251
  ## Safety
115
252
 
@@ -118,11 +255,16 @@ PostgreSQL server's major version. Mismatched tools are rejected before restore.
118
255
  - Project binding checks that the current target matches the recorded database.
119
256
  - Restore checks SQLite chunks and dump artifacts before applying them and, by default,
120
257
  creates a safety snapshot first. If that snapshot cannot be created, restore
121
- stops; the CLI has an explicit option to skip it.
258
+ stops. Only SQLite/PostgreSQL allow explicit opt-out; fresh MySQL/MariaDB
259
+ restores require a pinned safety snapshot.
122
260
  - A PostgreSQL server-side clone has a metadata fingerprint, not a content
123
261
  checksum. dbsnap checks that the clone exists before restore.
124
262
  - PostgreSQL restore is not atomic; an interruption can require manual
125
263
  recovery. Clone and staged dump restores journal their cutover.
264
+ - MySQL restore is in-place and non-atomic. Stop writers/events first. Visible
265
+ target connections and enabled events cause refusal before cleanup; this is
266
+ not a fence against future connections. Keep the pinned snapshot and recovery
267
+ journal if replay fails, including when server storage is full.
126
268
  - PostgreSQL network connections require verified TLS. Set `DBSNAP_PG_CA_CERT`
127
269
  to a trusted CA PEM file if needed; use `DBSNAP_PG_TLS=verify-full` to require
128
270
  TLS on loopback connections as well.
@@ -134,6 +276,9 @@ data you cannot afford to lose.
134
276
 
135
277
  - [Repository and full documentation](https://github.com/farhan0431/db-snap)
136
278
  - [MCP installation guide](https://github.com/farhan0431/db-snap/blob/main/INSTALL.md)
279
+ - [Testing and audit coverage](https://github.com/farhan0431/db-snap/blob/main/docs/TESTING.md)
280
+ - [MySQL recovery](https://github.com/farhan0431/db-snap/blob/main/docs/MYSQL-RESTORE.md)
281
+ - [Development workflow and feature coverage](https://github.com/farhan0431/db-snap/blob/main/docs/DEVELOPMENT-WORKFLOW.md)
137
282
  - [Report an issue](https://github.com/farhan0431/db-snap/issues)
138
283
 
139
284
  MIT license.
Binary file
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@farhan0431/db-snap",
3
- "version": "0.3.11",
4
- "description": "Instant physical database time-machine and MCP server for AI coding agents — git commit/checkout for your local database, powered by Rust.",
3
+ "version": "0.4.0",
4
+ "description": "Development database snapshots and MCP server for SQLite, PostgreSQL, and MySQL/MariaDB.",
5
5
  "license": "MIT",
6
6
  "bin": {
7
7
  "dbsnap": "bin/dbsnap.js"