Schemas are here!
This release has some big changes to Convex that we’re really excited to show to you all. Two of these are breaking changes that will require you to make minor updates to your app, so read carefully:
- Schema Support
- Breaking: Generated Code Changes
- Breaking:
db.update
renamed todb.patch
- TypeScript Type Checking
- Extra Goodies
As always, let us know what you think of this in the Convex Slack Community!
Schema Support
The biggest feature in this update is schemas. Convex now supports defining the schema of your project in a schema.ts
file. The schema file describes the tables in your Convex app and the type of documents stored in each table. It might look something like:
import { defineSchema, defineTable, s } from "convex-dev/schema";
export default defineSchema({
messages: defineTable({
body: s.string(),
time: s.number(),
user: s.id(),
}),
users: defineTable({
name: s.string(),
}),
});
Once you define a schema, if you rerun npx convex codegen
, Convex will use that schema to generate two new generated files: dataModel.ts
and server.ts
.
The Document
type from dataModel.ts
provides document types for all of your tables. You can use these both when writing Convex functions and in your React components:
import { Document } from "../convex/_generated/dataModel";
function MessageView(props: { message: Document<"messages"> }) {
...
}
The query
and mutation
functions in server.ts
have the same API as before but now provide a db
with more precise types. Functions like db.insert(table, document)
now understand your schema. Additionally database queries will now return the correct document type (not any
).
A couple of notes about schemas:
- This is currently a “types only” feature. Adding a schema will give you precise, code generated types, but won't completely prevent you from writing bad data into your tables. Convex will support schema enforcement at runtime in the future.
- There are still some APIs like
db.get(id)
that still use loose types likeany
even if you define a schema. We’ll be fixing this soon too!
Lastly, schemas are optional! We encourage you to start your project schema-less while you’re prototyping and add a schema once you've solidified your plan.
To learn more about schemas, see the documentation at https://docs.convex.dev/using/schemas!
Breaking: Generated Code Changes
We’ve made a couple of changes to our generated code:
- The location of our generated React hooks has moved from
convex/_generated.ts
toconvex/_generated/react.ts
. - The
query
andmutation
wrappers have moved from our npm package atconvex-dev/server
into generated code atconvex/_generated/server.ts
. - There is a new generated file:
convex/_generated/dataModel.ts
.
Rationale
We’ve added the new generated server.ts
and dataModel.ts
to give you schema-specific type safety. You can read more about that in “Schema Support” above. We also generate server.ts
and dataModel.ts
even before you define a schema so that you won’t need to change your imports when you add one.
We’ve moved all of the generated code into the _generated
directory to keep it organized now that there are multiple files.
Migration
- Run
npx convex codegen
. This will delete the old code generated file and create the new ones. - Update all of your import paths from
convex/_generated
toconvex/_generated/react
to import the React hooks from the new location. - Update all of your imports of
query
andmutation
fromconvex-dev/server
toconvex/_generated/server
.
If you don’t want to use code generation, you can still use the untyped versions of all of these functions:
queryGeneric
andmutationGeneric
fromconvex-dev/server
useQueryGeneric
anduseMutationGeneric
fromconvex-dev/react
Breaking: db.update
renamed to db.patch
We’ve renamed the db.update
method in mutations to be called db.patch
.
Rationale
The reasoning for this is that we’ve noticed some confusion around how db.update
works.
db.update
(now called db.patch
) takes a partial version of a document and updates the specified fields to the new values. It doesn’t edit fields on the document that aren’t specified. For example you can create a document and update a single field on it with db.patch
:
const id = db.insert("messages", {
message: "hello",
author: "Alex"
});
db.patch(id, {
message: "Hi!"
});
// The document still has the original author field and the new message.
This is in contrast to db.replace
which will replace an entire document with a new object, overwriting all fields.
Migration
Switch all of the usages of db.update
to use db.patch
. If you find call sites that are setting all the properties of a document, you probably want db.replace
instead.
TypeScript Type Checking
The Convex CLI will now run attempt TypeScript type checking on your Convex functions during npx convex push
and npx convex codegen
. This should help catch potential bugs early on and produce more readable error messages.
Extra Goodies
We also have a lot of small improvements that should make developing on Convex better than ever:
- There is now Next.js documentation that teaches you how to set up Convex in a Next.js app.
- The Convex CLI now updates your generated code during
npx convex push
so it doesn’t fall out of date. - Convex now works on Safari 14! It will also work on older versions of Safari as long as none of your functions use the
bigint
type. - If you forget to include the
ConvexProvider
in your app, there is now a helpful error message.