feat: attempt to fix the crud with auth
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## To do
|
## To do
|
||||||
|
|
||||||
- [ ] Add user creation in database
|
- [ ] Get premium Vercel account for database
|
||||||
- [ ] Add middleware for authentication
|
- [ ] Add middleware for authentication
|
||||||
- [ ] Add user profile and settings (i.e. language)
|
- [ ] Add user profile and settings (i.e. language)
|
||||||
- [ ] Add user roles
|
- [ ] Add user roles
|
||||||
|
|||||||
53
app/api/protected/customer-form/route.ts
Normal file
53
app/api/protected/customer-form/route.ts
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import { getSession, withApiAuthRequired } from '@auth0/nextjs-auth0';
|
||||||
|
import prisma from '@prisma/prisma';
|
||||||
|
import { randomUUID } from 'crypto';
|
||||||
|
import { NextResponse } from 'next/server';
|
||||||
|
|
||||||
|
export const GET = withApiAuthRequired(async () => {
|
||||||
|
const session = await getSession();
|
||||||
|
|
||||||
|
console.log('GET', session?.user);
|
||||||
|
|
||||||
|
// const userModules = await prisma.user.findUniqueOrThrow({
|
||||||
|
// where: {
|
||||||
|
// email: session?.user.email
|
||||||
|
// },
|
||||||
|
// include: {
|
||||||
|
// CustomerForm: true
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const customerForms: CustomerForm[] = userModules.CustomerForm;
|
||||||
|
|
||||||
|
return NextResponse.json([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
export const POST = withApiAuthRequired(async request => {
|
||||||
|
try {
|
||||||
|
const session = await getSession();
|
||||||
|
|
||||||
|
const body = await request.json();
|
||||||
|
|
||||||
|
console.log('POST', session?.user);
|
||||||
|
|
||||||
|
const newCustomerForm = await prisma.customerForm.create({
|
||||||
|
data: {
|
||||||
|
type: body.type,
|
||||||
|
text: body.text,
|
||||||
|
createdBy: {
|
||||||
|
connect: {
|
||||||
|
id: randomUUID(),
|
||||||
|
email: session?.user.email
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return NextResponse.json({ success: true, data: newCustomerForm });
|
||||||
|
} catch (error) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ success: false, message: 'Something went wrong.' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { NextRequest, NextResponse } from 'next/server';
|
|
||||||
|
|
||||||
export async function GET(request: NextRequest, response: NextResponse) {
|
|
||||||
return NextResponse.json('GET request');
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function POST(request: NextRequest, response: NextResponse) {
|
|
||||||
return NextResponse.json('POST request');
|
|
||||||
}
|
|
||||||
9
app/costumer-form/[id]/page.tsx
Normal file
9
app/costumer-form/[id]/page.tsx
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
export default function SingleCustomerForm({
|
||||||
|
params
|
||||||
|
}: {
|
||||||
|
params: { id: string };
|
||||||
|
}) {
|
||||||
|
return <div>Module {params.id}</div>;
|
||||||
|
}
|
||||||
106
app/costumer-form/page.tsx
Normal file
106
app/costumer-form/page.tsx
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Button } from '@components/Button';
|
||||||
|
import { FormControl } from '@components/FormControl';
|
||||||
|
import { FormMessage } from '@components/FormMessage';
|
||||||
|
import { Input } from '@components/Input';
|
||||||
|
import { FormField } from '@contexts/FormField/FormFieldProvider';
|
||||||
|
import { FormItem } from '@contexts/FormItem/FormItemProvider';
|
||||||
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
|
import { CustomerFormType } from '@prisma/client';
|
||||||
|
import {
|
||||||
|
CustomerForm,
|
||||||
|
CustomerFormListSchema,
|
||||||
|
CustomerFormSchema
|
||||||
|
} from '@utils/types';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { FormProvider, useForm } from 'react-hook-form';
|
||||||
|
|
||||||
|
export default function Modules() {
|
||||||
|
const [modules, setModules] = useState<CustomerForm[]>([]);
|
||||||
|
|
||||||
|
const form = useForm<CustomerForm>({
|
||||||
|
resolver: zodResolver(CustomerFormSchema),
|
||||||
|
defaultValues: {
|
||||||
|
type: CustomerFormType.TYPE1,
|
||||||
|
text: ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
const response = await axios.get('/api/protected/customer-form');
|
||||||
|
|
||||||
|
const validatedResponse = CustomerFormListSchema.safeParse(response.data);
|
||||||
|
|
||||||
|
if (!validatedResponse.success) {
|
||||||
|
console.error(validatedResponse.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setModules(validatedResponse.data);
|
||||||
|
})();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
async function handleSubmit(values: CustomerForm) {
|
||||||
|
console.log('values', values);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios.post(
|
||||||
|
'/api/protected/customer-form',
|
||||||
|
{
|
||||||
|
type: CustomerFormType.TYPE1,
|
||||||
|
text: values.text
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const validatedResponse = CustomerFormSchema.safeParse(response.data);
|
||||||
|
|
||||||
|
if (!validatedResponse.success) {
|
||||||
|
console.error(validatedResponse.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setModules([...modules, validatedResponse.data]);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1>Modules</h1>
|
||||||
|
{modules &&
|
||||||
|
modules.map(module => (
|
||||||
|
<div key={module.id}>
|
||||||
|
<h2>{module.type}</h2>
|
||||||
|
<p>{module.text}</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<h1>Create Module</h1>
|
||||||
|
<FormProvider {...form}>
|
||||||
|
<form onSubmit={form.handleSubmit(handleSubmit)}>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name='text'
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormMessage />
|
||||||
|
<FormControl>
|
||||||
|
<Input placeholder='name' {...field} />
|
||||||
|
</FormControl>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Button type='submit'>Submit</Button>
|
||||||
|
</form>
|
||||||
|
</FormProvider>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export default function SpecificModule({ params }: { params: { id: string } }) {
|
|
||||||
return <div>Module {params.id}</div>;
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export default function Module() {
|
|
||||||
return <div>Modules home</div>;
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { withPageAuthRequired } from '@auth0/nextjs-auth0/client';
|
import { withPageAuthRequired } from '@auth0/nextjs-auth0/client';
|
||||||
|
import axios from 'axios';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
export default withPageAuthRequired(function Profile() {
|
export default withPageAuthRequired(function Profile() {
|
||||||
@@ -8,18 +9,16 @@ export default withPageAuthRequired(function Profile() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const res = await fetch(
|
const response = await axios.get('/api/protected/profile');
|
||||||
`${window.location.origin}/api/protected/profile`
|
|
||||||
);
|
setUser(response.data);
|
||||||
setUser(await res.json());
|
|
||||||
})();
|
})();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main>
|
<>
|
||||||
<h1>Profile (fetched from API)</h1>
|
<h1>Profile (fetched from API)</h1>
|
||||||
<h3>User</h3>
|
{JSON.stringify(user, null, 2)}
|
||||||
<pre data-testid='module'>{JSON.stringify(user, null, 2)}</pre>
|
</>
|
||||||
</main>
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
19
components/Button.tsx
Normal file
19
components/Button.tsx
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { Slot } from '@radix-ui/react-slot';
|
||||||
|
import { cn } from '@utils/cn';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
export type ButtonProps = {
|
||||||
|
asChild?: boolean;
|
||||||
|
} & React.ButtonHTMLAttributes<HTMLButtonElement>;
|
||||||
|
|
||||||
|
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||||
|
({ asChild = false, ...props }, ref) => {
|
||||||
|
const Comp = asChild ? Slot : 'button';
|
||||||
|
return (
|
||||||
|
<Comp className={cn('btn-grad', 'btn-grad-hover')} ref={ref} {...props} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
Button.displayName = 'Button';
|
||||||
|
|
||||||
|
export { Button };
|
||||||
26
components/FormControl.tsx
Normal file
26
components/FormControl.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { useFormField } from '@hooks/useFormField';
|
||||||
|
import { Slot } from '@radix-ui/react-slot';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
export const FormControl = React.forwardRef<
|
||||||
|
React.ElementRef<typeof Slot>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof Slot>
|
||||||
|
>(({ ...props }, ref) => {
|
||||||
|
const { error, formItemId, formDescriptionId, formMessageId } =
|
||||||
|
useFormField();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Slot
|
||||||
|
ref={ref}
|
||||||
|
id={formItemId}
|
||||||
|
aria-describedby={
|
||||||
|
!error
|
||||||
|
? `${formDescriptionId}`
|
||||||
|
: `${formDescriptionId} ${formMessageId}`
|
||||||
|
}
|
||||||
|
aria-invalid={!!error}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
FormControl.displayName = 'FormControl';
|
||||||
28
components/FormMessage.tsx
Normal file
28
components/FormMessage.tsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { useFormField } from '@hooks/useFormField';
|
||||||
|
import { cn } from '@utils/cn';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
export const FormMessage = React.forwardRef<
|
||||||
|
HTMLParagraphElement,
|
||||||
|
React.HTMLAttributes<HTMLParagraphElement>
|
||||||
|
>(({ className, children, ...props }, ref) => {
|
||||||
|
const { error, formMessageId } = useFormField();
|
||||||
|
const body = error ? String(error?.message) : children;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{!body ? null : (
|
||||||
|
<p
|
||||||
|
ref={ref}
|
||||||
|
id={formMessageId}
|
||||||
|
className={cn('text-destructive text-sm font-medium', className)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{body}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
FormMessage.displayName = 'FormMessage';
|
||||||
22
components/Input.tsx
Normal file
22
components/Input.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { cn } from '@utils/cn';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
const Input = React.forwardRef<
|
||||||
|
HTMLInputElement,
|
||||||
|
React.InputHTMLAttributes<HTMLInputElement>
|
||||||
|
>(({ className, type, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<input
|
||||||
|
type={type}
|
||||||
|
className={cn(
|
||||||
|
'border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
ref={ref}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
Input.displayName = 'Input';
|
||||||
|
|
||||||
|
export { Input };
|
||||||
13
contexts/FormField/FormFieldContext.ts
Normal file
13
contexts/FormField/FormFieldContext.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { FieldPath, FieldValues } from 'react-hook-form';
|
||||||
|
|
||||||
|
interface FormFieldContextValue<
|
||||||
|
TFieldValues extends FieldValues = FieldValues,
|
||||||
|
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
|
||||||
|
> {
|
||||||
|
name: TName;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FormFieldContext = React.createContext<FormFieldContextValue>(
|
||||||
|
{} as FormFieldContextValue
|
||||||
|
);
|
||||||
20
contexts/FormField/FormFieldProvider.tsx
Normal file
20
contexts/FormField/FormFieldProvider.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import {
|
||||||
|
Controller,
|
||||||
|
ControllerProps,
|
||||||
|
FieldPath,
|
||||||
|
FieldValues
|
||||||
|
} from 'react-hook-form';
|
||||||
|
import { FormFieldContext } from './FormFieldContext';
|
||||||
|
|
||||||
|
export const FormField = <
|
||||||
|
TFieldValues extends FieldValues = FieldValues,
|
||||||
|
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
|
||||||
|
>({
|
||||||
|
...props
|
||||||
|
}: ControllerProps<TFieldValues, TName>) => {
|
||||||
|
return (
|
||||||
|
<FormFieldContext.Provider value={{ name: props.name }}>
|
||||||
|
<Controller {...props} />
|
||||||
|
</FormFieldContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
9
contexts/FormItem/FormItemContext.ts
Normal file
9
contexts/FormItem/FormItemContext.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
interface FormItemContextValue {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FormItemContext = React.createContext<FormItemContextValue>(
|
||||||
|
{} as FormItemContextValue
|
||||||
|
);
|
||||||
18
contexts/FormItem/FormItemProvider.tsx
Normal file
18
contexts/FormItem/FormItemProvider.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { cn } from '@utils/cn';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { FormItemContext } from './FormItemContext';
|
||||||
|
|
||||||
|
export const FormItem = React.forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
React.HTMLAttributes<HTMLDivElement>
|
||||||
|
>(({ className, ...props }, ref) => {
|
||||||
|
const id = React.useId();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormItemContext.Provider value={{ id }}>
|
||||||
|
<div ref={ref} className={cn('space-y-2', className)} {...props} />
|
||||||
|
</FormItemContext.Provider>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
FormItem.displayName = 'FormItem';
|
||||||
29
hooks/useFormField.tsx
Normal file
29
hooks/useFormField.tsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { FormFieldContext } from '@contexts/FormField/FormFieldContext';
|
||||||
|
import { FormItemContext } from '@contexts/FormItem/FormItemContext';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { useFormContext } from 'react-hook-form';
|
||||||
|
|
||||||
|
const useFormField = () => {
|
||||||
|
const fieldContext = React.useContext(FormFieldContext);
|
||||||
|
const itemContext = React.useContext(FormItemContext);
|
||||||
|
const { getFieldState, formState } = useFormContext();
|
||||||
|
|
||||||
|
const fieldState = getFieldState(fieldContext.name, formState);
|
||||||
|
|
||||||
|
if (!fieldContext) {
|
||||||
|
throw new Error('useFormField should be used within <FormField>');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { id } = itemContext;
|
||||||
|
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
name: fieldContext.name,
|
||||||
|
formItemId: `${id}-form-item`,
|
||||||
|
formDescriptionId: `${id}-form-item-description`,
|
||||||
|
formMessageId: `${id}-form-item-message`,
|
||||||
|
...fieldState
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export { useFormField };
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { withMiddlewareAuthRequired } from '@auth0/nextjs-auth0/edge';
|
|
||||||
|
|
||||||
export default withMiddlewareAuthRequired();
|
|
||||||
|
|
||||||
export const config = {
|
|
||||||
matcher: ['/api/protected/:path*', '/module/:path*', '/user']
|
|
||||||
};
|
|
||||||
@@ -19,15 +19,20 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@auth0/nextjs-auth0": "^3.5.0",
|
"@auth0/nextjs-auth0": "^3.5.0",
|
||||||
|
"@hookform/resolvers": "^3.6.0",
|
||||||
"@prisma/client": "^5.6.0",
|
"@prisma/client": "^5.6.0",
|
||||||
|
"@radix-ui/react-slot": "^1.1.0",
|
||||||
"@vercel/analytics": "^1.1.1",
|
"@vercel/analytics": "^1.1.1",
|
||||||
|
"axios": "^1.7.2",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
"next": "^14.1.0",
|
"next": "^14.1.0",
|
||||||
"postcss-nesting": "^12.0.2",
|
"postcss-nesting": "^12.0.2",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
"react-hook-form": "^7.48.2",
|
"react-hook-form": "^7.52.0",
|
||||||
"resend": "^3.1.0",
|
"resend": "^3.1.0",
|
||||||
"zod": "^3.22.4"
|
"tailwind-merge": "^2.3.0",
|
||||||
|
"zod": "^3.23.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^18.4.3",
|
"@commitlint/cli": "^18.4.3",
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- You are about to drop the `Module` table. If the table is not empty, all the data it contains will be lost.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "CustomerFormType" AS ENUM ('TYPE1', 'TYPE2', 'TYPE3');
|
||||||
|
|
||||||
|
-- DropForeignKey
|
||||||
|
ALTER TABLE "Module" DROP CONSTRAINT "Module_createdById_fkey";
|
||||||
|
|
||||||
|
-- DropTable
|
||||||
|
DROP TABLE "Module";
|
||||||
|
|
||||||
|
-- DropEnum
|
||||||
|
DROP TYPE "ModuleType";
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "CustomerForm" (
|
||||||
|
"id" DOUBLE PRECISION NOT NULL,
|
||||||
|
"type" "CustomerFormType" NOT NULL,
|
||||||
|
"text" TEXT NOT NULL,
|
||||||
|
"deleted" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"createdById" TEXT NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "CustomerForm_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "CustomerForm_id_key" ON "CustomerForm"("id");
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "CustomerForm" ADD CONSTRAINT "CustomerForm_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- The primary key for the `CustomerForm` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- DropIndex
|
||||||
|
DROP INDEX "CustomerForm_id_key";
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "CustomerForm" DROP CONSTRAINT "CustomerForm_pkey",
|
||||||
|
ALTER COLUMN "id" SET DATA TYPE TEXT,
|
||||||
|
ADD CONSTRAINT "CustomerForm_pkey" PRIMARY KEY ("id");
|
||||||
@@ -8,29 +8,29 @@ datasource db {
|
|||||||
directUrl = env("DATABASE_URL_NON_POOLING") // uses a direct connection
|
directUrl = env("DATABASE_URL_NON_POOLING") // uses a direct connection
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ModuleType {
|
enum CustomerFormType {
|
||||||
TYPE1
|
TYPE1
|
||||||
TYPE2
|
TYPE2
|
||||||
TYPE3
|
TYPE3
|
||||||
}
|
}
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
name String?
|
name String?
|
||||||
email String @unique
|
email String @unique
|
||||||
deleted Boolean @default(false)
|
deleted Boolean @default(false)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
Module Module[]
|
CustomerForm CustomerForm[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model Module {
|
model CustomerForm {
|
||||||
id Float @id @unique
|
id String @id @default(cuid())
|
||||||
type ModuleType
|
type CustomerFormType
|
||||||
text String
|
text String
|
||||||
deleted Boolean @default(false)
|
deleted Boolean @default(false)
|
||||||
createdById String
|
createdById String
|
||||||
createdBy User @relation(fields: [createdById], references: [id])
|
createdBy User @relation(fields: [createdById], references: [id])
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,11 @@
|
|||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@app/*": ["./app/*"],
|
"@app/*": ["./app/*"],
|
||||||
"@prisma/*": ["./prisma/*"]
|
"@prisma/*": ["./prisma/*"],
|
||||||
|
"@utils/*": ["./utils/*"],
|
||||||
|
"@contexts/*": ["./contexts/*"],
|
||||||
|
"@components/*": ["./components/*"],
|
||||||
|
"@hooks/*": ["./hooks/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
|
|||||||
6
utils/cn.ts
Normal file
6
utils/cn.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { type ClassValue, clsx } from 'clsx';
|
||||||
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
return twMerge(clsx(inputs));
|
||||||
|
}
|
||||||
24
utils/types.ts
Normal file
24
utils/types.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
export const UserSchema = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
name: z.string(),
|
||||||
|
email: z.string().email(),
|
||||||
|
deleted: z.boolean(),
|
||||||
|
createdAt: z.date().transform(date => date.toISOString()),
|
||||||
|
updatedAt: z.date().transform(date => date.toISOString())
|
||||||
|
});
|
||||||
|
|
||||||
|
export type User = z.infer<typeof UserSchema>;
|
||||||
|
|
||||||
|
export const CustomerFormSchema = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
type: z.string(),
|
||||||
|
text: z.string(),
|
||||||
|
createdAt: z.date().transform(date => date.toISOString()),
|
||||||
|
updatedAt: z.date().transform(date => date.toISOString())
|
||||||
|
});
|
||||||
|
|
||||||
|
export const CustomerFormListSchema = z.array(CustomerFormSchema);
|
||||||
|
|
||||||
|
export type CustomerForm = z.infer<typeof CustomerFormSchema>;
|
||||||
160
yarn.lock
160
yarn.lock
@@ -60,6 +60,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@babel/runtime@npm:^7.24.1":
|
||||||
|
version: 7.24.7
|
||||||
|
resolution: "@babel/runtime@npm:7.24.7"
|
||||||
|
dependencies:
|
||||||
|
regenerator-runtime: "npm:^0.14.0"
|
||||||
|
checksum: 7b77f566165dee62db3db0296e71d08cafda3f34e1b0dcefcd68427272e17c1704f4e4369bff76651b07b6e49d3ea5a0ce344818af9116e9292e4381e0918c76
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@commitlint/cli@npm:^18.4.3":
|
"@commitlint/cli@npm:^18.4.3":
|
||||||
version: 18.6.1
|
version: 18.6.1
|
||||||
resolution: "@commitlint/cli@npm:18.6.1"
|
resolution: "@commitlint/cli@npm:18.6.1"
|
||||||
@@ -330,6 +339,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@hookform/resolvers@npm:^3.6.0":
|
||||||
|
version: 3.6.0
|
||||||
|
resolution: "@hookform/resolvers@npm:3.6.0"
|
||||||
|
peerDependencies:
|
||||||
|
react-hook-form: ^7.0.0
|
||||||
|
checksum: 6dd1b7ad21ed2b171470740884e0b83982c79a0d4ceddabe60b616e53eeed2b5569cdba5e91ad844e379aeda5ffa835b0c2d2525d702fcd8b263c2194895f9b7
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@humanwhocodes/config-array@npm:^0.11.14":
|
"@humanwhocodes/config-array@npm:^0.11.14":
|
||||||
version: 0.11.14
|
version: 0.11.14
|
||||||
resolution: "@humanwhocodes/config-array@npm:0.11.14"
|
resolution: "@humanwhocodes/config-array@npm:0.11.14"
|
||||||
@@ -618,6 +636,34 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@radix-ui/react-compose-refs@npm:1.1.0":
|
||||||
|
version: 1.1.0
|
||||||
|
resolution: "@radix-ui/react-compose-refs@npm:1.1.0"
|
||||||
|
peerDependencies:
|
||||||
|
"@types/react": "*"
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
"@types/react":
|
||||||
|
optional: true
|
||||||
|
checksum: 047a4ed5f87cb848be475507cd62836cf5af5761484681f521ea543ea7c9d59d61d42806d6208863d5e2380bf38cdf4cff73c2bbe5f52dbbe50fb04e1a13ac72
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@radix-ui/react-slot@npm:^1.1.0":
|
||||||
|
version: 1.1.0
|
||||||
|
resolution: "@radix-ui/react-slot@npm:1.1.0"
|
||||||
|
dependencies:
|
||||||
|
"@radix-ui/react-compose-refs": "npm:1.1.0"
|
||||||
|
peerDependencies:
|
||||||
|
"@types/react": "*"
|
||||||
|
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||||
|
peerDependenciesMeta:
|
||||||
|
"@types/react":
|
||||||
|
optional: true
|
||||||
|
checksum: 95e190868418b1c83adf6627256f6b664b0dcbea95d7215de9c64ac2c31102fc09155565d9ca27be6abd20fc63d0b0bacfe1b67d78b2de1d198244c848e1a54e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@react-email/render@npm:0.0.15":
|
"@react-email/render@npm:0.0.15":
|
||||||
version: 0.0.15
|
version: 0.0.15
|
||||||
resolution: "@react-email/render@npm:0.0.15"
|
resolution: "@react-email/render@npm:0.0.15"
|
||||||
@@ -1216,6 +1262,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"asynckit@npm:^0.4.0":
|
||||||
|
version: 0.4.0
|
||||||
|
resolution: "asynckit@npm:0.4.0"
|
||||||
|
checksum: 3ce727cbc78f69d6a4722517a58ee926c8c21083633b1d3fdf66fd688f6c127a53a592141bd4866f9b63240a86e9d8e974b13919450bd17fa33c2d22c4558ad8
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"audit-ci@npm:^6.6.1":
|
"audit-ci@npm:^6.6.1":
|
||||||
version: 6.6.1
|
version: 6.6.1
|
||||||
resolution: "audit-ci@npm:6.6.1"
|
resolution: "audit-ci@npm:6.6.1"
|
||||||
@@ -1268,6 +1321,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"axios@npm:^1.7.2":
|
||||||
|
version: 1.7.2
|
||||||
|
resolution: "axios@npm:1.7.2"
|
||||||
|
dependencies:
|
||||||
|
follow-redirects: "npm:^1.15.6"
|
||||||
|
form-data: "npm:^4.0.0"
|
||||||
|
proxy-from-env: "npm:^1.1.0"
|
||||||
|
checksum: 6ae80dda9736bb4762ce717f1a26ff997d94672d3a5799ad9941c24d4fb019c1dff45be8272f08d1975d7950bac281f3ba24aff5ecd49ef5a04d872ec428782f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"axobject-query@npm:~3.1.1":
|
"axobject-query@npm:~3.1.1":
|
||||||
version: 3.1.1
|
version: 3.1.1
|
||||||
resolution: "axobject-query@npm:3.1.1"
|
resolution: "axobject-query@npm:3.1.1"
|
||||||
@@ -1512,6 +1576,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"clsx@npm:^2.1.1":
|
||||||
|
version: 2.1.1
|
||||||
|
resolution: "clsx@npm:2.1.1"
|
||||||
|
checksum: cdfb57fa6c7649bbff98d9028c2f0de2f91c86f551179541cf784b1cfdc1562dcb951955f46d54d930a3879931a980e32a46b598acaea274728dbe068deca919
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"color-convert@npm:^1.9.0":
|
"color-convert@npm:^1.9.0":
|
||||||
version: 1.9.3
|
version: 1.9.3
|
||||||
resolution: "color-convert@npm:1.9.3"
|
resolution: "color-convert@npm:1.9.3"
|
||||||
@@ -1551,6 +1622,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"combined-stream@npm:^1.0.8":
|
||||||
|
version: 1.0.8
|
||||||
|
resolution: "combined-stream@npm:1.0.8"
|
||||||
|
dependencies:
|
||||||
|
delayed-stream: "npm:~1.0.0"
|
||||||
|
checksum: 2e969e637d05d09fa50b02d74c83a1186f6914aae89e6653b62595cc75a221464f884f55f231b8f4df7a49537fba60bdc0427acd2bf324c09a1dbb84837e36e4
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"commander@npm:^10.0.0":
|
"commander@npm:^10.0.0":
|
||||||
version: 10.0.1
|
version: 10.0.1
|
||||||
resolution: "commander@npm:10.0.1"
|
resolution: "commander@npm:10.0.1"
|
||||||
@@ -1842,6 +1922,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"delayed-stream@npm:~1.0.0":
|
||||||
|
version: 1.0.0
|
||||||
|
resolution: "delayed-stream@npm:1.0.0"
|
||||||
|
checksum: 46fe6e83e2cb1d85ba50bd52803c68be9bd953282fa7096f51fc29edd5d67ff84ff753c51966061e5ba7cb5e47ef6d36a91924eddb7f3f3483b1c560f77a0020
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"didyoumean@npm:^1.2.2":
|
"didyoumean@npm:^1.2.2":
|
||||||
version: 1.2.2
|
version: 1.2.2
|
||||||
resolution: "didyoumean@npm:1.2.2"
|
resolution: "didyoumean@npm:1.2.2"
|
||||||
@@ -2647,6 +2734,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"follow-redirects@npm:^1.15.6":
|
||||||
|
version: 1.15.6
|
||||||
|
resolution: "follow-redirects@npm:1.15.6"
|
||||||
|
peerDependenciesMeta:
|
||||||
|
debug:
|
||||||
|
optional: true
|
||||||
|
checksum: 70c7612c4cab18e546e36b991bbf8009a1a41cf85354afe04b113d1117569abf760269409cb3eb842d9f7b03d62826687086b081c566ea7b1e6613cf29030bf7
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"for-each@npm:^0.3.3":
|
"for-each@npm:^0.3.3":
|
||||||
version: 0.3.3
|
version: 0.3.3
|
||||||
resolution: "for-each@npm:0.3.3"
|
resolution: "for-each@npm:0.3.3"
|
||||||
@@ -2666,6 +2763,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"form-data@npm:^4.0.0":
|
||||||
|
version: 4.0.0
|
||||||
|
resolution: "form-data@npm:4.0.0"
|
||||||
|
dependencies:
|
||||||
|
asynckit: "npm:^0.4.0"
|
||||||
|
combined-stream: "npm:^1.0.8"
|
||||||
|
mime-types: "npm:^2.1.12"
|
||||||
|
checksum: 7264aa760a8cf09482816d8300f1b6e2423de1b02bba612a136857413fdc96d7178298ced106817655facc6b89036c6e12ae31c9eb5bdc16aabf502ae8a5d805
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"fraction.js@npm:^4.3.7":
|
"fraction.js@npm:^4.3.7":
|
||||||
version: 4.3.7
|
version: 4.3.7
|
||||||
resolution: "fraction.js@npm:4.3.7"
|
resolution: "fraction.js@npm:4.3.7"
|
||||||
@@ -4039,6 +4147,22 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"mime-db@npm:1.52.0":
|
||||||
|
version: 1.52.0
|
||||||
|
resolution: "mime-db@npm:1.52.0"
|
||||||
|
checksum: 54bb60bf39e6f8689f6622784e668a3d7f8bed6b0d886f5c3c446cb3284be28b30bf707ed05d0fe44a036f8469976b2629bbea182684977b084de9da274694d7
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"mime-types@npm:^2.1.12":
|
||||||
|
version: 2.1.35
|
||||||
|
resolution: "mime-types@npm:2.1.35"
|
||||||
|
dependencies:
|
||||||
|
mime-db: "npm:1.52.0"
|
||||||
|
checksum: 89aa9651b67644035de2784a6e665fc685d79aba61857e02b9c8758da874a754aed4a9aced9265f5ed1171fd934331e5516b84a7f0218031b6fa0270eca1e51a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"mimic-fn@npm:^2.1.0":
|
"mimic-fn@npm:^2.1.0":
|
||||||
version: 2.1.0
|
version: 2.1.0
|
||||||
resolution: "mimic-fn@npm:2.1.0"
|
resolution: "mimic-fn@npm:2.1.0"
|
||||||
@@ -5011,6 +5135,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"proxy-from-env@npm:^1.1.0":
|
||||||
|
version: 1.1.0
|
||||||
|
resolution: "proxy-from-env@npm:1.1.0"
|
||||||
|
checksum: f0bb4a87cfd18f77bc2fba23ae49c3b378fb35143af16cc478171c623eebe181678f09439707ad80081d340d1593cd54a33a0113f3ccb3f4bc9451488780ee23
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"punycode@npm:^2.1.0":
|
"punycode@npm:^2.1.0":
|
||||||
version: 2.3.1
|
version: 2.3.1
|
||||||
resolution: "punycode@npm:2.3.1"
|
resolution: "punycode@npm:2.3.1"
|
||||||
@@ -5044,7 +5175,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"react-hook-form@npm:^7.48.2":
|
"react-hook-form@npm:^7.52.0":
|
||||||
version: 7.52.0
|
version: 7.52.0
|
||||||
resolution: "react-hook-form@npm:7.52.0"
|
resolution: "react-hook-form@npm:7.52.0"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -5162,6 +5293,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"regenerator-runtime@npm:^0.14.0":
|
||||||
|
version: 0.14.1
|
||||||
|
resolution: "regenerator-runtime@npm:0.14.1"
|
||||||
|
checksum: 5db3161abb311eef8c45bcf6565f4f378f785900ed3945acf740a9888c792f75b98ecb77f0775f3bf95502ff423529d23e94f41d80c8256e8fa05ed4b07cf471
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2":
|
"regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2":
|
||||||
version: 1.5.2
|
version: 1.5.2
|
||||||
resolution: "regexp.prototype.flags@npm:1.5.2"
|
resolution: "regexp.prototype.flags@npm:1.5.2"
|
||||||
@@ -5888,6 +6026,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"tailwind-merge@npm:^2.3.0":
|
||||||
|
version: 2.3.0
|
||||||
|
resolution: "tailwind-merge@npm:2.3.0"
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime": "npm:^7.24.1"
|
||||||
|
checksum: cf3b126bee82bc9ff3f60f9601b66925418db6906544198b637487b25fba1c9c307734ca37ccb8fa2355f69ad0c5aff34c5dce460809addb459a93205d9a0abe
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"tailwindcss@npm:^3.4.1":
|
"tailwindcss@npm:^3.4.1":
|
||||||
version: 3.4.4
|
version: 3.4.4
|
||||||
resolution: "tailwindcss@npm:3.4.4"
|
resolution: "tailwindcss@npm:3.4.4"
|
||||||
@@ -6241,7 +6388,9 @@ __metadata:
|
|||||||
"@auth0/nextjs-auth0": "npm:^3.5.0"
|
"@auth0/nextjs-auth0": "npm:^3.5.0"
|
||||||
"@commitlint/cli": "npm:^18.4.3"
|
"@commitlint/cli": "npm:^18.4.3"
|
||||||
"@commitlint/config-conventional": "npm:^18.4.3"
|
"@commitlint/config-conventional": "npm:^18.4.3"
|
||||||
|
"@hookform/resolvers": "npm:^3.6.0"
|
||||||
"@prisma/client": "npm:^5.6.0"
|
"@prisma/client": "npm:^5.6.0"
|
||||||
|
"@radix-ui/react-slot": "npm:^1.1.0"
|
||||||
"@types/node": "npm:^20"
|
"@types/node": "npm:^20"
|
||||||
"@types/react": "npm:^18"
|
"@types/react": "npm:^18"
|
||||||
"@types/react-dom": "npm:^18"
|
"@types/react-dom": "npm:^18"
|
||||||
@@ -6250,6 +6399,8 @@ __metadata:
|
|||||||
"@vercel/analytics": "npm:^1.1.1"
|
"@vercel/analytics": "npm:^1.1.1"
|
||||||
audit-ci: "npm:^6.6.1"
|
audit-ci: "npm:^6.6.1"
|
||||||
autoprefixer: "npm:^10.0.1"
|
autoprefixer: "npm:^10.0.1"
|
||||||
|
axios: "npm:^1.7.2"
|
||||||
|
clsx: "npm:^2.1.1"
|
||||||
eslint: "npm:^8"
|
eslint: "npm:^8"
|
||||||
eslint-config-next: "npm:14.0.3"
|
eslint-config-next: "npm:14.0.3"
|
||||||
eslint-config-prettier: "npm:^9.0.0"
|
eslint-config-prettier: "npm:^9.0.0"
|
||||||
@@ -6263,11 +6414,12 @@ __metadata:
|
|||||||
prisma: "npm:^5.6.0"
|
prisma: "npm:^5.6.0"
|
||||||
react: "npm:^18"
|
react: "npm:^18"
|
||||||
react-dom: "npm:^18"
|
react-dom: "npm:^18"
|
||||||
react-hook-form: "npm:^7.48.2"
|
react-hook-form: "npm:^7.52.0"
|
||||||
resend: "npm:^3.1.0"
|
resend: "npm:^3.1.0"
|
||||||
|
tailwind-merge: "npm:^2.3.0"
|
||||||
tailwindcss: "npm:^3.4.1"
|
tailwindcss: "npm:^3.4.1"
|
||||||
typescript: "npm:^5"
|
typescript: "npm:^5"
|
||||||
zod: "npm:^3.22.4"
|
zod: "npm:^3.23.8"
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
@@ -6457,7 +6609,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"zod@npm:^3.22.4":
|
"zod@npm:^3.23.8":
|
||||||
version: 3.23.8
|
version: 3.23.8
|
||||||
resolution: "zod@npm:3.23.8"
|
resolution: "zod@npm:3.23.8"
|
||||||
checksum: 846fd73e1af0def79c19d510ea9e4a795544a67d5b34b7e1c4d0425bf6bfd1c719446d94cdfa1721c1987d891321d61f779e8236fde517dc0e524aa851a6eff1
|
checksum: 846fd73e1af0def79c19d510ea9e4a795544a67d5b34b7e1c4d0425bf6bfd1c719446d94cdfa1721c1987d891321d61f779e8236fde517dc0e524aa851a6eff1
|
||||||
|
|||||||
Reference in New Issue
Block a user