Skip to content

Releases: binaryplease/zodstore

v0.5.0

Choose a tag to compare

@escherlies escherlies released this 17 Sep 21:14
v0.5.0
b3aeec5

Eighteen fixes to the schema gate and the where-clause compiler, and four
changes that make a previously-accepted call fail loudly. A minor bump rather
than a patch: a caller on 0.4.2 can meet a throw where a call used to return.

Full detail in CHANGELOG.md.

Breaking in practice

  • A like operand that is not a string is refused. LIKE NULL is NULL
    for every row, so the filter answered nothing and an empty answer is
    indistinguishable from a truthful "no rows" (#16).
  • A schema whose fields are not one readable shape is refused at
    store.collection(...)
    rather than skipped — a union of object schemas or
    an intersection. { enforceDefaults: false } is the way past it, which makes
    the exception a caller's decision rather than an accident of spelling.
  • A conflicting idField reopen is refused across connections, not only
    within one process. The convention is read back off a stored row, so the check
    answers on files that already exist and needs no migration
    (#1).
  • in/notIn containing null name the rows that have no value.
    in: [null] means eq: null, notIn: [null] means ne: null, so the list
    form and the singleton form of the same question now agree.

Fixed

  • ne and notIn no longer drop the rows whose value is NULL.
  • The declared-default guard walks a schema all the way down, and both
    collection guards see through Zod wrappers (#2, #7, #11).
  • Two index declarations can no longer collapse onto one name, silently
    dropping a unique: true (#6); a redefinition is refused loudly, and a
    file written by an earlier version keeps one index per declaration.
  • An in/notIn list binds as one JSON array instead of a placeholder per
    element, so the statement cache no longer holds one entry per distinct list
    length (#3).
  • A collection() call that fails on an option no longer poisons the store.
  • An operand that cannot be compared is refused, naming the operator or field,
    and an operator object naming no operator narrows instead of throwing.

Install

bun add @binaryplease/zodstore

Requirements

Bun. The library imports bun:sqlite and has no Node compatibility path. Zod
is a peer dependency (^3.24.0 || ^4.3).

License

MIT — see LICENSE.

v0.4.2

Choose a tag to compare

@escherlies escherlies released this 31 Aug 17:29
d19d3ed

The package is now @binaryplease/zodstore. The registry refused the
unscoped name zodstore as too similar to an existing zod-store, so no
version was ever published under it. This is the first release that reaches npm.

Nothing about the library changes from v0.4.1: the same modules, the same
exports, the same src/index.ts entry point. Only the specifier moves.

Install

bun add @binaryplease/zodstore zod
import { createStore, populate, ref } from "@binaryplease/zodstore";

Zod is a peer dependency (^3.24.0 || ^4.3) — the consumer owns the Zod
version, so two copies of Zod never end up in one process.

What zodstore is

A native SQLite + Zod document store for Bun. Zod is the gatekeeper;
bun:sqlite is the synchronous, in-process engine. One fixed table per
collection, no migrations and no ORM — the shape lives in Zod, the rows live in
SQLite.

Carried over from 0.4.1

The published tarball is an allowlist. package.json declares
files: ["src", "README.md", "CHANGELOG.md", "LICENSE"], so an install brings
the library, its documentation and its licence and nothing else. npm packs the
working directory rather than git, and a denylist fails open on whatever nobody
thought to name; an allowlist fails closed.

A stored row that fails the schema no longer reports its own content. The
read path used to forward a ZodError's message verbatim, on the premise that
it names paths and types and carries no values. It does not — under Zod 3 the
issue carries the rejected value as received, so ordinary schema drift put
document content into the exception thrown by get(), find(), findByIds()
and findOne(). The issue list is now rendered rather than forwarded: each
issue reads "consents.<key>" (invalid_type, expected boolean). The ZodError
remains the cause. The write gate carried the same defect and takes the same
remedy.

Requirements

Bun. The library imports bun:sqlite and has no Node compatibility path.

License

MIT — see LICENSE.

v0.4.1

Choose a tag to compare

@escherlies escherlies released this 31 Aug 17:14

Note — the package name changed. The unscoped name zodstore was refused by the npm registry as too similar to an existing zod-store, so no version was ever published under it and the install command below does not work. Use v0.4.2 and bun add @binaryplease/zodstore zod.

zodstore is a native SQLite + Zod document store for Bun. Zod is the
gatekeeper; bun:sqlite is the synchronous, in-process engine. No migrations,
no ORM — the shape lives in Zod, the rows live in SQLite.

This is the first public release. See README.md for the API and
the design rationale, and CHANGELOG.md for the full history.

Install

bun add zodstore zod

Zod is a peer dependency (^3.24.0 || ^4.3) — the consumer owns the Zod
version, so two copies of Zod never end up in one process.

Changed in 0.4.1

The published tarball is now an allowlist. package.json declares
files: ["src", "README.md", "CHANGELOG.md", "LICENSE"], so an install brings
the library, its documentation and its licence and nothing else. The test suite,
the CI workflow, the flake and the ignore files no longer ship. Nothing exported
changes and no consumer loses anything it could import.

The reason is the direction the control fails in. npm packs the working
directory rather than git, so a denylist fails open on whatever nobody thought
to name. An allowlist fails closed instead, and a registry version is never
taken back.

Fixed in 0.4.1

A stored row that fails the schema no longer reports its own content. The
read path forwarded a ZodError's message verbatim, on the premise that a
ZodError names paths and types and carries no values. It does not: its
message is the serialised issue list, an issue's path runs through a
z.record()'s keys, and under Zod 3 the issue carries the rejected value as
received. Ordinary schema drift therefore put document content into the
exception thrown by get(), find(), findByIds() and findOne(), and from
there into a log.

The issue list is now rendered rather than forwarded: each issue reads
"consents.<key>" (invalid_type, expected boolean) — the path, the code, and
expected where it is a string. A path segment is printed when the schema
declares it and elided as <key> when it does not; an array index is printed,
because a position is not content. The ZodError remains the cause, so a
caller that deliberately inspects it loses nothing.

The write gate carried the same defect and takes the same remedy.
serializeDocument interpolated a ZodError's message into the refusal it
raises for a document whose stored form its own schema rejects. It renders the
issue list through the same renderer now.

Message text only: what is thrown, when it is thrown, and what validate()
returns are all unchanged.

Requirements

Bun. The library imports bun:sqlite and has no Node compatibility path.

License

MIT — see LICENSE.