Skip to content

fix(sqlite): review fixes for #710 — restore the bun:sqlite driver path - #839

Closed
sroussey wants to merge 2 commits into
claude/better-sqlite3-node-sqlite-0ydg8gfrom
claude/sqlite-restore-bun-driver
Closed

fix(sqlite): review fixes for #710 — restore the bun:sqlite driver path#839
sroussey wants to merge 2 commits into
claude/better-sqlite3-node-sqlite-0ydg8gfrom
claude/sqlite-restore-bun-driver

Conversation

@sroussey

Copy link
Copy Markdown
Collaborator

Stacked on #710 (claude/better-sqlite3-node-sqlite-0ydg8g) so the diff here is just the review fixes. Merge into that branch.

What this fixes

1. The migration removed Bun's only working SQLite driver

#710 deleted providers/sqlite/src/storage/bun.ts, its _sqlite/bun.ts adapter and the "bun" export condition on ./storage, on the premise that both runtimes could share one node:sqlite driver. Bun cannot. No tagged Bun release carries the node:sqlite builtin — only the rolling canary does:

$ bun --version
1.3.11
$ bun -e 'await import("node:sqlite")'
node:sqlite FAIL: No such built-in module: node:sqlite
$ bun -e 'await import("bun:sqlite")'
bun:sqlite OK Database,SQLiteError,Statement,constants,default

With the condition gone, a Bun consumer resolved dist/storage/node.js and got a driver whose dynamic import throws, so every SQLite-backed path failed at Sqlite.init(). Measured on the storage section under Bun 1.3.11, all three trees built from source:

tree bun scripts/test.ts storage bun
origin/main (pre-migration, has bun:sqlite) 2072 pass / 23 skip / 0 fail
#710 head (pristine) 1716 pass / 22 skip / 20 fail, 7 errors
this branch 1960 pass / 34 skip / 0 fail

The restored adapter is the pre-migration one byte-for-byte, plus a comment explaining why it outlived the migration. Resolution now splits per runtime again — BunSqliteDatabase under Bun, NodeSqliteDatabase under Node — verified directly by importing @workglow/sqlite/storage from each.

2. The canary toolchain pin was unusable, and only existed for node:sqlite

engines.bun comes back down to ^1.3.11 and packageManager to bun@1.3.11. bun@1.4.0-canary.1 names a version no registry publishes — #710's own commit message says so — so bun i had no installable toolchain to name. The Node floor stays >=24, where node:sqlite is stable and where the Node driver still needs it.

The two bun-version: canary CI pins raised for the same reason go back to latest, restoring nightly-typecheck.yml and publish-preview.yml-off byte-for-byte to main (blob hashes match). test.yml and nightly-bun-parity.yml are not touched#710's merge with main already left them on latest, so there was nothing to revert.

3. Guards, drawn from measurement

BunExportConditions.test.ts is the exact-set fixture for every "bun" condition in the monorepo, so restoring @workglow/sqlite ./storage fails it until the fixture says three entries again. It also re-asserts which bundle the condition names (dist/storage/bun.js vs dist/storage/node.js), because the exact-set check alone would pass on a condition pointing at the wrong build. The prose the fixture's own comment names moves with it: .claude/CLAUDE.md, both spots in docs/technical/19-build-system.md, and docs/technical/18-multi-runtime-abstraction.md (plus the packages/storage README, which described Bun as loading node:sqlite).

SqliteDriver.contract.test.ts runs under both runners, so with two drivers back it now asserts one shared contract plus a node-scoped remainder. The split is drawn from measurement rather than from the module list: forcing the node groups on under Bun fails 11 of 16 assertions, and the other 5 pass — savepoint nesting from an exec'd or prepared BEGIN, recovery after a stray COMMIT, inner-only unwind, and all() row prototypes. Those 5 moved into the shared group rather than staying skipped. That matters most for savepoint nesting, which SqliteTabularStorage depends on and which would otherwise have had no Bun coverage at all.

What stays node-only is what genuinely diverges: better-sqlite3 error-code spellings, constructor-option rejection, the async-body refusal, the BigInt narrowing node:sqlite forces, and the busy-timeout contention window.

Verification

Run from the worktree root against the committed tree, dist mode (bun run build), real results.

Command Result
bun run build:types 41 successful, 41 total
bun run build 84 successful, 84 total
bun scripts/test.ts storage vitest ✅ 70 files, 1970 passed / 24 skipped, 0 failed
bun scripts/test.ts util vitest ✅ 53 files, 757 passed / 10 skipped, 0 failed
bun scripts/test.ts storage bun 1960 pass / 34 skip / 0 fail (baseline: 20 fail, 7 errors)
bun test on the two guard files (Bun 1.3.11) 14 pass / 11 skip / 0 fail
vitest run on SqliteDriver.contract.test.ts (Node) 22 passed
bun scripts/test.ts --check-sections ✅ every test file reachable
bunx eslint on all 4 touched source files ✅ exit 0
bunx prettier --check on all 12 touched files ✅ clean

Two notes on results that look like failures and are not:

  • bun scripts/test.ts util bun reports 8 failures. They are pre-existing and unrelated (vi.advanceTimersByTimeAsync is undefined under Bun's runner; dataUriToBlob / bytesToBase64 Buffer-path cases). The pristine Migrate SQLite driver from better-sqlite3 to node:sqlite #710 head produces the identical 701 pass / 10 skip / 8 fail with the same 8 names.
  • bun scripts/test.ts storage bun prints "exit code 99" with 0 failures. Pre-existing: origin/main prints the same line, also with 0 failures.

Prettier flags .claude/CLAUDE.md and docs/technical/19-build-system.md, but both were already unformatted on the pristine base, in regions this PR does not touch (a table at line 32, JSON blocks, emphasis markers at line 275). Left alone rather than reformatted as unrelated noise.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HJRf3YFa8DjmjsZvXz8xDT


Generated by Claude Code

claude added 2 commits August 17, 2026 20:25
…condition

The migration to `node:sqlite` deleted `src/storage/bun.ts`, its
`_sqlite/bun.ts` adapter and the `"bun"` export condition on `./storage`, on
the premise that both runtimes could share one driver. Bun cannot: no tagged
release carries the `node:sqlite` builtin — `import("node:sqlite")` fails with
"No such built-in module" on 1.3.11 through `latest`, and only the rolling
canary has it. With the condition gone a Bun consumer resolved
`dist/storage/node.js` and got a driver whose dynamic import throws, so every
SQLite-backed path failed at `Sqlite.init()`.

Measured on the storage section under Bun 1.3.11 (`bun scripts/test.ts storage
bun`): 1716 pass / 20 fail / 7 errors before, 1960 pass / 0 fail after, against
2072 pass / 0 fail on the pre-migration main.

The restored adapter is the pre-migration one, so the two runtimes diverge
again exactly where they did before — better-sqlite3 error-code spellings,
option validation, the async-body refusal, BigInt narrowing — all of which the
Node driver bridges for itself and `bun:sqlite` either provides natively or
does not need.

Consequently `engines.bun` comes back down to `^1.3.11` and `packageManager` to
`bun@1.3.11`: the canary floor only ever existed to reach `node:sqlite`, and
`bun@1.4.0-canary.1` names a version no registry publishes, so `bun i` had no
installable toolchain. The two `bun-version: canary` CI pins raised for the
same reason go back to `latest`, restoring both workflows byte-for-byte to
main. The Node floor stays `>=24`, where `node:sqlite` is stable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJRf3YFa8DjmjsZvXz8xDT
…contract

`BunExportConditions.test.ts` is the exact-set fixture for every `"bun"` export
condition in the monorepo, so restoring `@workglow/sqlite ./storage` fails it
until the fixture says three entries again. It also re-asserts which bundle the
condition names — `dist/storage/bun.js` for Bun, `dist/storage/node.js` for
Node — because the exact-set check alone would pass on a condition pointing at
the wrong build. The prose the fixture's comment names (`.claude/CLAUDE.md`,
both spots in `docs/technical/19-build-system.md`, and
`docs/technical/18-multi-runtime-abstraction.md`) moves with it.

`SqliteDriver.contract.test.ts` runs under both runners, so with two drivers
back it now asserts one shared contract plus a node-scoped remainder. The split
is drawn from measurement, not from the module list: forcing the node groups on
under Bun fails 11 of 16 assertions, and the other 5 — savepoint nesting from
an `exec`'d or prepared `BEGIN`, recovery after a stray `COMMIT`, inner-only
unwind, and `all()` row prototypes — pass, so they moved into the shared group
rather than staying skipped. That matters most for savepoint nesting, which
`SqliteTabularStorage` depends on and which would otherwise have had no Bun
coverage at all.

What stays node-only is what genuinely diverges: better-sqlite3 error-code
spellings, constructor-option rejection, the async-body refusal, the BigInt
narrowing `node:sqlite` forces, and the busy-timeout contention window.

Bun 1.3.11: 11 pass / 11 skip / 0 fail. Node (vitest): 22 pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJRf3YFa8DjmjsZvXz8xDT
@sroussey

Copy link
Copy Markdown
Collaborator Author

bun 1.4 has node:sqlite

@sroussey sroussey closed this Aug 17, 2026
@sroussey
sroussey deleted the claude/sqlite-restore-bun-driver branch August 17, 2026 20:34
@github-actions

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 60.4% 38859 / 64329
🔵 Statements 59.89% 40787 / 68098
🔵 Functions 60.99% 7529 / 12344
🔵 Branches 48.71% 19858 / 40767
File CoverageNo changed files found.
Generated in workflow #3219 for commit b111427 by the Vitest Coverage Report Action

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants