Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 68 additions & 14 deletions contents/docs/custom-mutators.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -358,24 +358,12 @@ If the client-side mutator fails, the `.server` promise is also rejected with th

You will need a server somewhere you can run an endpoint on. This is typically a serverless function on a platform like Vercel or AWS but can really be anything.

Configure the push endpoint with the `push.url` parameter in your `Zero` constructor:

```ts
const zero = new Zero({
push: {
url: 'https://zero.my-server.com/push',
},
});
```

You will also need to enable the server to be used as a push endpoint with the [`ZERO_PUSH_URL` environment variable or `--push-url` flag](./zero-cache-config#push-url):
Configure the push endpoint with the `ZERO_MUTATE_URL` configuration parameter:

```bash
ZERO_PUSH_URL=https://*.my-server.com/push
ZERO_MUTATE_URL=https://my-server.com/api/mutate
```

The `ZERO_PUSH_URL` parameter accepts wildcards, enabling the client to pass runtime configuration to the push endpoint or to use a different push endpoint, e.g., for previews. See the [config docs](./zero-cache-config#push-url) for the full syntax.

The push endpoint receives a `PushRequest` as input describing one or more mutations to apply to the backend, and must return a `PushResponse` describing the results of those mutations.

If you are implementing your server in TypeScript, you can use the `PushProcessor` class to trivially implement this endpoint. Here’s an example in a [Hono](https://hono.dev/) app:
Expand Down Expand Up @@ -419,6 +407,72 @@ export default handle(app);

To reuse the client mutators exactly as-is on the server just pass the result of the same `createMutators` function to `PushProcessor`.

### Custom Mutate URL

By default, custom mutators use the URL specified in the `ZERO_MUTATE_URL` parameter. However you can customize this on a per-client basis. To do so, list multiple comma-separted URLs in the `ZERO_MUTATE_URL` parameter:

```bash
ZERO_MUTATE_URL='https://api.example.com/mutate,https://api.staging.example.com/mutate'
```

Then choose one of those URLs by passing it to `mutateURL` on the `Zero` constructor:

```ts
const zero = new Zero({
schema,
mutators: createMutators(),
mutateURL: 'https://api.staging.example.com/mutate',
});
```

### Wildcards

The URLs listed in `ZERO_MUTATE_URL` can contain `*` wildcards:

```bash
# Allow any subdomain of example.com
ZERO_MUTATE_URL="https://*.example.com/push"
```

This mutate URL will allow clients to choose URLs like:
- `https://api.example.com/push` ✅
- `https://staging.example.com/push` ✅
- `https://api-feat-123.example.com/push` ✅

But rejects URLs like:
- `https://example.com/push` ❌ (no subdomain)
- `https://malicious.com/push` ❌ (different domain)
- `https://api.example.com/push/extra` ❌ (extra path)

Wildcards are only allowed for subdomains and follow these rules:

**Single Wildcard:**
```bash
ZERO_MUTATE_URL="https://*.example.com/push"
```
- ✅ Matches: `https://api.example.com/push`
- ✅ Matches: `https://www.example.com/push`
- ✅ Matches: `https://staging-v2.example.com/push`
- ❌ Does not match: `https://example.com/push` (no subdomain)
- ❌ Does not match: `https://api.staging.example.com/push` (multiple subdomains)

**Multiple Wildcards:**
```bash
ZERO_MUTATE_URL="https://*.*.example.com/push"
```
- ✅ Matches: `https://api.v1.example.com/push`
- ✅ Matches: `https://www.staging.example.com/push`
- ❌ Does not match: `https://api.example.com/push` (only one subdomain)
- ❌ Does not match: `https://api.v1.staging.example.com/push` (three subdomains)

**Path Restrictions:**
```bash
ZERO_MUTATE_URL="https://*.example.com/api/push"
```
- ✅ Matches: `https://api.example.com/api/push`
- ❌ Does not match: `https://api.example.com/api/push/extra` (trailing path)
- ❌ Does not match: `https://api.example.com/push` (missing /api)

### Server Error Handling

The `PushProcessor` in `@rocicorp/zero/pg` skips any mutations that throw:
Expand Down
24 changes: 24 additions & 0 deletions contents/docs/release-notes/0.24.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: Zero 0.24
description: Preview Support
---

## Install

```bash
npm install @rocicorp/[email protected]
```

## Upgrading

## Features

- Preview support for [custom mutators](/docs/custom-mutators#custom-mutate-url) and [synced queries](/docs/synced-queries#custom-get-queries-url).

## Fixes

## zbugs

## Breaking Changes

- The `push.url` client parameter was removed in favor of `mutateURL`. A matching `ZERO_MUTATE_URL` config param was also added.
1 change: 1 addition & 0 deletions contents/docs/release-notes/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
title: Release Notes
---

- [Zero 0.24: Preview Support](/docs/release-notes/0.24)
- [Zero 0.23: Synced Queries and React Native Support](/docs/release-notes/0.23)
- [Zero 0.22: Simplified TTLs](/docs/release-notes/0.22)
- [Zero 0.21: PG arrays, TanStack starter, and more](/docs/release-notes/0.21)
Expand Down
26 changes: 25 additions & 1 deletion contents/docs/synced-queries.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ This has many benefits:

* No need for a separate permission system. Your server enforces permissions by constructing queries dynamically. Clients have no direct access to the database.
* Simpler auth. Your server can use any auth system you want – Zero does not need to know or understand it.
* Previews. Since synced queries are implemented on your server, they can naturally support [branch previews](https://vercel.com/docs/deployments/sharing-deployments) on platforms like Vercel. This [doesn't quite work yet](https://bugs.rocicorp.dev/issue/4063), but will be coming to Zero soon.
* Previews. Since synced queries are implemented on your server, they can naturally support [branch previews](#custom-get-queries-url) on platforms like Vercel.

<Note emoji="💬" heading='"Synced Queries" === "Custom Queries"'>
This feature used to be called "custom queries". But soon it will be Zero's only read API, and won't be "custom" at all. So we renamed it.
Expand Down Expand Up @@ -317,6 +317,30 @@ function getQuery(
}
```

### Custom Get Queries URL

By default, synced queries use the URL specified in the `ZERO_GET_QUERIES_URL` parameter. However you can customize this on a per-client basis. To do so, list multiple comma-separted URLs in the `ZERO_GET_QUERIES_URL` parameter:

However you can customize this on a per-client basis. To do so, list multiple comma-separted URLs in the `ZERO_GET_QUERIES_URL` parameter:

```bash
ZERO_GET_QUERIES_URL='https://api.example.com/get-queries,https://api.staging.example.com/get-queries'
```

Then choose one of those URLs by passing it to `getQueriesURL` on the `Zero` constructor:

```ts
const zero = new Zero({
schema,
mutators: createMutators(),
getQueriesURL: 'https://api.staging.example.com/get-queries',
});
```

### Wildcards

The URLs listed in `ZERO_GET_QUERIES_URL` can contain `*` wildcards. See the [Wildcard Syntax](./custom-mutators#wildcard-syntax) section in the Custom Mutators documentation for details. It works the same way for synced queries.

## Custom Server Implementation

It is possible to implement the `ZERO_GET_QUERIES_URL` endpoint without using Zero's TypeScript libraries, or even in a different language entirely.
Expand Down