intentionally break post rendering

This commit is contained in:
Max Leiter 2022-12-16 11:49:10 -08:00
parent 70212232a0
commit 350575ccd4
14 changed files with 248 additions and 188 deletions

View file

@ -59,7 +59,7 @@ export const PostButtons = ({
> >
Edit a Copy Edit a Copy
</Button> </Button>
{viewParentClick && ( {parentId && (
<Button iconLeft={<ArrowUpCircle />} onClick={viewParentClick}> <Button iconLeft={<ArrowUpCircle />} onClick={viewParentClick}>
View Parent View Parent
</Button> </Button>

View file

@ -44,9 +44,11 @@ export const PostTitle = ({
)} )}
{loading && ( {loading && (
<span className={styles.badges}> <span className={styles.badges}>
<div style={{ display: "flex", alignItems: "center" }}>
<Skeleton width={100} height={20} /> <Skeleton width={100} height={20} />
<Skeleton width={100} height={20} /> <Skeleton width={100} height={20} />
<Skeleton width={100} height={20} /> <Skeleton width={100} height={20} />
</div>
</span> </span>
)} )}
</span> </span>

View file

@ -6,6 +6,7 @@ import { useEffect, useState } from "react"
import { useRouter } from "next/navigation" import { useRouter } from "next/navigation"
import PasswordModalPage from "./password-modal-wrapper" import PasswordModalPage from "./password-modal-wrapper"
import { File, PostWithFilesAndAuthor } from "@lib/server/prisma" import { File, PostWithFilesAndAuthor } from "@lib/server/prisma"
import { useSession } from "next-auth/react"
type Props = { type Props = {
post: string | PostWithFilesAndAuthor post: string | PostWithFilesAndAuthor
@ -13,11 +14,16 @@ type Props = {
isAuthor?: boolean isAuthor?: boolean
} }
const PostPage = ({ post: initialPost, isProtected, isAuthor }: Props) => { const PostPage = ({ post: initialPost, isProtected, isAuthor: isAuthorFromServer }: Props) => {
const { data: session } = useSession()
const [post, setPost] = useState<PostWithFilesAndAuthor>( const [post, setPost] = useState<PostWithFilesAndAuthor>(
typeof initialPost === "string" ? JSON.parse(initialPost) : initialPost typeof initialPost === "string" ? JSON.parse(initialPost) : initialPost
) )
// We generate public and unlisted posts at build time, so we can't use
// the session to determine if the user is the author on the server. We need to check
// the post's authorId against the session's user id.
const isAuthor = isAuthorFromServer ? true : session?.user?.id === post?.authorId;
const router = useRouter() const router = useRouter()
useEffect(() => { useEffect(() => {

View file

@ -1,6 +1,6 @@
import PostPage from "./components/post-page" import PostPage from "./components/post-page"
import { notFound, redirect } from "next/navigation" import { notFound, redirect } from "next/navigation"
import { getPostById, Post, PostWithFilesAndAuthor } from "@lib/server/prisma" import { getAllPosts, getPostById, Post, PostWithFilesAndAuthor } from "@lib/server/prisma"
import { getCurrentUser } from "@lib/server/session" import { getCurrentUser } from "@lib/server/session"
import ScrollToTop from "@components/scroll-to-top" import ScrollToTop from "@components/scroll-to-top"
import { title } from "process" import { title } from "process"
@ -14,19 +14,21 @@ export type PostProps = {
isProtected?: boolean isProtected?: boolean
} }
// export async function generateStaticParams() { export async function generateStaticParams() {
// const posts = await getAllPosts({ const posts = await getAllPosts({
// where: { where: {
// visibility: { visibility: {
// equals: "public" equals: "public"
// } }
// } }
// }) })
// return posts.map((post) => ({ return posts.map((post) => ({
// id: post.id id: post.id
// })) }))
// } }
export const dynamic = 'error';
const fetchOptions = { const fetchOptions = {
withFiles: true, withFiles: true,
@ -40,19 +42,16 @@ const getPost = async (id: string) => {
return notFound() return notFound()
} }
if (post.visibility === "public" || post.visibility === "unlisted") {
return { post }
}
const user = await getCurrentUser() const user = await getCurrentUser()
const isAuthorOrAdmin = user?.id === post?.authorId || user?.role === "admin" const isAuthorOrAdmin = user?.id === post?.authorId || user?.role === "admin"
if (post.visibility === "public") {
return { post, isAuthor: isAuthorOrAdmin }
}
if (post.visibility === "private" && !isAuthorOrAdmin) { if (post.visibility === "private" && !isAuthorOrAdmin) {
return notFound() return redirect("/signin")
}
if (post.visibility === "private" && !isAuthorOrAdmin) {
return notFound()
} }
if (post.visibility === "protected" && !isAuthorOrAdmin) { if (post.visibility === "protected" && !isAuthorOrAdmin) {
@ -64,8 +63,8 @@ const getPost = async (id: string) => {
files: [], files: [],
parentId: "", parentId: "",
title: "", title: "",
createdAt: new Date("1970-01-01"), createdAt: "",
expiresAt: new Date("1970-01-01"), expiresAt: "",
author: { author: {
displayName: "" displayName: ""
}, },
@ -112,7 +111,8 @@ const PostView = async ({
title={post.title} title={post.title}
createdAt={post.createdAt.toString()} createdAt={post.createdAt.toString()}
expiresAt={post.expiresAt?.toString()} expiresAt={post.expiresAt?.toString()}
displayName={post.author?.displayName || ""} // displayName is an optional param
displayName={post.author?.displayName || undefined}
visibility={post.visibility} visibility={post.visibility}
authorId={post.authorId} authorId={post.authorId}
/> />

View file

@ -1,17 +1,22 @@
import React from "react"
import styles from "./badge.module.css" import styles from "./badge.module.css"
type BadgeProps = { type BadgeProps = {
type: "primary" | "secondary" | "error" | "warning" type: "primary" | "secondary" | "error" | "warning"
children: React.ReactNode children: React.ReactNode
} }
const Badge = ({ type, children }: BadgeProps) => { const Badge = React.forwardRef<HTMLDivElement, BadgeProps>(
({ type, children }: BadgeProps, ref) => {
return ( return (
<div className={styles.container}> <div className={styles.container}>
<div className={`${styles.badge} ${styles[type]}`}> <div className={`${styles.badge} ${styles[type]}`} ref={ref}>
<span className={styles.badgeText}>{children}</span> {children}
</div> </div>
</div> </div>
) )
} }
)
Badge.displayName = "Badge"
export default Badge export default Badge

View file

@ -2,11 +2,7 @@
import styles from "./post-list.module.css" import styles from "./post-list.module.css"
import ListItem from "./list-item" import ListItem from "./list-item"
import { import { ChangeEvent, useCallback, useState } from "react"
ChangeEvent,
useCallback,
useState
} from "react"
import Link from "@components/link" import Link from "@components/link"
import type { PostWithFiles } from "@lib/server/prisma" import type { PostWithFiles } from "@lib/server/prisma"
import Input from "@components/input" import Input from "@components/input"
@ -60,7 +56,15 @@ const PostList = ({
[posts, hasMorePosts] [posts, hasMorePosts]
) )
const onSearch = (query: string) => { // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: address this
const onSearch = useCallback(
debounce((query: string) => {
if (!query) {
setPosts(initialPosts)
setSearching(false)
return
}
setSearching(true) setSearching(true)
async function fetchPosts() { async function fetchPosts() {
const res = await fetch( const res = await fetch(
@ -77,14 +81,17 @@ const PostList = ({
setSearching(false) setSearching(false)
} }
fetchPosts() fetchPosts()
} }, 300),
[userId]
)
const debouncedSearch = debounce(onSearch, 500) const onSearchChange = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
const handleSearchChange = (e: ChangeEvent<HTMLInputElement>) => {
setSearchValue(e.target.value) setSearchValue(e.target.value)
debouncedSearch(e.target.value) onSearch(e.target.value)
} },
[onSearch]
)
const deletePost = useCallback( const deletePost = useCallback(
(postId: string) => async () => { (postId: string) => async () => {
@ -108,16 +115,18 @@ const PostList = ({
return ( return (
<div className={styles.container}> <div className={styles.container}>
{!hideSearch && <div className={styles.searchContainer}> {!hideSearch && (
<div className={styles.searchContainer}>
<Input <Input
placeholder="Search..." placeholder="Search..."
onChange={handleSearchChange} onChange={onSearchChange}
disabled={!posts} disabled={!posts}
style={{ maxWidth: 300 }} style={{ maxWidth: 300 }}
aria-label="Search" aria-label="Search"
value={search} value={search}
/> />
</div>} </div>
)}
{!posts && <p style={{ color: "var(--warning)" }}>Failed to load.</p>} {!posts && <p style={{ color: "var(--warning)" }}>Failed to load.</p>}
{searching && ( {searching && (
<ul> <ul>
@ -125,7 +134,7 @@ const PostList = ({
<ListItemSkeleton /> <ListItemSkeleton />
</ul> </ul>
)} )}
{posts?.length === 0 && posts && ( {!searching && posts?.length === 0 && posts && (
<p> <p>
No posts found. Create one{" "} No posts found. Create one{" "}
<Link colored href="/new"> <Link colored href="/new">
@ -134,7 +143,7 @@ const PostList = ({
. .
</p> </p>
)} )}
{posts?.length > 0 && ( {!searching && posts?.length > 0 && (
<div> <div>
<ul> <ul>
{posts.map((post) => { {posts.map((post) => {
@ -149,7 +158,7 @@ const PostList = ({
</ul> </ul>
</div> </div>
)} )}
{hasMorePosts && !setSearchValue && ( {!searching && hasMorePosts && !setSearchValue && (
<div className={styles.moreContainer}> <div className={styles.moreContainer}>
<Button width={"100%"} onClick={loadMoreClick}> <Button width={"100%"} onClick={loadMoreClick}>
Load more Load more

View file

@ -1,5 +1,3 @@
"use client"
import Toast, { Toaster } from "react-hot-toast" import Toast, { Toaster } from "react-hot-toast"
export type ToastType = "success" | "error" | "loading" | "default" export type ToastType = "success" | "error" | "loading" | "default"

View file

@ -8,19 +8,18 @@ interface RootLayoutProps {
export default async function RootLayout({ children }: RootLayoutProps) { export default async function RootLayout({ children }: RootLayoutProps) {
return ( return (
<ServerThemeProvider // <ServerThemeProvider
enableSystem={true} // enableSystem={true}
disableTransitionOnChange // disableTransitionOnChange
cookieName={"drift-theme"} // cookieName={"drift-theme"}
attribute="data-theme" // attribute="data-theme"
enableColorScheme={true} // enableColorScheme={true}
> // >
<html lang="en"> <html lang="en">
<head /> <head />
<body> <body>
<LayoutWrapper>{children}</LayoutWrapper> <LayoutWrapper>{children}</LayoutWrapper>
</body> </body>
</html> </html>
</ServerThemeProvider>
) )
} }

View file

@ -13,7 +13,10 @@ const getWelcomeData = async () => {
export default async function Page() { export default async function Page() {
const { content, rendered, title } = await getWelcomeData() const { content, rendered, title } = await getWelcomeData()
const getPostsPromise = getAllPosts({ const getPostsPromise = getAllPosts({
where: { visibility: "public" } where: { visibility: "public" },
include: {
files: true,
}
}) })
return ( return (

View file

@ -4,7 +4,6 @@ import Header from "@components/header"
import Page from "@components/page" import Page from "@components/page"
import { Toasts } from "@components/toasts" import { Toasts } from "@components/toasts"
import * as RadixTooltip from "@radix-ui/react-tooltip" import * as RadixTooltip from "@radix-ui/react-tooltip"
import { ThemeProvider } from "@wits/next-themes"
import { SessionProvider } from "next-auth/react" import { SessionProvider } from "next-auth/react"
export function LayoutWrapper({ children }: { children: React.ReactNode }) { export function LayoutWrapper({ children }: { children: React.ReactNode }) {
@ -13,15 +12,7 @@ export function LayoutWrapper({ children }: { children: React.ReactNode }) {
<RadixTooltip.Provider delayDuration={200}> <RadixTooltip.Provider delayDuration={200}>
<Toasts /> <Toasts />
<Page> <Page>
<ThemeProvider
enableSystem={true}
defaultTheme="dark"
disableTransitionOnChange
attribute="data-theme"
enableColorScheme={true}
>
<Header /> <Header />
</ThemeProvider>
{children} {children}
</Page> </Page>
</RadixTooltip.Provider> </RadixTooltip.Provider>

View file

@ -1,3 +1,4 @@
type Config = { type Config = {
is_production: boolean is_production: boolean
enable_admin: boolean enable_admin: boolean
@ -14,9 +15,9 @@ type Environment = { [key: string]: EnvironmentValue }
export const config = (env: Environment): Config => { export const config = (env: Environment): Config => {
const stringToBoolean = (str: EnvironmentValue): boolean => { const stringToBoolean = (str: EnvironmentValue): boolean => {
if (str === "true") { if (str === "true" || str === "1") {
return true return true
} else if (str === "false") { } else if (str === "false" || str === "0") {
return false return false
} else if (str) { } else if (str) {
throw new Error(`Invalid boolean value: ${str}`) throw new Error(`Invalid boolean value: ${str}`)
@ -69,8 +70,8 @@ export const config = (env: Environment): Config => {
is_production, is_production,
enable_admin: stringToBoolean(env.ENABLE_ADMIN), enable_admin: stringToBoolean(env.ENABLE_ADMIN),
registration_password: env.REGISTRATION_PASSWORD ?? "", registration_password: env.REGISTRATION_PASSWORD ?? "",
welcome_content: env.WELCOME_CONTENT ?? "", welcome_content: env.WELCOME_CONTENT ?? "Welcome to Drift.",
welcome_title: env.WELCOME_TITLE ?? "", welcome_title: env.WELCOME_TITLE ?? "Drift",
url: process.env.VERCEL_URL ?? throwIfUndefined("DRIFT_URL"), url: process.env.VERCEL_URL ?? throwIfUndefined("DRIFT_URL"),
github_client_id: env.GITHUB_CLIENT_ID ?? "", github_client_id: env.GITHUB_CLIENT_ID ?? "",
github_client_secret: env.GITHUB_CLIENT_SECRET ?? "" github_client_secret: env.GITHUB_CLIENT_SECRET ?? ""

View file

@ -8,7 +8,40 @@ const providers: NextAuthOptions["providers"] = [
GitHubProvider({ GitHubProvider({
clientId: config.github_client_id, clientId: config.github_client_id,
clientSecret: config.github_client_secret clientSecret: config.github_client_secret
}) }),
// CredentialsProvider({
// name: "Credentials",
// credentials: {
// username: { label: "Username", type: "text", placeholder: "jsmith" },
// password: { label: "Password", type: "password" }
// },
// async authorize(credentials) {
// const user = await prisma.user.findUnique({
// where: {
// username: credentials.username
// }
// })
// if (!user) {
// // create with prisma
// // return user
// const newUser = await prisma.account.create({
// data: {
// provider: "credentials",
// providerAccountId: credentials.username,
// user: {
// create: {
// name: credentials.username,
// displayName: credentials.username
// }
// }
// }
// })
// }
// return user
// }
// })
] ]
export const authOptions: NextAuthOptions = { export const authOptions: NextAuthOptions = {

View file

@ -14,7 +14,7 @@
}, },
"dependencies": { "dependencies": {
"@next-auth/prisma-adapter": "^1.0.5", "@next-auth/prisma-adapter": "^1.0.5",
"@next/eslint-plugin-next": "13.0.5-canary.3", "@next/eslint-plugin-next": "13.0.7-canary.4",
"@prisma/client": "^4.7.1", "@prisma/client": "^4.7.1",
"@radix-ui/react-dialog": "^1.0.2", "@radix-ui/react-dialog": "^1.0.2",
"@radix-ui/react-dropdown-menu": "^2.0.1", "@radix-ui/react-dropdown-menu": "^2.0.1",
@ -24,11 +24,12 @@
"@wcj/markdown-to-html": "^2.1.2", "@wcj/markdown-to-html": "^2.1.2",
"@wits/next-themes": "0.2.14", "@wits/next-themes": "0.2.14",
"bcrypt": "^5.1.0", "bcrypt": "^5.1.0",
"client-only": "^0.0.1",
"client-zip": "2.2.1", "client-zip": "2.2.1",
"jest": "^29.3.1", "jest": "^29.3.1",
"lodash.debounce": "^4.0.8", "lodash.debounce": "^4.0.8",
"next": "13.0.7-canary.1", "next": "13.0.7-canary.4",
"next-auth": "^4.18.0", "next-auth": "^4.18.4",
"prisma": "^4.7.1", "prisma": "^4.7.1",
"react": "18.2.0", "react": "18.2.0",
"react-datepicker": "4.8.0", "react-datepicker": "4.8.0",
@ -36,11 +37,12 @@
"react-dropzone": "14.2.3", "react-dropzone": "14.2.3",
"react-feather": "^2.0.10", "react-feather": "^2.0.10",
"react-hot-toast": "^2.4.0", "react-hot-toast": "^2.4.0",
"server-only": "^0.0.1",
"textarea-markdown-editor": "1.0.4", "textarea-markdown-editor": "1.0.4",
"ts-jest": "^29.0.3" "ts-jest": "^29.0.3"
}, },
"devDependencies": { "devDependencies": {
"@next/bundle-analyzer": "13.0.7-canary.1", "@next/bundle-analyzer": "13.0.7-canary.4",
"@types/bcrypt": "^5.0.0", "@types/bcrypt": "^5.0.0",
"@types/lodash.debounce": "^4.0.7", "@types/lodash.debounce": "^4.0.7",
"@types/node": "17.0.23", "@types/node": "17.0.23",

View file

@ -2,8 +2,8 @@ lockfileVersion: 5.4
specifiers: specifiers:
'@next-auth/prisma-adapter': ^1.0.5 '@next-auth/prisma-adapter': ^1.0.5
'@next/bundle-analyzer': 13.0.7-canary.1 '@next/bundle-analyzer': 13.0.7-canary.4
'@next/eslint-plugin-next': 13.0.5-canary.3 '@next/eslint-plugin-next': 13.0.7-canary.4
'@prisma/client': ^4.7.1 '@prisma/client': ^4.7.1
'@radix-ui/react-dialog': ^1.0.2 '@radix-ui/react-dialog': ^1.0.2
'@radix-ui/react-dropdown-menu': ^2.0.1 '@radix-ui/react-dropdown-menu': ^2.0.1
@ -19,6 +19,7 @@ specifiers:
'@wcj/markdown-to-html': ^2.1.2 '@wcj/markdown-to-html': ^2.1.2
'@wits/next-themes': 0.2.14 '@wits/next-themes': 0.2.14
bcrypt: ^5.1.0 bcrypt: ^5.1.0
client-only: ^0.0.1
client-zip: 2.2.1 client-zip: 2.2.1
clsx: ^1.2.1 clsx: ^1.2.1
cross-env: 7.0.3 cross-env: 7.0.3
@ -27,8 +28,8 @@ specifiers:
eslint-config-next: 13.0.3 eslint-config-next: 13.0.3
jest: ^29.3.1 jest: ^29.3.1
lodash.debounce: ^4.0.8 lodash.debounce: ^4.0.8
next: 13.0.7-canary.1 next: 13.0.7-canary.4
next-auth: ^4.18.0 next-auth: ^4.18.4
next-unused: 0.0.6 next-unused: 0.0.6
prettier: 2.6.2 prettier: 2.6.2
prisma: ^4.7.1 prisma: ^4.7.1
@ -38,6 +39,7 @@ specifiers:
react-dropzone: 14.2.3 react-dropzone: 14.2.3
react-feather: ^2.0.10 react-feather: ^2.0.10
react-hot-toast: ^2.4.0 react-hot-toast: ^2.4.0
server-only: ^0.0.1
sharp: ^0.31.2 sharp: ^0.31.2
textarea-markdown-editor: 1.0.4 textarea-markdown-editor: 1.0.4
ts-jest: ^29.0.3 ts-jest: ^29.0.3
@ -45,8 +47,8 @@ specifiers:
typescript-plugin-css-modules: 3.4.0 typescript-plugin-css-modules: 3.4.0
dependencies: dependencies:
'@next-auth/prisma-adapter': 1.0.5_hpttyne5hky44pj2anoxcmv4zm '@next-auth/prisma-adapter': 1.0.5_4eojhct6t46nl4awizrjr4dkya
'@next/eslint-plugin-next': 13.0.5-canary.3 '@next/eslint-plugin-next': 13.0.7-canary.4
'@prisma/client': 4.7.1_prisma@4.7.1 '@prisma/client': 4.7.1_prisma@4.7.1
'@radix-ui/react-dialog': 1.0.2_jbvntnid6ohjelon6ccj5dhg2u '@radix-ui/react-dialog': 1.0.2_jbvntnid6ohjelon6ccj5dhg2u
'@radix-ui/react-dropdown-menu': 2.0.1_jbvntnid6ohjelon6ccj5dhg2u '@radix-ui/react-dropdown-menu': 2.0.1_jbvntnid6ohjelon6ccj5dhg2u
@ -54,20 +56,22 @@ dependencies:
'@radix-ui/react-tabs': 1.0.1_biqbaboplfbrettd7655fr4n2y '@radix-ui/react-tabs': 1.0.1_biqbaboplfbrettd7655fr4n2y
'@radix-ui/react-tooltip': 1.0.2_jbvntnid6ohjelon6ccj5dhg2u '@radix-ui/react-tooltip': 1.0.2_jbvntnid6ohjelon6ccj5dhg2u
'@wcj/markdown-to-html': 2.1.2 '@wcj/markdown-to-html': 2.1.2
'@wits/next-themes': 0.2.14_ihvxcpofhpc4k2aqfys2drrlkq '@wits/next-themes': 0.2.14_cn2wvw6rkm76gy2h2qfs2itv2u
bcrypt: 5.1.0 bcrypt: 5.1.0
client-only: 0.0.1
client-zip: 2.2.1 client-zip: 2.2.1
jest: 29.3.1_@types+node@17.0.23 jest: 29.3.1_@types+node@17.0.23
lodash.debounce: 4.0.8 lodash.debounce: 4.0.8
next: 13.0.7-canary.1_biqbaboplfbrettd7655fr4n2y next: 13.0.7-canary.4_biqbaboplfbrettd7655fr4n2y
next-auth: 4.18.0_ihvxcpofhpc4k2aqfys2drrlkq next-auth: 4.18.4_cn2wvw6rkm76gy2h2qfs2itv2u
prisma: 4.7.1 prisma: 4.7.1
react: 18.2.0 react: 18.2.0
react-datepicker: 4.8.0_biqbaboplfbrettd7655fr4n2y react-datepicker: 4.8.0_biqbaboplfbrettd7655fr4n2y
react-dom: 18.2.0_react@18.2.0 react-dom: 18.2.0_react@18.2.0
react-dropzone: 14.2.3_react@18.2.0 react-dropzone: 14.2.3_react@18.2.0
react-feather: 2.0.10_react@18.2.0 react-feather: 2.0.10_react@18.2.0
react-hot-toast: 2.4.0_owo25xnefcwdq3zjgtohz6dbju react-hot-toast: github.com/MaxLeiter/react-hot-toast/e48766e293f39871697bbae8d270694733fac954_owo25xnefcwdq3zjgtohz6dbju
server-only: 0.0.1
textarea-markdown-editor: 1.0.4_biqbaboplfbrettd7655fr4n2y textarea-markdown-editor: 1.0.4_biqbaboplfbrettd7655fr4n2y
ts-jest: 29.0.3_7hcmezpa7bajbjecov7p46z4aa ts-jest: 29.0.3_7hcmezpa7bajbjecov7p46z4aa
@ -75,7 +79,7 @@ optionalDependencies:
sharp: 0.31.2 sharp: 0.31.2
devDependencies: devDependencies:
'@next/bundle-analyzer': 13.0.7-canary.1 '@next/bundle-analyzer': 13.0.7-canary.4
'@types/bcrypt': 5.0.0 '@types/bcrypt': 5.0.0
'@types/lodash.debounce': 4.0.7 '@types/lodash.debounce': 4.0.7
'@types/node': 17.0.23 '@types/node': 17.0.23
@ -789,18 +793,18 @@ packages:
- supports-color - supports-color
dev: false dev: false
/@next-auth/prisma-adapter/1.0.5_hpttyne5hky44pj2anoxcmv4zm: /@next-auth/prisma-adapter/1.0.5_4eojhct6t46nl4awizrjr4dkya:
resolution: {integrity: sha512-VqMS11IxPXrPGXw6Oul6jcyS/n8GLOWzRMrPr3EMdtD6eOalM6zz05j08PcNiis8QzkfuYnCv49OvufTuaEwYQ==} resolution: {integrity: sha512-VqMS11IxPXrPGXw6Oul6jcyS/n8GLOWzRMrPr3EMdtD6eOalM6zz05j08PcNiis8QzkfuYnCv49OvufTuaEwYQ==}
peerDependencies: peerDependencies:
'@prisma/client': '>=2.26.0 || >=3' '@prisma/client': '>=2.26.0 || >=3'
next-auth: ^4 next-auth: ^4
dependencies: dependencies:
'@prisma/client': 4.7.1_prisma@4.7.1 '@prisma/client': 4.7.1_prisma@4.7.1
next-auth: 4.18.0_ihvxcpofhpc4k2aqfys2drrlkq next-auth: 4.18.4_cn2wvw6rkm76gy2h2qfs2itv2u
dev: false dev: false
/@next/bundle-analyzer/13.0.7-canary.1: /@next/bundle-analyzer/13.0.7-canary.4:
resolution: {integrity: sha512-3CKGOK1Fp5mhCQ001h/GIj/ceZa4IfljWAkxRkX4uAOUAyyQ9MNNLNUX9H95/+oO7k2YS/Z71wXRk/xDaxM3Jw==} resolution: {integrity: sha512-YgqSA+Ok3ITIJFJMrJkaanwUsaTGy4zmOE36f3S7h3XoRpjRIH/OFcctVLrvkpc6rKhVxYN1dN2GMojL9f5KUA==}
dependencies: dependencies:
webpack-bundle-analyzer: 4.7.0 webpack-bundle-analyzer: 4.7.0
transitivePeerDependencies: transitivePeerDependencies:
@ -808,8 +812,8 @@ packages:
- utf-8-validate - utf-8-validate
dev: true dev: true
/@next/env/13.0.7-canary.1: /@next/env/13.0.7-canary.4:
resolution: {integrity: sha512-pjFCstWLbHpO3wAI4H6Jueiqb9s1IB++w8e79RJvry5K2ElzRpUPXeTkjI/oLSZ6W9DDG8DTOMmJtat2o+h3jA==} resolution: {integrity: sha512-PEFzHZkan5SJtxAL+0TmL4Vx3BJp4tDbCnba/2H3CeW0hVEck0e+UY7UGSXwyBaojD6DwUtgHHN3tu2yd2x51w==}
dev: false dev: false
/@next/eslint-plugin-next/13.0.3: /@next/eslint-plugin-next/13.0.3:
@ -818,14 +822,14 @@ packages:
glob: 7.1.7 glob: 7.1.7
dev: true dev: true
/@next/eslint-plugin-next/13.0.5-canary.3: /@next/eslint-plugin-next/13.0.7-canary.4:
resolution: {integrity: sha512-HSho43Ul+m159QXy1ZFcA5KIKQ2J6eB35chITAEC5pREQpBLydi+XrjjwbkYiyYtpST97HgIcV0lrMXEznOi/g==} resolution: {integrity: sha512-jNgarJTQSia+yTcQr6dF9wZhCfCFIXbc0WzSIAfyx4Z8FZjfmTmeVDGL1JHSYlcSmTnJ6o6Z36MsFh/mreuE4g==}
dependencies: dependencies:
glob: 7.1.7 glob: 7.1.7
dev: false dev: false
/@next/swc-android-arm-eabi/13.0.7-canary.1: /@next/swc-android-arm-eabi/13.0.7-canary.4:
resolution: {integrity: sha512-bmUIfXap+EwEpkWqGso3fMScXpbbUHecFByjnnmWOXU21e1bhE7UfCDtXzEn3utwt8MlUwA/h/5CGf6wMFUU8w==} resolution: {integrity: sha512-mXpIUvBXaxYD/tI6FUuRKF0JPs03dBCQAtmZjG7hRISpnFWij1wgm+NewmXEZ7EmWIIstc+vTgP0Akzqfz6abg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm] cpu: [arm]
os: [android] os: [android]
@ -833,8 +837,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-android-arm64/13.0.7-canary.1: /@next/swc-android-arm64/13.0.7-canary.4:
resolution: {integrity: sha512-k0Wo/NgoAj1Bcp7X7fYc8C4G4Y+qiLrjqWGTQ38Cx5NHJfMJf6gUTfgc2OTBG96tKj21LwKhhg6BEqV9mRuzOg==} resolution: {integrity: sha512-sht0AvPUp4667+QwWLj4zAcTEFoxmAH5sYRddSIrBpMa2fE0FT6P4ZInJ5eSlxrS+Ag9ehRq09kb+y9j8Ci/ZQ==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
@ -842,8 +846,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-darwin-arm64/13.0.7-canary.1: /@next/swc-darwin-arm64/13.0.7-canary.4:
resolution: {integrity: sha512-phrROUvPXYouNl4Bs7kRmkTcU18V2gxIbwiWonQYWROfCQJckELHM0MFOAfLbkJYRT/vcyp/o2bgiPkWv/fP8A==} resolution: {integrity: sha512-8WhDzOW2byCRde6bgMigqzVE0Uihhg9hicm2IzR81quoLuPU9UBbk7OCFSUg3OqQjjmzo2ZChYq85bouRMjpJg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
@ -851,8 +855,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-darwin-x64/13.0.7-canary.1: /@next/swc-darwin-x64/13.0.7-canary.4:
resolution: {integrity: sha512-ERpeI2zWlTj4xKdhwq8h9gyMWHSCh5UNm3ekX/MCgq1Mg1cLsv/kINeVQuvVP5II5HSHoEjnw2GvAMB4ayhcUA==} resolution: {integrity: sha512-MWItc0vAwDFpW6kR+aPWhTj2Q0VaqKrWOemv28wv3Wv3kwCxheSzWImOkcGPn5eTnCRfn0Cn2b/+VHQ1tH79tg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
@ -860,8 +864,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-freebsd-x64/13.0.7-canary.1: /@next/swc-freebsd-x64/13.0.7-canary.4:
resolution: {integrity: sha512-L/YIIzaoV58UHLgiR8jfr0V9HXmUvHf1a2+1esSsTlMXZ0Y3SzcczuLgEu0/AYKEgHcfl+vcng9FBeqXtVlYyQ==} resolution: {integrity: sha512-mFoYF/rEi6Vd1RF6L3rNdYzwXATwqXUmbhY9Brav4JrJ9TQmf8GiZz0itn65J1QDuRw3rD+czKJ/HxwSvCNUMA==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
@ -869,8 +873,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-linux-arm-gnueabihf/13.0.7-canary.1: /@next/swc-linux-arm-gnueabihf/13.0.7-canary.4:
resolution: {integrity: sha512-KVB7lAgtUgqrroqozYSCZIwVQITHhjbe99n/C6A9BYIAUtwITrLIn8Sj7D0a0sEhdDL8Y/rzXZGWMqL7f1Hg3A==} resolution: {integrity: sha512-+uxKr1/BXvZjTeIFnue85pdDxnneD9lCvvfkIjcY2EIToTMOhTtqlyosXblENTL7uM+q26lhKOepRDttG9L2cQ==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
@ -878,8 +882,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-linux-arm64-gnu/13.0.7-canary.1: /@next/swc-linux-arm64-gnu/13.0.7-canary.4:
resolution: {integrity: sha512-tA4yYk1+2fPgs0q6r94d7sKQosf9jZGTMXIS0yOykk246L3+npsDqyBrdCusaJv9q3Fm5S8lfwp4vqoLNtcFLg==} resolution: {integrity: sha512-WVqK6/jXVjWePvIaOOgNHO6P8LUntvLuay6clhdBzAzArEStG1RRoupAnuqz9VXyFtHguRthejQhFAqYLq9jqw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
@ -887,8 +891,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-linux-arm64-musl/13.0.7-canary.1: /@next/swc-linux-arm64-musl/13.0.7-canary.4:
resolution: {integrity: sha512-KKN/nd2g2Cixs+av1mLeiNvhm+8T8ZiuzZHRrA4h4OWwreI+weS0iXBa1sBGvNp863MxE1mxKOv2xFhSbWK/CQ==} resolution: {integrity: sha512-LEu82umP+iLyP710qYA37UT6FFhcKZ7z9GmitFZxE9Jj6wenOFZHkkFDm624pJyAhfLcbLdT5MYqIgXIuwloDg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
@ -896,8 +900,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-linux-x64-gnu/13.0.7-canary.1: /@next/swc-linux-x64-gnu/13.0.7-canary.4:
resolution: {integrity: sha512-1crxMrvO2pHmsDxSkVknchiyLHYpkKKkwhnrFYKP06bZSEONAry6VTYJ6l73PK9mp1kzFAtke5k9yG4LG0fbAQ==} resolution: {integrity: sha512-ycoLEMKaNM/T/iplgVsjYFpYE7tTh/UNaBxuFnsxBLuQJJET26mCWNPjM7CpiDWZVhdFwD5ad9PI3+HeOnSgSg==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
@ -905,8 +909,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-linux-x64-musl/13.0.7-canary.1: /@next/swc-linux-x64-musl/13.0.7-canary.4:
resolution: {integrity: sha512-1incysWrn+PEK6XRE1QnK2UI7//N6gfmeaFC1KIlRyt0JmyF8U3V+I6Qcar9nHz9hY9e8yszFQY0A9X0jsfkUQ==} resolution: {integrity: sha512-xR22ldRvmg0l5bJbuK11iNFXAKS8+cgbkQZeHizYM5ngWOIEz8WQWn01+9sBeydtQZbvySpWHfm/Ev3XFEJHOw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
@ -914,8 +918,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-win32-arm64-msvc/13.0.7-canary.1: /@next/swc-win32-arm64-msvc/13.0.7-canary.4:
resolution: {integrity: sha512-AE5NYCeXilQnzIOma7y3cNcYVQsHJsEZ3r4/DTKvmFvuFVBkxza7Uxzi5rwD67ewSbOzir1xr+LBtI6vCmQ/Fw==} resolution: {integrity: sha512-psFkg4qGIx85tqDu9f7vl1jgLumzGsCdVL+OvLWY9opASDNaSYMp0xcwKT1BvGYpY8sGs81Q21yVrGl4sa8vvA==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
@ -923,8 +927,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-win32-ia32-msvc/13.0.7-canary.1: /@next/swc-win32-ia32-msvc/13.0.7-canary.4:
resolution: {integrity: sha512-kG84cAm/FZsK3u2vgcUpQRT28NEA+vMTMrp4ufdHPu+c0o0aEcLqh3yQstWqw+hGpYQxiB0EF95K9bbRfHkgOQ==} resolution: {integrity: sha512-4b0snVdqN8wDQMucJDbM759sC1txN/PwtaTn/rgcBaybXBFlYBc01mj3ePWcGcUj0378+FSKZWfo1+ldYBurFw==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [ia32] cpu: [ia32]
os: [win32] os: [win32]
@ -932,8 +936,8 @@ packages:
dev: false dev: false
optional: true optional: true
/@next/swc-win32-x64-msvc/13.0.7-canary.1: /@next/swc-win32-x64-msvc/13.0.7-canary.4:
resolution: {integrity: sha512-FrEMvjaPJ3g2BcQp0aovr4Jj5L/KnvWlnvw5fIPMMoDmUYuMkbR4ZbAvIrOaLGCRiO0862kcoCcdhZ75AwzU2g==} resolution: {integrity: sha512-RbxWU5fswTBBuI2o7hHJ2KgSUAS73pw0RNMI387eGfh7Nmo5QQg9DCUJFXQlxCWUmvC+mvYPwMFWsolYdEd++A==}
engines: {node: '>= 10'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
@ -1725,14 +1729,14 @@ packages:
- supports-color - supports-color
dev: false dev: false
/@wits/next-themes/0.2.14_ihvxcpofhpc4k2aqfys2drrlkq: /@wits/next-themes/0.2.14_cn2wvw6rkm76gy2h2qfs2itv2u:
resolution: {integrity: sha512-fHKb/tRcWbYNblGHZtfvAQztDhzUB9d7ZkYOny0BisSPh6EABcsqxKB48ABUQztcmKywlp2zEMkLcSRj/PQBSw==} resolution: {integrity: sha512-fHKb/tRcWbYNblGHZtfvAQztDhzUB9d7ZkYOny0BisSPh6EABcsqxKB48ABUQztcmKywlp2zEMkLcSRj/PQBSw==}
peerDependencies: peerDependencies:
next: '*' next: '*'
react: '*' react: '*'
react-dom: '*' react-dom: '*'
dependencies: dependencies:
next: 13.0.7-canary.1_biqbaboplfbrettd7655fr4n2y next: 13.0.7-canary.4_biqbaboplfbrettd7655fr4n2y
react: 18.2.0 react: 18.2.0
react-dom: 18.2.0_react@18.2.0 react-dom: 18.2.0_react@18.2.0
dev: false dev: false
@ -5225,8 +5229,8 @@ packages:
dev: true dev: true
optional: true optional: true
/next-auth/4.18.0_ihvxcpofhpc4k2aqfys2drrlkq: /next-auth/4.18.4_cn2wvw6rkm76gy2h2qfs2itv2u:
resolution: {integrity: sha512-lqJtusYqUwDiwzO4+B+lx/vKCuf/akcdhxT5R47JmS5gvI9O6Y4CZYc8coysY7XaMGHCxfttvTSEw76RA8gNTg==} resolution: {integrity: sha512-tvXOabxv5U/y6ib56XPkOnc/48tYc+xT6GNOLREIme8WVGYHDTc3CGEfe2+0bVCWAm0ax/GYXH0By5NFoaJDww==}
engines: {node: ^12.19.0 || ^14.15.0 || ^16.13.0 || ^18.12.0} engines: {node: ^12.19.0 || ^14.15.0 || ^16.13.0 || ^18.12.0}
peerDependencies: peerDependencies:
next: ^12.2.5 || ^13 next: ^12.2.5 || ^13
@ -5241,7 +5245,7 @@ packages:
'@panva/hkdf': 1.0.2 '@panva/hkdf': 1.0.2
cookie: 0.5.0 cookie: 0.5.0
jose: 4.11.0 jose: 4.11.0
next: 13.0.7-canary.1_biqbaboplfbrettd7655fr4n2y next: 13.0.7-canary.4_biqbaboplfbrettd7655fr4n2y
oauth: 0.9.15 oauth: 0.9.15
openid-client: 5.3.0 openid-client: 5.3.0
preact: 10.11.2 preact: 10.11.2
@ -5262,8 +5266,8 @@ packages:
- supports-color - supports-color
dev: true dev: true
/next/13.0.7-canary.1_biqbaboplfbrettd7655fr4n2y: /next/13.0.7-canary.4_biqbaboplfbrettd7655fr4n2y:
resolution: {integrity: sha512-xfLT5Ikty2zcFCYSsYaQta3Dik09BJmwwj5a3i/ceh+51rJ+I3lP9+BbB9dUCUmgftOgxyyFUkzIZJ/gi3fUiQ==} resolution: {integrity: sha512-cx0ST4A/ZYB5eqygzx59cW4/xhVBanPhDr7JytkzZJ/HUCX67VR/ho+rcekB/C/ZNsefYukhMrep6vwfidV95A==}
engines: {node: '>=14.6.0'} engines: {node: '>=14.6.0'}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
@ -5280,7 +5284,7 @@ packages:
sass: sass:
optional: true optional: true
dependencies: dependencies:
'@next/env': 13.0.7-canary.1 '@next/env': 13.0.7-canary.4
'@swc/helpers': 0.4.14 '@swc/helpers': 0.4.14
caniuse-lite: 1.0.30001431 caniuse-lite: 1.0.30001431
postcss: 8.4.14 postcss: 8.4.14
@ -5288,19 +5292,19 @@ packages:
react-dom: 18.2.0_react@18.2.0 react-dom: 18.2.0_react@18.2.0
styled-jsx: 5.1.0_react@18.2.0 styled-jsx: 5.1.0_react@18.2.0
optionalDependencies: optionalDependencies:
'@next/swc-android-arm-eabi': 13.0.7-canary.1 '@next/swc-android-arm-eabi': 13.0.7-canary.4
'@next/swc-android-arm64': 13.0.7-canary.1 '@next/swc-android-arm64': 13.0.7-canary.4
'@next/swc-darwin-arm64': 13.0.7-canary.1 '@next/swc-darwin-arm64': 13.0.7-canary.4
'@next/swc-darwin-x64': 13.0.7-canary.1 '@next/swc-darwin-x64': 13.0.7-canary.4
'@next/swc-freebsd-x64': 13.0.7-canary.1 '@next/swc-freebsd-x64': 13.0.7-canary.4
'@next/swc-linux-arm-gnueabihf': 13.0.7-canary.1 '@next/swc-linux-arm-gnueabihf': 13.0.7-canary.4
'@next/swc-linux-arm64-gnu': 13.0.7-canary.1 '@next/swc-linux-arm64-gnu': 13.0.7-canary.4
'@next/swc-linux-arm64-musl': 13.0.7-canary.1 '@next/swc-linux-arm64-musl': 13.0.7-canary.4
'@next/swc-linux-x64-gnu': 13.0.7-canary.1 '@next/swc-linux-x64-gnu': 13.0.7-canary.4
'@next/swc-linux-x64-musl': 13.0.7-canary.1 '@next/swc-linux-x64-musl': 13.0.7-canary.4
'@next/swc-win32-arm64-msvc': 13.0.7-canary.1 '@next/swc-win32-arm64-msvc': 13.0.7-canary.4
'@next/swc-win32-ia32-msvc': 13.0.7-canary.1 '@next/swc-win32-ia32-msvc': 13.0.7-canary.4
'@next/swc-win32-x64-msvc': 13.0.7-canary.1 '@next/swc-win32-x64-msvc': 13.0.7-canary.4
transitivePeerDependencies: transitivePeerDependencies:
- '@babel/core' - '@babel/core'
- babel-plugin-macros - babel-plugin-macros
@ -5953,20 +5957,6 @@ packages:
react: 18.2.0 react: 18.2.0
dev: false dev: false
/react-hot-toast/2.4.0_owo25xnefcwdq3zjgtohz6dbju:
resolution: {integrity: sha512-qnnVbXropKuwUpriVVosgo8QrB+IaPJCpL8oBI6Ov84uvHZ5QQcTp2qg6ku2wNfgJl6rlQXJIQU5q+5lmPOutA==}
engines: {node: '>=10'}
peerDependencies:
react: '>=16'
react-dom: '>=16'
dependencies:
goober: 2.1.11_csstype@3.1.1
react: 18.2.0
react-dom: 18.2.0_react@18.2.0
transitivePeerDependencies:
- csstype
dev: false
/react-is/16.13.1: /react-is/16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
@ -6388,6 +6378,10 @@ packages:
dependencies: dependencies:
lru-cache: 6.0.0 lru-cache: 6.0.0
/server-only/0.0.1:
resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==}
dev: false
/set-blocking/2.0.0: /set-blocking/2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
dev: false dev: false
@ -7311,3 +7305,20 @@ packages:
/zwitch/2.0.2: /zwitch/2.0.2:
resolution: {integrity: sha512-JZxotl7SxAJH0j7dN4pxsTV6ZLXoLdGME+PsjkL/DaBrVryK9kTGq06GfKrwcSOqypP+fdXGoCHE36b99fWVoA==} resolution: {integrity: sha512-JZxotl7SxAJH0j7dN4pxsTV6ZLXoLdGME+PsjkL/DaBrVryK9kTGq06GfKrwcSOqypP+fdXGoCHE36b99fWVoA==}
dev: false dev: false
github.com/MaxLeiter/react-hot-toast/e48766e293f39871697bbae8d270694733fac954_owo25xnefcwdq3zjgtohz6dbju:
resolution: {registry: https://registry.npmjs.org/, tarball: https://codeload.github.com/MaxLeiter/react-hot-toast/tar.gz/e48766e293f39871697bbae8d270694733fac954}
id: github.com/MaxLeiter/react-hot-toast/e48766e293f39871697bbae8d270694733fac954
name: react-hot-toast
version: 2.4.0
engines: {node: '>=10'}
peerDependencies:
react: '>=16'
react-dom: '>=16'
dependencies:
goober: 2.1.11_csstype@3.1.1
react: 18.2.0
react-dom: 18.2.0_react@18.2.0
transitivePeerDependencies:
- csstype
dev: false