-
-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(example): add nested schema example
- Loading branch information
Showing
3 changed files
with
126 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import ShopForm from "./shop-form"; | ||
|
||
export const metadata = { | ||
title: "Nested schema", | ||
}; | ||
|
||
export default function NestedSchemaPage() { | ||
return ( | ||
<> | ||
<ShopForm /> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
"use server"; | ||
|
||
import { action } from "@/lib/safe-action"; | ||
import { z } from "zod"; | ||
|
||
const input = z | ||
.object({ | ||
user: z.object({ | ||
id: z.string().uuid(), | ||
}), | ||
product: z.object({ | ||
deeplyNested: z.object({ | ||
id: z.string().uuid(), | ||
}), | ||
}), | ||
}) | ||
.superRefine((_, ctx) => { | ||
// Randomly generate validation error for root. | ||
if (Math.random() > 0.5) { | ||
ctx.addIssue({ | ||
code: "custom", | ||
message: "Parent schema error", | ||
}); | ||
} | ||
|
||
// Randomly generate validation error for user object. | ||
if (Math.random() > 0.5) { | ||
ctx.addIssue({ | ||
code: "custom", | ||
path: ["user"], | ||
message: "Parent user error", | ||
}); | ||
ctx.addIssue({ | ||
code: "custom", | ||
path: ["user"], | ||
message: "Parent user error 2", | ||
}); | ||
} | ||
|
||
// Randomly generate validation error for user id. | ||
if (Math.random() > 0.5) { | ||
ctx.addIssue({ | ||
code: "custom", | ||
path: ["user", "id"], | ||
message: "Another bad user id error", | ||
}); | ||
} | ||
|
||
// Randomly generate validation errors for product object. | ||
if (Math.random() > 0.5) { | ||
ctx.addIssue({ | ||
code: "custom", | ||
path: ["product"], | ||
message: "Parent product error", | ||
}); | ||
|
||
ctx.addIssue({ | ||
code: "custom", | ||
path: ["product", "deeplyNested"], | ||
message: "Deeply nested product error", | ||
}); | ||
|
||
ctx.addIssue({ | ||
code: "custom", | ||
path: ["product", "deeplyNested", "id"], | ||
message: "Product not found in the store", | ||
}); | ||
} | ||
}); | ||
|
||
export const buyProduct = action(input, async () => { | ||
return { | ||
success: true, | ||
}; | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
"use client"; | ||
|
||
import { useState } from "react"; | ||
import { buyProduct } from "./shop-action"; | ||
|
||
const ShopForm = () => { | ||
const [result, setResult] = useState( | ||
"fill in form and click on the log in button" | ||
); | ||
|
||
return ( | ||
<> | ||
<form | ||
onSubmit={async (e) => { | ||
e.preventDefault(); | ||
|
||
// Change one of these two to generate validation errors. | ||
const userId = crypto.randomUUID(); | ||
const productId = crypto.randomUUID(); | ||
|
||
const res = await buyProduct({ | ||
user: { id: userId }, | ||
product: { deeplyNested: { id: productId } }, | ||
}); // this is the typesafe action called from client | ||
|
||
setResult(JSON.stringify(res, null, 1)); | ||
}}> | ||
<button type="submit">Buy product</button> | ||
</form> | ||
<div id="result-container"> | ||
<div>Action result:</div> | ||
<pre className="result">{result}</pre> | ||
</div> | ||
</> | ||
); | ||
}; | ||
|
||
export default ShopForm; |