Compare commits
9 Commits
old_code
...
f30f9090b3
Author | SHA1 | Date | |
---|---|---|---|
f30f9090b3 | |||
3fbe04896e | |||
a627addad5 | |||
4afe2f906d | |||
b87df50328 | |||
582455933e | |||
a408abdb97 | |||
f4eadc34c7 | |||
38f3caa524 |
@ -47,10 +47,6 @@ selfservice:
|
||||
registration:
|
||||
lifespan: 10m
|
||||
ui_url: http://127.0.0.1:3000/signup
|
||||
after:
|
||||
password:
|
||||
hooks:
|
||||
- hook: session
|
||||
|
||||
log:
|
||||
level: debug
|
||||
|
3
client/.gitignore
vendored
3
client/.gitignore
vendored
@ -38,3 +38,6 @@ yarn-error.log*
|
||||
|
||||
cypress/screenshots
|
||||
cypress/videos
|
||||
|
||||
# Sentry
|
||||
.sentryclirc
|
||||
|
@ -1,38 +0,0 @@
|
||||
import { ArrowLeftIcon } from '@heroicons/react/24/outline';
|
||||
|
||||
import Button from './Button';
|
||||
import NavBar from './NavBar';
|
||||
import SideNavChannel from './SideNavChannel';
|
||||
import streamData from '../placeholder/GetStreams';
|
||||
import { NextPage } from 'next';
|
||||
import Link from 'next/link';
|
||||
|
||||
const BrowseLayout: NextPage = ({children}) => {
|
||||
return (
|
||||
<div className="font-inter flex flex-col h-screen text-gray-100">
|
||||
<NavBar />
|
||||
<main className="flex-1 flex flex-row overflow-hidden">
|
||||
<div className="bg-neutral-800 w-60 flex flex-col">
|
||||
<div className="flex flex-row justify-between p-2 items-center">
|
||||
<p className="uppercase font-semibold text-sm">Trending channels</p>
|
||||
<Button variant="subtle" className="p-2">
|
||||
<ArrowLeftIcon className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
<ul className="flex-1 overflow-scrollbar">
|
||||
{streamData.data.map((stream) => (
|
||||
<li key={stream.id}>
|
||||
<Link href={`/${stream.user_login}`} passHref={true}>
|
||||
<SideNavChannel stream={stream} />
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
{children}
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default BrowseLayout;
|
@ -1,7 +0,0 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
const ChatBadge: FC = () => {
|
||||
return <span className="w-5 h-5 rounded-sm bg-pink-300 inline-block align-middle" />;
|
||||
};
|
||||
|
||||
export default ChatBadge;
|
@ -1,25 +0,0 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
import ChatBadge from './ChatBadge';
|
||||
|
||||
const ChatMessage: FC = () => {
|
||||
return (
|
||||
<p className="mx-2 p-2 hover:bg-neutral-700 text-sm rounded-md">
|
||||
<div className="space-x-1 inline">
|
||||
<ChatBadge />
|
||||
<ChatBadge />
|
||||
<span className="align-middle">Username</span>
|
||||
</div>
|
||||
<span className="align-middle">: </span>
|
||||
<span className="break-all align-middle">
|
||||
<img
|
||||
src="https://cdn.7tv.app/emote/60afbe0599923bbe7fe9bae1/2x"
|
||||
alt="Poggies"
|
||||
className="inline w-7 h-7"
|
||||
/>
|
||||
</span>
|
||||
</p>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChatMessage;
|
@ -1,40 +0,0 @@
|
||||
import { FC } from 'react';
|
||||
import { useForm, SubmitHandler } from 'react-hook-form';
|
||||
|
||||
import FormField from './FormField';
|
||||
import InlineLink from './InlineLink';
|
||||
import SubmitButton from './SubmitButton';
|
||||
|
||||
interface LoginFormValues {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
const LoginForm: FC = () => {
|
||||
const { register, handleSubmit } = useForm<LoginFormValues>();
|
||||
const onSubmit: SubmitHandler<LoginFormValues> = (data) => console.log(data);
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
|
||||
<FormField
|
||||
label="Username"
|
||||
className="py-2 px-2 outline-2 w-full"
|
||||
{...register('username')}
|
||||
/>
|
||||
<FormField
|
||||
label="Password"
|
||||
type="password"
|
||||
{...register('password')}
|
||||
className="py-2 px-2 outline-2 w-full"
|
||||
bottomElement={
|
||||
<InlineLink to="#" className="block mt-2">
|
||||
Trouble logging in?
|
||||
</InlineLink>
|
||||
}
|
||||
/>
|
||||
<SubmitButton className="w-full" value="Log In" />
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoginForm;
|
@ -1,65 +0,0 @@
|
||||
import { UserIcon } from '@heroicons/react/24/outline';
|
||||
import { FC, useState } from 'react';
|
||||
|
||||
import Button from './Button';
|
||||
import Input from './Input';
|
||||
import LoginModal from './LoginModal';
|
||||
|
||||
const NavBar: FC = () => {
|
||||
const [showLogin, setShowLogin] = useState(false);
|
||||
const [showTab, setShowTab] = useState(0);
|
||||
|
||||
const showLoginTab = () => {
|
||||
setShowTab(0);
|
||||
setShowLogin(true);
|
||||
};
|
||||
|
||||
const showSignupTab = () => {
|
||||
setShowTab(1);
|
||||
setShowLogin(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<nav className="bg-zinc-800 w-screen font-semibold border-b border-b-black">
|
||||
<div className="flex flex-row justify-between items-center mx-2">
|
||||
<div className="basis-1/4">
|
||||
<ul className="flex flex-row space-x-8 items-center">
|
||||
<li>
|
||||
<img src="./assets/images/logo.png" className="w-8 h-8" alt="logo" />
|
||||
</li>
|
||||
<li>
|
||||
<p className="text-lg">Browse</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="basis-2/4">
|
||||
<div className="flex flex-row space-x-3 items-center justify-center">
|
||||
<Input className=" w-72 my-2 p-2" placeholder="Search" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="basis-1/4">
|
||||
<ul className="justify-end flex flex-row space-x-3 items-center">
|
||||
<li>
|
||||
<Button className="text-sm px-3 py-2 bg-neutral-700" onClick={showLoginTab}>
|
||||
Log In
|
||||
</Button>
|
||||
</li>
|
||||
<li>
|
||||
<Button className="text-sm px-3 py-2 bg-violet-500" onClick={showSignupTab}>
|
||||
Sign Up
|
||||
</Button>
|
||||
</li>
|
||||
<li>
|
||||
<Button variant="subtle" className="p-1">
|
||||
<UserIcon className="h-5 w-5 inline-block" />
|
||||
</Button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<LoginModal isOpen={showLogin} defaultPage={showTab} onClose={() => setShowLogin(false)} />
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
export default NavBar;
|
@ -1,28 +0,0 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
import { Stream } from '../types';
|
||||
import { numFormatter } from '../utils/format';
|
||||
|
||||
interface SideNavChannelProps {
|
||||
stream: Stream;
|
||||
}
|
||||
|
||||
const SideNavChannel: FC<SideNavChannelProps> = ({ stream }) => {
|
||||
return (
|
||||
<div className="flex flex-row px-3 py-2 text-sm leading-4 space-x-2 hover:bg-neutral-700/40 cursor-pointer">
|
||||
<img className="rounded-full w-8 h-8" src={stream.thumbnail_url} alt="avatar" />
|
||||
<div className="flex flex-col flex-1">
|
||||
<div className="flex flex-row justify-between">
|
||||
<div className="font-bold">{stream.user_name}</div>
|
||||
<div className="space-x-1 flex flex-row items-center">
|
||||
<div className="w-2 h-2 bg-red-600 rounded-full inline-block" />
|
||||
<span>{numFormatter.format(stream.viewer_count)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-gray-300">{stream.game_name}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SideNavChannel;
|
@ -1,143 +0,0 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { SelfServiceRegistrationFlow } from "@ory/client"
|
||||
import { useRouter } from "next/router"
|
||||
import { useMemo } from "react"
|
||||
import { FC, useEffect, useState } from "react"
|
||||
import { SubmitHandler, useForm } from "react-hook-form"
|
||||
import { z } from "zod"
|
||||
import ory from "../services/ory"
|
||||
|
||||
import FormField from "./FormField"
|
||||
import InlineLink from "./InlineLink"
|
||||
import Input from "./Input"
|
||||
import SubmitButton from "./SubmitButton"
|
||||
|
||||
const PASSWORD_REGEX =
|
||||
/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$ %^&*-]).{8,64}$/
|
||||
|
||||
const SignupFormSchema = z
|
||||
.object({
|
||||
csrfToken: z.string(),
|
||||
username: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1, { message: "Username must be at least 1 character long." })
|
||||
.max(16, { message: "Username can't be longer than 16 characters.." }),
|
||||
password: z
|
||||
.string()
|
||||
.trim()
|
||||
.regex(
|
||||
PASSWORD_REGEX,
|
||||
"Password must be 8-64 long and must contain a number, uppercase, lowercase and special character.",
|
||||
),
|
||||
passwordRepeat: z.string().trim(),
|
||||
email: z.string().email({ message: "Not a valid email address" }).trim(),
|
||||
})
|
||||
.refine((data) => data.password === data.passwordRepeat, {
|
||||
message: "Passwords do not match.",
|
||||
path: ["passwordRepeat"],
|
||||
})
|
||||
|
||||
type SignupFormValues = z.infer<typeof SignupFormSchema>
|
||||
|
||||
const formFields = [
|
||||
{ id: "username", label: "Username", type: "text" },
|
||||
{ id: "password", label: "Password", type: "password" },
|
||||
{ id: "passwordRepeat", label: "Confirm Password", type: "password" },
|
||||
{ id: "email", label: "Email", type: "email" },
|
||||
]
|
||||
|
||||
const SignupForm: FC = () => {
|
||||
const router = useRouter()
|
||||
const [flow, setFlow] = useState<SelfServiceRegistrationFlow>()
|
||||
const { flow: flowId, return_to: returnTo } = router.query
|
||||
const { register, handleSubmit, formState } = useForm<SignupFormValues>({
|
||||
resolver: zodResolver(SignupFormSchema),
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
const func = async () => {
|
||||
if (!router.isReady || flow) {
|
||||
return
|
||||
}
|
||||
|
||||
let serviceFlow
|
||||
if (flowId) {
|
||||
serviceFlow = await ory.getSelfServiceRegistrationFlow(String(flowId))
|
||||
} else {
|
||||
serviceFlow =
|
||||
await ory.initializeSelfServiceRegistrationFlowForBrowsers(
|
||||
returnTo ? String(returnTo) : undefined,
|
||||
)
|
||||
}
|
||||
|
||||
setFlow(serviceFlow.data)
|
||||
}
|
||||
|
||||
func()
|
||||
}, [flowId, router, router.isReady, returnTo, flow])
|
||||
|
||||
const onSubmit: SubmitHandler<SignupFormValues> = async (data) => {
|
||||
await router.push(`/signup?flow=${flow?.id}`, undefined, {
|
||||
shallow: true,
|
||||
})
|
||||
try {
|
||||
const resp = await ory.submitSelfServiceRegistrationFlow(
|
||||
String(flow?.id),
|
||||
{
|
||||
csrf_token: data.csrfToken,
|
||||
method: "password",
|
||||
password: data.password,
|
||||
traits: {
|
||||
email: data.email,
|
||||
// username: data.username,
|
||||
},
|
||||
},
|
||||
)
|
||||
console.log(resp)
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
|
||||
{flow && (
|
||||
<Input
|
||||
hidden={true}
|
||||
value={flow.ui.nodes[0].attributes.value}
|
||||
{...register("csrfToken")}
|
||||
/>
|
||||
)}
|
||||
<p className="text-sm">
|
||||
Creating an account allows you to participate in chat, follow your
|
||||
favorite channels, and broadcast from your own channel.
|
||||
</p>
|
||||
{formFields.map((field) => (
|
||||
<FormField
|
||||
key={field.id}
|
||||
id={field.id}
|
||||
type={field.type}
|
||||
label={field.label}
|
||||
{...register(field.id as any)}
|
||||
className="py-2 px-2 outline-2 w-full"
|
||||
bottomElement={
|
||||
<p className="text-xs">
|
||||
{formState.errors[(field.id as any) || ""]?.message}
|
||||
</p>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
<p className="text-sm text-center">
|
||||
By clicking Sign Up, you are agreeing to twitch-clone's{" "}
|
||||
<InlineLink to="https://tosdr.org/en/service/200">
|
||||
Terms of Service
|
||||
</InlineLink>
|
||||
.
|
||||
</p>
|
||||
<SubmitButton className="w-full" value="Sign Up" />
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
export default SignupForm
|
11
client/components/common/Logo.tsx
Normal file
11
client/components/common/Logo.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import { FC } from "react"
|
||||
|
||||
interface LogoProps {
|
||||
className?: string
|
||||
}
|
||||
|
||||
const Logo: FC<LogoProps> = ({ className }) => {
|
||||
return <img src="./assets/images/logo.png" className={className} alt="logo" />
|
||||
}
|
||||
|
||||
export default Logo
|
@ -1,7 +1,7 @@
|
||||
/* eslint-disable react/display-name */
|
||||
import { forwardRef, ReactNode } from "react"
|
||||
|
||||
import Input from "./Input"
|
||||
import Input from "../Input"
|
||||
|
||||
interface FormFieldProps extends React.ComponentPropsWithoutRef<"input"> {
|
||||
label?: string
|
13
client/components/layout/BrowseLayout.tsx
Normal file
13
client/components/layout/BrowseLayout.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import NavBar from "../nav/NavBar"
|
||||
import { NextPage } from "next"
|
||||
|
||||
const BrowseLayout: NextPage = ({ children }) => {
|
||||
return (
|
||||
<div className="font-inter flex flex-col h-screen text-gray-100">
|
||||
<NavBar />
|
||||
<main className="flex-1 flex flex-row overflow-hidden">{children}</main>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default BrowseLayout
|
72
client/components/login/LoginForm.tsx
Normal file
72
client/components/login/LoginForm.tsx
Normal file
@ -0,0 +1,72 @@
|
||||
import { FC } from "react"
|
||||
import { useForm, SubmitHandler } from "react-hook-form"
|
||||
|
||||
import FormField from "../common/form/FormField"
|
||||
import InlineLink from "../common/InlineLink"
|
||||
import SubmitButton from "../common/form/SubmitButton"
|
||||
|
||||
import * as validation from "../../config/validation"
|
||||
import { z } from "zod"
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import useLogInFlow from "../../hooks/useLogInFlow"
|
||||
import Input from "../common/Input"
|
||||
|
||||
const LogInFormSchema = z.object({
|
||||
csrfToken: z.string(),
|
||||
password: validation.password,
|
||||
email: z.string().email({ message: "Not a valid email address" }).trim(),
|
||||
})
|
||||
|
||||
type LogInFormValues = z.infer<typeof LogInFormSchema>
|
||||
|
||||
const formFields = [
|
||||
{ id: "email", label: "Email", type: "email" },
|
||||
{ id: "password", label: "Password", type: "password" },
|
||||
]
|
||||
|
||||
const LoginForm: FC = () => {
|
||||
const logInFlow = useLogInFlow()
|
||||
const { register, handleSubmit, formState } = useForm<LogInFormValues>({
|
||||
resolver: zodResolver(LogInFormSchema),
|
||||
})
|
||||
const onSubmit: SubmitHandler<LogInFormValues> = (data) =>
|
||||
logInFlow.submitData({
|
||||
csrf_token: data.csrfToken,
|
||||
method: "password",
|
||||
identifier: data.email,
|
||||
password: data.password,
|
||||
})
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
|
||||
{logInFlow.flow && (
|
||||
<Input
|
||||
hidden={true}
|
||||
value={logInFlow.flow.ui.nodes[0].attributes.value}
|
||||
{...register("csrfToken")}
|
||||
/>
|
||||
)}
|
||||
{formFields.map((field) => (
|
||||
<FormField
|
||||
key={field.id}
|
||||
id={field.id}
|
||||
type={field.type}
|
||||
label={field.label}
|
||||
{...register(field.id as any)}
|
||||
className="py-2 px-2 outline-2 w-full"
|
||||
bottomElement={
|
||||
<p className="text-xs">
|
||||
{formState.errors[(field.id as any) || ""]?.message}
|
||||
</p>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
<SubmitButton className="w-full" value="Log In" />
|
||||
<div className="text-center">
|
||||
<InlineLink to="#">Trouble logging in?</InlineLink>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
export default LoginForm
|
@ -1,33 +1,42 @@
|
||||
import { Dialog, Tab } from '@headlessui/react';
|
||||
import { FC, useEffect, useRef } from 'react';
|
||||
import { Dialog, Tab } from "@headlessui/react"
|
||||
import { FC } from "react"
|
||||
import Logo from "../common/Logo"
|
||||
|
||||
import LoginForm from './LoginForm';
|
||||
import LoginModalTab from './LoginModalTab';
|
||||
import SignupForm from './SignupForm';
|
||||
import LoginForm from "./LoginForm"
|
||||
import LoginModalTab from "./LoginModalTab"
|
||||
import SignupForm from "./SignupForm"
|
||||
|
||||
export interface LoginModelProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => any;
|
||||
defaultPage?: number;
|
||||
isOpen: boolean
|
||||
onClose?: () => any
|
||||
defaultPage?: number
|
||||
}
|
||||
|
||||
const LoginModal: FC<LoginModelProps> = ({ defaultPage, isOpen, onClose }) => {
|
||||
const LoginModal: FC<LoginModelProps> = ({
|
||||
defaultPage,
|
||||
isOpen,
|
||||
onClose = (b: boolean) => {},
|
||||
}) => {
|
||||
return (
|
||||
<Dialog open={isOpen} onClose={onClose} className="relative z-50">
|
||||
<div className="bg-black/80 fixed inset-0 flex items-center justify-center">
|
||||
<Dialog.Panel className="bg-zinc-900 text-gray-100 w-[420px] rounded-md py-12 px-6">
|
||||
<div className="flex flex-row items-center justify-center">
|
||||
<Dialog.Title className="text-xl">
|
||||
<img src="./assets/images/logo.png" className="inline w-12 h-12" alt="logo" /> Log in to twitch-clone
|
||||
<Logo className="inline w-12 h-12" /> Log in to twitch-clone
|
||||
</Dialog.Title>
|
||||
</div>
|
||||
<Tab.Group defaultIndex={defaultPage}>
|
||||
<Tab.List className="space-x-4 border-b border-b-neutral-100/40 mt-4">
|
||||
<Tab>
|
||||
{({ selected }) => <LoginModalTab selected={selected}>Log In</LoginModalTab>}
|
||||
{({ selected }) => (
|
||||
<LoginModalTab selected={selected}>Log In</LoginModalTab>
|
||||
)}
|
||||
</Tab>
|
||||
<Tab>
|
||||
{({ selected }) => <LoginModalTab selected={selected}>Sign Up</LoginModalTab>}
|
||||
{({ selected }) => (
|
||||
<LoginModalTab selected={selected}>Sign Up</LoginModalTab>
|
||||
)}
|
||||
</Tab>
|
||||
</Tab.List>
|
||||
<Tab.Panels className="mt-4">
|
||||
@ -41,7 +50,8 @@ const LoginModal: FC<LoginModelProps> = ({ defaultPage, isOpen, onClose }) => {
|
||||
</Tab.Group>
|
||||
</Dialog.Panel>
|
||||
</div>
|
||||
</Dialog>)
|
||||
};
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
export default LoginModal;
|
||||
export default LoginModal
|
96
client/components/login/SignupForm.tsx
Normal file
96
client/components/login/SignupForm.tsx
Normal file
@ -0,0 +1,96 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { FC } from "react"
|
||||
import { SubmitHandler, useForm } from "react-hook-form"
|
||||
import { z } from "zod"
|
||||
|
||||
import FormField from "../common/form/FormField"
|
||||
import InlineLink from "../common/InlineLink"
|
||||
import Input from "../common/Input"
|
||||
import SubmitButton from "../common/form/SubmitButton"
|
||||
import useSignUpFlow from "../../hooks/useSignUpFlow"
|
||||
import * as validation from "../../config/validation"
|
||||
|
||||
const SignupFormSchema = z
|
||||
.object({
|
||||
csrfToken: z.string(),
|
||||
username: validation.username,
|
||||
password: validation.password,
|
||||
passwordRepeat: z.string().trim(),
|
||||
email: z.string().email({ message: "Not a valid email address" }).trim(),
|
||||
})
|
||||
.refine((data) => data.password === data.passwordRepeat, {
|
||||
message: "Passwords do not match.",
|
||||
path: ["passwordRepeat"],
|
||||
})
|
||||
|
||||
type SignupFormValues = z.infer<typeof SignupFormSchema>
|
||||
|
||||
const formFields = [
|
||||
{ id: "username", label: "Username", type: "text" },
|
||||
{ id: "password", label: "Password", type: "password" },
|
||||
{ id: "passwordRepeat", label: "Confirm Password", type: "password" },
|
||||
{ id: "email", label: "Email", type: "email" },
|
||||
]
|
||||
|
||||
const SignupForm: FC = () => {
|
||||
const signUpFlow = useSignUpFlow()
|
||||
const { register, handleSubmit, formState } = useForm<SignupFormValues>({
|
||||
resolver: zodResolver(SignupFormSchema),
|
||||
})
|
||||
|
||||
const onSubmit: SubmitHandler<SignupFormValues> = async (data) => {
|
||||
await signUpFlow.submitData({
|
||||
csrf_token: data.csrfToken,
|
||||
method: "password",
|
||||
password: data.password,
|
||||
traits: {
|
||||
email: data.email,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
|
||||
<p className="text-sm">
|
||||
Creating an account allows you to participate in chat, follow your
|
||||
favorite channels, and broadcast from your own channel.
|
||||
</p>
|
||||
{signUpFlow.flow && (
|
||||
<Input
|
||||
hidden={true}
|
||||
value={signUpFlow.flow.ui.nodes[0].attributes.value}
|
||||
{...register("csrfToken")}
|
||||
/>
|
||||
)}
|
||||
{formFields.map((field) => (
|
||||
<FormField
|
||||
key={field.id}
|
||||
id={field.id}
|
||||
type={field.type}
|
||||
label={field.label}
|
||||
{...register(field.id as any)}
|
||||
className="py-2 px-2 outline-2 w-full"
|
||||
bottomElement={
|
||||
<p className="text-xs">
|
||||
{formState.errors[(field.id as any) || ""]?.message}
|
||||
</p>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
<p className="text-sm text-center">
|
||||
By clicking Sign Up, you are agreeing to twitch-clone's{" "}
|
||||
<InlineLink to="https://tosdr.org/en/service/200">
|
||||
Terms of Service
|
||||
</InlineLink>
|
||||
.
|
||||
</p>
|
||||
<SubmitButton
|
||||
disabled={!signUpFlow.flow}
|
||||
className="w-full"
|
||||
value="Sign Up"
|
||||
/>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
export default SignupForm
|
21
client/components/message/ChatMessage.tsx
Normal file
21
client/components/message/ChatMessage.tsx
Normal file
@ -0,0 +1,21 @@
|
||||
import { FC } from "react"
|
||||
import { ChatMessage } from "../../types"
|
||||
|
||||
export interface ChatMessageProps {
|
||||
message: ChatMessage
|
||||
}
|
||||
|
||||
const ChatMessage: FC<ChatMessageProps> = ({
|
||||
message: { author, content },
|
||||
}) => {
|
||||
return (
|
||||
<div className="mx-2 p-2 hover:bg-neutral-700 text-sm rounded-md">
|
||||
<div className="space-x-1 inline">
|
||||
<span className="align-middle">{author}: </span>
|
||||
</div>
|
||||
<span className="break-all align-middle">{content}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ChatMessage
|
93
client/components/nav/NavBar.tsx
Normal file
93
client/components/nav/NavBar.tsx
Normal file
@ -0,0 +1,93 @@
|
||||
import {
|
||||
ArrowRightIcon,
|
||||
ArrowRightOnRectangleIcon,
|
||||
UserIcon,
|
||||
} from "@heroicons/react/24/outline"
|
||||
import { FC, useState } from "react"
|
||||
import { useLogout } from "../../hooks/useLogout"
|
||||
import useSession from "../../hooks/useSession"
|
||||
|
||||
import Button from "../common/Button"
|
||||
import Logo from "../common/Logo"
|
||||
import LoginModal, { LoginModelProps } from "../login/LoginModal"
|
||||
|
||||
const NavBar: FC = () => {
|
||||
const logout = useLogout()
|
||||
const session = useSession((state) => state.session)
|
||||
const [modalProps, setModalProps] = useState<LoginModelProps>({
|
||||
isOpen: false,
|
||||
defaultPage: 0,
|
||||
})
|
||||
|
||||
const showLoginTab = () =>
|
||||
setModalProps({
|
||||
defaultPage: 0,
|
||||
isOpen: true,
|
||||
})
|
||||
|
||||
const showSignupTab = () =>
|
||||
setModalProps({
|
||||
defaultPage: 1,
|
||||
isOpen: true,
|
||||
})
|
||||
|
||||
console.log({ session })
|
||||
return (
|
||||
<nav className="bg-zinc-800 w-screen font-semibold border-b border-b-black">
|
||||
<div className="flex flex-row justify-between items-center h-12 mx-2">
|
||||
<div>
|
||||
<ul className="flex flex-row space-x-8 items-center">
|
||||
<li>
|
||||
<Logo className="w-8 h-8" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<ul className="justify-end flex flex-row space-x-3 items-center">
|
||||
{session ? (
|
||||
<>
|
||||
<li>
|
||||
<UserIcon className="h-5 w-5 inline-block" />
|
||||
</li>
|
||||
<li>
|
||||
<Button
|
||||
variant="subtle"
|
||||
className="p-[0.4rem]"
|
||||
onClick={logout}
|
||||
>
|
||||
<ArrowRightOnRectangleIcon className="h-5 w-5 inline-block" />
|
||||
</Button>
|
||||
</li>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<li>
|
||||
<Button
|
||||
className="text-sm px-3 py-2 bg-neutral-700"
|
||||
onClick={showLoginTab}
|
||||
>
|
||||
Log In
|
||||
</Button>
|
||||
</li>
|
||||
<li>
|
||||
<Button
|
||||
className="text-sm px-3 py-2 bg-violet-500"
|
||||
onClick={showSignupTab}
|
||||
>
|
||||
Sign Up
|
||||
</Button>
|
||||
</li>
|
||||
</>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<LoginModal
|
||||
{...modalProps}
|
||||
onClose={() => setModalProps((old) => ({ ...old, isOpen: false }))}
|
||||
/>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
|
||||
export default NavBar
|
18
client/config/validation.ts
Normal file
18
client/config/validation.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { z } from "zod"
|
||||
|
||||
export const PASSWORD_REGEX =
|
||||
/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$ %^&*-]).{8,64}$/
|
||||
|
||||
export const username = z
|
||||
.string()
|
||||
.trim()
|
||||
.min(3, { message: "Username must be at least 3 character long." })
|
||||
.max(16, { message: "Username can't be longer than 16 characters.." })
|
||||
|
||||
export const password = z
|
||||
.string()
|
||||
.trim()
|
||||
.regex(
|
||||
PASSWORD_REGEX,
|
||||
"Password must be 8-64 long and must contain a number, uppercase, lowercase and special character.",
|
||||
)
|
53
client/hooks/useLogInFlow.ts
Normal file
53
client/hooks/useLogInFlow.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import {
|
||||
SelfServiceRegistrationFlow,
|
||||
SubmitSelfServiceLoginFlowBody,
|
||||
} from "@ory/client"
|
||||
import { useRouter } from "next/router"
|
||||
import { useEffect, useState } from "react"
|
||||
import ory from "../services/ory"
|
||||
import useSession from "./useSession"
|
||||
|
||||
const useLogInFlow = () => {
|
||||
const router = useRouter()
|
||||
const [flow, setFlow] = useState<SelfServiceRegistrationFlow>()
|
||||
const { flow: flowId } = router.query
|
||||
const updateSession = useSession((state) => state.update)
|
||||
|
||||
useEffect(() => {
|
||||
const func = async () => {
|
||||
if (!router.isReady || flow) {
|
||||
return
|
||||
}
|
||||
|
||||
let serviceFlow
|
||||
if (flowId) {
|
||||
serviceFlow = await ory.getSelfServiceLoginFlow(String(flowId))
|
||||
} else {
|
||||
serviceFlow = await ory.initializeSelfServiceLoginFlowForBrowsers()
|
||||
}
|
||||
|
||||
setFlow(serviceFlow.data)
|
||||
}
|
||||
|
||||
func()
|
||||
}, [flowId, router, router.isReady, flow])
|
||||
|
||||
const submitData = async (data: SubmitSelfServiceLoginFlowBody) => {
|
||||
await router.push(`/login?flow=${flow?.id}`, undefined, {
|
||||
shallow: true,
|
||||
})
|
||||
ory
|
||||
.submitSelfServiceLoginFlow(String(flow?.id), undefined, data)
|
||||
.then(async ({ data }) => {
|
||||
updateSession(data.session)
|
||||
await router.push(flow?.return_to || "/")
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log({ err })
|
||||
})
|
||||
}
|
||||
|
||||
return { flow, submitData }
|
||||
}
|
||||
|
||||
export default useLogInFlow
|
38
client/hooks/useLogout.ts
Normal file
38
client/hooks/useLogout.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { AxiosError } from "axios"
|
||||
import { useRouter } from "next/router"
|
||||
import { useState, useEffect, DependencyList } from "react"
|
||||
|
||||
import ory from "../services/ory"
|
||||
import useSession from "./useSession"
|
||||
|
||||
export function useLogout(deps?: DependencyList) {
|
||||
const session = useSession()
|
||||
const [logoutToken, setLogoutToken] = useState<string>("")
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
ory
|
||||
.createSelfServiceLogoutFlowUrlForBrowsers()
|
||||
.then(({ data }) => {
|
||||
setLogoutToken(data.logout_token)
|
||||
})
|
||||
.catch((err: AxiosError) => {
|
||||
switch (err.response?.status) {
|
||||
case 401:
|
||||
return
|
||||
}
|
||||
|
||||
return Promise.reject(err)
|
||||
})
|
||||
}, deps)
|
||||
|
||||
return () => {
|
||||
if (logoutToken) {
|
||||
session.drop()
|
||||
ory
|
||||
.submitSelfServiceLogoutFlow(logoutToken)
|
||||
.then(() => router.push("/"))
|
||||
.then(() => router.reload())
|
||||
}
|
||||
}
|
||||
}
|
31
client/hooks/useSession.ts
Normal file
31
client/hooks/useSession.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import create from "zustand"
|
||||
|
||||
import { Session } from "@ory/client"
|
||||
import ory from "../services/ory"
|
||||
import { AxiosError } from "axios"
|
||||
|
||||
export interface SessionState {
|
||||
session?: Session
|
||||
|
||||
load: () => void
|
||||
update: (data: Session) => void
|
||||
drop: () => void
|
||||
}
|
||||
const useSession = create<SessionState>((set) => ({
|
||||
session: undefined,
|
||||
|
||||
load: () => {
|
||||
ory
|
||||
.toSession()
|
||||
.then(({ data }) => {
|
||||
set({ session: data })
|
||||
})
|
||||
.catch((err: AxiosError) => {})
|
||||
},
|
||||
update: (session) => set({ session }),
|
||||
drop: () => {
|
||||
set({ session: undefined })
|
||||
},
|
||||
}))
|
||||
|
||||
export default useSession
|
55
client/hooks/useSignUpFlow.ts
Normal file
55
client/hooks/useSignUpFlow.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import {
|
||||
SelfServiceRegistrationFlow,
|
||||
Session,
|
||||
SubmitSelfServiceRegistrationFlowBody,
|
||||
} from "@ory/client"
|
||||
import { useRouter } from "next/router"
|
||||
import { useEffect, useState } from "react"
|
||||
import ory from "../services/ory"
|
||||
import useSession from "./useSession"
|
||||
|
||||
export const useSignUpFlow = () => {
|
||||
const router = useRouter()
|
||||
const [flow, setFlow] = useState<SelfServiceRegistrationFlow>()
|
||||
const { flow: flowId } = router.query
|
||||
const updateSession = useSession((state) => state.update)
|
||||
|
||||
useEffect(() => {
|
||||
const func = async () => {
|
||||
if (!router.isReady || flow) {
|
||||
return
|
||||
}
|
||||
|
||||
let serviceFlow
|
||||
if (flowId) {
|
||||
serviceFlow = await ory.getSelfServiceRegistrationFlow(String(flowId))
|
||||
} else {
|
||||
serviceFlow =
|
||||
await ory.initializeSelfServiceRegistrationFlowForBrowsers()
|
||||
}
|
||||
|
||||
setFlow(serviceFlow.data)
|
||||
}
|
||||
|
||||
func()
|
||||
}, [flowId, router, router.isReady, flow])
|
||||
|
||||
const submitData = async (data: SubmitSelfServiceRegistrationFlowBody) => {
|
||||
await router.push(`/signup?flow=${flow?.id}`, undefined, {
|
||||
shallow: true,
|
||||
})
|
||||
ory
|
||||
.submitSelfServiceRegistrationFlow(String(flow?.id), data)
|
||||
.then(async ({ data }) => {
|
||||
updateSession(data.session as Session)
|
||||
await router.push(flow?.return_to || "/")
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log({ err })
|
||||
})
|
||||
}
|
||||
|
||||
return { flow, submitData }
|
||||
}
|
||||
|
||||
export default useSignUpFlow
|
@ -1,4 +1,36 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
module.exports = {
|
||||
reactStrictMode: true
|
||||
// This file sets a custom webpack configuration to use your Next.js app
|
||||
// with Sentry.
|
||||
// https://nextjs.org/docs/api-reference/next.config.js/introduction
|
||||
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
|
||||
|
||||
const { withSentryConfig } = require("@sentry/nextjs")
|
||||
|
||||
const moduleExports = {
|
||||
// Your existing module.exports
|
||||
reactStrictMode: true,
|
||||
sentry: {
|
||||
// Use `hidden-source-map` rather than `source-map` as the Webpack `devtool`
|
||||
// for client-side builds. (This will be the default starting in
|
||||
// `@sentry/nextjs` version 8.0.0.) See
|
||||
// https://webpack.js.org/configuration/devtool/ and
|
||||
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#use-hidden-source-map
|
||||
// for more information.
|
||||
hideSourceMaps: true,
|
||||
},
|
||||
}
|
||||
|
||||
const sentryWebpackPluginOptions = {
|
||||
// Additional config options for the Sentry Webpack plugin. Keep in mind that
|
||||
// the following options are set automatically, and overriding them is not
|
||||
// recommended:
|
||||
// release, url, org, project, authToken, configFile, stripPrefix,
|
||||
// urlPrefix, include, ignore
|
||||
|
||||
silent: true, // Suppresses all logs
|
||||
// For all available options, see:
|
||||
// https://github.com/getsentry/sentry-webpack-plugin#options.
|
||||
}
|
||||
|
||||
// Make sure adding Sentry options is the last code to run before exporting, to
|
||||
// ensure that your source maps include changes from all other Webpack plugins
|
||||
module.exports = withSentryConfig(moduleExports, sentryWebpackPluginOptions)
|
||||
|
@ -21,6 +21,7 @@
|
||||
"@hookform/resolvers": "^2.9.8",
|
||||
"@ory/client": "0.0.1-alpha.169",
|
||||
"@ory/integrations": "0.2.5",
|
||||
"@sentry/nextjs": "^7.16.0",
|
||||
"axios": "^1.1.2",
|
||||
"clsx": "^1.2.1",
|
||||
"next": "12.1.5",
|
||||
@ -28,9 +29,12 @@
|
||||
"react-dom": "17.0.2",
|
||||
"react-hook-form": "^7.37.0",
|
||||
"tailwind-scrollbar": "2.1.0-preview.0",
|
||||
"zod": "^3.19.1"
|
||||
"zod": "^3.19.1",
|
||||
"zustand": "^4.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^7.6.0",
|
||||
"@sentry/cli": "^2.7.0",
|
||||
"@trivago/prettier-plugin-sort-imports": "^2.0.2",
|
||||
"@types/node": "16.11.6",
|
||||
"@types/react": "17.0.33",
|
||||
@ -38,7 +42,7 @@
|
||||
"cypress": "^9.6.0",
|
||||
"eslint": "7.32.0",
|
||||
"eslint-config-next": "12.0.1",
|
||||
"ory-prettier-styles": "^1.1.2",
|
||||
"ory-prettier-styles": "^1.3.0",
|
||||
"postcss": "^8.4.18",
|
||||
"prettier": "^2.3.2",
|
||||
"tailwindcss": "^3.1.8",
|
||||
|
@ -1,68 +1,39 @@
|
||||
import { ArrowRightIcon, HeartIcon, UserIcon } from '@heroicons/react/24/outline';
|
||||
|
||||
import Button from '../../components/Button';
|
||||
import ChatMessage from '../../components/ChatMessage';
|
||||
import Input from '../../components/Input';
|
||||
import { numFormatter } from '../../utils/format';
|
||||
import streams from '../../placeholder/GetStreams';
|
||||
import { NextPage } from 'next';
|
||||
import BrowseLayout from '../../components/BrowseLayout';
|
||||
import ChatMessage from "../../components/message/ChatMessage"
|
||||
import Input from "../../components/common/Input"
|
||||
import { NextPage } from "next"
|
||||
import BrowseLayout from "../../components/layout/BrowseLayout"
|
||||
import { createRandomMessage } from "../../placeholder/chatMessages"
|
||||
|
||||
const ChannelPage: NextPage = () => {
|
||||
const stream = streams.data[1];
|
||||
|
||||
return (
|
||||
<BrowseLayout>
|
||||
<div className="flex-1 flex flex-row">
|
||||
<div className="bg-neutral-900 flex-1">
|
||||
<div className="w-full h-auto aspect-video bg-red-200 " />
|
||||
<div className="flex flex-row p-4 space-x-3">
|
||||
<div className="w-20 h-20 bg-yellow-300 rounded-full" />
|
||||
<div className="flex-1">
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<div className="font-bold">{stream.user_name}</div>
|
||||
<div>
|
||||
<Button className="h-8 w-10">
|
||||
<HeartIcon className="text-gray-100 h-5 w-5 mx-auto" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<div className="space-y-1">
|
||||
<div className="font-bold">{stream.title}</div>
|
||||
<div className="text-violet-400">{stream.game_name}</div>
|
||||
</div>
|
||||
<div className="flex flex-row items-center text-sm space-x-3">
|
||||
<span>
|
||||
<UserIcon className="h-5 w-5 inline-block" />
|
||||
<span>{numFormatter.format(stream.viewer_count)}</span>
|
||||
</span>
|
||||
<span>{stream.started_at}</span>
|
||||
</div>
|
||||
<div className="flex-1 flex flex-row">
|
||||
<div className="bg-neutral-900 flex-1 flex flex-col">
|
||||
<div className="w-full bg-red-200 flex-1" />
|
||||
<div className="flex flex-row p-2 items-center justify-between">
|
||||
<div className="flex flex-row items-center space-x-3">
|
||||
<span className="w-8 h-8 bg-yellow-300 rounded-full" />
|
||||
<span className="font-bold">niku</span>
|
||||
</div>
|
||||
<div>1:14:32</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-zinc-900 w-80 border-l border-l-zinc-700 flex flex-col">
|
||||
<div className="flex flex-row justify-center items-center border-b border-b-zinc-700 p-2 h-12">
|
||||
<p className="uppercase font-semibold text-sm">Stream Chat</p>
|
||||
</div>
|
||||
<div className="flex-1 overflow-scrollbar">
|
||||
{new Array(60).fill(0).map((_, i) => (
|
||||
<ChatMessage message={createRandomMessage()} key={i} />
|
||||
))}
|
||||
</div>
|
||||
<div className="m-2">
|
||||
<Input className="w-full p-2" placeholder="Send a message" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-zinc-900 w-80 border-l border-l-zinc-700 flex flex-col">
|
||||
<div className="flex flex-row justify-between items-center border-b border-b-zinc-700 p-2">
|
||||
<Button variant="subtle" className="p-2">
|
||||
<ArrowRightIcon className="w-4 h-4" />
|
||||
</Button>
|
||||
<p className="uppercase font-semibold text-sm">Stream Chat</p>
|
||||
<div className="w-5" />
|
||||
</div>
|
||||
<div className="flex-1 overflow-scrollbar">
|
||||
{new Array(60).fill(0).map((_, i) => (
|
||||
<ChatMessage key={i} />
|
||||
))}
|
||||
</div>
|
||||
<div className="m-2">
|
||||
<Input className="w-full p-2" placeholder="Send a message" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BrowseLayout>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
export default ChannelPage;
|
||||
export default ChannelPage
|
||||
|
@ -1,7 +1,14 @@
|
||||
import '../styles/globals.css'
|
||||
import type { AppProps } from 'next/app'
|
||||
import "../styles/globals.css"
|
||||
import type { AppProps } from "next/app"
|
||||
import useSession from "../hooks/useSession"
|
||||
import { useEffect } from "react"
|
||||
|
||||
function MyApp({ Component, pageProps }: AppProps) {
|
||||
const loadSession = useSession((state) => state.load)
|
||||
useEffect(() => {
|
||||
loadSession()
|
||||
}, [loadSession])
|
||||
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
|
||||
|
39
client/pages/_error.js
Normal file
39
client/pages/_error.js
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* NOTE: This requires `@sentry/nextjs` version 7.3.0 or higher.
|
||||
*
|
||||
* NOTE: If using this with `next` version 12.2.0 or lower, uncomment the
|
||||
* penultimate line in `CustomErrorComponent`.
|
||||
*
|
||||
* This page is loaded by Nextjs:
|
||||
* - on the server, when data-fetching methods throw or reject
|
||||
* - on the client, when `getInitialProps` throws or rejects
|
||||
* - on the client, when a React lifecycle method throws or rejects, and it's
|
||||
* caught by the built-in Nextjs error boundary
|
||||
*
|
||||
* See:
|
||||
* - https://nextjs.org/docs/basic-features/data-fetching/overview
|
||||
* - https://nextjs.org/docs/api-reference/data-fetching/get-initial-props
|
||||
* - https://reactjs.org/docs/error-boundaries.html
|
||||
*/
|
||||
|
||||
import * as Sentry from "@sentry/nextjs"
|
||||
import NextErrorComponent from "next/error"
|
||||
|
||||
const CustomErrorComponent = (props) => {
|
||||
// If you're using a Nextjs version prior to 12.2.1, uncomment this to
|
||||
// compensate for https://github.com/vercel/next.js/issues/8592
|
||||
// Sentry.captureUnderscoreErrorException(props);
|
||||
|
||||
return <NextErrorComponent statusCode={props.statusCode} />
|
||||
}
|
||||
|
||||
CustomErrorComponent.getInitialProps = async (contextData) => {
|
||||
// In case this is running in a serverless function, await this in order to give Sentry
|
||||
// time to send the error before the lambda exits
|
||||
await Sentry.captureUnderscoreErrorException(contextData)
|
||||
|
||||
// This will contain the status code of the response
|
||||
return NextErrorComponent.getInitialProps(contextData)
|
||||
}
|
||||
|
||||
export default CustomErrorComponent
|
@ -1,26 +0,0 @@
|
||||
import { categories } from '../../placeholder/SearchCategories';
|
||||
|
||||
function ChannelPage() {
|
||||
const category = categories.data[0];
|
||||
return (
|
||||
<div className="flex-1 flex flex-row">
|
||||
<div className="bg-neutral-900 flex-1 text-gray-100">
|
||||
<div className="max-w-[200rem] mx-12 mt-12">
|
||||
<div className="flex flex-row items-center space-x-4">
|
||||
<img src={category.box_art_url} alt={category.name} />
|
||||
<div className="">
|
||||
<h1>{category.name}</h1>
|
||||
<div>
|
||||
<p>
|
||||
<span>603K</span> Viewers * <span>20.8M</span> Followers
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ChannelPage;
|
9
client/pages/index.tsx
Normal file
9
client/pages/index.tsx
Normal file
@ -0,0 +1,9 @@
|
||||
import { NextPage } from "next"
|
||||
import useSession from "../hooks/useSession"
|
||||
|
||||
const IndexPage: NextPage = () => {
|
||||
const session = useSession()
|
||||
return <div>{JSON.stringify(session.session || {})}</div>
|
||||
}
|
||||
|
||||
export default IndexPage
|
@ -1,13 +1,13 @@
|
||||
import { NextPage } from 'next';
|
||||
import { NextPage } from "next"
|
||||
|
||||
import LoginModal from '../components/LoginModal';
|
||||
import LoginModal from "../components/login/LoginModal"
|
||||
|
||||
const LoginPage: NextPage = () => {
|
||||
return (
|
||||
<div className="bg-neutral-900 w-screen h-screen">
|
||||
<LoginModal isOpen={true} defaultPage={0} onClose={() => {}} />
|
||||
<LoginModal isOpen={true} defaultPage={0} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default LoginPage;
|
||||
export default LoginPage
|
||||
|
@ -1,13 +1,12 @@
|
||||
|
||||
import { NextPage } from 'next';
|
||||
import LoginModal from '../components/LoginModal';
|
||||
import { NextPage } from "next"
|
||||
import LoginModal from "../components/login/LoginModal"
|
||||
|
||||
const SignupPage: NextPage = () => {
|
||||
return (
|
||||
<div className="bg-neutral-900 w-screen h-screen">
|
||||
<LoginModal isOpen={true} defaultPage={1} onClose={() => {}} />
|
||||
<LoginModal isOpen={true} defaultPage={1} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
export default SignupPage;
|
||||
export default SignupPage
|
||||
|
@ -1,44 +0,0 @@
|
||||
import { FollowedStreams } from '../types';
|
||||
|
||||
const streams: FollowedStreams = {
|
||||
data: [
|
||||
{
|
||||
id: '41375541868',
|
||||
user_id: '459331509',
|
||||
user_login: 'auronplay',
|
||||
user_name: 'auronplay',
|
||||
game_id: '494131',
|
||||
game_name: 'Little Nightmares',
|
||||
type: 'live',
|
||||
title: 'hablamos y le damos a Little Nightmares 1',
|
||||
viewer_count: 78365,
|
||||
started_at: '2021-03-10T15:04:21Z',
|
||||
language: 'es',
|
||||
thumbnail_url: 'https://static-cdn.jtvnw.net/previews-ttv/live_user_auronplay-250x250.jpg',
|
||||
tag_ids: [],
|
||||
is_mature: false,
|
||||
},
|
||||
{
|
||||
id: '41375541869',
|
||||
user_id: '459331510',
|
||||
user_login: 'xqcow',
|
||||
user_name: 'xqcow',
|
||||
game_id: '494131',
|
||||
game_name: 'Just Chatting',
|
||||
type: 'live',
|
||||
title: 'slam',
|
||||
viewer_count: 56230,
|
||||
started_at: '2022-09-29T14:04:21Z',
|
||||
language: 'en',
|
||||
thumbnail_url: 'https://static-cdn.jtvnw.net/previews-ttv/live_user_xqcow-250x250.jpg',
|
||||
tag_ids: [],
|
||||
is_mature: false,
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
cursor:
|
||||
'eyJiIjp7IkN1cnNvciI6ImV5SnpJam8zT0RNMk5TNDBORFF4TlRjMU1UY3hOU3dpWkNJNlptRnNjMlVzSW5RaU9uUnlkV1Y5In0sImEiOnsiQ3Vyc29yIjoiZXlKeklqb3hOVGs0TkM0MU56RXhNekExTVRZNU1ESXNJbVFpT21aaGJITmxMQ0owSWpwMGNuVmxmUT09In19',
|
||||
},
|
||||
};
|
||||
|
||||
export default streams;
|
@ -1,28 +0,0 @@
|
||||
import { UserFollows } from '../types';
|
||||
|
||||
export const following: UserFollows = {
|
||||
total: 4,
|
||||
data: [
|
||||
{
|
||||
from_id: '171003792',
|
||||
from_login: 'niku',
|
||||
from_name: 'niku',
|
||||
to_id: '23161357',
|
||||
to_name: 'LIRIK',
|
||||
to_login: 'lirik',
|
||||
followed_at: '2017-08-22T22:55:24Z',
|
||||
},
|
||||
{
|
||||
from_id: '171003792',
|
||||
from_login: 'niku',
|
||||
from_name: 'niku',
|
||||
to_id: '23161358',
|
||||
to_name: 'Cowser',
|
||||
to_login: 'cowser',
|
||||
followed_at: '2017-08-22T22:55:24Z',
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
cursor: 'eyJiIjpudWxsLCJhIjoiMTUwMzQ0MTc3NjQyNDQyMjAwMCJ9',
|
||||
},
|
||||
};
|
@ -1,12 +0,0 @@
|
||||
export const categories = {
|
||||
data: [
|
||||
{
|
||||
id: '33214',
|
||||
name: 'Just Chatting',
|
||||
box_art_url: 'https://static-cdn.jtvnw.net/ttv-boxart/509658-144x192.jpg',
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
cursor: 'eyJiIjpudWxsLCJhIjp7IkN',
|
||||
},
|
||||
};
|
9
client/placeholder/chatMessages.ts
Normal file
9
client/placeholder/chatMessages.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { ChatMessage } from "../types"
|
||||
import { faker } from "@faker-js/faker"
|
||||
|
||||
export const createRandomMessage = (): ChatMessage => {
|
||||
return {
|
||||
author: faker.name.firstName(),
|
||||
content: faker.lorem.words(10),
|
||||
}
|
||||
}
|
563
client/pnpm-lock.yaml
generated
563
client/pnpm-lock.yaml
generated
@ -1,11 +1,14 @@
|
||||
lockfileVersion: 5.4
|
||||
|
||||
specifiers:
|
||||
'@faker-js/faker': ^7.6.0
|
||||
'@headlessui/react': ^1.7.3
|
||||
'@heroicons/react': ^2.0.12
|
||||
'@hookform/resolvers': ^2.9.8
|
||||
'@ory/client': 0.0.1-alpha.169
|
||||
'@ory/integrations': 0.2.5
|
||||
'@sentry/cli': ^2.7.0
|
||||
'@sentry/nextjs': ^7.16.0
|
||||
'@trivago/prettier-plugin-sort-imports': ^2.0.2
|
||||
'@types/node': 16.11.6
|
||||
'@types/react': 17.0.33
|
||||
@ -16,7 +19,7 @@ specifiers:
|
||||
eslint: 7.32.0
|
||||
eslint-config-next: 12.0.1
|
||||
next: 12.1.5
|
||||
ory-prettier-styles: ^1.1.2
|
||||
ory-prettier-styles: ^1.3.0
|
||||
postcss: ^8.4.18
|
||||
prettier: ^2.3.2
|
||||
react: 17.0.2
|
||||
@ -26,6 +29,7 @@ specifiers:
|
||||
tailwindcss: ^3.1.8
|
||||
typescript: 4.4.4
|
||||
zod: ^3.19.1
|
||||
zustand: ^4.1.2
|
||||
|
||||
dependencies:
|
||||
'@headlessui/react': 1.7.3_sfoxds7t5ydpegc3knd667wn6m
|
||||
@ -33,6 +37,7 @@ dependencies:
|
||||
'@hookform/resolvers': 2.9.8_react-hook-form@7.37.0
|
||||
'@ory/client': 0.0.1-alpha.169
|
||||
'@ory/integrations': 0.2.5_sfoxds7t5ydpegc3knd667wn6m
|
||||
'@sentry/nextjs': 7.16.0_next@12.1.5+react@17.0.2
|
||||
axios: 1.1.2
|
||||
clsx: 1.2.1
|
||||
next: 12.1.5_sfoxds7t5ydpegc3knd667wn6m
|
||||
@ -41,8 +46,11 @@ dependencies:
|
||||
react-hook-form: 7.37.0_react@17.0.2
|
||||
tailwind-scrollbar: 2.1.0-preview.0_tailwindcss@3.1.8
|
||||
zod: 3.19.1
|
||||
zustand: 4.1.2_react@17.0.2
|
||||
|
||||
devDependencies:
|
||||
'@faker-js/faker': 7.6.0
|
||||
'@sentry/cli': 2.7.0
|
||||
'@trivago/prettier-plugin-sort-imports': 2.0.4_prettier@2.7.1
|
||||
'@types/node': 16.11.6
|
||||
'@types/react': 17.0.33
|
||||
@ -370,6 +378,11 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@faker-js/faker/7.6.0:
|
||||
resolution: {integrity: sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==}
|
||||
engines: {node: '>=14.0.0', npm: '>=6.0.0'}
|
||||
dev: true
|
||||
|
||||
/@headlessui/react/1.7.3_sfoxds7t5ydpegc3knd667wn6m:
|
||||
resolution: {integrity: sha512-LGp06SrGv7BMaIQlTs8s2G06moqkI0cb0b8stgq7KZ3xcHdH3qMP+cRyV7qe5x4XEW/IGY48BW4fLesD6NQLng==}
|
||||
engines: {node: '>=10'}
|
||||
@ -597,10 +610,185 @@ packages:
|
||||
- sass
|
||||
dev: false
|
||||
|
||||
/@rollup/plugin-sucrase/4.0.4_rollup@2.78.0:
|
||||
resolution: {integrity: sha512-YH4J8yoJb5EVnLhAwWxYAQNh2SJOR+SdZ6XdgoKEv6Kxm33riYkM8MlMaggN87UoISP52qAFyZ5ey56wu6umGg==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
rollup: ^2.53.1
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 4.2.1
|
||||
rollup: 2.78.0
|
||||
sucrase: 3.28.0
|
||||
dev: false
|
||||
|
||||
/@rollup/pluginutils/4.2.1:
|
||||
resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==}
|
||||
engines: {node: '>= 8.0.0'}
|
||||
dependencies:
|
||||
estree-walker: 2.0.2
|
||||
picomatch: 2.3.1
|
||||
dev: false
|
||||
|
||||
/@rushstack/eslint-patch/1.2.0:
|
||||
resolution: {integrity: sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==}
|
||||
dev: true
|
||||
|
||||
/@sentry/browser/7.16.0:
|
||||
resolution: {integrity: sha512-tJ063zvoF8Raw7mzQEXupOFPSN6v36WIbsDVGeFdToPCwViaBuATaxvWCrudGzsnBkMyItmTLJkzn9SEIXUOiw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
'@sentry/core': 7.16.0
|
||||
'@sentry/types': 7.16.0
|
||||
'@sentry/utils': 7.16.0
|
||||
tslib: 1.14.1
|
||||
dev: false
|
||||
|
||||
/@sentry/cli/1.74.5:
|
||||
resolution: {integrity: sha512-Ze1ec306ZWHtrxKypOJ8nhtFqkrx2f/6bRH+DcJzEQ3bBePQ0ZnqJTTe4BBHADYBtxFIaUWzCZ6DquLz2Zv/sw==}
|
||||
engines: {node: '>= 8'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
https-proxy-agent: 5.0.1
|
||||
mkdirp: 0.5.6
|
||||
node-fetch: 2.6.7
|
||||
npmlog: 4.1.2
|
||||
progress: 2.0.3
|
||||
proxy-from-env: 1.1.0
|
||||
which: 2.0.2
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@sentry/cli/2.7.0:
|
||||
resolution: {integrity: sha512-rSKPFun5mKxQCWOo3ERdhz9avdTsiz3A7GD5GcsML2iB0NQ5ErlNQIMFGC+8EXOHCjjsLSi13lh6cPeccz81nw==}
|
||||
engines: {node: '>= 12'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
https-proxy-agent: 5.0.1
|
||||
node-fetch: 2.6.7
|
||||
npmlog: 6.0.2
|
||||
progress: 2.0.3
|
||||
proxy-from-env: 1.1.0
|
||||
which: 2.0.2
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@sentry/core/7.16.0:
|
||||
resolution: {integrity: sha512-vq6H1b/IPTvzDD9coQ3wIudvSjkAYuUlXb1dv69dRlq4v3st9dcKBps1Zf0lQ1i4TVlDLoe1iGMmNFglMF1Q5w==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
'@sentry/types': 7.16.0
|
||||
'@sentry/utils': 7.16.0
|
||||
tslib: 1.14.1
|
||||
dev: false
|
||||
|
||||
/@sentry/integrations/7.16.0:
|
||||
resolution: {integrity: sha512-PJRmFUHOKMf1APOlwxGB7Z6LHzJP4xL6OLSoiwnruRuHaGvdyILA53fr/A6wRMSPyTxJDJpNkcN36cA56mLxYA==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
'@sentry/types': 7.16.0
|
||||
'@sentry/utils': 7.16.0
|
||||
localforage: 1.10.0
|
||||
tslib: 1.14.1
|
||||
dev: false
|
||||
|
||||
/@sentry/nextjs/7.16.0_next@12.1.5+react@17.0.2:
|
||||
resolution: {integrity: sha512-EqEfcL36TocxQZ820O2q01pF76oEEU4x8MzhRu4HrKByU7seUwU9m6a6YL8DmzcyJdenwL1HJK0Oyhg99pNcuw==}
|
||||
engines: {node: '>=8'}
|
||||
peerDependencies:
|
||||
next: ^10.0.8 || ^11.0 || ^12.0
|
||||
react: 15.x || 16.x || 17.x || 18.x
|
||||
webpack: '>= 4.0.0'
|
||||
peerDependenciesMeta:
|
||||
webpack:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@rollup/plugin-sucrase': 4.0.4_rollup@2.78.0
|
||||
'@sentry/core': 7.16.0
|
||||
'@sentry/integrations': 7.16.0
|
||||
'@sentry/node': 7.16.0
|
||||
'@sentry/react': 7.16.0_react@17.0.2
|
||||
'@sentry/tracing': 7.16.0
|
||||
'@sentry/types': 7.16.0
|
||||
'@sentry/utils': 7.16.0
|
||||
'@sentry/webpack-plugin': 1.19.0
|
||||
chalk: 3.0.0
|
||||
next: 12.1.5_sfoxds7t5ydpegc3knd667wn6m
|
||||
react: 17.0.2
|
||||
rollup: 2.78.0
|
||||
tslib: 1.14.1
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@sentry/node/7.16.0:
|
||||
resolution: {integrity: sha512-OC0TO6UTetv8IsX3zNhdeui7YVIQCnhkbfi+CMrB6YsHaMP2A9qH5gNyu/hKbaY9+4xci7e4rxyRmI65aKS9ow==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
'@sentry/core': 7.16.0
|
||||
'@sentry/types': 7.16.0
|
||||
'@sentry/utils': 7.16.0
|
||||
cookie: 0.4.2
|
||||
https-proxy-agent: 5.0.1
|
||||
lru_map: 0.3.3
|
||||
tslib: 1.14.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@sentry/react/7.16.0_react@17.0.2:
|
||||
resolution: {integrity: sha512-tJH5zO4MPopzqZgi7Yd4iIB9Am5uGVefgkHaoeCGXffveEVWqEdjj8TqPL36SBb76gCmtpa01NBDsUSDZ1w/yw==}
|
||||
engines: {node: '>=8'}
|
||||
peerDependencies:
|
||||
react: 15.x || 16.x || 17.x || 18.x
|
||||
dependencies:
|
||||
'@sentry/browser': 7.16.0
|
||||
'@sentry/types': 7.16.0
|
||||
'@sentry/utils': 7.16.0
|
||||
hoist-non-react-statics: 3.3.2
|
||||
react: 17.0.2
|
||||
tslib: 1.14.1
|
||||
dev: false
|
||||
|
||||
/@sentry/tracing/7.16.0:
|
||||
resolution: {integrity: sha512-8a9bViUY7oS35msBMouxkgz5OGd9NGutuKF7SQ8hPZwTcQPOxOwPyHccykgr56k6OmaDjGCLZMqZowaysJj+4g==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
'@sentry/core': 7.16.0
|
||||
'@sentry/types': 7.16.0
|
||||
'@sentry/utils': 7.16.0
|
||||
tslib: 1.14.1
|
||||
dev: false
|
||||
|
||||
/@sentry/types/7.16.0:
|
||||
resolution: {integrity: sha512-i6D+OK6d0l/k+VQvRp/Pt21WkDEgVBUIZq+sOkEZJczbcfexVdXKeXXoYTD2vYuFq8Yy28fzlsZaKI+NoH94yQ==}
|
||||
engines: {node: '>=8'}
|
||||
dev: false
|
||||
|
||||
/@sentry/utils/7.16.0:
|
||||
resolution: {integrity: sha512-3Zh1txg7IRp4kZAdG27YF7K6lD1IZyuAo9KjoPg1Xzqa4DOZyASJuEkbf+rK2a9T4HrtVHHXJUsNbKg8WM3VHg==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
'@sentry/types': 7.16.0
|
||||
tslib: 1.14.1
|
||||
dev: false
|
||||
|
||||
/@sentry/webpack-plugin/1.19.0:
|
||||
resolution: {integrity: sha512-qSpdgdGMtdzagGveSWgo2b+t8PdPUscuOjbOyWCsJme9jlTFnNk0rX7JEA55OUozikKHM/+vVh08USLBnPboZw==}
|
||||
engines: {node: '>= 8'}
|
||||
dependencies:
|
||||
'@sentry/cli': 1.74.5
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@trivago/prettier-plugin-sort-imports/2.0.4_prettier@2.7.1:
|
||||
resolution: {integrity: sha512-SCVUhQdbjn/Z4AY7b9JO00fZCeXxiVuarVxYP0n6cX2ijiQkE5HmGrOk32n0u385OebzQ9bZcrc51lAGLjXnFQ==}
|
||||
peerDependencies:
|
||||
@ -757,6 +945,14 @@ packages:
|
||||
engines: {node: '>=0.4.0'}
|
||||
hasBin: true
|
||||
|
||||
/agent-base/6.0.2:
|
||||
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
|
||||
engines: {node: '>= 6.0.0'}
|
||||
dependencies:
|
||||
debug: 4.3.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
/aggregate-error/3.1.0:
|
||||
resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
|
||||
engines: {node: '>=8'}
|
||||
@ -794,10 +990,14 @@ packages:
|
||||
type-fest: 0.21.3
|
||||
dev: true
|
||||
|
||||
/ansi-regex/2.1.1:
|
||||
resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/ansi-regex/5.0.1:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/ansi-styles/3.2.1:
|
||||
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
|
||||
@ -811,7 +1011,10 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
color-convert: 2.0.1
|
||||
dev: true
|
||||
|
||||
/any-promise/1.3.0:
|
||||
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
|
||||
dev: false
|
||||
|
||||
/anymatch/3.1.2:
|
||||
resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==}
|
||||
@ -820,10 +1023,28 @@ packages:
|
||||
normalize-path: 3.0.0
|
||||
picomatch: 2.3.1
|
||||
|
||||
/aproba/1.2.0:
|
||||
resolution: {integrity: sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==}
|
||||
|
||||
/arch/2.2.0:
|
||||
resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==}
|
||||
dev: true
|
||||
|
||||
/are-we-there-yet/1.1.7:
|
||||
resolution: {integrity: sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==}
|
||||
dependencies:
|
||||
delegates: 1.0.0
|
||||
readable-stream: 2.3.7
|
||||
dev: false
|
||||
|
||||
/are-we-there-yet/3.0.1:
|
||||
resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
|
||||
dependencies:
|
||||
delegates: 1.0.0
|
||||
readable-stream: 3.6.0
|
||||
dev: true
|
||||
|
||||
/arg/5.0.2:
|
||||
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
|
||||
|
||||
@ -958,7 +1179,6 @@ packages:
|
||||
|
||||
/balanced-match/1.0.2:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
dev: true
|
||||
|
||||
/base64-js/1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
@ -991,7 +1211,6 @@ packages:
|
||||
dependencies:
|
||||
balanced-match: 1.0.2
|
||||
concat-map: 0.0.1
|
||||
dev: true
|
||||
|
||||
/braces/3.0.2:
|
||||
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
|
||||
@ -1057,6 +1276,14 @@ packages:
|
||||
supports-color: 5.5.0
|
||||
dev: true
|
||||
|
||||
/chalk/3.0.0:
|
||||
resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
supports-color: 7.2.0
|
||||
dev: false
|
||||
|
||||
/chalk/4.1.2:
|
||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||
engines: {node: '>=10'}
|
||||
@ -1122,6 +1349,11 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
/code-point-at/1.1.0:
|
||||
resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/color-convert/1.9.3:
|
||||
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
|
||||
dependencies:
|
||||
@ -1133,7 +1365,6 @@ packages:
|
||||
engines: {node: '>=7.0.0'}
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
dev: true
|
||||
|
||||
/color-name/1.1.3:
|
||||
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
|
||||
@ -1142,6 +1373,11 @@ packages:
|
||||
/color-name/1.1.4:
|
||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
||||
|
||||
/color-support/1.1.3:
|
||||
resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/colorette/2.0.19:
|
||||
resolution: {integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==}
|
||||
dev: true
|
||||
@ -1152,6 +1388,11 @@ packages:
|
||||
dependencies:
|
||||
delayed-stream: 1.0.0
|
||||
|
||||
/commander/4.1.1:
|
||||
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
|
||||
engines: {node: '>= 6'}
|
||||
dev: false
|
||||
|
||||
/commander/5.1.0:
|
||||
resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==}
|
||||
engines: {node: '>= 6'}
|
||||
@ -1164,7 +1405,9 @@ packages:
|
||||
|
||||
/concat-map/0.0.1:
|
||||
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
|
||||
dev: true
|
||||
|
||||
/console-control-strings/1.1.0:
|
||||
resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
|
||||
|
||||
/convert-source-map/1.9.0:
|
||||
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
|
||||
@ -1309,7 +1552,6 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
ms: 2.1.2
|
||||
dev: true
|
||||
|
||||
/debug/4.3.4_supports-color@8.1.1:
|
||||
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
||||
@ -1343,6 +1585,9 @@ packages:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
/delegates/1.0.0:
|
||||
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
|
||||
|
||||
/detective/5.2.1:
|
||||
resolution: {integrity: sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==}
|
||||
engines: {node: '>=0.8.0'}
|
||||
@ -1391,7 +1636,6 @@ packages:
|
||||
|
||||
/emoji-regex/8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
dev: true
|
||||
|
||||
/emoji-regex/9.2.2:
|
||||
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
|
||||
@ -1752,6 +1996,10 @@ packages:
|
||||
engines: {node: '>=4.0'}
|
||||
dev: true
|
||||
|
||||
/estree-walker/2.0.2:
|
||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||
dev: false
|
||||
|
||||
/esutils/2.0.3:
|
||||
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -1913,7 +2161,6 @@ packages:
|
||||
|
||||
/fs.realpath/1.0.0:
|
||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||
dev: true
|
||||
|
||||
/fsevents/2.3.2:
|
||||
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
|
||||
@ -1943,6 +2190,33 @@ packages:
|
||||
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
|
||||
dev: true
|
||||
|
||||
/gauge/2.7.4:
|
||||
resolution: {integrity: sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==}
|
||||
dependencies:
|
||||
aproba: 1.2.0
|
||||
console-control-strings: 1.1.0
|
||||
has-unicode: 2.0.1
|
||||
object-assign: 4.1.1
|
||||
signal-exit: 3.0.7
|
||||
string-width: 1.0.2
|
||||
strip-ansi: 3.0.1
|
||||
wide-align: 1.1.5
|
||||
dev: false
|
||||
|
||||
/gauge/4.0.4:
|
||||
resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
|
||||
dependencies:
|
||||
aproba: 1.2.0
|
||||
color-support: 1.1.3
|
||||
console-control-strings: 1.1.0
|
||||
has-unicode: 2.0.1
|
||||
signal-exit: 3.0.7
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
wide-align: 1.1.5
|
||||
dev: true
|
||||
|
||||
/gensync/1.0.0-beta.2:
|
||||
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@ -1994,6 +2268,17 @@ packages:
|
||||
dependencies:
|
||||
is-glob: 4.0.3
|
||||
|
||||
/glob/7.1.6:
|
||||
resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==}
|
||||
dependencies:
|
||||
fs.realpath: 1.0.0
|
||||
inflight: 1.0.6
|
||||
inherits: 2.0.4
|
||||
minimatch: 3.1.2
|
||||
once: 1.4.0
|
||||
path-is-absolute: 1.0.1
|
||||
dev: false
|
||||
|
||||
/glob/7.1.7:
|
||||
resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==}
|
||||
dependencies:
|
||||
@ -2077,7 +2362,6 @@ packages:
|
||||
/has-flag/4.0.0:
|
||||
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/has-property-descriptors/1.0.0:
|
||||
resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==}
|
||||
@ -2097,12 +2381,21 @@ packages:
|
||||
has-symbols: 1.0.3
|
||||
dev: true
|
||||
|
||||
/has-unicode/2.0.1:
|
||||
resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
|
||||
|
||||
/has/1.0.3:
|
||||
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
|
||||
engines: {node: '>= 0.4.0'}
|
||||
dependencies:
|
||||
function-bind: 1.1.1
|
||||
|
||||
/hoist-non-react-statics/3.3.2:
|
||||
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
|
||||
dependencies:
|
||||
react-is: 16.13.1
|
||||
dev: false
|
||||
|
||||
/http-signature/1.2.0:
|
||||
resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==}
|
||||
engines: {node: '>=0.8', npm: '>=1.3.7'}
|
||||
@ -2121,6 +2414,15 @@ packages:
|
||||
sshpk: 1.17.0
|
||||
dev: true
|
||||
|
||||
/https-proxy-agent/5.0.1:
|
||||
resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
|
||||
engines: {node: '>= 6'}
|
||||
dependencies:
|
||||
agent-base: 6.0.2
|
||||
debug: 4.3.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
/human-signals/1.1.1:
|
||||
resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==}
|
||||
engines: {node: '>=8.12.0'}
|
||||
@ -2140,6 +2442,10 @@ packages:
|
||||
engines: {node: '>= 4'}
|
||||
dev: true
|
||||
|
||||
/immediate/3.0.6:
|
||||
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
|
||||
dev: false
|
||||
|
||||
/import-fresh/3.3.0:
|
||||
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
|
||||
engines: {node: '>=6'}
|
||||
@ -2163,11 +2469,9 @@ packages:
|
||||
dependencies:
|
||||
once: 1.4.0
|
||||
wrappy: 1.0.2
|
||||
dev: true
|
||||
|
||||
/inherits/2.0.4:
|
||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||
dev: true
|
||||
|
||||
/ini/2.0.0:
|
||||
resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==}
|
||||
@ -2231,10 +2535,16 @@ packages:
|
||||
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
/is-fullwidth-code-point/1.0.0:
|
||||
resolution: {integrity: sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
number-is-nan: 1.0.1
|
||||
dev: false
|
||||
|
||||
/is-fullwidth-code-point/3.0.0:
|
||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/is-glob/4.0.3:
|
||||
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||
@ -2318,9 +2628,12 @@ packages:
|
||||
call-bind: 1.0.2
|
||||
dev: true
|
||||
|
||||
/isarray/1.0.0:
|
||||
resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
|
||||
dev: false
|
||||
|
||||
/isexe/2.0.0:
|
||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||
dev: true
|
||||
|
||||
/isstream/0.1.2:
|
||||
resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==}
|
||||
@ -2446,10 +2759,20 @@ packages:
|
||||
type-check: 0.4.0
|
||||
dev: true
|
||||
|
||||
/lie/3.1.1:
|
||||
resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==}
|
||||
dependencies:
|
||||
immediate: 3.0.6
|
||||
dev: false
|
||||
|
||||
/lilconfig/2.0.6:
|
||||
resolution: {integrity: sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
/lines-and-columns/1.2.4:
|
||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||
dev: false
|
||||
|
||||
/listr2/3.14.0_enquirer@2.3.6:
|
||||
resolution: {integrity: sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
@ -2470,6 +2793,12 @@ packages:
|
||||
wrap-ansi: 7.0.0
|
||||
dev: true
|
||||
|
||||
/localforage/1.10.0:
|
||||
resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==}
|
||||
dependencies:
|
||||
lie: 3.1.1
|
||||
dev: false
|
||||
|
||||
/lodash.merge/4.6.2:
|
||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||
dev: true
|
||||
@ -2517,6 +2846,10 @@ packages:
|
||||
yallist: 4.0.0
|
||||
dev: true
|
||||
|
||||
/lru_map/0.3.3:
|
||||
resolution: {integrity: sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==}
|
||||
dev: false
|
||||
|
||||
/merge-stream/2.0.0:
|
||||
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
|
||||
dev: true
|
||||
@ -2551,23 +2884,36 @@ packages:
|
||||
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
|
||||
dependencies:
|
||||
brace-expansion: 1.1.11
|
||||
dev: true
|
||||
|
||||
/minimist/1.2.7:
|
||||
resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==}
|
||||
|
||||
/mkdirp/0.5.6:
|
||||
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
minimist: 1.2.7
|
||||
dev: false
|
||||
|
||||
/ms/2.0.0:
|
||||
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
||||
dev: true
|
||||
|
||||
/ms/2.1.2:
|
||||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
||||
dev: true
|
||||
|
||||
/ms/2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
dev: true
|
||||
|
||||
/mz/2.7.0:
|
||||
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
|
||||
dependencies:
|
||||
any-promise: 1.3.0
|
||||
object-assign: 4.1.1
|
||||
thenify-all: 1.6.0
|
||||
dev: false
|
||||
|
||||
/nanoid/3.3.4:
|
||||
resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
@ -2618,6 +2964,17 @@ packages:
|
||||
- '@babel/core'
|
||||
- babel-plugin-macros
|
||||
|
||||
/node-fetch/2.6.7:
|
||||
resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==}
|
||||
engines: {node: 4.x || >=6.0.0}
|
||||
peerDependencies:
|
||||
encoding: ^0.1.0
|
||||
peerDependenciesMeta:
|
||||
encoding:
|
||||
optional: true
|
||||
dependencies:
|
||||
whatwg-url: 5.0.0
|
||||
|
||||
/node-releases/2.0.6:
|
||||
resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==}
|
||||
dev: true
|
||||
@ -2638,6 +2995,30 @@ packages:
|
||||
path-key: 3.1.1
|
||||
dev: true
|
||||
|
||||
/npmlog/4.1.2:
|
||||
resolution: {integrity: sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==}
|
||||
dependencies:
|
||||
are-we-there-yet: 1.1.7
|
||||
console-control-strings: 1.1.0
|
||||
gauge: 2.7.4
|
||||
set-blocking: 2.0.0
|
||||
dev: false
|
||||
|
||||
/npmlog/6.0.2:
|
||||
resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
|
||||
dependencies:
|
||||
are-we-there-yet: 3.0.1
|
||||
console-control-strings: 1.1.0
|
||||
gauge: 4.0.4
|
||||
set-blocking: 2.0.0
|
||||
dev: true
|
||||
|
||||
/number-is-nan/1.0.1:
|
||||
resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/oauth-sign/0.9.0:
|
||||
resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==}
|
||||
dev: false
|
||||
@ -2707,7 +3088,6 @@ packages:
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||
dependencies:
|
||||
wrappy: 1.0.2
|
||||
dev: true
|
||||
|
||||
/onetime/5.1.2:
|
||||
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
|
||||
@ -2752,7 +3132,6 @@ packages:
|
||||
/path-is-absolute/1.0.1:
|
||||
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/path-key/3.1.1:
|
||||
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
|
||||
@ -2785,6 +3164,11 @@ packages:
|
||||
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
/pirates/4.0.5:
|
||||
resolution: {integrity: sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==}
|
||||
engines: {node: '>= 6'}
|
||||
dev: false
|
||||
|
||||
/postcss-import/14.1.0_postcss@8.4.18:
|
||||
resolution: {integrity: sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
@ -2871,10 +3255,13 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/process-nextick-args/2.0.1:
|
||||
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
||||
dev: false
|
||||
|
||||
/progress/2.0.3:
|
||||
resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
dev: true
|
||||
|
||||
/prop-types/15.8.1:
|
||||
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
|
||||
@ -2890,7 +3277,6 @@ packages:
|
||||
|
||||
/proxy-from-env/1.1.0:
|
||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||
dev: false
|
||||
|
||||
/psl/1.9.0:
|
||||
resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==}
|
||||
@ -2942,7 +3328,6 @@ packages:
|
||||
|
||||
/react-is/16.13.1:
|
||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||
dev: true
|
||||
|
||||
/react/17.0.2:
|
||||
resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==}
|
||||
@ -2956,6 +3341,27 @@ packages:
|
||||
dependencies:
|
||||
pify: 2.3.0
|
||||
|
||||
/readable-stream/2.3.7:
|
||||
resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==}
|
||||
dependencies:
|
||||
core-util-is: 1.0.2
|
||||
inherits: 2.0.4
|
||||
isarray: 1.0.0
|
||||
process-nextick-args: 2.0.1
|
||||
safe-buffer: 5.1.2
|
||||
string_decoder: 1.1.1
|
||||
util-deprecate: 1.0.2
|
||||
dev: false
|
||||
|
||||
/readable-stream/3.6.0:
|
||||
resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==}
|
||||
engines: {node: '>= 6'}
|
||||
dependencies:
|
||||
inherits: 2.0.4
|
||||
string_decoder: 1.1.1
|
||||
util-deprecate: 1.0.2
|
||||
dev: true
|
||||
|
||||
/readdirp/3.6.0:
|
||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
@ -3063,6 +3469,14 @@ packages:
|
||||
glob: 7.2.3
|
||||
dev: true
|
||||
|
||||
/rollup/2.78.0:
|
||||
resolution: {integrity: sha512-4+YfbQC9QEVvKTanHhIAFVUFSRsezvQF8vFOJwtGfb9Bb+r014S+qryr9PSmw8x6sMnPkmFBGAvIFVQxvJxjtg==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
hasBin: true
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
dev: false
|
||||
|
||||
/run-parallel/1.2.0:
|
||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||
dependencies:
|
||||
@ -3074,6 +3488,9 @@ packages:
|
||||
tslib: 2.4.0
|
||||
dev: true
|
||||
|
||||
/safe-buffer/5.1.2:
|
||||
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
|
||||
|
||||
/safe-buffer/5.2.1:
|
||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
||||
|
||||
@ -3107,6 +3524,9 @@ packages:
|
||||
lru-cache: 6.0.0
|
||||
dev: true
|
||||
|
||||
/set-blocking/2.0.0:
|
||||
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
||||
|
||||
/set-cookie-parser/2.5.1:
|
||||
resolution: {integrity: sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==}
|
||||
dev: false
|
||||
@ -3133,7 +3553,6 @@ packages:
|
||||
|
||||
/signal-exit/3.0.7:
|
||||
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
||||
dev: true
|
||||
|
||||
/slash/3.0.0:
|
||||
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
|
||||
@ -3186,6 +3605,15 @@ packages:
|
||||
safer-buffer: 2.1.2
|
||||
tweetnacl: 0.14.5
|
||||
|
||||
/string-width/1.0.2:
|
||||
resolution: {integrity: sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
code-point-at: 1.1.0
|
||||
is-fullwidth-code-point: 1.0.0
|
||||
strip-ansi: 3.0.1
|
||||
dev: false
|
||||
|
||||
/string-width/4.2.3:
|
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||
engines: {node: '>=8'}
|
||||
@ -3193,7 +3621,6 @@ packages:
|
||||
emoji-regex: 8.0.0
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
strip-ansi: 6.0.1
|
||||
dev: true
|
||||
|
||||
/string.prototype.matchall/4.0.7:
|
||||
resolution: {integrity: sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==}
|
||||
@ -3224,12 +3651,23 @@ packages:
|
||||
es-abstract: 1.20.4
|
||||
dev: true
|
||||
|
||||
/string_decoder/1.1.1:
|
||||
resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
|
||||
dependencies:
|
||||
safe-buffer: 5.1.2
|
||||
|
||||
/strip-ansi/3.0.1:
|
||||
resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
ansi-regex: 2.1.1
|
||||
dev: false
|
||||
|
||||
/strip-ansi/6.0.1:
|
||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
ansi-regex: 5.0.1
|
||||
dev: true
|
||||
|
||||
/strip-bom/3.0.0:
|
||||
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
|
||||
@ -3261,6 +3699,19 @@ packages:
|
||||
dependencies:
|
||||
react: 17.0.2
|
||||
|
||||
/sucrase/3.28.0:
|
||||
resolution: {integrity: sha512-TK9600YInjuiIhVM3729rH4ZKPOsGeyXUwY+Ugu9eilNbdTFyHr6XcAGYbRVZPDgWj6tgI7bx95aaJjHnbffag==}
|
||||
engines: {node: '>=8'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
commander: 4.1.1
|
||||
glob: 7.1.6
|
||||
lines-and-columns: 1.2.4
|
||||
mz: 2.7.0
|
||||
pirates: 4.0.5
|
||||
ts-interface-checker: 0.1.13
|
||||
dev: false
|
||||
|
||||
/supports-color/5.5.0:
|
||||
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
|
||||
engines: {node: '>=4'}
|
||||
@ -3273,7 +3724,6 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
has-flag: 4.0.0
|
||||
dev: true
|
||||
|
||||
/supports-color/8.1.1:
|
||||
resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
|
||||
@ -3345,6 +3795,19 @@ packages:
|
||||
engines: {node: '>=0.8'}
|
||||
dev: false
|
||||
|
||||
/thenify-all/1.6.0:
|
||||
resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
|
||||
engines: {node: '>=0.8'}
|
||||
dependencies:
|
||||
thenify: 3.3.1
|
||||
dev: false
|
||||
|
||||
/thenify/3.3.1:
|
||||
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
|
||||
dependencies:
|
||||
any-promise: 1.3.0
|
||||
dev: false
|
||||
|
||||
/throttleit/1.0.0:
|
||||
resolution: {integrity: sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==}
|
||||
dev: true
|
||||
@ -3386,6 +3849,13 @@ packages:
|
||||
psl: 1.9.0
|
||||
punycode: 2.1.1
|
||||
|
||||
/tr46/0.0.3:
|
||||
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
||||
|
||||
/ts-interface-checker/0.1.13:
|
||||
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
|
||||
dev: false
|
||||
|
||||
/tsconfig-paths/3.14.1:
|
||||
resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==}
|
||||
dependencies:
|
||||
@ -3397,7 +3867,6 @@ packages:
|
||||
|
||||
/tslib/1.14.1:
|
||||
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
|
||||
dev: true
|
||||
|
||||
/tslib/2.4.0:
|
||||
resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==}
|
||||
@ -3479,6 +3948,14 @@ packages:
|
||||
dependencies:
|
||||
punycode: 2.1.1
|
||||
|
||||
/use-sync-external-store/1.2.0_react@17.0.2:
|
||||
resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
dependencies:
|
||||
react: 17.0.2
|
||||
dev: false
|
||||
|
||||
/util-deprecate/1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
|
||||
@ -3505,6 +3982,15 @@ packages:
|
||||
core-util-is: 1.0.2
|
||||
extsprintf: 1.3.0
|
||||
|
||||
/webidl-conversions/3.0.1:
|
||||
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||
|
||||
/whatwg-url/5.0.0:
|
||||
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
||||
dependencies:
|
||||
tr46: 0.0.3
|
||||
webidl-conversions: 3.0.1
|
||||
|
||||
/which-boxed-primitive/1.0.2:
|
||||
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
|
||||
dependencies:
|
||||
@ -3521,7 +4007,11 @@ packages:
|
||||
hasBin: true
|
||||
dependencies:
|
||||
isexe: 2.0.0
|
||||
dev: true
|
||||
|
||||
/wide-align/1.1.5:
|
||||
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
|
||||
/word-wrap/1.2.3:
|
||||
resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==}
|
||||
@ -3548,7 +4038,6 @@ packages:
|
||||
|
||||
/wrappy/1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
dev: true
|
||||
|
||||
/xtend/4.0.2:
|
||||
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
|
||||
@ -3572,3 +4061,19 @@ packages:
|
||||
/zod/3.19.1:
|
||||
resolution: {integrity: sha512-LYjZsEDhCdYET9ikFu6dVPGp2YH9DegXjdJToSzD9rO6fy4qiRYFoyEYwps88OseJlPyl2NOe2iJuhEhL7IpEA==}
|
||||
dev: false
|
||||
|
||||
/zustand/4.1.2_react@17.0.2:
|
||||
resolution: {integrity: sha512-gcRaKchcxFPbImrBb/BKgujOhHhik9YhVpIeP87ETT7uokEe2Szu7KkuZ9ghjtD+/KKkcrRNktR2AiLXPIbKIQ==}
|
||||
engines: {node: '>=12.7.0'}
|
||||
peerDependencies:
|
||||
immer: '>=9.0'
|
||||
react: '>=16.8'
|
||||
peerDependenciesMeta:
|
||||
immer:
|
||||
optional: true
|
||||
react:
|
||||
optional: true
|
||||
dependencies:
|
||||
react: 17.0.2
|
||||
use-sync-external-store: 1.2.0_react@17.0.2
|
||||
dev: false
|
||||
|
17
client/sentry.client.config.js
Normal file
17
client/sentry.client.config.js
Normal file
@ -0,0 +1,17 @@
|
||||
// This file configures the initialization of Sentry on the browser.
|
||||
// The config you add here will be used whenever a page is visited.
|
||||
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
|
||||
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
|
||||
|
||||
Sentry.init({
|
||||
dsn: SENTRY_DSN || 'https://69c12baf84284b558f1aaea95321b6e5@o4504010426941440.ingest.sentry.io/4504010431397888',
|
||||
// Adjust this value in production, or use tracesSampler for greater control
|
||||
tracesSampleRate: 1.0,
|
||||
// ...
|
||||
// Note: if you want to override the automatic release value, do not set a
|
||||
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
|
||||
// that it will also get attached to your source maps
|
||||
});
|
4
client/sentry.properties
Normal file
4
client/sentry.properties
Normal file
@ -0,0 +1,4 @@
|
||||
defaults.url=https://sentry.io/
|
||||
defaults.org=niku-94
|
||||
defaults.project=twitch-clone-frontend
|
||||
cli.executable=./node_modules/.bin/sentry-cli
|
17
client/sentry.server.config.js
Normal file
17
client/sentry.server.config.js
Normal file
@ -0,0 +1,17 @@
|
||||
// This file configures the initialization of Sentry on the server.
|
||||
// The config you add here will be used whenever the server handles a request.
|
||||
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
|
||||
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
|
||||
|
||||
Sentry.init({
|
||||
dsn: SENTRY_DSN || 'https://69c12baf84284b558f1aaea95321b6e5@o4504010426941440.ingest.sentry.io/4504010431397888',
|
||||
// Adjust this value in production, or use tracesSampler for greater control
|
||||
tracesSampleRate: 1.0,
|
||||
// ...
|
||||
// Note: if you want to override the automatic release value, do not set a
|
||||
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
|
||||
// that it will also get attached to your source maps
|
||||
});
|
@ -1,52 +1,4 @@
|
||||
export interface Pagination {
|
||||
cursor: string;
|
||||
}
|
||||
|
||||
export interface UserFollow {
|
||||
followed_at: string;
|
||||
from_id: string;
|
||||
from_login: string;
|
||||
from_name: string;
|
||||
to_id: string;
|
||||
to_login: string;
|
||||
to_name: string;
|
||||
}
|
||||
|
||||
export interface UserFollows {
|
||||
total: number;
|
||||
data: UserFollow[];
|
||||
pagination: Pagination;
|
||||
}
|
||||
|
||||
export interface Stream {
|
||||
game_id: string;
|
||||
game_name: string;
|
||||
id: string;
|
||||
language: string;
|
||||
started_at: string;
|
||||
tag_ids: string[];
|
||||
thumbnail_url: string;
|
||||
title: string;
|
||||
type: string;
|
||||
user_id: string;
|
||||
user_login: string;
|
||||
user_name: string;
|
||||
viewer_count: number;
|
||||
is_mature: boolean;
|
||||
}
|
||||
|
||||
export interface FollowedStreams {
|
||||
data: Stream[];
|
||||
pagination: Pagination;
|
||||
}
|
||||
|
||||
export interface Category {
|
||||
id: string;
|
||||
name: string;
|
||||
box_art_url: string;
|
||||
}
|
||||
|
||||
export interface SearchCategories {
|
||||
data: Category[];
|
||||
pagination: Pagination;
|
||||
export interface ChatMessage {
|
||||
author: string
|
||||
content: string
|
||||
}
|
||||
|
15
dist/index.html
vendored
15
dist/index.html
vendored
@ -1,15 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + React + TS</title>
|
||||
<script type="module" crossorigin src="/assets/index.08ff9814.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index.3fce1f81.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user