ALWAYS readllms.txtfor curated documentation pages and examples.
Zero 0.25
DX Overhaul, Query Planning
# Zero 0.25
## Installation
```bash
npm install @rocicorp/zero@0.25
```
## Overview
This release massively overhauls and simplifies the entire Zero API.
Conceptually, Zero is now just [schemas](https://zero.rocicorp.dev/docs/schema), [queries](https://zero.rocicorp.dev/docs/queries), and [mutators](https://zero.rocicorp.dev/docs/mutators).
There are no longer first-class auth or permission systems. There are no longer "custom mutators" and "crud mutators", or "synced queries" and "zql queries".
All the old APIs have been deprecated, and the docs have been rewritten and simpilfied. Additionally, this release introduces a [raft of big new features](#features).
To ease the transition, and allow access to new features without a ton of work, you can still use the old APIs via the `enableLegacyQueries` and `enableLegacyMutators` flags. Note that support for these older APIs will be removed for the Zero beta early next year.
## Upgrading
We have implemented both "minimal" and "maximal" sample upgrades.
The minimal upgrades show how to update to 0.25 with very little work, by opting into deprecated APIs:
* [ztunes minimal](https://github.com/rocicorp/ztunes/pull/25): Minimal React upgrade.
* [hello-zero-solid minimal](https://github.com/rocicorp/hello-zero-solid/pull/30): Minimal SolidJS upgrade.
The maximal upgrades show how to use all the new features. Refer to the commit log of each PR for step-by-step examples of how to upgrade:
* [ztunes maximal](https://github.com/rocicorp/ztunes/pull/24): Maximal React upgrade.
* [hello-zero-solid maximal](https://github.com/rocicorp/hello-zero-solid/pull/31): Maximal SolidJS upgrade.
* [zslack](https://github.com/rocicorp/zslack/pull/22): Maximal React Native upgrade.
* [hello-zero-cf](https://github.com/rocicorp/hello-zero-cf/pull/1): Maximal Cloudflare upgrade.
Additionally, the old `hello-zero` sample has been updated from the original CRUD mutators and queries [all the way to the latest hotness](https://github.com/rocicorp/hello-zero/pull/54). So if you were still using those APIs, you can use this as a guide to upgrade.
## Features
* [**Query Planning:**](https://zero.rocicorp.dev/docs/zql#planning) Zero now automatically plans joins, similar to other databases. You no longer need to specify `flip:true` to optimize `whereExists()` calls.
* [**Reworked Query DX:**](https://zero.rocicorp.dev/docs/queries) Queries now receive a `Context` automatically – you don't have to pass it at the call site. Also, any [Standard Schema](https://standardschema.dev/) conforming library can be used for validation and the API has been generally simplified and streamlined.
* [**Reworked Mutator DX:**](https://zero.rocicorp.dev/docs/mutators) The mutator API has been overhauled to match queries. Mutators now also support validation.
* [**drizzle-zero and prisma-zero are now first-class:**](https://zero.rocicorp.dev/docs/schema#generating-from-database) They have moved into the rocicorp org and are now officially supported.
* [**Default Schema Type:**](https://zero.rocicorp.dev/docs/schema#default-type-parameter) The `Schema` type can now be registered as a default with Zero. You can just say `useZero()` – `useZero<Schema>` is no longer needed. You can also delete your `createUseZero()` helper if you have one. This registration happens by default if you use the new `drizzle-zero` or `prisma-zero` packages.
* [**New Connection Status API:**](https://zero.rocicorp.dev/docs/connection) Brand new connection status API with overhauled error-handling and reconnection behavior.
* [**Mutator promises now return structured errors:**](https://zero.rocicorp.dev/docs/mutators#waiting-for-mutator-result) The `client` and `server` promises now always resolve. In the case of an error, they now return a structured error object.
* [**New Install Guide:**](https://zero.rocicorp.dev/docs/install) Rewritten guide to add Zero to an existing project.
* [**New zero-out tool:**](https://zero.rocicorp.dev/docs/debug/zero-out) Removes all trace of Zero from Postgres.
* [**Support for Generated Columns:**](https://zero.rocicorp.dev/docs/postgres-support#object-types) In Postgres 18+, `generated stored` columns are now synced. This is useful for denormalizing data from JSON columns to support filtering in Zero.
## Performance
Queries should be 0.2x to 4x faster, depending on the query. Some highlights:
* [Only cache for duration of `fetch` in `exists`](https://github.com/rocicorp/mono/pull/5259): 60% improvement on sparse `exists` queries.
* [Do not fetch on `null` constraint](https://github.com/rocicorp/mono/pull/5271): 33% improvement on some queries.
* [Remove join storage](https://github.com/rocicorp/mono/pull/5264): \~25% improvement in queries with related calls.
## Fixes
* [Cooperative concurrency for queries](https://github.com/rocicorp/mono/pull/5267)
* [ZERO\_REPLICA\_FILE now defaults to zero.db](https://github.com/rocicorp/mono/pull/5227)
* [`serverURL` renamed to `cacheURL`](https://github.com/rocicorp/mono/pull/5228)
* [`GET_QUERIES` renamed to `QUERY` throughout](https://github.com/rocicorp/mono/pull/5230)
* [Ping timeouts now configurable in constructor](https://github.com/rocicorp/mono/pull/5114) and [at runtime](https://github.com/rocicorp/mono/pull/5116)
* [Add configurable WebSocket compression](https://github.com/rocicorp/mono/pull/5071)
* [tx.upsert should not overwrite w/ null on missing value](https://github.com/rocicorp/mono/pull/5031)
* [`sourceField` in schema wasn't strongly typed](https://github.com/rocicorp/mono/pull/5041)
* [Avoid unique violations during push caused by history compression](https://github.com/rocicorp/mono/pull/5030)
* [Invalid SQL was being generated for arrays](https://github.com/rocicorp/mono/pull/5042)
* [Handle connections to a view-syncer that has shut down properly](https://github.com/rocicorp/mono/pull/5101)
* [Process pending messages on closed websocket](https://github.com/rocicorp/mono/pull/5110)
* [Do not hydrate queries if no clients initialized](https://github.com/rocicorp/mono/pull/5107)
* [Inspector.analyzeQuery() wasn't mapping names](https://github.com/rocicorp/mono/pull/5096)
* [Add flow control to subscriber catchup](https://github.com/rocicorp/mono/pull/5125)
* [Migrate TTL/inactivatedAt to DOUBLE PRECISION with clamping](https://github.com/rocicorp/mono/pull/5130)
* [Continuous change-log cleanup for single-node](https://github.com/rocicorp/mono/pull/5135)
* [Count SQLite row scans, not what is returned to us](https://github.com/rocicorp/mono/pull/5119)
* [Make schema path optional for zero-cache-dev](https://github.com/rocicorp/mono/pull/5137) (thanks [@mattkinnersley](https://github.com/mattkinnersley)!)
* [Export context types](https://github.com/rocicorp/mono/pull/5102) (thanks [@awkweb](https://github.com/tmm)!)
* [Suppress deprecation warnings for unset options](https://github.com/rocicorp/mono/pull/5155)
* [Fixed closing expo-sqlite DB before deleting](https://github.com/rocicorp/mono/pull/5149)
* [Catch errors from async/pipelined db calls](https://github.com/rocicorp/mono/pull/5163)
* [Expliclty set isolation level in CVR transactions](https://github.com/rocicorp/mono/pull/5165)
* [Change when/where we check advance progress to catch slow change](https://github.com/rocicorp/mono/pull/5161)
* [Fix desync caused by client/server inconsistency in keys used to identify rows](https://github.com/rocicorp/mono/pull/5191)
* [Send name/args for named queries to enable auth context](https://github.com/rocicorp/mono/pull/5197)
* [Re-transform queries on every reconnect](https://github.com/rocicorp/mono/pull/5189)
* [Defer completing orderBy(s) until pipeline build and use client primary key](https://github.com/rocicorp/mono/pull/5194)
* [Pipeline-driver was in invalid state after ResetPipelinesSignal error](https://github.com/rocicorp/mono/pull/5213)
* [Fix pipeline storage db collision](https://github.com/rocicorp/mono/pull/5214)
* [SolidJS connection state not updating](https://github.com/rocicorp/mono/pull/5171) (thanks [@fezproof](https://github.com/fezproof))
* [Corrects the error semantics of the mutate callback](https://github.com/rocicorp/mono/pull/5207)
* [Delay resolving ViewSyncer#initialized until cvr.clientSchema is ensured](https://github.com/rocicorp/mono/pull/5236)
* [Use memo to ensure minimal updates in SolidJS](https://github.com/rocicorp/mono/pull/5241)
* [Sort queries by hydrateServer desc](https://github.com/rocicorp/mono/pull/5242)
* [Delay the replication-manager handoff for loadbalancer task registration](https://github.com/rocicorp/mono/pull/5250)
* [Use `zql_root` as root table name instead of `root`](https://github.com/rocicorp/mono/pull/5308) (thanks [@tjenkinson](https://github.com/tjenkinson)!)
## Breaking Changes
Despite the large DX update, we tried to make the upgrade as smooth as possible. However, there are a few breaking changes we could not easily avoid.
1. If you do not want to immediately opt-in to the new query and mutator APIs, set [`enableLegacyQueries`](https://zero.rocicorp.dev/docs/deprecated/ad-hoc-queries) and [`enableLegacyMutators`](https://zero.rocicorp.dev/docs/deprecated/crud-mutators) to `true` in your schema.ts.
2. If you are using the `.client` or `.server` promises with custom mutators, these no longer ever reject. [They now always resolve with a result type that has success/error cases](https://zero.rocicorp.dev/docs/mutators#waiting-for-results)
3. [Mutators now reject while Zero is offline](https://zero.rocicorp.dev/docs/connection#disconnecting). You may want to use the new [Connection Status API](https://zero.rocicorp.dev/docs/connection) to detect this and display custom UI to users.
4. The pattern for reauthentication has changed. The `auth` parameter is now always a `string` – the `function` form is no longer supported. Instead, [call `zero.connection.connect({auth: token})` to reconnect](https://zero.rocicorp.dev/docs/auth#auth-failure-and-refresh). This was done to simplify the API and support reauth via cookies consistently.
5. The `onError` feature of `Zero` has been removed. It was undocumented and only half-working. Please use the new [Connection Status API](https://zero.rocicorp.dev/docs/connection) to detect errors and display custom UI to users.
Or, for AI assistants
ALWAYS readllms.txtfor curated documentation pages and examples.
There are no longer first-class auth or permission systems. There are no longer "custom mutators" and "crud mutators", or "synced queries" and "zql queries".
All the old APIs have been deprecated, and the docs have been rewritten and simpilfied. Additionally, this release introduces a raft of big new features.
To ease the transition, and allow access to new features without a ton of work, you can still use the old APIs via the enableLegacyQueries and enableLegacyMutators flags. Note that support for these older APIs will be removed for the Zero beta early next year.
Additionally, the old hello-zero sample has been updated from the original CRUD mutators and queries all the way to the latest hotness. So if you were still using those APIs, you can use this as a guide to upgrade.
Query Planning: Zero now automatically plans joins, similar to other databases. You no longer need to specify flip:true to optimize whereExists() calls.
Reworked Query DX: Queries now receive a Context automatically – you don't have to pass it at the call site. Also, any Standard Schema conforming library can be used for validation and the API has been generally simplified and streamlined.
Reworked Mutator DX: The mutator API has been overhauled to match queries. Mutators now also support validation.
Default Schema Type: The Schema type can now be registered as a default with Zero. You can just say useZero() – useZero<Schema> is no longer needed. You can also delete your createUseZero() helper if you have one. This registration happens by default if you use the new drizzle-zero or prisma-zero packages.
New Connection Status API: Brand new connection status API with overhauled error-handling and reconnection behavior.
Support for Generated Columns: In Postgres 18+, generated stored columns are now synced. This is useful for denormalizing data from JSON columns to support filtering in Zero.
The pattern for reauthentication has changed. The auth parameter is now always a string – the function form is no longer supported. Instead, call zero.connection.connect({auth: token}) to reconnect. This was done to simplify the API and support reauth via cookies consistently.
The onError feature of Zero has been removed. It was undocumented and only half-working. Please use the new Connection Status API to detect errors and display custom UI to users.