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
13 changes: 9 additions & 4 deletions docs/src/content/docs/guides/validation/body.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ The request body can be validated with the `schemas.body` option.
`ctx.body` defaults to `unknown`, since its shape can't be inferred.
</Callout>

<Callout type="warn">
Aura Router has limited type inference for TypeBox schemas, due to the expensive computation operations performed by TypeBox. If
you want to use TypeBox, use the `Static` type to infer the schema type inside the endpoint handler.
</Callout>

<Tabs items={["zod", "valibot", "arktype", "typebox"]} persist groupId="schema-validation">

<Tab value="zod">
Expand Down Expand Up @@ -99,7 +104,7 @@ export const createUser = createEndpoint(
<Tab value="typebox">

```ts lineNumbers
import { Type } from "typebox"
import { Type, type Static } from "typebox"
import { createEndpointConfig, createEndpoint } from "@aura-stack/router"

export const config = createEndpointConfig({
Expand All @@ -115,7 +120,7 @@ export const createUser = createEndpoint(
"POST",
"/users",
async (ctx) => {
const { name, email } = ctx.body
const { name, email } = ctx.body as unknown as Static<typeof ctx.body>
return ctx.json({ id: "new-id", name, email }, { status: 201 })
},
config
Expand Down Expand Up @@ -235,7 +240,7 @@ export const createUser = createEndpoint(
<Tab value="typebox">

```ts lineNumbers
import { Type } from "typebox"
import { Type, type Static } from "typebox"
import { createEndpointConfig, createEndpoint } from "@aura-stack/router"

export const config = createEndpointConfig({
Expand All @@ -257,7 +262,7 @@ export const createUser = createEndpoint(
"POST",
"/users",
async (ctx) => {
const { name, email } = ctx.body
const { name, email } = ctx.body as unknown as Static<typeof ctx.body>
return ctx.json({ id: "new-id", name, email }, { status: 201 })
},
config
Expand Down
13 changes: 9 additions & 4 deletions docs/src/content/docs/guides/validation/headers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ Request headers can be validated with the `schemas.headers` option, which checks
correctly.
</Callout>

<Callout type="warn">
Aura Router has limited type inference for TypeBox schemas, due to the expensive computation operations performed by TypeBox. If
you want to use TypeBox, use the `Static` type to infer the schema type inside the endpoint handler.
</Callout>

<Tabs items={["zod", "valibot", "arktype", "typebox"]} persist groupId="schema-validation">

<Tab value="zod">
Expand Down Expand Up @@ -104,7 +109,7 @@ export const signOut = createEndpoint(
<Tab value="typebox">

```ts lineNumbers
import { Type } from "typebox"
import { Type, type Static } from "typebox"
import { createEndpointConfig, createEndpoint } from "@aura-stack/router"

export const config = createEndpointConfig({
Expand All @@ -120,7 +125,7 @@ export const signOut = createEndpoint(
"POST",
"/signOut",
async (ctx) => {
const { authorization } = ctx.headers
const { authorization } = ctx.headers as unknown as Static<typeof ctx.headers>
return ctx.json({ message: "Signed out successfully" })
},
config
Expand Down Expand Up @@ -237,7 +242,7 @@ export const signOut = createEndpoint(
<Tab value="typebox">

```ts lineNumbers
import { Type } from "typebox"
import { Type, type Static } from "typebox"
import { createEndpointConfig, createEndpoint } from "@aura-stack/router"

export const config = createEndpointConfig({
Expand All @@ -258,7 +263,7 @@ export const signOut = createEndpoint(
"POST",
"/signOut",
async (ctx) => {
const { authorization } = ctx.headers
const { authorization } = ctx.headers as unknown as Static<typeof ctx.headers>
return ctx.json({ message: "Signed out successfully" })
},
config
Expand Down
105 changes: 103 additions & 2 deletions docs/src/content/docs/guides/validation/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,21 @@ title: Schema Validation
description: Learn how to add schema validation to your Aura Router endpoints using popular validation libraries.
---

Schema validation is an optional configuration in `createEndpoint` and `createEndpointConfig`. It enables runtime validation for `headers`, `params`, `searchParams`, `body` and `response` verifying the incoming data and giving the endpoint's request context full type safety.
Schema validation is an optional configuration in `createEndpoint` and `createEndpointConfig`. It enables runtime validation for `headers`, `params`, `searchParams`, `body`, and `response`, verifying the incoming data and giving the endpoint's request context full type safety.

<Callout>
Aura Router doesn't ship built-in schema validation. Install a supported validation library to use this feature — see
[Installation](#installation) below.
</Callout>

<Callout type="warn">
Aura Router has limited type inference for TypeBox schemas, due to the expensive computation operations performed by TypeBox. If
you want to use TypeBox, use the `Static` type to infer the schema type inside the endpoint handler.
</Callout>

<Tabs items={["zod", "valibot", "arktype", "typebox"]} persist groupId="schema-validation">

<Tab value="zod">

```ts lineNumbers
import { z } from "zod"
Expand All @@ -14,7 +28,7 @@ export const endpoint = createEndpoint(
"/auth/signIn",
async (ctx) => {
const { username, password } = ctx.body
return Response.json({ message: "Successful Login" })
return ctx.json({ message: "Successful Login" })
},
{
schemas: {
Expand All @@ -27,6 +41,89 @@ export const endpoint = createEndpoint(
)
```

</Tab>

<Tab value="valibot">

```ts lineNumbers
import * as valibot from "valibot"
import { createEndpoint } from "@aura-stack/router"

export const endpoint = createEndpoint(
"POST",
"/auth/signIn",
async (ctx) => {
const { username, password } = ctx.body
return ctx.json({ message: "Successful Login" })
},
{
schemas: {
body: valibot.object({
username: valibot.string(),
password: valibot.string(),
}),
},
}
)
```

</Tab>

<Tab value="arktype">

```ts lineNumbers
import { type } from "arktype"
import { createEndpoint } from "@aura-stack/router"

export const endpoint = createEndpoint(
"POST",
"/auth/signIn",
async (ctx) => {
const { username, password } = ctx.body
return ctx.json({ message: "Successful Login" })
},
{
schemas: {
body: type({
username: "string",
password: "string",
}),
},
}
)
```

</Tab>

<Tab value="typebox">

```ts lineNumbers
import { Type, type Static } from "typebox"
import { createEndpoint } from "@aura-stack/router"

export const endpoint = createEndpoint(
"POST",
"/auth/signIn",
async (ctx) => {
// TypeBox has limited type inference, cast manually using Static<>
const { username, password } = ctx.body as unknown as Static<typeof ctx.body>
return ctx.json({ message: "Successful Login" })
},
{
schemas: {
body: Type.Object({
username: Type.String(),
password: Type.String(),
}),
},
}
)
```

</Tab>

</Tabs>

## Installation

To add schema validation support, install the corresponding validation library alongside `@aura-stack/router`. Supported validators are Zod, TypeBox, Valibot, and ArkType.
Expand Down Expand Up @@ -72,15 +169,19 @@ npm install arktype
<Card title="Headers" href="/docs/guides/validation/headers">
Validate request headers using the `schemas.headers` option.
</Card>

<Card title="Params" href="/docs/guides/validation/params">
Validate request params using the `schemas.params` option.
</Card>

<Card title="Search Params" href="/docs/guides/validation/search-params">
Validate request search params using the `schemas.searchParams` option.
</Card>

<Card title="Body" href="/docs/guides/validation/body">
Validate request body using the `schemas.body` option.
</Card>

<Card title="Response" href="/docs/guides/validation/response">
Validate outgoing responses using the `schemas.response` option.
</Card>
Expand Down
13 changes: 9 additions & 4 deletions docs/src/content/docs/guides/validation/params.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ Dynamic URL segments can be validated with the `schemas.params` option, which ch
each param is instead inferred as a plain string, extracted directly from the route pattern.
</Callout>

<Callout type="warn">
Aura Router has limited type inference for TypeBox schemas, due to the expensive computation operations performed by TypeBox. If
you want to use TypeBox, use the `Static` type to infer the schema type inside the endpoint handler.
</Callout>

<Tabs items={["zod", "valibot", "arktype", "typebox"]} persist groupId="schema-validation">

<Tab value="zod">
Expand Down Expand Up @@ -99,7 +104,7 @@ export const getBookById = createEndpoint(
<Tab value="typebox">

```ts lineNumbers
import { Type } from "typebox"
import { Type, type Static } from "typebox"
import { createEndpointConfig, createEndpoint } from "@aura-stack/router"

export const config = createEndpointConfig("/users/:userId/books/:bookId", {
Expand All @@ -115,7 +120,7 @@ export const getBookById = createEndpoint(
"GET",
"/users/:userId/books/:bookId",
async (ctx) => {
const { userId, bookId } = ctx.params
const { userId, bookId } = ctx.params as unknown as Static<typeof ctx.params>
return ctx.json({ bookId })
},
config
Expand Down Expand Up @@ -235,7 +240,7 @@ export const getBookById = createEndpoint(
<Tab value="typebox">

```ts lineNumbers
import { Type } from "typebox"
import { Type, type Static } from "typebox"
import { createEndpointConfig, createEndpoint } from "@aura-stack/router"

export const config = createEndpointConfig("/users/:userId/books/:bookId", {
Expand All @@ -257,7 +262,7 @@ export const getBookById = createEndpoint(
"GET",
"/users/:userId/books/:bookId",
async (ctx) => {
const { userId, bookId } = ctx.params
const { userId, bookId } = ctx.params as unknown as Static<typeof ctx.params>
return ctx.json({ bookId })
},
config
Expand Down
13 changes: 9 additions & 4 deletions docs/src/content/docs/guides/validation/search-params.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ Search params (query params) can be validated with the `schemas.searchParams` op
schema is defined, `ctx.searchParams` is the native `URLSearchParams` object instead.
</Callout>

<Callout type="warn">
Aura Router has limited type inference for TypeBox schemas, due to the expensive computation operations performed by TypeBox. If
you want to use TypeBox, use the `Static` type to infer the schema type inside the endpoint handler.
</Callout>

<Tabs items={["zod", "valibot", "arktype", "typebox"]} persist groupId="schema-validation">

<Tab value="zod">
Expand Down Expand Up @@ -107,7 +112,7 @@ export const searchUsers = createEndpoint(
<Tab value="typebox">

```ts lineNumbers
import { Type } from "typebox"
import { Type, type Static } from "typebox"
import { createEndpointConfig, createEndpoint } from "@aura-stack/router"

export const config = createEndpointConfig({
Expand All @@ -130,7 +135,7 @@ export const searchUsers = createEndpoint(
"GET",
"/users/search",
async (ctx) => {
const { q, page } = ctx.searchParams
const { q, page } = ctx.searchParams as unknown as Static<typeof ctx.searchParams>
return ctx.json({ query: q, page, results: [] })
},
config
Expand Down Expand Up @@ -261,7 +266,7 @@ export const searchUsers = createEndpoint(
<Tab value="typebox">

```ts lineNumbers
import { Type } from "typebox"
import { Type, type Static } from "typebox"
import { createEndpointConfig, createEndpoint } from "@aura-stack/router"

export const config = createEndpointConfig({
Expand Down Expand Up @@ -291,7 +296,7 @@ export const searchUsers = createEndpoint(
"GET",
"/users/search",
async (ctx) => {
const { q, page } = ctx.searchParams
const { q, page } = ctx.searchParams as unknown as Static<typeof ctx.searchParams>
return ctx.json({ query: q, page, results: [] })
},
config
Expand Down
Loading