feat: add D1 storage layer with per-module migration runner

- SqlStore interface + CF D1 wrapper + per-module factory (table prefix convention)
- init signature extended to ({ db, sql, env }); sql is null when DB binding absent
- custom migration runner walks src/modules/*/migrations/*.sql, tracks applied in _migrations table
- npm run db:migrate with --dry-run and --local flags; chained into deploy
- fake-d1 test helper with subset of SQL semantics for retention and history tests
This commit is contained in:
2026-04-15 13:21:53 +07:00
parent fb8c7518f7
commit 83c6892d6e
15 changed files with 1879 additions and 15 deletions

View File

@@ -10,26 +10,26 @@
*/
/**
* @typedef {Object} KVStorePutOptions
* @typedef {object} KVStorePutOptions
* @property {number} [expirationTtl] seconds — value auto-deletes after this many seconds.
*/
/**
* @typedef {Object} KVStoreListOptions
* @typedef {object} KVStoreListOptions
* @property {string} [prefix] additional prefix (appended AFTER the module namespace).
* @property {number} [limit]
* @property {string} [cursor] pagination cursor from a previous list() call.
*/
/**
* @typedef {Object} KVStoreListResult
* @typedef {object} KVStoreListResult
* @property {string[]} keys — module namespace already stripped.
* @property {string} [cursor] — present if more pages available.
* @property {boolean} done — true when list_complete.
*/
/**
* @typedef {Object} KVStore
* @typedef {object} KVStore
* @property {(key: string) => Promise<string|null>} get
* @property {(key: string, value: string, opts?: KVStorePutOptions) => Promise<void>} put
* @property {(key: string) => Promise<void>} delete