Skip to content
Merged
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
1 change: 1 addition & 0 deletions astro.sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export const sidebar = [
'reference/modules/astro-i18n',
'reference/modules/astro-middleware',
'reference/modules/astro-transitions',
'reference/modules/astro-zod',
],
}),
group('reference.other', {
Expand Down
22 changes: 11 additions & 11 deletions src/content/docs/en/guides/actions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Astro Actions allow you to define and call backend functions with type-safety. A

Use actions instead of API endpoints for seamless communication between your client and server code and to:

- Automatically validate JSON and form data inputs using [Zod validation](https://zod.dev/?id=primitives).
- Automatically validate JSON and form data inputs using [Zod validation](/en/reference/modules/astro-zod/).
- Generate type-safe functions to call your backend from the client and even [from HTML form actions](#call-actions-from-an-html-form-action). No need for manual `fetch()` calls.
- Standardize backend errors with the [`ActionError`](/en/reference/modules/astro-actions/#actionerror) object.

Expand All @@ -24,7 +24,7 @@ Actions are defined in a `server` object exported from `src/actions/index.ts`:

```ts title="src/actions/index.ts"
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
import { z } from 'astro/zod';

export const server = {
myAction: defineAction({ /* ... */ })
Expand Down Expand Up @@ -62,22 +62,22 @@ Follow these steps to define an action and call it in a `script` tag in your Ast
}
```

2. Import the `defineAction()` utility from `astro:actions`, and the `z` object from `astro:schema`.
2. Import the `defineAction()` utility from `astro:actions`, and the `z` object from `astro/zod`.

```ts ins={1-2} title="src/actions/index.ts"
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
import { z } from 'astro/zod';

export const server = {
// action declarations
}
```

3. Use the `defineAction()` utility to define a `getGreeting` action. The `input` property will be used to validate input parameters with a [Zod](https://zod.dev) schema and the `handler()` function includes the backend logic to run on the server.
3. Use the `defineAction()` utility to define a `getGreeting` action. The `input` property will be used to validate input parameters with a [Zod schema](/en/reference/modules/astro-zod/#common-data-type-validators) and the `handler()` function includes the backend logic to run on the server.

```ts ins={5-12} title="src/actions/index.ts"
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
import { z } from 'astro/zod';

export const server = {
getGreeting: defineAction({
Expand Down Expand Up @@ -213,7 +213,7 @@ This example throws an error from a `likePost` action when a user is not logged

```ts title="src/actions/index.ts" ins=/ActionError(?= )/ ins={9-12}
import { defineAction, ActionError } from "astro:actions";
import { z } from "astro:schema";
import { z } from "astro/zod";

export const server = {
likePost: defineAction({
Expand Down Expand Up @@ -290,7 +290,7 @@ Actions accept JSON data by default. To accept form data from an HTML form, set

```ts title="src/actions/index.ts" ins={6}
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
import { z } from 'astro/zod';

export const server = {
comment: defineAction({
Expand Down Expand Up @@ -319,7 +319,7 @@ To apply a union of different validators, use the `z.discriminatedUnion()` wrapp

```ts title="src/actions/index.ts" {7-21} "create" "update"
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
import { z } from 'astro/zod';

export const server = {
changeUser: defineAction({
Expand Down Expand Up @@ -378,7 +378,7 @@ The following example shows a validated newsletter registration form that accept

```ts title="src/actions/index.ts" ins={5-12}
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
import { z } from 'astro/zod';

export const server = {
newsletter: defineAction({
Expand Down Expand Up @@ -492,7 +492,7 @@ For example, say you have a `createProduct` action that returns the generated pr

```ts title="src/actions/index.ts" mark={10}
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
import { z } from 'astro/zod';

export const server = {
createProduct: defineAction({
Expand Down
2 changes: 1 addition & 1 deletion src/content/docs/en/guides/astro-db.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ You can also use [Astro actions](/en/guides/actions/) to insert data into an Ast
// src/actions/index.ts
import { db, Comment } from 'astro:db';
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
import { z } from 'astro/zod';

export const server = {
addComment: defineAction({
Expand Down
62 changes: 19 additions & 43 deletions src/content/docs/en/guides/content-collections.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,19 @@ To define collections, you must create a `src/content.config.ts` file in your pr

```ts title="src/content.config.ts"
// 1. Import utilities from `astro:content`
import { defineCollection, z } from 'astro:content';
import { defineCollection } from 'astro:content';

// 2. Import loader(s)
import { glob, file } from 'astro/loaders';

// 3. Define your collection(s)
// 3. Import Zod
import { z } from 'astro/zod';

// 4. Define your collection(s)
const blog = defineCollection({ /* ... */ });
const dogs = defineCollection({ /* ... */ });

// 4. Export a single `collections` object to register your collection(s)
// 5. Export a single `collections` object to register your collection(s)
export const collections = { blog, dogs };
```

Expand All @@ -89,9 +92,10 @@ The [`glob()` loader](/en/reference/content-loader-reference/#glob-loader) creat

The [`file()` loader](/en/reference/content-loader-reference/#file-loader) creates multiple entries from a single local file. Each entry in the file must have a unique `id` key property. It accepts a `base` file path to your file and optionally a [`parser` function](#parser-function) for data files it cannot parse automatically. Use this loader when your data file can be parsed as an array of objects.

```ts title="src/content.config.ts" {5,9}
import { defineCollection, z } from 'astro:content';
```ts title="src/content.config.ts" {6,10}
import { defineCollection } from 'astro:content';
import { glob, file } from 'astro/loaders'; // Not available with legacy API
import { z } from 'astro/zod';

const blog = defineCollection({
loader: glob({ pattern: "**/*.md", base: "./src/data/blog" }),
Expand Down Expand Up @@ -208,11 +212,12 @@ Schemas also power Astro's automatic TypeScript typings for your content. When y
In order for Astro to recognize a new or updated schema, you may need to restart the dev server or [sync the content layer](/en/reference/cli-reference/#astro-dev) (<code>s + enter</code>) to define the `astro:content` module.
:::

Every frontmatter or data property of your collection entries must be defined using a Zod data type:
Every frontmatter or data property of your collection entries must be defined using a [Zod data type](/en/reference/modules/astro-zod/#common-data-type-validators):

```ts title="src/content.config.ts" {6-11,15-19}
import { defineCollection, z } from 'astro:content';
import { glob, file } from 'astro/loaders'; // Not available with legacy API
```ts title="src/content.config.ts" {7-12,16-20}
import { defineCollection } from 'astro:content';
import { glob, file } from 'astro/loaders';
import { z } from 'astro/zod';

const blog = defineCollection({
loader: glob({ pattern: "**/*.md", base: "./src/data/blog" }),
Expand All @@ -239,43 +244,13 @@ export const collections = { blog, dogs };

Astro uses [Zod](https://github.com/colinhacks/zod) to power its content schemas. With Zod, Astro is able to validate every file's data within a collection *and* provide automatic TypeScript types when you go to query content from inside your project.

To use Zod in Astro, import the `z` utility from `"astro:content"`. This is a re-export of the Zod library, and it supports all of the features of Zod.

```ts
// Example: A cheatsheet of many common Zod datatypes
import { z, defineCollection } from 'astro:content';

defineCollection({
schema: z.object({
isDraft: z.boolean(),
title: z.string(),
sortOrder: z.number(),
image: z.object({
src: z.string(),
alt: z.string(),
}),
author: z.string().default('Anonymous'),
language: z.enum(['en', 'es']),
tags: z.array(z.string()),
footnote: z.string().optional(),

// In YAML, dates written without quotes around them are interpreted as Date objects
publishDate: z.date(), // e.g. 2024-09-17

// Transform a date string (e.g. "2022-07-08") to a Date object
updatedDate: z.string().transform((str) => new Date(str)),

authorContact: z.string().email(),
canonicalURL: z.string().url(),
})
})
```
To use Zod in Astro, import the `z` utility from `"astro/zod"`. This is a re-export of the Zod library, and it supports all of the features of Zod.

<ReadMore>See [Zod's README](https://github.com/colinhacks/zod) for complete documentation on how Zod works and what features are available.</ReadMore>
<ReadMore>See the [`z` utility reference](/en/reference/modules/astro-zod/) for a cheatsheet of common datatypes and to learn how Zod works and what features are available.</ReadMore>

##### Zod schema methods

All [Zod schema methods](https://zod.dev/?id=schema-methods) (e.g. `.parse()`, `.transform()`) are available, with some limitations. Notably, performing custom validation checks on images using `image().refine()` is unsupported.
All [Zod schema methods](/en/reference/modules/astro-zod/#using-zod-methods) (e.g. `.parse()`, `.transform()`) are available, with some limitations. Notably, performing custom validation checks on images using `image().refine()` is unsupported.

#### Defining collection references

Expand All @@ -286,8 +261,9 @@ With the [`reference()` function](/en/reference/modules/astro-content/#reference
A common example is a blog post that references reusable author profiles stored as JSON, or related post URLs stored in the same collection:

```ts title="src/content.config.ts"
import { defineCollection, reference, z } from 'astro:content';
import { defineCollection, reference } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';

const blog = defineCollection({
loader: glob({ pattern: '**/[^_]*.md', base: "./src/data/blog" }),
Expand Down
3 changes: 2 additions & 1 deletion src/content/docs/en/guides/images.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,8 @@ This is a blog post
The `image` helper for the content collections schema lets you validate and import the image.

```ts title="src/content.config.ts"
import { defineCollection, z } from "astro:content";
import { defineCollection } from "astro:content";
import { z } from "astro/zod";

const blogCollection = defineCollection({
schema: ({ image }) => z.object({
Expand Down
3 changes: 2 additions & 1 deletion src/content/docs/en/guides/integrations-guide/mdx.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,9 @@ It also adds extra features to standard MDX, including support for Markdown-styl
To include MDX files in a content collection, make sure that your [collection loader](/en/guides/content-collections/#defining-the-collection-loader) is configured to load content from `.mdx` files:

```js title="src/content.config.ts" ins="mdx"
import { defineCollection, z } from 'astro:content';
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';

const blog = defineCollection({
loader: glob({ pattern: "**/*.{md,mdx}", base: "./src/blog" }),
Expand Down
2 changes: 1 addition & 1 deletion src/content/docs/en/guides/integrations-guide/react.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ The example below gets the current value of likes from a counter, typed as a num

```ts title="actions.ts" ins={3,11}
import { defineAction, type SafeResult } from 'astro:actions';
import { z } from 'astro:schema';
import { z } from 'astro/zod';
import { getActionState } from '@astrojs/react/actions';

export const server = {
Expand Down
2 changes: 1 addition & 1 deletion src/content/docs/en/guides/sessions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ In actions, the session object is available on the `context` object. For example

```ts title="src/actions/addToCart.ts" "context.session"
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
import { z } from 'astro/zod';

export const server = {
addToCart: defineAction({
Expand Down
26 changes: 0 additions & 26 deletions src/content/docs/en/recipes/build-forms-api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -428,29 +428,3 @@ This recipe shows you how to send form data to an API endpoint and handle that d
</Fragment>
</UIFrameworkTabs>
</Steps>

{/* ## Extension: Use Zod to validate your form

[Zod form data](https://www.npmjs.com/package/zod-form-data) builds on top of [Zod](https://github.com/colinhacks/zod) to validate your form using a schema. This simplifies your code, as it allows you to declare the fields and their requirements, and let Zod handle the validation.

1. Install `zod` and `zod-form-data`.

<PackageManagerTabs>
<Fragment slot="npm">
```shell
npm i zod zod-form-data
```
</Fragment>
<Fragment slot="pnpm">
```shell
pnpm i zod zod-form-data
```
</Fragment>
<Fragment slot="yarn">
```shell
yarn add zod zod-form-data
```
</Fragment>
</PackageManagerTabs>

2. In your API Route file, declare your schema using `zfd.formData` and export it. */}
3 changes: 2 additions & 1 deletion src/content/docs/en/recipes/i18n.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ If you prefer the default language to not be visible in the URL unlike other lan

```ts
//src/content.config.ts
import { defineCollection, z } from 'astro:content';
import { defineCollection } from 'astro:content';
import { z } from 'astro/zod';

const blogCollection = defineCollection({
schema: z.object({
Expand Down
9 changes: 5 additions & 4 deletions src/content/docs/en/reference/content-loader-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ The recommended pattern is to define a function that accepts configuration optio

```ts title=loader.ts
import type { Loader, LoaderContext } from 'astro/loaders';
import { z } from 'astro:content';
import { z } from 'astro/zod';
import { loadFeedData } from "./feed.js";

// Define any options that the loader needs
Expand All @@ -209,9 +209,10 @@ export function myLoader(options: { url: string, apiKey: string }): Loader {

These configuration options can then be set when defining a collection:

```ts title="src/content.config.ts" {2,5-8}
import { defineCollection, z } from 'astro:content';
import myLoader from '../../loader.ts';
```ts title="src/content.config.ts" {3,6-9}
import { defineCollection } from 'astro:content';
import { z } from 'astro/zod';
import myLoader from '../../loader.ts';

const blog = defineCollection({
loader: myLoader({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,8 @@ if (error) {
Just like with build-time collections, you can use [Zod schemas](/en/guides/content-collections/#defining-the-collection-schema) with live collections to validate and transform data at runtime. When you define a schema, it takes precedence over [the loader's types](#type-safe-data) when you query the collection:

```ts title="src/live.config.ts"
import { z, defineLiveCollection } from 'astro:content';
import { defineLiveCollection } from 'astro:content';
import { z } from 'astro/zod';
import { apiLoader } from './loaders/api-loader';

const products = defineLiveCollection({
Expand Down
2 changes: 1 addition & 1 deletion src/content/docs/en/reference/legacy-flags.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ When you are ready to remove this flag and migrate to the new Content Layer API

```js
// src/content/config.ts
import { defineCollection, z } from 'astro:content';
import { defineCollection } from 'astro:content';

const blog = defineCollection({ })

Expand Down
4 changes: 2 additions & 2 deletions src/content/docs/en/reference/modules/astro-actions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ A utility to define new actions in the `src/actions/index.ts` file. This accepts

```ts title="src/actions/index.ts"
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
import { z } from 'astro/zod';

export const server = {
getGreeting: defineAction({
Expand Down Expand Up @@ -76,7 +76,7 @@ Return values are parsed using the [devalue library](https://github.com/Rich-Har
**Type:** `ZodType | undefined`
</p>

An optional property that accepts a Zod validator (e.g. Zod object, Zod discriminated union) to validate handler inputs at runtime. If the action fails to validate, [a `BAD_REQUEST` error](#actionerror) is returned and the `handler` is not called.
An optional property that accepts a [Zod validator](/en/reference/modules/astro-zod/#common-data-type-validators) (e.g. Zod object, Zod discriminated union) to validate handler inputs at runtime. If the action fails to validate, [a `BAD_REQUEST` error](#actionerror) is returned and the `handler` is not called.

If `input` is omitted, the `handler` will receive an input of type `unknown` for JSON requests and type `FormData` for form requests.

Expand Down
3 changes: 1 addition & 2 deletions src/content/docs/en/reference/modules/astro-content.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ Content collections offer APIs to configure and query your Markdown or MDX docum

```js
import {
z,
defineCollection,
getCollection,
getEntry,
Expand Down Expand Up @@ -76,7 +75,7 @@ A `loader` is either an object or a function that allows you to load data from a
<Since v="2.0.0" />
</p>

`schema` is an optional Zod object to configure the type and shape of document frontmatter for a collection. Each value must use [a Zod validator](https://github.com/colinhacks/zod).
`schema` is an optional Zod object to configure the type and shape of document frontmatter for a collection. Each value must use [a Zod validator](/en/reference/modules/astro-zod/#common-data-type-validators).

[See the `Content Collection` guide](/en/guides/content-collections/#defining-the-collection-schema) for example usage.

Expand Down
Loading