Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
# `bunSqliteReader`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Production-grade `SqliteReader` backed by Bun's built-in `bun:sqlite`
driver. The reader is the single seam through which
`IMessageWatcher` reaches Apple's `chat.db` SQLite database; replacing
upstream's `require("bun:sqlite") as any` cast with a typed,
swappable factory lets tests inject a reader pointing at a real temp
chat.db without re-implementing the SQL layer.
## Features
- Lazy module resolution via `createRequire(import.meta.url)` — the
`bun:sqlite` import is not added to the static graph, so vite and
vitest do not attempt to resolve it on non-Bun runners during build
/ type-check / lint passes.
- Errors thrown from the load step or the `new Database(...)` call
are wrapped in `IMessageDbOpenFailedError` carrying the offending
path on `context.path`, so the watcher can surface a stable error
code to consumers.
- Returns a `SqliteHandle` whose `execScript` member maps to
`Database.run` (Bun's bulk-SQL entry point) and whose `prepare`
member returns a `SqliteStatement` wrapping Bun's per-statement
`all` / `get` / `run` methods structurally — production and test
code share the exact same call shape.
- Read-only by default: `open(path, { readonly: true })` opens the
database read-only as required for `~/Library/Messages/chat.db`,
while tests open with `readonly: false` to populate the fixture.
## Usage: Basic
```ts
import { bunSqliteReader } from "@suaveplan/imessage-adapter";
const handle = bunSqliteReader.open("/path/to/chat.db", { readonly: true });
const rows = handle.prepare("SELECT ROWID FROM message LIMIT 1").all();
handle.close();
```
## Usage: Advanced
```ts
import { createBunSqliteReader } from "@suaveplan/imessage-adapter";
// Inject a custom loader (e.g. for vitest under WSL2 where bun:sqlite is
// reached through a different worker bridge).
const reader = createBunSqliteReader(() => require("bun:sqlite"));
const handle = reader.open(path, { readonly: false });
handle.execScript("CREATE TABLE foo (id INTEGER PRIMARY KEY)");
```
## API Reference
- `bunSqliteReader: SqliteReader` — default reader, ready for
production wiring.
- `createBunSqliteReader(loader?: BunSqliteLoader): SqliteReader` —
factory accepting a custom loader; defaults to a
`createRequire`-based one that resolves `bun:sqlite` against the
module's own URL.
- `BunSqliteLoader = () => BunSqliteModule` — the loader contract.
## Implementation Notes
`createRequire(import.meta.url)` is the documented Node + Bun bridge
for resolving CommonJS / built-in modules from ESM without statically
declaring them. We use it because static `import "bun:sqlite"` would
make vite resolve the specifier at build time and fail on non-Bun
hosts (CI, lint). The `BunDatabase` interface is intentionally
minimal — it only declares the methods the watcher actually calls,
so changes to Bun's broader Database surface cannot bleed into the
package.