clave docs

Store

A site with code has its own database, the store. The site's code reaches it as env.DB (Cloudflare D1, which is SQLite). These calls let you read it, repair it, and take a copy.

The store is not in git, and it is not part of a version. Restoring an old version brings back code, and the data stays as it is.

Make the store

Write the schema as migrations in the site's repository:

migrations/0001_create_orders.sql
migrations/0002_add_stock.sql

Name each file with four digits, an underscore, and lowercase words. The number sets the order. On publish, Clave runs each new migration once, in order. If one fails, nothing is published, and the error names the file. Never edit a migration that ran. Add a new one.

The first publish with a migration makes the store. The draft has a store of its own, and it keeps its data from draft to draft.

Clave keeps the hash of each migration that ran:

Seeds

Seeds put rows in. Migrations make the tables. Two folders sit next to migrations/, with the same file names:

seeds/draft/0001_test_products.sql   the draft's store only
seeds/live/0001_first_products.sql   the live store only

After the migrations of a publish, Clave runs each seed of that kind that the store has not run, in order, one time. A seed that fails stops the publish, and the error names the file. Clave never copies live data into a draft, or the other way.

POST /v1/previews/{id}/reset-store empties the draft's store and runs the migrations and the draft seeds again, so a test starts from the seeds.

Read

POST /v1/sites/{id}/store/query

{ "sql": "SELECT id, status FROM orders WHERE status = ?", "params": ["paid"] }

One statement that only reads. The answer holds at most 1000 rows, and truncated is true when there were more. Add "slot": 1 to read a draft's store.

Repair

POST /v1/sites/{id}/store/execute takes one statement that can change rows. Use it for a repair that no action of the site fits.

A raw write skips the site's own rules. For example, it marks an order shipped and sends no mail. For daily work, call the site's action.

It never changes the schema. The answer holds rows_changed and a bookmark. Clave keeps a record of each write. An account makes at most 20 writes a minute; more answers 429 rate_limited.

Undo

POST /v1/sites/{id}/store/restore with { "bookmark": "..." } puts the store back to that bookmark. Every write after it is undone, the site's own writes too.

Take a copy

GET /v1/sites/{id}/store/export answers with an SQL dump of the store. A big store can take a minute. If the answer is export_pending, ask again.

One statement is one step

D1 has no transaction that stays open across a read in code. So "check the stock, then take one" must be one statement:

UPDATE stock SET n = n - 1 WHERE id = ? AND n >= 1

Then check that one row changed. Two statements, a read and then a write, can sell the last item twice.