Add eslint configs, fix lint errors
This commit is contained in:
parent
631f98aaaf
commit
19c5725847
45 changed files with 388 additions and 164 deletions
|
@ -1,3 +1,11 @@
|
||||||
{
|
{
|
||||||
"extends": "next/core-web-vitals"
|
"extends": [
|
||||||
|
"next/core-web-vitals",
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended"
|
||||||
|
],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"plugins": ["@typescript-eslint"],
|
||||||
|
"root": true,
|
||||||
|
"ignorePatterns": ["node_modules/", "__tests__/"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@ import config from "@lib/config"
|
||||||
import Auth from "../components"
|
import Auth from "../components"
|
||||||
|
|
||||||
function isGithubEnabled() {
|
function isGithubEnabled() {
|
||||||
return config.github_client_id.length && config.github_client_secret.length ? true : false
|
return config.github_client_id.length && config.github_client_secret.length
|
||||||
|
? true
|
||||||
|
: false
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SignInPage() {
|
export default function SignInPage() {
|
||||||
|
|
|
@ -7,10 +7,18 @@ const getPasscode = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function isGithubEnabled() {
|
function isGithubEnabled() {
|
||||||
return config.github_client_id.length && config.github_client_secret.length ? true : false
|
return config.github_client_id.length && config.github_client_secret.length
|
||||||
|
? true
|
||||||
|
: false
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function SignUpPage() {
|
export default async function SignUpPage() {
|
||||||
const requiresPasscode = await getPasscode()
|
const requiresPasscode = await getPasscode()
|
||||||
return <Auth page="signup" requiresServerPassword={requiresPasscode} isGithubEnabled={isGithubEnabled()} />
|
return (
|
||||||
|
<Auth
|
||||||
|
page="signup"
|
||||||
|
requiresServerPassword={requiresPasscode}
|
||||||
|
isGithubEnabled={isGithubEnabled()}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
import { Popover } from "@components/popover"
|
import { Popover } from "@components/popover"
|
||||||
import { codeFileExtensions } from "@lib/constants"
|
import { codeFileExtensions } from "@lib/constants"
|
||||||
import clsx from "clsx"
|
import clsx from "clsx"
|
||||||
import type { File, PostWithFiles } from "lib/server/prisma"
|
import type { PostWithFiles } from "lib/server/prisma"
|
||||||
import styles from "./dropdown.module.css"
|
import styles from "./dropdown.module.css"
|
||||||
import buttonStyles from "@components/button/button.module.css"
|
import buttonStyles from "@components/button/button.module.css"
|
||||||
import { ChevronDown, Code, File as FileIcon } from "react-feather"
|
import { ChevronDown, Code, File as FileIcon } from "react-feather"
|
||||||
import { Spinner } from "@components/spinner"
|
import { Spinner } from "@components/spinner"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
|
|
||||||
type Item = File & {
|
|
||||||
icon: JSX.Element
|
|
||||||
}
|
|
||||||
|
|
||||||
const FileDropdown = ({
|
const FileDropdown = ({
|
||||||
files,
|
files,
|
||||||
loading
|
loading
|
||||||
|
@ -23,9 +19,7 @@ const FileDropdown = ({
|
||||||
return (
|
return (
|
||||||
<Popover>
|
<Popover>
|
||||||
<Popover.Trigger className={buttonStyles.button}>
|
<Popover.Trigger className={buttonStyles.button}>
|
||||||
<div
|
<div style={{ minWidth: 125 }}>
|
||||||
style={{ minWidth: 125 }}
|
|
||||||
>
|
|
||||||
<Spinner />
|
<Spinner />
|
||||||
</div>
|
</div>
|
||||||
</Popover.Trigger>
|
</Popover.Trigger>
|
||||||
|
|
|
@ -37,7 +37,7 @@ const MarkdownPreview = ({
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
},
|
},
|
||||||
body,
|
body
|
||||||
})
|
})
|
||||||
|
|
||||||
if (resp.ok) {
|
if (resp.ok) {
|
||||||
|
|
|
@ -55,6 +55,7 @@ const Post = ({
|
||||||
title: doc.title,
|
title: doc.title,
|
||||||
content: doc.content,
|
content: doc.content,
|
||||||
id: doc.id
|
id: doc.id
|
||||||
|
// eslint-disable-next-line no-mixed-spaces-and-tabs
|
||||||
}))
|
}))
|
||||||
: [emptyDoc]
|
: [emptyDoc]
|
||||||
|
|
||||||
|
@ -300,7 +301,7 @@ const Post = ({
|
||||||
placeholderText="Won't expire"
|
placeholderText="Won't expire"
|
||||||
selected={expiresAt}
|
selected={expiresAt}
|
||||||
showTimeInput={true}
|
showTimeInput={true}
|
||||||
// @ts-ignore
|
// @ts-expect-error fix time input type
|
||||||
customTimeInput={<CustomTimeInput />}
|
customTimeInput={<CustomTimeInput />}
|
||||||
timeInputLabel="Time:"
|
timeInputLabel="Time:"
|
||||||
dateFormat="MM/dd/yyyy h:mm aa"
|
dateFormat="MM/dd/yyyy h:mm aa"
|
||||||
|
|
|
@ -31,7 +31,7 @@ const NewFromExisting = async ({
|
||||||
select: {
|
select: {
|
||||||
title: true,
|
title: true,
|
||||||
content: true,
|
content: true,
|
||||||
id: true,
|
id: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
import { getCurrentUser } from "@lib/server/session"
|
|
||||||
import { redirect } from "next/navigation"
|
|
||||||
|
|
||||||
export default function NewLayout({ children }: { children: React.ReactNode }) {
|
export default function NewLayout({ children }: { children: React.ReactNode }) {
|
||||||
return <>{children}</>
|
return <>{children}</>
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,4 +5,4 @@ const New = () => <NewPost />
|
||||||
|
|
||||||
export default New
|
export default New
|
||||||
|
|
||||||
export const dynamic = 'force-static'
|
export const dynamic = "force-static"
|
||||||
|
|
|
@ -26,9 +26,11 @@ export const PostTitle = ({
|
||||||
}: TitleProps) => {
|
}: TitleProps) => {
|
||||||
return (
|
return (
|
||||||
<span className={styles.title}>
|
<span className={styles.title}>
|
||||||
<h1 style={{
|
<h1
|
||||||
|
style={{
|
||||||
fontSize: "1.175rem"
|
fontSize: "1.175rem"
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
{title}{" "}
|
{title}{" "}
|
||||||
<span style={{ color: "var(--gray)" }}>
|
<span style={{ color: "var(--gray)" }}>
|
||||||
by{" "}
|
by{" "}
|
||||||
|
|
|
@ -77,11 +77,13 @@ const PostFiles = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main style={{
|
<main
|
||||||
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
gap: "var(--gap-double)"
|
gap: "var(--gap-double)"
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
{post.files?.map(({ id, content, title, html }) => (
|
{post.files?.map(({ id, content, title, html }) => (
|
||||||
<DocumentComponent
|
<DocumentComponent
|
||||||
skeleton={false}
|
skeleton={false}
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { memo, useEffect } from "react"
|
|
||||||
import styles from "./document.module.css"
|
|
||||||
import Skeleton from "@components/skeleton"
|
|
||||||
import Link from "next/link"
|
|
||||||
|
|
||||||
import Tooltip from "@components/tooltip"
|
|
||||||
import Button from "@components/button"
|
import Button from "@components/button"
|
||||||
import ButtonGroup from "@components/button-group"
|
import ButtonGroup from "@components/button-group"
|
||||||
|
import Skeleton from "@components/skeleton"
|
||||||
|
import Tooltip from "@components/tooltip"
|
||||||
import DocumentTabs from "app/(posts)/components/tabs"
|
import DocumentTabs from "app/(posts)/components/tabs"
|
||||||
|
import Link from "next/link"
|
||||||
|
import { memo } from "react"
|
||||||
import { Download, ExternalLink } from "react-feather"
|
import { Download, ExternalLink } from "react-feather"
|
||||||
|
import styles from "./document.module.css"
|
||||||
|
|
||||||
type SharedProps = {
|
type SharedProps = {
|
||||||
title?: string
|
title?: string
|
||||||
|
@ -22,9 +21,11 @@ type SharedProps = {
|
||||||
type Props = (
|
type Props = (
|
||||||
| {
|
| {
|
||||||
skeleton?: true
|
skeleton?: true
|
||||||
|
// eslint-disable-next-line no-mixed-spaces-and-tabs
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
skeleton?: false
|
skeleton?: false
|
||||||
|
// eslint-disable-next-line no-mixed-spaces-and-tabs
|
||||||
}
|
}
|
||||||
) &
|
) &
|
||||||
SharedProps
|
SharedProps
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
import { notFound, redirect } from "next/navigation"
|
import { notFound, redirect } from "next/navigation"
|
||||||
import {
|
import { getPostById, Post, PostWithFilesAndAuthor } from "@lib/server/prisma"
|
||||||
getPostById,
|
|
||||||
Post,
|
|
||||||
PostWithFilesAndAuthor
|
|
||||||
} from "@lib/server/prisma"
|
|
||||||
import { getCurrentUser } from "@lib/server/session"
|
import { getCurrentUser } from "@lib/server/session"
|
||||||
import ScrollToTop from "@components/scroll-to-top"
|
import ScrollToTop from "@components/scroll-to-top"
|
||||||
import { title } from "process"
|
import { title } from "process"
|
||||||
|
|
|
@ -27,7 +27,7 @@ const getPost = async (id: string) => {
|
||||||
content: true,
|
content: true,
|
||||||
updatedAt: true,
|
updatedAt: true,
|
||||||
title: true,
|
title: true,
|
||||||
html: true,
|
html: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import Button from "@components/button"
|
import Button from "@components/button"
|
||||||
import ButtonDropdown from "@components/button-dropdown"
|
|
||||||
import { Spinner } from "@components/spinner"
|
import { Spinner } from "@components/spinner"
|
||||||
import { useToasts } from "@components/toasts"
|
import { useToasts } from "@components/toasts"
|
||||||
import { Post, User } from "@lib/server/prisma"
|
import { Post, User } from "@lib/server/prisma"
|
||||||
|
@ -19,7 +18,6 @@ export function UserTable({
|
||||||
email: string | null
|
email: string | null
|
||||||
role: string | null
|
role: string | null
|
||||||
displayName: string | null
|
displayName: string | null
|
||||||
|
|
||||||
}[]
|
}[]
|
||||||
}) {
|
}) {
|
||||||
const { setToast } = useToasts()
|
const { setToast } = useToasts()
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { Spinner } from "@components/spinner"
|
|
||||||
import { getAllPosts, getAllUsers } from "@lib/server/prisma"
|
import { getAllPosts, getAllUsers } from "@lib/server/prisma"
|
||||||
import { PostTable, UserTable } from "./components/tables"
|
import { PostTable, UserTable } from "./components/tables"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import PostList from "@components/post-list"
|
import PostList from "@components/post-list"
|
||||||
import { getPostsByUser, getUserById } from "@lib/server/prisma"
|
import { getPostsByUser, getUserById } from "@lib/server/prisma"
|
||||||
|
import Image from "next/image"
|
||||||
import { Suspense } from "react"
|
import { Suspense } from "react"
|
||||||
|
import { User } from "react-feather"
|
||||||
|
|
||||||
async function PostListWrapper({
|
async function PostListWrapper({
|
||||||
posts,
|
posts,
|
||||||
|
@ -28,15 +30,40 @@ export default async function UserPage({
|
||||||
}) {
|
}) {
|
||||||
// TODO: the route should be user.name, not id
|
// TODO: the route should be user.name, not id
|
||||||
const id = params.username
|
const id = params.username
|
||||||
const user = await getUserById(id)
|
const user = await getUserById(id, {
|
||||||
|
image: true
|
||||||
|
})
|
||||||
|
|
||||||
const posts = getPostsByUser(id, true)
|
const posts = getPostsByUser(id, true)
|
||||||
|
|
||||||
|
const Avatar = () => {
|
||||||
|
if (!user?.image) {
|
||||||
|
return <User />
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Image
|
||||||
|
src={user.image}
|
||||||
|
alt="User avatar"
|
||||||
|
className="w-12 h-12 rounded-full"
|
||||||
|
width={48}
|
||||||
|
height={48}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between"
|
||||||
|
}}
|
||||||
|
>
|
||||||
<h1>Public posts by {user?.displayName || "Anonymous"}</h1>
|
<h1>Public posts by {user?.displayName || "Anonymous"}</h1>
|
||||||
|
<Avatar />
|
||||||
|
</div>
|
||||||
<Suspense fallback={<PostList initialPosts={JSON.stringify({})} />}>
|
<Suspense fallback={<PostList initialPosts={JSON.stringify({})} />}>
|
||||||
{/* @ts-ignore because TS async JSX support is iffy */}
|
{/* @ts-expect-error because TS async JSX support is iffy */}
|
||||||
<PostListWrapper posts={posts} userId={id} />
|
<PostListWrapper posts={posts} userId={id} />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -60,12 +60,10 @@ const Header = () => {
|
||||||
)
|
)
|
||||||
} else if (tab.href) {
|
} else if (tab.href) {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link key={tab.value} href={tab.href} data-tab={tab.value}>
|
||||||
key={tab.value}
|
<Button className={activeStyle} iconLeft={tab.icon}>
|
||||||
href={tab.href}
|
{tab.name ? tab.name : undefined}
|
||||||
data-tab={tab.value}
|
</Button>
|
||||||
>
|
|
||||||
<Button className={activeStyle} iconLeft={tab.icon}>{tab.name ? tab.name : undefined}</Button>
|
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,6 @@ const ListItem = ({
|
||||||
<li key={file.id}>
|
<li key={file.id}>
|
||||||
<Link colored href={`/post/${post.id}#${file.title}`}>
|
<Link colored href={`/post/${post.id}#${file.title}`}>
|
||||||
{getIconFromFilename(file.title)}
|
{getIconFromFilename(file.title)}
|
||||||
|
|
||||||
{file.title || "Untitled file"}
|
{file.title || "Untitled file"}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -33,3 +33,9 @@
|
||||||
gap: var(--gap-half);
|
gap: var(--gap-half);
|
||||||
margin-bottom: var(--gap);
|
margin-bottom: var(--gap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.container ul {
|
||||||
|
padding: 0 var(--gap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,11 +3,13 @@ import styles from "./skeleton.module.css"
|
||||||
export default function Skeleton({
|
export default function Skeleton({
|
||||||
width = 100,
|
width = 100,
|
||||||
height = 24,
|
height = 24,
|
||||||
borderRadius = 4,
|
borderRadius = 4
|
||||||
}: {
|
}: {
|
||||||
width?: number | string
|
width?: number | string
|
||||||
height?: number | string,
|
height?: number | string
|
||||||
borderRadius?: number | string
|
borderRadius?: number | string
|
||||||
}) {
|
}) {
|
||||||
return <div className={styles.skeleton} style={{ width, height, borderRadius }} />
|
return (
|
||||||
|
<div className={styles.skeleton} style={{ width, height, borderRadius }} />
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
"use client";
|
"use client"
|
||||||
import Toast, { Toaster } from "react-hot-toast"
|
import Toast, { Toaster } from "react-hot-toast"
|
||||||
|
|
||||||
export type ToastType = "success" | "error" | "loading" | "default"
|
export type ToastType = "success" | "error" | "loading" | "default"
|
||||||
|
|
|
@ -4,9 +4,9 @@ import { Providers } from "./providers"
|
||||||
import Page from "@components/page"
|
import Page from "@components/page"
|
||||||
import { Toasts } from "@components/toasts"
|
import { Toasts } from "@components/toasts"
|
||||||
import Header from "@components/header"
|
import Header from "@components/header"
|
||||||
import { Inter } from '@next/font/google';
|
import { Inter } from "@next/font/google"
|
||||||
|
|
||||||
const inter = Inter({ subsets: ['latin'], variable: "--inter-font" })
|
const inter = Inter({ subsets: ["latin"], variable: "--inter-font" })
|
||||||
|
|
||||||
interface RootLayoutProps {
|
interface RootLayoutProps {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
|
|
|
@ -5,3 +5,43 @@
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
margin-top: var(--gap);
|
margin-top: var(--gap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* <div className={styles.upload}>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
disabled={imageViaOauth}
|
||||||
|
className={styles.uploadInput}
|
||||||
|
/>
|
||||||
|
<Button type="button" disabled={imageViaOauth} width="100%" className={styles.uploadButton}>
|
||||||
|
Upload
|
||||||
|
</Button>
|
||||||
|
</div> */
|
||||||
|
/* we want the file input to be invisible and full width but still interactive button */
|
||||||
|
.upload {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--gap);
|
||||||
|
max-width: 300px;
|
||||||
|
margin-top: var(--gap);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploadInput {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 300px;
|
||||||
|
height: 37px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploadButton {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hover should affect button */
|
||||||
|
.uploadInput:hover + button {
|
||||||
|
border: 1px solid var(--fg);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -4,13 +4,13 @@ import Button from "@components/button"
|
||||||
import Input from "@components/input"
|
import Input from "@components/input"
|
||||||
import Note from "@components/note"
|
import Note from "@components/note"
|
||||||
import { useToasts } from "@components/toasts"
|
import { useToasts } from "@components/toasts"
|
||||||
import { User } from "next-auth"
|
import { useSession } from "next-auth/react"
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
import styles from "./profile.module.css"
|
import styles from "./profile.module.css"
|
||||||
|
|
||||||
const Profile = ({ user }: { user: User }) => {
|
const Profile = () => {
|
||||||
// TODO: make this displayName, requires fetching user from DB as session doesnt have it
|
const { data: session } = useSession()
|
||||||
const [name, setName] = useState<string>(user.name || "")
|
const [name, setName] = useState<string>(session?.user.displayName || "")
|
||||||
const [submitting, setSubmitting] = useState<boolean>(false)
|
const [submitting, setSubmitting] = useState<boolean>(false)
|
||||||
|
|
||||||
const { setToast } = useToasts()
|
const { setToast } = useToasts()
|
||||||
|
@ -31,10 +31,10 @@ const Profile = ({ user }: { user: User }) => {
|
||||||
setSubmitting(true)
|
setSubmitting(true)
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
displayName: name,
|
displayName: name
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await fetch(`/api/user/${user.id}`, {
|
const res = await fetch(`/api/user/${session?.user.id}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
|
@ -57,6 +57,18 @@ const Profile = ({ user }: { user: User }) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if we have their email, they signed in with OAuth */
|
||||||
|
// const imageViaOauth = Boolean(session?.user.email)
|
||||||
|
|
||||||
|
// const TooltipComponent = ({ children }: { children: React.ReactNode }) =>
|
||||||
|
// imageViaOauth ? (
|
||||||
|
// <Tooltip content="Change your profile image on your OAuth provider">
|
||||||
|
// {children}
|
||||||
|
// </Tooltip>
|
||||||
|
// ) : (
|
||||||
|
// <>{children}</>
|
||||||
|
// )
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Note type="warning">
|
<Note type="warning">
|
||||||
|
@ -83,12 +95,49 @@ const Profile = ({ user }: { user: User }) => {
|
||||||
type="email"
|
type="email"
|
||||||
width={"100%"}
|
width={"100%"}
|
||||||
placeholder="my@email.io"
|
placeholder="my@email.io"
|
||||||
value={user.email || undefined}
|
value={session?.user.email || undefined}
|
||||||
disabled
|
disabled
|
||||||
aria-label="Email"
|
aria-label="Email"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Button type="submit" loading={submitting}>Submit</Button>
|
{/* <div>
|
||||||
|
<label htmlFor="image">User Avatar</label>
|
||||||
|
{user.image ? (
|
||||||
|
<Input
|
||||||
|
id="image"
|
||||||
|
type="file"
|
||||||
|
width={"100%"}
|
||||||
|
placeholder="my image"
|
||||||
|
disabled
|
||||||
|
aria-label="Image"
|
||||||
|
src={user.image}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<UserIcon />
|
||||||
|
)}
|
||||||
|
<TooltipComponent>
|
||||||
|
<div className={styles.upload}>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
disabled={imageViaOauth}
|
||||||
|
className={styles.uploadInput}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
disabled={imageViaOauth}
|
||||||
|
width="100%"
|
||||||
|
className={styles.uploadButton}
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
Upload
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</TooltipComponent>
|
||||||
|
</div> */}
|
||||||
|
|
||||||
|
<Button type="submit" loading={submitting}>
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,19 +1,10 @@
|
||||||
import SettingsGroup from "../components/settings-group"
|
import SettingsGroup from "../components/settings-group"
|
||||||
import Profile from "app/settings/components/sections/profile"
|
import Profile from "app/settings/components/sections/profile"
|
||||||
import { authOptions } from "@lib/server/auth"
|
|
||||||
import { getCurrentUser } from "@lib/server/session"
|
|
||||||
import { redirect } from "next/navigation"
|
|
||||||
|
|
||||||
export default async function SettingsPage() {
|
export default async function SettingsPage() {
|
||||||
const user = await getCurrentUser()
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
return redirect(authOptions.pages?.signIn || "/new")
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingsGroup title="Profile">
|
<SettingsGroup title="Profile">
|
||||||
<Profile user={user} />
|
<Profile />
|
||||||
</SettingsGroup>
|
</SettingsGroup>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,13 +35,13 @@ export const config = (env: Environment): Config => {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultIfUndefined = (str: string, defaultValue: string): string => {
|
// const defaultIfUndefined = (str: string, defaultValue: string): string => {
|
||||||
const value = env[str]
|
// const value = env[str]
|
||||||
if (value === undefined) {
|
// if (value === undefined) {
|
||||||
return defaultValue
|
// return defaultValue
|
||||||
}
|
// }
|
||||||
return value
|
// return value
|
||||||
}
|
// }
|
||||||
|
|
||||||
const validNodeEnvs = (str: EnvironmentValue) => {
|
const validNodeEnvs = (str: EnvironmentValue) => {
|
||||||
const valid = ["development", "production", "test"]
|
const valid = ["development", "production", "test"]
|
||||||
|
@ -56,14 +56,6 @@ export const config = (env: Environment): Config => {
|
||||||
|
|
||||||
const is_production = env.NODE_ENV === "production"
|
const is_production = env.NODE_ENV === "production"
|
||||||
|
|
||||||
const developmentDefault = (name: string, defaultValue: string): string => {
|
|
||||||
if (is_production) {
|
|
||||||
return throwIfUndefined(name)
|
|
||||||
} else {
|
|
||||||
return defaultIfUndefined(name, defaultValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
validNodeEnvs(env.NODE_ENV)
|
validNodeEnvs(env.NODE_ENV)
|
||||||
|
|
||||||
throwIfUndefined("DATABASE_URL")
|
throwIfUndefined("DATABASE_URL")
|
||||||
|
|
|
@ -22,7 +22,7 @@ interface File {
|
||||||
export interface GistResponse {
|
export interface GistResponse {
|
||||||
id: string
|
id: string
|
||||||
created_at: Timestamp
|
created_at: Timestamp
|
||||||
description: String
|
description: string
|
||||||
files: {
|
files: {
|
||||||
[key: string]: File
|
[key: string]: File
|
||||||
}
|
}
|
||||||
|
|
2
src/lib/gist/types.d.ts
vendored
2
src/lib/gist/types.d.ts
vendored
|
@ -6,6 +6,6 @@ export interface GistFile {
|
||||||
export interface Gist {
|
export interface Gist {
|
||||||
id: string
|
id: string
|
||||||
created_at: Date
|
created_at: Date
|
||||||
description: String
|
description: string
|
||||||
files: GistFile[]
|
files: GistFile[]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { useRef, useEffect } from "react"
|
import { useRef, useEffect } from "react"
|
||||||
|
|
||||||
function useTraceUpdate(props: { [key: string]: any }) {
|
function useTraceUpdate(props: { [key: string]: unknown }) {
|
||||||
const prev = useRef(props)
|
const prev = useRef(props)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const changedProps = Object.entries(props).reduce((ps, [k, v]) => {
|
const changedProps = Object.entries(props).reduce((ps, [k, v]) => {
|
||||||
|
@ -8,7 +8,7 @@ function useTraceUpdate(props: { [key: string]: any }) {
|
||||||
ps[k] = [prev.current[k], v]
|
ps[k] = [prev.current[k], v]
|
||||||
}
|
}
|
||||||
return ps
|
return ps
|
||||||
}, {} as { [key: string]: any })
|
}, {} as { [key: string]: unknown })
|
||||||
if (Object.keys(changedProps).length > 0) {
|
if (Object.keys(changedProps).length > 0) {
|
||||||
console.log("Changed props:", changedProps)
|
console.log("Changed props:", changedProps)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,9 @@ import CredentialsProvider from "next-auth/providers/credentials"
|
||||||
import { prisma } from "@lib/server/prisma"
|
import { prisma } from "@lib/server/prisma"
|
||||||
import config from "@lib/config"
|
import config from "@lib/config"
|
||||||
import * as crypto from "crypto"
|
import * as crypto from "crypto"
|
||||||
import { Provider } from "next-auth/providers"
|
|
||||||
|
|
||||||
const credentialsOptions = () => {
|
const credentialsOptions = () => {
|
||||||
const options: Record<string, any> = {
|
const options: Record<string, unknown> = {
|
||||||
username: {
|
username: {
|
||||||
label: "Username",
|
label: "Username",
|
||||||
required: true,
|
required: true,
|
||||||
|
@ -47,7 +46,8 @@ const providers = () => {
|
||||||
providers.push(
|
providers.push(
|
||||||
CredentialsProvider({
|
CredentialsProvider({
|
||||||
name: "Drift",
|
name: "Drift",
|
||||||
credentials: credentialsOptions(),
|
// @ts-expect-error TODO: fix types
|
||||||
|
credentials: credentialsOptions() as unknown,
|
||||||
async authorize(credentials) {
|
async authorize(credentials) {
|
||||||
if (!credentials || !credentials.username || !credentials.password) {
|
if (!credentials || !credentials.username || !credentials.password) {
|
||||||
throw new Error("Missing credentials")
|
throw new Error("Missing credentials")
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
declare global {
|
declare global {
|
||||||
|
// eslint-disable-next-line no-var
|
||||||
var prisma: PrismaClient | undefined
|
var prisma: PrismaClient | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
import config from "@lib/config"
|
import config from "@lib/config"
|
||||||
import { Post, PrismaClient, File, User, Prisma } from "@prisma/client"
|
import { Post, PrismaClient, User, Prisma } from "@prisma/client"
|
||||||
export type { User, File, Post } from "@prisma/client"
|
export type { User, File, Post } from "@prisma/client"
|
||||||
|
|
||||||
export const prisma =
|
export const prisma =
|
||||||
|
@ -126,7 +127,7 @@ export async function getPostsByUser(userId: User["id"], withFiles?: boolean) {
|
||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
title: true,
|
title: true,
|
||||||
createdAt: true,
|
createdAt: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -136,7 +137,10 @@ export async function getPostsByUser(userId: User["id"], withFiles?: boolean) {
|
||||||
return posts
|
return posts
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getUserById = async (userId: User["id"]) => {
|
export const getUserById = async (
|
||||||
|
userId: User["id"],
|
||||||
|
selects?: Prisma.UserFindUniqueArgs["select"]
|
||||||
|
) => {
|
||||||
const user = await prisma.user.findUnique({
|
const user = await prisma.user.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: userId
|
id: userId
|
||||||
|
@ -146,7 +150,8 @@ export const getUserById = async (userId: User["id"]) => {
|
||||||
email: true,
|
email: true,
|
||||||
// displayName: true,
|
// displayName: true,
|
||||||
role: true,
|
role: true,
|
||||||
displayName: true
|
displayName: true,
|
||||||
|
...selects
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -199,7 +204,7 @@ export const getPostById = async (
|
||||||
postId: Post["id"],
|
postId: Post["id"],
|
||||||
options?: GetPostByIdOptions
|
options?: GetPostByIdOptions
|
||||||
): Promise<Post | PostWithFiles | PostWithFilesAndAuthor | null> => {
|
): Promise<Post | PostWithFiles | PostWithFilesAndAuthor | null> => {
|
||||||
let post = await prisma.post.findUnique({
|
const post = await prisma.post.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: postId
|
id: postId
|
||||||
},
|
},
|
||||||
|
|
|
@ -11,7 +11,7 @@ const epochs = [
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
const getDuration = (timeAgoInSeconds: number) => {
|
const getDuration = (timeAgoInSeconds: number) => {
|
||||||
for (let [name, seconds] of epochs) {
|
for (const [name, seconds] of epochs) {
|
||||||
const interval = Math.floor(timeAgoInSeconds / seconds)
|
const interval = Math.floor(timeAgoInSeconds / seconds)
|
||||||
|
|
||||||
if (interval >= 1) {
|
if (interval >= 1) {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
"dev": "next dev --port 3000",
|
"dev": "next dev --port 3000",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start --port 3000",
|
"start": "next start --port 3000",
|
||||||
"lint": "next lint && prettier --list-different --config .prettierrc '{components,lib,app}/**/*.{ts,tsx}' --write",
|
"lint": "next lint && prettier --list-different --config .prettierrc '{components,lib,app,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",
|
"prisma": "prisma",
|
||||||
|
@ -51,6 +51,8 @@
|
||||||
"@types/react-datepicker": "4.4.1",
|
"@types/react-datepicker": "4.4.1",
|
||||||
"@types/react-dom": "18.0.3",
|
"@types/react-dom": "18.0.3",
|
||||||
"@types/uuid": "^9.0.0",
|
"@types/uuid": "^9.0.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.46.1",
|
||||||
|
"@typescript-eslint/parser": "^5.46.1",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"csstype": "^3.1.1",
|
"csstype": "^3.1.1",
|
||||||
|
|
|
@ -45,13 +45,15 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
switch (req.method) {
|
switch (req.method) {
|
||||||
case "GET":
|
case "GET":
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case "users":
|
case "users": {
|
||||||
const users = await prisma.user.findMany()
|
const users = await prisma.user.findMany()
|
||||||
return res.status(200).json(users)
|
return res.status(200).json(users)
|
||||||
case "posts":
|
}
|
||||||
|
case "posts": {
|
||||||
const posts = await prisma.post.findMany()
|
const posts = await prisma.post.findMany()
|
||||||
return res.status(200).json(posts)
|
return res.status(200).json(posts)
|
||||||
case "user":
|
}
|
||||||
|
case "user": {
|
||||||
const { id: userId } = req.query
|
const { id: userId } = req.query
|
||||||
const user = await prisma.user.findUnique({
|
const user = await prisma.user.findUnique({
|
||||||
where: {
|
where: {
|
||||||
|
@ -59,7 +61,8 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return res.status(200).json(user)
|
return res.status(200).json(user)
|
||||||
case "post":
|
}
|
||||||
|
case "post": {
|
||||||
const { id: postId } = req.query
|
const { id: postId } = req.query
|
||||||
const post = await prisma.post.findUnique({
|
const post = await prisma.post.findUnique({
|
||||||
where: {
|
where: {
|
||||||
|
@ -68,10 +71,11 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
})
|
})
|
||||||
return res.status(200).json(post)
|
return res.status(200).json(post)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case "PATCH":
|
case "PATCH":
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case "set-role":
|
case "set-role": {
|
||||||
const { userId, role } = req.body
|
const { userId, role } = req.body
|
||||||
if (!userId || !role || role !== "admin" || role !== "user") {
|
if (!userId || !role || role !== "admin" || role !== "user") {
|
||||||
return res.status(400).json({ error: "Invalid request" })
|
return res.status(400).json({ error: "Invalid request" })
|
||||||
|
@ -86,10 +90,11 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
|
|
||||||
return res.status(200).json(user)
|
return res.status(200).json(user)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case "DELETE":
|
case "DELETE":
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case "delete-user":
|
case "delete-user": {
|
||||||
const { userId } = req.body
|
const { userId } = req.body
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
return res.status(400).json({ error: "Invalid request" })
|
return res.status(400).json({ error: "Invalid request" })
|
||||||
|
@ -98,7 +103,8 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
await deleteUser(userId)
|
await deleteUser(userId)
|
||||||
|
|
||||||
return res.status(200).send("User deleted")
|
return res.status(200).send("User deleted")
|
||||||
case "delete-post":
|
}
|
||||||
|
case "delete-post": {
|
||||||
const { postId } = req.body
|
const { postId } = req.body
|
||||||
if (!postId) {
|
if (!postId) {
|
||||||
return res.status(400).json({ error: "Invalid request" })
|
return res.status(400).json({ error: "Invalid request" })
|
||||||
|
@ -110,6 +116,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
|
|
||||||
return res.status(200).json(post)
|
return res.status(200).json(post)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ export default async function requiresPasscode(
|
||||||
if (slug === "requires-passcode") {
|
if (slug === "requires-passcode") {
|
||||||
return handleRequiresPasscode(req, res)
|
return handleRequiresPasscode(req, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return res.status(404).json({ error: "Not found" })
|
||||||
default:
|
default:
|
||||||
return res.status(405).json({ error: "Method not allowed" })
|
return res.status(405).json({ error: "Method not allowed" })
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { withMethods } from "@lib/api-middleware/with-methods"
|
import { withMethods } from "@lib/api-middleware/with-methods"
|
||||||
import { parseQueryParam } from "@lib/server/parse-query-param"
|
import { parseQueryParam } from "@lib/server/parse-query-param"
|
||||||
import { getPostById, PostWithFiles } from "@lib/server/prisma"
|
import { getPostById } from "@lib/server/prisma"
|
||||||
import type { NextApiRequest, NextApiResponse } from "next"
|
import type { NextApiRequest, NextApiResponse } from "next"
|
||||||
import { getSession } from "next-auth/react"
|
import { getSession } from "next-auth/react"
|
||||||
import { prisma } from "lib/server/prisma"
|
import { prisma } from "lib/server/prisma"
|
||||||
|
@ -14,7 +14,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
|
|
||||||
export default withMethods(["GET", "PUT", "DELETE"], handler)
|
export default withMethods(["GET", "PUT", "DELETE"], handler)
|
||||||
|
|
||||||
async function handleGet(req: NextApiRequest, res: NextApiResponse<any>) {
|
async function handleGet(req: NextApiRequest, res: NextApiResponse<unknown>) {
|
||||||
const id = parseQueryParam(req.query.id)
|
const id = parseQueryParam(req.query.id)
|
||||||
|
|
||||||
if (!id) {
|
if (!id) {
|
||||||
|
@ -44,7 +44,7 @@ async function handleGet(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||||
// the user can always go directly to their own post
|
// the user can always go directly to their own post
|
||||||
if (session?.user.id === post.authorId) {
|
if (session?.user.id === post.authorId) {
|
||||||
return res.json({
|
return res.json({
|
||||||
...post,
|
...post
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ async function handleGet(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||||
|
|
||||||
if (hash === post.password) {
|
if (hash === post.password) {
|
||||||
return res.json({
|
return res.json({
|
||||||
...post,
|
...post
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
|
@ -76,7 +76,7 @@ async function handleGet(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// PUT is for adjusting visibility and password
|
// PUT is for adjusting visibility and password
|
||||||
async function handlePut(req: NextApiRequest, res: NextApiResponse<any>) {
|
async function handlePut(req: NextApiRequest, res: NextApiResponse<unknown>) {
|
||||||
const { password, visibility } = req.body
|
const { password, visibility } = req.body
|
||||||
const id = parseQueryParam(req.query.id)
|
const id = parseQueryParam(req.query.id)
|
||||||
|
|
||||||
|
@ -124,7 +124,10 @@ async function handlePut(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleDelete(req: NextApiRequest, res: NextApiResponse<any>) {
|
async function handleDelete(
|
||||||
|
req: NextApiRequest,
|
||||||
|
res: NextApiResponse<unknown>
|
||||||
|
) {
|
||||||
const id = parseQueryParam(req.query.id)
|
const id = parseQueryParam(req.query.id)
|
||||||
|
|
||||||
if (!id) {
|
if (!id) {
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
// nextjs typescript api handler
|
|
||||||
|
|
||||||
import { withMethods } from "@lib/api-middleware/with-methods"
|
import { withMethods } from "@lib/api-middleware/with-methods"
|
||||||
|
|
||||||
import { authOptions } from "@lib/server/auth"
|
import { authOptions } from "@lib/server/auth"
|
||||||
import { prisma, getPostById } from "@lib/server/prisma"
|
import { prisma } from "@lib/server/prisma"
|
||||||
import { NextApiRequest, NextApiResponse } from "next"
|
import { NextApiRequest, NextApiResponse } from "next"
|
||||||
import { unstable_getServerSession } from "next-auth/next"
|
import { unstable_getServerSession } from "next-auth/next"
|
||||||
import { File } from "@lib/server/prisma"
|
import { File } from "@lib/server/prisma"
|
||||||
import * as crypto from "crypto"
|
import * as crypto from "crypto"
|
||||||
import { getHtmlFromFile } from "@lib/server/get-html-from-drift-file"
|
import { getHtmlFromFile } from "@lib/server/get-html-from-drift-file"
|
||||||
import { getSession } from "next-auth/react"
|
|
||||||
import { parseQueryParam } from "@lib/server/parse-query-param"
|
|
||||||
|
|
||||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
return await handlePost(req, res)
|
return await handlePost(req, res)
|
||||||
|
@ -18,7 +14,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
|
|
||||||
export default withMethods(["POST"], handler)
|
export default withMethods(["POST"], handler)
|
||||||
|
|
||||||
async function handlePost(req: NextApiRequest, res: NextApiResponse<any>) {
|
async function handlePost(req: NextApiRequest, res: NextApiResponse<unknown>) {
|
||||||
try {
|
try {
|
||||||
const session = await unstable_getServerSession(req, res, authOptions)
|
const session = await unstable_getServerSession(req, res, authOptions)
|
||||||
if (!session || !session.user.id) {
|
if (!session || !session.user.id) {
|
||||||
|
@ -49,7 +45,7 @@ async function handlePost(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||||
throw new Error("You must submit at least one file")
|
throw new Error("You must submit at least one file")
|
||||||
}
|
}
|
||||||
|
|
||||||
let hashedPassword: string = ""
|
let hashedPassword = ""
|
||||||
if (req.body.visibility === "protected") {
|
if (req.body.visibility === "protected") {
|
||||||
hashedPassword = crypto
|
hashedPassword = crypto
|
||||||
.createHash("sha256")
|
.createHash("sha256")
|
||||||
|
|
|
@ -20,7 +20,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
let posts: ServerPostWithFiles[]
|
let posts: ServerPostWithFiles[]
|
||||||
if (session?.user.id === user || session?.user.role === "admin") {
|
if (session?.user.id === user || session?.user.role === "admin") {
|
||||||
posts = await searchPosts(query, {
|
posts = await searchPosts(query, {
|
||||||
userId: user,
|
userId: user
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
posts = await searchPosts(query, {
|
posts = await searchPosts(query, {
|
||||||
|
|
|
@ -23,7 +23,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (req.method) {
|
switch (req.method) {
|
||||||
case "PUT":
|
case "PUT": {
|
||||||
const { displayName } = req.body
|
const { displayName } = req.body
|
||||||
const updatedUser = await prisma.user.update({
|
const updatedUser = await prisma.user.update({
|
||||||
where: {
|
where: {
|
||||||
|
@ -40,6 +40,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
name: updatedUser.displayName
|
name: updatedUser.displayName
|
||||||
// bio: updatedUser.bio
|
// bio: updatedUser.bio
|
||||||
})
|
})
|
||||||
|
}
|
||||||
case "GET":
|
case "GET":
|
||||||
return res.json(currUser)
|
return res.json(currUser)
|
||||||
case "DELETE":
|
case "DELETE":
|
||||||
|
@ -48,7 +49,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
await deleteUser(id)
|
await deleteUser(id)
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
return res.status(405).json({ message: "Method not allowed" })
|
return res.status(405).json({ message: "Method not allowed" })
|
||||||
}
|
}
|
||||||
|
@ -61,7 +62,6 @@ export default withMethods(["GET", "PUT", "DELETE"], handler)
|
||||||
* @warning This function does not perform any authorization checks
|
* @warning This function does not perform any authorization checks
|
||||||
*/
|
*/
|
||||||
export async function deleteUser(id: string | undefined) {
|
export async function deleteUser(id: string | undefined) {
|
||||||
|
|
||||||
// first delete all of the user's posts
|
// first delete all of the user's posts
|
||||||
await prisma.post.deleteMany({
|
await prisma.post.deleteMany({
|
||||||
where: {
|
where: {
|
||||||
|
|
|
@ -7,7 +7,7 @@ export default async function handle(
|
||||||
res: NextApiResponse
|
res: NextApiResponse
|
||||||
) {
|
) {
|
||||||
switch (req.method) {
|
switch (req.method) {
|
||||||
case "GET":
|
case "GET": {
|
||||||
const userId = parseQueryParam(req.query.userId)
|
const userId = parseQueryParam(req.query.userId)
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
return res.status(400).json({ error: "Missing userId" })
|
return res.status(400).json({ error: "Missing userId" })
|
||||||
|
@ -15,6 +15,7 @@ export default async function handle(
|
||||||
|
|
||||||
const posts = await getPostsByUser(userId)
|
const posts = await getPostsByUser(userId)
|
||||||
return res.json(posts)
|
return res.json(posts)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return res.status(405).end()
|
return res.status(405).end()
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ specifiers:
|
||||||
'@types/react-datepicker': 4.4.1
|
'@types/react-datepicker': 4.4.1
|
||||||
'@types/react-dom': 18.0.3
|
'@types/react-dom': 18.0.3
|
||||||
'@types/uuid': ^9.0.0
|
'@types/uuid': ^9.0.0
|
||||||
|
'@typescript-eslint/eslint-plugin': ^5.46.1
|
||||||
|
'@typescript-eslint/parser': ^5.46.1
|
||||||
'@wcj/markdown-to-html': ^2.1.2
|
'@wcj/markdown-to-html': ^2.1.2
|
||||||
'@wits/next-themes': 0.2.14
|
'@wits/next-themes': 0.2.14
|
||||||
client-only: ^0.0.1
|
client-only: ^0.0.1
|
||||||
|
@ -90,6 +92,8 @@ devDependencies:
|
||||||
'@types/react-datepicker': 4.4.1_biqbaboplfbrettd7655fr4n2y
|
'@types/react-datepicker': 4.4.1_biqbaboplfbrettd7655fr4n2y
|
||||||
'@types/react-dom': 18.0.3
|
'@types/react-dom': 18.0.3
|
||||||
'@types/uuid': 9.0.0
|
'@types/uuid': 9.0.0
|
||||||
|
'@typescript-eslint/eslint-plugin': 5.46.1_byqm7zzsgtndvuamqqta6vngru
|
||||||
|
'@typescript-eslint/parser': 5.46.1_hsmo2rtalirsvadpuxki35bq2i
|
||||||
clsx: 1.2.1
|
clsx: 1.2.1
|
||||||
cross-env: 7.0.3
|
cross-env: 7.0.3
|
||||||
csstype: 3.1.1
|
csstype: 3.1.1
|
||||||
|
@ -1509,6 +1513,10 @@ packages:
|
||||||
'@types/istanbul-lib-report': 3.0.0
|
'@types/istanbul-lib-report': 3.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@types/json-schema/7.0.11:
|
||||||
|
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/json5/0.0.29:
|
/@types/json5/0.0.29:
|
||||||
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -1583,6 +1591,10 @@ packages:
|
||||||
/@types/scheduler/0.16.2:
|
/@types/scheduler/0.16.2:
|
||||||
resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==}
|
resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==}
|
||||||
|
|
||||||
|
/@types/semver/7.3.13:
|
||||||
|
resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/stack-utils/2.0.1:
|
/@types/stack-utils/2.0.1:
|
||||||
resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==}
|
resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -1605,8 +1617,35 @@ packages:
|
||||||
'@types/yargs-parser': 21.0.0
|
'@types/yargs-parser': 21.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@typescript-eslint/parser/5.42.1_hsmo2rtalirsvadpuxki35bq2i:
|
/@typescript-eslint/eslint-plugin/5.46.1_byqm7zzsgtndvuamqqta6vngru:
|
||||||
resolution: {integrity: sha512-kAV+NiNBWVQDY9gDJDToTE/NO8BHi4f6b7zTsVAJoTkmB/zlfOpiEVBzHOKtlgTndCKe8vj9F/PuolemZSh50Q==}
|
resolution: {integrity: sha512-YpzNv3aayRBwjs4J3oz65eVLXc9xx0PDbIRisHj+dYhvBn02MjYOD96P8YGiWEIFBrojaUjxvkaUpakD82phsA==}
|
||||||
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
'@typescript-eslint/parser': ^5.0.0
|
||||||
|
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||||
|
typescript: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@typescript-eslint/parser': 5.46.1_hsmo2rtalirsvadpuxki35bq2i
|
||||||
|
'@typescript-eslint/scope-manager': 5.46.1
|
||||||
|
'@typescript-eslint/type-utils': 5.46.1_hsmo2rtalirsvadpuxki35bq2i
|
||||||
|
'@typescript-eslint/utils': 5.46.1_hsmo2rtalirsvadpuxki35bq2i
|
||||||
|
debug: 4.3.4
|
||||||
|
eslint: 8.27.0
|
||||||
|
ignore: 5.2.0
|
||||||
|
natural-compare-lite: 1.4.0
|
||||||
|
regexpp: 3.2.0
|
||||||
|
semver: 7.3.8
|
||||||
|
tsutils: 3.21.0_typescript@4.6.4
|
||||||
|
typescript: 4.6.4
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/parser/5.46.1_hsmo2rtalirsvadpuxki35bq2i:
|
||||||
|
resolution: {integrity: sha512-RelQ5cGypPh4ySAtfIMBzBGyrNerQcmfA1oJvPj5f+H4jI59rl9xxpn4bonC0tQvUKOEN7eGBFWxFLK3Xepneg==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||||
|
@ -1615,9 +1654,9 @@ packages:
|
||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/scope-manager': 5.42.1
|
'@typescript-eslint/scope-manager': 5.46.1
|
||||||
'@typescript-eslint/types': 5.42.1
|
'@typescript-eslint/types': 5.46.1
|
||||||
'@typescript-eslint/typescript-estree': 5.42.1_typescript@4.6.4
|
'@typescript-eslint/typescript-estree': 5.46.1_typescript@4.6.4
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
eslint: 8.27.0
|
eslint: 8.27.0
|
||||||
typescript: 4.6.4
|
typescript: 4.6.4
|
||||||
|
@ -1625,12 +1664,32 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@typescript-eslint/scope-manager/5.42.1:
|
/@typescript-eslint/scope-manager/5.46.1:
|
||||||
resolution: {integrity: sha512-QAZY/CBP1Emx4rzxurgqj3rUinfsh/6mvuKbLNMfJMMKYLRBfweus8brgXF8f64ABkIZ3zdj2/rYYtF8eiuksQ==}
|
resolution: {integrity: sha512-iOChVivo4jpwUdrJZyXSMrEIM/PvsbbDOX1y3UCKjSgWn+W89skxWaYXACQfxmIGhPVpRWK/VWPYc+bad6smIA==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 5.42.1
|
'@typescript-eslint/types': 5.46.1
|
||||||
'@typescript-eslint/visitor-keys': 5.42.1
|
'@typescript-eslint/visitor-keys': 5.46.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/type-utils/5.46.1_hsmo2rtalirsvadpuxki35bq2i:
|
||||||
|
resolution: {integrity: sha512-V/zMyfI+jDmL1ADxfDxjZ0EMbtiVqj8LUGPAGyBkXXStWmCUErMpW873zEHsyguWCuq2iN4BrlWUkmuVj84yng==}
|
||||||
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
eslint: '*'
|
||||||
|
typescript: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@typescript-eslint/typescript-estree': 5.46.1_typescript@4.6.4
|
||||||
|
'@typescript-eslint/utils': 5.46.1_hsmo2rtalirsvadpuxki35bq2i
|
||||||
|
debug: 4.3.4
|
||||||
|
eslint: 8.27.0
|
||||||
|
tsutils: 3.21.0_typescript@4.6.4
|
||||||
|
typescript: 4.6.4
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@typescript-eslint/types/4.33.0:
|
/@typescript-eslint/types/4.33.0:
|
||||||
|
@ -1638,8 +1697,8 @@ packages:
|
||||||
engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1}
|
engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@typescript-eslint/types/5.42.1:
|
/@typescript-eslint/types/5.46.1:
|
||||||
resolution: {integrity: sha512-Qrco9dsFF5lhalz+lLFtxs3ui1/YfC6NdXu+RAGBa8uSfn01cjO7ssCsjIsUs484vny9Xm699FSKwpkCcqwWwA==}
|
resolution: {integrity: sha512-Z5pvlCaZgU+93ryiYUwGwLl9AQVB/PQ1TsJ9NZ/gHzZjN7g9IAn6RSDkpCV8hqTwAiaj6fmCcKSQeBPlIpW28w==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
@ -1664,8 +1723,8 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@typescript-eslint/typescript-estree/5.42.1_typescript@4.6.4:
|
/@typescript-eslint/typescript-estree/5.46.1_typescript@4.6.4:
|
||||||
resolution: {integrity: sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==}
|
resolution: {integrity: sha512-j9W4t67QiNp90kh5Nbr1w92wzt+toiIsaVPnEblB2Ih2U9fqBTyqV9T3pYWZBRt6QoMh/zVWP59EpuCjc4VRBg==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '*'
|
typescript: '*'
|
||||||
|
@ -1673,8 +1732,8 @@ packages:
|
||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 5.42.1
|
'@typescript-eslint/types': 5.46.1
|
||||||
'@typescript-eslint/visitor-keys': 5.42.1
|
'@typescript-eslint/visitor-keys': 5.46.1
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
globby: 11.1.0
|
globby: 11.1.0
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
|
@ -1685,6 +1744,26 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/utils/5.46.1_hsmo2rtalirsvadpuxki35bq2i:
|
||||||
|
resolution: {integrity: sha512-RBdBAGv3oEpFojaCYT4Ghn4775pdjvwfDOfQ2P6qzNVgQOVrnSPe5/Pb88kv7xzYQjoio0eKHKB9GJ16ieSxvA==}
|
||||||
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||||
|
dependencies:
|
||||||
|
'@types/json-schema': 7.0.11
|
||||||
|
'@types/semver': 7.3.13
|
||||||
|
'@typescript-eslint/scope-manager': 5.46.1
|
||||||
|
'@typescript-eslint/types': 5.46.1
|
||||||
|
'@typescript-eslint/typescript-estree': 5.46.1_typescript@4.6.4
|
||||||
|
eslint: 8.27.0
|
||||||
|
eslint-scope: 5.1.1
|
||||||
|
eslint-utils: 3.0.0_eslint@8.27.0
|
||||||
|
semver: 7.3.8
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
- typescript
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@typescript-eslint/visitor-keys/4.33.0:
|
/@typescript-eslint/visitor-keys/4.33.0:
|
||||||
resolution: {integrity: sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==}
|
resolution: {integrity: sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==}
|
||||||
engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1}
|
engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1}
|
||||||
|
@ -1693,11 +1772,11 @@ packages:
|
||||||
eslint-visitor-keys: 2.1.0
|
eslint-visitor-keys: 2.1.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@typescript-eslint/visitor-keys/5.42.1:
|
/@typescript-eslint/visitor-keys/5.46.1:
|
||||||
resolution: {integrity: sha512-LOQtSF4z+hejmpUvitPlc4hA7ERGoj2BVkesOcG91HCn8edLGUXbTrErmutmPbl8Bo9HjAvOO/zBKQHExXNA2A==}
|
resolution: {integrity: sha512-jczZ9noovXwy59KjRTk1OftT78pwygdcmCuBf8yMoWt/8O8l+6x2LSEze0E4TeepXK4MezW3zGSyoDRZK7Y9cg==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 5.42.1
|
'@typescript-eslint/types': 5.46.1
|
||||||
eslint-visitor-keys: 3.3.0
|
eslint-visitor-keys: 3.3.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
@ -2780,11 +2859,11 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@next/eslint-plugin-next': 13.0.3
|
'@next/eslint-plugin-next': 13.0.3
|
||||||
'@rushstack/eslint-patch': 1.2.0
|
'@rushstack/eslint-patch': 1.2.0
|
||||||
'@typescript-eslint/parser': 5.42.1_hsmo2rtalirsvadpuxki35bq2i
|
'@typescript-eslint/parser': 5.46.1_hsmo2rtalirsvadpuxki35bq2i
|
||||||
eslint: 8.27.0
|
eslint: 8.27.0
|
||||||
eslint-import-resolver-node: 0.3.6
|
eslint-import-resolver-node: 0.3.6
|
||||||
eslint-import-resolver-typescript: 2.7.1_dcpv4nbdr5ks2h5677xdltrk6e
|
eslint-import-resolver-typescript: 2.7.1_dcpv4nbdr5ks2h5677xdltrk6e
|
||||||
eslint-plugin-import: 2.26.0_fjrawv2a4e2kreqduevmayjdry
|
eslint-plugin-import: 2.26.0_gqysc5ehwyt3mg2jls3nr3332q
|
||||||
eslint-plugin-jsx-a11y: 6.6.1_eslint@8.27.0
|
eslint-plugin-jsx-a11y: 6.6.1_eslint@8.27.0
|
||||||
eslint-plugin-react: 7.31.10_eslint@8.27.0
|
eslint-plugin-react: 7.31.10_eslint@8.27.0
|
||||||
eslint-plugin-react-hooks: 4.6.0_eslint@8.27.0
|
eslint-plugin-react-hooks: 4.6.0_eslint@8.27.0
|
||||||
|
@ -2812,7 +2891,7 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
eslint: 8.27.0
|
eslint: 8.27.0
|
||||||
eslint-plugin-import: 2.26.0_fjrawv2a4e2kreqduevmayjdry
|
eslint-plugin-import: 2.26.0_gqysc5ehwyt3mg2jls3nr3332q
|
||||||
glob: 7.2.3
|
glob: 7.2.3
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
resolve: 1.22.1
|
resolve: 1.22.1
|
||||||
|
@ -2821,7 +2900,7 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/eslint-module-utils/2.7.4_c5vbubjxm3sqe7zyydgtitlaga:
|
/eslint-module-utils/2.7.4_nw56cc7ve4sv3zakvubomgge2q:
|
||||||
resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==}
|
resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -2842,7 +2921,7 @@ packages:
|
||||||
eslint-import-resolver-webpack:
|
eslint-import-resolver-webpack:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/parser': 5.42.1_hsmo2rtalirsvadpuxki35bq2i
|
'@typescript-eslint/parser': 5.46.1_hsmo2rtalirsvadpuxki35bq2i
|
||||||
debug: 3.2.7
|
debug: 3.2.7
|
||||||
eslint: 8.27.0
|
eslint: 8.27.0
|
||||||
eslint-import-resolver-node: 0.3.6
|
eslint-import-resolver-node: 0.3.6
|
||||||
|
@ -2851,7 +2930,7 @@ packages:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/eslint-plugin-import/2.26.0_fjrawv2a4e2kreqduevmayjdry:
|
/eslint-plugin-import/2.26.0_gqysc5ehwyt3mg2jls3nr3332q:
|
||||||
resolution: {integrity: sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==}
|
resolution: {integrity: sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -2861,14 +2940,14 @@ packages:
|
||||||
'@typescript-eslint/parser':
|
'@typescript-eslint/parser':
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/parser': 5.42.1_hsmo2rtalirsvadpuxki35bq2i
|
'@typescript-eslint/parser': 5.46.1_hsmo2rtalirsvadpuxki35bq2i
|
||||||
array-includes: 3.1.6
|
array-includes: 3.1.6
|
||||||
array.prototype.flat: 1.3.1
|
array.prototype.flat: 1.3.1
|
||||||
debug: 2.6.9
|
debug: 2.6.9
|
||||||
doctrine: 2.1.0
|
doctrine: 2.1.0
|
||||||
eslint: 8.27.0
|
eslint: 8.27.0
|
||||||
eslint-import-resolver-node: 0.3.6
|
eslint-import-resolver-node: 0.3.6
|
||||||
eslint-module-utils: 2.7.4_c5vbubjxm3sqe7zyydgtitlaga
|
eslint-module-utils: 2.7.4_nw56cc7ve4sv3zakvubomgge2q
|
||||||
has: 1.0.3
|
has: 1.0.3
|
||||||
is-core-module: 2.11.0
|
is-core-module: 2.11.0
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
|
@ -2936,6 +3015,14 @@ packages:
|
||||||
string.prototype.matchall: 4.0.8
|
string.prototype.matchall: 4.0.8
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/eslint-scope/5.1.1:
|
||||||
|
resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
|
||||||
|
engines: {node: '>=8.0.0'}
|
||||||
|
dependencies:
|
||||||
|
esrecurse: 4.3.0
|
||||||
|
estraverse: 4.3.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/eslint-scope/7.1.1:
|
/eslint-scope/7.1.1:
|
||||||
resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==}
|
resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
@ -3040,6 +3127,11 @@ packages:
|
||||||
estraverse: 5.3.0
|
estraverse: 5.3.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/estraverse/4.3.0:
|
||||||
|
resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==}
|
||||||
|
engines: {node: '>=4.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/estraverse/5.3.0:
|
/estraverse/5.3.0:
|
||||||
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
|
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
|
||||||
engines: {node: '>=4.0'}
|
engines: {node: '>=4.0'}
|
||||||
|
@ -5102,6 +5194,10 @@ packages:
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
/natural-compare-lite/1.4.0:
|
||||||
|
resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/natural-compare/1.4.0:
|
/natural-compare/1.4.0:
|
||||||
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue