start api transition, prisma additions
This commit is contained in:
parent
da870d6957
commit
9b9c3c1d87
82 changed files with 1671 additions and 202 deletions
|
@ -1,2 +0,0 @@
|
||||||
API_URL=http://localhost:3000
|
|
||||||
SECRET_KEY=secret
|
|
5
client/app/(auth)/head.tsx
Normal file
5
client/app/(auth)/head.tsx
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import PageSeo from "@components/head"
|
||||||
|
|
||||||
|
export default function AuthHead() {
|
||||||
|
return <PageSeo title="Sign In" />
|
||||||
|
}
|
5
client/app/(auth)/signin/page.tsx
Normal file
5
client/app/(auth)/signin/page.tsx
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import Auth from "@components/auth"
|
||||||
|
|
||||||
|
export default function SignInPage() {
|
||||||
|
return <Auth page="signin" />
|
||||||
|
}
|
12
client/app/(auth)/signup/page.tsx
Normal file
12
client/app/(auth)/signup/page.tsx
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import Auth from "@components/auth"
|
||||||
|
import config from "@lib/config"
|
||||||
|
import { getRequiresPasscode } from "pages/api/auth/requires-passcode"
|
||||||
|
|
||||||
|
const getPasscode = async () => {
|
||||||
|
return await getRequiresPasscode()
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function SignUpPage() {
|
||||||
|
const requiresPasscode = await getPasscode()
|
||||||
|
return <Auth page="signup" requiresServerPassword={requiresPasscode} />
|
||||||
|
}
|
67
client/app/(posts)/new/from/[id]/page.tsx
Normal file
67
client/app/(posts)/new/from/[id]/page.tsx
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
import styles from "@styles/Home.module.css"
|
||||||
|
import NewPost from "@components/new-post"
|
||||||
|
import PageSeo from "@components/page-seo"
|
||||||
|
import { Page } from "@geist-ui/core/dist"
|
||||||
|
import Head from "next/head"
|
||||||
|
import { GetServerSideProps } from "next"
|
||||||
|
import { Post } from "@lib/types"
|
||||||
|
import cookie from "cookie"
|
||||||
|
|
||||||
|
|
||||||
|
const NewFromExisting = async () => {
|
||||||
|
return (
|
||||||
|
// <Head>
|
||||||
|
// {/* TODO: solve this. */}
|
||||||
|
// {/* eslint-disable-next-line @next/next/no-css-tags */}
|
||||||
|
// <link rel="stylesheet" href="/css/react-datepicker.css" />
|
||||||
|
// </Head>
|
||||||
|
<NewPost initialPost={post} newPostParent={parentId} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// export const getServerSideProps: GetServerSideProps = async ({
|
||||||
|
// req,
|
||||||
|
// params
|
||||||
|
// }) => {
|
||||||
|
// const id = params?.id
|
||||||
|
// const redirect = {
|
||||||
|
// redirect: {
|
||||||
|
// destination: "/new",
|
||||||
|
// permanent: false
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!id) {
|
||||||
|
// return redirect
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const driftToken = cookie.parse(req.headers.cookie || "")[`drift-token`]
|
||||||
|
|
||||||
|
// const post = await fetch(`${process.env.API_URL}/posts/${id}`, {
|
||||||
|
// method: "GET",
|
||||||
|
// headers: {
|
||||||
|
// "Content-Type": "application/json",
|
||||||
|
// Authorization: `Bearer ${driftToken}`,
|
||||||
|
// "x-secret-key": process.env.SECRET_KEY || ""
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
|
||||||
|
// if (!post.ok) {
|
||||||
|
// return redirect
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const data = await post.json()
|
||||||
|
|
||||||
|
// if (!data) {
|
||||||
|
// return redirect
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return {
|
||||||
|
// props: {
|
||||||
|
// post: data,
|
||||||
|
// parentId: id
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
export default NewFromExisting
|
5
client/app/(posts)/new/head.tsx
Normal file
5
client/app/(posts)/new/head.tsx
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import PageSeo from "@components/page-seo"
|
||||||
|
|
||||||
|
export default function NewPostHead() {
|
||||||
|
return <PageSeo title="Create a new Drift" />
|
||||||
|
}
|
10
client/app/(posts)/new/page.tsx
Normal file
10
client/app/(posts)/new/page.tsx
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import NewPost from "@components/new-post"
|
||||||
|
import '@styles/react-datepicker.css'
|
||||||
|
|
||||||
|
const New = () => {
|
||||||
|
return (
|
||||||
|
<NewPost />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default New
|
|
@ -1,5 +1,6 @@
|
||||||
import "styles/globals.css"
|
import "@styles/globals.css"
|
||||||
import { ServerThemeProvider } from "next-themes"
|
import { ServerThemeProvider } from "next-themes"
|
||||||
|
import { LayoutWrapper } from "./root-layout-wrapper"
|
||||||
|
|
||||||
interface RootLayoutProps {
|
interface RootLayoutProps {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
|
@ -8,9 +9,9 @@ interface RootLayoutProps {
|
||||||
export default function RootLayout({ children }: RootLayoutProps) {
|
export default function RootLayout({ children }: RootLayoutProps) {
|
||||||
return (
|
return (
|
||||||
<ServerThemeProvider
|
<ServerThemeProvider
|
||||||
forcedTheme="system"
|
|
||||||
disableTransitionOnChange
|
disableTransitionOnChange
|
||||||
cookieName="drift-theme"
|
cookieName="drift-theme"
|
||||||
|
attribute="data-theme"
|
||||||
>
|
>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
@ -48,7 +49,7 @@ export default function RootLayout({ children }: RootLayoutProps) {
|
||||||
<meta name="theme-color" content="#ffffff" />
|
<meta name="theme-color" content="#ffffff" />
|
||||||
<title>Drift</title>
|
<title>Drift</title>
|
||||||
</head>
|
</head>
|
||||||
<body>{children}</body>
|
<body><LayoutWrapper>{children}</LayoutWrapper></body>
|
||||||
</html>
|
</html>
|
||||||
</ServerThemeProvider>
|
</ServerThemeProvider>
|
||||||
)
|
)
|
||||||
|
|
21
client/app/page-wrapper.tsx
Normal file
21
client/app/page-wrapper.tsx
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
"use client"
|
||||||
|
|
||||||
|
import Header from "@components/header"
|
||||||
|
import { Page } from "@geist-ui/core/dist"
|
||||||
|
import styles from "@styles/Home.module.css"
|
||||||
|
|
||||||
|
export default function PageWrapper({
|
||||||
|
children
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Page width={"100%"}>
|
||||||
|
<Page.Header>
|
||||||
|
<Header />
|
||||||
|
</Page.Header>
|
||||||
|
|
||||||
|
<Page.Content className={styles.main}>{children}</Page.Content>
|
||||||
|
</Page>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,7 +1,12 @@
|
||||||
export default function Page() {
|
import { getWelcomeContent } from "pages/api/welcome"
|
||||||
return (
|
|
||||||
<>
|
const getWelcomeData = async () => {
|
||||||
<h1>Hello, world!</h1>
|
const welcomeContent = await getWelcomeContent()
|
||||||
</>
|
return welcomeContent
|
||||||
)
|
}
|
||||||
|
|
||||||
|
export default async function Page() {
|
||||||
|
const welcomeData = await getWelcomeData()
|
||||||
|
|
||||||
|
return <h1>{JSON.stringify(welcomeData)}</h1>
|
||||||
}
|
}
|
||||||
|
|
52
client/app/prisma.ts
Normal file
52
client/app/prisma.ts
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import { Post, PrismaClient, File } from "@prisma/client"
|
||||||
|
|
||||||
|
const prisma = new PrismaClient()
|
||||||
|
|
||||||
|
export default prisma
|
||||||
|
|
||||||
|
export type {
|
||||||
|
User,
|
||||||
|
AuthTokens,
|
||||||
|
File,
|
||||||
|
Post,
|
||||||
|
PostToAuthors
|
||||||
|
} from "@prisma/client"
|
||||||
|
|
||||||
|
export type PostWithFiles = Post & {
|
||||||
|
files: File[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getFilesForPost = async (postId: string) => {
|
||||||
|
const files = await prisma.file.findMany({
|
||||||
|
where: {
|
||||||
|
postId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getPostWithFiles = async (
|
||||||
|
postId: string
|
||||||
|
): Promise<PostWithFiles | undefined> => {
|
||||||
|
const post = await prisma.post.findUnique({
|
||||||
|
where: {
|
||||||
|
id: postId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!post) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const files = await getFilesForPost(postId)
|
||||||
|
|
||||||
|
if (!files) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...post,
|
||||||
|
files
|
||||||
|
}
|
||||||
|
}
|
66
client/app/root-layout-wrapper.tsx
Normal file
66
client/app/root-layout-wrapper.tsx
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
"use client"
|
||||||
|
|
||||||
|
import { CssBaseline, GeistProvider, Themes } from "@geist-ui/core/dist"
|
||||||
|
import { ThemeProvider } from "next-themes"
|
||||||
|
import { SkeletonTheme } from "react-loading-skeleton"
|
||||||
|
import PageWrapper from "./page-wrapper"
|
||||||
|
|
||||||
|
export function LayoutWrapper({ children }: { children: React.ReactNode }) {
|
||||||
|
const skeletonBaseColor = "var(--light-gray)"
|
||||||
|
const skeletonHighlightColor = "var(--lighter-gray)"
|
||||||
|
|
||||||
|
const customTheme = Themes.createFromLight({
|
||||||
|
type: "custom",
|
||||||
|
palette: {
|
||||||
|
background: "var(--bg)",
|
||||||
|
foreground: "var(--fg)",
|
||||||
|
accents_1: "var(--lightest-gray)",
|
||||||
|
accents_2: "var(--lighter-gray)",
|
||||||
|
accents_3: "var(--light-gray)",
|
||||||
|
accents_4: "var(--gray)",
|
||||||
|
accents_5: "var(--darker-gray)",
|
||||||
|
accents_6: "var(--darker-gray)",
|
||||||
|
accents_7: "var(--darkest-gray)",
|
||||||
|
accents_8: "var(--darkest-gray)",
|
||||||
|
border: "var(--light-gray)",
|
||||||
|
warning: "var(--warning)"
|
||||||
|
},
|
||||||
|
expressiveness: {
|
||||||
|
dropdownBoxShadow: "0 0 0 1px var(--light-gray)",
|
||||||
|
shadowSmall: "0 0 0 1px var(--light-gray)",
|
||||||
|
shadowLarge: "0 0 0 1px var(--light-gray)",
|
||||||
|
shadowMedium: "0 0 0 1px var(--light-gray)"
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
gap: "var(--gap)",
|
||||||
|
gapHalf: "var(--gap-half)",
|
||||||
|
gapQuarter: "var(--gap-quarter)",
|
||||||
|
gapNegative: "var(--gap-negative)",
|
||||||
|
gapHalfNegative: "var(--gap-half-negative)",
|
||||||
|
gapQuarterNegative: "var(--gap-quarter-negative)",
|
||||||
|
radius: "var(--radius)"
|
||||||
|
},
|
||||||
|
font: {
|
||||||
|
mono: "var(--font-mono)",
|
||||||
|
sans: "var(--font-sans)"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GeistProvider themes={[customTheme]} themeType={"custom"}>
|
||||||
|
<SkeletonTheme
|
||||||
|
baseColor={skeletonBaseColor}
|
||||||
|
highlightColor={skeletonHighlightColor}
|
||||||
|
>
|
||||||
|
<ThemeProvider
|
||||||
|
disableTransitionOnChange
|
||||||
|
cookieName="drift-theme"
|
||||||
|
attribute="data-theme"
|
||||||
|
>
|
||||||
|
<CssBaseline />
|
||||||
|
<PageWrapper>{children}</PageWrapper>
|
||||||
|
</ThemeProvider>
|
||||||
|
</SkeletonTheme>
|
||||||
|
</GeistProvider>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import { Popover, Button } from "@geist-ui/core"
|
import { Popover, Button } from "@geist-ui/core/dist"
|
||||||
import { MoreVertical } from "@geist-ui/icons"
|
import { MoreVertical } from "@geist-ui/icons"
|
||||||
|
|
||||||
type Action = {
|
type Action = {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import SettingsGroup from "@components/settings-group"
|
import SettingsGroup from "@components/settings-group"
|
||||||
import { Fieldset, useToasts } from "@geist-ui/core"
|
import { Fieldset, useToasts } from "@geist-ui/core/dist"
|
||||||
import byteToMB from "@lib/byte-to-mb"
|
import byteToMB from "@lib/byte-to-mb"
|
||||||
import { Post } from "@lib/types"
|
import { Post } from "@lib/types"
|
||||||
import Table from "rc-table"
|
import Table from "rc-table"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Fieldset, useToasts } from "@geist-ui/core"
|
import { Fieldset, useToasts } from "@geist-ui/core/dist"
|
||||||
import { User } from "@lib/types"
|
import { User } from "@lib/types"
|
||||||
import { useEffect, useMemo, useState } from "react"
|
import { useEffect, useMemo, useState } from "react"
|
||||||
import { adminFetcher } from "."
|
import { adminFetcher } from "."
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import Header from "@components/header"
|
import Header from "@components/header"
|
||||||
import { GeistProvider, CssBaseline, Themes, Page } from "@geist-ui/core"
|
import { GeistProvider, CssBaseline, Themes, Page } from "@geist-ui/core/dist"
|
||||||
import type { NextComponentType, NextPageContext } from "next"
|
import type { NextComponentType, NextPageContext } from "next"
|
||||||
import { SkeletonTheme } from "react-loading-skeleton"
|
import { SkeletonTheme } from "react-loading-skeleton"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
"use client"
|
||||||
|
|
||||||
import { FormEvent, useEffect, useState } from "react"
|
import { FormEvent, useEffect, useState } from "react"
|
||||||
import styles from "./auth.module.css"
|
import styles from "./auth.module.css"
|
||||||
import { useRouter } from "next/router"
|
import { useRouter } from "next/navigation"
|
||||||
import Link from "../link"
|
import Link from "../link"
|
||||||
import Cookies from "js-cookie"
|
import Cookies from "js-cookie"
|
||||||
import useSignedIn from "@lib/hooks/use-signed-in"
|
import useSignedIn from "@lib/hooks/use-signed-in"
|
||||||
|
@ -12,32 +14,21 @@ const NO_EMPTY_SPACE_REGEX = /^\S*$/
|
||||||
const ERROR_MESSAGE =
|
const ERROR_MESSAGE =
|
||||||
"Provide a non empty username and a password with at least 6 characters"
|
"Provide a non empty username and a password with at least 6 characters"
|
||||||
|
|
||||||
const Auth = ({ page }: { page: "signup" | "signin" }) => {
|
const Auth = ({
|
||||||
|
page,
|
||||||
|
requiresServerPassword
|
||||||
|
}: {
|
||||||
|
page: "signup" | "signin"
|
||||||
|
requiresServerPassword?: boolean
|
||||||
|
}) => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const [username, setUsername] = useState("")
|
const [username, setUsername] = useState("")
|
||||||
const [password, setPassword] = useState("")
|
const [password, setPassword] = useState("")
|
||||||
const [serverPassword, setServerPassword] = useState("")
|
const [serverPassword, setServerPassword] = useState("")
|
||||||
const [errorMsg, setErrorMsg] = useState("")
|
const [errorMsg, setErrorMsg] = useState("")
|
||||||
const [requiresServerPassword, setRequiresServerPassword] = useState(false)
|
|
||||||
const signingIn = page === "signin"
|
const signingIn = page === "signin"
|
||||||
const { signin } = useSignedIn()
|
const { signin } = useSignedIn()
|
||||||
useEffect(() => {
|
|
||||||
async function fetchRequiresPass() {
|
|
||||||
if (!signingIn) {
|
|
||||||
const resp = await fetch("/server-api/auth/requires-passcode", {
|
|
||||||
method: "GET"
|
|
||||||
})
|
|
||||||
if (resp.ok) {
|
|
||||||
const res = await resp.json()
|
|
||||||
setRequiresServerPassword(res.requiresPasscode)
|
|
||||||
} else {
|
|
||||||
setErrorMsg("Something went wrong. Is the server running?")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fetchRequiresPass()
|
|
||||||
}, [page, signingIn])
|
|
||||||
|
|
||||||
const handleJson = (json: any) => {
|
const handleJson = (json: any) => {
|
||||||
signin(json.token)
|
signin(json.token)
|
||||||
|
@ -70,9 +61,7 @@ const Auth = ({ page }: { page: "signup" | "signin" }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const signUrl = signingIn
|
const signUrl = signingIn ? "/api/auth/signin" : "/api/auth/signup"
|
||||||
? "/server-api/auth/signin"
|
|
||||||
: "/server-api/auth/signup"
|
|
||||||
const resp = await fetch(signUrl, reqOpts)
|
const resp = await fetch(signUrl, reqOpts)
|
||||||
const json = await resp.json()
|
const json = await resp.json()
|
||||||
if (!resp.ok) throw new Error(json.error.message)
|
if (!resp.ok) throw new Error(json.error.message)
|
||||||
|
@ -141,11 +130,7 @@ const Auth = ({ page }: { page: "signup" | "signin" }) => {
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{errorMsg && (
|
{errorMsg && <Note type="error">{errorMsg}</Note>}
|
||||||
<Note type="error">
|
|
||||||
{errorMsg}
|
|
||||||
</Note>
|
|
||||||
)}
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Badge, Tooltip } from "@geist-ui/core"
|
import { Badge, Tooltip } from "@geist-ui/core/dist"
|
||||||
import { timeAgo } from "@lib/time-ago"
|
import { timeAgo } from "@lib/time-ago"
|
||||||
import { useMemo, useState, useEffect } from "react"
|
import { useMemo, useState, useEffect } from "react"
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Badge, Tooltip } from "@geist-ui/core"
|
import { Badge, Tooltip } from "@geist-ui/core/dist"
|
||||||
import { timeUntil } from "@lib/time-ago"
|
import { timeUntil } from "@lib/time-ago"
|
||||||
import { useCallback, useEffect, useMemo, useState } from "react"
|
import { useCallback, useEffect, useMemo, useState } from "react"
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Badge } from "@geist-ui/core"
|
import { Badge } from "@geist-ui/core/dist"
|
||||||
import type { PostVisibility } from "@lib/types"
|
import type { PostVisibility } from "@lib/types"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import PasswordModal from "@components/new-post/password-modal"
|
import PasswordModal from "@components/new-post/password-modal"
|
||||||
import { Button, ButtonGroup, Loading, useToasts } from "@geist-ui/core"
|
import { Button, ButtonGroup, Loading, useToasts } from "@geist-ui/core/dist"
|
||||||
import type { PostVisibility } from "@lib/types"
|
import type { PostVisibility } from "@lib/types"
|
||||||
import Cookies from "js-cookie"
|
import Cookies from "js-cookie"
|
||||||
import { useCallback, useState } from "react"
|
import { useCallback, useState } from "react"
|
||||||
|
|
|
@ -7,7 +7,7 @@ import List from "@geist-ui/icons/list"
|
||||||
import ImageIcon from "@geist-ui/icons/image"
|
import ImageIcon from "@geist-ui/icons/image"
|
||||||
import { RefObject, useMemo } from "react"
|
import { RefObject, useMemo } from "react"
|
||||||
import styles from "../document.module.css"
|
import styles from "../document.module.css"
|
||||||
import { Button, ButtonGroup, Tooltip } from "@geist-ui/core"
|
import { Button, ButtonGroup, Tooltip } from "@geist-ui/core/dist"
|
||||||
import { TextareaMarkdownRef } from "textarea-markdown-editor"
|
import { TextareaMarkdownRef } from "textarea-markdown-editor"
|
||||||
|
|
||||||
// TODO: clean up
|
// TODO: clean up
|
||||||
|
|
|
@ -11,7 +11,7 @@ import Trash from "@geist-ui/icons/trash"
|
||||||
import FormattingIcons from "./formatting-icons"
|
import FormattingIcons from "./formatting-icons"
|
||||||
import TextareaMarkdown, { TextareaMarkdownRef } from "textarea-markdown-editor"
|
import TextareaMarkdown, { TextareaMarkdownRef } from "textarea-markdown-editor"
|
||||||
|
|
||||||
import { Button, Input, Spacer, Tabs, Textarea } from "@geist-ui/core"
|
import { Button, Input, Spacer, Tabs, Textarea } from "@geist-ui/core/dist"
|
||||||
import Preview from "@components/preview"
|
import Preview from "@components/preview"
|
||||||
|
|
||||||
// import Link from "next/link"
|
// import Link from "next/link"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Page } from "@geist-ui/core"
|
import { Page } from "@geist-ui/core/dist"
|
||||||
|
|
||||||
const Error = ({ status }: { status: number }) => {
|
const Error = ({ status }: { status: number }) => {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import ShiftBy from "@components/shift-by"
|
import ShiftBy from "@components/shift-by"
|
||||||
import { Button, Popover } from "@geist-ui/core"
|
import { Button, Popover } from "@geist-ui/core/dist"
|
||||||
import ChevronDown from "@geist-ui/icons/chevronDown"
|
import ChevronDown from "@geist-ui/icons/chevronDown"
|
||||||
import CodeIcon from "@geist-ui/icons/fileFunction"
|
import CodeIcon from "@geist-ui/icons/fileFunction"
|
||||||
import FileIcon from "@geist-ui/icons/fileText"
|
import FileIcon from "@geist-ui/icons/fileText"
|
||||||
|
|
|
@ -3,7 +3,7 @@ import MoonIcon from "@geist-ui/icons/moon"
|
||||||
import SunIcon from "@geist-ui/icons/sun"
|
import SunIcon from "@geist-ui/icons/sun"
|
||||||
// import { useAllThemes, useTheme } from '@geist-ui/core'
|
// import { useAllThemes, useTheme } from '@geist-ui/core'
|
||||||
import styles from "./header.module.css"
|
import styles from "./header.module.css"
|
||||||
import { Select } from "@geist-ui/core"
|
import { Select } from "@geist-ui/core/dist"
|
||||||
import { useTheme } from "next-themes"
|
import { useTheme } from "next-themes"
|
||||||
|
|
||||||
const Controls = () => {
|
const Controls = () => {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
'use client';
|
"use client"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
|
@ -7,7 +7,7 @@ import {
|
||||||
Spacer,
|
Spacer,
|
||||||
useBodyScroll,
|
useBodyScroll,
|
||||||
useMediaQuery
|
useMediaQuery
|
||||||
} from "@geist-ui/core"
|
} from "@geist-ui/core/dist"
|
||||||
|
|
||||||
import { useCallback, useEffect, useMemo, useState } from "react"
|
import { useCallback, useEffect, useMemo, useState } from "react"
|
||||||
import styles from "./header.module.css"
|
import styles from "./header.module.css"
|
||||||
|
@ -27,7 +27,7 @@ import SunIcon from "@geist-ui/icons/sun"
|
||||||
import { useTheme } from "next-themes"
|
import { useTheme } from "next-themes"
|
||||||
import useUserData from "@lib/hooks/use-user-data"
|
import useUserData from "@lib/hooks/use-user-data"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
import { useRouter } from "next/router"
|
import { usePathname } from "next/navigation"
|
||||||
|
|
||||||
type Tab = {
|
type Tab = {
|
||||||
name: string
|
name: string
|
||||||
|
@ -38,7 +38,7 @@ type Tab = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
const router = useRouter()
|
const pathname = usePathname()
|
||||||
const [expanded, setExpanded] = useState<boolean>(false)
|
const [expanded, setExpanded] = useState<boolean>(false)
|
||||||
const [, setBodyHidden] = useBodyScroll(null, { scrollLayer: true })
|
const [, setBodyHidden] = useBodyScroll(null, { scrollLayer: true })
|
||||||
const isMobile = useMediaQuery("xs", { match: "down" })
|
const isMobile = useMediaQuery("xs", { match: "down" })
|
||||||
|
@ -154,7 +154,7 @@ const Header = () => {
|
||||||
|
|
||||||
const getButton = useCallback(
|
const getButton = useCallback(
|
||||||
(tab: Tab) => {
|
(tab: Tab) => {
|
||||||
const activeStyle = router.pathname === tab.href ? styles.active : ""
|
const activeStyle = pathname === tab.href ? styles.active : ""
|
||||||
if (tab.onClick) {
|
if (tab.onClick) {
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
|
@ -170,7 +170,7 @@ const Header = () => {
|
||||||
)
|
)
|
||||||
} else if (tab.href) {
|
} else if (tab.href) {
|
||||||
return (
|
return (
|
||||||
(<Link key={tab.value} href={tab.href} className={styles.tab}>
|
<Link key={tab.value} href={tab.href} className={styles.tab}>
|
||||||
<Button
|
<Button
|
||||||
className={activeStyle}
|
className={activeStyle}
|
||||||
auto={isMobile ? false : true}
|
auto={isMobile ? false : true}
|
||||||
|
@ -179,12 +179,11 @@ const Header = () => {
|
||||||
>
|
>
|
||||||
{tab.name ? tab.name : undefined}
|
{tab.name ? tab.name : undefined}
|
||||||
</Button>
|
</Button>
|
||||||
|
</Link>
|
||||||
</Link>)
|
)
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[isMobile, onTabChange, router.pathname]
|
[isMobile, onTabChange, pathname]
|
||||||
)
|
)
|
||||||
|
|
||||||
const buttons = useMemo(() => pages.map(getButton), [pages, getButton])
|
const buttons = useMemo(() => pages.map(getButton), [pages, getButton])
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import ShiftBy from "@components/shift-by"
|
import ShiftBy from "@components/shift-by"
|
||||||
import { Spacer, Tabs, Card, Textarea, Text } from "@geist-ui/core"
|
import { Spacer, Tabs, Card, Textarea, Text } from "@geist-ui/core/dist"
|
||||||
import Image from "next/image"
|
import Image from "next/image"
|
||||||
import styles from "./home.module.css"
|
import styles from "./home.module.css"
|
||||||
import markdownStyles from "@components/preview/preview.module.css"
|
import markdownStyles from "@components/preview/preview.module.css"
|
||||||
|
|
|
@ -3,21 +3,14 @@ import NextLink from "next/link"
|
||||||
import styles from "./link.module.css"
|
import styles from "./link.module.css"
|
||||||
|
|
||||||
type LinkProps = {
|
type LinkProps = {
|
||||||
href: string,
|
|
||||||
colored?: boolean,
|
colored?: boolean,
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
} & React.ComponentProps<typeof NextLink>
|
} & React.ComponentProps<typeof NextLink>
|
||||||
|
|
||||||
const Link = ({ href, colored, children, ...props }: LinkProps) => {
|
const Link = ({ colored, children, ...props }: LinkProps) => {
|
||||||
const { basePath } = useRouter()
|
|
||||||
const propHrefWithoutLeadingSlash =
|
|
||||||
href && href.startsWith("/") ? href.substring(1) : href
|
|
||||||
|
|
||||||
const url = basePath ? `${basePath}/${propHrefWithoutLeadingSlash}` : href
|
|
||||||
|
|
||||||
const className = colored ? `${styles.link} ${styles.color}` : styles.link
|
const className = colored ? `${styles.link} ${styles.color}` : styles.link
|
||||||
return (
|
return (
|
||||||
<NextLink {...props} href={url} className={className}>
|
<NextLink {...props} className={className}>
|
||||||
{children}
|
{children}
|
||||||
</NextLink>
|
</NextLink>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import { ChangeEvent, memo } from "react"
|
import { ChangeEvent, memo } from "react"
|
||||||
import { Input } from "@geist-ui/core"
|
import { Input } from "@geist-ui/core/dist"
|
||||||
|
|
||||||
import styles from "../post.module.css"
|
import styles from "../post.module.css"
|
||||||
|
|
||||||
type props = {
|
type props = {
|
||||||
onChange: (e: ChangeEvent<HTMLInputElement>) => void
|
onChange: (e: ChangeEvent<HTMLInputElement>) => void
|
||||||
description?: string
|
description: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const Description = ({ onChange, description }: props) => {
|
const Description = ({ onChange, description }: props) => {
|
||||||
return (
|
return (
|
||||||
<div className={styles.description}>
|
<div className={styles.description}>
|
||||||
<Input
|
<Input
|
||||||
value={description}
|
value={description || ""}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
label="Description"
|
label="Description"
|
||||||
maxLength={256}
|
maxLength={256}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Text, useMediaQuery, useTheme, useToasts } from "@geist-ui/core"
|
import { Text, useMediaQuery, useTheme, useToasts } from "@geist-ui/core/dist"
|
||||||
import { memo } from "react"
|
import { memo } from "react"
|
||||||
import { useDropzone } from "react-dropzone"
|
import { useDropzone } from "react-dropzone"
|
||||||
import styles from "./drag-and-drop.module.css"
|
import styles from "./drag-and-drop.module.css"
|
||||||
|
|
|
@ -1,64 +1,52 @@
|
||||||
import { Button, useToasts, ButtonDropdown, Input } from "@geist-ui/core"
|
"use client"
|
||||||
import { useRouter } from "next/router"
|
|
||||||
|
import { Button, useToasts, Input, ButtonDropdown } from "@geist-ui/core/dist"
|
||||||
|
import { useRouter } from "next/navigation"
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||||
import generateUUID from "@lib/generate-uuid"
|
import generateUUID from "@lib/generate-uuid"
|
||||||
import FileDropzone from "./drag-and-drop"
|
import FileDropzone from "./drag-and-drop"
|
||||||
import styles from "./post.module.css"
|
import styles from "./post.module.css"
|
||||||
import Title from "./title"
|
import Title from "./title"
|
||||||
import Cookies from "js-cookie"
|
import Cookies from "js-cookie"
|
||||||
import type {
|
import type { PostVisibility, Document as DocumentType } from "@lib/types"
|
||||||
Post as PostType,
|
|
||||||
PostVisibility,
|
|
||||||
Document as DocumentType
|
|
||||||
} from "@lib/types"
|
|
||||||
import PasswordModal from "./password-modal"
|
import PasswordModal from "./password-modal"
|
||||||
import EditDocumentList from "@components/edit-document-list"
|
import EditDocumentList from "@components/edit-document-list"
|
||||||
import { ChangeEvent } from "react"
|
import { ChangeEvent } from "react"
|
||||||
import DatePicker from "react-datepicker"
|
import DatePicker from "react-datepicker"
|
||||||
import getTitleForPostCopy from "@lib/get-title-for-post-copy"
|
import getTitleForPostCopy from "@lib/get-title-for-post-copy"
|
||||||
import Description from "./description"
|
import Description from "./description"
|
||||||
|
import { PostWithFiles } from "app/prisma"
|
||||||
|
|
||||||
|
const emptyDoc = {
|
||||||
|
title: "",
|
||||||
|
content: "",
|
||||||
|
id: generateUUID()
|
||||||
|
}
|
||||||
|
|
||||||
const Post = ({
|
const Post = ({
|
||||||
initialPost,
|
initialPost,
|
||||||
newPostParent
|
newPostParent
|
||||||
}: {
|
}: {
|
||||||
initialPost?: PostType
|
initialPost?: PostWithFiles
|
||||||
newPostParent?: string
|
newPostParent?: string
|
||||||
}) => {
|
}) => {
|
||||||
const { setToast } = useToasts()
|
const { setToast } = useToasts()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const [title, setTitle] = useState<string>()
|
const [title, setTitle] = useState(
|
||||||
const [description, setDescription] = useState<string>()
|
getTitleForPostCopy(initialPost?.title) || ""
|
||||||
const [expiresAt, setExpiresAt] = useState<Date | null>(null)
|
|
||||||
|
|
||||||
const emptyDoc = useMemo(
|
|
||||||
() => [
|
|
||||||
{
|
|
||||||
title: "",
|
|
||||||
content: "",
|
|
||||||
id: generateUUID()
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[]
|
|
||||||
)
|
)
|
||||||
|
const [description, setDescription] = useState(initialPost?.description || "")
|
||||||
|
const [expiresAt, setExpiresAt] = useState(initialPost?.expiresAt)
|
||||||
|
|
||||||
const [docs, setDocs] = useState<DocumentType[]>(emptyDoc)
|
const defaultDocs: DocumentType[] = initialPost
|
||||||
|
? initialPost.files?.map((doc) => ({
|
||||||
// the /new/from/{id} route fetches an initial post
|
|
||||||
useEffect(() => {
|
|
||||||
if (initialPost) {
|
|
||||||
setDocs(
|
|
||||||
initialPost.files?.map((doc) => ({
|
|
||||||
title: doc.title,
|
title: doc.title,
|
||||||
content: doc.content,
|
content: doc.content,
|
||||||
id: doc.id
|
id: doc.id
|
||||||
})) || emptyDoc
|
}))
|
||||||
)
|
: [emptyDoc]
|
||||||
|
|
||||||
setTitle(getTitleForPostCopy(initialPost.title))
|
const [docs, setDocs] = useState(defaultDocs)
|
||||||
setDescription(initialPost.description)
|
|
||||||
}
|
|
||||||
}, [emptyDoc, initialPost])
|
|
||||||
|
|
||||||
const [passwordModalVisible, setPasswordModalVisible] = useState(false)
|
const [passwordModalVisible, setPasswordModalVisible] = useState(false)
|
||||||
|
|
||||||
|
@ -151,13 +139,13 @@ const Post = ({
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
await sendRequest("/server-api/posts/create", {
|
await sendRequest("/api/posts/create", {
|
||||||
title,
|
title,
|
||||||
files: docs,
|
files: docs,
|
||||||
visibility,
|
visibility,
|
||||||
password,
|
password,
|
||||||
userId: Cookies.get("drift-userid") || "",
|
userId: Cookies.get("drift-userid") || "",
|
||||||
expiresAt,
|
expiresAt: expiresAt || null,
|
||||||
parentId: newPostParent
|
parentId: newPostParent
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -233,18 +221,15 @@ const Post = ({
|
||||||
// }))
|
// }))
|
||||||
// }
|
// }
|
||||||
|
|
||||||
const onPaste = useCallback(
|
const onPaste = (e: ClipboardEvent) => {
|
||||||
(e: any) => {
|
const pastedText = e.clipboardData?.getData("text")
|
||||||
const pastedText = e.clipboardData.getData("text")
|
|
||||||
|
|
||||||
if (pastedText) {
|
if (pastedText) {
|
||||||
if (!title) {
|
if (!title) {
|
||||||
setTitle("Pasted text")
|
setTitle("Pasted text")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
[title]
|
|
||||||
)
|
|
||||||
|
|
||||||
const CustomTimeInput = ({
|
const CustomTimeInput = ({
|
||||||
date,
|
date,
|
||||||
|
@ -328,10 +313,10 @@ const Post = ({
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
<ButtonDropdown loading={isSubmitting} type="success">
|
<ButtonDropdown loading={isSubmitting} type="success">
|
||||||
<ButtonDropdown.Item onClick={() => onSubmit("unlisted")}>
|
<ButtonDropdown.Item main onClick={() => onSubmit("unlisted")}>
|
||||||
Create Unlisted
|
Create Unlisted
|
||||||
</ButtonDropdown.Item>
|
</ButtonDropdown.Item>
|
||||||
<ButtonDropdown.Item main onClick={() => onSubmit("private")}>
|
<ButtonDropdown.Item onClick={() => onSubmit("private")}>
|
||||||
Create Private
|
Create Private
|
||||||
</ButtonDropdown.Item>
|
</ButtonDropdown.Item>
|
||||||
<ButtonDropdown.Item onClick={() => onSubmit("public")}>
|
<ButtonDropdown.Item onClick={() => onSubmit("public")}>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Modal, Note, Spacer, Input } from "@geist-ui/core"
|
import { Modal, Note, Spacer, Input } from "@geist-ui/core/dist"
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { ChangeEvent, memo, useEffect, useState } from "react"
|
import { ChangeEvent, memo, useEffect, useState } from "react"
|
||||||
import { Text } from "@geist-ui/core"
|
import { Text } from "@geist-ui/core/dist"
|
||||||
|
|
||||||
import ShiftBy from "@components/shift-by"
|
import ShiftBy from "@components/shift-by"
|
||||||
import styles from "../post.module.css"
|
import styles from "../post.module.css"
|
||||||
import { Input } from "@geist-ui/core"
|
import { Input } from "@geist-ui/core/dist"
|
||||||
|
|
||||||
const titlePlaceholders = [
|
const titlePlaceholders = [
|
||||||
"How to...",
|
"How to...",
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
background: red;
|
background: #f33;
|
||||||
}
|
}
|
||||||
|
|
||||||
.type {
|
.type {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import Head from "next/head"
|
|
||||||
import React from "react"
|
import React from "react"
|
||||||
|
|
||||||
type PageSeoProps = {
|
type PageSeoProps = {
|
||||||
|
@ -15,10 +14,8 @@ const PageSeo = ({
|
||||||
}: PageSeoProps) => {
|
}: PageSeoProps) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Head>
|
<title>Drift - {title}</title>
|
||||||
<title>{title}</title>
|
|
||||||
{!isPrivate && <meta name="description" content={description} />}
|
{!isPrivate && <meta name="description" content={description} />}
|
||||||
</Head>
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Button, Input, Text } from "@geist-ui/core"
|
import { Button, Input, Text } from "@geist-ui/core/dist"
|
||||||
|
|
||||||
import styles from "./post-list.module.css"
|
import styles from "./post-list.module.css"
|
||||||
import ListItemSkeleton from "./list-item-skeleton"
|
import ListItemSkeleton from "./list-item-skeleton"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import Skeleton from "react-loading-skeleton"
|
import Skeleton from "react-loading-skeleton"
|
||||||
import { Card, Divider, Grid, Spacer } from "@geist-ui/core"
|
import { Card, Divider, Grid, Spacer } from "@geist-ui/core/dist"
|
||||||
|
|
||||||
const ListItemSkeleton = () => (
|
const ListItemSkeleton = () => (
|
||||||
<Card>
|
<Card>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import NextLink from "next/link"
|
import NextLink from "next/link"
|
||||||
import VisibilityBadge from "../badges/visibility-badge"
|
import VisibilityBadge from "../badges/visibility-badge"
|
||||||
import { Text, Card, Tooltip, Divider, Badge, Button } from "@geist-ui/core"
|
import { Text, Card, Tooltip, Divider, Badge, Button } from "@geist-ui/core/dist"
|
||||||
import { File, Post } from "@lib/types"
|
import { File, Post } from "@lib/types"
|
||||||
import FadeIn from "@components/fade-in"
|
import FadeIn from "@components/fade-in"
|
||||||
import Trash from "@geist-ui/icons/trash"
|
import Trash from "@geist-ui/icons/trash"
|
||||||
|
|
|
@ -5,7 +5,7 @@ import styles from "./post-page.module.css"
|
||||||
import homeStyles from "@styles/Home.module.css"
|
import homeStyles from "@styles/Home.module.css"
|
||||||
|
|
||||||
import type { File, Post, PostVisibility } from "@lib/types"
|
import type { File, Post, PostVisibility } from "@lib/types"
|
||||||
import { Page, Button, Text, ButtonGroup, useMediaQuery } from "@geist-ui/core"
|
import { Page, Button, Text, ButtonGroup, useMediaQuery } from "@geist-ui/core/dist"
|
||||||
import { useEffect, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
import Archive from "@geist-ui/icons/archive"
|
import Archive from "@geist-ui/icons/archive"
|
||||||
import Edit from "@geist-ui/icons/edit"
|
import Edit from "@geist-ui/icons/edit"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import PasswordModal from "@components/new-post/password-modal"
|
import PasswordModal from "@components/new-post/password-modal"
|
||||||
import { Page, useToasts } from "@geist-ui/core"
|
import { Page, useToasts } from "@geist-ui/core/dist"
|
||||||
import { Post } from "@lib/types"
|
import { Post } from "@lib/types"
|
||||||
import { useRouter } from "next/router"
|
import { useRouter } from "next/router"
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
|
|
|
@ -16,7 +16,7 @@ const MarkdownPreview = ({ height = 500, fileId, content, title }: Props) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchPost() {
|
async function fetchPost() {
|
||||||
if (fileId) {
|
if (fileId) {
|
||||||
const resp = await fetch(`/api/html/${fileId}`, {
|
const resp = await fetch(`/api/file/html/${fileId}`, {
|
||||||
method: "GET"
|
method: "GET"
|
||||||
})
|
})
|
||||||
if (resp.ok) {
|
if (resp.ok) {
|
||||||
|
@ -25,16 +25,19 @@ const MarkdownPreview = ({ height = 500, fileId, content, title }: Props) => {
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
}
|
}
|
||||||
} else if (content) {
|
} else if (content) {
|
||||||
const resp = await fetch("/server-api/files/html", {
|
// add title and query to url params
|
||||||
method: "POST",
|
const urlQuery = new URLSearchParams({
|
||||||
|
title: title || "",
|
||||||
|
content
|
||||||
|
})
|
||||||
|
|
||||||
|
const resp = await fetch(`/api/files/get-html?${urlQuery}`, {
|
||||||
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Authorization: `Bearer ${Cookies.get("drift-token") || ""}`
|
Authorization: `Bearer ${Cookies.get("drift-token") || ""}`
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
|
||||||
title,
|
|
||||||
content
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (resp.ok) {
|
if (resp.ok) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Tooltip, Button, Spacer } from "@geist-ui/core"
|
import { Tooltip, Button, Spacer } from "@geist-ui/core/dist"
|
||||||
import ChevronUp from "@geist-ui/icons/chevronUpCircleFill"
|
import ChevronUp from "@geist-ui/icons/chevronUpCircleFill"
|
||||||
import { useEffect, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
import styles from "./scroll.module.css"
|
import styles from "./scroll.module.css"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Fieldset, Text, Divider } from "@geist-ui/core"
|
import { Fieldset, Text, Divider } from "@geist-ui/core/dist"
|
||||||
import styles from "./settings-group.module.css"
|
import styles from "./settings-group.module.css"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Input, Button, useToasts } from "@geist-ui/core"
|
import { Input, Button, useToasts } from "@geist-ui/core/dist"
|
||||||
import Cookies from "js-cookie"
|
import Cookies from "js-cookie"
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Note, Input, Textarea, Button, useToasts } from "@geist-ui/core"
|
import { Note, Input, Textarea, Button, useToasts } from "@geist-ui/core/dist"
|
||||||
import useUserData from "@lib/hooks/use-user-data"
|
import useUserData from "@lib/hooks/use-user-data"
|
||||||
import Cookies from "js-cookie"
|
import Cookies from "js-cookie"
|
||||||
import { useEffect, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {
|
||||||
Textarea,
|
Textarea,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Tag
|
Tag
|
||||||
} from "@geist-ui/core"
|
} from "@geist-ui/core/dist"
|
||||||
import HtmlPreview from "@components/preview"
|
import HtmlPreview from "@components/preview"
|
||||||
import FadeIn from "@components/fade-in"
|
import FadeIn from "@components/fade-in"
|
||||||
|
|
||||||
|
|
27
client/lib/api/generate-access-token.ts
Normal file
27
client/lib/api/generate-access-token.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import config from "@lib/config"
|
||||||
|
import { User } from "@prisma/client"
|
||||||
|
import prisma from "app/prisma"
|
||||||
|
import { sign } from "jsonwebtoken"
|
||||||
|
|
||||||
|
export async function generateAccessToken(user: User) {
|
||||||
|
const token = sign({ id: user.id }, config.jwt_secret, { expiresIn: "2d" })
|
||||||
|
|
||||||
|
await prisma.authTokens.create({
|
||||||
|
data: {
|
||||||
|
userId: user.id,
|
||||||
|
token: token
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO: set expiredReason?
|
||||||
|
prisma.authTokens.deleteMany({
|
||||||
|
where: {
|
||||||
|
userId: user.id,
|
||||||
|
token: {
|
||||||
|
not: token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return token
|
||||||
|
}
|
39
client/lib/api/get-html-from-drift-file.ts
Normal file
39
client/lib/api/get-html-from-drift-file.ts
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import markdown from "../render-markdown"
|
||||||
|
import type { File } from "app/prisma"
|
||||||
|
/**
|
||||||
|
* returns rendered HTML from a Drift file
|
||||||
|
*/
|
||||||
|
function getHtmlFromFile({ content, title }: Pick<File, "content" | "title">) {
|
||||||
|
const renderAsMarkdown = [
|
||||||
|
"markdown",
|
||||||
|
"md",
|
||||||
|
"mdown",
|
||||||
|
"mkdn",
|
||||||
|
"mkd",
|
||||||
|
"mdwn",
|
||||||
|
"mdtxt",
|
||||||
|
"mdtext",
|
||||||
|
"text",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
const fileType = () => {
|
||||||
|
const pathParts = title.split(".")
|
||||||
|
const language = pathParts.length > 1 ? pathParts[pathParts.length - 1] : ""
|
||||||
|
return language
|
||||||
|
}
|
||||||
|
const type = fileType()
|
||||||
|
let contentToRender: string = content || ""
|
||||||
|
|
||||||
|
if (!renderAsMarkdown.includes(type)) {
|
||||||
|
contentToRender = `~~~${type}
|
||||||
|
${content}
|
||||||
|
~~~`
|
||||||
|
} else {
|
||||||
|
contentToRender = "\n" + content
|
||||||
|
}
|
||||||
|
|
||||||
|
const html = markdown(contentToRender)
|
||||||
|
return html
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getHtmlFromFile
|
64
client/lib/api/jwt.ts
Normal file
64
client/lib/api/jwt.ts
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
// next api route jwt middleware; check if the user has a valid jwt token
|
||||||
|
|
||||||
|
import config from "@lib/config"
|
||||||
|
import { User } from "@prisma/client"
|
||||||
|
import prisma from "app/prisma"
|
||||||
|
import * as jwt from "jsonwebtoken"
|
||||||
|
import next, { NextApiHandler, NextApiRequest, NextApiResponse } from "next"
|
||||||
|
|
||||||
|
type ReqWithUser = NextApiRequest & {
|
||||||
|
user?: User
|
||||||
|
}
|
||||||
|
|
||||||
|
type WrappedHandler = (req: ReqWithUser, res: NextApiResponse) => Promise<void>
|
||||||
|
|
||||||
|
// usage: useJwt(otherHandler)
|
||||||
|
|
||||||
|
// we want the usage to be the user writing their API route and exporting it with useJwt(handler)
|
||||||
|
|
||||||
|
// uses prisma
|
||||||
|
export async function withJwt(
|
||||||
|
origHandler: NextApiHandler
|
||||||
|
): Promise<WrappedHandler | void> {
|
||||||
|
return async (req: ReqWithUser, res: NextApiResponse) => {
|
||||||
|
const authHeader = req ? req.headers["authorization"] : undefined
|
||||||
|
const token = authHeader && authHeader.split(" ")[1]
|
||||||
|
|
||||||
|
if (token == null) return res.status(401).send("Unauthorized")
|
||||||
|
|
||||||
|
const authToken = await prisma.authTokens.findUnique({
|
||||||
|
where: { id: token }
|
||||||
|
})
|
||||||
|
if (authToken == null) {
|
||||||
|
return res.status(401).send("Unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authToken.deletedAt) {
|
||||||
|
return res.status(401).json({
|
||||||
|
message: "Token is no longer valid"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
jwt.verify(token, config.jwt_secret, async (err: any, user: any) => {
|
||||||
|
if (err) return res.status(403).send("Forbidden")
|
||||||
|
const userObj = await prisma.user.findUnique({
|
||||||
|
where: { id: user.id },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
email: true,
|
||||||
|
displayName: true,
|
||||||
|
bio: true,
|
||||||
|
createdAt: true,
|
||||||
|
updatedAt: true,
|
||||||
|
deletedAt: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (!userObj) {
|
||||||
|
return res.status(403).send("Forbidden")
|
||||||
|
}
|
||||||
|
|
||||||
|
;(req as ReqWithUser).user = user
|
||||||
|
return origHandler(req, res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
13
client/lib/api/parse-url-query.ts
Normal file
13
client/lib/api/parse-url-query.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* Parses a URL query string from string | string[] | ...
|
||||||
|
* to string | undefined. If it's an array, we return the last item.
|
||||||
|
*/
|
||||||
|
export function parseUrlQuery(query: string | string[] | undefined) {
|
||||||
|
if (typeof query === "string") {
|
||||||
|
return query
|
||||||
|
} else if (Array.isArray(query)) {
|
||||||
|
return query[query.length - 1]
|
||||||
|
} else {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
89
client/lib/config.ts
Normal file
89
client/lib/config.ts
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
type Config = {
|
||||||
|
// port: number
|
||||||
|
jwt_secret: string
|
||||||
|
drift_home: string
|
||||||
|
is_production: boolean
|
||||||
|
memory_db: boolean
|
||||||
|
enable_admin: boolean
|
||||||
|
secret_key: string
|
||||||
|
registration_password: string
|
||||||
|
welcome_content: string
|
||||||
|
welcome_title: string
|
||||||
|
url: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type EnvironmentValue = string | undefined
|
||||||
|
type Environment = { [key: string]: EnvironmentValue }
|
||||||
|
|
||||||
|
export const config = (env: Environment): Config => {
|
||||||
|
const stringToBoolean = (str: EnvironmentValue): boolean => {
|
||||||
|
if (str === "true") {
|
||||||
|
return true
|
||||||
|
} else if (str === "false") {
|
||||||
|
return false
|
||||||
|
} else if (str) {
|
||||||
|
throw new Error(`Invalid boolean value: ${str}`)
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const throwIfUndefined = (str: EnvironmentValue, name: string): string => {
|
||||||
|
if (str === undefined) {
|
||||||
|
throw new Error(`Missing environment variable: ${name}`)
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultIfUndefined = (
|
||||||
|
str: EnvironmentValue,
|
||||||
|
defaultValue: string
|
||||||
|
): string => {
|
||||||
|
if (str === undefined) {
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
const validNodeEnvs = (str: EnvironmentValue) => {
|
||||||
|
const valid = ["development", "production", "test"]
|
||||||
|
if (str && !valid.includes(str)) {
|
||||||
|
throw new Error(`Invalid NODE_ENV set: ${str}`)
|
||||||
|
} else if (!str) {
|
||||||
|
console.warn("No NODE_ENV specified, defaulting to development")
|
||||||
|
} else {
|
||||||
|
console.log(`Using NODE_ENV: ${str}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const is_production = env.NODE_ENV === "production"
|
||||||
|
|
||||||
|
const developmentDefault = (
|
||||||
|
str: EnvironmentValue,
|
||||||
|
name: string,
|
||||||
|
defaultValue: string
|
||||||
|
): string => {
|
||||||
|
if (is_production) return throwIfUndefined(str, name)
|
||||||
|
return defaultIfUndefined(str, defaultValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
validNodeEnvs(env.NODE_ENV)
|
||||||
|
|
||||||
|
const config: Config = {
|
||||||
|
// port: env.PORT ? parseInt(env.PORT) : 3000,
|
||||||
|
jwt_secret: env.JWT_SECRET || "myjwtsecret",
|
||||||
|
drift_home: env.DRIFT_HOME || "~/.drift",
|
||||||
|
is_production,
|
||||||
|
memory_db: stringToBoolean(env.MEMORY_DB),
|
||||||
|
enable_admin: stringToBoolean(env.ENABLE_ADMIN),
|
||||||
|
secret_key: developmentDefault(env.SECRET_KEY, "SECRET_KEY", "secret"),
|
||||||
|
registration_password: env.REGISTRATION_PASSWORD ?? "",
|
||||||
|
welcome_content: env.WELCOME_CONTENT ?? "",
|
||||||
|
welcome_title: env.WELCOME_TITLE ?? "",
|
||||||
|
url: 'http://localhost:3000'
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default config(process.env)
|
|
@ -14,7 +14,9 @@ const replaceLastInString = (
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTitleForPostCopy = (title: string) => {
|
const getTitleForPostCopy = (title?: string) => {
|
||||||
|
if (!title) return ""
|
||||||
|
|
||||||
const numberAtEndOfTitle = title.split(" ").pop()
|
const numberAtEndOfTitle = title.split(" ").pop()
|
||||||
if (numberAtEndOfTitle) {
|
if (numberAtEndOfTitle) {
|
||||||
const number = parseInt(numberAtEndOfTitle)
|
const number = parseInt(numberAtEndOfTitle)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { User } from "@lib/types"
|
import { User } from "@lib/types"
|
||||||
import Cookies from "js-cookie"
|
import Cookies from "js-cookie"
|
||||||
import { useRouter } from "next/router"
|
import { useRouter } from "next/navigation"
|
||||||
import { useEffect, useMemo, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
|
|
||||||
const useUserData = () => {
|
const useUserData = () => {
|
||||||
const [authToken, setAuthToken] = useState<string>(
|
const [authToken, setAuthToken] = useState<string>(
|
||||||
|
|
189
client/lib/render-markdown.tsx
Normal file
189
client/lib/render-markdown.tsx
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
import { marked } from "marked"
|
||||||
|
// import Highlight, { defaultProps, Language } from "prism-react-renderer"
|
||||||
|
import { renderToStaticMarkup } from "react-dom/server"
|
||||||
|
import Image from "next/image"
|
||||||
|
import Link from "next/link"
|
||||||
|
|
||||||
|
// // image sizes. DDoS Safe?
|
||||||
|
// const imageSizeLink = /^!?\[((?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|[^\[\]\\])*?)\]\(\s*(<(?:\\[<>]?|[^\s<>\\])*>|(?:\\[()]?|\([^\s\x00-\x1f()\\]*\)|[^\s\x00-\x1f()\\])*?(?:\s+=(?:[\w%]+)?x(?:[\w%]+)?)?)(?:\s+("(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)))?\s*\)/;
|
||||||
|
// //@ts-ignore
|
||||||
|
// Lexer.rules.inline.normal.link = imageSizeLink;
|
||||||
|
// //@ts-ignore
|
||||||
|
// Lexer.rules.inline.gfm.link = imageSizeLink;
|
||||||
|
// //@ts-ignore
|
||||||
|
// Lexer.rules.inline.breaks.link = imageSizeLink;
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
// delete defaultProps.theme
|
||||||
|
// import linkStyles from '../components/link/link.module.css'
|
||||||
|
|
||||||
|
const renderer = new marked.Renderer()
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
renderer.heading = (text, level, _, slugger) => {
|
||||||
|
const id = slugger.slug(text)
|
||||||
|
const Component = `h${level}`
|
||||||
|
|
||||||
|
return (
|
||||||
|
<h1>
|
||||||
|
<Link
|
||||||
|
href={`#${id}`}
|
||||||
|
id={id}
|
||||||
|
style={{ color: "inherit" }}
|
||||||
|
dangerouslySetInnerHTML={{ __html: text }}
|
||||||
|
></Link>
|
||||||
|
</h1>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// renderer.link = (href, _, text) => {
|
||||||
|
// const isHrefLocal = href?.startsWith('/') || href?.startsWith('#')
|
||||||
|
// if (isHrefLocal) {
|
||||||
|
// return renderToStaticMarkup(
|
||||||
|
// <a href={href || ''}>
|
||||||
|
// {text}
|
||||||
|
// </a>
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // dirty hack
|
||||||
|
// // if text contains elements, render as html
|
||||||
|
// return <a href={href || ""} target="_blank" rel="noopener noreferrer" dangerouslySetInnerHTML={{ __html: convertHtmlEntities(text) }} ></a>
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
renderer.image = function (href, _, text) {
|
||||||
|
return <Image loading="lazy" src="${href}" alt="${text}" layout="fill" />
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.checkbox = () => ""
|
||||||
|
// @ts-ignore
|
||||||
|
renderer.listitem = (text, task, checked) => {
|
||||||
|
if (task) {
|
||||||
|
return (
|
||||||
|
<li className="reset">
|
||||||
|
<span className="check">
|
||||||
|
​
|
||||||
|
<input type="checkbox" disabled checked={checked} />
|
||||||
|
</span>
|
||||||
|
<span>${text}</span>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return `<li>${text}</li>`
|
||||||
|
}
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
renderer.code = (code: string, language: string) => {
|
||||||
|
return (
|
||||||
|
<pre>
|
||||||
|
{/* {title && <code>{title} </code>} */}
|
||||||
|
{/* {language && title && <code style={{}}> {language} </code>} */}
|
||||||
|
<Code
|
||||||
|
language={language}
|
||||||
|
// title={title}
|
||||||
|
code={code}
|
||||||
|
// highlight={highlight}
|
||||||
|
/>
|
||||||
|
</pre>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
marked.setOptions({
|
||||||
|
gfm: true,
|
||||||
|
breaks: true,
|
||||||
|
headerIds: true,
|
||||||
|
renderer
|
||||||
|
})
|
||||||
|
|
||||||
|
const markdown = (markdown: string) => marked(markdown)
|
||||||
|
|
||||||
|
export default markdown
|
||||||
|
|
||||||
|
const Code = ({
|
||||||
|
code,
|
||||||
|
language,
|
||||||
|
highlight,
|
||||||
|
title,
|
||||||
|
...props
|
||||||
|
}: {
|
||||||
|
code: string
|
||||||
|
language: string
|
||||||
|
highlight?: string
|
||||||
|
title?: string
|
||||||
|
}) => {
|
||||||
|
if (!language)
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<code {...props} dangerouslySetInnerHTML={{ __html: code }} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
|
||||||
|
const highlightedLines = highlight
|
||||||
|
? //@ts-ignore
|
||||||
|
highlight.split(",").reduce((lines, h) => {
|
||||||
|
if (h.includes("-")) {
|
||||||
|
// Expand ranges like 3-5 into [3,4,5]
|
||||||
|
const [start, end] = h.split("-").map(Number)
|
||||||
|
const x = Array(end - start + 1)
|
||||||
|
.fill(undefined)
|
||||||
|
.map((_, i) => i + start)
|
||||||
|
return [...lines, ...x]
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...lines, Number(h)]
|
||||||
|
}, [])
|
||||||
|
: ""
|
||||||
|
|
||||||
|
// https://mdxjs.com/guides/syntax-harkedighlighting#all-together
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* <Highlight
|
||||||
|
{...defaultProps}
|
||||||
|
code={code.trim()}
|
||||||
|
language={language as Language}
|
||||||
|
>
|
||||||
|
{({
|
||||||
|
className,
|
||||||
|
style,
|
||||||
|
tokens,
|
||||||
|
getLineProps,
|
||||||
|
getTokenProps
|
||||||
|
}: {
|
||||||
|
className: string
|
||||||
|
style: any
|
||||||
|
tokens: any
|
||||||
|
getLineProps: any
|
||||||
|
getTokenProps: any
|
||||||
|
}) => (
|
||||||
|
<code className={className} style={{ ...style }}>
|
||||||
|
{tokens.map((line: string[], i: number) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
{...getLineProps({ line, key: i })}
|
||||||
|
style={
|
||||||
|
//@ts-ignore
|
||||||
|
highlightedLines.includes((i + 1).toString())
|
||||||
|
? {
|
||||||
|
background: "var(--highlight)",
|
||||||
|
margin: "0 -1rem",
|
||||||
|
padding: "0 1rem"
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{line.map((token: string, key: number) => (
|
||||||
|
<span key={key} {...getTokenProps({ token, key })} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</code>
|
||||||
|
)}
|
||||||
|
</Highlight> */}
|
||||||
|
<>
|
||||||
|
<code {...props} dangerouslySetInnerHTML={{ __html: code }} />
|
||||||
|
</>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -65,7 +65,7 @@ export function middleware(req: NextRequest, event: NextFetchEvent) {
|
||||||
export const config = {
|
export const config = {
|
||||||
match: [
|
match: [
|
||||||
"/signout",
|
"/signout",
|
||||||
"/",
|
// "/",
|
||||||
"/signin",
|
"/signin",
|
||||||
"/signup",
|
"/signup",
|
||||||
"/new",
|
"/new",
|
||||||
|
|
|
@ -3,25 +3,31 @@
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev --port 3001",
|
"dev": "next dev --port 3000",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start --port 3001",
|
"start": "next start --port 3000",
|
||||||
"lint": "next lint && prettier --list-different --config .prettierrc '{components,lib,pages}/**/*.{ts,tsx}' --write",
|
"lint": "next lint && prettier --list-different --config .prettierrc '{components,lib,pages}/**/*.{ts,tsx}' --write",
|
||||||
"analyze": "cross-env ANALYZE=true next build",
|
"analyze": "cross-env ANALYZE=true next build",
|
||||||
"find:unused": "next-unused"
|
"find:unused": "next-unused",
|
||||||
|
"prisma": "prisma"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@geist-ui/core": "^2.3.8",
|
"@geist-ui/core": "^2.3.8",
|
||||||
"@geist-ui/icons": "1.0.2",
|
"@geist-ui/icons": "1.0.2",
|
||||||
|
"@prisma/client": "^4.6.0",
|
||||||
"@types/cookie": "0.5.1",
|
"@types/cookie": "0.5.1",
|
||||||
"@types/js-cookie": "3.0.2",
|
"@types/js-cookie": "3.0.2",
|
||||||
|
"bcrypt": "^5.1.0",
|
||||||
"client-zip": "2.2.1",
|
"client-zip": "2.2.1",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"cookie": "0.5.0",
|
"cookie": "0.5.0",
|
||||||
"dotenv": "16.0.0",
|
"dotenv": "16.0.0",
|
||||||
"js-cookie": "3.0.1",
|
"js-cookie": "3.0.1",
|
||||||
|
"jsonwebtoken": "^8.5.1",
|
||||||
|
"marked": "^4.2.2",
|
||||||
"next": "13.0.3-canary.2",
|
"next": "13.0.3-canary.2",
|
||||||
"next-themes": "npm:@wits/next-themes@0.2.7",
|
"next-themes": "npm:@wits/next-themes@0.2.7",
|
||||||
|
"prism-react-renderer": "^1.3.5",
|
||||||
"rc-table": "7.24.1",
|
"rc-table": "7.24.1",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-datepicker": "4.8.0",
|
"react-datepicker": "4.8.0",
|
||||||
|
@ -30,10 +36,14 @@
|
||||||
"react-hot-toast": "^2.4.0",
|
"react-hot-toast": "^2.4.0",
|
||||||
"react-loading-skeleton": "3.1.0",
|
"react-loading-skeleton": "3.1.0",
|
||||||
"swr": "1.3.0",
|
"swr": "1.3.0",
|
||||||
"textarea-markdown-editor": "0.1.13"
|
"textarea-markdown-editor": "0.1.13",
|
||||||
|
"zod": "^3.19.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@next/bundle-analyzer": "12.1.6",
|
"@next/bundle-analyzer": "12.1.6",
|
||||||
|
"@types/bcrypt": "^5.0.0",
|
||||||
|
"@types/jsonwebtoken": "^8.5.9",
|
||||||
|
"@types/marked": "^4.0.7",
|
||||||
"@types/node": "17.0.23",
|
"@types/node": "17.0.23",
|
||||||
"@types/react": "18.0.9",
|
"@types/react": "18.0.9",
|
||||||
"@types/react-datepicker": "4.4.1",
|
"@types/react-datepicker": "4.4.1",
|
||||||
|
@ -43,6 +53,7 @@
|
||||||
"eslint-config-next": "13.0.2",
|
"eslint-config-next": "13.0.2",
|
||||||
"next-unused": "0.0.6",
|
"next-unused": "0.0.6",
|
||||||
"prettier": "2.6.2",
|
"prettier": "2.6.2",
|
||||||
|
"prisma": "^4.6.0",
|
||||||
"typescript": "4.6.4",
|
"typescript": "4.6.4",
|
||||||
"typescript-plugin-css-modules": "3.4.0"
|
"typescript-plugin-css-modules": "3.4.0"
|
||||||
},
|
},
|
||||||
|
@ -59,8 +70,5 @@
|
||||||
"components",
|
"components",
|
||||||
"lib"
|
"lib"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
"overrides": {
|
|
||||||
"next": "13.0.2"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { CssBaseline } from "@geist-ui/core"
|
import { CssBaseline } from "@geist-ui/core/dist"
|
||||||
import Document, {
|
import Document, {
|
||||||
Html,
|
Html,
|
||||||
Head,
|
Head,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import styles from "@styles/Home.module.css"
|
import styles from "@styles/Home.module.css"
|
||||||
|
|
||||||
import { Page } from "@geist-ui/core"
|
import { Page } from "@geist-ui/core/dist"
|
||||||
import { useEffect } from "react"
|
import { useEffect } from "react"
|
||||||
import Admin from "@components/admin"
|
import Admin from "@components/admin"
|
||||||
import useSignedIn from "@lib/hooks/use-signed-in"
|
import useSignedIn from "@lib/hooks/use-signed-in"
|
||||||
|
|
32
client/pages/api/auth/backup.ts
Normal file
32
client/pages/api/auth/backup.ts
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import config from "@lib/config"
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next"
|
||||||
|
|
||||||
|
const handleRequiresPasscode = async (
|
||||||
|
req: NextApiRequest,
|
||||||
|
res: NextApiResponse
|
||||||
|
) => {
|
||||||
|
const requiresPasscode = Boolean(config.registration_password)
|
||||||
|
return res.json({ requiresPasscode })
|
||||||
|
}
|
||||||
|
|
||||||
|
const PATH_TO_HANDLER = {
|
||||||
|
"requires-passcode": handleRequiresPasscode
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/no-anonymous-default-export
|
||||||
|
export default (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
|
const { slug } = req.query
|
||||||
|
|
||||||
|
if (!slug || Array.isArray(slug)) {
|
||||||
|
return res.status(400).json({ error: "Missing param" })
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (req.method) {
|
||||||
|
case "GET":
|
||||||
|
if (PATH_TO_HANDLER[slug as keyof typeof PATH_TO_HANDLER]) {
|
||||||
|
return PATH_TO_HANDLER[slug as keyof typeof PATH_TO_HANDLER](req, res)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return res.status(405).json({ error: "Method not allowed" })
|
||||||
|
}
|
||||||
|
}
|
35
client/pages/api/auth/requires-passcode.ts
Normal file
35
client/pages/api/auth/requires-passcode.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import config from "@lib/config"
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next"
|
||||||
|
|
||||||
|
|
||||||
|
export const getRequiresPasscode = async () => {
|
||||||
|
const requiresPasscode = Boolean(config.registration_password)
|
||||||
|
return requiresPasscode
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRequiresPasscode = async (
|
||||||
|
req: NextApiRequest,
|
||||||
|
res: NextApiResponse
|
||||||
|
) => {
|
||||||
|
return res.json({ requiresPasscode: await getRequiresPasscode() })
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function requiresPasscode(
|
||||||
|
req: NextApiRequest,
|
||||||
|
res: NextApiResponse
|
||||||
|
) {
|
||||||
|
const { slug } = req.query
|
||||||
|
|
||||||
|
if (!slug || Array.isArray(slug)) {
|
||||||
|
return res.status(400).json({ error: "Missing param" })
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (req.method) {
|
||||||
|
case "GET":
|
||||||
|
if (slug === "requires-passcode") {
|
||||||
|
return handleRequiresPasscode(req, res)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return res.status(405).json({ error: "Method not allowed" })
|
||||||
|
}
|
||||||
|
}
|
36
client/pages/api/auth/signin.ts
Normal file
36
client/pages/api/auth/signin.ts
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import config from "@lib/config"
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next"
|
||||||
|
import prisma from "app/prisma"
|
||||||
|
import bcrypt from "bcrypt"
|
||||||
|
import { generateAccessToken } from "@lib/api/generate-access-token"
|
||||||
|
import Cookies from "js-cookie"
|
||||||
|
|
||||||
|
export default async function handler(
|
||||||
|
req: NextApiRequest,
|
||||||
|
res: NextApiResponse
|
||||||
|
) {
|
||||||
|
const { username, password } = req.body
|
||||||
|
if (!username || !password) {
|
||||||
|
return res.status(400).json({ error: "Missing param" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await prisma.user.findFirst({
|
||||||
|
where: {
|
||||||
|
username
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(401).json({ error: "Unauthorized" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const isPasswordValid = await bcrypt.compare(password, user.password)
|
||||||
|
if (!isPasswordValid) {
|
||||||
|
return res.status(401).json({ error: "Unauthorized" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = await generateAccessToken(user)
|
||||||
|
Cookies.set("drift-user", user.id, { path: "/" })
|
||||||
|
Cookies.set("drift-token", token, { path: "/" })
|
||||||
|
return res.status(201).json({ token: token, userId: user.id })
|
||||||
|
}
|
45
client/pages/api/auth/signup.ts
Normal file
45
client/pages/api/auth/signup.ts
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import config from "@lib/config"
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next"
|
||||||
|
import prisma from "app/prisma"
|
||||||
|
import bcrypt, { genSalt } from "bcrypt"
|
||||||
|
import { generateAccessToken } from "@lib/api/generate-access-token"
|
||||||
|
|
||||||
|
export default async function handler(
|
||||||
|
req: NextApiRequest,
|
||||||
|
res: NextApiResponse
|
||||||
|
) {
|
||||||
|
const { username, password, serverPassword } = req.body
|
||||||
|
if (!username || !password) {
|
||||||
|
return res.status(400).json({ error: "Missing param" })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
config.registration_password &&
|
||||||
|
serverPassword !== config.registration_password
|
||||||
|
) {
|
||||||
|
console.log("Registration password mismatch")
|
||||||
|
return res.status(401).json({ error: "Unauthorized" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const salt = await genSalt(10)
|
||||||
|
|
||||||
|
// the first user is the admin
|
||||||
|
const isUserAdminByDefault = config.enable_admin && (await prisma.user.count()) === 0
|
||||||
|
const userRole = isUserAdminByDefault ? "admin" : "user"
|
||||||
|
|
||||||
|
const user = await prisma.user.create({
|
||||||
|
data: {
|
||||||
|
username,
|
||||||
|
password: await bcrypt.hash(password, salt),
|
||||||
|
role: userRole
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const token = await generateAccessToken(user)
|
||||||
|
|
||||||
|
return res.status(201).json({ token: token, userId: user.id })
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
52
client/pages/api/file/get-html.ts
Normal file
52
client/pages/api/file/get-html.ts
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import getHtmlFromFile from "@lib/api/get-html-from-drift-file"
|
||||||
|
import { parseUrlQuery } from "@lib/api/parse-url-query"
|
||||||
|
import prisma from "app/prisma"
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next"
|
||||||
|
|
||||||
|
export default async function handler(
|
||||||
|
req: NextApiRequest,
|
||||||
|
res: NextApiResponse
|
||||||
|
) {
|
||||||
|
switch (req.method) {
|
||||||
|
case "GET":
|
||||||
|
const query = req.query
|
||||||
|
const fileId = parseUrlQuery(query.fileId)
|
||||||
|
const content = parseUrlQuery(query.content)
|
||||||
|
const title = parseUrlQuery(query.title)
|
||||||
|
|
||||||
|
if (fileId && (content || title)) {
|
||||||
|
return res.status(400).json({ error: "Too many arguments" })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileId) {
|
||||||
|
// TODO: abstract to getFileById
|
||||||
|
const file = await prisma.file.findUnique({
|
||||||
|
where: {
|
||||||
|
id: fileId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
return res.status(404).json({ error: "File not found" })
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json(file.html)
|
||||||
|
} else {
|
||||||
|
if (!content || !title) {
|
||||||
|
return res.status(400).json({ error: "Missing arguments" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderedHTML = getHtmlFromFile({
|
||||||
|
title,
|
||||||
|
content
|
||||||
|
})
|
||||||
|
|
||||||
|
res.setHeader("Content-Type", "text/plain")
|
||||||
|
res.status(200).write(renderedHTML)
|
||||||
|
res.end()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return res.status(405).json({ error: "Method not allowed" })
|
||||||
|
}
|
||||||
|
}
|
32
client/pages/api/user/[slug].ts
Normal file
32
client/pages/api/user/[slug].ts
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import { withJwt } from "@lib/api/jwt"
|
||||||
|
import config from "@lib/config"
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next"
|
||||||
|
|
||||||
|
const handleSelf = async (
|
||||||
|
req: NextApiRequest,
|
||||||
|
res: NextApiResponse
|
||||||
|
) => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const PATH_TO_HANDLER = {
|
||||||
|
"self": handleRequiresPasscode
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/no-anonymous-default-export
|
||||||
|
export default withJwt((req: NextApiRequest, res: NextApiResponse) => {
|
||||||
|
const { slug } = req.query
|
||||||
|
|
||||||
|
if (!slug || Array.isArray(slug)) {
|
||||||
|
return res.status(400).json({ error: "Missing param" })
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (req.method) {
|
||||||
|
case "GET":
|
||||||
|
if (PATH_TO_HANDLER[slug as keyof typeof PATH_TO_HANDLER]) {
|
||||||
|
return PATH_TO_HANDLER[slug as keyof typeof PATH_TO_HANDLER](req, res)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return res.status(405).json({ error: "Method not allowed" })
|
||||||
|
}
|
||||||
|
})
|
34
client/pages/api/welcome.ts
Normal file
34
client/pages/api/welcome.ts
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// a nextjs api handerl
|
||||||
|
|
||||||
|
import config from "@lib/config"
|
||||||
|
import markdown from "@lib/render-markdown"
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next"
|
||||||
|
|
||||||
|
export const getWelcomeContent = async () => {
|
||||||
|
const introContent = config.welcome_content
|
||||||
|
const introTitle = config.welcome_title
|
||||||
|
// if (!introContent || !introTitle) {
|
||||||
|
// return {}
|
||||||
|
// }
|
||||||
|
|
||||||
|
console.log(introContent)
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: introTitle,
|
||||||
|
content: introContent,
|
||||||
|
rendered: markdown(introContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function handler(
|
||||||
|
req: NextApiRequest,
|
||||||
|
res: NextApiResponse
|
||||||
|
) {
|
||||||
|
const welcomeContent = await getWelcomeContent()
|
||||||
|
if (!welcomeContent) {
|
||||||
|
return res.status(500).json({ error: "Missing welcome content" })
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json(welcomeContent)
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import { Note, Page, Text } from "@geist-ui/core"
|
import { Note, Page, Text } from "@geist-ui/core/dist"
|
||||||
import styles from "@styles/Home.module.css"
|
import styles from "@styles/Home.module.css"
|
||||||
|
|
||||||
const Expired = () => {
|
const Expired = () => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import styles from "@styles/Home.module.css"
|
import styles from "@styles/Home.module.css"
|
||||||
import PageSeo from "@components/page-seo"
|
import PageSeo from "@components/page-seo"
|
||||||
import HomeComponent from "@components/home"
|
import HomeComponent from "@components/home"
|
||||||
import { Page, Text } from "@geist-ui/core"
|
import { Page, Text } from "@geist-ui/core/dist"
|
||||||
import type { GetStaticProps } from "next"
|
import type { GetStaticProps } from "next"
|
||||||
import { InferGetStaticPropsType } from "next"
|
import { InferGetStaticPropsType } from "next"
|
||||||
type Props =
|
type Props =
|
||||||
|
|
|
@ -5,7 +5,7 @@ import MyPosts from "@components/my-posts"
|
||||||
import cookie from "cookie"
|
import cookie from "cookie"
|
||||||
import type { GetServerSideProps } from "next"
|
import type { GetServerSideProps } from "next"
|
||||||
import { Post } from "@lib/types"
|
import { Post } from "@lib/types"
|
||||||
import { Page } from "@geist-ui/core"
|
import { Page } from "@geist-ui/core/dist"
|
||||||
|
|
||||||
const Home = ({
|
const Home = ({
|
||||||
morePosts,
|
morePosts,
|
||||||
|
|
|
@ -2,7 +2,7 @@ import styles from "@styles/Home.module.css"
|
||||||
import NewPost from "@components/new-post"
|
import NewPost from "@components/new-post"
|
||||||
import Header from "@components/header"
|
import Header from "@components/header"
|
||||||
import PageSeo from "@components/page-seo"
|
import PageSeo from "@components/page-seo"
|
||||||
import { Page } from "@geist-ui/core"
|
import { Page } from "@geist-ui/core/dist"
|
||||||
import Head from "next/head"
|
import Head from "next/head"
|
||||||
import { GetServerSideProps } from "next"
|
import { GetServerSideProps } from "next"
|
||||||
import { Post } from "@lib/types"
|
import { Post } from "@lib/types"
|
|
@ -2,7 +2,7 @@ import styles from "@styles/Home.module.css"
|
||||||
import NewPost from "@components/new-post"
|
import NewPost from "@components/new-post"
|
||||||
import Header from "@components/header"
|
import Header from "@components/header"
|
||||||
import PageSeo from "@components/page-seo"
|
import PageSeo from "@components/page-seo"
|
||||||
import { Page } from "@geist-ui/core"
|
import { Page } from "@geist-ui/core/dist"
|
||||||
import Head from "next/head"
|
import Head from "next/head"
|
||||||
|
|
||||||
const New = () => {
|
const New = () => {
|
|
@ -7,7 +7,7 @@ import {
|
||||||
Page,
|
Page,
|
||||||
Note,
|
Note,
|
||||||
Textarea
|
Textarea
|
||||||
} from "@geist-ui/core"
|
} from "@geist-ui/core/dist"
|
||||||
import PageSeo from "@components/page-seo"
|
import PageSeo from "@components/page-seo"
|
||||||
import styles from "@styles/Home.module.css"
|
import styles from "@styles/Home.module.css"
|
||||||
import SettingsPage from "@components/settings"
|
import SettingsPage from "@components/settings"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Page } from "@geist-ui/core"
|
import { Page } from "@geist-ui/core/dist"
|
||||||
import PageSeo from "@components/page-seo"
|
import PageSeo from "@components/page-seo"
|
||||||
import Auth from "@components/auth"
|
import Auth from "@components/auth"
|
||||||
import styles from "@styles/Home.module.css"
|
import styles from "@styles/Home.module.css"
|
|
@ -1,4 +1,4 @@
|
||||||
import { Page } from "@geist-ui/core"
|
import { Page } from "@geist-ui/core/dist"
|
||||||
import Auth from "@components/auth"
|
import Auth from "@components/auth"
|
||||||
import PageSeo from "@components/page-seo"
|
import PageSeo from "@components/page-seo"
|
||||||
import styles from "@styles/Home.module.css"
|
import styles from "@styles/Home.module.css"
|
|
@ -4,12 +4,17 @@ specifiers:
|
||||||
'@geist-ui/core': ^2.3.8
|
'@geist-ui/core': ^2.3.8
|
||||||
'@geist-ui/icons': 1.0.2
|
'@geist-ui/icons': 1.0.2
|
||||||
'@next/bundle-analyzer': 12.1.6
|
'@next/bundle-analyzer': 12.1.6
|
||||||
|
'@prisma/client': ^4.6.0
|
||||||
|
'@types/bcrypt': ^5.0.0
|
||||||
'@types/cookie': 0.5.1
|
'@types/cookie': 0.5.1
|
||||||
'@types/js-cookie': 3.0.2
|
'@types/js-cookie': 3.0.2
|
||||||
|
'@types/jsonwebtoken': ^8.5.9
|
||||||
|
'@types/marked': ^4.0.7
|
||||||
'@types/node': 17.0.23
|
'@types/node': 17.0.23
|
||||||
'@types/react': 18.0.9
|
'@types/react': 18.0.9
|
||||||
'@types/react-datepicker': 4.4.1
|
'@types/react-datepicker': 4.4.1
|
||||||
'@types/react-dom': 18.0.3
|
'@types/react-dom': 18.0.3
|
||||||
|
bcrypt: ^5.1.0
|
||||||
client-zip: 2.2.1
|
client-zip: 2.2.1
|
||||||
clsx: ^1.2.1
|
clsx: ^1.2.1
|
||||||
cookie: 0.5.0
|
cookie: 0.5.0
|
||||||
|
@ -18,10 +23,14 @@ specifiers:
|
||||||
eslint: 8.27.0
|
eslint: 8.27.0
|
||||||
eslint-config-next: 13.0.2
|
eslint-config-next: 13.0.2
|
||||||
js-cookie: 3.0.1
|
js-cookie: 3.0.1
|
||||||
|
jsonwebtoken: ^8.5.1
|
||||||
|
marked: ^4.2.2
|
||||||
next: 13.0.3-canary.2
|
next: 13.0.3-canary.2
|
||||||
next-themes: npm:@wits/next-themes@0.2.7
|
next-themes: npm:@wits/next-themes@0.2.7
|
||||||
next-unused: 0.0.6
|
next-unused: 0.0.6
|
||||||
prettier: 2.6.2
|
prettier: 2.6.2
|
||||||
|
prism-react-renderer: ^1.3.5
|
||||||
|
prisma: ^4.6.0
|
||||||
rc-table: 7.24.1
|
rc-table: 7.24.1
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-datepicker: 4.8.0
|
react-datepicker: 4.8.0
|
||||||
|
@ -34,19 +43,25 @@ specifiers:
|
||||||
textarea-markdown-editor: 0.1.13
|
textarea-markdown-editor: 0.1.13
|
||||||
typescript: 4.6.4
|
typescript: 4.6.4
|
||||||
typescript-plugin-css-modules: 3.4.0
|
typescript-plugin-css-modules: 3.4.0
|
||||||
|
zod: ^3.19.1
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
'@geist-ui/core': 2.3.8_biqbaboplfbrettd7655fr4n2y
|
'@geist-ui/core': 2.3.8_biqbaboplfbrettd7655fr4n2y
|
||||||
'@geist-ui/icons': 1.0.2_zhza2kbnl2wkkf7vqdl3ton2f4
|
'@geist-ui/icons': 1.0.2_zhza2kbnl2wkkf7vqdl3ton2f4
|
||||||
|
'@prisma/client': 4.6.0_prisma@4.6.0
|
||||||
'@types/cookie': 0.5.1
|
'@types/cookie': 0.5.1
|
||||||
'@types/js-cookie': 3.0.2
|
'@types/js-cookie': 3.0.2
|
||||||
|
bcrypt: 5.1.0
|
||||||
client-zip: 2.2.1
|
client-zip: 2.2.1
|
||||||
clsx: 1.2.1
|
clsx: 1.2.1
|
||||||
cookie: 0.5.0
|
cookie: 0.5.0
|
||||||
dotenv: 16.0.0
|
dotenv: 16.0.0
|
||||||
js-cookie: 3.0.1
|
js-cookie: 3.0.1
|
||||||
|
jsonwebtoken: 8.5.1
|
||||||
|
marked: 4.2.2
|
||||||
next: 13.0.3-canary.2_biqbaboplfbrettd7655fr4n2y
|
next: 13.0.3-canary.2_biqbaboplfbrettd7655fr4n2y
|
||||||
next-themes: /@wits/next-themes/0.2.7_qjr36eup74ongf7bl2iopfchwe
|
next-themes: /@wits/next-themes/0.2.7_qjr36eup74ongf7bl2iopfchwe
|
||||||
|
prism-react-renderer: 1.3.5_react@18.2.0
|
||||||
rc-table: 7.24.1_biqbaboplfbrettd7655fr4n2y
|
rc-table: 7.24.1_biqbaboplfbrettd7655fr4n2y
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-datepicker: 4.8.0_biqbaboplfbrettd7655fr4n2y
|
react-datepicker: 4.8.0_biqbaboplfbrettd7655fr4n2y
|
||||||
|
@ -56,12 +71,16 @@ dependencies:
|
||||||
react-loading-skeleton: 3.1.0_react@18.2.0
|
react-loading-skeleton: 3.1.0_react@18.2.0
|
||||||
swr: 1.3.0_react@18.2.0
|
swr: 1.3.0_react@18.2.0
|
||||||
textarea-markdown-editor: 0.1.13_biqbaboplfbrettd7655fr4n2y
|
textarea-markdown-editor: 0.1.13_biqbaboplfbrettd7655fr4n2y
|
||||||
|
zod: 3.19.1
|
||||||
|
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
sharp: 0.31.2
|
sharp: 0.31.2
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@next/bundle-analyzer': 12.1.6
|
'@next/bundle-analyzer': 12.1.6
|
||||||
|
'@types/bcrypt': 5.0.0
|
||||||
|
'@types/jsonwebtoken': 8.5.9
|
||||||
|
'@types/marked': 4.0.7
|
||||||
'@types/node': 17.0.23
|
'@types/node': 17.0.23
|
||||||
'@types/react': 18.0.9
|
'@types/react': 18.0.9
|
||||||
'@types/react-datepicker': 4.4.1_biqbaboplfbrettd7655fr4n2y
|
'@types/react-datepicker': 4.4.1_biqbaboplfbrettd7655fr4n2y
|
||||||
|
@ -71,6 +90,7 @@ devDependencies:
|
||||||
eslint-config-next: 13.0.2_hsmo2rtalirsvadpuxki35bq2i
|
eslint-config-next: 13.0.2_hsmo2rtalirsvadpuxki35bq2i
|
||||||
next-unused: 0.0.6
|
next-unused: 0.0.6
|
||||||
prettier: 2.6.2
|
prettier: 2.6.2
|
||||||
|
prisma: 4.6.0
|
||||||
typescript: 4.6.4
|
typescript: 4.6.4
|
||||||
typescript-plugin-css-modules: 3.4.0_typescript@4.6.4
|
typescript-plugin-css-modules: 3.4.0_typescript@4.6.4
|
||||||
|
|
||||||
|
@ -175,6 +195,24 @@ packages:
|
||||||
resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
|
resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@mapbox/node-pre-gyp/1.0.10:
|
||||||
|
resolution: {integrity: sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
detect-libc: 2.0.1
|
||||||
|
https-proxy-agent: 5.0.1
|
||||||
|
make-dir: 3.1.0
|
||||||
|
node-fetch: 2.6.7
|
||||||
|
nopt: 5.0.0
|
||||||
|
npmlog: 5.0.1
|
||||||
|
rimraf: 3.0.2
|
||||||
|
semver: 7.3.8
|
||||||
|
tar: 6.1.12
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@next/bundle-analyzer/12.1.6:
|
/@next/bundle-analyzer/12.1.6:
|
||||||
resolution: {integrity: sha512-WLydwytAeHoC/neXsiIgK+a6Me12PuSpwopnsZgX5JFNwXQ9MlwPeMGS3aTZkYsv8QmSm0Ns9Yh9FkgLKYaUuQ==}
|
resolution: {integrity: sha512-WLydwytAeHoC/neXsiIgK+a6Me12PuSpwopnsZgX5JFNwXQ9MlwPeMGS3aTZkYsv8QmSm0Ns9Yh9FkgLKYaUuQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -339,6 +377,28 @@ packages:
|
||||||
/@popperjs/core/2.11.6:
|
/@popperjs/core/2.11.6:
|
||||||
resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==}
|
resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==}
|
||||||
|
|
||||||
|
/@prisma/client/4.6.0_prisma@4.6.0:
|
||||||
|
resolution: {integrity: sha512-D9LaQinDxOHinRpcJTw2tjMtjhc9HTP+aF1IRd2oLldp/8TiwIfxK8x17OhBBiX4y1PzbJXXET7kS+5wB3es/w==}
|
||||||
|
engines: {node: '>=14.17'}
|
||||||
|
requiresBuild: true
|
||||||
|
peerDependencies:
|
||||||
|
prisma: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
prisma:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@prisma/engines-version': 4.6.0-53.2e719efb80b56a3f32d18a62489de95bb9c130e3
|
||||||
|
prisma: 4.6.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@prisma/engines-version/4.6.0-53.2e719efb80b56a3f32d18a62489de95bb9c130e3:
|
||||||
|
resolution: {integrity: sha512-0CTnfEuUbLlO6n1fM89ERDbSwI4LoyZn+1OKVSwG+aVqohj34+mXRfwOWIM0ONtYtLGGBpddvQAnAZkg+cgS6g==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@prisma/engines/4.6.0:
|
||||||
|
resolution: {integrity: sha512-S+72PAl0zTCbIGou1uXD/McvzdtP+bjOs0LRmGZfcOQcVqR9x/0f6Z+dqpUU0zIcqHEl+0DOB8UXaTwRvssFsQ==}
|
||||||
|
requiresBuild: true
|
||||||
|
|
||||||
/@rushstack/eslint-patch/1.2.0:
|
/@rushstack/eslint-patch/1.2.0:
|
||||||
resolution: {integrity: sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==}
|
resolution: {integrity: sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -349,6 +409,12 @@ packages:
|
||||||
tslib: 2.4.1
|
tslib: 2.4.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@types/bcrypt/5.0.0:
|
||||||
|
resolution: {integrity: sha512-agtcFKaruL8TmcvqbndlqHPSJgsolhf/qPWchFlgnW1gECTN/nKbFcoFnvKAQRFfKbh+BO6A3SWdJu9t+xF3Lw==}
|
||||||
|
dependencies:
|
||||||
|
'@types/node': 17.0.23
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/cookie/0.5.1:
|
/@types/cookie/0.5.1:
|
||||||
resolution: {integrity: sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==}
|
resolution: {integrity: sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -361,6 +427,16 @@ packages:
|
||||||
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/jsonwebtoken/8.5.9:
|
||||||
|
resolution: {integrity: sha512-272FMnFGzAVMGtu9tkr29hRL6bZj4Zs1KZNeHLnKqAvp06tAIcarTMwOh8/8bz4FmKRcMxZhZNeUAQsNLoiPhg==}
|
||||||
|
dependencies:
|
||||||
|
'@types/node': 17.0.23
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@types/marked/4.0.7:
|
||||||
|
resolution: {integrity: sha512-eEAhnz21CwvKVW+YvRvcTuFKNU9CV1qH+opcgVK3pIMI6YZzDm6gc8o2vHjldFk6MGKt5pueSB7IOpvpx5Qekw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/node/17.0.23:
|
/@types/node/17.0.23:
|
||||||
resolution: {integrity: sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==}
|
resolution: {integrity: sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -507,6 +583,10 @@ packages:
|
||||||
react-dom: 18.2.0_react@18.2.0
|
react-dom: 18.2.0_react@18.2.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/abbrev/1.1.1:
|
||||||
|
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/acorn-jsx/5.3.2_acorn@8.8.1:
|
/acorn-jsx/5.3.2_acorn@8.8.1:
|
||||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -526,6 +606,15 @@ packages:
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/agent-base/6.0.2:
|
||||||
|
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
|
||||||
|
engines: {node: '>= 6.0.0'}
|
||||||
|
dependencies:
|
||||||
|
debug: 4.3.4
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
/ajv/6.12.6:
|
/ajv/6.12.6:
|
||||||
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
|
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -538,7 +627,6 @@ packages:
|
||||||
/ansi-regex/5.0.1:
|
/ansi-regex/5.0.1:
|
||||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ansi-styles/3.2.1:
|
/ansi-styles/3.2.1:
|
||||||
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
|
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
|
||||||
|
@ -566,6 +654,18 @@ packages:
|
||||||
resolution: {integrity: sha512-gkco+qxENJV+8vFcDiiFhuoSvRXb2a/QPqpSoWhVz829VNJfOTnELbBmPmNKFxf3xdNnw4DWCkzkDaavcX/1YQ==}
|
resolution: {integrity: sha512-gkco+qxENJV+8vFcDiiFhuoSvRXb2a/QPqpSoWhVz829VNJfOTnELbBmPmNKFxf3xdNnw4DWCkzkDaavcX/1YQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/aproba/2.0.0:
|
||||||
|
resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/are-we-there-yet/2.0.0:
|
||||||
|
resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
dependencies:
|
||||||
|
delegates: 1.0.0
|
||||||
|
readable-stream: 3.6.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/argparse/2.0.1:
|
/argparse/2.0.1:
|
||||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -649,11 +749,22 @@ packages:
|
||||||
|
|
||||||
/balanced-match/1.0.2:
|
/balanced-match/1.0.2:
|
||||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/base64-js/1.5.1:
|
/base64-js/1.5.1:
|
||||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||||
|
|
||||||
|
/bcrypt/5.1.0:
|
||||||
|
resolution: {integrity: sha512-RHBS7HI5N5tEnGTmtR/pppX0mmDSBpQ4aCBsj7CEQfYXDcO74A8sIBYcJMuCsis2E81zDxeENYhv66oZwLiA+Q==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
requiresBuild: true
|
||||||
|
dependencies:
|
||||||
|
'@mapbox/node-pre-gyp': 1.0.10
|
||||||
|
node-addon-api: 5.0.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
/big.js/3.2.0:
|
/big.js/3.2.0:
|
||||||
resolution: {integrity: sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==}
|
resolution: {integrity: sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -679,7 +790,6 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
balanced-match: 1.0.2
|
balanced-match: 1.0.2
|
||||||
concat-map: 0.0.1
|
concat-map: 0.0.1
|
||||||
dev: true
|
|
||||||
|
|
||||||
/braces/3.0.2:
|
/braces/3.0.2:
|
||||||
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
|
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
|
||||||
|
@ -688,6 +798,10 @@ packages:
|
||||||
fill-range: 7.0.1
|
fill-range: 7.0.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/buffer-equal-constant-time/1.0.1:
|
||||||
|
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/buffer/5.7.1:
|
/buffer/5.7.1:
|
||||||
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -747,6 +861,11 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
/chownr/2.0.0:
|
||||||
|
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/classnames/2.3.2:
|
/classnames/2.3.2:
|
||||||
resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==}
|
resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -808,6 +927,11 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
/color-support/1.1.3:
|
||||||
|
resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
|
||||||
|
hasBin: true
|
||||||
|
dev: false
|
||||||
|
|
||||||
/color/4.2.3:
|
/color/4.2.3:
|
||||||
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
|
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
|
||||||
engines: {node: '>=12.5.0'}
|
engines: {node: '>=12.5.0'}
|
||||||
|
@ -832,7 +956,10 @@ packages:
|
||||||
|
|
||||||
/concat-map/0.0.1:
|
/concat-map/0.0.1:
|
||||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||||
dev: true
|
|
||||||
|
/console-control-strings/1.1.0:
|
||||||
|
resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/cookie/0.5.0:
|
/cookie/0.5.0:
|
||||||
resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
|
resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
|
||||||
|
@ -954,7 +1081,6 @@ packages:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.2
|
ms: 2.1.2
|
||||||
dev: true
|
|
||||||
|
|
||||||
/decode-uri-component/0.2.0:
|
/decode-uri-component/0.2.0:
|
||||||
resolution: {integrity: sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==}
|
resolution: {integrity: sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==}
|
||||||
|
@ -991,6 +1117,10 @@ packages:
|
||||||
object-keys: 1.1.1
|
object-keys: 1.1.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/delegates/1.0.0:
|
||||||
|
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/dependency-tree/8.1.2:
|
/dependency-tree/8.1.2:
|
||||||
resolution: {integrity: sha512-c4CL1IKxkKng0oT5xrg4uNiiMVFqTGOXqHSFx7XEFdgSsp6nw3AGGruICppzJUrfad/r7GLqt26rmWU4h4j39A==}
|
resolution: {integrity: sha512-c4CL1IKxkKng0oT5xrg4uNiiMVFqTGOXqHSFx7XEFdgSsp6nw3AGGruICppzJUrfad/r7GLqt26rmWU4h4j39A==}
|
||||||
engines: {node: ^10.13 || ^12 || >=14}
|
engines: {node: ^10.13 || ^12 || >=14}
|
||||||
|
@ -1009,7 +1139,6 @@ packages:
|
||||||
resolution: {integrity: sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==}
|
resolution: {integrity: sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
|
||||||
|
|
||||||
/detective-amd/3.1.2:
|
/detective-amd/3.1.2:
|
||||||
resolution: {integrity: sha512-jffU26dyqJ37JHR/o44La6CxtrDf3Rt9tvd2IbImJYxWKTMdBjctp37qoZ6ZcY80RHg+kzWz4bXn39e4P7cctQ==}
|
resolution: {integrity: sha512-jffU26dyqJ37JHR/o44La6CxtrDf3Rt9tvd2IbImJYxWKTMdBjctp37qoZ6ZcY80RHg+kzWz4bXn39e4P7cctQ==}
|
||||||
|
@ -1139,6 +1268,16 @@ packages:
|
||||||
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
|
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/ecdsa-sig-formatter/1.0.11:
|
||||||
|
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
|
||||||
|
dependencies:
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/emoji-regex/8.0.0:
|
||||||
|
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/emoji-regex/9.2.2:
|
/emoji-regex/9.2.2:
|
||||||
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
|
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -1646,9 +1785,15 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
/fs-minipass/2.1.0:
|
||||||
|
resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
|
||||||
|
engines: {node: '>= 8'}
|
||||||
|
dependencies:
|
||||||
|
minipass: 3.3.4
|
||||||
|
dev: false
|
||||||
|
|
||||||
/fs.realpath/1.0.0:
|
/fs.realpath/1.0.0:
|
||||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/fsevents/2.3.2:
|
/fsevents/2.3.2:
|
||||||
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
|
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
|
||||||
|
@ -1676,6 +1821,21 @@ packages:
|
||||||
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
|
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/gauge/3.0.2:
|
||||||
|
resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
dependencies:
|
||||||
|
aproba: 2.0.0
|
||||||
|
color-support: 1.1.3
|
||||||
|
console-control-strings: 1.1.0
|
||||||
|
has-unicode: 2.0.1
|
||||||
|
object-assign: 4.1.1
|
||||||
|
signal-exit: 3.0.7
|
||||||
|
string-width: 4.2.3
|
||||||
|
strip-ansi: 6.0.1
|
||||||
|
wide-align: 1.1.5
|
||||||
|
dev: false
|
||||||
|
|
||||||
/generic-names/1.0.3:
|
/generic-names/1.0.3:
|
||||||
resolution: {integrity: sha512-b6OHfQuKasIKM9b6YPkX+KUj/TLBTx3B/1aT1T5F12FEuEqyFMdr59OMS53aoaSw8eVtapdqieX6lbg5opaOhA==}
|
resolution: {integrity: sha512-b6OHfQuKasIKM9b6YPkX+KUj/TLBTx3B/1aT1T5F12FEuEqyFMdr59OMS53aoaSw8eVtapdqieX6lbg5opaOhA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -1749,7 +1909,6 @@ packages:
|
||||||
minimatch: 3.1.2
|
minimatch: 3.1.2
|
||||||
once: 1.4.0
|
once: 1.4.0
|
||||||
path-is-absolute: 1.0.1
|
path-is-absolute: 1.0.1
|
||||||
dev: true
|
|
||||||
|
|
||||||
/globals/13.17.0:
|
/globals/13.17.0:
|
||||||
resolution: {integrity: sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==}
|
resolution: {integrity: sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==}
|
||||||
|
@ -1838,6 +1997,10 @@ packages:
|
||||||
has-symbols: 1.0.3
|
has-symbols: 1.0.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/has-unicode/2.0.1:
|
||||||
|
resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/has/1.0.3:
|
/has/1.0.3:
|
||||||
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
|
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
|
||||||
engines: {node: '>= 0.4.0'}
|
engines: {node: '>= 0.4.0'}
|
||||||
|
@ -1845,6 +2008,16 @@ packages:
|
||||||
function-bind: 1.1.1
|
function-bind: 1.1.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/https-proxy-agent/5.0.1:
|
||||||
|
resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
|
||||||
|
engines: {node: '>= 6'}
|
||||||
|
dependencies:
|
||||||
|
agent-base: 6.0.2
|
||||||
|
debug: 4.3.4
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
/iconv-lite/0.6.3:
|
/iconv-lite/0.6.3:
|
||||||
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -1910,7 +2083,6 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
once: 1.4.0
|
once: 1.4.0
|
||||||
wrappy: 1.0.2
|
wrappy: 1.0.2
|
||||||
dev: true
|
|
||||||
|
|
||||||
/inherits/2.0.4:
|
/inherits/2.0.4:
|
||||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||||
|
@ -1976,6 +2148,11 @@ packages:
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/is-fullwidth-code-point/3.0.0:
|
||||||
|
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/is-glob/4.0.3:
|
/is-glob/4.0.3:
|
||||||
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -2118,6 +2295,22 @@ packages:
|
||||||
minimist: 1.2.7
|
minimist: 1.2.7
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/jsonwebtoken/8.5.1:
|
||||||
|
resolution: {integrity: sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==}
|
||||||
|
engines: {node: '>=4', npm: '>=1.4.28'}
|
||||||
|
dependencies:
|
||||||
|
jws: 3.2.2
|
||||||
|
lodash.includes: 4.3.0
|
||||||
|
lodash.isboolean: 3.0.3
|
||||||
|
lodash.isinteger: 4.0.4
|
||||||
|
lodash.isnumber: 3.0.3
|
||||||
|
lodash.isplainobject: 4.0.6
|
||||||
|
lodash.isstring: 4.0.1
|
||||||
|
lodash.once: 4.1.1
|
||||||
|
ms: 2.1.3
|
||||||
|
semver: 5.7.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/jsx-ast-utils/3.3.3:
|
/jsx-ast-utils/3.3.3:
|
||||||
resolution: {integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==}
|
resolution: {integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==}
|
||||||
engines: {node: '>=4.0'}
|
engines: {node: '>=4.0'}
|
||||||
|
@ -2126,6 +2319,21 @@ packages:
|
||||||
object.assign: 4.1.4
|
object.assign: 4.1.4
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/jwa/1.4.1:
|
||||||
|
resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==}
|
||||||
|
dependencies:
|
||||||
|
buffer-equal-constant-time: 1.0.1
|
||||||
|
ecdsa-sig-formatter: 1.0.11
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/jws/3.2.2:
|
||||||
|
resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==}
|
||||||
|
dependencies:
|
||||||
|
jwa: 1.4.1
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/language-subtag-registry/0.3.22:
|
/language-subtag-registry/0.3.22:
|
||||||
resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==}
|
resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -2206,10 +2414,38 @@ packages:
|
||||||
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
|
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/lodash.includes/4.3.0:
|
||||||
|
resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/lodash.isboolean/3.0.3:
|
||||||
|
resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/lodash.isinteger/4.0.4:
|
||||||
|
resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/lodash.isnumber/3.0.3:
|
||||||
|
resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/lodash.isplainobject/4.0.6:
|
||||||
|
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/lodash.isstring/4.0.1:
|
||||||
|
resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/lodash.merge/4.6.2:
|
/lodash.merge/4.6.2:
|
||||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/lodash.once/4.1.1:
|
||||||
|
resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/lodash/4.17.21:
|
/lodash/4.17.21:
|
||||||
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -2275,6 +2511,19 @@ packages:
|
||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
/make-dir/3.1.0:
|
||||||
|
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
dependencies:
|
||||||
|
semver: 6.3.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/marked/4.2.2:
|
||||||
|
resolution: {integrity: sha512-JjBTFTAvuTgANXx82a5vzK9JLSMoV6V3LBVn4Uhdso6t7vXrGx7g1Cd2r6NYSsxrYbQGFCMqBDhFHyK5q2UvcQ==}
|
||||||
|
engines: {node: '>= 12'}
|
||||||
|
hasBin: true
|
||||||
|
dev: false
|
||||||
|
|
||||||
/memory-fs/0.5.0:
|
/memory-fs/0.5.0:
|
||||||
resolution: {integrity: sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==}
|
resolution: {integrity: sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==}
|
||||||
engines: {node: '>=4.3.0 <5.0.0 || >=5.10'}
|
engines: {node: '>=4.3.0 <5.0.0 || >=5.10'}
|
||||||
|
@ -2319,11 +2568,25 @@ packages:
|
||||||
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
|
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion: 1.1.11
|
brace-expansion: 1.1.11
|
||||||
dev: true
|
|
||||||
|
|
||||||
/minimist/1.2.7:
|
/minimist/1.2.7:
|
||||||
resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==}
|
resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==}
|
||||||
|
|
||||||
|
/minipass/3.3.4:
|
||||||
|
resolution: {integrity: sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
dependencies:
|
||||||
|
yallist: 4.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/minizlib/2.1.2:
|
||||||
|
resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
|
||||||
|
engines: {node: '>= 8'}
|
||||||
|
dependencies:
|
||||||
|
minipass: 3.3.4
|
||||||
|
yallist: 4.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/mkdirp-classic/0.5.3:
|
/mkdirp-classic/0.5.3:
|
||||||
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
|
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -2333,7 +2596,6 @@ packages:
|
||||||
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
|
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
|
||||||
|
|
||||||
/module-definition/3.4.0:
|
/module-definition/3.4.0:
|
||||||
resolution: {integrity: sha512-XxJ88R1v458pifaSkPNLUTdSPNVGMP2SXVncVmApGO+gAfrLANiYe6JofymCzVceGOMwQE2xogxBSc8uB7XegA==}
|
resolution: {integrity: sha512-XxJ88R1v458pifaSkPNLUTdSPNVGMP2SXVncVmApGO+gAfrLANiYe6JofymCzVceGOMwQE2xogxBSc8uB7XegA==}
|
||||||
|
@ -2373,11 +2635,9 @@ packages:
|
||||||
|
|
||||||
/ms/2.1.2:
|
/ms/2.1.2:
|
||||||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ms/2.1.3:
|
/ms/2.1.3:
|
||||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/nanoid/3.3.4:
|
/nanoid/3.3.4:
|
||||||
resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==}
|
resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==}
|
||||||
|
@ -2474,7 +2734,18 @@ packages:
|
||||||
/node-addon-api/5.0.0:
|
/node-addon-api/5.0.0:
|
||||||
resolution: {integrity: sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA==}
|
resolution: {integrity: sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/node-fetch/2.6.7:
|
||||||
|
resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==}
|
||||||
|
engines: {node: 4.x || >=6.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
encoding: ^0.1.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
encoding:
|
||||||
optional: true
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
whatwg-url: 5.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/node-source-walk/4.3.0:
|
/node-source-walk/4.3.0:
|
||||||
resolution: {integrity: sha512-8Q1hXew6ETzqKRAs3jjLioSxNfT1cx74ooiF8RlAONwVMcfq+UdzLC2eB5qcPldUxaE5w3ytLkrmV1TGddhZTA==}
|
resolution: {integrity: sha512-8Q1hXew6ETzqKRAs3jjLioSxNfT1cx74ooiF8RlAONwVMcfq+UdzLC2eB5qcPldUxaE5w3ytLkrmV1TGddhZTA==}
|
||||||
|
@ -2483,11 +2754,28 @@ packages:
|
||||||
'@babel/parser': 7.20.3
|
'@babel/parser': 7.20.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/nopt/5.0.0:
|
||||||
|
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
abbrev: 1.1.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/normalize-path/3.0.0:
|
/normalize-path/3.0.0:
|
||||||
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/npmlog/5.0.1:
|
||||||
|
resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==}
|
||||||
|
dependencies:
|
||||||
|
are-we-there-yet: 2.0.0
|
||||||
|
console-control-strings: 1.1.0
|
||||||
|
gauge: 3.0.2
|
||||||
|
set-blocking: 2.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/object-assign/4.1.1:
|
/object-assign/4.1.1:
|
||||||
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -2640,7 +2928,6 @@ packages:
|
||||||
/path-is-absolute/1.0.1:
|
/path-is-absolute/1.0.1:
|
||||||
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
|
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/path-key/3.1.1:
|
/path-key/3.1.1:
|
||||||
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
|
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
|
||||||
|
@ -2843,6 +3130,22 @@ packages:
|
||||||
parse-ms: 2.1.0
|
parse-ms: 2.1.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/prism-react-renderer/1.3.5_react@18.2.0:
|
||||||
|
resolution: {integrity: sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=0.14.9'
|
||||||
|
dependencies:
|
||||||
|
react: 18.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/prisma/4.6.0:
|
||||||
|
resolution: {integrity: sha512-TAnObUMGCM9NLt9nsRs1WWYQGPKsJOK8bN/7gSAnBcYIxMCFFDe+XtFYJbyTzsJZ/i+0rH4zg8au3m7HX354LA==}
|
||||||
|
engines: {node: '>=14.17'}
|
||||||
|
hasBin: true
|
||||||
|
requiresBuild: true
|
||||||
|
dependencies:
|
||||||
|
'@prisma/engines': 4.6.0
|
||||||
|
|
||||||
/process-nextick-args/2.0.1:
|
/process-nextick-args/2.0.1:
|
||||||
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -3142,7 +3445,6 @@ packages:
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dependencies:
|
dependencies:
|
||||||
glob: 7.2.3
|
glob: 7.2.3
|
||||||
dev: true
|
|
||||||
|
|
||||||
/run-parallel/1.2.0:
|
/run-parallel/1.2.0:
|
||||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||||
|
@ -3199,13 +3501,10 @@ packages:
|
||||||
/semver/5.7.1:
|
/semver/5.7.1:
|
||||||
resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==}
|
resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
/semver/6.3.0:
|
/semver/6.3.0:
|
||||||
resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
|
resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
|
||||||
|
|
||||||
/semver/7.3.8:
|
/semver/7.3.8:
|
||||||
resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==}
|
resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==}
|
||||||
|
@ -3214,6 +3513,10 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
lru-cache: 6.0.0
|
lru-cache: 6.0.0
|
||||||
|
|
||||||
|
/set-blocking/2.0.0:
|
||||||
|
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/shallowequal/1.1.0:
|
/shallowequal/1.1.0:
|
||||||
resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==}
|
resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -3256,7 +3559,6 @@ packages:
|
||||||
|
|
||||||
/signal-exit/3.0.7:
|
/signal-exit/3.0.7:
|
||||||
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/simple-concat/1.0.1:
|
/simple-concat/1.0.1:
|
||||||
resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
|
resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
|
||||||
|
@ -3323,6 +3625,15 @@ packages:
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/string-width/4.2.3:
|
||||||
|
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
dependencies:
|
||||||
|
emoji-regex: 8.0.0
|
||||||
|
is-fullwidth-code-point: 3.0.0
|
||||||
|
strip-ansi: 6.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/string.prototype.matchall/4.0.8:
|
/string.prototype.matchall/4.0.8:
|
||||||
resolution: {integrity: sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==}
|
resolution: {integrity: sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -3377,7 +3688,6 @@ packages:
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-regex: 5.0.1
|
ansi-regex: 5.0.1
|
||||||
dev: true
|
|
||||||
|
|
||||||
/strip-bom/3.0.0:
|
/strip-bom/3.0.0:
|
||||||
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
|
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
|
||||||
|
@ -3496,6 +3806,18 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
/tar/6.1.12:
|
||||||
|
resolution: {integrity: sha512-jU4TdemS31uABHd+Lt5WEYJuzn+TJTCBLljvIAHZOz6M9Os5pJ4dD+vRFLxPa/n3T0iEFzpi+0x1UfuDZYbRMw==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
dependencies:
|
||||||
|
chownr: 2.0.0
|
||||||
|
fs-minipass: 2.1.0
|
||||||
|
minipass: 3.3.4
|
||||||
|
minizlib: 2.1.2
|
||||||
|
mkdirp: 1.0.4
|
||||||
|
yallist: 4.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/temp/0.4.0:
|
/temp/0.4.0:
|
||||||
resolution: {integrity: sha512-IsFisGgDKk7qzK9erMIkQe/XwiSUdac7z3wYOsjcLkhPBy3k1SlvLoIh2dAHIlEpgA971CgguMrx9z8fFg7tSA==}
|
resolution: {integrity: sha512-IsFisGgDKk7qzK9erMIkQe/XwiSUdac7z3wYOsjcLkhPBy3k1SlvLoIh2dAHIlEpgA971CgguMrx9z8fFg7tSA==}
|
||||||
engines: {'0': node >=0.4.0}
|
engines: {'0': node >=0.4.0}
|
||||||
|
@ -3534,6 +3856,10 @@ packages:
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/tr46/0.0.3:
|
||||||
|
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/ts-loader/7.0.5_typescript@4.6.4:
|
/ts-loader/7.0.5_typescript@4.6.4:
|
||||||
resolution: {integrity: sha512-zXypEIT6k3oTc+OZNx/cqElrsbBtYqDknf48OZos0NQ3RTt045fBIU8RRSu+suObBzYB355aIPGOe/3kj9h7Ig==}
|
resolution: {integrity: sha512-zXypEIT6k3oTc+OZNx/cqElrsbBtYqDknf48OZos0NQ3RTt045fBIU8RRSu+suObBzYB355aIPGOe/3kj9h7Ig==}
|
||||||
engines: {node: '>=10.0.0'}
|
engines: {node: '>=10.0.0'}
|
||||||
|
@ -3697,6 +4023,10 @@ packages:
|
||||||
defaults: 1.0.4
|
defaults: 1.0.4
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/webidl-conversions/3.0.1:
|
||||||
|
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/webpack-bundle-analyzer/4.3.0:
|
/webpack-bundle-analyzer/4.3.0:
|
||||||
resolution: {integrity: sha512-J3TPm54bPARx6QG8z4cKBszahnUglcv70+N+8gUqv2I5KOFHJbzBiLx+pAp606so0X004fxM7hqRu10MLjJifA==}
|
resolution: {integrity: sha512-J3TPm54bPARx6QG8z4cKBszahnUglcv70+N+8gUqv2I5KOFHJbzBiLx+pAp606so0X004fxM7hqRu10MLjJifA==}
|
||||||
engines: {node: '>= 10.13.0'}
|
engines: {node: '>= 10.13.0'}
|
||||||
|
@ -3716,6 +4046,13 @@ packages:
|
||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/whatwg-url/5.0.0:
|
||||||
|
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
||||||
|
dependencies:
|
||||||
|
tr46: 0.0.3
|
||||||
|
webidl-conversions: 3.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/which-boxed-primitive/1.0.2:
|
/which-boxed-primitive/1.0.2:
|
||||||
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
|
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -3734,6 +4071,12 @@ packages:
|
||||||
isexe: 2.0.0
|
isexe: 2.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/wide-align/1.1.5:
|
||||||
|
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
|
||||||
|
dependencies:
|
||||||
|
string-width: 4.2.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
/word-wrap/1.2.3:
|
/word-wrap/1.2.3:
|
||||||
resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==}
|
resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -3767,3 +4110,7 @@ packages:
|
||||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/zod/3.19.1:
|
||||||
|
resolution: {integrity: sha512-LYjZsEDhCdYET9ikFu6dVPGp2YH9DegXjdJToSzD9rO6fy4qiRYFoyEYwps88OseJlPyl2NOe2iJuhEhL7IpEA==}
|
||||||
|
dev: false
|
||||||
|
|
73
client/prisma/migrations/20221110002714_init/migration.sql
Normal file
73
client/prisma/migrations/20221110002714_init/migration.sql
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "AuthTokens" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"token" TEXT NOT NULL,
|
||||||
|
"expiredReason" TEXT NOT NULL,
|
||||||
|
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" DATETIME NOT NULL,
|
||||||
|
"deletedAt" DATETIME NOT NULL,
|
||||||
|
"userId" TEXT NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY ("id", "token")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "SequelizeMeta" (
|
||||||
|
"name" TEXT NOT NULL PRIMARY KEY
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Files" (
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"title" TEXT,
|
||||||
|
"content" TEXT,
|
||||||
|
"sha" TEXT,
|
||||||
|
"html" TEXT,
|
||||||
|
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" DATETIME NOT NULL,
|
||||||
|
"deletedAt" DATETIME,
|
||||||
|
"userId" TEXT NOT NULL,
|
||||||
|
"postId" TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "PostAuthors" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" DATETIME NOT NULL,
|
||||||
|
"postId" TEXT NOT NULL,
|
||||||
|
"userId" TEXT NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY ("id", "postId", "userId")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Posts" (
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"title" TEXT NOT NULL,
|
||||||
|
"visibility" TEXT NOT NULL,
|
||||||
|
"password" TEXT,
|
||||||
|
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" DATETIME NOT NULL,
|
||||||
|
"deletedAt" DATETIME,
|
||||||
|
"expiresAt" DATETIME,
|
||||||
|
"parentId" TEXT,
|
||||||
|
"description" TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Users" (
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"username" TEXT NOT NULL,
|
||||||
|
"password" TEXT NOT NULL,
|
||||||
|
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" DATETIME NOT NULL,
|
||||||
|
"deletedAt" DATETIME,
|
||||||
|
"role" TEXT DEFAULT 'user',
|
||||||
|
"email" TEXT,
|
||||||
|
"displayName" TEXT,
|
||||||
|
"bio" TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "AuthTokens_id_token_key" ON "AuthTokens"("id", "token");
|
|
@ -0,0 +1,19 @@
|
||||||
|
-- RedefineTables
|
||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
CREATE TABLE "new_AuthTokens" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"token" TEXT NOT NULL,
|
||||||
|
"expiredReason" TEXT,
|
||||||
|
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" DATETIME NOT NULL,
|
||||||
|
"deletedAt" DATETIME,
|
||||||
|
"userId" TEXT NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY ("id", "token")
|
||||||
|
);
|
||||||
|
INSERT INTO "new_AuthTokens" ("createdAt", "deletedAt", "expiredReason", "id", "token", "updatedAt", "userId") SELECT "createdAt", "deletedAt", "expiredReason", "id", "token", "updatedAt", "userId" FROM "AuthTokens";
|
||||||
|
DROP TABLE "AuthTokens";
|
||||||
|
ALTER TABLE "new_AuthTokens" RENAME TO "AuthTokens";
|
||||||
|
CREATE UNIQUE INDEX "AuthTokens_id_token_key" ON "AuthTokens"("id", "token");
|
||||||
|
PRAGMA foreign_key_check;
|
||||||
|
PRAGMA foreign_keys=ON;
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- Made the column `content` on table `Files` required. This step will fail if there are existing NULL values in that column.
|
||||||
|
- Made the column `html` on table `Files` required. This step will fail if there are existing NULL values in that column.
|
||||||
|
- Made the column `sha` on table `Files` required. This step will fail if there are existing NULL values in that column.
|
||||||
|
- Made the column `title` on table `Files` required. This step will fail if there are existing NULL values in that column.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- RedefineTables
|
||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
CREATE TABLE "new_Files" (
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"title" TEXT NOT NULL,
|
||||||
|
"content" TEXT NOT NULL,
|
||||||
|
"sha" TEXT NOT NULL,
|
||||||
|
"html" TEXT NOT NULL,
|
||||||
|
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" DATETIME NOT NULL,
|
||||||
|
"deletedAt" DATETIME,
|
||||||
|
"userId" TEXT NOT NULL,
|
||||||
|
"postId" TEXT NOT NULL
|
||||||
|
);
|
||||||
|
INSERT INTO "new_Files" ("content", "createdAt", "deletedAt", "html", "id", "postId", "sha", "title", "updatedAt", "userId") SELECT "content", "createdAt", "deletedAt", "html", "id", "postId", "sha", "title", "updatedAt", "userId" FROM "Files";
|
||||||
|
DROP TABLE "Files";
|
||||||
|
ALTER TABLE "new_Files" RENAME TO "Files";
|
||||||
|
PRAGMA foreign_key_check;
|
||||||
|
PRAGMA foreign_keys=ON;
|
3
client/prisma/migrations/migration_lock.toml
Normal file
3
client/prisma/migrations/migration_lock.toml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Please do not edit this file manually
|
||||||
|
# It should be added in your version-control system (i.e. Git)
|
||||||
|
provider = "sqlite"
|
93
client/prisma/schema.prisma
Normal file
93
client/prisma/schema.prisma
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client-js"
|
||||||
|
}
|
||||||
|
|
||||||
|
datasource db {
|
||||||
|
provider = "sqlite"
|
||||||
|
url = env("DATABASE_URL")
|
||||||
|
}
|
||||||
|
|
||||||
|
model AuthTokens {
|
||||||
|
id String @default(cuid())
|
||||||
|
token String
|
||||||
|
expiredReason String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
deletedAt DateTime?
|
||||||
|
userId String
|
||||||
|
// TODO: verify this isn't necessary / is replaced by an implicit m-n relation
|
||||||
|
// users User[] @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
@@id([id, token])
|
||||||
|
// make id and token keys
|
||||||
|
@@unique([id, token])
|
||||||
|
}
|
||||||
|
|
||||||
|
model SequelizeMeta {
|
||||||
|
name String @id
|
||||||
|
}
|
||||||
|
|
||||||
|
model File {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
title String
|
||||||
|
content String
|
||||||
|
sha String
|
||||||
|
html String
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
deletedAt DateTime?
|
||||||
|
userId String
|
||||||
|
postId String
|
||||||
|
// posts Post[] @relation(fields: [postId], references: [id], onDelete: Cascade)
|
||||||
|
// users User[] @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
@@map("Files")
|
||||||
|
}
|
||||||
|
|
||||||
|
model PostToAuthors {
|
||||||
|
id String @default(cuid())
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
postId String
|
||||||
|
userId String
|
||||||
|
// users User[] @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
// posts Post[] @relation(fields: [postId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
@@id([id, postId, userId])
|
||||||
|
@@map("PostAuthors")
|
||||||
|
}
|
||||||
|
|
||||||
|
model Post {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
title String
|
||||||
|
visibility String
|
||||||
|
password String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
deletedAt DateTime?
|
||||||
|
expiresAt DateTime?
|
||||||
|
parentId String?
|
||||||
|
description String?
|
||||||
|
// files File[]
|
||||||
|
// postToAuthors PostToAuthors[]
|
||||||
|
|
||||||
|
@@map("Posts")
|
||||||
|
}
|
||||||
|
|
||||||
|
model User {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
username String
|
||||||
|
password String
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
deletedAt DateTime?
|
||||||
|
role String? @default("user")
|
||||||
|
email String?
|
||||||
|
displayName String?
|
||||||
|
bio String?
|
||||||
|
// AuthTokens AuthTokens[]
|
||||||
|
// files File[]
|
||||||
|
// post_authors PostToAuthors[]
|
||||||
|
|
||||||
|
@@map("Users")
|
||||||
|
}
|
Loading…
Reference in a new issue