Add @b9g/zen/schema entrypoint for client-side usage - #23
Open
brainkim wants to merge 1 commit into
Open
Conversation
Closes #7. A table is just a Zod schema plus metadata, so it is useful well away from a database connection: form validation, API request/response contracts, and types shared between client and server. None of that needs Database, drivers, migrations, query building or DDL generation. @b9g/zen/schema exposes table/view definition, the extended zod, field metadata (for form generation), the SQL builtins and the validation errors — and nothing that reaches impl/database.js. One subtlety worth noting: the main entrypoint re-exports the SQL builtins *from* impl/database.js, so importing NOW from "@b9g/zen" pulls in the whole database runtime. This entrypoint re-exports them from impl/builtins.js instead. Same symbols (they are Symbol.for(), so identity holds across both), none of the runtime. extendZod is idempotent, so importing both entrypoints is safe. Bundled for the browser with zod external: @b9g/zen/schema 37,896 bytes @b9g/zen 108,829 bytes (65% larger) The isolation is asserted structurally rather than trusted: the tests bundle the entrypoint and assert Database/DatabaseUpgradeEvent/"upgradeneeded" are absent, with a control test asserting they ARE present in the main bundle, so the assertions cannot quietly become vacuous if the import graph changes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016Vvtr747kUp1NobqCBeZJi
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #7.
A table is just a Zod schema plus metadata, so it's useful well away from a database connection — form validation, API contracts, types shared between client and server. None of that needs
Database, drivers, migrations, query building or DDL generation.@b9g/zen/schemaexposes table/view definition, the extendedz, field metadata (for form generation), the SQL builtins, and the validation errors — and nothing that reachesimpl/database.js.Result
Bundled for the browser with
zodexternal:@b9g/zen/schema@b9g/zen65% smaller — ~71KB of database runtime excluded.
One subtlety
The main entrypoint re-exports the SQL builtins from
impl/database.js(zen.ts:89), so evenimport {NOW} from "@b9g/zen"drags in the whole database runtime. This entrypoint re-exports them fromimpl/builtins.jsinstead — same symbols (they'reSymbol.for(), so identity holds across both), none of the runtime.extendZodis idempotent (it guards withif (!("db" in value.prototype))), so importing both entrypoints is safe.The isolation is pinned, not trusted
Rather than assume the import graph stays clean, the tests bundle the entrypoint and assert
Database/DatabaseUpgradeEvent/"upgradeneeded"are absent — plus a control test asserting they are present in the main bundle, so the assertions can't quietly rot into vacuous truths.(Careful with markers:
"class Database"is a substring of"class DatabaseError", which legitimately is in the schema bundle. The tests match on"class Database extends EventTarget".)Verification
bun test— 603 pass / 0 fail (9 new)tsc --noEmit— clean🤖 Generated with Claude Code