├── .devcontainer ├── Dockerfile └── devcontainer.json ├── .editorconfig ├── .env.example ├── .gitignore ├── .prettierrc ├── .vscode └── settings.json ├── README.md ├── apps └── web │ ├── next-env.d.ts │ ├── next.config.mjs │ ├── package.json │ ├── postcss.config.cjs │ ├── prisma │ └── schema.prisma │ ├── src │ ├── app │ │ └── logout │ │ │ └── route.ts │ ├── components │ │ ├── LoginForm.tsx │ │ ├── email-templates │ │ │ └── login-code.tsx │ │ └── ui │ │ │ ├── Button.tsx │ │ │ ├── Control.tsx │ │ │ ├── Input.tsx │ │ │ └── Spinner.tsx │ ├── css │ │ ├── spinner.css │ │ └── tailwind.css │ ├── lib │ │ ├── cn.ts │ │ ├── config.ts │ │ ├── current-user.ts │ │ ├── toast.ts │ │ ├── trpc.ts │ │ └── utils.ts │ ├── pages │ │ ├── _app.tsx │ │ ├── _document.tsx │ │ ├── api │ │ │ └── trpc │ │ │ │ └── [trpc].ts │ │ └── index.tsx │ └── server │ │ ├── auth.ts │ │ ├── email.ts │ │ ├── env.ts │ │ ├── gate.ts │ │ ├── prisma.ts │ │ ├── singleton.ts │ │ └── trpc │ │ ├── auth.router.ts │ │ ├── context.ts │ │ ├── index.ts │ │ ├── t.ts │ │ └── user.router.ts │ ├── tailwind.config.cjs │ ├── tsconfig.json │ └── types.d.ts ├── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml └── renovate.json /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.222.0/containers/javascript-node/.devcontainer/base.Dockerfile 2 | 3 | # [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 16, 14, 12, 16-bullseye, 14-bullseye, 12-bullseye, 16-buster, 14-buster, 12-buster 4 | ARG VARIANT="16-bullseye" 5 | FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT} 6 | 7 | # [Optional] Uncomment this section to install additional OS packages. 8 | # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 9 | # && apt-get -y install --no-install-recommends 10 | 11 | # [Optional] Uncomment if you want to install an additional version of node using nvm 12 | # ARG EXTRA_NODE_VERSION=10 13 | # RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}" 14 | 15 | # [Optional] Uncomment if you want to install more global node modules 16 | RUN su node -c "npm install -g pnpm" 17 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: 2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.222.0/containers/javascript-node 3 | { 4 | "name": "Node.js", 5 | "build": { 6 | "dockerfile": "Dockerfile", 7 | // Update 'VARIANT' to pick a Node version: 16, 14, 12. 8 | // Append -bullseye or -buster to pin to an OS version. 9 | // Use -bullseye variants on local arm64/Apple Silicon. 10 | "args": { "VARIANT": "16-bullseye" } 11 | }, 12 | 13 | // Set *default* container specific settings.json values on container create. 14 | "settings": {}, 15 | 16 | // Add the IDs of extensions you want installed when the container is created. 17 | "extensions": ["dbaeumer.vscode-eslint"], 18 | 19 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 20 | // "forwardPorts": [], 21 | 22 | // Use 'postCreateCommand' to run commands after the container is created. 23 | "postCreateCommand": "pnpm install", 24 | 25 | // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. 26 | "remoteUser": "node" 27 | } 28 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = false 8 | insert_final_newline = true 9 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | DATABASE_URL="postgresql://postgres:password@localhost:5432/mydb?schema=public" 2 | 3 | AUTH_COOKIE_NAME=app.session-token 4 | # Optional 5 | AUTH_COOKIE_DOMAIN= 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .DS_Store 4 | .next 5 | out/ 6 | .env 7 | server-dist/ 8 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | "@egoist/prettier-config" -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.watcherExclude": { 3 | "**/.git/objects/**": true, 4 | "**/.git/subtree-cache/**": true, 5 | "**/.hg/store/**": true 6 | }, 7 | "prisma.plugin.nextjs.addTypesOnSave": true, 8 | "prisma.plugin.nextjs.hasPrompted": true 9 | } 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Next FullStack Starter 2 | 3 | Next.js + Prisma + TailwindCSS + TRPC 4 | 5 | This project serves as the starting point of some of my SaaS products, so I'm continuously improving it. 6 | 7 | ## Features 8 | 9 | - Query database with [Prisma](https://prisma.io) 10 | - [Fullstack development with TRPC](https://trpc.io/) 11 | - [TailwindCSS](https://tailwindcss.com) 12 | - Login by sending code to email 13 | - More to come.. 14 | 15 | ## Documentation 16 | 17 | ### Prerequisites 18 | 19 | Moving `.env.example` to `.env`. 20 | 21 | Use [direnv](https://direnv.net/) to automatically load environment variables. 22 | 23 | Then get your database ready, install PostgreSQL and make sure you have a user and database matching the default one we use: 24 | 25 | ``` 26 | DATABASE_URL="postgresql://postgres:password@localhost:5432/mydb?schema=public" 27 | ``` 28 | 29 | You can also customize it by updating `.env` file. 30 | 31 | ### Development 32 | 33 | ```bash 34 | # Install dependencies 35 | pnpm i 36 | 37 | # Initial database 38 | pnpm --filter web db-push 39 | 40 | # Start Next.js web app 41 | pnpm dev 42 | ``` 43 | 44 | ### NPM Scripts 45 | 46 | #### `pnpm dev` 47 | 48 | Run the development server for web app. 49 | 50 | #### `pnpm build` 51 | 52 | Build the web app. 53 | 54 | ### TRPC 55 | 56 | [TRPC](https://trpc.io) app router is located at [server/trpc/index.ts](./server/trpc/index.ts). 57 | 58 | ## License 59 | 60 | MIT © [EGOIST](https://github.com/sponsors/egoist) 61 | -------------------------------------------------------------------------------- /apps/web/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | 5 | // NOTE: This file should not be edited 6 | // see https://nextjs.org/docs/basic-features/typescript for more information. 7 | -------------------------------------------------------------------------------- /apps/web/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const config = { 3 | experimental: { 4 | scrollRestoration: true, 5 | }, 6 | } 7 | 8 | export default config 9 | -------------------------------------------------------------------------------- /apps/web/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "web", 4 | "scripts": { 5 | "dev": "next", 6 | "build": "next build", 7 | "start": "next start --port $PORT", 8 | "prisma-client": "prisma generate", 9 | "migrate-dev": "prisma migrate dev", 10 | "migrate-deploy": "prisma migrate deploy", 11 | "db-push": "prisma db push" 12 | }, 13 | "dependencies": { 14 | "@prisma/client": "4.16.2", 15 | "@radix-ui/react-slot": "^1.0.2", 16 | "@tanstack/react-query": "^4.29.19", 17 | "@trpc/client": "^10.34.0", 18 | "@trpc/next": "^10.34.0", 19 | "@trpc/react-query": "^10.34.0", 20 | "@trpc/server": "^10.34.0", 21 | "clsx": "^1.2.1", 22 | "dayjs": "^1.11.9", 23 | "nanoid": "^4.0.2", 24 | "next": "^13.4.9", 25 | "next-seo": "^6.1.0", 26 | "react": "18.2.0", 27 | "react-dom": "18.2.0", 28 | "react-hook-form": "^7.45.1", 29 | "react-hot-toast": "^2.4.1", 30 | "resend": "^0.16.0", 31 | "tailwind-merge": "^1.13.2", 32 | "tailwind-variants": "^0.1.10", 33 | "zod": "^3.21.4" 34 | }, 35 | "devDependencies": { 36 | "@egoist/prettier-config": "1.0.0", 37 | "@types/cookie": "0.5.1", 38 | "@types/node": "18.7.13", 39 | "@types/react": "18.0.17", 40 | "autoprefixer": "10.4.4", 41 | "postcss": "8.4.25", 42 | "prettier": "3.0.0", 43 | "prisma": "4.16.2", 44 | "tailwindcss": "3.3.2", 45 | "typescript": "5.1.6" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /apps/web/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['tailwindcss', 'autoprefixer'], 3 | } 4 | -------------------------------------------------------------------------------- /apps/web/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | 4 | datasource db { 5 | provider = "postgresql" 6 | url = env("DATABASE_URL") 7 | } 8 | 9 | generator client { 10 | provider = "prisma-client-js" 11 | } 12 | 13 | model Session { 14 | id String @id @default(uuid()) 15 | createdAt DateTime @default(now()) 16 | name String 17 | token String @unique 18 | user User @relation(fields: [userId], references: [id], onDelete: Cascade) 19 | userId String 20 | 21 | @@index([userId]) 22 | } 23 | 24 | model User { 25 | id String @id @default(uuid()) 26 | createdAt DateTime @default(now()) 27 | email String @unique 28 | emailVerified DateTime? 29 | image String? 30 | sessions Session[] 31 | } 32 | 33 | model LoginCode { 34 | id String @id @default(uuid()) 35 | createdAt DateTime @default(now()) 36 | code String 37 | email String 38 | expiresAt DateTime 39 | 40 | @@unique([email, code]) 41 | } 42 | -------------------------------------------------------------------------------- /apps/web/src/app/logout/route.ts: -------------------------------------------------------------------------------- 1 | import { NextRequest, NextResponse } from "next/server" 2 | import { env } from "~/server/env" 3 | 4 | export const GET = (request: NextRequest) => { 5 | const url = request.nextUrl.clone() 6 | url.pathname = "/" 7 | const res = NextResponse.redirect(url) 8 | res.cookies.delete(env.AUTH_COOKIE_NAME) 9 | return res 10 | } 11 | -------------------------------------------------------------------------------- /apps/web/src/components/LoginForm.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react" 2 | import { useForm } from "react-hook-form" 3 | import { trpc } from "~/lib/trpc" 4 | import { toastError } from "~/lib/toast" 5 | import { useRouter } from "next/router" 6 | import { Button } from "./ui/Button" 7 | import { Input } from "./ui/Input" 8 | 9 | export const LoginForm = () => { 10 | const router = useRouter() 11 | const trpcContext = trpc.useContext() 12 | const [sentLoginCode, setSentLoginCode] = useState(false) 13 | const { handleSubmit, register, watch, reset } = useForm({ 14 | defaultValues: { 15 | email: "", 16 | loginCode: "", 17 | }, 18 | }) 19 | const email = watch("email") 20 | const requestLoginCode = trpc.auth.requestLoginCode.useMutation({ 21 | onSuccess() { 22 | setSentLoginCode(true) 23 | }, 24 | onError(error) { 25 | toastError(error) 26 | }, 27 | }) 28 | const login = trpc.auth.login.useMutation({ 29 | onSuccess() { 30 | trpcContext.invalidate() 31 | router.push("/") 32 | }, 33 | onError(error) { 34 | toastError(error) 35 | }, 36 | }) 37 | 38 | const onSubmit = handleSubmit((values) => { 39 | if (sentLoginCode) { 40 | login.mutate({ 41 | email: values.email, 42 | loginCode: values.loginCode, 43 | }) 44 | return 45 | } 46 | requestLoginCode.mutate({ 47 | email: values.email, 48 | }) 49 | }) 50 | return ( 51 |
52 | {sentLoginCode ? ( 53 |
54 | A login code has been sent to{" "} 55 | {email}, please enter it below. 56 |
57 | ) : ( 58 |
59 | Enter your email and we'll send you a secure login code. 60 |
61 | )} 62 | 63 | {!sentLoginCode && ( 64 |
65 | 74 |
75 | )} 76 | 77 | {sentLoginCode && ( 78 |
79 | 86 |
87 | )} 88 | 89 |
90 | 98 |
99 |
100 | ) 101 | } 102 | -------------------------------------------------------------------------------- /apps/web/src/components/email-templates/login-code.tsx: -------------------------------------------------------------------------------- 1 | export default function LoginCodeEmailTemplate({ code }: { code: string }) { 2 | return ( 3 |
4 |

5 | Your login code is {code} 6 |

7 | 8 |

This code will expire in 30 minutes.

9 |
10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /apps/web/src/components/ui/Button.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { tv, VariantProps } from "tailwind-variants" 3 | import { Slot } from "@radix-ui/react-slot" 4 | 5 | const buttonVariants = tv({ 6 | base: "inline-flex items-center justify-center rounded-full text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background", 7 | variants: { 8 | variant: { 9 | default: "bg-blue-500 text-white hover:bg-blue-500/90", 10 | destructive: 11 | "bg-destructive text-destructive-foreground hover:bg-destructive/90", 12 | outline: 13 | "border border-input hover:bg-accent hover:text-accent-foreground", 14 | secondary: "bg-zinc-200 text-black hover:bg-zinc-200/80", 15 | ghost: "hover:bg-accent hover:text-accent-foreground", 16 | link: "underline-offset-4 hover:underline text-primary", 17 | }, 18 | size: { 19 | default: "h-8 py-2 px-4", 20 | sm: "h-6 px-3 text-xs", 21 | lg: "h-10 px-8", 22 | xs: "h-5 px-2 text-xs", 23 | }, 24 | }, 25 | defaultVariants: { 26 | variant: "default", 27 | size: "default", 28 | }, 29 | }) 30 | 31 | export interface ButtonProps 32 | extends React.ButtonHTMLAttributes, 33 | VariantProps { 34 | asChild?: boolean 35 | isLoading?: boolean 36 | left?: React.ReactNode 37 | } 38 | 39 | const Button = React.forwardRef( 40 | ( 41 | { 42 | className, 43 | variant, 44 | size, 45 | asChild, 46 | children, 47 | isLoading, 48 | disabled, 49 | left, 50 | ...props 51 | }, 52 | ref, 53 | ) => { 54 | const Comp = asChild ? Slot : "button" 55 | const isDisabled = isLoading || disabled 56 | 57 | return ( 58 | 64 | {isLoading && ( 65 | 66 | )} 67 | {!isLoading && left} 68 | {children} 69 | 70 | ) 71 | }, 72 | ) 73 | Button.displayName = "Button" 74 | 75 | export { Button, buttonVariants } 76 | -------------------------------------------------------------------------------- /apps/web/src/components/ui/Control.tsx: -------------------------------------------------------------------------------- 1 | export const Control = ({ 2 | children, 3 | label, 4 | labelRight, 5 | desc, 6 | className, 7 | }: { 8 | children: React.ReactNode 9 | label?: React.ReactNode 10 | labelRight?: React.ReactNode 11 | desc?: React.ReactNode 12 | className?: string 13 | }) => { 14 | return ( 15 |
16 | {label && ( 17 |
18 | 19 | {labelRight} 20 |
21 | )} 22 | {desc &&
{desc}
} 23 | {children} 24 |
25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /apps/web/src/components/ui/Input.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | import { forwardRef, useEffect, useState } from "react" 3 | import { tv } from "tailwind-variants" 4 | import { Slot } from "@radix-ui/react-slot" 5 | 6 | const style = tv({ 7 | base: "border w-full rounded-lg h-10 inline-flex items-center px-3 focus:ring outline-none bg-white dark:bg-transparent focus:border-blue-400 ring-blue-400 read-only:focus:ring-0 dark:text-white dark:ring-blue-600 dark:focus:border-blue-600", 8 | }) 9 | 10 | type Props = React.InputHTMLAttributes & { 11 | asChild?: boolean 12 | suffix?: React.ReactNode 13 | isPassword?: boolean 14 | } 15 | 16 | export const Input = forwardRef( 17 | ({ className, asChild, suffix, isPassword, ...props }, ref) => { 18 | const Comp = asChild ? Slot : "input" 19 | const [isRevealed, setIsRevealed] = useState(false) 20 | 21 | return ( 22 |
23 | 29 | {isPassword ? ( 30 | 39 | ) : ( 40 | suffix 41 | )} 42 |
43 | ) 44 | }, 45 | ) 46 | -------------------------------------------------------------------------------- /apps/web/src/components/ui/Spinner.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react" 2 | import { cn } from "~/lib/cn" 3 | 4 | export const Spinner = ({ 5 | className, 6 | delay, 7 | }: { 8 | className?: string 9 | delay?: number 10 | }) => { 11 | const [show, setShow] = useState(!delay) 12 | 13 | useEffect(() => { 14 | const id = window.setTimeout(() => { 15 | setShow(true) 16 | }, delay) 17 | 18 | return () => { 19 | window.clearTimeout(id) 20 | } 21 | }, [delay]) 22 | 23 | if (!show) { 24 | return null 25 | } 26 | 27 | return ( 28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | ) 43 | } 44 | -------------------------------------------------------------------------------- /apps/web/src/css/spinner.css: -------------------------------------------------------------------------------- 1 | .spinner { 2 | font-size: 1em; 3 | position: relative; 4 | display: inline-block; 5 | width: 1em; 6 | height: 1em; 7 | } 8 | 9 | .spinner .spinner-blade { 10 | position: absolute; 11 | left: 0.4629em; 12 | bottom: 0; 13 | width: 0.074em; 14 | height: 0.2777em; 15 | border-radius: 0.0555em; 16 | background-color: transparent; 17 | -webkit-transform-origin: center -0.2222em; 18 | -ms-transform-origin: center -0.2222em; 19 | transform-origin: center -0.2222em; 20 | animation: spinner-fade9234 1s infinite linear; 21 | } 22 | 23 | .spinner .spinner-blade:nth-child(1) { 24 | -webkit-animation-delay: 0s; 25 | animation-delay: 0s; 26 | -webkit-transform: rotate(0deg); 27 | -ms-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 31 | .spinner .spinner-blade:nth-child(2) { 32 | -webkit-animation-delay: 0.083s; 33 | animation-delay: 0.083s; 34 | -webkit-transform: rotate(30deg); 35 | -ms-transform: rotate(30deg); 36 | transform: rotate(30deg); 37 | } 38 | 39 | .spinner .spinner-blade:nth-child(3) { 40 | -webkit-animation-delay: 0.166s; 41 | animation-delay: 0.166s; 42 | -webkit-transform: rotate(60deg); 43 | -ms-transform: rotate(60deg); 44 | transform: rotate(60deg); 45 | } 46 | 47 | .spinner .spinner-blade:nth-child(4) { 48 | -webkit-animation-delay: 0.249s; 49 | animation-delay: 0.249s; 50 | -webkit-transform: rotate(90deg); 51 | -ms-transform: rotate(90deg); 52 | transform: rotate(90deg); 53 | } 54 | 55 | .spinner .spinner-blade:nth-child(5) { 56 | -webkit-animation-delay: 0.332s; 57 | animation-delay: 0.332s; 58 | -webkit-transform: rotate(120deg); 59 | -ms-transform: rotate(120deg); 60 | transform: rotate(120deg); 61 | } 62 | 63 | .spinner .spinner-blade:nth-child(6) { 64 | -webkit-animation-delay: 0.415s; 65 | animation-delay: 0.415s; 66 | -webkit-transform: rotate(150deg); 67 | -ms-transform: rotate(150deg); 68 | transform: rotate(150deg); 69 | } 70 | 71 | .spinner .spinner-blade:nth-child(7) { 72 | -webkit-animation-delay: 0.498s; 73 | animation-delay: 0.498s; 74 | -webkit-transform: rotate(180deg); 75 | -ms-transform: rotate(180deg); 76 | transform: rotate(180deg); 77 | } 78 | 79 | .spinner .spinner-blade:nth-child(8) { 80 | -webkit-animation-delay: 0.581s; 81 | animation-delay: 0.581s; 82 | -webkit-transform: rotate(210deg); 83 | -ms-transform: rotate(210deg); 84 | transform: rotate(210deg); 85 | } 86 | 87 | .spinner .spinner-blade:nth-child(9) { 88 | -webkit-animation-delay: 0.664s; 89 | animation-delay: 0.664s; 90 | -webkit-transform: rotate(240deg); 91 | -ms-transform: rotate(240deg); 92 | transform: rotate(240deg); 93 | } 94 | 95 | .spinner .spinner-blade:nth-child(10) { 96 | -webkit-animation-delay: 0.747s; 97 | animation-delay: 0.747s; 98 | -webkit-transform: rotate(270deg); 99 | -ms-transform: rotate(270deg); 100 | transform: rotate(270deg); 101 | } 102 | 103 | .spinner .spinner-blade:nth-child(11) { 104 | -webkit-animation-delay: 0.83s; 105 | animation-delay: 0.83s; 106 | -webkit-transform: rotate(300deg); 107 | -ms-transform: rotate(300deg); 108 | transform: rotate(300deg); 109 | } 110 | 111 | .spinner .spinner-blade:nth-child(12) { 112 | -webkit-animation-delay: 0.913s; 113 | animation-delay: 0.913s; 114 | -webkit-transform: rotate(330deg); 115 | -ms-transform: rotate(330deg); 116 | transform: rotate(330deg); 117 | } 118 | 119 | @keyframes spinner-fade9234 { 120 | 0% { 121 | background-color: currentColor; 122 | } 123 | 124 | 100% { 125 | background-color: transparent; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /apps/web/src/css/tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /apps/web/src/lib/cn.ts: -------------------------------------------------------------------------------- 1 | import { clsx, ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...args: ClassValue[]) { 5 | return twMerge(clsx(...args)) 6 | } 7 | -------------------------------------------------------------------------------- /apps/web/src/lib/config.ts: -------------------------------------------------------------------------------- 1 | export const APP_NAME = "My App" 2 | -------------------------------------------------------------------------------- /apps/web/src/lib/current-user.ts: -------------------------------------------------------------------------------- 1 | import { trpc } from "./trpc" 2 | 3 | export const useCurrentUser = () => 4 | trpc.user.currentUser.useQuery(undefined, { 5 | trpc: { 6 | context: { 7 | skipBatch: true, 8 | }, 9 | }, 10 | }) 11 | -------------------------------------------------------------------------------- /apps/web/src/lib/toast.ts: -------------------------------------------------------------------------------- 1 | import { toast } from "react-hot-toast" 2 | 3 | export const toastError = (error: unknown, id?: string) => { 4 | if (error instanceof Error) { 5 | const message = error.message 6 | 7 | toast.error(message, { 8 | id, 9 | }) 10 | } else if (typeof error === "string") { 11 | toast.error(error, { 12 | id, 13 | }) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/lib/trpc.ts: -------------------------------------------------------------------------------- 1 | import { httpBatchLink, splitLink, httpLink } from "@trpc/client" 2 | import { createTRPCNext } from "@trpc/next" 3 | import { AppRouter } from "~/server/trpc" 4 | 5 | export const trpc = createTRPCNext({ 6 | config({ ctx }) { 7 | const url = `/api/trpc` 8 | return { 9 | links: [ 10 | splitLink({ 11 | condition(op) { 12 | // check for context property `skipBatch` 13 | return op.context.skipBatch === true 14 | }, 15 | // when condition is true, use normal request 16 | true: httpLink({ 17 | url, 18 | fetch: (url, init) => 19 | window.fetch(url, { 20 | credentials: "include", 21 | ...init, 22 | }), 23 | }), 24 | // when condition is false, use batching 25 | false: httpBatchLink({ 26 | url, 27 | fetch: (url, init) => 28 | window.fetch(url, { 29 | credentials: "include", 30 | ...init, 31 | }), 32 | }), 33 | }), 34 | ], 35 | } 36 | }, 37 | /** 38 | * @link https://trpc.io/docs/ssr 39 | **/ 40 | ssr: false, 41 | }) 42 | -------------------------------------------------------------------------------- /apps/web/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | type Truthy = T extends false | "" | 0 | null | undefined ? never : T // from lodash 2 | 3 | export function truthy(value: T): value is Truthy { 4 | return Boolean(value) 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import "../css/spinner.css" 2 | import "../css/tailwind.css" 3 | import { AppType } from "next/dist/shared/lib/utils" 4 | import { Toaster } from "react-hot-toast" 5 | import { trpc } from "~/lib/trpc" 6 | import { NextSeo } from "next-seo" 7 | import { APP_NAME } from "~/lib/config" 8 | 9 | const MyApp: AppType = ({ Component, pageProps }) => { 10 | return ( 11 | <> 12 | 13 | 14 | 15 | 16 | ) 17 | } 18 | 19 | export default trpc.withTRPC(MyApp) 20 | -------------------------------------------------------------------------------- /apps/web/src/pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import { Html, Head, Main, NextScript } from "next/document" 2 | 3 | export default function Document() { 4 | return ( 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/src/pages/api/trpc/[trpc].ts: -------------------------------------------------------------------------------- 1 | import * as trpcNext from "@trpc/server/adapters/next" 2 | import { createContext } from "~/server/trpc/context" 3 | import { appRouter } from "~/server/trpc" 4 | // export API handler 5 | // @see https://trpc.io/docs/server/adapters 6 | export default trpcNext.createNextApiHandler({ 7 | router: appRouter, 8 | createContext: createContext, 9 | }) 10 | -------------------------------------------------------------------------------- /apps/web/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import { LoginForm } from "~/components/LoginForm" 2 | import { Spinner } from "~/components/ui/Spinner" 3 | import { APP_NAME } from "~/lib/config" 4 | import { useCurrentUser } from "~/lib/current-user" 5 | 6 | export default function Page() { 7 | const currentUser = useCurrentUser() 8 | return ( 9 |
10 |

{APP_NAME}

11 | {currentUser.isLoading ? ( 12 | 13 | ) : currentUser.data ? ( 14 |

Hi, {currentUser.data.email}

15 | ) : ( 16 | 17 | )} 18 |
19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /apps/web/src/server/auth.ts: -------------------------------------------------------------------------------- 1 | import { IncomingMessage, ServerResponse } from "http" 2 | import { z } from "zod" 3 | import Cookie from "cookie" 4 | import { env } from "./env" 5 | import { prisma } from "./prisma" 6 | 7 | export const AuthUserSchema = z.object({ 8 | id: z.string(), 9 | email: z.string(), 10 | createdAt: z.string(), 11 | }) 12 | 13 | export type AuthUser = z.infer 14 | 15 | export async function getUserFromHeader( 16 | req: IncomingMessage, 17 | ): Promise { 18 | const cookie = req.headers.cookie 19 | const token = cookie ? Cookie.parse(cookie)[env.AUTH_COOKIE_NAME] : null 20 | if (token) { 21 | const session = await prisma.session.findUnique({ 22 | where: { 23 | token, 24 | }, 25 | }) 26 | if (session) { 27 | const [user] = await Promise.all([ 28 | prisma.user.findUnique({ where: { id: session.userId } }), 29 | ]) 30 | if (user) { 31 | return { 32 | id: user.id, 33 | email: user.email, 34 | createdAt: user.createdAt.toISOString(), 35 | } 36 | } 37 | } 38 | } 39 | return null 40 | } 41 | 42 | export const setAuthCookie = ( 43 | res: ServerResponse, 44 | token: string, 45 | remove?: boolean, 46 | ) => { 47 | const value = Cookie.serialize(env.AUTH_COOKIE_NAME, token, { 48 | path: "/", 49 | httpOnly: true, 50 | secure: true, 51 | sameSite: "lax", 52 | domain: env.AUTH_COOKIE_DOMAIN, 53 | // 1 year 54 | maxAge: remove ? 0 : 60 * 60 * 24 * 365, 55 | }) 56 | 57 | console.log("set auth cookie", value) 58 | res.setHeader("Set-Cookie", value) 59 | } 60 | -------------------------------------------------------------------------------- /apps/web/src/server/email.ts: -------------------------------------------------------------------------------- 1 | import { Resend } from "resend" 2 | import { env } from "./env" 3 | import LoginCodeEmailTemplate from "~/components/email-templates/login-code" 4 | 5 | const isDev = process.env.NODE_ENV === "development" 6 | 7 | export const sendLoginCodeEmail = async ({ 8 | email, 9 | code, 10 | }: { 11 | email: string 12 | code: string 13 | }) => { 14 | if (isDev) { 15 | console.log("Login code:", code) 16 | return 17 | } 18 | 19 | const resend = new Resend(env.RESEND_API_KEY) 20 | await resend.emails.send({ 21 | from: `Panik `, 22 | to: [email], 23 | subject: "Log in to Panik", 24 | react: LoginCodeEmailTemplate({ code }), 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /apps/web/src/server/env.ts: -------------------------------------------------------------------------------- 1 | const parseEnv = (name: string, required?: T) => { 2 | if (required && !process.env[name]) { 3 | throw new Error(`Missing required environment variable: ${name}`) 4 | } 5 | return process.env[name] as T extends true ? string : string | undefined 6 | } 7 | 8 | export const env = { 9 | AUTH_COOKIE_NAME: parseEnv("AUTH_COOKIE_NAME", true), 10 | AUTH_COOKIE_DOMAIN: parseEnv("AUTH_COOKIE_DOMAIN"), 11 | RESEND_API_KEY: parseEnv("RESEND_API_KEY"), 12 | } 13 | -------------------------------------------------------------------------------- /apps/web/src/server/gate.ts: -------------------------------------------------------------------------------- 1 | import { TRPCError } from "@trpc/server" 2 | import { AuthUser } from "./auth" 3 | 4 | export const createGate = (user: AuthUser | null) => { 5 | return { 6 | getUser: (requireAuth: T) => { 7 | if (requireAuth && !user) { 8 | throw new TRPCError({ code: "UNAUTHORIZED" }) 9 | } 10 | 11 | return user as T extends true ? AuthUser : AuthUser | null 12 | }, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /apps/web/src/server/prisma.ts: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from "@prisma/client" 2 | import { singleton } from "./singleton" 3 | 4 | export const prisma = singleton("prisma", () => new PrismaClient()) 5 | -------------------------------------------------------------------------------- /apps/web/src/server/singleton.ts: -------------------------------------------------------------------------------- 1 | global._singletons = global._singletons || {} 2 | 3 | export const singleton = (id: string, factory: () => T): T => { 4 | if (!global._singletons[id]) { 5 | global._singletons[id] = factory() 6 | } 7 | return global._singletons[id] 8 | } 9 | 10 | export const singletonAsync = ( 11 | id: string, 12 | factory: () => Promise, 13 | singleton = true, 14 | ): { readonly value: T; wait: Promise } => { 15 | if (global._singletons[id] && singleton) { 16 | return { 17 | wait: Promise.resolve(), 18 | 19 | get value() { 20 | return global._singletons[id] 21 | }, 22 | } 23 | } 24 | 25 | let ready = false 26 | 27 | const wait = factory().then((value) => { 28 | ready = true 29 | global._singletons[id] = value 30 | }) 31 | 32 | return { 33 | wait, 34 | 35 | get value() { 36 | if (!ready) { 37 | throw new Error(`please await .wait before using the value of '${id}'`) 38 | } 39 | return global._singletons[id] 40 | }, 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /apps/web/src/server/trpc/auth.router.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod" 2 | import { t } from "./t" 3 | import { prisma } from "../prisma" 4 | import { TRPCError } from "@trpc/server" 5 | import { setAuthCookie } from "../auth" 6 | import { nanoid, customAlphabet } from "nanoid" 7 | import dayjs from "dayjs" 8 | import { sendLoginCodeEmail } from "../email" 9 | 10 | const generateLoginCode = customAlphabet( 11 | "0123456789ABCDEFGHIJKLMNOPQRXTUVWXYZ", 12 | 6, 13 | ) 14 | 15 | export const authRouter = t.router({ 16 | login: t.procedure 17 | .input( 18 | z.object({ 19 | email: z.string().email(), 20 | loginCode: z.string(), 21 | }), 22 | ) 23 | .mutation(async ({ ctx, input }) => { 24 | const loginCode = await prisma.loginCode.findUnique({ 25 | where: { 26 | email_code: { 27 | email: input.email, 28 | code: input.loginCode, 29 | }, 30 | }, 31 | }) 32 | 33 | if (!loginCode) { 34 | throw new TRPCError({ 35 | code: "BAD_REQUEST", 36 | message: "Login code not found", 37 | }) 38 | } 39 | 40 | if (loginCode.expiresAt < new Date()) { 41 | throw new TRPCError({ 42 | code: "BAD_REQUEST", 43 | message: "Login code expired", 44 | }) 45 | } 46 | 47 | let user = await prisma.user.findUnique({ 48 | where: { 49 | email: input.email, 50 | }, 51 | }) 52 | 53 | if (!user) { 54 | user = await prisma.user.create({ 55 | data: { 56 | email: input.email, 57 | }, 58 | }) 59 | } 60 | 61 | const [session] = await Promise.all([ 62 | prisma.session.create({ 63 | data: { 64 | user: { 65 | connect: { 66 | id: user.id, 67 | }, 68 | }, 69 | name: "Login via Email", 70 | token: nanoid(), 71 | }, 72 | }), 73 | prisma.loginCode.delete({ 74 | where: { 75 | id: loginCode.id, 76 | }, 77 | }), 78 | ]) 79 | 80 | setAuthCookie(ctx.res, session.token) 81 | }), 82 | 83 | requestLoginCode: t.procedure 84 | .input( 85 | z.object({ 86 | email: z.string().email(), 87 | }), 88 | ) 89 | .mutation(async ({ input }) => { 90 | const loginCode = await prisma.loginCode.create({ 91 | data: { 92 | email: input.email, 93 | expiresAt: dayjs().add(30, "minute").toDate(), 94 | code: generateLoginCode(), 95 | }, 96 | }) 97 | 98 | await sendLoginCodeEmail({ email: input.email, code: loginCode.code }) 99 | }), 100 | }) 101 | -------------------------------------------------------------------------------- /apps/web/src/server/trpc/context.ts: -------------------------------------------------------------------------------- 1 | import { inferAsyncReturnType } from "@trpc/server" 2 | import { createGate } from "../gate" 3 | import { getUserFromHeader } from "../auth" 4 | import { IncomingMessage, ServerResponse } from "http" 5 | 6 | export async function createContext({ 7 | req, 8 | res, 9 | }: { 10 | req: IncomingMessage 11 | res: ServerResponse 12 | }) { 13 | const user = await getUserFromHeader(req) 14 | const gate = createGate(user) 15 | return { req, res, user, gate } 16 | } 17 | export type Context = inferAsyncReturnType 18 | -------------------------------------------------------------------------------- /apps/web/src/server/trpc/index.ts: -------------------------------------------------------------------------------- 1 | import { t } from "./t" 2 | import { authRouter } from "./auth.router" 3 | import { userRouter } from "./user.router" 4 | 5 | export const appRouter = t.router({ 6 | auth: authRouter, 7 | user: userRouter, 8 | }) 9 | // export type definition of API 10 | export type AppRouter = typeof appRouter 11 | -------------------------------------------------------------------------------- /apps/web/src/server/trpc/t.ts: -------------------------------------------------------------------------------- 1 | import { initTRPC } from "@trpc/server" 2 | import { Context } from "./context" 3 | import { ZodError } from "zod" 4 | 5 | export const t = initTRPC.context().create({ 6 | errorFormatter(opts) { 7 | const { shape, error } = opts 8 | console.error(error) 9 | 10 | let message = shape.message 11 | 12 | if (error.cause instanceof ZodError) { 13 | message = error.cause.issues 14 | .map((issue) => `${issue.path}: ${issue.message}`) 15 | .join("\n") 16 | } 17 | 18 | return { 19 | ...shape, 20 | message, 21 | data: { 22 | ...shape.data, 23 | zodError: 24 | error.code === "BAD_REQUEST" && error.cause instanceof ZodError 25 | ? error.cause.flatten() 26 | : null, 27 | }, 28 | } 29 | }, 30 | }) 31 | -------------------------------------------------------------------------------- /apps/web/src/server/trpc/user.router.ts: -------------------------------------------------------------------------------- 1 | import { t } from "./t" 2 | 3 | export const userRouter = t.router({ 4 | currentUser: t.procedure.query(({ ctx }) => { 5 | return ctx.user 6 | }), 7 | }) 8 | -------------------------------------------------------------------------------- /apps/web/tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | darkMode: "class", 4 | content: ["./src/**/*.tsx"], 5 | theme: {}, 6 | variants: {}, 7 | plugins: [], 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "esnext", 5 | "jsx": "preserve", 6 | "strict": true, 7 | "strictPropertyInitialization": false, 8 | "skipLibCheck": true, 9 | "moduleResolution": "node", 10 | "esModuleInterop": true, 11 | "experimentalDecorators": true, 12 | "emitDecoratorMetadata": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "baseUrl": ".", 15 | "paths": { 16 | "~/*": [ 17 | "./src/*" 18 | ] 19 | }, 20 | "lib": [ 21 | "dom", 22 | "dom.iterable", 23 | "esnext" 24 | ], 25 | "allowJs": true, 26 | "noEmit": true, 27 | "resolveJsonModule": true, 28 | "isolatedModules": true, 29 | "incremental": true, 30 | "plugins": [ 31 | { 32 | "name": "next" 33 | } 34 | ] 35 | }, 36 | "include": [ 37 | "next-env.d.ts", 38 | "**/*.ts", 39 | "**/*.tsx", 40 | ".next/types/**/*.ts" 41 | ], 42 | "exclude": [ 43 | "node_modules" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /apps/web/types.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace NodeJS { 2 | interface ProcessEnv { 3 | // Additional environment variables 4 | } 5 | } 6 | 7 | type $TsFixMe = any 8 | 9 | declare var _singletons: Record 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "my-workspace", 4 | "scripts": { 5 | "dev": "pnpm --filter web dev", 6 | "build": "pnpm --filter web build" 7 | }, 8 | "devDependencies": { 9 | "typescript": "5.1.6" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.1' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | devDependencies: 11 | typescript: 12 | specifier: 5.1.6 13 | version: 5.1.6 14 | 15 | apps/web: 16 | dependencies: 17 | '@prisma/client': 18 | specifier: 4.16.2 19 | version: 4.16.2(prisma@4.16.2) 20 | '@radix-ui/react-slot': 21 | specifier: ^1.0.2 22 | version: 1.0.2(@types/react@18.0.17)(react@18.2.0) 23 | '@tanstack/react-query': 24 | specifier: ^4.29.19 25 | version: 4.29.19(react-dom@18.2.0)(react@18.2.0) 26 | '@trpc/client': 27 | specifier: ^10.34.0 28 | version: 10.34.0(@trpc/server@10.34.0) 29 | '@trpc/next': 30 | specifier: ^10.34.0 31 | version: 10.34.0(@tanstack/react-query@4.29.19)(@trpc/client@10.34.0)(@trpc/react-query@10.34.0)(@trpc/server@10.34.0)(next@13.4.9)(react-dom@18.2.0)(react@18.2.0) 32 | '@trpc/react-query': 33 | specifier: ^10.34.0 34 | version: 10.34.0(@tanstack/react-query@4.29.19)(@trpc/client@10.34.0)(@trpc/server@10.34.0)(react-dom@18.2.0)(react@18.2.0) 35 | '@trpc/server': 36 | specifier: ^10.34.0 37 | version: 10.34.0 38 | clsx: 39 | specifier: ^1.2.1 40 | version: 1.2.1 41 | dayjs: 42 | specifier: ^1.11.9 43 | version: 1.11.9 44 | nanoid: 45 | specifier: ^4.0.2 46 | version: 4.0.2 47 | next: 48 | specifier: ^13.4.9 49 | version: 13.4.9(react-dom@18.2.0)(react@18.2.0) 50 | next-seo: 51 | specifier: ^6.1.0 52 | version: 6.1.0(next@13.4.9)(react-dom@18.2.0)(react@18.2.0) 53 | react: 54 | specifier: 18.2.0 55 | version: 18.2.0 56 | react-dom: 57 | specifier: 18.2.0 58 | version: 18.2.0(react@18.2.0) 59 | react-hook-form: 60 | specifier: ^7.45.1 61 | version: 7.45.1(react@18.2.0) 62 | react-hot-toast: 63 | specifier: ^2.4.1 64 | version: 2.4.1(csstype@3.0.10)(react-dom@18.2.0)(react@18.2.0) 65 | resend: 66 | specifier: ^0.16.0 67 | version: 0.16.0 68 | tailwind-merge: 69 | specifier: ^1.13.2 70 | version: 1.13.2 71 | tailwind-variants: 72 | specifier: ^0.1.10 73 | version: 0.1.10(tailwindcss@3.3.2) 74 | zod: 75 | specifier: ^3.21.4 76 | version: 3.21.4 77 | devDependencies: 78 | '@egoist/prettier-config': 79 | specifier: 1.0.0 80 | version: 1.0.0 81 | '@types/cookie': 82 | specifier: 0.5.1 83 | version: 0.5.1 84 | '@types/node': 85 | specifier: 18.7.13 86 | version: 18.7.13 87 | '@types/react': 88 | specifier: 18.0.17 89 | version: 18.0.17 90 | autoprefixer: 91 | specifier: 10.4.4 92 | version: 10.4.4(postcss@8.4.25) 93 | postcss: 94 | specifier: 8.4.25 95 | version: 8.4.25 96 | prettier: 97 | specifier: 3.0.0 98 | version: 3.0.0 99 | prisma: 100 | specifier: 4.16.2 101 | version: 4.16.2 102 | tailwindcss: 103 | specifier: 3.3.2 104 | version: 3.3.2 105 | typescript: 106 | specifier: 5.1.6 107 | version: 5.1.6 108 | 109 | packages: 110 | 111 | /@alloc/quick-lru@5.2.0: 112 | resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} 113 | engines: {node: '>=10'} 114 | 115 | /@babel/runtime@7.22.6: 116 | resolution: {integrity: sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==} 117 | engines: {node: '>=6.9.0'} 118 | dependencies: 119 | regenerator-runtime: 0.13.11 120 | dev: false 121 | 122 | /@egoist/prettier-config@1.0.0: 123 | resolution: {integrity: sha512-D1Tp9Jv4aVoEo3cOAO966gFCI0wx/1lZ6sEHX8uMAfyVxuxD2+knGxhfGlb/FNLxWV3ifSI5hOmB/zFfsi7Rzw==} 124 | dev: true 125 | 126 | /@jridgewell/gen-mapping@0.3.3: 127 | resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} 128 | engines: {node: '>=6.0.0'} 129 | dependencies: 130 | '@jridgewell/set-array': 1.1.2 131 | '@jridgewell/sourcemap-codec': 1.4.15 132 | '@jridgewell/trace-mapping': 0.3.18 133 | 134 | /@jridgewell/resolve-uri@3.1.0: 135 | resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} 136 | engines: {node: '>=6.0.0'} 137 | 138 | /@jridgewell/set-array@1.1.2: 139 | resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} 140 | engines: {node: '>=6.0.0'} 141 | 142 | /@jridgewell/sourcemap-codec@1.4.14: 143 | resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} 144 | 145 | /@jridgewell/sourcemap-codec@1.4.15: 146 | resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} 147 | 148 | /@jridgewell/trace-mapping@0.3.18: 149 | resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} 150 | dependencies: 151 | '@jridgewell/resolve-uri': 3.1.0 152 | '@jridgewell/sourcemap-codec': 1.4.14 153 | 154 | /@next/env@13.4.9: 155 | resolution: {integrity: sha512-vuDRK05BOKfmoBYLNi2cujG2jrYbEod/ubSSyqgmEx9n/W3eZaJQdRNhTfumO+qmq/QTzLurW487n/PM/fHOkw==} 156 | dev: false 157 | 158 | /@next/swc-darwin-arm64@13.4.9: 159 | resolution: {integrity: sha512-TVzGHpZoVBk3iDsTOQA/R6MGmFp0+17SWXMEWd6zG30AfuELmSSMe2SdPqxwXU0gbpWkJL1KgfLzy5ReN0crqQ==} 160 | engines: {node: '>= 10'} 161 | cpu: [arm64] 162 | os: [darwin] 163 | requiresBuild: true 164 | dev: false 165 | optional: true 166 | 167 | /@next/swc-darwin-x64@13.4.9: 168 | resolution: {integrity: sha512-aSfF1fhv28N2e7vrDZ6zOQ+IIthocfaxuMWGReB5GDriF0caTqtHttAvzOMgJgXQtQx6XhyaJMozLTSEXeNN+A==} 169 | engines: {node: '>= 10'} 170 | cpu: [x64] 171 | os: [darwin] 172 | requiresBuild: true 173 | dev: false 174 | optional: true 175 | 176 | /@next/swc-linux-arm64-gnu@13.4.9: 177 | resolution: {integrity: sha512-JhKoX5ECzYoTVyIy/7KykeO4Z2lVKq7HGQqvAH+Ip9UFn1MOJkOnkPRB7v4nmzqAoY+Je05Aj5wNABR1N18DMg==} 178 | engines: {node: '>= 10'} 179 | cpu: [arm64] 180 | os: [linux] 181 | requiresBuild: true 182 | dev: false 183 | optional: true 184 | 185 | /@next/swc-linux-arm64-musl@13.4.9: 186 | resolution: {integrity: sha512-OOn6zZBIVkm/4j5gkPdGn4yqQt+gmXaLaSjRSO434WplV8vo2YaBNbSHaTM9wJpZTHVDYyjzuIYVEzy9/5RVZw==} 187 | engines: {node: '>= 10'} 188 | cpu: [arm64] 189 | os: [linux] 190 | requiresBuild: true 191 | dev: false 192 | optional: true 193 | 194 | /@next/swc-linux-x64-gnu@13.4.9: 195 | resolution: {integrity: sha512-iA+fJXFPpW0SwGmx/pivVU+2t4zQHNOOAr5T378PfxPHY6JtjV6/0s1vlAJUdIHeVpX98CLp9k5VuKgxiRHUpg==} 196 | engines: {node: '>= 10'} 197 | cpu: [x64] 198 | os: [linux] 199 | requiresBuild: true 200 | dev: false 201 | optional: true 202 | 203 | /@next/swc-linux-x64-musl@13.4.9: 204 | resolution: {integrity: sha512-rlNf2WUtMM+GAQrZ9gMNdSapkVi3koSW3a+dmBVp42lfugWVvnyzca/xJlN48/7AGx8qu62WyO0ya1ikgOxh6A==} 205 | engines: {node: '>= 10'} 206 | cpu: [x64] 207 | os: [linux] 208 | requiresBuild: true 209 | dev: false 210 | optional: true 211 | 212 | /@next/swc-win32-arm64-msvc@13.4.9: 213 | resolution: {integrity: sha512-5T9ybSugXP77nw03vlgKZxD99AFTHaX8eT1ayKYYnGO9nmYhJjRPxcjU5FyYI+TdkQgEpIcH7p/guPLPR0EbKA==} 214 | engines: {node: '>= 10'} 215 | cpu: [arm64] 216 | os: [win32] 217 | requiresBuild: true 218 | dev: false 219 | optional: true 220 | 221 | /@next/swc-win32-ia32-msvc@13.4.9: 222 | resolution: {integrity: sha512-ojZTCt1lP2ucgpoiFgrFj07uq4CZsq4crVXpLGgQfoFq00jPKRPgesuGPaz8lg1yLfvafkU3Jd1i8snKwYR3LA==} 223 | engines: {node: '>= 10'} 224 | cpu: [ia32] 225 | os: [win32] 226 | requiresBuild: true 227 | dev: false 228 | optional: true 229 | 230 | /@next/swc-win32-x64-msvc@13.4.9: 231 | resolution: {integrity: sha512-QbT03FXRNdpuL+e9pLnu+XajZdm/TtIXVYY4lA9t+9l0fLZbHXDYEKitAqxrOj37o3Vx5ufxiRAniaIebYDCgw==} 232 | engines: {node: '>= 10'} 233 | cpu: [x64] 234 | os: [win32] 235 | requiresBuild: true 236 | dev: false 237 | optional: true 238 | 239 | /@nodelib/fs.scandir@2.1.5: 240 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 241 | engines: {node: '>= 8'} 242 | dependencies: 243 | '@nodelib/fs.stat': 2.0.5 244 | run-parallel: 1.2.0 245 | 246 | /@nodelib/fs.stat@2.0.5: 247 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 248 | engines: {node: '>= 8'} 249 | 250 | /@nodelib/fs.walk@1.2.8: 251 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 252 | engines: {node: '>= 8'} 253 | dependencies: 254 | '@nodelib/fs.scandir': 2.1.5 255 | fastq: 1.13.0 256 | 257 | /@prisma/client@4.16.2(prisma@4.16.2): 258 | resolution: {integrity: sha512-qCoEyxv1ZrQ4bKy39GnylE8Zq31IRmm8bNhNbZx7bF2cU5aiCCnSa93J2imF88MBjn7J9eUQneNxUQVJdl/rPQ==} 259 | engines: {node: '>=14.17'} 260 | requiresBuild: true 261 | peerDependencies: 262 | prisma: '*' 263 | peerDependenciesMeta: 264 | prisma: 265 | optional: true 266 | dependencies: 267 | '@prisma/engines-version': 4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81 268 | prisma: 4.16.2 269 | dev: false 270 | 271 | /@prisma/engines-version@4.16.1-1.4bc8b6e1b66cb932731fb1bdbbc550d1e010de81: 272 | resolution: {integrity: sha512-q617EUWfRIDTriWADZ4YiWRZXCa/WuhNgLTVd+HqWLffjMSPzyM5uOWoauX91wvQClSKZU4pzI4JJLQ9Kl62Qg==} 273 | dev: false 274 | 275 | /@prisma/engines@4.16.2: 276 | resolution: {integrity: sha512-vx1nxVvN4QeT/cepQce68deh/Turxy5Mr+4L4zClFuK1GlxN3+ivxfuv+ej/gvidWn1cE1uAhW7ALLNlYbRUAw==} 277 | requiresBuild: true 278 | 279 | /@radix-ui/react-compose-refs@1.0.1(@types/react@18.0.17)(react@18.2.0): 280 | resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} 281 | peerDependencies: 282 | '@types/react': '*' 283 | react: ^16.8 || ^17.0 || ^18.0 284 | peerDependenciesMeta: 285 | '@types/react': 286 | optional: true 287 | dependencies: 288 | '@babel/runtime': 7.22.6 289 | '@types/react': 18.0.17 290 | react: 18.2.0 291 | dev: false 292 | 293 | /@radix-ui/react-slot@1.0.2(@types/react@18.0.17)(react@18.2.0): 294 | resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==} 295 | peerDependencies: 296 | '@types/react': '*' 297 | react: ^16.8 || ^17.0 || ^18.0 298 | peerDependenciesMeta: 299 | '@types/react': 300 | optional: true 301 | dependencies: 302 | '@babel/runtime': 7.22.6 303 | '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.0.17)(react@18.2.0) 304 | '@types/react': 18.0.17 305 | react: 18.2.0 306 | dev: false 307 | 308 | /@react-email/render@0.0.7: 309 | resolution: {integrity: sha512-hMMhxk6TpOcDC5qnKzXPVJoVGEwfm+U5bGOPH+MyTTlx0F02RLQygcATBKsbP7aI/mvkmBAZoFbgPIHop7ovug==} 310 | engines: {node: '>=16.0.0'} 311 | dependencies: 312 | html-to-text: 9.0.3 313 | pretty: 2.0.0 314 | react: 18.2.0 315 | react-dom: 18.2.0(react@18.2.0) 316 | dev: false 317 | 318 | /@selderee/plugin-htmlparser2@0.10.0: 319 | resolution: {integrity: sha512-gW69MEamZ4wk1OsOq1nG1jcyhXIQcnrsX5JwixVw/9xaiav8TCyjESAruu1Rz9yyInhgBXxkNwMeygKnN2uxNA==} 320 | dependencies: 321 | domhandler: 5.0.3 322 | selderee: 0.10.0 323 | dev: false 324 | 325 | /@swc/helpers@0.5.1: 326 | resolution: {integrity: sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==} 327 | dependencies: 328 | tslib: 2.4.0 329 | dev: false 330 | 331 | /@tanstack/query-core@4.29.19: 332 | resolution: {integrity: sha512-uPe1DukeIpIHpQi6UzIgBcXsjjsDaLnc7hF+zLBKnaUlh7jFE/A+P8t4cU4VzKPMFB/C970n/9SxtpO5hmIRgw==} 333 | dev: false 334 | 335 | /@tanstack/react-query@4.29.19(react-dom@18.2.0)(react@18.2.0): 336 | resolution: {integrity: sha512-XiTIOHHQ5Cw1WUlHaD4fmVUMhoWjuNJlAeJGq7eM4BraI5z7y8WkZO+NR8PSuRnQGblpuVdjClQbDFtwxTtTUw==} 337 | peerDependencies: 338 | react: ^16.8.0 || ^17.0.0 || ^18.0.0 339 | react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 340 | react-native: '*' 341 | peerDependenciesMeta: 342 | react-dom: 343 | optional: true 344 | react-native: 345 | optional: true 346 | dependencies: 347 | '@tanstack/query-core': 4.29.19 348 | react: 18.2.0 349 | react-dom: 18.2.0(react@18.2.0) 350 | use-sync-external-store: 1.2.0(react@18.2.0) 351 | dev: false 352 | 353 | /@trpc/client@10.34.0(@trpc/server@10.34.0): 354 | resolution: {integrity: sha512-nqtDTIqSY/9syo2EjSy4WWWXPU9GsamEh9Tsg698gLAh1nhgFc5+/YYeb+Ne1pbvWGZ5/3t9Dcz3h4wMyyJ9gQ==} 355 | peerDependencies: 356 | '@trpc/server': 10.34.0 357 | dependencies: 358 | '@trpc/server': 10.34.0 359 | dev: false 360 | 361 | /@trpc/next@10.34.0(@tanstack/react-query@4.29.19)(@trpc/client@10.34.0)(@trpc/react-query@10.34.0)(@trpc/server@10.34.0)(next@13.4.9)(react-dom@18.2.0)(react@18.2.0): 362 | resolution: {integrity: sha512-8jQPedVkCYCAG6PXDEumG5ILeD1aYVC6/aApk5Y96eeqnmAtX7TO9grVRfGGNaISuTtJ/oIDmRfSRqo1eOU4OA==} 363 | peerDependencies: 364 | '@tanstack/react-query': ^4.18.0 365 | '@trpc/client': 10.34.0 366 | '@trpc/react-query': 10.34.0 367 | '@trpc/server': 10.34.0 368 | next: '*' 369 | react: '>=16.8.0' 370 | react-dom: '>=16.8.0' 371 | dependencies: 372 | '@tanstack/react-query': 4.29.19(react-dom@18.2.0)(react@18.2.0) 373 | '@trpc/client': 10.34.0(@trpc/server@10.34.0) 374 | '@trpc/react-query': 10.34.0(@tanstack/react-query@4.29.19)(@trpc/client@10.34.0)(@trpc/server@10.34.0)(react-dom@18.2.0)(react@18.2.0) 375 | '@trpc/server': 10.34.0 376 | next: 13.4.9(react-dom@18.2.0)(react@18.2.0) 377 | react: 18.2.0 378 | react-dom: 18.2.0(react@18.2.0) 379 | react-ssr-prepass: 1.5.0(react@18.2.0) 380 | dev: false 381 | 382 | /@trpc/react-query@10.34.0(@tanstack/react-query@4.29.19)(@trpc/client@10.34.0)(@trpc/server@10.34.0)(react-dom@18.2.0)(react@18.2.0): 383 | resolution: {integrity: sha512-dnp7CmCBXwBgd8nAjMoHWMJwQrvAzjP+f8EXKfJVF66y9FydTBTf4CuXRh+A4EgA5CZeu4Ecva4D61Eu2I13GA==} 384 | peerDependencies: 385 | '@tanstack/react-query': ^4.18.0 386 | '@trpc/client': 10.34.0 387 | '@trpc/server': 10.34.0 388 | react: '>=16.8.0' 389 | react-dom: '>=16.8.0' 390 | dependencies: 391 | '@tanstack/react-query': 4.29.19(react-dom@18.2.0)(react@18.2.0) 392 | '@trpc/client': 10.34.0(@trpc/server@10.34.0) 393 | '@trpc/server': 10.34.0 394 | react: 18.2.0 395 | react-dom: 18.2.0(react@18.2.0) 396 | dev: false 397 | 398 | /@trpc/server@10.34.0: 399 | resolution: {integrity: sha512-2VMW44Fpaoyqb50dBtzdSWMhqt8lmoJiocEyBBeDb03R0W+XrzbVD5kU/wqKPlcp1DWeNCkOEIMtetMZCfo1hA==} 400 | dev: false 401 | 402 | /@types/cookie@0.5.1: 403 | resolution: {integrity: sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==} 404 | dev: true 405 | 406 | /@types/node@18.7.13: 407 | resolution: {integrity: sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw==} 408 | dev: true 409 | 410 | /@types/prop-types@15.7.4: 411 | resolution: {integrity: sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==} 412 | 413 | /@types/react@18.0.17: 414 | resolution: {integrity: sha512-38ETy4tL+rn4uQQi7mB81G7V1g0u2ryquNmsVIOKUAEIDK+3CUjZ6rSRpdvS99dNBnkLFL83qfmtLacGOTIhwQ==} 415 | dependencies: 416 | '@types/prop-types': 15.7.4 417 | '@types/scheduler': 0.16.2 418 | csstype: 3.0.10 419 | 420 | /@types/scheduler@0.16.2: 421 | resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} 422 | 423 | /abbrev@1.1.1: 424 | resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} 425 | dev: false 426 | 427 | /any-promise@1.3.0: 428 | resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} 429 | 430 | /anymatch@3.1.2: 431 | resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} 432 | engines: {node: '>= 8'} 433 | dependencies: 434 | normalize-path: 3.0.0 435 | picomatch: 2.3.1 436 | 437 | /arg@5.0.2: 438 | resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} 439 | 440 | /asynckit@0.4.0: 441 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} 442 | dev: false 443 | 444 | /autoprefixer@10.4.4(postcss@8.4.25): 445 | resolution: {integrity: sha512-Tm8JxsB286VweiZ5F0anmbyGiNI3v3wGv3mz9W+cxEDYB/6jbnj6GM9H9mK3wIL8ftgl+C07Lcwb8PG5PCCPzA==} 446 | engines: {node: ^10 || ^12 || >=14} 447 | hasBin: true 448 | peerDependencies: 449 | postcss: ^8.1.0 450 | dependencies: 451 | browserslist: 4.20.2 452 | caniuse-lite: 1.0.30001513 453 | fraction.js: 4.2.0 454 | normalize-range: 0.1.2 455 | picocolors: 1.0.0 456 | postcss: 8.4.25 457 | postcss-value-parser: 4.2.0 458 | dev: true 459 | 460 | /axios@1.4.0: 461 | resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==} 462 | dependencies: 463 | follow-redirects: 1.15.2 464 | form-data: 4.0.0 465 | proxy-from-env: 1.1.0 466 | transitivePeerDependencies: 467 | - debug 468 | dev: false 469 | 470 | /balanced-match@1.0.2: 471 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 472 | 473 | /binary-extensions@2.2.0: 474 | resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} 475 | engines: {node: '>=8'} 476 | 477 | /brace-expansion@1.1.11: 478 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 479 | dependencies: 480 | balanced-match: 1.0.2 481 | concat-map: 0.0.1 482 | 483 | /brace-expansion@2.0.1: 484 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 485 | dependencies: 486 | balanced-match: 1.0.2 487 | dev: false 488 | 489 | /braces@3.0.2: 490 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} 491 | engines: {node: '>=8'} 492 | dependencies: 493 | fill-range: 7.0.1 494 | 495 | /browserslist@4.20.2: 496 | resolution: {integrity: sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==} 497 | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 498 | hasBin: true 499 | dependencies: 500 | caniuse-lite: 1.0.30001513 501 | electron-to-chromium: 1.4.86 502 | escalade: 3.1.1 503 | node-releases: 2.0.2 504 | picocolors: 1.0.0 505 | dev: true 506 | 507 | /busboy@1.6.0: 508 | resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} 509 | engines: {node: '>=10.16.0'} 510 | dependencies: 511 | streamsearch: 1.1.0 512 | dev: false 513 | 514 | /camelcase-css@2.0.1: 515 | resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} 516 | engines: {node: '>= 6'} 517 | 518 | /caniuse-lite@1.0.30001513: 519 | resolution: {integrity: sha512-pnjGJo7SOOjAGytZZ203Em95MRM8Cr6jhCXNF/FAXTpCTRTECnqQWLpiTRqrFtdYcth8hf4WECUpkezuYsMVww==} 520 | 521 | /chokidar@3.5.3: 522 | resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} 523 | engines: {node: '>= 8.10.0'} 524 | dependencies: 525 | anymatch: 3.1.2 526 | braces: 3.0.2 527 | glob-parent: 5.1.2 528 | is-binary-path: 2.1.0 529 | is-glob: 4.0.3 530 | normalize-path: 3.0.0 531 | readdirp: 3.6.0 532 | optionalDependencies: 533 | fsevents: 2.3.2 534 | 535 | /client-only@0.0.1: 536 | resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} 537 | dev: false 538 | 539 | /clsx@1.2.1: 540 | resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} 541 | engines: {node: '>=6'} 542 | dev: false 543 | 544 | /combined-stream@1.0.8: 545 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} 546 | engines: {node: '>= 0.8'} 547 | dependencies: 548 | delayed-stream: 1.0.0 549 | dev: false 550 | 551 | /commander@2.20.3: 552 | resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} 553 | dev: false 554 | 555 | /commander@4.1.1: 556 | resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} 557 | engines: {node: '>= 6'} 558 | 559 | /concat-map@0.0.1: 560 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 561 | 562 | /condense-newlines@0.2.1: 563 | resolution: {integrity: sha512-P7X+QL9Hb9B/c8HI5BFFKmjgBu2XpQuF98WZ9XkO+dBGgk5XgwiQz7o1SmpglNWId3581UcS0SFAWfoIhMHPfg==} 564 | engines: {node: '>=0.10.0'} 565 | dependencies: 566 | extend-shallow: 2.0.1 567 | is-whitespace: 0.3.0 568 | kind-of: 3.2.2 569 | dev: false 570 | 571 | /config-chain@1.1.13: 572 | resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} 573 | dependencies: 574 | ini: 1.3.8 575 | proto-list: 1.2.4 576 | dev: false 577 | 578 | /cssesc@3.0.0: 579 | resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} 580 | engines: {node: '>=4'} 581 | hasBin: true 582 | 583 | /csstype@3.0.10: 584 | resolution: {integrity: sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==} 585 | 586 | /dayjs@1.11.9: 587 | resolution: {integrity: sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==} 588 | dev: false 589 | 590 | /deepmerge@4.3.1: 591 | resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} 592 | engines: {node: '>=0.10.0'} 593 | dev: false 594 | 595 | /delayed-stream@1.0.0: 596 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} 597 | engines: {node: '>=0.4.0'} 598 | dev: false 599 | 600 | /didyoumean@1.2.2: 601 | resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} 602 | 603 | /dlv@1.1.3: 604 | resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} 605 | 606 | /dom-serializer@2.0.0: 607 | resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} 608 | dependencies: 609 | domelementtype: 2.3.0 610 | domhandler: 5.0.3 611 | entities: 4.5.0 612 | dev: false 613 | 614 | /domelementtype@2.3.0: 615 | resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} 616 | dev: false 617 | 618 | /domhandler@5.0.3: 619 | resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} 620 | engines: {node: '>= 4'} 621 | dependencies: 622 | domelementtype: 2.3.0 623 | dev: false 624 | 625 | /domutils@3.1.0: 626 | resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} 627 | dependencies: 628 | dom-serializer: 2.0.0 629 | domelementtype: 2.3.0 630 | domhandler: 5.0.3 631 | dev: false 632 | 633 | /editorconfig@0.15.3: 634 | resolution: {integrity: sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==} 635 | hasBin: true 636 | dependencies: 637 | commander: 2.20.3 638 | lru-cache: 4.1.5 639 | semver: 5.7.1 640 | sigmund: 1.0.1 641 | dev: false 642 | 643 | /electron-to-chromium@1.4.86: 644 | resolution: {integrity: sha512-EVTZ+igi8x63pK4bPuA95PXIs2b2Cowi3WQwI9f9qManLiZJOD1Lash1J3W4TvvcUCcIR4o/rgi9o8UicXSO+w==} 645 | dev: true 646 | 647 | /entities@4.5.0: 648 | resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} 649 | engines: {node: '>=0.12'} 650 | dev: false 651 | 652 | /escalade@3.1.1: 653 | resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} 654 | engines: {node: '>=6'} 655 | dev: true 656 | 657 | /extend-shallow@2.0.1: 658 | resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} 659 | engines: {node: '>=0.10.0'} 660 | dependencies: 661 | is-extendable: 0.1.1 662 | dev: false 663 | 664 | /fast-glob@3.3.0: 665 | resolution: {integrity: sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==} 666 | engines: {node: '>=8.6.0'} 667 | dependencies: 668 | '@nodelib/fs.stat': 2.0.5 669 | '@nodelib/fs.walk': 1.2.8 670 | glob-parent: 5.1.2 671 | merge2: 1.4.1 672 | micromatch: 4.0.5 673 | 674 | /fastq@1.13.0: 675 | resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} 676 | dependencies: 677 | reusify: 1.0.4 678 | 679 | /fill-range@7.0.1: 680 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} 681 | engines: {node: '>=8'} 682 | dependencies: 683 | to-regex-range: 5.0.1 684 | 685 | /follow-redirects@1.15.2: 686 | resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} 687 | engines: {node: '>=4.0'} 688 | peerDependencies: 689 | debug: '*' 690 | peerDependenciesMeta: 691 | debug: 692 | optional: true 693 | dev: false 694 | 695 | /form-data@4.0.0: 696 | resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} 697 | engines: {node: '>= 6'} 698 | dependencies: 699 | asynckit: 0.4.0 700 | combined-stream: 1.0.8 701 | mime-types: 2.1.35 702 | dev: false 703 | 704 | /fraction.js@4.2.0: 705 | resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} 706 | dev: true 707 | 708 | /fs.realpath@1.0.0: 709 | resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} 710 | 711 | /fsevents@2.3.2: 712 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} 713 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 714 | os: [darwin] 715 | requiresBuild: true 716 | optional: true 717 | 718 | /function-bind@1.1.1: 719 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} 720 | 721 | /glob-parent@5.1.2: 722 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 723 | engines: {node: '>= 6'} 724 | dependencies: 725 | is-glob: 4.0.3 726 | 727 | /glob-parent@6.0.2: 728 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 729 | engines: {node: '>=10.13.0'} 730 | dependencies: 731 | is-glob: 4.0.3 732 | 733 | /glob-to-regexp@0.4.1: 734 | resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} 735 | dev: false 736 | 737 | /glob@7.1.6: 738 | resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} 739 | dependencies: 740 | fs.realpath: 1.0.0 741 | inflight: 1.0.6 742 | inherits: 2.0.4 743 | minimatch: 3.1.2 744 | once: 1.4.0 745 | path-is-absolute: 1.0.1 746 | 747 | /glob@8.1.0: 748 | resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} 749 | engines: {node: '>=12'} 750 | dependencies: 751 | fs.realpath: 1.0.0 752 | inflight: 1.0.6 753 | inherits: 2.0.4 754 | minimatch: 5.1.6 755 | once: 1.4.0 756 | dev: false 757 | 758 | /goober@2.1.13(csstype@3.0.10): 759 | resolution: {integrity: sha512-jFj3BQeleOoy7t93E9rZ2de+ScC4lQICLwiAQmKMg9F6roKGaLSHoCDYKkWlSafg138jejvq/mTdvmnwDQgqoQ==} 760 | peerDependencies: 761 | csstype: ^3.0.10 762 | dependencies: 763 | csstype: 3.0.10 764 | dev: false 765 | 766 | /graceful-fs@4.2.11: 767 | resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 768 | dev: false 769 | 770 | /has@1.0.3: 771 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} 772 | engines: {node: '>= 0.4.0'} 773 | dependencies: 774 | function-bind: 1.1.1 775 | 776 | /html-to-text@9.0.3: 777 | resolution: {integrity: sha512-hxDF1kVCF2uw4VUJ3vr2doc91pXf2D5ngKcNviSitNkhP9OMOaJkDrFIFL6RMvko7NisWTEiqGpQ9LAxcVok1w==} 778 | engines: {node: '>=14'} 779 | dependencies: 780 | '@selderee/plugin-htmlparser2': 0.10.0 781 | deepmerge: 4.3.1 782 | dom-serializer: 2.0.0 783 | htmlparser2: 8.0.2 784 | selderee: 0.10.0 785 | dev: false 786 | 787 | /htmlparser2@8.0.2: 788 | resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} 789 | dependencies: 790 | domelementtype: 2.3.0 791 | domhandler: 5.0.3 792 | domutils: 3.1.0 793 | entities: 4.5.0 794 | dev: false 795 | 796 | /inflight@1.0.6: 797 | resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} 798 | dependencies: 799 | once: 1.4.0 800 | wrappy: 1.0.2 801 | 802 | /inherits@2.0.4: 803 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 804 | 805 | /ini@1.3.8: 806 | resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} 807 | dev: false 808 | 809 | /is-binary-path@2.1.0: 810 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 811 | engines: {node: '>=8'} 812 | dependencies: 813 | binary-extensions: 2.2.0 814 | 815 | /is-buffer@1.1.6: 816 | resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} 817 | dev: false 818 | 819 | /is-core-module@2.12.1: 820 | resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==} 821 | dependencies: 822 | has: 1.0.3 823 | 824 | /is-extendable@0.1.1: 825 | resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} 826 | engines: {node: '>=0.10.0'} 827 | dev: false 828 | 829 | /is-extglob@2.1.1: 830 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 831 | engines: {node: '>=0.10.0'} 832 | 833 | /is-glob@4.0.3: 834 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 835 | engines: {node: '>=0.10.0'} 836 | dependencies: 837 | is-extglob: 2.1.1 838 | 839 | /is-number@7.0.0: 840 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 841 | engines: {node: '>=0.12.0'} 842 | 843 | /is-whitespace@0.3.0: 844 | resolution: {integrity: sha512-RydPhl4S6JwAyj0JJjshWJEFG6hNye3pZFBRZaTUfZFwGHxzppNaNOVgQuS/E/SlhrApuMXrpnK1EEIXfdo3Dg==} 845 | engines: {node: '>=0.10.0'} 846 | dev: false 847 | 848 | /jiti@1.19.1: 849 | resolution: {integrity: sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==} 850 | hasBin: true 851 | 852 | /js-beautify@1.14.8: 853 | resolution: {integrity: sha512-4S7HFeI9YfRvRgKnEweohs0tgJj28InHVIj4Nl8Htf96Y6pHg3+tJrmo4ucAM9f7l4SHbFI3IvFAZ2a1eQPbyg==} 854 | engines: {node: '>=12'} 855 | hasBin: true 856 | dependencies: 857 | config-chain: 1.1.13 858 | editorconfig: 0.15.3 859 | glob: 8.1.0 860 | nopt: 6.0.0 861 | dev: false 862 | 863 | /js-tokens@4.0.0: 864 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 865 | dev: false 866 | 867 | /kind-of@3.2.2: 868 | resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} 869 | engines: {node: '>=0.10.0'} 870 | dependencies: 871 | is-buffer: 1.1.6 872 | dev: false 873 | 874 | /leac@0.6.0: 875 | resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==} 876 | dev: false 877 | 878 | /lilconfig@2.1.0: 879 | resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} 880 | engines: {node: '>=10'} 881 | 882 | /lines-and-columns@1.1.6: 883 | resolution: {integrity: sha512-8ZmlJFVK9iCmtLz19HpSsR8HaAMWBT284VMNednLwlIMDP2hJDCIhUp0IZ2xUcZ+Ob6BM0VvCSJwzASDM45NLQ==} 884 | 885 | /loose-envify@1.4.0: 886 | resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} 887 | hasBin: true 888 | dependencies: 889 | js-tokens: 4.0.0 890 | dev: false 891 | 892 | /lru-cache@4.1.5: 893 | resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} 894 | dependencies: 895 | pseudomap: 1.0.2 896 | yallist: 2.1.2 897 | dev: false 898 | 899 | /merge2@1.4.1: 900 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 901 | engines: {node: '>= 8'} 902 | 903 | /micromatch@4.0.5: 904 | resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} 905 | engines: {node: '>=8.6'} 906 | dependencies: 907 | braces: 3.0.2 908 | picomatch: 2.3.1 909 | 910 | /mime-db@1.52.0: 911 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} 912 | engines: {node: '>= 0.6'} 913 | dev: false 914 | 915 | /mime-types@2.1.35: 916 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} 917 | engines: {node: '>= 0.6'} 918 | dependencies: 919 | mime-db: 1.52.0 920 | dev: false 921 | 922 | /minimatch@3.1.2: 923 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 924 | dependencies: 925 | brace-expansion: 1.1.11 926 | 927 | /minimatch@5.1.6: 928 | resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} 929 | engines: {node: '>=10'} 930 | dependencies: 931 | brace-expansion: 2.0.1 932 | dev: false 933 | 934 | /mz@2.7.0: 935 | resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} 936 | dependencies: 937 | any-promise: 1.3.0 938 | object-assign: 4.1.1 939 | thenify-all: 1.6.0 940 | 941 | /nanoid@3.3.6: 942 | resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} 943 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 944 | hasBin: true 945 | 946 | /nanoid@4.0.2: 947 | resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==} 948 | engines: {node: ^14 || ^16 || >=18} 949 | hasBin: true 950 | dev: false 951 | 952 | /next-seo@6.1.0(next@13.4.9)(react-dom@18.2.0)(react@18.2.0): 953 | resolution: {integrity: sha512-iMBpFoJsR5zWhguHJvsoBDxDSmdYTHtnVPB1ij+CD0NReQCP78ZxxbdL9qkKIf4oEuZEqZkrjAQLB0bkII7RYA==} 954 | peerDependencies: 955 | next: ^8.1.1-canary.54 || >=9.0.0 956 | react: '>=16.0.0' 957 | react-dom: '>=16.0.0' 958 | dependencies: 959 | next: 13.4.9(react-dom@18.2.0)(react@18.2.0) 960 | react: 18.2.0 961 | react-dom: 18.2.0(react@18.2.0) 962 | dev: false 963 | 964 | /next@13.4.9(react-dom@18.2.0)(react@18.2.0): 965 | resolution: {integrity: sha512-vtefFm/BWIi/eWOqf1GsmKG3cjKw1k3LjuefKRcL3iiLl3zWzFdPG3as6xtxrGO6gwTzzaO1ktL4oiHt/uvTjA==} 966 | engines: {node: '>=16.8.0'} 967 | hasBin: true 968 | peerDependencies: 969 | '@opentelemetry/api': ^1.1.0 970 | fibers: '>= 3.1.0' 971 | react: ^18.2.0 972 | react-dom: ^18.2.0 973 | sass: ^1.3.0 974 | peerDependenciesMeta: 975 | '@opentelemetry/api': 976 | optional: true 977 | fibers: 978 | optional: true 979 | sass: 980 | optional: true 981 | dependencies: 982 | '@next/env': 13.4.9 983 | '@swc/helpers': 0.5.1 984 | busboy: 1.6.0 985 | caniuse-lite: 1.0.30001513 986 | postcss: 8.4.14 987 | react: 18.2.0 988 | react-dom: 18.2.0(react@18.2.0) 989 | styled-jsx: 5.1.1(react@18.2.0) 990 | watchpack: 2.4.0 991 | zod: 3.21.4 992 | optionalDependencies: 993 | '@next/swc-darwin-arm64': 13.4.9 994 | '@next/swc-darwin-x64': 13.4.9 995 | '@next/swc-linux-arm64-gnu': 13.4.9 996 | '@next/swc-linux-arm64-musl': 13.4.9 997 | '@next/swc-linux-x64-gnu': 13.4.9 998 | '@next/swc-linux-x64-musl': 13.4.9 999 | '@next/swc-win32-arm64-msvc': 13.4.9 1000 | '@next/swc-win32-ia32-msvc': 13.4.9 1001 | '@next/swc-win32-x64-msvc': 13.4.9 1002 | transitivePeerDependencies: 1003 | - '@babel/core' 1004 | - babel-plugin-macros 1005 | dev: false 1006 | 1007 | /node-releases@2.0.2: 1008 | resolution: {integrity: sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==} 1009 | dev: true 1010 | 1011 | /nopt@6.0.0: 1012 | resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} 1013 | engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} 1014 | hasBin: true 1015 | dependencies: 1016 | abbrev: 1.1.1 1017 | dev: false 1018 | 1019 | /normalize-path@3.0.0: 1020 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 1021 | engines: {node: '>=0.10.0'} 1022 | 1023 | /normalize-range@0.1.2: 1024 | resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} 1025 | engines: {node: '>=0.10.0'} 1026 | dev: true 1027 | 1028 | /object-assign@4.1.1: 1029 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 1030 | engines: {node: '>=0.10.0'} 1031 | 1032 | /object-hash@3.0.0: 1033 | resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} 1034 | engines: {node: '>= 6'} 1035 | 1036 | /once@1.4.0: 1037 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 1038 | dependencies: 1039 | wrappy: 1.0.2 1040 | 1041 | /parseley@0.11.0: 1042 | resolution: {integrity: sha512-VfcwXlBWgTF+unPcr7yu3HSSA6QUdDaDnrHcytVfj5Z8azAyKBDrYnSIfeSxlrEayndNcLmrXzg+Vxbo6DWRXQ==} 1043 | dependencies: 1044 | leac: 0.6.0 1045 | peberminta: 0.8.0 1046 | dev: false 1047 | 1048 | /path-is-absolute@1.0.1: 1049 | resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} 1050 | engines: {node: '>=0.10.0'} 1051 | 1052 | /path-parse@1.0.7: 1053 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1054 | 1055 | /peberminta@0.8.0: 1056 | resolution: {integrity: sha512-YYEs+eauIjDH5nUEGi18EohWE0nV2QbGTqmxQcqgZ/0g+laPCQmuIqq7EBLVi9uim9zMgfJv0QBZEnQ3uHw/Tw==} 1057 | dev: false 1058 | 1059 | /picocolors@1.0.0: 1060 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 1061 | 1062 | /picomatch@2.3.1: 1063 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1064 | engines: {node: '>=8.6'} 1065 | 1066 | /pify@2.3.0: 1067 | resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} 1068 | engines: {node: '>=0.10.0'} 1069 | 1070 | /pirates@4.0.6: 1071 | resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} 1072 | engines: {node: '>= 6'} 1073 | 1074 | /postcss-import@15.1.0(postcss@8.4.25): 1075 | resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} 1076 | engines: {node: '>=14.0.0'} 1077 | peerDependencies: 1078 | postcss: ^8.0.0 1079 | dependencies: 1080 | postcss: 8.4.25 1081 | postcss-value-parser: 4.2.0 1082 | read-cache: 1.0.0 1083 | resolve: 1.22.2 1084 | 1085 | /postcss-js@4.0.1(postcss@8.4.25): 1086 | resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} 1087 | engines: {node: ^12 || ^14 || >= 16} 1088 | peerDependencies: 1089 | postcss: ^8.4.21 1090 | dependencies: 1091 | camelcase-css: 2.0.1 1092 | postcss: 8.4.25 1093 | 1094 | /postcss-load-config@4.0.1(postcss@8.4.25): 1095 | resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==} 1096 | engines: {node: '>= 14'} 1097 | peerDependencies: 1098 | postcss: '>=8.0.9' 1099 | ts-node: '>=9.0.0' 1100 | peerDependenciesMeta: 1101 | postcss: 1102 | optional: true 1103 | ts-node: 1104 | optional: true 1105 | dependencies: 1106 | lilconfig: 2.1.0 1107 | postcss: 8.4.25 1108 | yaml: 2.1.1 1109 | 1110 | /postcss-nested@6.0.1(postcss@8.4.25): 1111 | resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} 1112 | engines: {node: '>=12.0'} 1113 | peerDependencies: 1114 | postcss: ^8.2.14 1115 | dependencies: 1116 | postcss: 8.4.25 1117 | postcss-selector-parser: 6.0.13 1118 | 1119 | /postcss-selector-parser@6.0.13: 1120 | resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} 1121 | engines: {node: '>=4'} 1122 | dependencies: 1123 | cssesc: 3.0.0 1124 | util-deprecate: 1.0.2 1125 | 1126 | /postcss-value-parser@4.2.0: 1127 | resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} 1128 | 1129 | /postcss@8.4.14: 1130 | resolution: {integrity: sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==} 1131 | engines: {node: ^10 || ^12 || >=14} 1132 | dependencies: 1133 | nanoid: 3.3.6 1134 | picocolors: 1.0.0 1135 | source-map-js: 1.0.2 1136 | dev: false 1137 | 1138 | /postcss@8.4.25: 1139 | resolution: {integrity: sha512-7taJ/8t2av0Z+sQEvNzCkpDynl0tX3uJMCODi6nT3PfASC7dYCWV9aQ+uiCf+KBD4SEFcu+GvJdGdwzQ6OSjCw==} 1140 | engines: {node: ^10 || ^12 || >=14} 1141 | dependencies: 1142 | nanoid: 3.3.6 1143 | picocolors: 1.0.0 1144 | source-map-js: 1.0.2 1145 | 1146 | /prettier@3.0.0: 1147 | resolution: {integrity: sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==} 1148 | engines: {node: '>=14'} 1149 | hasBin: true 1150 | dev: true 1151 | 1152 | /pretty@2.0.0: 1153 | resolution: {integrity: sha512-G9xUchgTEiNpormdYBl+Pha50gOUovT18IvAe7EYMZ1/f9W/WWMPRn+xI68yXNMUk3QXHDwo/1wV/4NejVNe1w==} 1154 | engines: {node: '>=0.10.0'} 1155 | dependencies: 1156 | condense-newlines: 0.2.1 1157 | extend-shallow: 2.0.1 1158 | js-beautify: 1.14.8 1159 | dev: false 1160 | 1161 | /prisma@4.16.2: 1162 | resolution: {integrity: sha512-SYCsBvDf0/7XSJyf2cHTLjLeTLVXYfqp7pG5eEVafFLeT0u/hLFz/9W196nDRGUOo1JfPatAEb+uEnTQImQC1g==} 1163 | engines: {node: '>=14.17'} 1164 | hasBin: true 1165 | requiresBuild: true 1166 | dependencies: 1167 | '@prisma/engines': 4.16.2 1168 | 1169 | /proto-list@1.2.4: 1170 | resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} 1171 | dev: false 1172 | 1173 | /proxy-from-env@1.1.0: 1174 | resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} 1175 | dev: false 1176 | 1177 | /pseudomap@1.0.2: 1178 | resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} 1179 | dev: false 1180 | 1181 | /queue-microtask@1.2.3: 1182 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1183 | 1184 | /react-dom@18.2.0(react@18.2.0): 1185 | resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} 1186 | peerDependencies: 1187 | react: ^18.2.0 1188 | dependencies: 1189 | loose-envify: 1.4.0 1190 | react: 18.2.0 1191 | scheduler: 0.23.0 1192 | dev: false 1193 | 1194 | /react-hook-form@7.45.1(react@18.2.0): 1195 | resolution: {integrity: sha512-6dWoFJwycbuFfw/iKMcl+RdAOAOHDiF11KWYhNDRN/OkUt+Di5qsZHwA0OwsVnu9y135gkHpTw9DJA+WzCeR9w==} 1196 | engines: {node: '>=12.22.0'} 1197 | peerDependencies: 1198 | react: ^16.8.0 || ^17 || ^18 1199 | dependencies: 1200 | react: 18.2.0 1201 | dev: false 1202 | 1203 | /react-hot-toast@2.4.1(csstype@3.0.10)(react-dom@18.2.0)(react@18.2.0): 1204 | resolution: {integrity: sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==} 1205 | engines: {node: '>=10'} 1206 | peerDependencies: 1207 | react: '>=16' 1208 | react-dom: '>=16' 1209 | dependencies: 1210 | goober: 2.1.13(csstype@3.0.10) 1211 | react: 18.2.0 1212 | react-dom: 18.2.0(react@18.2.0) 1213 | transitivePeerDependencies: 1214 | - csstype 1215 | dev: false 1216 | 1217 | /react-ssr-prepass@1.5.0(react@18.2.0): 1218 | resolution: {integrity: sha512-yFNHrlVEReVYKsLI5lF05tZoHveA5pGzjFbFJY/3pOqqjGOmMmqx83N4hIjN2n6E1AOa+eQEUxs3CgRnPmT0RQ==} 1219 | peerDependencies: 1220 | react: ^16.8.0 || ^17.0.0 || ^18.0.0 1221 | dependencies: 1222 | react: 18.2.0 1223 | dev: false 1224 | 1225 | /react@18.2.0: 1226 | resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} 1227 | engines: {node: '>=0.10.0'} 1228 | dependencies: 1229 | loose-envify: 1.4.0 1230 | dev: false 1231 | 1232 | /read-cache@1.0.0: 1233 | resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} 1234 | dependencies: 1235 | pify: 2.3.0 1236 | 1237 | /readdirp@3.6.0: 1238 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 1239 | engines: {node: '>=8.10.0'} 1240 | dependencies: 1241 | picomatch: 2.3.1 1242 | 1243 | /regenerator-runtime@0.13.11: 1244 | resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} 1245 | dev: false 1246 | 1247 | /resend@0.16.0: 1248 | resolution: {integrity: sha512-6NnrtEapGD6FtnhRUrtDdfgQFH2av5cTkrnElUh6AjTzGrHXiMpD/GRwT46pqpA6i/AXSDXKV7Wh/hHQJLKFew==} 1249 | dependencies: 1250 | '@react-email/render': 0.0.7 1251 | axios: 1.4.0 1252 | transitivePeerDependencies: 1253 | - debug 1254 | dev: false 1255 | 1256 | /resolve@1.22.2: 1257 | resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} 1258 | hasBin: true 1259 | dependencies: 1260 | is-core-module: 2.12.1 1261 | path-parse: 1.0.7 1262 | supports-preserve-symlinks-flag: 1.0.0 1263 | 1264 | /reusify@1.0.4: 1265 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 1266 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1267 | 1268 | /run-parallel@1.2.0: 1269 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1270 | dependencies: 1271 | queue-microtask: 1.2.3 1272 | 1273 | /scheduler@0.23.0: 1274 | resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} 1275 | dependencies: 1276 | loose-envify: 1.4.0 1277 | dev: false 1278 | 1279 | /selderee@0.10.0: 1280 | resolution: {integrity: sha512-DEL/RW/f4qLw/NrVg97xKaEBC8IpzIG2fvxnzCp3Z4yk4jQ3MXom+Imav9wApjxX2dfS3eW7x0DXafJr85i39A==} 1281 | dependencies: 1282 | parseley: 0.11.0 1283 | dev: false 1284 | 1285 | /semver@5.7.1: 1286 | resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} 1287 | hasBin: true 1288 | dev: false 1289 | 1290 | /sigmund@1.0.1: 1291 | resolution: {integrity: sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==} 1292 | dev: false 1293 | 1294 | /source-map-js@1.0.2: 1295 | resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} 1296 | engines: {node: '>=0.10.0'} 1297 | 1298 | /streamsearch@1.1.0: 1299 | resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} 1300 | engines: {node: '>=10.0.0'} 1301 | dev: false 1302 | 1303 | /styled-jsx@5.1.1(react@18.2.0): 1304 | resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} 1305 | engines: {node: '>= 12.0.0'} 1306 | peerDependencies: 1307 | '@babel/core': '*' 1308 | babel-plugin-macros: '*' 1309 | react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' 1310 | peerDependenciesMeta: 1311 | '@babel/core': 1312 | optional: true 1313 | babel-plugin-macros: 1314 | optional: true 1315 | dependencies: 1316 | client-only: 0.0.1 1317 | react: 18.2.0 1318 | dev: false 1319 | 1320 | /sucrase@3.32.0: 1321 | resolution: {integrity: sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==} 1322 | engines: {node: '>=8'} 1323 | hasBin: true 1324 | dependencies: 1325 | '@jridgewell/gen-mapping': 0.3.3 1326 | commander: 4.1.1 1327 | glob: 7.1.6 1328 | lines-and-columns: 1.1.6 1329 | mz: 2.7.0 1330 | pirates: 4.0.6 1331 | ts-interface-checker: 0.1.13 1332 | 1333 | /supports-preserve-symlinks-flag@1.0.0: 1334 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1335 | engines: {node: '>= 0.4'} 1336 | 1337 | /tailwind-merge@1.13.2: 1338 | resolution: {integrity: sha512-R2/nULkdg1VR/EL4RXg4dEohdoxNUJGLMnWIQnPKL+O9Twu7Cn3Rxi4dlXkDzZrEGtR+G+psSXFouWlpTyLhCQ==} 1339 | dev: false 1340 | 1341 | /tailwind-variants@0.1.10(tailwindcss@3.3.2): 1342 | resolution: {integrity: sha512-PlOoXweMcOt2TXYr01lZ8iuRJG3M3voiWdAIb1vSqmuGuLvjtJwGphmwPToHRLXebC0dnKXow/xz2gRShCqI9w==} 1343 | engines: {node: '>=16.x', pnpm: '>=7.x'} 1344 | peerDependencies: 1345 | tailwindcss: '*' 1346 | dependencies: 1347 | tailwind-merge: 1.13.2 1348 | tailwindcss: 3.3.2 1349 | dev: false 1350 | 1351 | /tailwindcss@3.3.2: 1352 | resolution: {integrity: sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==} 1353 | engines: {node: '>=14.0.0'} 1354 | hasBin: true 1355 | dependencies: 1356 | '@alloc/quick-lru': 5.2.0 1357 | arg: 5.0.2 1358 | chokidar: 3.5.3 1359 | didyoumean: 1.2.2 1360 | dlv: 1.1.3 1361 | fast-glob: 3.3.0 1362 | glob-parent: 6.0.2 1363 | is-glob: 4.0.3 1364 | jiti: 1.19.1 1365 | lilconfig: 2.1.0 1366 | micromatch: 4.0.5 1367 | normalize-path: 3.0.0 1368 | object-hash: 3.0.0 1369 | picocolors: 1.0.0 1370 | postcss: 8.4.25 1371 | postcss-import: 15.1.0(postcss@8.4.25) 1372 | postcss-js: 4.0.1(postcss@8.4.25) 1373 | postcss-load-config: 4.0.1(postcss@8.4.25) 1374 | postcss-nested: 6.0.1(postcss@8.4.25) 1375 | postcss-selector-parser: 6.0.13 1376 | postcss-value-parser: 4.2.0 1377 | resolve: 1.22.2 1378 | sucrase: 3.32.0 1379 | transitivePeerDependencies: 1380 | - ts-node 1381 | 1382 | /thenify-all@1.6.0: 1383 | resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} 1384 | engines: {node: '>=0.8'} 1385 | dependencies: 1386 | thenify: 3.3.1 1387 | 1388 | /thenify@3.3.1: 1389 | resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} 1390 | dependencies: 1391 | any-promise: 1.3.0 1392 | 1393 | /to-regex-range@5.0.1: 1394 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1395 | engines: {node: '>=8.0'} 1396 | dependencies: 1397 | is-number: 7.0.0 1398 | 1399 | /ts-interface-checker@0.1.13: 1400 | resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} 1401 | 1402 | /tslib@2.4.0: 1403 | resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} 1404 | dev: false 1405 | 1406 | /typescript@5.1.6: 1407 | resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} 1408 | engines: {node: '>=14.17'} 1409 | hasBin: true 1410 | dev: true 1411 | 1412 | /use-sync-external-store@1.2.0(react@18.2.0): 1413 | resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} 1414 | peerDependencies: 1415 | react: ^16.8.0 || ^17.0.0 || ^18.0.0 1416 | dependencies: 1417 | react: 18.2.0 1418 | dev: false 1419 | 1420 | /util-deprecate@1.0.2: 1421 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} 1422 | 1423 | /watchpack@2.4.0: 1424 | resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} 1425 | engines: {node: '>=10.13.0'} 1426 | dependencies: 1427 | glob-to-regexp: 0.4.1 1428 | graceful-fs: 4.2.11 1429 | dev: false 1430 | 1431 | /wrappy@1.0.2: 1432 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 1433 | 1434 | /yallist@2.1.2: 1435 | resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} 1436 | dev: false 1437 | 1438 | /yaml@2.1.1: 1439 | resolution: {integrity: sha512-o96x3OPo8GjWeSLF+wOAbrPfhFOGY0W00GNaxCDv+9hkcDJEnev1yh8S7pgHF0ik6zc8sQLuL8hjHjJULZp8bw==} 1440 | engines: {node: '>= 14'} 1441 | 1442 | /zod@3.21.4: 1443 | resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==} 1444 | dev: false 1445 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - apps/* 3 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | --------------------------------------------------------------------------------