Introducing return value validators as well as updates to the CLI to show progress when backfilling indexes.

Return value validators

Convex queries, mutations, and actions now accept returns: property to specify a return value validator.

Return value validators throw a runtime error when the value returned from a function does not match this validator. This is stricter than TypeScript in that extra properties will not be allowed.

// convex/messages.ts
export const send = mutation({
	args: { author: v.string(), body: v.string() },
	returns: v.id("messages"),
	handler: async (ctx, { author, body }) => {
		return ctx.db.insert("messages", { author, body })
	}
})

Libraries like convex-helpers and convex-ents will be updated shortly to work with return value validators.

Exposing validator metadata

Validator fields are now exposed: the return value of v.object({ ... }) now has a .fields property with the validators for each property on it, allowing programmatically constructing new validators from existing validators:

const message = v.object({ user: v.string(), body: v.string() });
const imageMessage = v.object({ ...message.fields, kind: v.literal("image") })

Similarly, v.id(tableName) exposes .tableName, v.literal(value) exposes .value, v.array(element) exposes .element, and v.union(validator1, validator2) exposes .members.

Schema validators are also exposed on the schema at schema.tables.messages.validator.

The Validator export is no longer a class. It is now a discriminated union type of all validators where the .kind as the discriminator. The Validator type still has three type parameters with only the first (the TypeScript type enforced by the validator) required.

These are breaking changes if you're using the two optional type parameters of Validator or doing instanceof checks with Validator! We apologize for the inconvenience. The same users this affects should be the ones that most benefit from the ability to work with validator types more directly.

New types for query, mutation, and action wrappers

The types UnvalidatedFunction and ValidatedFunction are now deprecated in favor of types that support functions with and without argument validation or return value validation. See MutationBuilder or similar to see the updated types.

This is a breaking change for libraries that use these types, but should make TypeScript errors around query, mutation, and action more readable. convex-helpers and convex-ents will be updated shortly to work with these new types.

Index backfill progress in CLI

You can now see progress in the CLI when pushing new indexes:

0:00
/0:08

Updated tsconfig.json defaults

The default tsconfig.json created in projects when first creating the convex/ directory now uses "moduleResolution": "Bundler". This is just a better default, you probably never want the previous default "node"/"node10". We also added "jsx": "react-jsx" as a default.