yeah we specifically decided not to be local/offline-first because these add huge complexity that is not needed for the type of apps we want to support. I spoke about this a bit here if you are interested:
https://www.youtube.com/watch?v=86NmEerklTs&t=1764sAs for ZQL:
a) basically all of our customers already use Drizzle/Prisma. So they are very used to custom DSLs, and like them. I know, I was surprised to!
b) You typically use the same code client-side and server-side. There's no branching. The example you pasted is showing an escape hatch for when you want to use custom SQL. The option is there, but it's not the common experience.
This is what a typical mutator looks like:
```ts
// src/mutators.ts
import {defineMutators, defineMutator} from '@rocicorp/zero'
import {z} from 'zod'
export const mutators = defineMutators({
updateIssue: defineMutator(
z.object({
id: z.string(),
title: z.string()
}),
async ({tx, args: {id, title}}) => {
if (title.length > 100) {
throw new Error(`Title is too long`)
}
await tx.mutate.issue.update({
id,
title
})
}
)
})
```
We are trying to make apps like Notion, Linear, Superhuman easier to create. These apps all uses custom-built sync engines that took their teams many person-years of effort to construct.
Whether this complexity is worth it depends on how badly you want instantaneous response. If you do, you will end up using sync one way or other, and you will end up with something roughly like Zero mutators.