Initial Commit
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user