Skip to content

Releases: eagerpatch/durable-db

durable-db@0.1.11

Choose a tag to compare

@github-actions github-actions released this 03 Jul 10:46
cbe6726

Patch Changes

  • 512cc62: fix: validate no longer reports false schema drift for tables altered with ALTER TABLE ... ADD COLUMN

    The drift check compared raw sqlite_master CREATE text between the migration-replay database and the from-scratch schema database. SQLite rewrites a table's stored CREATE statement when a column is added via ALTER (the column is spliced in before the closing paren, always last), so any generated column-add migration could never text-match the fresh CREATE — every such migration failed validation and blocked deploys.

    Tables are now compared structurally via PRAGMA introspection (pragma_table_info, pragma_index_list/pragma_index_info for UNIQUE constraints, pragma_foreign_key_list), which reflects what SQLite actually enforces regardless of how the table was built. Column order is intentionally ignored. Indexes, views, and triggers are still compared textually. Known gap: CHECK constraints, column collations, and WITHOUT ROWID/STRICT options are not exposed by PRAGMAs and are no longer part of the comparison.

durable-db@0.1.9

Choose a tag to compare

@github-actions github-actions released this 02 Jul 22:02

Patch Changes

  • The generated Durable Object now carries the database's Drizzle schema and builds its Kysely with the full schema-aware plugin chain.

    Previously the DO used the base class's schema-less Kysely (createKyselyFromSql(sql) with only CamelCase + heuristic date handling), so the schema-aware plugins — DrizzleDefaultsPlugin (defaultFn/onUpdateFn), SchemaPlugin (exact column-name mapping), schema-gated date deserialization, and the new BooleanDeserializePlugin — never ran on the production action path. Most visibly: integer({ mode: 'boolean' }) columns read back as raw storage values instead of booleans.

    The Vite plugin now emits an aliased import of the schema tables into the generated module and a schema = { … } class property; SqliteDurableObject builds db lazily (subclass field initializers run after the constructor) with the schema when present. Subclassing without a schema keeps the old behavior.

durable-db@0.1.8

Choose a tag to compare

@github-actions github-actions released this 02 Jul 21:38

Patch Changes

  • Two Kysely-over-SqlStorage driver fixes, both found in the field and both invisible to the node-based unit suites:

    • Statements with more than 100 bound parameters no longer throw too many SQL variables. workerd's SQLite is compiled with SQLITE_MAX_VARIABLE_NUMBER = 100, so a modest multi-row insert (24 rows × 7 columns = 168 params) or a large WHERE … IN (…) list blew up. Past the limit, the driver now inlines parameters as escaped SQL literals (a real scanner that never touches ? inside string literals, quoted identifiers, or comments) — still a single statement with identical semantics.
    • Boolean columns round-trip as booleans. workerd has no boolean binding type and silently stringified JS true into TEXT 'true' (which then failed 'boolean' arg validation downstream, and made a stored 'false' truthy). The driver now normalizes boolean bindings to SQLite's 1/0 (and undefined → NULL), and a new schema-aware BooleanDeserializePlugin maps integer({ mode: 'boolean' }) columns back to real booleans on read — including legacy TEXT 'true'/'false' rows written by the old driver.

    Covered by a new workerd E2E suite (tests/workers/kysely-e2e.test.ts) that runs the production plugin chain against a real DO SqlStorage.

durable-db@0.1.10

Choose a tag to compare

@github-actions github-actions released this 02 Jul 22:58

Patch Changes

  • Migration chunks now commit atomically with their journal row (storage.transactionSync).

    Previously each chunk's statements and the __migrations journal insert ran as separate writes. A crash — or a dev server killed mid-boot — between a CREATE TABLE and the journal insert left the schema applied but unrecorded: storage that throws MigrationSchemaConflictError ("table already exists ... journal has no record") on every subsequent boot. Production is shielded by the PITR bookmark restore, but local dev has no PITR, so the only way out was db reset --purge-local-storage.

    With transactionSync, a failed or interrupted chunk rolls back completely — either the whole chunk plus its journal row lands, or nothing does. Mocked/test storages without transactionSync fall back to the old inline execution.

durable-db@0.1.7

Choose a tag to compare

@github-actions github-actions released this 30 Jun 13:49
6df6a94

Patch Changes

  • 02bf9f2: Register all actions in the Durable Object's isolate at startup. The action registry is a module singleton populated when an action file loads, but the generated DO module didn't import action files — so it relied on the request path having loaded them. That holds in dev (one shared isolate) and via in-app navigation, but a Durable Object is a separate, persistent isolate in production: a freshly deep-linked route whose action the DO never loaded threw Unknown action "X" (was it imported?). The generated DO module now side-effect-imports every action-defining file (discovered recursively under the databases dir), so all actions register at DO startup regardless of entry route.
  • 02bf9f2: Fix EvalError: Code generation from strings disallowed (500) in production Cloudflare Workers. arktype compiles validators with new Function (runtime codegen), which Workers allow at startup but block during request handling — so a route's action args schema that compiles at request time crashed. arktype's envHasCsp() auto-probe mis-detects this (it runs at startup, where codegen still works). durable-db now re-exports type from an explicitly jitless (eval-free) arktype scope, so every type({...}) is interpreted rather than compiled — independent of bundle init order. Dev was unaffected because its workerd allows codegen.

durable-db@0.1.6

Choose a tag to compare

@github-actions github-actions released this 30 Jun 08:36
a695636

Patch Changes

  • 052c049: vite: keep Drizzle base classes through Rolldown (Vite 8) production tree-shaking. drizzle-orm ships sideEffects:false, and Rolldown fails to count a cyclic class Sub extends Base as a use of Base — so it deletes the apparently-unused base-class module entirely while keeping the extends reference, crashing the worker at boot with e.g. TypedQueryBuilder is not defined. databasePlugin() now tags drizzle-orm modules side-effectful (a plugin hook's moduleSideEffects outranks the package's sideEffects field), forcing Rolldown to retain them. Fixes the bug at the source for any durable-db + Vite 8 consumer.

durable-db@0.1.5

Choose a tag to compare

@github-actions github-actions released this 29 Jun 23:01
21f1053

Patch Changes

  • 597c275: Strip the Cloudflare RPC Symbol.dispose from action results in the generated
    page→DO stub
    too.

    0.1.4 stripped it in callAction (the action-to-action cross-DB path), but the
    common case — an app page / "use server" function calling an action, which goes
    through the Vite-plugin-generated action proxy (stub.rpc(...)) — still
    returned the symbol-keyed RPC object, so passing the result to a client component
    still threw "Objects with symbol properties like Symbol.dispose are not supported".
    The generated proxy's out-of-DO path now returns stub.rpc(...).then(structuredClone),
    yielding a plain clone (symbol keys dropped, Date/Map/Set preserved). Verified
    end-to-end in a ShopLayer app.

durable-db@0.1.4

Choose a tag to compare

@github-actions github-actions released this 29 Jun 22:21
13e5a6b

Patch Changes

  • fd6a6c5: Strip the Cloudflare RPC Symbol.dispose from cross-DB action results.

    Action results returned over the Durable Object RPC boundary carry a top-level
    Symbol.dispose that Cloudflare attaches for explicit resource management. React
    Server Components refuse to serialize symbol-keyed props ("Objects with symbol
    properties like Symbol.dispose are not supported"), so returning an action result
    from a "use server" function — or passing it straight to a client component —
    threw at runtime. callAction now structuredClones the RPC result, dropping all
    symbol keys while preserving value types (Date/Map/Set/etc., unlike a JSON
    round-trip). The same-DB direct-call and WebSocket transport paths already returned
    plain values and are unchanged.

durable-db@0.1.3

Choose a tag to compare

@github-actions github-actions released this 29 Jun 07:26
28b1c9b

Patch Changes

  • c1f1c85: Replace the debug dependency with a tiny internal logger. debug's entry is a
    runtime-conditional module.exports = require(isBrowser ? './browser' : './node'),
    which Rolldown can't statically interop. Under Vite 8 the database:vite/cli/migrations
    namespaces get pulled into the worker runtime via context, and the worker
    module-runner evaluates that CJS with no module in scope → crash at boot
    ("module is not defined"). The internal logger keeps the same createDebug(namespace)
    API and DEBUG-env gating, with zero dependencies.

durable-db@0.1.2

Choose a tag to compare

@github-actions github-actions released this 28 Jun 15:10

Patch Changes

  • Alias the injected type import so it never collides with an app's own type
    import. The action transform injects import { …, type } from "durable-db/registry"
    into the user's file; if the app already does import { type } from '…' (e.g.
    arktype's type re-exported by a framework), the two top-level type bindings are a
    duplicate declaration. Rollup tolerated it, but rolldown (Vite 8+) rejects it with
    Identifier 'type' has already been declared. The injected type is now imported
    under an internal alias (__ddType) and the generated validators reference that,
    so the transform still routes to durable-db's own arktype instance with no clash.