2
0

🦴 Add viewer backbone

This commit is contained in:
Baptiste Arnaud
2021-12-23 16:31:56 +01:00
parent 9a78a341d2
commit d369b4d941
24 changed files with 576 additions and 182 deletions

View File

@ -14,7 +14,7 @@ import { useEditor } from 'contexts/EditorContext'
import { useGraph } from 'contexts/GraphContext'
import { useTypebot } from 'contexts/TypebotContext'
import React, { useMemo, useState } from 'react'
import { parseTypebotToPublicTypebot } from 'services/typebots'
import { parseTypebotToPublicTypebot } from 'services/publicTypebot'
export const PreviewDrawer = () => {
const { typebot } = useTypebot()

View File

@ -1,9 +1,18 @@
import { Button } from '@chakra-ui/react'
import { useTypebot } from 'contexts/TypebotContext'
export const PublishButton = () => {
const { isPublishing, isPublished, publishTypebot } = useTypebot()
return (
<Button ml={2} colorScheme={'blue'}>
Publish
<Button
ml={2}
colorScheme="blue"
isLoading={isPublishing}
isDisabled={isPublished}
onClick={publishTypebot}
>
{isPublished ? 'Published' : 'Publish'}
</Button>
)
}

View File

@ -2,7 +2,7 @@ import { Flex } from '@chakra-ui/react'
import { TypebotViewer } from 'bot-engine'
import { useTypebot } from 'contexts/TypebotContext'
import React, { useMemo } from 'react'
import { parseTypebotToPublicTypebot } from 'services/typebots'
import { parseTypebotToPublicTypebot } from 'services/publicTypebot'
import { SideMenu } from './SideMenu'
export const ThemeContent = () => {

View File

@ -1,6 +1,7 @@
import { useToast } from '@chakra-ui/react'
import {
Block,
PublicTypebot,
Settings,
Step,
StepType,
@ -8,16 +9,25 @@ import {
Theme,
Typebot,
} from 'bot-engine'
import { deepEqual } from 'fast-equals'
import { useRouter } from 'next/router'
import {
createContext,
ReactNode,
useContext,
useEffect,
useMemo,
useState,
} from 'react'
import {
createPublishedTypebot,
parseTypebotToPublicTypebot,
updatePublishedTypebot,
} from 'services/publicTypebot'
import {
checkIfPublished,
checkIfTypebotsAreEqual,
parseDefaultPublicId,
parseNewBlock,
parseNewStep,
updateTypebot,
@ -25,6 +35,8 @@ import {
import {
fetcher,
insertItemInList,
isDefined,
omit,
preventUserFromRefreshing,
} from 'services/utils'
import useSWR from 'swr'
@ -32,6 +44,9 @@ import { NewBlockPayload, Coordinates } from './GraphContext'
const typebotContext = createContext<{
typebot?: Typebot
publishedTypebot?: PublicTypebot
isPublished: boolean
isPublishing: boolean
hasUnsavedChanges: boolean
isSavingLoading: boolean
save: () => void
@ -57,6 +72,7 @@ const typebotContext = createContext<{
updateTheme: (theme: Theme) => void
updateSettings: (settings: Settings) => void
updatePublicId: (publicId: string) => void
publishTypebot: () => void
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
}>({})
@ -74,7 +90,7 @@ export const TypebotContext = ({
status: 'error',
})
const [undoStack, setUndoStack] = useState<Typebot[]>([])
const { typebot, isLoading, mutate } = useFetchedTypebot({
const { typebot, publishedTypebot, isLoading, mutate } = useFetchedTypebot({
typebotId,
onError: (error) =>
toast({
@ -83,18 +99,33 @@ export const TypebotContext = ({
}),
})
const [localTypebot, setLocalTypebot] = useState<Typebot>()
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false)
const [localPublishedTypebot, setLocalPublishedTypebot] =
useState<PublicTypebot>()
const [isSavingLoading, setIsSavingLoading] = useState(false)
const [isPublishing, setIsPublishing] = useState(false)
const hasUnsavedChanges = useMemo(
() =>
isDefined(typebot) &&
isDefined(localTypebot) &&
!deepEqual(localTypebot, typebot),
[typebot, localTypebot]
)
const isPublished = useMemo(
() =>
isDefined(typebot) &&
isDefined(publishedTypebot) &&
checkIfPublished(typebot, publishedTypebot),
[typebot, publishedTypebot]
)
useEffect(() => {
if (!localTypebot || !typebot) return
if (!checkIfTypebotsAreEqual(localTypebot, typebot)) {
setHasUnsavedChanges(true)
pushNewTypebotInUndoStack(localTypebot)
window.removeEventListener('beforeunload', preventUserFromRefreshing)
window.addEventListener('beforeunload', preventUserFromRefreshing)
} else {
setHasUnsavedChanges(false)
window.removeEventListener('beforeunload', preventUserFromRefreshing)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
@ -108,6 +139,7 @@ export const TypebotContext = ({
return
}
setLocalTypebot({ ...typebot })
if (publishedTypebot) setLocalPublishedTypebot({ ...publishedTypebot })
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isLoading])
@ -128,7 +160,6 @@ export const TypebotContext = ({
setIsSavingLoading(false)
if (error) return toast({ title: error.name, description: error.message })
mutate({ typebot: localTypebot })
setHasUnsavedChanges(false)
window.removeEventListener('beforeunload', preventUserFromRefreshing)
}
@ -290,10 +321,34 @@ export const TypebotContext = ({
setLocalTypebot({ ...localTypebot, publicId })
}
const publishTypebot = async () => {
if (!localTypebot) return
if (!localPublishedTypebot)
updatePublicId(parseDefaultPublicId(localTypebot.name, localTypebot.id))
if (hasUnsavedChanges) await saveTypebot()
setIsPublishing(true)
if (localPublishedTypebot) {
const { error } = await updatePublishedTypebot(
localPublishedTypebot.id,
omit(parseTypebotToPublicTypebot(localTypebot), 'id')
)
setIsPublishing(false)
if (error) return toast({ title: error.name, description: error.message })
} else {
const { error } = await createPublishedTypebot(
omit(parseTypebotToPublicTypebot(localTypebot), 'id')
)
setIsPublishing(false)
if (error) return toast({ title: error.name, description: error.message })
}
mutate({ typebot: localTypebot })
}
return (
<typebotContext.Provider
value={{
typebot: localTypebot,
publishedTypebot: localPublishedTypebot,
updateStep,
addNewBlock,
addStepToBlock,
@ -308,6 +363,9 @@ export const TypebotContext = ({
updateTheme,
updateSettings,
updatePublicId,
publishTypebot,
isPublishing,
isPublished,
}}
>
{children}
@ -324,13 +382,14 @@ export const useFetchedTypebot = ({
typebotId?: string
onError: (error: Error) => void
}) => {
const { data, error, mutate } = useSWR<{ typebot: Typebot }, Error>(
typebotId ? `/api/typebots/${typebotId}` : null,
fetcher
)
const { data, error, mutate } = useSWR<
{ typebot: Typebot; publishedTypebot?: PublicTypebot },
Error
>(typebotId ? `/api/typebots/${typebotId}` : null, fetcher)
if (error) onError(error)
return {
typebot: data?.typebot,
publishedTypebot: data?.publishedTypebot,
isLoading: !error && !data,
mutate,
}

View File

@ -0,0 +1,30 @@
import prisma from 'libs/prisma'
import { NextApiRequest, NextApiResponse } from 'next'
import { getSession } from 'next-auth/react'
import { methodNotAllowed } from 'services/api/utils'
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const session = await getSession({ req })
if (!session?.user)
return res.status(401).json({ message: 'Not authenticated' })
try {
if (req.method === 'POST') {
const data = JSON.parse(req.body)
const typebot = await prisma.publicTypebot.create({
data: { ...data },
})
return res.send(typebot)
}
return methodNotAllowed(res)
} catch (err) {
console.error(err)
if (err instanceof Error) {
return res.status(500).send({ title: err.name, message: err.message })
}
return res.status(500).send({ message: 'An error occured', error: err })
}
}
export default handler

View File

@ -0,0 +1,24 @@
import prisma from 'libs/prisma'
import { NextApiRequest, NextApiResponse } from 'next'
import { getSession } from 'next-auth/react'
import { methodNotAllowed } from 'services/api/utils'
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const session = await getSession({ req })
if (!session?.user)
return res.status(401).json({ message: 'Not authenticated' })
const id = req.query.id.toString()
if (req.method === 'PUT') {
const data = JSON.parse(req.body)
const typebots = await prisma.publicTypebot.update({
where: { id },
data,
})
return res.send({ typebots })
}
return methodNotAllowed(res)
}
export default handler

View File

@ -13,8 +13,13 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method === 'GET') {
const typebot = await prisma.typebot.findUnique({
where: { id },
include: {
publishedTypebot: true,
},
})
return res.send({ typebot })
if (!typebot) return res.send({ typebot: null })
const { publishedTypebot, ...restOfTypebot } = typebot
return res.send({ typebot: restOfTypebot, publishedTypebot })
}
if (req.method === 'DELETE') {
const typebots = await prisma.typebot.delete({

View File

@ -0,0 +1,35 @@
import { PublicTypebot, Typebot } from 'bot-engine'
import { sendRequest } from './utils'
import shortId from 'short-uuid'
export const parseTypebotToPublicTypebot = (
typebot: Typebot
): PublicTypebot => ({
id: shortId.generate(),
blocks: typebot.blocks,
name: typebot.name,
startBlock: typebot.startBlock,
typebotId: typebot.id,
theme: typebot.theme,
settings: typebot.settings,
publicId: typebot.publicId,
})
export const createPublishedTypebot = async (
typebot: Omit<PublicTypebot, 'id'>
) =>
sendRequest({
url: `/api/publicTypebots`,
method: 'POST',
body: typebot,
})
export const updatePublishedTypebot = async (
id: string,
typebot: Omit<PublicTypebot, 'id'>
) =>
sendRequest({
url: `/api/publicTypebots/${id}`,
method: 'PUT',
body: typebot,
})

View File

@ -3,8 +3,8 @@ import {
StepType,
Block,
TextStep,
PublicTypebot,
TextInputStep,
PublicTypebot,
} from 'bot-engine'
import shortId from 'short-uuid'
import { Typebot } from 'bot-engine'
@ -154,18 +154,16 @@ export const checkIfTypebotsAreEqual = (
}
)
export const parseTypebotToPublicTypebot = (
typebot: Typebot
): PublicTypebot => ({
id: shortId.generate(),
blocks: typebot.blocks,
name: typebot.name,
startBlock: typebot.startBlock,
typebotId: typebot.id,
theme: typebot.theme,
settings: typebot.settings,
publicId: typebot.publicId,
})
export const checkIfPublished = (
typebot: Typebot,
publicTypebot: PublicTypebot
) =>
deepEqual(typebot.blocks, publicTypebot.blocks) &&
deepEqual(typebot.startBlock, publicTypebot.startBlock) &&
typebot.name === publicTypebot.name &&
typebot.publicId === publicTypebot.publicId &&
deepEqual(typebot.settings, publicTypebot.settings) &&
deepEqual(typebot.theme, publicTypebot.theme)
export const parseDefaultPublicId = (name: string, id: string) =>
toKebabCase(`${name}-${id?.slice(0, 5)}`)

View File

@ -71,3 +71,23 @@ export const toKebabCase = (value: string) => {
if (!matched) return ''
return matched.map((x) => x.toLowerCase()).join('-')
}
interface Omit {
// eslint-disable-next-line @typescript-eslint/ban-types
<T extends object, K extends [...(keyof T)[]]>(obj: T, ...keys: K): {
[K2 in Exclude<keyof T, K[number]>]: T[K2]
}
}
export const omit: Omit = (obj, ...keys) => {
const ret = {} as {
[K in keyof typeof obj]: typeof obj[K]
}
let key: keyof typeof obj
for (key in obj) {
if (!keys.includes(key)) {
ret[key] = obj[key]
}
}
return ret
}

View File

@ -0,0 +1,3 @@
body {
margin: 0;
}

View File

@ -0,0 +1,62 @@
import Head from 'next/head'
import React from 'react'
type SEOProps = any
export const SEO = ({
iconUrl,
thumbnailUrl,
title,
description,
url,
chatbotName,
}: SEOProps) => (
<Head>
<title>{title ?? chatbotName}</title>
<link
rel="icon"
type="image/png"
href={iconUrl ?? 'https://bot.typebot.io/favicon.png'}
/>
<meta name="title" content={title ?? chatbotName} />
<meta
name="description"
content={
description ??
'Build beautiful conversational forms and embed them directly in your applications without a line of code. Triple your response rate and collect answers that has more value compared to a traditional form.'
}
/>
<meta property="og:type" content="website" />
<meta property="og:url" content={url ?? 'https://bot.typebot.io'} />
<meta property="og:title" content={title ?? chatbotName} />
<meta property="og:site_name" content={title ?? chatbotName} />
<meta
property="og:description"
content={
description ??
'Build beautiful conversational forms and embed them directly in your applications without a line of code. Triple your response rate and collect answers that has more value compared to a traditional form.'
}
/>
<meta
property="og:image"
itemProp="image"
content={thumbnailUrl ?? 'https://bot.typebot.io/site-preview.png'}
/>
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content={url ?? 'https://bot.typebot.io'} />
<meta property="twitter:title" content={title ?? chatbotName} />
<meta
property="twitter:description"
content={
description ??
'Build beautiful conversational forms and embed them directly in your applications without a line of code. Triple your response rate and collect answers that has more value compared to a traditional form.'
}
/>
<meta
property="twitter:image"
content={thumbnailUrl ?? 'https://bot.typebot.io/site-preview.png'}
/>
</Head>
)

View File

@ -0,0 +1,29 @@
import React from 'react'
export const ErrorPage = ({ error }: { error: 'offline' | '500' | 'IE' }) => {
let errorLabel =
'An error occured. Please try to refresh or contact the owner of this bot.'
if (error === 'offline') {
errorLabel =
'Looks like your device is offline. Please, try to refresh the page.'
}
if (error === 'IE') {
errorLabel = "This bot isn't compatible with Internet Explorer."
}
return (
<div
style={{
height: '100vh',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'column',
}}
>
{error === '500' && (
<h1 style={{ fontWeight: 'bold', fontSize: '30px' }}>500</h1>
)}
<h2>{errorLabel}</h2>
</div>
)
}

View File

@ -0,0 +1,16 @@
import React from 'react'
export const NotFoundPage = () => (
<div
style={{
height: '100vh',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'column',
}}
>
<h1 style={{ fontWeight: 'bold', fontSize: '30px' }}>404</h1>
<h2>The bot you&apos;re looking for doesn&apos;t exist</h2>
</div>
)

View File

@ -0,0 +1,26 @@
import { PublicTypebot, TypebotViewer } from 'bot-engine'
import React from 'react'
import { SEO } from '../components/Seo'
import { ErrorPage } from './ErrorPage'
import { NotFoundPage } from './NotFoundPage'
export type TypebotPageProps = {
typebot?: PublicTypebot
url: string
isIE: boolean
}
export const TypebotPage = ({ typebot, isIE, url }: TypebotPageProps) => {
if (!typebot) {
return <NotFoundPage />
}
if (isIE) {
return <ErrorPage error={'IE'} />
}
return (
<div style={{ height: '100vh' }}>
<SEO url={url} chatbotName={typebot.name} />
<TypebotViewer typebot={typebot} />
</div>
)
}

View File

@ -0,0 +1,15 @@
import { PrismaClient } from 'db'
declare const global: { prisma: PrismaClient }
let prisma: PrismaClient
if (process.env.NODE_ENV === 'production') {
prisma = new PrismaClient()
} else {
if (!global.prisma) {
global.prisma = new PrismaClient()
}
prisma = global.prisma
}
export default prisma

View File

@ -11,20 +11,20 @@
"dependencies": {
"bot-engine": "*",
"db": "*",
"next": "^12.0.4",
"next": "^12.0.7",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"devDependencies": {
"@types/node": "^16.11.9",
"@types/react": "^17.0.35",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"@types/node": "^17.0.4",
"@types/react": "^17.0.38",
"@typescript-eslint/eslint-plugin": "^5.8.0",
"eslint": "<8.0.0",
"eslint-config-next": "12.0.4",
"eslint-config-next": "12.0.7",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-prettier": "^4.0.0",
"prettier": "^2.4.1",
"prettier": "^2.5.1",
"typescript": "^4.5.4"
}
}

View File

@ -0,0 +1,5 @@
import React from 'react'
import { NotFoundPage } from '../layouts/NotFoundPage'
const NotFoundErrorPage = () => <NotFoundPage />
export default NotFoundErrorPage

View File

@ -0,0 +1,44 @@
import { PublicTypebot } from 'bot-engine'
import { GetServerSideProps, GetServerSidePropsContext } from 'next'
import { TypebotPage, TypebotPageProps } from '../layouts/TypebotPage'
import prisma from '../libs/prisma'
export const getServerSideProps: GetServerSideProps = async (
context: GetServerSidePropsContext
) => {
let typebot: PublicTypebot | undefined
const isIE = /MSIE|Trident/.test(context.req.headers['user-agent'] ?? '')
const pathname = context.resolvedUrl.split('?')[0]
try {
if (!context.req.headers.host) return { props: {} }
typebot = await getTypebotFromPublicId(context.query.publicId.toString())
if (!typebot) return { props: {} }
return {
props: {
typebot,
isIE,
url: `https://${context.req.headers.host}${pathname}`,
},
}
} catch (err) {
console.error(err)
}
return {
props: {
isIE,
url: `https://${context.req.headers.host}${pathname}`,
},
}
}
const getTypebotFromPublicId = async (
publicId: string
): Promise<PublicTypebot | undefined> => {
const typebot = await prisma.publicTypebot.findUnique({
where: { publicId },
})
return (typebot as unknown as PublicTypebot | undefined) ?? undefined
}
const App = (props: TypebotPageProps) => <TypebotPage {...props} />
export default App

View File

@ -0,0 +1,15 @@
import React from 'react'
import '../assets/styles.css'
type Props = {
Component: React.ComponentType
pageProps: {
[key: string]: unknown
}
}
export default function MyApp({ Component, pageProps }: Props): JSX.Element {
const { ...componentProps } = pageProps
return <Component {...componentProps} />
}

View File

@ -1,7 +1,46 @@
import React from 'react'
import { PublicTypebot } from 'bot-engine'
import { GetServerSideProps, GetServerSidePropsContext } from 'next'
import { TypebotPage, TypebotPageProps } from '../layouts/TypebotPage'
import prisma from '../libs/prisma'
const HomePage = () => {
return <div>Welcome to "Viewer"!</div>
export const getServerSideProps: GetServerSideProps = async (
context: GetServerSidePropsContext
) => {
let typebot: PublicTypebot | undefined
const isIE = /MSIE|Trident/.test(context.req.headers['user-agent'] ?? '')
const pathname = context.resolvedUrl.split('?')[0]
try {
if (!context.req.headers.host) return { props: {} }
typebot = await getTypebotFromUrl(context.req.headers.host)
if (!typebot) return { props: {} }
return {
props: {
typebot,
isIE,
url: `https://${context.req.headers.host}${pathname}`,
},
}
} catch (err) {
console.error(err)
}
return {
props: {
isIE,
url: `https://${context.req.headers.host}${pathname}`,
},
}
}
export default HomePage
const getTypebotFromUrl = async (
hostname: string
): Promise<PublicTypebot | undefined> => {
const publicId = hostname.split('.').shift()
if (!publicId) return
const typebot = await prisma.publicTypebot.findUnique({
where: { publicId },
})
return (typebot as unknown as PublicTypebot | undefined) ?? undefined
}
const App = (props: TypebotPageProps) => <TypebotPage {...props} />
export default App

View File

@ -11,13 +11,12 @@
"db:nuke": "docker-compose down --volumes --remove-orphans",
"dev": "dotenv -e .env yarn docker:up && dotenv -e .env turbo run dev --parallel",
"build": "dotenv -e .env turbo run build",
"build:builder": "yarn build --scope=builder --includeDependencies",
"test": "dotenv -e .env turbo run dev test",
"lint": "turbo run lint"
},
"devDependencies": {
"dotenv-cli": "^4.1.0",
"turbo": "^1.0.19"
"dotenv-cli": "^4.1.1",
"turbo": "^1.0.23"
},
"turbo": {
"baseBranch": "origin/main",

View File

@ -30,7 +30,7 @@ export const TypebotViewer = ({
<Frame
id="typebot-iframe"
head={<style>{style}</style>}
style={{ width: '100%' }}
style={{ width: '100%', height: '100%', border: 'none' }}
>
<style
dangerouslySetInnerHTML={{
@ -42,7 +42,7 @@ export const TypebotViewer = ({
<div
className="flex text-base overflow-hidden bg-cover h-screen w-screen flex-col items-center typebot-container"
style={{
// We set this as inline style to avoid color flashing (due to SSR)
// We set this as inline style to avoid color for SSR
backgroundColor: containerBgColor,
}}
>

241
yarn.lock
View File

@ -1010,13 +1010,6 @@
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.0.7.tgz#316f7bd1b6b69f554d2676cfc91a16bc7e32ee79"
integrity sha512-TNDqBV37wd95SiNdZsSUq8gnnrTwr+aN9wqy4Zxrxw4bC/jCHNsbK94DxjkG99VL30VCRXXDBTA1/Wa2jIpF9Q==
"@next/eslint-plugin-next@12.0.4":
version "12.0.4"
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.0.4.tgz#f1751715634e200a868aa3fa42b4c3391254de81"
integrity sha512-3N+LG+wQQB0JLfMj4YKkefWnjcsFVBmixRWdzbVBnt/cxbVZ0izf+BR1MzvrPX1oaP0OrYk8X/9Mn9Yftuajvg==
dependencies:
glob "7.1.7"
"@next/eslint-plugin-next@12.0.7":
version "12.0.7"
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.0.7.tgz#2c71bb66b8f8ff1080086342113406aa3156976f"
@ -1288,7 +1281,7 @@
estree-walker "^1.0.1"
picomatch "^2.2.2"
"@rushstack/eslint-patch@^1.0.6", "@rushstack/eslint-patch@^1.0.8":
"@rushstack/eslint-patch@^1.0.8":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz#7f698254aadf921e48dda8c0a6b304026b8a9323"
integrity sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==
@ -1447,6 +1440,11 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.14.tgz#4939fb42e5b0ffb3ea7e193c28244fe7414977a6"
integrity sha512-mK6BKLpL0bG6v2CxHbm0ed6RcZrAtTHBTd/ZpnlVPVa3HkumsqLE4BC4u6TQ8D7pnrRbOU0am6epuALs+Ncnzw==
"@types/node@^17.0.4":
version "17.0.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.4.tgz#fec0ce0526abb6062fd206d72a642811b887a111"
integrity sha512-6xwbrW4JJiJLgF+zNypN5wr2ykM9/jHcL7rQ8fZe2vuftggjzZeRSM4OwRc6Xk8qWjwJ99qVHo/JgOGmomWRog==
"@types/nprogress@^0.2.0":
version "0.2.0"
resolved "https://registry.yarnpkg.com/@types/nprogress/-/nprogress-0.2.0.tgz#86c593682d4199212a0509cc3c4d562bbbd6e45f"
@ -1476,7 +1474,7 @@
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^17.0.35", "@types/react@^17.0.37":
"@types/react@*", "@types/react@^17.0.37":
version "17.0.37"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.37.tgz#6884d0aa402605935c397ae689deed115caad959"
integrity sha512-2FS1oTqBGcH/s0E+CjrCCR9+JMpsu9b69RTFO+40ua43ZqP5MmQ4iUde/dMjWR909KxZwmOQIFq6AV6NjEG5xg==
@ -1485,6 +1483,15 @@
"@types/scheduler" "*"
csstype "^3.0.2"
"@types/react@^17.0.38":
version "17.0.38"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.38.tgz#f24249fefd89357d5fa71f739a686b8d7c7202bd"
integrity sha512-SI92X1IA+FMnP3qM5m4QReluXzhcmovhZnLNm3pyeQlooi02qI7sLiepEYqT678uNiyc25XfCqxREFpy3W7YhQ==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
csstype "^3.0.2"
"@types/resolve@1.17.1":
version "1.17.1"
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6"
@ -1546,20 +1553,6 @@
dependencies:
"@types/node" "*"
"@typescript-eslint/eslint-plugin@^5.4.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.7.0.tgz#12d54709f8ea1da99a01d8a992cd0474ad0f0aa9"
integrity sha512-8RTGBpNn5a9M628wBPrCbJ+v3YTEOE2qeZb7TDkGKTDXSj36KGRg92SpFFaR/0S3rSXQxM0Og/kV9EyadsYSBg==
dependencies:
"@typescript-eslint/experimental-utils" "5.7.0"
"@typescript-eslint/scope-manager" "5.7.0"
debug "^4.3.2"
functional-red-black-tree "^1.0.1"
ignore "^5.1.8"
regexpp "^3.2.0"
semver "^7.3.5"
tsutils "^3.21.0"
"@typescript-eslint/eslint-plugin@^5.8.0":
version "5.8.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.8.0.tgz#52cd9305ceef98a5333f9492d519e6c6c7fe7d43"
@ -1574,18 +1567,6 @@
semver "^7.3.5"
tsutils "^3.21.0"
"@typescript-eslint/experimental-utils@5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.7.0.tgz#2b1633e6613c3238036156f70c32634843ad034f"
integrity sha512-u57eZ5FbEpzN5kSjmVrSesovWslH2ZyNPnaXQMXWgH57d5+EVHEt76W75vVuI9qKZ5BMDKNfRN+pxcPEjQjb2A==
dependencies:
"@types/json-schema" "^7.0.9"
"@typescript-eslint/scope-manager" "5.7.0"
"@typescript-eslint/types" "5.7.0"
"@typescript-eslint/typescript-estree" "5.7.0"
eslint-scope "^5.1.1"
eslint-utils "^3.0.0"
"@typescript-eslint/experimental-utils@5.8.0":
version "5.8.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.8.0.tgz#0916ffe98d34b3c95e3652efa0cace61a7b25728"
@ -1598,16 +1579,6 @@
eslint-scope "^5.1.1"
eslint-utils "^3.0.0"
"@typescript-eslint/parser@^4.20.0":
version "4.33.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.33.0.tgz#dfe797570d9694e560528d18eecad86c8c744899"
integrity sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==
dependencies:
"@typescript-eslint/scope-manager" "4.33.0"
"@typescript-eslint/types" "4.33.0"
"@typescript-eslint/typescript-estree" "4.33.0"
debug "^4.3.1"
"@typescript-eslint/parser@^5.0.0":
version "5.8.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.8.0.tgz#b39970b21c1d7bc4a6018507fb29b380328d2587"
@ -1618,22 +1589,6 @@
"@typescript-eslint/typescript-estree" "5.8.0"
debug "^4.3.2"
"@typescript-eslint/scope-manager@4.33.0":
version "4.33.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3"
integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==
dependencies:
"@typescript-eslint/types" "4.33.0"
"@typescript-eslint/visitor-keys" "4.33.0"
"@typescript-eslint/scope-manager@5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.7.0.tgz#70adf960e5a58994ad50438ba60d98ecadd79452"
integrity sha512-7mxR520DGq5F7sSSgM0HSSMJ+TFUymOeFRMfUfGFAVBv8BR+Jv1vHgAouYUvWRZeszVBJlLcc9fDdktxb5kmxA==
dependencies:
"@typescript-eslint/types" "5.7.0"
"@typescript-eslint/visitor-keys" "5.7.0"
"@typescript-eslint/scope-manager@5.8.0":
version "5.8.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.8.0.tgz#2371095b4fa4c7be6a80b380f4e1b49c715e16f4"
@ -1642,47 +1597,11 @@
"@typescript-eslint/types" "5.8.0"
"@typescript-eslint/visitor-keys" "5.8.0"
"@typescript-eslint/types@4.33.0":
version "4.33.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72"
integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==
"@typescript-eslint/types@5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.7.0.tgz#2d4cae0105ba7d08bffa69698197a762483ebcbe"
integrity sha512-5AeYIF5p2kAneIpnLFve8g50VyAjq7udM7ApZZ9JYjdPjkz0LvODfuSHIDUVnIuUoxafoWzpFyU7Sqbxgi79mA==
"@typescript-eslint/types@5.8.0":
version "5.8.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.8.0.tgz#e7fa74ec35d9dbe3560d039d3d8734986c3971e0"
integrity sha512-LdCYOqeqZWqCMOmwFnum6YfW9F3nKuxJiR84CdIRN5nfHJ7gyvGpXWqL/AaW0k3Po0+wm93ARAsOdzlZDPCcXg==
"@typescript-eslint/typescript-estree@4.33.0":
version "4.33.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609"
integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==
dependencies:
"@typescript-eslint/types" "4.33.0"
"@typescript-eslint/visitor-keys" "4.33.0"
debug "^4.3.1"
globby "^11.0.3"
is-glob "^4.0.1"
semver "^7.3.5"
tsutils "^3.21.0"
"@typescript-eslint/typescript-estree@5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.7.0.tgz#968fad899050ccce4f08a40cd5fabc0798525006"
integrity sha512-aO1Ql+izMrTnPj5aFFlEJkpD4jRqC4Gwhygu2oHK2wfVQpmOPbyDSveJ+r/NQo+PWV43M6uEAeLVbTi09dFLhg==
dependencies:
"@typescript-eslint/types" "5.7.0"
"@typescript-eslint/visitor-keys" "5.7.0"
debug "^4.3.2"
globby "^11.0.4"
is-glob "^4.0.3"
semver "^7.3.5"
tsutils "^3.21.0"
"@typescript-eslint/typescript-estree@5.8.0":
version "5.8.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.8.0.tgz#900469ba9d5a37f4482b014ecce4a5dbb86cb4dd"
@ -1696,22 +1615,6 @@
semver "^7.3.5"
tsutils "^3.21.0"
"@typescript-eslint/visitor-keys@4.33.0":
version "4.33.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd"
integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==
dependencies:
"@typescript-eslint/types" "4.33.0"
eslint-visitor-keys "^2.0.0"
"@typescript-eslint/visitor-keys@5.7.0":
version "5.7.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.7.0.tgz#e05164239eb7cb8aa9fa06c516ede480ce260178"
integrity sha512-hdohahZ4lTFcglZSJ3DGdzxQHBSxsLVqHzkiOmKi7xVAWC4y2c1bIMKmPJSrA4aOEoRUPOKQ87Y/taC7yVHpFg==
dependencies:
"@typescript-eslint/types" "5.7.0"
eslint-visitor-keys "^3.0.0"
"@typescript-eslint/visitor-keys@5.8.0":
version "5.8.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.8.0.tgz#22d4ed96fe2451135299239feedb9fe1dcec780c"
@ -3213,7 +3116,7 @@ domutils@^2.8.0:
domelementtype "^2.2.0"
domhandler "^4.2.0"
dotenv-cli@^4.1.0:
dotenv-cli@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/dotenv-cli/-/dotenv-cli-4.1.1.tgz#26a59fbb25876008985a15fa366b416607e8372c"
integrity sha512-XvKv1pa+UBrsr3CtLGBsR6NdsoS7znqaHUf4Knj0eZO+gOI/hjj9KgWDP+KjpfEbj6wAba1UpbhaP9VezNkWhg==
@ -3384,21 +3287,6 @@ escape-string-regexp@^4.0.0:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
eslint-config-next@12.0.4:
version "12.0.4"
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.0.4.tgz#22f0305770f0d11bfa034df0efea7cf9cdb37d58"
integrity sha512-uBOHBjYaRF0MaS5feB7lFOncHhSrtFxZy/oud6pEW/wn/JUQtZWeH/J4JyODBfX+G7h9mttgHLZNmUjNJis6Kw==
dependencies:
"@next/eslint-plugin-next" "12.0.4"
"@rushstack/eslint-patch" "^1.0.6"
"@typescript-eslint/parser" "^4.20.0"
eslint-import-resolver-node "^0.3.4"
eslint-import-resolver-typescript "^2.4.0"
eslint-plugin-import "^2.22.1"
eslint-plugin-jsx-a11y "^6.4.1"
eslint-plugin-react "^7.23.1"
eslint-plugin-react-hooks "^4.2.0"
eslint-config-next@12.0.7:
version "12.0.7"
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.0.7.tgz#985f06c3d749673f6b4b214db6b9321da1bf0b5f"
@ -3454,7 +3342,7 @@ eslint-plugin-cypress@^2.12.1:
dependencies:
globals "^11.12.0"
eslint-plugin-import@^2.22.1, eslint-plugin-import@^2.25.2:
eslint-plugin-import@^2.25.2:
version "2.25.3"
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.3.tgz#a554b5f66e08fb4f6dc99221866e57cfff824766"
integrity sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg==
@ -3473,7 +3361,7 @@ eslint-plugin-import@^2.22.1, eslint-plugin-import@^2.25.2:
resolve "^1.20.0"
tsconfig-paths "^3.11.0"
eslint-plugin-jsx-a11y@^6.4.1, eslint-plugin-jsx-a11y@^6.5.1:
eslint-plugin-jsx-a11y@^6.5.1:
version "6.5.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz#cdbf2df901040ca140b6ec14715c988889c2a6d8"
integrity sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==
@ -3498,12 +3386,12 @@ eslint-plugin-prettier@^4.0.0:
dependencies:
prettier-linter-helpers "^1.0.0"
eslint-plugin-react-hooks@^4.2.0, eslint-plugin-react-hooks@^4.3.0:
eslint-plugin-react-hooks@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172"
integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==
eslint-plugin-react@^7.23.1, eslint-plugin-react@^7.27.0:
eslint-plugin-react@^7.27.0:
version "7.27.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.27.1.tgz#469202442506616f77a854d91babaae1ec174b45"
integrity sha512-meyunDjMMYeWr/4EBLTV1op3iSG3mjT/pz5gti38UzfM4OPpNc2m0t2xvKCOMU5D6FSdd34BIMFOvQbW+i8GAA==
@ -4078,7 +3966,7 @@ globals@^13.6.0, globals@^13.9.0:
dependencies:
type-fest "^0.20.2"
globby@^11.0.3, globby@^11.0.4:
globby@^11.0.4:
version "11.0.4"
resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5"
integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==
@ -5076,7 +4964,7 @@ next-auth@beta:
preact-render-to-string "^5.1.19"
uuid "^8.3.2"
next@^12.0.4, next@^12.0.7:
next@^12.0.7:
version "12.0.7"
resolved "https://registry.yarnpkg.com/next/-/next-12.0.7.tgz#33ebf229b81b06e583ab5ae7613cffe1ca2103fc"
integrity sha512-sKO8GJJYfuk9c+q+zHSNumvff+wP7ufmOlwT6BuzwiYfFJ61VTTkfTcDLSJ+95ErQJiC54uS4Yg5JEE8H6jXRA==
@ -5936,7 +5824,7 @@ prettier-linter-helpers@^1.0.0:
dependencies:
fast-diff "^1.1.2"
prettier@^2.4.1, prettier@^2.5.1:
prettier@^2.5.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a"
integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==
@ -7289,10 +7177,83 @@ tunnel-agent@^0.6.0:
dependencies:
safe-buffer "^5.0.1"
turbo@^1.0.19:
version "1.0.19"
resolved "https://registry.yarnpkg.com/turbo/-/turbo-1.0.19.tgz#5c666b7b497e443269da2c553d00fe23dbcc6914"
integrity sha512-/gdEdpdludyHX+344JQ84bglK33dI4IWTtGkBkfJnSQW+lC3/JFAu9jy+4zNK2gdzxjwcB2/qQK+Pv53SZd1Kw==
turbo-darwin-64@1.0.23:
version "1.0.23"
resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-1.0.23.tgz#0164b1a2ee6782bf2233bb1887b01ac78486378e"
integrity sha512-z6ArzNKpQIw/YhFf20lUGl5VaGTZ94MSppXuuYkCyxMQwK3qye3r2ENQbUKkxfv16fAmfr7z1bJt6YwfOjwPiw==
turbo-darwin-arm64@1.0.23:
version "1.0.23"
resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-1.0.23.tgz#7d6de986595d6ded9d853744c26780b50c7b196c"
integrity sha512-U02Ip7kO7eDN3WRliIrPtqYFqcpsvpNsE5fX1T0uFjXfSJruiDBrrNpGmZEh8hatS5wQyG7VaxW+izJqd7TCsw==
turbo-freebsd-64@1.0.23:
version "1.0.23"
resolved "https://registry.yarnpkg.com/turbo-freebsd-64/-/turbo-freebsd-64-1.0.23.tgz#f78d2056414496334cb8c6bc28ac7f3d5d0ab30c"
integrity sha512-5XT8pp0uJ1vRqNJydacn6ouY4COUeufOdLuiPOWAOsvMW5FOJNAOdAJ7lISBBqhCpYF8CEZ9kCAI2f9nOzzY0Q==
turbo-freebsd-arm64@1.0.23:
version "1.0.23"
resolved "https://registry.yarnpkg.com/turbo-freebsd-arm64/-/turbo-freebsd-arm64-1.0.23.tgz#d7d4eca48a21da17403c804e5bd52a3daffbdc1c"
integrity sha512-70BGJTVX3jYvzDISp8dWM/rwiK4CDlNVQJnnlUMKrueFtpgHZhsRKjIeNgIKxVSTyp4xT0Vl4xhc9zFhMT17aw==
turbo-linux-32@1.0.23:
version "1.0.23"
resolved "https://registry.yarnpkg.com/turbo-linux-32/-/turbo-linux-32-1.0.23.tgz#c11de3c98944d43b9e25582c03ddd8f38d6cd85c"
integrity sha512-ee3N8f7h1qg5noKII5Tq2gyG6PVFl/apllX0TPbZiUab6553QPfVt+tB+5W6BZmKGUdHHCvW42xuig0krrrRGw==
turbo-linux-64@1.0.23:
version "1.0.23"
resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-1.0.23.tgz#7700a5e5ad96e741405957e7cd33a7422c49bfbd"
integrity sha512-j2+1P2+rdOXb/yzz78SCmxXLdFSSlCzZS0Psg1vetYozuoT0k+xu7gr6iqEHdBWw39jNFuT72hVqrNZ4TClHcA==
turbo-linux-arm64@1.0.23:
version "1.0.23"
resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-1.0.23.tgz#79b49e14ef3038f99036134abcf53c17645b5eb9"
integrity sha512-VNW8yyBG63MGUzZ/Y2DS883P8rzz/hQuiCklw2lTBQ4O9dp2FxYrAVnmCxbnsIDZG/wEupdvaHVgqH7j2DJgwg==
turbo-linux-arm@1.0.23:
version "1.0.23"
resolved "https://registry.yarnpkg.com/turbo-linux-arm/-/turbo-linux-arm-1.0.23.tgz#7140b73572948a0285395feb3abe8a9067f74d68"
integrity sha512-+aD+v03bpkmuXEfk14w2fLH5cAyfyGlAs5gBwQmwyF3XllJ40OL/cw9xDnBREpZsnm9o1GTQpr0wmepjw9d4iQ==
turbo-linux-mips64le@1.0.23:
version "1.0.23"
resolved "https://registry.yarnpkg.com/turbo-linux-mips64le/-/turbo-linux-mips64le-1.0.23.tgz#fa4e989a8e149e3684f4732ed1b2a386fc829c8a"
integrity sha512-CJNd7F9z8EhqcdJnd1rSiU/+hSNG3E+fudQ5pr55y0nhSShFMMdZxdLvL5zzhWpBl1g8YldphjPqNLChgGatKw==
turbo-linux-ppc64le@1.0.23:
version "1.0.23"
resolved "https://registry.yarnpkg.com/turbo-linux-ppc64le/-/turbo-linux-ppc64le-1.0.23.tgz#3c1e0f5a79b8c34d790c7828ec443ed73ed95706"
integrity sha512-RjzDqXQl+nqV+2A6MRk1sALBQtpCB/h8qDWhJIL/VUgToTMdllAThiYI+lALLmGWBumXs4XDbk+83FGJlJ1bDg==
turbo-windows-32@1.0.23:
version "1.0.23"
resolved "https://registry.yarnpkg.com/turbo-windows-32/-/turbo-windows-32-1.0.23.tgz#17d58f43406cd68062131924f94c2df8ca159f9e"
integrity sha512-qTfldTd5OO/s8unGFnITe4IX8ua2SNj/VVQbvVcObDJK6xrfBY4tDS78rIo9//xTSRyK+28AoPxRZsVqqF2hlA==
turbo-windows-64@1.0.23:
version "1.0.23"
resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-1.0.23.tgz#0e53fde0395fa88006be7fcd36c1853995cfa319"
integrity sha512-yzhF6GEYiyrXoO/l9T6amB16OITsFXdeMTc0Vf2BZFOG1fn9Muc4CxQ+CcdsLlai+TqQTKlpEf0+l83vI+R2Jw==
turbo@^1.0.23:
version "1.0.23"
resolved "https://registry.yarnpkg.com/turbo/-/turbo-1.0.23.tgz#9a8f54f116daee67e0c131c4c936f075d32281a2"
integrity sha512-/VHsARQyl8wsfCJtuJicjYq7Do/P5yjJde3bjG9TAZHj/PzA9LuRU7WOEPfUrT+felOQ3vwUMZtC8xrYFmndLA==
optionalDependencies:
turbo-darwin-64 "1.0.23"
turbo-darwin-arm64 "1.0.23"
turbo-freebsd-64 "1.0.23"
turbo-freebsd-arm64 "1.0.23"
turbo-linux-32 "1.0.23"
turbo-linux-64 "1.0.23"
turbo-linux-arm "1.0.23"
turbo-linux-arm64 "1.0.23"
turbo-linux-mips64le "1.0.23"
turbo-linux-ppc64le "1.0.23"
turbo-windows-32 "1.0.23"
turbo-windows-64 "1.0.23"
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"