Skip to content

Version Packages - #28

Open
github-actions[bot] wants to merge 1 commit into
mainfrom
changeset-release/main
Open

Version Packages#28
github-actions[bot] wants to merge 1 commit into
mainfrom
changeset-release/main

Conversation

@github-actions

@github-actions github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

@baas/adapter-convex@0.1.0

Minor Changes

  • b0ddc5c: Add the client-side Convex adapter (the . entry): createConvexBackend /
    convexAdapter with ConvexDocumentStore (named ops via FunctionReferences,
    direct CRUD + reactive subscribe via the deployed helpers), ConvexAuth
    (verify-only, managesCredentials: false, forceRefreshToken adapted), and
    ConvexFileStore (the upload-URL-then-POST dance). Passes the full conformance
    suite against a live deployment. The deployable helpers now normalize Convex's
    throw-on-missing/foreign-id into the portable contract (idempotent remove,
    not_found patch, null get).

  • 6079e6e: Add @baas/adapter-convex with its deployable server helpers (the ./convex
    entry): schemaless, table-name-first CRUD (insert/get/list/patch/
    remove), file storage (generateUploadUrl/getFileUrl/deleteFile), and an
    auth whoami, built on Convex's generic queryGeneric/mutationGeneric
    builders so they ship from npm with no codegen dependency. Proven hermetically
    with convex-test. The client-side adapter follows.

  • e3abea8: Extend list with the in operator and field ordering.

    • in operator: where: [["status", "in", ["open", "pending"]]]. Maps to
      Supabase .in(), memory Array.includes, and an OR-of-eq expansion on Convex
      (which has no native in). WhereCondition is now a discriminated tuple union
      (in takes an array; the other six operators take a scalar).
    • Field ordering: order accepts { field, direction } in addition to the
      bare "asc"/"desc" creation-order shorthand. Supabase and memory order by any
      field directly (keyset on (field, pk)). On Convex, field ordering uses a
      by_<field> index; ordering by an unindexed field returns an
      unsupported_capability error rather than silently falling back to creation
      order. Page size still defaults to 50, clamped to 200.
  • 8d97270: Add a portable list primitive to DocumentStore: cursor-paginated,
    creation-ordered listing with a small filter set. store.list(collection, { where, order, limit, cursor }) returns { items, nextCursor }, where each item carries a
    portable _id. Filters use six comparison operators (eq/neq/gt/gte/lt/lte,
    AND-combined); ordering is creation-order direction only (asc/desc); pagination
    is keyset/cursor (never offset). Implemented identically across memory, Supabase
    (keyset on a configurable timestampColumn, default created_at), and Convex
    (.paginate() over the deployed helper), and asserted by the conformance suite.

    Contract note: loop until nextCursor is null; a non-null cursor may yield an
    empty trailing page on a scan-based backend (Convex with a filter). Arbitrary-field
    sorting, in/text/array operators, joins, and aggregation remain out of scope via
    native().

Patch Changes

@baas/adapter-memory@0.1.0

Minor Changes

  • f59ded2: Initial port layer (@baas/core) and in-memory reference adapter
    (@baas/adapter-memory), validated against the parameterized conformance suite.

  • e3abea8: Extend list with the in operator and field ordering.

    • in operator: where: [["status", "in", ["open", "pending"]]]. Maps to
      Supabase .in(), memory Array.includes, and an OR-of-eq expansion on Convex
      (which has no native in). WhereCondition is now a discriminated tuple union
      (in takes an array; the other six operators take a scalar).
    • Field ordering: order accepts { field, direction } in addition to the
      bare "asc"/"desc" creation-order shorthand. Supabase and memory order by any
      field directly (keyset on (field, pk)). On Convex, field ordering uses a
      by_<field> index; ordering by an unindexed field returns an
      unsupported_capability error rather than silently falling back to creation
      order. Page size still defaults to 50, clamped to 200.
  • 8d97270: Add a portable list primitive to DocumentStore: cursor-paginated,
    creation-ordered listing with a small filter set. store.list(collection, { where, order, limit, cursor }) returns { items, nextCursor }, where each item carries a
    portable _id. Filters use six comparison operators (eq/neq/gt/gte/lt/lte,
    AND-combined); ordering is creation-order direction only (asc/desc); pagination
    is keyset/cursor (never offset). Implemented identically across memory, Supabase
    (keyset on a configurable timestampColumn, default created_at), and Convex
    (.paginate() over the deployed helper), and asserted by the conformance suite.

    Contract note: loop until nextCursor is null; a non-null cursor may yield an
    empty trailing page on a scan-based backend (Convex with a filter). Arbitrary-field
    sorting, in/text/array operators, joins, and aggregation remain out of scope via
    native().

Patch Changes

  • d2b2887: remove() of a non-existent id is now idempotent (returns ok) instead of erroring, establishing the portable contract the conformance suite enforces. remove() reaches a desired end state, so a redundant remove succeeds; patch() still requires an existing document and reports not_found.
  • e367b83: Internal: type-aware lint (typescript-eslint strictTypeChecked) cleanups. Remove unnecessary type assertions and a redundant boolean comparison surfaced by the new lint pass. No behavior or public API change.
  • Updated dependencies [e2d32fe]
  • Updated dependencies [f59ded2]
  • Updated dependencies [e3abea8]
  • Updated dependencies [e367b83]
  • Updated dependencies [8d97270]
    • @baas/core@0.1.0

@baas/adapter-supabase@0.1.0

Minor Changes

  • e3abea8: Extend list with the in operator and field ordering.

    • in operator: where: [["status", "in", ["open", "pending"]]]. Maps to
      Supabase .in(), memory Array.includes, and an OR-of-eq expansion on Convex
      (which has no native in). WhereCondition is now a discriminated tuple union
      (in takes an array; the other six operators take a scalar).
    • Field ordering: order accepts { field, direction } in addition to the
      bare "asc"/"desc" creation-order shorthand. Supabase and memory order by any
      field directly (keyset on (field, pk)). On Convex, field ordering uses a
      by_<field> index; ordering by an unindexed field returns an
      unsupported_capability error rather than silently falling back to creation
      order. Page size still defaults to 50, clamped to 200.
  • 8d97270: Add a portable list primitive to DocumentStore: cursor-paginated,
    creation-ordered listing with a small filter set. store.list(collection, { where, order, limit, cursor }) returns { items, nextCursor }, where each item carries a
    portable _id. Filters use six comparison operators (eq/neq/gt/gte/lt/lte,
    AND-combined); ordering is creation-order direction only (asc/desc); pagination
    is keyset/cursor (never offset). Implemented identically across memory, Supabase
    (keyset on a configurable timestampColumn, default created_at), and Convex
    (.paginate() over the deployed helper), and asserted by the conformance suite.

    Contract note: loop until nextCursor is null; a non-null cursor may yield an
    empty trailing page on a scan-based backend (Convex with a filter). Arbitrary-field
    sorting, in/text/array operators, joins, and aggregation remain out of scope via
    native().

  • f59ded2: Add the Supabase adapter (PostgREST document store, Supabase Auth credential
    management, Supabase Storage), passing the conformance suite 15/15 against a live
    local stack.

  • c33fc22: Realtime watches can now be filtered. A realtime watch entry accepts
    { table, filter } (a Supabase Realtime filter string like "room_id=eq.42")
    in place of a bare table name, narrowing the subscription to matching rows to cut
    fan-out on high-write tables. Bare table names still watch the whole table (the
    safe default). Filters are unsafe for columns whose value changes after insert (a
    row leaving the filtered set fires no event), so they are opt-in and documented
    for append-mostly tables.

  • 81039a5: Add opt-in live subscribe() via a realtime watch map. Declaring
    realtime: { <query>: { tables: [...] } } flips reactiveQueries on and makes
    subscribe() deliver live updates: a change to a watched table re-runs the query
    and delivers the full fresh result (the same shape Convex delivers), coalesced
    over a short debounce. Channel failures and subscribing to a query with no
    declared watch surface as loud error Results rather than silently degrading to
    one-shot. Requires the watched tables in the supabase_realtime publication. The
    default (no realtime config) is unchanged: reactiveQueries: false, one-shot.

Patch Changes

  • d2b2887: patch() of a non-existent id now returns err(not_found) instead of silently succeeding, matching the portable conformance contract. PostgREST reports no error for an update that affects 0 rows, so the adapter now adds .select(pk) and treats an empty result as not_found. remove() remains an idempotent no-op. (Caveat: under RLS, an update permitted but a select denied would also surface as not_found.)
  • 4f62837: Map more Postgres SQLSTATE codes to the portable error taxonomy so a condition
    surfaces as the same ErrorCode it does on the other adapters. Notably 42501
    (insufficient_privilege, the SQLSTATE an RLS denial reaches the client as) now maps
    to unauthorized
    instead of falling through to unknown; also 23503
    (foreign_key_violation) -> conflict, and 23502/23514/22P02
    (not_null / check / invalid_text_representation) -> validation. The normalizer
    moved to src/errors.ts (internal, not part of the public surface) and is now
    unit-tested against the full mapping table; the Convex normalizer gained matching
    unit tests for parity.
  • e367b83: Internal: type-aware lint (typescript-eslint strictTypeChecked) cleanups. Remove unnecessary type assertions and a redundant boolean comparison surfaced by the new lint pass. No behavior or public API change.
  • 53b4933: Fix: store.get() now surfaces the portable _id like store.list() does. Previously get() returned the raw PostgREST row keyed only by the primary-key column, so a fetched document had no _id (an inconsistency with list(), and with the Convex adapter whose documents carry _id natively). A document fetched via get() can now be passed straight to patch()/remove(). Found by the Marquee dogfood.
  • 9c2406f: Fix: subscribe() and files.upload() no longer crash in a non-secure browser context. Both used crypto.randomUUID() (for the Realtime channel name and the default Storage path), but crypto.randomUUID is defined ONLY in secure contexts (https, or http on localhost). On a plain-http origin such as a LAN-IP dev server (http://192.168.x.x) or any non-https deployment it is undefined, so opening a live subscription threw TypeError: crypto.randomUUID is not a function and unmounted the React tree. Both now use an internal id helper that prefers crypto.randomUUID() and falls back to a time + counter + Math.random() id when it is unavailable. Found by the Marquee dogfood (the realtime UI smoke over a LAN IP).
  • 2260831: signUp() now detects a duplicate registration reliably. It maps by the stable error.code === "user_already_exists" instead of regex-matching the (localized, version-dependent) error message, and it surfaces the enumeration-protection obfuscated success (a user with an empty identities array and no session, returned when email confirmation is ON) as conflict rather than a misleading ok(null). A genuine confirmation-pending signup (one identity, no session) is still ok(null).
  • Updated dependencies [e2d32fe]
  • Updated dependencies [f59ded2]
  • Updated dependencies [e3abea8]
  • Updated dependencies [e367b83]
  • Updated dependencies [8d97270]
    • @baas/core@0.1.0

@baas/core@0.1.0

Minor Changes

  • e2d32fe: Add CAPABILITY_KEYS, the runtime list of every Capabilities key, kept exhaustive against the interface by a type-level test (as const literal tuple). It is a trustworthy source of truth for iterating capabilities, used by the conformance suite's new capability-coverage meta-test to guard against a newly added flag silently going untested.

  • f59ded2: Initial port layer (@baas/core) and in-memory reference adapter
    (@baas/adapter-memory), validated against the parameterized conformance suite.

  • e3abea8: Extend list with the in operator and field ordering.

    • in operator: where: [["status", "in", ["open", "pending"]]]. Maps to
      Supabase .in(), memory Array.includes, and an OR-of-eq expansion on Convex
      (which has no native in). WhereCondition is now a discriminated tuple union
      (in takes an array; the other six operators take a scalar).
    • Field ordering: order accepts { field, direction } in addition to the
      bare "asc"/"desc" creation-order shorthand. Supabase and memory order by any
      field directly (keyset on (field, pk)). On Convex, field ordering uses a
      by_<field> index; ordering by an unindexed field returns an
      unsupported_capability error rather than silently falling back to creation
      order. Page size still defaults to 50, clamped to 200.
  • 8d97270: Add a portable list primitive to DocumentStore: cursor-paginated,
    creation-ordered listing with a small filter set. store.list(collection, { where, order, limit, cursor }) returns { items, nextCursor }, where each item carries a
    portable _id. Filters use six comparison operators (eq/neq/gt/gte/lt/lte,
    AND-combined); ordering is creation-order direction only (asc/desc); pagination
    is keyset/cursor (never offset). Implemented identically across memory, Supabase
    (keyset on a configurable timestampColumn, default created_at), and Convex
    (.paginate() over the deployed helper), and asserted by the conformance suite.

    Contract note: loop until nextCursor is null; a non-null cursor may yield an
    empty trailing page on a scan-based backend (Convex with a filter). Arbitrary-field
    sorting, in/text/array operators, joins, and aggregation remain out of scope via
    native().

Patch Changes

  • e367b83: Internal: type-aware lint (typescript-eslint strictTypeChecked) cleanups. Remove unnecessary type assertions and a redundant boolean comparison surfaced by the new lint pass. No behavior or public API change.

@baas/migrate@0.1.0

Minor Changes

  • 92cacd4: Add dryRunMigrate(source, target, opts): project a cutover WITHOUT writing
    anything. It reads the source and the target's resume index and returns a
    MigratePlan — per collection, how many rows would be copied vs skipped — plus
    the first validation issue (missing _id, or a payload over maxValueBytes)
    the real run would fail-fast on, computed with the SAME per-row checks migrate()
    uses (extracted into shared helpers so the preview can't drift from reality). It
    is reads-only and honest about its limits: it does not project the relink pass
    (relinking needs ids the target mints during the real copy) nor exercise the
    read-after-write precondition (nothing is inserted). New exports: dryRunMigrate,
    MigratePlan, MigratePlanCollection.
  • d431e7d: New package @baas/migrate: a one-time portable data cutover between any two
    Backends, built on the core list/insert/patch primitives (no provider SDK).
    migrate(source, target, { collections, relations?, stripFields?, batchSize?, onProgress? }) pages the source, re-inserts each row into the target (stamping
    migratedFrom: <oldId> and stripping backend system fields), and optionally
    remaps foreign keys to the target's re-minted ids in a second pass. It is
    idempotent/resumable (re-runs skip rows already stamped on the target) and
    fail-fast (the first backend error stops the run and is returned with the partial
    idMap intact, never thrown). Proven memory → memory in the test suite; the live
    Supabase → Convex cutover is a manual smoke. Explicitly NOT live sync, NOT atomic
    across backends, and NOT a schema/DDL tool, a deliberate cutover documented as
    such.
  • e6e7554: Add an opt-in maxValueBytes option and document migrate's size/scan bounds
    against Convex's hard limits (16 MiB/mutation, 32k docs scanned, ~1 MiB/value).
    When set, a row whose copied payload serializes to more than maxValueBytes
    UTF-8 bytes aborts with a clear validation error BEFORE the insert, instead of
    letting a size-capped target reject it with a provider-specific message
    mid-insert; maxValueBytes: 1_000_000 is a sensible bound for a Convex target.
    Off by default, so the abstraction bakes in no backend's limit. Size is measured
    portably (UTF-8 length of the JSON encoding via TextEncoder, so it works in the
    browser too); a bigint (a legitimate Convex int64) is measured as its decimal
    string rather than throwing, and a value that still cannot serialize (a circular
    reference) skips the check rather than crashing the run. The README gains a
    "Size and scan bounds" section noting that
    reads page at ≤ 200 rows (under the 32k docs-scanned limit) and writes are one
    mutation per row.

Patch Changes

  • 5cd6692: Fix: use a portable resume marker migratedFrom (no leading underscore) instead
    of _migratedFrom. Convex rejects any user field whose name starts with _
    ("only allowed for system fields like _id"), so the old marker made Convex
    unusable as a migration target. The new name is accepted by Convex, Supabase, and
    the in-memory adapter alike. Caught by driving a real Supabase -> Convex cutover
    against live stacks (the memory -> memory suite could not surface it); a guard test
    now asserts the marker carries no leading underscore.

  • a813527: Enforce the read-after-write precondition and document migration preconditions.
    After the first row it copies into each collection, migrate() now reads that
    row back and aborts with a validation error if it is invisible ("inserted a row
    but could not read it back"). This converts a silent footgun into a loud, early
    failure: a Supabase target reached without a service-role key can have RLS that
    allows the insert but denies the select, in which case the resume scan would
    silently see an empty target and re-copy everything (duplicates) on a re-run. The
    check is portable (it asserts only "what I just wrote, I can read back" and never
    inspects RLS) and costs one extra read per collection.

    MigrateEndpoint now requires get on its store (alongside list/insert/
    patch); any whole Backend already satisfies this. The README gains a
    Preconditions section: Supabase targets need a service-role key (or RLS granting
    read + write); Convex targets re-mint _id, so report.idMap is the only
    old-to-new link and id stability is never promised.

  • 5fec07e: Docs: spell out two requirements a STRICT-SCHEMA target (Postgres/Supabase) has that a schemaless target (Convex) does not, both surfaced by the Marquee dogfood's reverse Convex->Supabase cutover. (1) Every migrated table needs a nullable migratedFrom text column — the resume marker is stamped on each row and read back to resume, and it is NOT part of the source schema, so it is easy to miss; without it the first insert fails with "Could not find the 'migratedFrom' column …". (2) The two-pass copy inserts each row's foreign keys with the source id first and rewrites them in the relink pass, so FK columns on a relational target must be permissive during the copy (plain text, no FK constraint); a uuid-typed or FK-constrained column rejects the transient source id before relink can fix it. Both are inherent to copy-then-relink. The docstring also notes the resulting tension on Postgres: a FK constraint is what PostgREST needs for a server-side embedded join (the serverSideJoins capability) but is exactly what blocks the same table from being a migration target, so a schema tuned for native joins is not automatically a clean migration target. Documented in the module docstring.

  • Updated dependencies [e2d32fe]

  • Updated dependencies [f59ded2]

  • Updated dependencies [e3abea8]

  • Updated dependencies [e367b83]

  • Updated dependencies [8d97270]

    • @baas/core@0.1.0

marquee@0.0.1

Patch Changes

  • Updated dependencies [e2d32fe]
  • Updated dependencies [b0ddc5c]
  • Updated dependencies [6079e6e]
  • Updated dependencies [d2b2887]
  • Updated dependencies [d2b2887]
  • Updated dependencies [4f62837]
  • Updated dependencies [f59ded2]
  • Updated dependencies [e3abea8]
  • Updated dependencies [5cd6692]
  • Updated dependencies [92cacd4]
  • Updated dependencies [d431e7d]
  • Updated dependencies [a813527]
  • Updated dependencies [e6e7554]
  • Updated dependencies [5fec07e]
  • Updated dependencies [e367b83]
  • Updated dependencies [8d97270]
  • Updated dependencies [f59ded2]
  • Updated dependencies [c33fc22]
  • Updated dependencies [53b4933]
  • Updated dependencies [81039a5]
  • Updated dependencies [9c2406f]
  • Updated dependencies [2260831]
    • @baas/core@0.1.0
    • @baas/adapter-convex@0.1.0
    • @baas/adapter-memory@0.1.0
    • @baas/adapter-supabase@0.1.0
    • @baas/migrate@0.1.0

@github-actions
github-actions Bot force-pushed the changeset-release/main branch 11 times, most recently from 67dcf90 to 1dccb2c Compare June 20, 2026 01:13
2bTwist added a commit that referenced this pull request Jun 20, 2026
From the 2026-06-20 repo snapshot's drift report:
- changeset: migrate stamps 'migratedFrom' not '_migratedFrom' (pre-#34 name)
  would ship a self-contradictory CHANGELOG when PR #28 merges.
- supabase migration: 'notes' table gains created_at, so list() on it no longer
  fails at runtime under the default timestampColumn.
- adapter-supabase README: drop the stale 'filtered watches not yet supported'
  (they ship + are tested) and the hardcoded '15/15' count.
- adapter-convex README: drop the 'in progress / client adapter lands next'
  status; the client adapter shipped.
- demo: Supabase 'open table' link no longer hardcodes a table OID that a fresh
  supabase start reassigns.
- add @baas/migrate to the README status table + packages list, CONTRIBUTING
  workspace layout (also adds adapter-convex), RELEASING publishable packages,
  and typedoc entryPoints.
@github-actions
github-actions Bot force-pushed the changeset-release/main branch 15 times, most recently from 8db5515 to 757844d Compare June 20, 2026 21:37
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 757844d to a784516 Compare June 20, 2026 21:42
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.

0 participants