refactor: some adjustments

This commit is contained in:
Daniel Soares
2021-12-19 20:03:59 -03:00
parent a9ff01aa52
commit e4b037f273
52 changed files with 417 additions and 481 deletions

View File

@@ -1,9 +1,30 @@
{ {
"extends": ["next", "next/core-web-vitals", "plugin:prettier/recommended"], "extends": [
"plugins": ["prettier", "simple-import-sort"], "next",
"next/core-web-vitals",
"plugin:prettier/recommended",
"plugin:import/recommended",
"plugin:import/typescript"
],
"plugins": ["prettier", "import"],
"rules": { "rules": {
"prettier/prettier": "error", "prettier/prettier": "error",
"simple-import-sort/imports": "error", "import/order": [
"simple-import-sort/exports": "error" "error",
{
"groups": [
"builtin",
"external",
"internal",
"parent",
"sibling",
"index",
"object",
"type"
],
"newlines-between": "always"
}
],
"@next/next/no-page-custom-font": "off"
} }
} }

View File

@@ -19,50 +19,50 @@
"prisma:seed": "prisma db seed" "prisma:seed": "prisma db seed"
}, },
"dependencies": { "dependencies": {
"@prisma/client": "^3.6.0", "@prisma/client": "3.6.0",
"axios": "^0.24.0", "axios": "0.24.0",
"bcryptjs": "^2.4.3", "bcryptjs": "2.4.3",
"cuid": "^2.1.8", "cuid": "2.1.8",
"dotenv": "^10.0.0", "dotenv": "10.0.0",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "8.5.1",
"lodash": "^4.17.21", "lodash": "4.17.21",
"next": "12.0.7", "next": "12.0.7",
"next-connect": "^0.11.0", "next-connect": "0.11.0",
"nookies": "^2.5.2", "nookies": "2.5.2",
"polished": "^4.1.3", "polished": "4.1.3",
"rc-slider": "^9.7.5", "rc-slider": "9.7.5",
"react": "^17.0.2", "react": "17.0.2",
"react-collapsible": "^2.8.4", "react-collapsible": "2.8.4",
"react-color": "^2.19.3", "react-color": "2.19.3",
"react-dom": "^17.0.2", "react-dom": "17.0.2",
"react-icons": "^4.3.1", "react-icons": "4.3.1",
"sharp": "^0.29.3", "sharp": "0.29.3",
"styled-components": "^5.3.3" "styled-components": "5.3.3"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "15.0.0", "@commitlint/cli": "15.0.0",
"@commitlint/config-conventional": "15.0.0", "@commitlint/config-conventional": "15.0.0",
"@types/bcryptjs": "^2.4.2", "@types/bcryptjs": "2.4.2",
"@types/jsonwebtoken": "^8.5.6", "@types/jsonwebtoken": "8.5.6",
"@types/lodash": "^4.14.178", "@types/lodash": "4.14.178",
"@types/node": "^17.0.0", "@types/node": "17.0.0",
"@types/react": "17.0.37", "@types/react": "17.0.37",
"@types/react-color": "^3.0.6", "@types/react-color": "3.0.6",
"@types/styled-components": "^5.1.18", "@types/styled-components": "5.1.18",
"babel-plugin-styled-components": "^2.0.2", "babel-plugin-styled-components": "2.0.2",
"eslint": "8.5.0", "eslint": "8.5.0",
"eslint-config-next": "12.0.7", "eslint-config-next": "12.0.7",
"eslint-config-prettier": "8.3.0", "eslint-config-prettier": "8.3.0",
"eslint-plugin-import": "2.25.3",
"eslint-plugin-prettier": "4.0.0", "eslint-plugin-prettier": "4.0.0",
"eslint-plugin-simple-import-sort": "7.0.0",
"husky": "7.0.4", "husky": "7.0.4",
"lint-staged": "12.1.3", "lint-staged": "12.1.3",
"prettier": "2.5.1", "prettier": "2.5.1",
"pretty-quick": "3.1.2", "pretty-quick": "3.1.2",
"prisma": "^3.6.0", "prisma": "3.6.0",
"react-is": "^17.0.2", "react-is": "17.0.2",
"ts-node": "^10.4.0", "ts-node": "10.4.0",
"typescript": "^4.5.4" "typescript": "4.5.4"
}, },
"prisma": { "prisma": {
"seed": "ts-node prisma/seed.ts" "seed": "ts-node prisma/seed.ts"

View File

@@ -16,7 +16,7 @@ async function main() {
name: 'John Doe', name: 'John Doe',
description: description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec euismod, nisl eget aliquam consectetur, nisl nunc aliquet nunc, euismod aliquam nunc nisl euismod.', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec euismod, nisl eget aliquam consectetur, nisl nunc aliquet nunc, euismod aliquam nunc nisl euismod.',
font: '"Roboto", sans-serif', font: 'oswald',
buttonBorderRadius: '4', buttonBorderRadius: '4',
colors: { colors: {
texts: '#e11d48', texts: '#e11d48',

View File

@@ -1,4 +1,5 @@
import { useData } from '../../hooks/useData' import { useData } from 'hooks/useData'
import { Wrapper } from './styles' import { Wrapper } from './styles'
export function Avatar() { export function Avatar() {

View File

@@ -6,7 +6,6 @@ type ButtonProps = {
backgroundColor?: string backgroundColor?: string
borderColor?: string borderColor?: string
borderRadius?: string borderRadius?: string
font?: string
size?: 'small' | 'medium' size?: 'small' | 'medium'
} }
@@ -15,7 +14,6 @@ export const Button = styled.button.attrs((props: ButtonProps) => ({
backgroundColor: props.backgroundColor || '#e11d48', backgroundColor: props.backgroundColor || '#e11d48',
borderColor: props.borderColor || '#e11d48', borderColor: props.borderColor || '#e11d48',
borderRadius: props.borderRadius || 8, borderRadius: props.borderRadius || 8,
font: props.font || 'inherit',
size: props.size || 'medium' size: props.size || 'medium'
}))<ButtonProps>` }))<ButtonProps>`
display: flex; display: flex;
@@ -23,7 +21,6 @@ export const Button = styled.button.attrs((props: ButtonProps) => ({
justify-content: center; justify-content: center;
width: 100%; width: 100%;
padding: 0 1rem; padding: 0 1rem;
font-family: ${({ font }) => font};
color: ${({ labelColor }) => labelColor}; color: ${({ labelColor }) => labelColor};
background: ${({ backgroundColor }) => backgroundColor}; background: ${({ backgroundColor }) => backgroundColor};
border-radius: ${({ borderRadius }) => borderRadius}px; border-radius: ${({ borderRadius }) => borderRadius}px;

View File

@@ -1,7 +1,7 @@
import { BlockPicker } from 'react-color' import { BlockPicker } from 'react-color'
import { useData } from '../../../hooks/useData' import { colors } from 'constants/colors'
import { colors } from '../../../styles/colors' import { useData } from 'hooks/useData'
type ColorPickerProps = { type ColorPickerProps = {
prop: prop:

View File

@@ -1,4 +1,4 @@
import { ColorPicker } from '../ColorPicker' import { ColorPicker } from 'components/Dash/ColorPicker'
export function ColorsSettings() { export function ColorsSettings() {
return ( return (

View File

@@ -2,10 +2,10 @@ import 'rc-slider/assets/index.css'
import Slider from 'rc-slider' import Slider from 'rc-slider'
import { useData } from '../../../hooks/useData' import { useData } from 'hooks/useData'
import { DescriptionInput } from '../DescriptionInput' import { DescriptionInput } from 'components/Dash/DescriptionInput'
import { FontsSelect } from '../FontsSelect' import { FontsSelect } from 'components/Dash/FontsSelect'
import { NameInput } from '../NameInput' import { NameInput } from 'components/Dash/NameInput'
export function DataSettings() { export function DataSettings() {
const { data, setData } = useData() const { data, setData } = useData()

View File

@@ -1,4 +1,4 @@
import { useData } from '../../../hooks/useData' import { useData } from 'hooks/useData'
export function DescriptionInput() { export function DescriptionInput() {
const { data, setData } = useData() const { data, setData } = useData()

View File

@@ -1,4 +1,6 @@
import { useData } from '../../../hooks/useData' import { useData } from 'hooks/useData'
import type { Fonts } from 'types/Fonts'
export function FontsSelect() { export function FontsSelect() {
const { data, setData } = useData() const { data, setData } = useData()
@@ -11,14 +13,18 @@ export function FontsSelect() {
...data, ...data,
settings: { settings: {
...data.settings, ...data.settings,
font: e.target.value font: e.target.value as Fonts
} }
}) })
} }
> >
<option value="'Baloo Bhaijaan 2', sans-serif">Baloo</option> <option value="inconsolata">Inconsolata</option>
<option value="'Montserrat', sans-serif">Montserrat</option> <option value="oswald">Oswald</option>
<option value="'Roboto', sans-serif">Roboto</option> <option value="poppins">Poppins</option>
<option value="quicksand">Quicksand</option>
<option value="roboto">Roboto</option>
<option value="robotoSlab">Roboto Slab</option>
<option value="ubuntu">Ubuntu</option>
</select> </select>
) )
} }

View File

@@ -1,4 +1,4 @@
import { useData } from '../../../hooks/useData' import { useData } from 'hooks/useData'
export function NameInput() { export function NameInput() {
const { data, setData } = useData() const { data, setData } = useData()

View File

@@ -1,13 +1,15 @@
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import type { Dispatch, SetStateAction } from 'react'
import { useData } from '../../../hooks/useData' import { useData } from 'hooks/useData'
import { api } from '../../../services/api' import { api } from 'services/api'
import type { Data } from '../../../types/Data' import { removeLocalStorageData } from 'utils/localStorage'
import { removeLocalStorageData } from '../../../utils/localStorage' import { Button } from 'components/Button'
import { Button } from '../../Button'
import { ButtonsGroup, Wrapper } from './styles' import { ButtonsGroup, Wrapper } from './styles'
import type { Data } from '../../../types/Data'
import type { Dispatch, SetStateAction } from 'react'
type SaveChangesAlertProps = { type SaveChangesAlertProps = {
hasUnsavedChanges: boolean hasUnsavedChanges: boolean
setHasUnsavedChanges: Dispatch<SetStateAction<boolean>> setHasUnsavedChanges: Dispatch<SetStateAction<boolean>>

View File

@@ -2,16 +2,18 @@ import { isEqual } from 'lodash'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import Collapsible from 'react-collapsible' import Collapsible from 'react-collapsible'
import { useAuth } from '../../hooks/useAuth' import { useAuth } from 'hooks/useAuth'
import { useData } from '../../hooks/useData' import { useData } from 'hooks/useData'
import type { Data } from '../../types/Data' import { getLocalStorageData, setLocalStorageData } from 'utils/localStorage'
import { getLocalStorageData, setLocalStorageData } from '../../utils/localStorage' import { Home } from 'components/Home'
import { Home } from '../Home' import { ColorsSettings } from 'components/Dash/ColorsSettings'
import { ColorsSettings } from './ColorsSettings' import { DataSettings } from 'components/Dash/DataSettings'
import { DataSettings } from './DataSettings' import { SaveChangesAlert } from 'components/Dash/SaveChangesAlert'
import { SaveChangesAlert } from './SaveChangesAlert'
import { Content, Preview, Wrapper } from './styles' import { Content, Preview, Wrapper } from './styles'
import type { Data } from 'types/Data'
type DashProps = { type DashProps = {
initialData: Data initialData: Data
} }

View File

@@ -1,7 +1,9 @@
import { useData } from '../../hooks/useData' import { fonts } from 'constants/fonts'
import { Avatar } from '../Avatar' import { useData } from 'hooks/useData'
import { Button } from '../Button' import { Button } from 'components/Button'
import { SocialLinks } from '../SocialLinks' import { Avatar } from 'components/Avatar'
import { SocialLinks } from 'components/SocialLinks'
import { Content, Description, Name, Wrapper } from './styles' import { Content, Description, Name, Wrapper } from './styles'
export const Home = () => { export const Home = () => {
@@ -9,7 +11,7 @@ export const Home = () => {
const { colors, buttonBorderRadius, font, name, description } = data.settings const { colors, buttonBorderRadius, font, name, description } = data.settings
return ( return (
<Wrapper color={colors.texts} font={font}> <Wrapper color={colors.texts} font={fonts[font].name}>
<Content> <Content>
<Avatar /> <Avatar />
<Name>{name}</Name> <Name>{name}</Name>

View File

@@ -0,0 +1,25 @@
import Head from 'next/head'
import { fonts } from 'constants/fonts'
import { useData } from 'hooks/useData'
import { Global } from 'styles/global'
import type { ReactNode } from 'react'
type LayoutProps = {
children: ReactNode
}
export function Layout({ children }: LayoutProps) {
const { data } = useData()
return (
<>
<Global data={data} />
<Head>
<link href={fonts[data.settings.font].url} rel="stylesheet" />
</Head>
{children}
</>
)
}

View File

@@ -5,12 +5,14 @@ import {
} from 'react-icons/ai' } from 'react-icons/ai'
import { BsEnvelope as Email } from 'react-icons/bs' import { BsEnvelope as Email } from 'react-icons/bs'
import { FaDev as Dev, FaLinkedinIn as LinkedIn } from 'react-icons/fa' import { FaDev as Dev, FaLinkedinIn as LinkedIn } from 'react-icons/fa'
import type { IconType } from 'react-icons/lib'
import { useData } from '../../hooks/useData' import { useData } from 'hooks/useData'
import { Link } from '../Link' import { Link } from 'components/Link'
import { SocialItem, Wrapper } from './styles' import { SocialItem, Wrapper } from './styles'
import type { IconType } from 'react-icons/lib'
const Icons = { const Icons = {
Email, Email,
GitHub, GitHub,

15
src/constants/auth.ts Normal file
View File

@@ -0,0 +1,15 @@
const JWT_EXPIRES_IN = 15 // minutes
const SESSION_EXPIRES_IN = 30 // days
const { JWT_SECRET } = process.env
const SESSION_EXPIRES_IN_S = SESSION_EXPIRES_IN * 24 * 60 * 60
const SESSION_EXPIRES_IN_MS = SESSION_EXPIRES_IN_S * 1000
if (!JWT_SECRET && !process.browser) throw new Error('JWT_SECRET is not defined')
export const authConstants = {
JWT_SECRET,
JWT_EXPIRES_IN,
SESSION_EXPIRES_IN_S,
SESSION_EXPIRES_IN_MS
}

30
src/constants/fonts.ts Normal file
View File

@@ -0,0 +1,30 @@
export const fonts = {
roboto: {
name: "'Roboto', sans-serif",
url: 'https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&display=swap'
},
robotoSlab: {
name: "'Roboto Slab', serif",
url: 'https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@400;500&display=swap'
},
oswald: {
name: "'Oswald', sans-serif",
url: 'https://fonts.googleapis.com/css2?family=Oswald:wght@400;500&display=swap'
},
poppins: {
name: "'Poppins', sans-serif",
url: 'https://fonts.googleapis.com/css2?family=Poppins:wght@400;500&display=swap'
},
ubuntu: {
name: "'Ubuntu', sans-serif",
url: 'https://fonts.googleapis.com/css2?family=Ubuntu:wght@400;500&display=swap'
},
quicksand: {
name: "'Quicksand', sans-serif",
url: 'https://fonts.googleapis.com/css2?family=Quicksand:wght@400;500&display=swap'
},
inconsolata: {
name: "'Inconsolata', monospace",
url: 'https://fonts.googleapis.com/css2?family=Inconsolata:wght@400;500&display=swap'
}
}

View File

@@ -1,17 +1,16 @@
import type { User } from '@prisma/client'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { parseCookies } from 'nookies' import { parseCookies } from 'nookies'
import type { ReactNode } from 'react' import { useEffect, createContext, useState } from 'react'
import { useEffect } from 'react'
import { createContext, useState } from 'react'
import { api } from '../services/api' import { api } from 'services/api'
import { destroyCookies } from '../utils/destroyCookies' import { destroyCookies, setCookies } from 'utils/cookies'
import { retrieveUser } from '../utils/retrieveUser' import { retrieveUser } from 'utils/retrieveUser'
import { setCookies } from '../utils/setCookies'
import type { ReactNode } from 'react'
import type { User } from 'types/User'
type AuthContextType = { type AuthContextType = {
user?: Omit<User, 'password'> user?: User
signIn: (username: string, password: string) => Promise<void> signIn: (username: string, password: string) => Promise<void>
signOut: () => void signOut: () => void
} }
@@ -23,7 +22,7 @@ type AuthProviderProps = {
export const AuthContext = createContext({} as AuthContextType) export const AuthContext = createContext({} as AuthContextType)
export const AuthProvider = ({ children }: AuthProviderProps) => { export const AuthProvider = ({ children }: AuthProviderProps) => {
const [user, setUser] = useState<Omit<User, 'password'>>() const [user, setUser] = useState<User>()
const { push } = useRouter() const { push } = useRouter()
useEffect(() => { useEffect(() => {

View File

@@ -1,7 +1,7 @@
import type { Dispatch, ReactNode, SetStateAction } from 'react'
import { createContext, useState } from 'react' import { createContext, useState } from 'react'
import type { Data } from '../types/Data' import type { Dispatch, ReactNode, SetStateAction } from 'react'
import type { Data } from 'types/Data'
type DataContextType = { type DataContextType = {
data: Data data: Data

View File

@@ -1,5 +1,5 @@
import { useContext } from 'react' import { useContext } from 'react'
import { AuthContext } from '../contexts/AuthContext' import { AuthContext } from 'contexts/AuthContext'
export const useAuth = () => useContext(AuthContext) export const useAuth = () => useContext(AuthContext)

View File

@@ -1,5 +1,5 @@
import { useContext } from 'react' import { useContext } from 'react'
import { DataContext } from '../contexts/DataContext' import { DataContext } from 'contexts/DataContext'
export const useData = () => useContext(DataContext) export const useData = () => useContext(DataContext)

View File

@@ -1,8 +1,8 @@
import type { AppProps } from 'next/app' import { Layout } from 'components/Layout'
import { AuthProvider } from 'contexts/AuthContext'
import { DataProvider } from 'contexts/DataContext'
import { AuthProvider } from '../contexts/AuthContext' import type { AppProps } from 'next/app'
import { DataProvider } from '../contexts/DataContext'
import { Layout } from '../styles/layout'
export default function App({ Component, pageProps }: AppProps) { export default function App({ Component, pageProps }: AppProps) {
return ( return (

View File

@@ -7,10 +7,6 @@ export default class Document extends NextDocument {
<Head> <Head>
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" />
<link
href="https://fonts.googleapis.com/css2?family=Baloo+Bhaijaan+2:wght@400;500&family=Montserrat:wght@400;500&family=Roboto:wght@400;500&display=swap"
rel="stylesheet"
/>
</Head> </Head>
<body> <body>
<Main /> <Main />

View File

@@ -1,35 +1,11 @@
import { Prisma } from '@prisma/client'
import { compare } from 'bcryptjs' import { compare } from 'bcryptjs'
import type { NextApiRequest, NextApiResponse } from 'next'
import nc from 'next-connect'
import { prisma } from '../../../services/prisma' import { prisma } from 'services/prisma'
import { createSession } from '../../../utils/createSession' import { createSession } from 'utils/createSession'
import { ExceptionError } from '../../../utils/error' import { ExceptionError } from 'utils/error'
import { nc } from 'utils/nc'
const handler = nc<NextApiRequest, NextApiResponse>({ const handler = nc.post(async (req, res) => {
onNoMatch: (_req, res) => {
res.status(404).json({ error: 'Not found' })
},
onError: (err, _req, res) => {
if (err instanceof ExceptionError) {
res.status(err.status).json({
status: err.status,
error: err.message
})
} else if (err instanceof Prisma.PrismaClientKnownRequestError) {
res.status(400).json({
status: 400,
error: err.message
})
} else {
res.status(500).json({
status: 500,
error: err.message
})
}
}
}).post(async (req, res) => {
const { username, password } = req.body const { username, password } = req.body
if (!username || !password) { if (!username || !password) {

View File

@@ -1,34 +1,9 @@
import { Prisma } from '@prisma/client' import { prisma } from 'services/prisma'
import type { NextApiRequest, NextApiResponse } from 'next' import { createSession } from 'utils/createSession'
import nc from 'next-connect' import { ExceptionError } from 'utils/error'
import { nc } from 'utils/nc'
import { prisma } from '../../../services/prisma' const handler = nc.post(async (req, res) => {
import { createSession } from '../../../utils/createSession'
import { ExceptionError } from '../../../utils/error'
const handler = nc<NextApiRequest, NextApiResponse>({
onNoMatch: (_req, res) => {
res.status(404).json({ error: 'Not found' })
},
onError: (err, _req, res) => {
if (err instanceof ExceptionError) {
res.status(err.status).json({
status: err.status,
error: err.message
})
} else if (err instanceof Prisma.PrismaClientKnownRequestError) {
res.status(400).json({
status: 400,
error: err.message
})
} else {
res.status(500).json({
status: 500,
error: err.message
})
}
}
}).post(async (req, res) => {
const { refreshToken } = req.body const { refreshToken } = req.body
if (!refreshToken) { if (!refreshToken) {

View File

@@ -1,34 +1,9 @@
import { Prisma } from '@prisma/client' import { prisma } from 'services/prisma'
import type { NextApiRequest, NextApiResponse } from 'next'
import nc from 'next-connect'
import { prisma } from '../../services/prisma'
// import { authMiddleware } from '../../utils/authMiddleware' // import { authMiddleware } from '../../utils/authMiddleware'
import { ExceptionError } from '../../utils/error' import { ExceptionError } from 'utils/error'
import { nc } from 'utils/nc'
const handler = nc<NextApiRequest, NextApiResponse>({ const handler = nc
onNoMatch: (_req, res) => {
res.status(404).json({ error: 'Not found' })
},
onError: (err, _req, res) => {
if (err instanceof ExceptionError) {
res.status(err.status).json({
status: err.status,
error: err.message
})
} else if (err instanceof Prisma.PrismaClientKnownRequestError) {
res.status(400).json({
status: 400,
error: err.message
})
} else {
res.status(500).json({
status: 500,
error: err.message
})
}
}
})
.get(async (_req, res) => { .get(async (_req, res) => {
const response = await prisma.data.findUnique({ const response = await prisma.data.findUnique({
where: { id: 1 } where: { id: 1 }

View File

@@ -1,39 +1,10 @@
import { Prisma } from '@prisma/client'
import { compare, hashSync } from 'bcryptjs' import { compare, hashSync } from 'bcryptjs'
import type { NextApiRequest, NextApiResponse } from 'next'
import nc from 'next-connect'
import { prisma } from '../../../services/prisma' import { nc } from 'utils/nc'
import { ExceptionError } from '../../../utils/error' import { prisma } from 'services/prisma'
import { ExceptionError } from 'utils/error'
interface Request extends NextApiRequest { const handler = nc
userId: string
userRole: string
}
const handler = nc<Request, NextApiResponse>({
onNoMatch: (_req, res) => {
res.status(404).json({ error: 'Not found' })
},
onError: (err, _req, res) => {
if (err instanceof ExceptionError) {
res.status(err.status).json({
status: err.status,
error: err.message
})
} else if (err instanceof Prisma.PrismaClientKnownRequestError) {
res.status(400).json({
status: 400,
error: err.message
})
} else {
res.status(500).json({
status: 500,
error: err.message
})
}
}
})
.get(async (req, res) => { .get(async (req, res) => {
const { id } = req.query const { id } = req.query

View File

@@ -1,40 +1,11 @@
import { Prisma } from '@prisma/client'
import { hashSync } from 'bcryptjs' import { hashSync } from 'bcryptjs'
import type { NextApiRequest, NextApiResponse } from 'next'
import nc from 'next-connect'
import { prisma } from '../../../services/prisma' import { prisma } from 'services/prisma'
import { authMiddleware } from '../../../utils/authMiddleware' import { authMiddleware } from 'utils/authMiddleware'
import { ExceptionError } from '../../../utils/error' import { ExceptionError } from 'utils/error'
import { nc } from 'utils/nc'
interface Request extends NextApiRequest { const handler = nc
userId: string
userRole: string
}
const handler = nc<Request, NextApiResponse>({
onNoMatch: (_req, res) => {
res.status(404).json({ error: 'Not found' })
},
onError: (err, _req, res) => {
if (err instanceof ExceptionError) {
res.status(err.status).json({
status: err.status,
error: err.message
})
} else if (err instanceof Prisma.PrismaClientKnownRequestError) {
res.status(400).json({
status: 400,
error: err.message
})
} else {
res.status(500).json({
status: 500,
error: err.message
})
}
}
})
.use(authMiddleware) .use(authMiddleware)
.get(async (_req, res) => { .get(async (_req, res) => {
const response = await prisma.user.findMany({ const response = await prisma.user.findMany({

View File

@@ -1,56 +1,24 @@
import { Prisma } from '@prisma/client' import { prisma } from 'services/prisma'
import type { NextApiRequest, NextApiResponse } from 'next' import { authMiddleware } from 'utils/authMiddleware'
import nc from 'next-connect' import { ExceptionError } from 'utils/error'
import { nc } from 'utils/nc'
import { prisma } from '../../../services/prisma' const handler = nc.use(authMiddleware).get(async (req, res) => {
import { authMiddleware } from '../../../utils/authMiddleware' const { userId } = req
import { ExceptionError } from '../../../utils/error' const response = await prisma.user.findUnique({
where: { id: +userId },
interface Request extends NextApiRequest { select: {
userId: string id: true,
userRole: string username: true,
} role: true
const handler = nc<Request, NextApiResponse>({
onNoMatch: (_req, res) => {
res.status(404).json({ error: 'Not found' })
},
onError: (err, _req, res) => {
if (err instanceof ExceptionError) {
res.status(err.status).json({
status: err.status,
error: err.message
})
} else if (err instanceof Prisma.PrismaClientKnownRequestError) {
res.status(400).json({
status: 400,
error: err.message
})
} else {
res.status(500).json({
status: 500,
error: err.message
})
} }
}
})
.use(authMiddleware)
.get(async (req, res) => {
const { userId } = req
const response = await prisma.user.findUnique({
where: { id: +userId },
select: {
id: true,
username: true,
role: true
}
})
if (!response) {
throw new ExceptionError('User not found')
}
res.status(200).json(response)
}) })
if (!response) {
throw new ExceptionError('User not found')
}
res.status(200).json(response)
})
export default handler export default handler

View File

@@ -1,8 +1,9 @@
import type { GetServerSideProps } from 'next'
import { useState } from 'react' import { useState } from 'react'
import { useAuth } from '../hooks/useAuth' import { useAuth } from 'hooks/useAuth'
import { fetchData } from '../services/fetchData' import { fetchData } from 'services/fetchData'
import type { GetStaticProps } from 'next'
export default function AuthPage() { export default function AuthPage() {
const { signIn } = useAuth() const { signIn } = useAuth()
@@ -35,10 +36,7 @@ export default function AuthPage() {
) )
} }
export const getServerSideProps: GetServerSideProps = async () => { export const getStaticProps: GetStaticProps = async () => {
const initialData = await fetchData() const initialData = await fetchData()
return { props: { initialData }, revalidate: 1 }
return {
props: { initialData }
}
} }

View File

@@ -1,8 +1,8 @@
import type { GetServerSideProps } from 'next' import { Dash } from 'components/Dash'
import { fetchData } from 'services/fetchData'
import { Dash } from '../components/Dash' import type { GetServerSideProps } from 'next'
import { fetchData } from '../services/fetchData' import type { Data } from 'types/Data'
import type { Data } from '../types/Data'
type DashPageProps = { type DashPageProps = {
initialData: Data initialData: Data
@@ -14,8 +14,5 @@ export default function DashPage({ initialData }: DashPageProps) {
export const getServerSideProps: GetServerSideProps = async () => { export const getServerSideProps: GetServerSideProps = async () => {
const initialData = await fetchData() const initialData = await fetchData()
return { props: { initialData } }
return {
props: { initialData }
}
} }

View File

@@ -1,7 +1,7 @@
import type { GetStaticProps } from 'next' import { Home } from 'components/Home'
import { fetchData } from 'services/fetchData'
import { Home } from '../components/Home' import type { GetStaticProps } from 'next'
import { fetchData } from '../services/fetchData'
export default function HomePage() { export default function HomePage() {
return <Home /> return <Home />
@@ -9,9 +9,5 @@ export default function HomePage() {
export const getStaticProps: GetStaticProps = async () => { export const getStaticProps: GetStaticProps = async () => {
const initialData = await fetchData() const initialData = await fetchData()
return { props: { initialData }, revalidate: 1 }
return {
props: { initialData },
revalidate: 1
}
} }

View File

@@ -3,8 +3,7 @@ import { GetServerSidePropsContext } from 'next'
import router from 'next/router' import router from 'next/router'
import { parseCookies } from 'nookies' import { parseCookies } from 'nookies'
import { destroyCookies } from '../utils/destroyCookies' import { destroyCookies, setCookies } from 'utils/cookies'
import { setCookies } from '../utils/setCookies'
let isRefreshing = false let isRefreshing = false
let failedRequestsQueued: any[] = [] let failedRequestsQueued: any[] = []

View File

@@ -1,5 +1,6 @@
import type { Data } from '../types/Data' import { prisma } from 'services/prisma'
import { prisma } from './prisma'
import type { Data } from 'types/Data'
export async function fetchData(): Promise<Data> { export async function fetchData(): Promise<Data> {
const response = await prisma.data.findUnique({ const response = await prisma.data.findUnique({

22
src/styles/global.ts Normal file
View File

@@ -0,0 +1,22 @@
import { createGlobalStyle } from 'styled-components'
import type { Data } from 'types/Data'
type GlobalStyleProps = {
data: Data
}
export const Global = createGlobalStyle<GlobalStyleProps>`
* {
margin: 0;
padding: 0;
box-sizing: border-box;
transition: all 0.25s ease;
}
body {
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
color: #0f172a;
background: ${({ data }) => data.settings.colors.background};
}
`

View File

@@ -1,39 +0,0 @@
import { ReactNode } from 'react'
import { createGlobalStyle } from 'styled-components'
import { useData } from '../hooks/useData'
import { Data } from '../types/Data'
type GlobalStyleProps = {
data: Data
}
type LayoutProps = {
children: ReactNode
}
const GlobalStyles = createGlobalStyle<GlobalStyleProps>`
* {
margin: 0;
padding: 0;
box-sizing: border-box;
transition: all 0.25s ease;
}
body {
font-family: "Roboto", sans-serif;
color: #0f172a;
background: ${({ data }) => data.settings.colors.background};
}
`
export function Layout({ children }: LayoutProps) {
const { data } = useData()
return (
<>
<GlobalStyles data={data} />
{children}
</>
)
}

View File

@@ -1,9 +1,11 @@
import type { Fonts } from './Fonts'
export type Data = { export type Data = {
settings: { settings: {
avatar: string avatar: string
name: string name: string
description: string description: string
font: string font: Fonts
buttonBorderRadius: string buttonBorderRadius: string
colors: { colors: {
texts: string texts: string

2
src/types/Fonts.ts Normal file
View File

@@ -0,0 +1,2 @@
import { fonts } from 'constants/fonts'
export type Fonts = keyof typeof fonts

2
src/types/User.ts Normal file
View File

@@ -0,0 +1,2 @@
import { User as UserModel } from '@prisma/client'
export type User = Omit<UserModel, 'password'>

8
src/types/next.d.ts vendored Normal file
View File

@@ -0,0 +1,8 @@
import { IncomingMessage } from 'http'
declare module 'next' {
export interface NextApiRequest extends IncomingMessage {
userId: string
userRole: string
}
}

View File

@@ -1,19 +1,17 @@
import jwt from 'jsonwebtoken' import jwt from 'jsonwebtoken'
import { authConstants } from 'constants/auth'
import { ExceptionError } from 'utils/error'
import type { NextApiRequest, NextApiResponse } from 'next' import type { NextApiRequest, NextApiResponse } from 'next'
import { ExceptionError } from './error'
interface Request extends NextApiRequest {
userId: string
userRole: string
}
type Token = { type Token = {
sub: string sub: string
role: string role: string
} }
export async function authMiddleware(req: Request, _res: NextApiResponse, next: () => void) { export async function authMiddleware(req: NextApiRequest, _res: NextApiResponse, next: () => void) {
const { JWT_SECRET } = authConstants
const token = req.headers['authorization'] const token = req.headers['authorization']
if (!token) { if (!token) {
@@ -22,13 +20,7 @@ export async function authMiddleware(req: Request, _res: NextApiResponse, next:
const [, tokenValue] = token.split(' ') const [, tokenValue] = token.split(' ')
const { JWT_SECRET } = process.env const isValidToken = jwt.verify(tokenValue, JWT_SECRET!) as Token
if (!JWT_SECRET) {
throw new ExceptionError('JWT_SECRET is not defined')
}
const isValidToken = jwt.verify(tokenValue, JWT_SECRET) as Token
if (!isValidToken) { if (!isValidToken) {
throw new ExceptionError('Invalid token', 401) throw new ExceptionError('Invalid token', 401)

38
src/utils/cookies.ts Normal file
View File

@@ -0,0 +1,38 @@
import { destroyCookie, setCookie } from 'nookies'
import { authConstants } from 'constants/auth'
import { api } from 'services/api'
import type { GetServerSidePropsContext } from 'next'
type SetCookiesProps = {
ctx?: GetServerSidePropsContext
accessToken: string
refreshToken: string
}
export function setCookies({ ctx = undefined, accessToken, refreshToken }: SetCookiesProps) {
const { SESSION_EXPIRES_IN_S } = authConstants
// @ts-ignore
api.defaults.headers['authorization'] = `Bearer ${accessToken}`
setCookie(ctx, 'accessToken', accessToken, {
maxAge: SESSION_EXPIRES_IN_S,
path: '/'
})
setCookie(ctx, 'refreshToken', refreshToken, {
maxAge: SESSION_EXPIRES_IN_S,
path: '/'
})
}
export function destroyCookies(ctx: GetServerSidePropsContext | undefined = undefined) {
destroyCookie(ctx, 'accessToken', {
path: '/'
})
destroyCookie(ctx, 'refreshToken', {
path: '/'
})
}

View File

@@ -1,30 +1,25 @@
import type { User } from '@prisma/client'
import jwt from 'jsonwebtoken' import jwt from 'jsonwebtoken'
import { prisma } from '../services/prisma' import { authConstants } from 'constants/auth'
import { ExceptionError } from './error' import { prisma } from 'services/prisma'
import { ExceptionError } from 'utils/error'
const EXPIRES_IN = 30 // days import type { User } from '@prisma/client'
const EXPIRES_IN_MS = EXPIRES_IN * 24 * 60 * 60 * 1000
export async function createSession(user: User) { export async function createSession(user: User) {
const { JWT_SECRET } = process.env const { SESSION_EXPIRES_IN_MS, JWT_EXPIRES_IN, JWT_SECRET } = authConstants
if (!JWT_SECRET) {
throw new ExceptionError('JWT_SECRET is not defined')
}
try { try {
const session = await prisma.session.create({ const session = await prisma.session.create({
data: { data: {
userId: user.id, userId: user.id,
expiresAt: new Date(Date.now() + EXPIRES_IN_MS) expiresAt: new Date(Date.now() + SESSION_EXPIRES_IN_MS)
} }
}) })
const payload = { role: user.role, sub: user.id } const payload = { role: user.role, sub: user.id }
const accessToken = jwt.sign(payload, JWT_SECRET, { const accessToken = jwt.sign(payload, JWT_SECRET!, {
expiresIn: '15m' expiresIn: `${JWT_EXPIRES_IN}m`
}) })
return { accessToken, refreshToken: session.id } return { accessToken, refreshToken: session.id }

View File

@@ -1,12 +0,0 @@
import { GetServerSidePropsContext } from 'next'
import { destroyCookie } from 'nookies'
export function destroyCookies(ctx: GetServerSidePropsContext | undefined = undefined) {
destroyCookie(ctx, 'accessToken', {
path: '/'
})
destroyCookie(ctx, 'refreshToken', {
path: '/'
})
}

View File

@@ -1,4 +1,4 @@
import type { Data } from '../types/Data' import type { Data } from 'types/Data'
const KEY = 'link-free-data' const KEY = 'link-free-data'
@@ -8,9 +8,9 @@ export function getLocalStorageData(): Data | null {
} }
export function setLocalStorageData(data = {}) { export function setLocalStorageData(data = {}) {
localStorage.setItem(KEY, JSON.stringify(data)) process.browser && localStorage.setItem(KEY, JSON.stringify(data))
} }
export function removeLocalStorageData() { export function removeLocalStorageData() {
localStorage.removeItem(KEY) process.browser && localStorage.removeItem(KEY)
} }

30
src/utils/nc.ts Normal file
View File

@@ -0,0 +1,30 @@
import nextConnect from 'next-connect'
import { Prisma } from '@prisma/client'
import { ExceptionError } from 'utils/error'
import type { NextApiRequest, NextApiResponse } from 'next'
export const nc = nextConnect<NextApiRequest, NextApiResponse>({
onNoMatch: (_req, res) => {
res.status(404).json({ error: 'Not found' })
},
onError: (err, _req, res) => {
if (err instanceof ExceptionError) {
res.status(err.status).json({
status: err.status,
error: err.message
})
} else if (err instanceof Prisma.PrismaClientKnownRequestError) {
res.status(400).json({
status: 400,
error: err.message
})
} else {
res.status(500).json({
status: 500,
error: err.message
})
}
}
})

View File

@@ -1,10 +1,10 @@
import type { User } from '@prisma/client' import { api } from 'services/api'
import { api } from '../services/api' import type { User } from 'types/User'
export async function retrieveUser() { export async function retrieveUser() {
try { try {
const { data } = await api.get<Omit<User, 'password'>>('users/me') const { data } = await api.get<User>('users/me')
return data return data
} catch (error) { } catch (error) {
console.log(error) console.log(error)

View File

@@ -1,25 +0,0 @@
import { GetServerSidePropsContext } from 'next'
import { setCookie } from 'nookies'
import { api } from '../services/api'
type SetCookiesProps = {
ctx?: GetServerSidePropsContext
accessToken: string
refreshToken: string
}
export function setCookies({ ctx = undefined, accessToken, refreshToken }: SetCookiesProps) {
// @ts-ignore
api.defaults.headers['authorization'] = `Bearer ${accessToken}`
setCookie(ctx, 'accessToken', accessToken, {
maxAge: 60 * 60 * 24 * 30, // 30 days
path: '/'
})
setCookie(ctx, 'refreshToken', refreshToken, {
maxAge: 60 * 60 * 24 * 30, // 30 days
path: '/'
})
}

View File

@@ -1,5 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"baseUrl": "./src",
"target": "es5", "target": "es5",
"lib": ["dom", "dom.iterable", "esnext"], "lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true, "allowJs": true,

View File

@@ -535,7 +535,7 @@
"@nodelib/fs.scandir" "2.1.5" "@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0" fastq "^1.6.0"
"@prisma/client@^3.6.0": "@prisma/client@3.6.0":
version "3.6.0" version "3.6.0"
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-3.6.0.tgz#68a60cd4c73a369b11f72e173e86fd6789939293" resolved "https://registry.yarnpkg.com/@prisma/client/-/client-3.6.0.tgz#68a60cd4c73a369b11f72e173e86fd6789939293"
integrity sha512-ycSGY9EZGROtje0iCNsgC5Zqi/ttX2sO7BNMYaLsUMiTlf3F69ZPH+08pRo0hrDfkZzyimXYqeXJlaoYDH1w7A== integrity sha512-ycSGY9EZGROtje0iCNsgC5Zqi/ttX2sO7BNMYaLsUMiTlf3F69ZPH+08pRo0hrDfkZzyimXYqeXJlaoYDH1w7A==
@@ -577,7 +577,7 @@
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e"
integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==
"@types/bcryptjs@^2.4.2": "@types/bcryptjs@2.4.2":
version "2.4.2" version "2.4.2"
resolved "https://registry.yarnpkg.com/@types/bcryptjs/-/bcryptjs-2.4.2.tgz#e3530eac9dd136bfdfb0e43df2c4c5ce1f77dfae" resolved "https://registry.yarnpkg.com/@types/bcryptjs/-/bcryptjs-2.4.2.tgz#e3530eac9dd136bfdfb0e43df2c4c5ce1f77dfae"
integrity sha512-LiMQ6EOPob/4yUL66SZzu6Yh77cbzJFYll+ZfaPiPPFswtIlA/Fs1MzdKYA7JApHU49zQTbJGX3PDmCpIdDBRQ== integrity sha512-LiMQ6EOPob/4yUL66SZzu6Yh77cbzJFYll+ZfaPiPPFswtIlA/Fs1MzdKYA7JApHU49zQTbJGX3PDmCpIdDBRQ==
@@ -595,14 +595,14 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
"@types/jsonwebtoken@^8.5.6": "@types/jsonwebtoken@8.5.6":
version "8.5.6" version "8.5.6"
resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.6.tgz#1913e5a61e70a192c5a444623da4901a7b1a9d42" resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.6.tgz#1913e5a61e70a192c5a444623da4901a7b1a9d42"
integrity sha512-+P3O/xC7nzVizIi5VbF34YtqSonFsdnbXBnWUCYRiKOi1f9gA4sEFvXkrGr/QVV23IbMYvcoerI7nnhDUiWXRQ== integrity sha512-+P3O/xC7nzVizIi5VbF34YtqSonFsdnbXBnWUCYRiKOi1f9gA4sEFvXkrGr/QVV23IbMYvcoerI7nnhDUiWXRQ==
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/lodash@^4.14.178": "@types/lodash@4.14.178":
version "4.14.178" version "4.14.178"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8"
integrity sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw== integrity sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==
@@ -622,7 +622,7 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.12.tgz#ac7fb693ac587ee182c3780c26eb65546a1a3c10" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.12.tgz#ac7fb693ac587ee182c3780c26eb65546a1a3c10"
integrity sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw== integrity sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==
"@types/node@^17.0.0": "@types/node@17.0.0":
version "17.0.0" version "17.0.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.0.tgz#62797cee3b8b497f6547503b2312254d4fe3c2bb" resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.0.tgz#62797cee3b8b497f6547503b2312254d4fe3c2bb"
integrity sha512-eMhwJXc931Ihh4tkU+Y7GiLzT/y/DBNpNtr4yU9O2w3SYBsr9NaOPhQlLKRmoWtI54uNwuo0IOUFQjVOTZYRvw== integrity sha512-eMhwJXc931Ihh4tkU+Y7GiLzT/y/DBNpNtr4yU9O2w3SYBsr9NaOPhQlLKRmoWtI54uNwuo0IOUFQjVOTZYRvw==
@@ -642,7 +642,7 @@
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==
"@types/react-color@^3.0.6": "@types/react-color@3.0.6":
version "3.0.6" version "3.0.6"
resolved "https://registry.yarnpkg.com/@types/react-color/-/react-color-3.0.6.tgz#602fed023802b2424e7cd6ff3594ccd3d5055f9a" resolved "https://registry.yarnpkg.com/@types/react-color/-/react-color-3.0.6.tgz#602fed023802b2424e7cd6ff3594ccd3d5055f9a"
integrity sha512-OzPIO5AyRmLA7PlOyISlgabpYUa3En74LP8mTMa0veCA719SvYQov4WLMsHvCgXP+L+KI9yGhYnqZafVGG0P4w== integrity sha512-OzPIO5AyRmLA7PlOyISlgabpYUa3En74LP8mTMa0veCA719SvYQov4WLMsHvCgXP+L+KI9yGhYnqZafVGG0P4w==
@@ -671,7 +671,7 @@
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
"@types/styled-components@^5.1.18": "@types/styled-components@5.1.18":
version "5.1.18" version "5.1.18"
resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.1.18.tgz#1c361130f76a52f1cb4851c2a32aa328267e5b78" resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.1.18.tgz#1c361130f76a52f1cb4851c2a32aa328267e5b78"
integrity sha512-xPTYmWP7Mxk5TAD3pYsqjwA9G5fAI8e/S51QUJEl7EQD1siKCdiYXIWiH2lzoHRl+QqbQCJMcGv3YTF3OmyPdQ== integrity sha512-xPTYmWP7Mxk5TAD3pYsqjwA9G5fAI8e/S51QUJEl7EQD1siKCdiYXIWiH2lzoHRl+QqbQCJMcGv3YTF3OmyPdQ==
@@ -954,7 +954,7 @@ axe-core@^4.3.5:
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.3.5.tgz#78d6911ba317a8262bfee292aeafcc1e04b49cc5" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.3.5.tgz#78d6911ba317a8262bfee292aeafcc1e04b49cc5"
integrity sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA== integrity sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA==
axios@^0.24.0: axios@0.24.0:
version "0.24.0" version "0.24.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6" resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6"
integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA== integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==
@@ -966,7 +966,7 @@ axobject-query@^2.2.0:
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==
"babel-plugin-styled-components@>= 1.12.0", babel-plugin-styled-components@^2.0.2: babel-plugin-styled-components@2.0.2, "babel-plugin-styled-components@>= 1.12.0":
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.2.tgz#0fac11402dc9db73698b55847ab1dc73f5197c54" resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.2.tgz#0fac11402dc9db73698b55847ab1dc73f5197c54"
integrity sha512-7eG5NE8rChnNTDxa6LQfynwgHTVOYYaHJbUYSlOhk8QBXIQiMBKq4gyfHBBKPrxUcVBXVJL61ihduCpCQbuNbw== integrity sha512-7eG5NE8rChnNTDxa6LQfynwgHTVOYYaHJbUYSlOhk8QBXIQiMBKq4gyfHBBKPrxUcVBXVJL61ihduCpCQbuNbw==
@@ -991,7 +991,7 @@ base64-js@^1.0.2, base64-js@^1.3.1:
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
bcryptjs@^2.4.3: bcryptjs@2.4.3:
version "2.4.3" version "2.4.3"
resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb" resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb"
integrity sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms= integrity sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=
@@ -1553,7 +1553,7 @@ csstype@^3.0.2:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5"
integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA== integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==
cuid@^2.1.8: cuid@2.1.8:
version "2.1.8" version "2.1.8"
resolved "https://registry.yarnpkg.com/cuid/-/cuid-2.1.8.tgz#cbb88f954171e0d5747606c0139fb65c5101eac0" resolved "https://registry.yarnpkg.com/cuid/-/cuid-2.1.8.tgz#cbb88f954171e0d5747606c0139fb65c5101eac0"
integrity sha512-xiEMER6E7TlTPnDxrM4eRiC6TRgjNX9xzEZ5U/Se2YJKr7Mq4pJn/2XEHjl3STcSh96GmkHPcBXLES8M29wyyg== integrity sha512-xiEMER6E7TlTPnDxrM4eRiC6TRgjNX9xzEZ5U/Se2YJKr7Mq4pJn/2XEHjl3STcSh96GmkHPcBXLES8M29wyyg==
@@ -1706,7 +1706,7 @@ dot-prop@^5.1.0:
dependencies: dependencies:
is-obj "^2.0.0" is-obj "^2.0.0"
dotenv@^10.0.0: dotenv@10.0.0:
version "10.0.0" version "10.0.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81"
integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==
@@ -1882,7 +1882,7 @@ eslint-module-utils@^2.7.1:
find-up "^2.1.0" find-up "^2.1.0"
pkg-dir "^2.0.0" pkg-dir "^2.0.0"
eslint-plugin-import@^2.25.2: eslint-plugin-import@2.25.3, eslint-plugin-import@^2.25.2:
version "2.25.3" version "2.25.3"
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.3.tgz#a554b5f66e08fb4f6dc99221866e57cfff824766" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.3.tgz#a554b5f66e08fb4f6dc99221866e57cfff824766"
integrity sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg== integrity sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg==
@@ -1951,11 +1951,6 @@ eslint-plugin-react@^7.27.0:
semver "^6.3.0" semver "^6.3.0"
string.prototype.matchall "^4.0.6" string.prototype.matchall "^4.0.6"
eslint-plugin-simple-import-sort@7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-7.0.0.tgz#a1dad262f46d2184a90095a60c66fef74727f0f8"
integrity sha512-U3vEDB5zhYPNfxT5TYR7u01dboFZp+HNpnGhkDB2g/2E4wZ/g1Q9Ton8UwCLfRV9yAKyYqDh62oHOamvkFxsvw==
eslint-scope@^7.1.0: eslint-scope@^7.1.0:
version "7.1.0" version "7.1.0"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.0.tgz#c1f6ea30ac583031f203d65c73e723b01298f153" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.0.tgz#c1f6ea30ac583031f203d65c73e723b01298f153"
@@ -2867,7 +2862,7 @@ jsonparse@^1.2.0:
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=
jsonwebtoken@^8.5.1: jsonwebtoken@8.5.1:
version "8.5.1" version "8.5.1"
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==
@@ -3062,7 +3057,7 @@ lodash.sortby@^4.7.0:
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
lodash@^4.0.1, lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21: lodash@4.17.21, lodash@^4.0.1, lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21:
version "4.17.21" version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -3267,7 +3262,7 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
next-connect@^0.11.0: next-connect@0.11.0:
version "0.11.0" version "0.11.0"
resolved "https://registry.yarnpkg.com/next-connect/-/next-connect-0.11.0.tgz#447c7b78937ff71f36c97d03f1623a6d0264ef49" resolved "https://registry.yarnpkg.com/next-connect/-/next-connect-0.11.0.tgz#447c7b78937ff71f36c97d03f1623a6d0264ef49"
integrity sha512-7VW5z9MWOpd8wnbST9dXgVd0c0V76LLLk5mBDYLSMtEC2dj3v3YF/Bl3t58cJrzm4SZ0e/s3yeD361F888u0yg== integrity sha512-7VW5z9MWOpd8wnbST9dXgVd0c0V76LLLk5mBDYLSMtEC2dj3v3YF/Bl3t58cJrzm4SZ0e/s3yeD361F888u0yg==
@@ -3370,7 +3365,7 @@ node-releases@^1.1.71:
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.77.tgz#50b0cfede855dd374e7585bf228ff34e57c1c32e" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.77.tgz#50b0cfede855dd374e7585bf228ff34e57c1c32e"
integrity sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ== integrity sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==
nookies@^2.5.2: nookies@2.5.2:
version "2.5.2" version "2.5.2"
resolved "https://registry.yarnpkg.com/nookies/-/nookies-2.5.2.tgz#cc55547efa982d013a21475bd0db0c02c1b35b27" resolved "https://registry.yarnpkg.com/nookies/-/nookies-2.5.2.tgz#cc55547efa982d013a21475bd0db0c02c1b35b27"
integrity sha512-x0TRSaosAEonNKyCrShoUaJ5rrT5KHRNZ5DwPCuizjgrnkpE5DRf3VL7AyyQin4htict92X1EQ7ejDbaHDVdYA== integrity sha512-x0TRSaosAEonNKyCrShoUaJ5rrT5KHRNZ5DwPCuizjgrnkpE5DRf3VL7AyyQin4htict92X1EQ7ejDbaHDVdYA==
@@ -3691,7 +3686,7 @@ platform@1.3.6:
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7" resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7"
integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg== integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==
polished@^4.1.3: polished@4.1.3:
version "4.1.3" version "4.1.3"
resolved "https://registry.yarnpkg.com/polished/-/polished-4.1.3.tgz#7a3abf2972364e7d97770b827eec9a9e64002cfc" resolved "https://registry.yarnpkg.com/polished/-/polished-4.1.3.tgz#7a3abf2972364e7d97770b827eec9a9e64002cfc"
integrity sha512-ocPAcVBUOryJEKe0z2KLd1l9EBa1r5mSwlKpExmrLzsnIzJo4axsoU9O2BjOTkDGDT4mZ0WFE5XKTlR3nLnZOA== integrity sha512-ocPAcVBUOryJEKe0z2KLd1l9EBa1r5mSwlKpExmrLzsnIzJo4axsoU9O2BjOTkDGDT4mZ0WFE5XKTlR3nLnZOA==
@@ -3760,7 +3755,7 @@ pretty-quick@3.1.2:
mri "^1.1.5" mri "^1.1.5"
multimatch "^4.0.0" multimatch "^4.0.0"
prisma@^3.6.0: prisma@3.6.0:
version "3.6.0" version "3.6.0"
resolved "https://registry.yarnpkg.com/prisma/-/prisma-3.6.0.tgz#99532abc02e045e58c6133a19771bdeb28cecdbe" resolved "https://registry.yarnpkg.com/prisma/-/prisma-3.6.0.tgz#99532abc02e045e58c6133a19771bdeb28cecdbe"
integrity sha512-6SqgHS/5Rq6HtHjsWsTxlj+ySamGyCLBUQfotc2lStOjPv52IQuDVpp58GieNqc9VnfuFyHUvTZw7aQB+G2fvQ== integrity sha512-6SqgHS/5Rq6HtHjsWsTxlj+ySamGyCLBUQfotc2lStOjPv52IQuDVpp58GieNqc9VnfuFyHUvTZw7aQB+G2fvQ==
@@ -3889,7 +3884,7 @@ rc-motion@^2.0.0:
classnames "^2.2.1" classnames "^2.2.1"
rc-util "^5.2.1" rc-util "^5.2.1"
rc-slider@^9.7.5: rc-slider@9.7.5:
version "9.7.5" version "9.7.5"
resolved "https://registry.yarnpkg.com/rc-slider/-/rc-slider-9.7.5.tgz#193141c68e99b1dc3b746daeb6bf852946f5b7f4" resolved "https://registry.yarnpkg.com/rc-slider/-/rc-slider-9.7.5.tgz#193141c68e99b1dc3b746daeb6bf852946f5b7f4"
integrity sha512-LV/MWcXFjco1epPbdw1JlLXlTgmWpB9/Y/P2yinf8Pg3wElHxA9uajN21lJiWtZjf5SCUekfSP6QMJfDo4t1hg== integrity sha512-LV/MWcXFjco1epPbdw1JlLXlTgmWpB9/Y/P2yinf8Pg3wElHxA9uajN21lJiWtZjf5SCUekfSP6QMJfDo4t1hg==
@@ -3938,12 +3933,12 @@ rc@^1.2.7:
minimist "^1.2.0" minimist "^1.2.0"
strip-json-comments "~2.0.1" strip-json-comments "~2.0.1"
react-collapsible@^2.8.4: react-collapsible@2.8.4:
version "2.8.4" version "2.8.4"
resolved "https://registry.yarnpkg.com/react-collapsible/-/react-collapsible-2.8.4.tgz#319ff7471138c4381ce0afa3ac308ccde7f4e09f" resolved "https://registry.yarnpkg.com/react-collapsible/-/react-collapsible-2.8.4.tgz#319ff7471138c4381ce0afa3ac308ccde7f4e09f"
integrity sha512-oG4yOk6AGKswe0OD/8t3/nf4Rgj4UhlZUUvqL5jop0/ez02B3dBDmNvs3sQz0PcTpJvt0ai8zF7Atd1SzN/UNw== integrity sha512-oG4yOk6AGKswe0OD/8t3/nf4Rgj4UhlZUUvqL5jop0/ez02B3dBDmNvs3sQz0PcTpJvt0ai8zF7Atd1SzN/UNw==
react-color@^2.19.3: react-color@2.19.3:
version "2.19.3" version "2.19.3"
resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.19.3.tgz#ec6c6b4568312a3c6a18420ab0472e146aa5683d" resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.19.3.tgz#ec6c6b4568312a3c6a18420ab0472e146aa5683d"
integrity sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA== integrity sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==
@@ -3956,7 +3951,7 @@ react-color@^2.19.3:
reactcss "^1.2.0" reactcss "^1.2.0"
tinycolor2 "^1.4.1" tinycolor2 "^1.4.1"
react-dom@^17.0.2: react-dom@17.0.2:
version "17.0.2" version "17.0.2"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
@@ -3965,12 +3960,12 @@ react-dom@^17.0.2:
object-assign "^4.1.1" object-assign "^4.1.1"
scheduler "^0.20.2" scheduler "^0.20.2"
react-icons@^4.3.1: react-icons@4.3.1:
version "4.3.1" version "4.3.1"
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.3.1.tgz#2fa92aebbbc71f43d2db2ed1aed07361124e91ca" resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.3.1.tgz#2fa92aebbbc71f43d2db2ed1aed07361124e91ca"
integrity sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ== integrity sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ==
react-is@17.0.2, react-is@^17.0.2: react-is@17.0.2:
version "17.0.2" version "17.0.2"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
@@ -3985,7 +3980,7 @@ react-refresh@0.8.3:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg== integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
react@^17.0.2: react@17.0.2:
version "17.0.2" version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
@@ -4247,7 +4242,7 @@ shallowequal@^1.1.0:
resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==
sharp@^0.29.3: sharp@0.29.3:
version "0.29.3" version "0.29.3"
resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.29.3.tgz#0da183d626094c974516a48fab9b3e4ba92eb5c2" resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.29.3.tgz#0da183d626094c974516a48fab9b3e4ba92eb5c2"
integrity sha512-fKWUuOw77E4nhpyzCCJR1ayrttHoFHBT2U/kR/qEMRhvPEcluG4BKj324+SCO1e84+knXHwhJ1HHJGnUt4ElGA== integrity sha512-fKWUuOw77E4nhpyzCCJR1ayrttHoFHBT2U/kR/qEMRhvPEcluG4BKj324+SCO1e84+knXHwhJ1HHJGnUt4ElGA==
@@ -4573,7 +4568,7 @@ strip-json-comments@~2.0.1:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
styled-components@^5.3.3: styled-components@5.3.3:
version "5.3.3" version "5.3.3"
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.3.3.tgz#312a3d9a549f4708f0fb0edc829eb34bde032743" resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.3.3.tgz#312a3d9a549f4708f0fb0edc829eb34bde032743"
integrity sha512-++4iHwBM7ZN+x6DtPPWkCI4vdtwumQ+inA/DdAsqYd4SVgUKJie5vXyzotA00ttcFdQkCng7zc6grwlfIfw+lw== integrity sha512-++4iHwBM7ZN+x6DtPPWkCI4vdtwumQ+inA/DdAsqYd4SVgUKJie5vXyzotA00ttcFdQkCng7zc6grwlfIfw+lw==
@@ -4730,7 +4725,7 @@ trouter@^3.1.0:
dependencies: dependencies:
regexparam "^1.3.0" regexparam "^1.3.0"
ts-node@^10.4.0: ts-node@10.4.0:
version "10.4.0" version "10.4.0"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7"
integrity sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A== integrity sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==
@@ -4841,16 +4836,16 @@ type-fest@^0.8.1:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
typescript@4.5.4:
version "4.5.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.4.tgz#a17d3a0263bf5c8723b9c52f43c5084edf13c2e8"
integrity sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==
typescript@^4.4.3: typescript@^4.4.3:
version "4.5.3" version "4.5.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.3.tgz#afaa858e68c7103317d89eb90c5d8906268d353c" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.3.tgz#afaa858e68c7103317d89eb90c5d8906268d353c"
integrity sha512-eVYaEHALSt+s9LbvgEv4Ef+Tdq7hBiIZgii12xXJnukryt3pMgJf6aKhoCZ3FWQsu6sydEnkg11fYXLzhLBjeQ== integrity sha512-eVYaEHALSt+s9LbvgEv4Ef+Tdq7hBiIZgii12xXJnukryt3pMgJf6aKhoCZ3FWQsu6sydEnkg11fYXLzhLBjeQ==
typescript@^4.5.4:
version "4.5.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.4.tgz#a17d3a0263bf5c8723b9c52f43c5084edf13c2e8"
integrity sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==
unbox-primitive@^1.0.1: unbox-primitive@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"