fix(admin-next, utils, medusa): Handle db errors properly and fix form (#7416)

* fix(admin-next, utils, medusa): Handle db errors properly and fix form

* fix(admin-next, utils, medusa): Handle db errors properly and fix form

* fix(admin-next, utils, medusa): Handle db errors properly and fix form

* fix(admin-next, utils, medusa): Handle db errors properly and fix form
This commit is contained in:
Adrien de Peretti
2024-05-23 12:36:45 +02:00
committed by GitHub
parent e01472aae6
commit 37ae87fe9b
6 changed files with 47 additions and 14 deletions

View File

@@ -0,0 +1,5 @@
import { FetchError } from "@medusajs/js-sdk"
export const isFetchError = (error: any): error is FetchError => {
return error instanceof FetchError
}

View File

@@ -2,6 +2,7 @@ import { zodResolver } from "@hookform/resolvers/zod"
import { ArrowPath, Trash } from "@medusajs/icons"
import { InviteDTO } from "@medusajs/types"
import {
Alert,
Button,
Container,
Heading,
@@ -29,6 +30,7 @@ import {
} from "../../../../../hooks/api/invites"
import { DataTable } from "../../../../../components/table/data-table"
import { useUserInviteTableQuery } from "../../../../../hooks/table/query/use-user-invite-table-query"
import { isFetchError } from "../../../../../lib/is-fetch-error.ts"
const InviteUserSchema = zod.object({
email: zod.string().email(),
@@ -74,16 +76,18 @@ export const InviteUserForm = () => {
const { mutateAsync, isPending } = useCreateInvite()
const handleSubmit = form.handleSubmit(async (values) => {
await mutateAsync(
{
email: values.email,
},
{
onSuccess: () => {
form.reset()
},
try {
await mutateAsync({ email: values.email })
form.reset()
} catch (error) {
if (isFetchError(error) && error.status === 400) {
form.setError("root", {
type: "manual",
message: error.message,
})
return
}
)
}
})
if (isError) {
@@ -106,6 +110,17 @@ export const InviteUserForm = () => {
{t("users.inviteUserHint")}
</Text>
</div>
{form.formState.errors.root && (
<Alert
variant="error"
dismissible={false}
className="text-balance"
>
{form.formState.errors.root.message}
</Alert>
)}
<div className="flex flex-col gap-y-4">
<div className="grid grid-cols-2 gap-4">
<Form.Field

View File

@@ -45,8 +45,12 @@ const normalizeRequest = (
const normalizeResponse = async (resp: Response, reqHeaders: Headers) => {
if (resp.status >= 300) {
const error = new FetchError(resp.statusText, resp.status)
throw error
const jsonError = await resp.json().catch(() => ({})) as { message?: string }
throw new FetchError(
jsonError.message ?? resp.statusText,
resp.statusText,
resp.status
)
}
// If we requested JSON, we try to parse the response. Otherwise, we return the raw response.
@@ -56,9 +60,11 @@ const normalizeResponse = async (resp: Response, reqHeaders: Headers) => {
export class FetchError extends Error {
status: number | undefined
statusText: string | undefined
constructor(message: string, status?: number) {
constructor(message: string, statusText?: string, status?: number) {
super(message)
this.statusText = statusText
this.status = status
}
}

View File

@@ -21,3 +21,4 @@ class Medusa {
}
export default Medusa
export { FetchError } from "./client"

View File

@@ -74,7 +74,7 @@ const getConstraintInfo = (err: any) => {
return null
}
const [keys, values] = detail.match(/\([^\(.]*\)/g) || []
const [keys, values] = detail.match(/\([^\(]*\)/g) || []
if (!keys || !values) {
return null

View File

@@ -45,9 +45,15 @@ export const POST = async (
input: {
invites: [req.validatedBody],
},
throwOnError: false,
}
const { result, errors } = await workflow.run(input)
if (errors?.length) {
throw errors[0].error
}
const { result } = await workflow.run(input)
const invite = await refetchInvite(
result[0].id,
req.scope,