Fixed up profile page (WIP)

This commit is contained in:
Fergal Moran
2023-02-27 20:17:50 +00:00
parent 0b7b09088c
commit 011784a737
26 changed files with 1477 additions and 250 deletions

13
.hintrc Normal file
View File

@@ -0,0 +1,13 @@
{
"extends": [
"development"
],
"hints": {
"axe/parsing": [
"default",
{
"duplicate-id-aria": "off"
}
]
}
}

1068
.working/layout.html Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"turbo": "NODE_OPTIONS='-r next-logger' next dev --turbo",
"dev": "NODE_OPTIONS='-r next-logger' node ./server.js",
"debug": "node ./server.js",
"dev-nossl": "next dev",
@@ -28,7 +29,7 @@
"firebase": "^9.17.1",
"firebase-functions": "^4.2.1",
"fireschema": "^4.0.4",
"next": "13.2.0",
"next": "^13.2.1",
"next-logger": "^3.0.1",
"next-seo": "^5.15.0",
"pino": "^8.11.0",

21
src/app/error.tsx Normal file
View File

@@ -0,0 +1,21 @@
"use client";
import logger from "@/lib/util/logging";
import React from "react";
const ErrorPage = ({ error, reset }: { error: Error; reset: () => void }) => {
React.useEffect(() => {
// Log the error to an error reporting service
console.error(error);
logger.error(error);
}, [error]);
return (
<div>
<div>An error occurred: {error.message}</div>
<button className="btn-danger btn" onClick={() => reset()}>
Retry?
</button>
</div>
);
};
export default ErrorPage;

View File

@@ -2,12 +2,16 @@
import React from "react";
import { themeChange } from "theme-change";
import "./globals.css";
import { Inter } from "@next/font/google";
import { Raleway } from "@next/font/google";
import { NavBar } from "@/components/layout";
import { AuthUserProvider } from "@/lib/auth/authUserContext";
import { Toaster } from "react-hot-toast";
const inter = Inter({ subsets: ["latin"] });
const font = Raleway({
weight: ["400", "700"],
subsets: ["latin"],
variable: "--font-raleway",
});
export default function RootLayout({
children,
@@ -20,13 +24,15 @@ export default function RootLayout({
return (
<html lang="en">
<head />
<body>
<AuthUserProvider>
<div className="w-full min-h-screen m-auto bg-base-100 text-base-content">
<div className="flex flex-col min-h-screen p-5 mx-auto max-w-7xl">
<body className={`${font.className}`}>
<Toaster />
<AuthUserProvider>
<div className="flex flex-col min-h-screen bg-base-100">
<div className="sticky top-0 z-30 flex justify-center flex-none w-full h-16 transition-all duration-100 bg-opacity-90 text-primary-content backdrop-blur">
<NavBar />
<main className="flex-1">{children}</main>
</div>
<div className="-mt-[4rem] grow place-items-center items-end bg-gradient-to-br from-primary to-secondary pt-20 text-primary-content ">
<main className="text-base-content">{children}</main>
</div>
</div>
</AuthUserProvider>

View File

@@ -1,68 +1,18 @@
import RemindMeButton from "@/components/widgets/RemindMeButton";
import { getMonthName, getTime } from "@/lib/util/dateUtils";
import logger from "@/lib/util/logging";
import { Show } from "@/models";
import React from "react";
import HomePageComponent from "@/components/pages/home/HomePageComponent";
const getData = async (): Promise<Show[]> => {
const getData = async () => {
// const res = await fetch(
// `${process.env.NEXT_PUBLIC_API_URL}/api/shows/upcoming`
// );
const res = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/api/shows/upcoming`
"https://otherway.dev.fergl.ie:3000/api/shows/upcoming"
);
logger.debug("getDate", res);
const data = await res.json();
return data.map((r: string) => Show.fromJson(r));
return await res.json();
};
const Home = async () => {
const results = await getData();
logger.debug("results", results);
return results.length === 0 ? (
<div className="min-h-screen hero bg-base-200">
<div className="text-center hero-content">
<div className="max-w-md">
<h1 className="text-5xl font-bold">No upcoming shows found</h1>
</div>
</div>
</div>
) : (
<div className="container flex justify-center h-screen py-20 mx-auto">
<div className="flex flex-col w-6/12 h-full pl-4">
<div className="px-5 py-2 text-sm font-bold text-gray-500 bg-white border-b border-gray-300 shadow">
Tracking events
</div>
<div
className="w-full h-full overflow-auto bg-white shadow"
id="journal-scroll"
>
<table className="w-full">
<tbody>
{results &&
results.map((show: Show) => (
<tr
key={show.id}
className="relative py-1 transform scale-100 border-b-2 border-blue-100 cursor-default text-md"
>
<td className="pl-5 pr-3 whitespace-no-wrap">
<div className="text-gray-400">
{`${new Date(show.date).getDay()} ${getMonthName(show.date)}`}
</div>
<div>{getTime(show.date)}</div>
</td>
<td className="px-2 py-4 space-y-2 whitespace-no-wrap">
<div className="font-medium leading-5 text-gray-500">
{show.creator}
</div>
<div className="leading-5 text-gray-900">{show.title}</div>
</td>
<td className="px-2 py-4">
<RemindMeButton showId={show.id} />
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
);
return <HomePageComponent shows={results} />;
};
export default Home;

View File

@@ -1,4 +1,4 @@
import { ProfilePageComponent } from "@/components/pages";
import { ProfilePageComponent } from "@/components/pages/profile";
const ProfilePage = () => {
return <ProfilePageComponent />;

View File

@@ -9,6 +9,7 @@ const LoginPage = () => {
useFirebaseAuth();
const router = useRouter();
const [error, setError] = React.useState("");
const [forgot, setForgot] = React.useState(false);
const [email, setEmail] = React.useState("");
const [password, setPassword] = React.useState("");

View File

@@ -1,18 +1,15 @@
"use client";
import React from "react";
import { BiLogInCircle } from "react-icons/bi";
import Link from "next/link";
import useFirebaseAuth from "@/lib/auth/useFirebaseAuth";
import { useAuthUserContext } from "@/lib/auth/authUserContext";
import Image from "next/image";
import { LogIn, LogOut, PlusSquare, Menu, User } from "react-feather";
import dynamic from "next/dynamic";
import Signup from "@/app/(auth)/signup/page";
const ThemeToggle = dynamic(
() => import("@/components/widgets/ui/theme/ThemeToggle"),
{
ssr: false
ssr: false,
}
);
const Navbar = () => {
@@ -22,18 +19,24 @@ const Navbar = () => {
<Link
href="/profile"
id="profile"
className="font-normal normal-case font-body btn-primary btn-sm btn"
className="gap-1 normal-case btn-ghost btn"
>
<User size={12} className="mr-2" />
<User
size={20}
className="inline-block w-5 h-5 stroke-current md:h-6 md:w-6"
/>
Profile
</Link>
<button
id="logout-btn"
className="btn-ghost btn-sm btn"
tabIndex={0}
className="gap-1 normal-case btn-ghost btn"
onClick={() => logOut()}
>
<LogOut size={12} className="mr-2" />
Logout
<LogOut
size={20}
className="inline-block w-5 h-5 stroke-current md:h-6 md:w-6"
/>
<span className="hidden md:inline">Logout</span>
</button>
</React.Fragment>
) : (
@@ -46,8 +49,15 @@ const Navbar = () => {
<PlusSquare size={12} className="mr-2" />
Register
</Link>
<Link href="/login" id="login" className="btn-ghost btn-sm btn">
<LogIn size={12} className="mr-2" />
<Link
href="/login"
id="login"
className="gap-1 normal-case btn-ghost btn"
>
<LogIn
size={20}
className="inline-block w-5 h-5 stroke-current md:h-6 md:w-6"
/>
Login
</Link>
</React.Fragment>
@@ -59,7 +69,7 @@ const Navbar = () => {
<Image src="/logo.png" alt="Otherway" width={48} height={48} />
</Link>
<div className="flex-col hidden ml-auto text-sm text-center font-body md:flex md:flex-row md:space-x-10">
{NavMenu}
{!loading && NavMenu}
</div>
<ThemeToggle />

View File

@@ -0,0 +1,35 @@
import Loading from "@/app/loading";
import { RemindMeButton } from "@/components/widgets";
import { getMonthName, getTime } from "@/lib/util/dateUtils";
import { Show } from "@/models";
import React from "react";
import NoShows from "./NoShows";
import UpcomingShowsTable from "./UpcomingShowsTable";
interface IHomePageComponentProps {
shows: Show[] | undefined;
}
const HomePageComponent = ({ shows }: IHomePageComponentProps) => {
const _getLayout = () => {
if (!shows) {
return <Loading />;
}
if (shows.length === 0) {
return <NoShows />;
}
return (
<div className="h-full pt-4 overflow-hidden">
<div className="justify-center flex-1 px-2 mx-2 md:flex md:justify-start">
<span className="text-2xl font-bold">Upcoming events</span>
</div>
<div className="mt-1 divider" />
<div className="flex justify-center mx-6 mt-4" id="journal-scroll">
<UpcomingShowsTable shows={shows} />
</div>
</div>
);
};
return _getLayout();
};
export default HomePageComponent;

View File

@@ -0,0 +1,15 @@
import React from "react";
const NoShows = () => {
return (
<div className="flex items-center justify-center flex-grow -mt-32">
<div className="text-center ">
<div className="max-w-md">
<h1 className="text-5xl font-bold">No upcoming shows found</h1>
</div>
</div>
</div>
);
};
export default NoShows;

View File

@@ -0,0 +1,44 @@
import React from "react";
import { RemindMeButton } from "@/components/widgets";
import { getMonthName, getTime } from "@/lib/util/dateUtils";
import { Show } from "@/models";
interface IUpcomingShowsTableProps {
shows: Show[];
}
const UpcomingShowsTable = ({ shows }: IUpcomingShowsTableProps) => {
return (
<table className="table w-full">
{/* head */}
<thead>
<tr>
<th>Who?</th>
<th>When?</th>
<th>What?</th>
<th></th>
</tr>
</thead>
<tbody>
{/* row 1 */}
{shows &&
shows.map((show: Show) => (
<tr key={show.id}>
<th>{show.creator}</th>
<td className="pl-5 pr-3 whitespace-no-wrap">
<div className="text-gray-400">
{`${new Date(show.date).getDay()} ${getMonthName(show.date)}`}{" "}
@ {getTime(show.date)}
</div>
</td>
<td>{show.title}</td>
<th>
<RemindMeButton showId={show.id} />
</th>
</tr>
))}
</tbody>
</table>
);
};
export default UpcomingShowsTable;

View File

View File

@@ -4,11 +4,9 @@ import { useRouter } from "next/navigation";
import { User, Bell } from "react-feather";
import classNames from "classnames";
import { useAuthUserContext } from "@/lib/auth/authUserContext";
import useFirebaseAuth from "@/lib/auth/useFirebaseAuth";
import { ImageUpload, InputText } from "../widgets/inputs";
import { HeadingSubComponent } from "../widgets/text";
import ProfilePageComponentProfile from "./ProfilePageComponentProfile";
import ProfilePageComponentNotifications from "./ProfilePageComponentNotifications";
const ProfilePageComponent = () => {
const { profile, loading } = useAuthUserContext();
const router = useRouter();
@@ -42,8 +40,11 @@ const ProfilePageComponent = () => {
return <div>Rerouting</div>;
} else if (!loading && profile) {
return (
<div className="overflow-hidden rounded-lg shadow bg-base-100 text-base-content">
<h1>{selectedItem}</h1>
<div className="pt-4 overflow-hidden">
<div className="justify-center flex-1 px-2 mx-2 md:flex md:justify-start">
<span className="text-2xl font-bold">Your Profile</span>
</div>
<div className="mt-1 divider" />
<div className="divide-y lg:grid lg:grid-cols-12 lg:divide-y-0 lg:divide-x">
<aside className="py-6 lg:col-span-3">
<nav className="space-y-1">

View File

@@ -1,8 +1,6 @@
import React from "react";
import { HeadingSubComponent } from "@/components/widgets/text";
import { InputText } from "@/components/widgets/inputs";
import { PhoneNumberContextImpl } from "twilio/lib/rest/lookups/v2/phoneNumber";
import { PhoneNumber } from "../widgets/notifications";
import { PhoneNumber } from "@/components/widgets/notifications";
const ProfilePageComponentNotifications = () => {
return (

View File

@@ -1,18 +1,47 @@
"use client";
import { InputText } from "@/components/widgets/inputs";
import { HeadingSubComponent } from "@/components/widgets/text";
import { useAuthUserContext } from "@/lib/auth/authUserContext";
import db, { users } from "@/lib/db";
import { debug } from "console";
import { doc, setDoc } from "firebase/firestore";
import React from "react";
import { InputText } from "../widgets/inputs";
import { HeadingSubComponent } from "../widgets/text";
const ProfilePageComponentProfile = () => {
const { loading, profile } = useAuthUserContext();
const [sendReminders, setSendReminders] = React.useState(false);
const [userName, setUserName] = React.useState("");
const [email, setEmail] = React.useState("");
const [password, setPassword] = React.useState("");
const [about, setAbout] = React.useState("");
const [displayName, setDisplayName] = React.useState("");
const [url, setUrl] = React.useState("");
const [image, setImage] = React.useState("");
React.useEffect(() => {
console.log("ProfilePageComponentProfile", "useEffect", profile);
if (profile) {
setEmail(profile.email as string);
setDisplayName(profile.displayName as string);
setAbout(profile.about as string);
}
}, [profile]);
const _submitProfileForm = async ($event: React.SyntheticEvent) => {
$event.preventDefault();
const result = await setDoc(
doc(users, profile?.id),
Object.assign(
{},
{
email,
displayName,
about: about || "",
lastSeen: new Date(),
}
),
{ merge: true }
);
console.log("ProfilePageComponentProfile", "_submitProfileForm", result);
};
return (
<form className="space-y-8 divide-y ">
<form className="space-y-8 divide-y" onSubmit={_submitProfileForm}>
<div className="space-y-8 divide-y sm:space-y-5">
<div>
<div>
@@ -22,20 +51,22 @@ const ProfilePageComponentProfile = () => {
share.
</p>
</div>
<div className="mt-6 space-y-6 sm:mt-5 sm:space-y-5">
<div className="space-x-3 sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:border-t sm:pt-5">
<HeadingSubComponent
title="Username"
subHeading="The username that you would like to use to login to the site. This could be your email address"
title="Display Name"
subHeading="The name you would like others to see you as."
/>
<div className="mt-1 sm:col-span-2 sm:mt-0">
<div className="flex max-w-lg rounded-md shadow-sm">
<InputText
id="username"
labelTitle="Username"
defaultValue={userName}
updateFormValue={(v) => setUserName(v)}
id="displayname"
type="text"
labelTitle="Display name"
value={displayName}
updateFormValue={(v) => {
setDisplayName(v);
}}
showLabel={false}
/>
</div>
@@ -52,7 +83,7 @@ const ProfilePageComponentProfile = () => {
id="email"
type="email"
labelTitle="Email address"
defaultValue={email}
value={email}
updateFormValue={(v) => setEmail(v)}
showLabel={false}
/>
@@ -71,7 +102,7 @@ const ProfilePageComponentProfile = () => {
id="about"
type="textarea"
labelTitle="About"
defaultValue={about}
value={about}
updateFormValue={(v) => setAbout(v)}
showLabel={false}
/>

View File

@@ -6,7 +6,7 @@ interface IInputTextProps {
labelStyle?: string;
type?: string;
containerStyle?: string;
defaultValue: string;
value: string;
placeholder?: string;
showLabel?: boolean;
updateFormValue: (value: string) => void;
@@ -17,15 +17,13 @@ const InputText = ({
labelStyle,
type,
containerStyle,
defaultValue,
value,
placeholder,
updateFormValue,
showLabel = true,
}: IInputTextProps) => {
const [value, setValue] = React.useState(defaultValue);
const updateInputValue = (val: string) => {
setValue(val);
updateFormValue(val);
};
const _getId = () => (type === "text" ? `inp_${id}` : `ta_${id}`);
@@ -36,16 +34,18 @@ const InputText = ({
name={_getId()}
rows={3}
className="w-full h-24 textarea-bordered textarea"
defaultValue={defaultValue}
placeholder={placeholder || ""}
defaultValue={value}
onChange={(e) => updateInputValue(e.target.value)}
/>
) : (
<input
id={_getId()}
type={type || "text"}
value={value}
placeholder={placeholder || ""}
onChange={(e) => updateInputValue(e.target.value)}
className="w-full input-bordered input"
type={type || "text"}
placeholder={placeholder || ""}
value={value}
onChange={(e) => updateInputValue(e.target.value)}
/>
);
return (

View File

@@ -1,21 +1,23 @@
import { useEffect, useState } from "react";
import { useEffect, useState, useCallback } from "react";
import {
createUserWithEmailAndPassword,
FacebookAuthProvider,
getAuth,
GoogleAuthProvider, linkWithPopup, OAuthProvider,
GoogleAuthProvider,
linkWithPopup,
OAuthProvider,
onAuthStateChanged,
signInWithEmailAndPassword,
signInWithPopup, signInWithRedirect,
signInWithPopup,
signOut,
TwitterAuthProvider, UserCredential
TwitterAuthProvider,
UserCredential,
} from "firebase/auth";
import { app } from "./firebase";
import { useRouter } from "next/navigation";
import { Profile } from "@/models";
import { FirebaseAuth } from "@firebase/auth-types";
import firebase from "firebase/app";
import { users } from "../db";
import { doc, setDoc } from "firebase/firestore";
export default function useFirebaseAuth() {
const [profile, setProfile] = useState<Profile | undefined>();
@@ -24,7 +26,7 @@ export default function useFirebaseAuth() {
const [loading, setLoading] = useState(true);
const getUserProfile = (): Profile | undefined => {
const getUserProfile = useCallback(() => {
if (auth.currentUser !== null) {
// The user object has basic properties such as display name, email, etc.
// Going forward we may look this up from the user table in firestore
@@ -33,36 +35,43 @@ export default function useFirebaseAuth() {
auth.currentUser.email,
auth.currentUser.displayName,
auth.currentUser.photoURL,
auth.currentUser.emailVerified
auth.currentUser.emailVerified,
new Date()
);
setProfile(profile);
setDoc(doc(users, auth.currentUser.uid), Object.assign({}, profile), {
merge: true,
});
return profile;
}
};
const authStateChanged = async (user: any) => {
}, [auth.currentUser]);
const authStateChanged = useCallback(
(user: any) => {
if (user) {
setLoading(false);
setLoading(true);
const profile = getUserProfile();
setProfile(profile);
return;
}
};
setLoading(false);
},
[getUserProfile]
);
const clear = () => {
setProfile(undefined);
setLoading(true);
};
const signIn = (email: string, password: string): Promise<> =>
const signIn = (email: string, password: string) =>
signInWithEmailAndPassword(auth, email, password);
const signUp = (email: string, password: string) =>
createUserWithEmailAndPassword(auth, email, password);
const logOut = () =>
signOut(auth).then(clear);
const logOut = () => signOut(auth).then(clear);
const _processSignIn = async (provider: any): Promise<UserCredential | undefined> => {
const _processSignIn = async (
provider: any
): Promise<UserCredential | undefined> => {
try {
const result = await signInWithPopup(auth, provider);
return result;
@@ -73,11 +82,19 @@ export default function useFirebaseAuth() {
console.log("useFirebaseAuth", "_processSignIn_duplicateAccount", err);
const auth = getAuth();
if (auth?.currentUser) {
linkWithPopup(auth.currentUser, provider).then((result) => {
const credential = GoogleAuthProvider.credentialFromResult(result);
linkWithPopup(auth.currentUser, provider)
.then((result) => {
const credential =
GoogleAuthProvider.credentialFromResult(result);
return credential;
}).catch((error) => {
console.log("useFirebaseAuth", "_processSignIn", "Failure in _processSignIn", err);
})
.catch((error) => {
console.log(
"useFirebaseAuth",
"_processSignIn",
"Failure in _processSignIn",
err
);
});
}
}
@@ -114,7 +131,7 @@ export default function useFirebaseAuth() {
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, authStateChanged);
return unsubscribe;
}, []);
}, [auth, getUserProfile]);
return {
profile,
@@ -125,6 +142,6 @@ export default function useFirebaseAuth() {
signInWithGoogle,
signInWithTwitter,
signInWithFacebook,
getUserProfile
getUserProfile,
};
}

View File

@@ -1,4 +1,4 @@
export const defaults = {
defaultTheme: "fantasy",
defaultTheme: "synthwave",
defaultDarkTheme: "luxury",
};

View File

@@ -1,4 +1,3 @@
import serviceAccount from "serviceAccount.json";
import { initializeApp } from "firebase/app";
import {
getFirestore,
@@ -6,7 +5,9 @@ import {
collection,
DocumentData,
WithFieldValue,
QueryDocumentSnapshot, SnapshotOptions, Timestamp
QueryDocumentSnapshot,
SnapshotOptions,
Timestamp,
} from "firebase/firestore";
const firebaseConfig = {
@@ -16,7 +17,7 @@ const firebaseConfig = {
storageBucket: "radio-otherway.appspot.com",
messagingSenderId: "47147490249",
appId: "1:47147490249:web:a84515b3ce1c481826e618",
measurementId: "G-12YB78EZM4"
measurementId: "G-12YB78EZM4",
};
export const firebaseApp = initializeApp(firebaseConfig);
const firestore = getFirestore();
@@ -27,7 +28,9 @@ const showConverter = {
toFirestore(show: WithFieldValue<Show>): DocumentData {
return {
...show,
date: Timestamp.fromDate(<Date>show.date)
date: show.date
? Timestamp.fromDate(new Date(show.date as string))
: new Date(),
};
},
fromFirestore(
@@ -35,20 +38,18 @@ const showConverter = {
options: SnapshotOptions
): Show {
const data = snapshot.data(options)!;
return new Show(
snapshot.id,
data.title,
data.date.toDate(),
data.creator);
}
return new Show(snapshot.id, data.title, data.date.toDate(), data.creator);
},
};
// Import all your model types
import { Show, Reminder, RemindersProcessed } from "@/models";
import { Show, Reminder, RemindersProcessed, Profile } from "@/models";
// export all your collections
export const shows = createCollection<Show>("shows")
.withConverter(showConverter);
export const users = createCollection<Profile>("users");
export const shows =
createCollection<Show>("shows").withConverter(showConverter);
export const reminders = createCollection<Reminder>("reminders");
export const remindersProcessed = createCollection<RemindersProcessed>("reminders");
export const remindersProcessed =
createCollection<RemindersProcessed>("reminders");
export default firestore;

View File

@@ -4,12 +4,22 @@ export default class Profile {
displayName: string | null;
photoURL: string | null;
emailVerified: boolean;
constructor(id: string, email: string | null, displayName: string | null, photoURL: string | null, emailVerified: boolean) {
about?: String;
lastSeen: Date;
constructor(
id: string,
email: string | null,
displayName: string | null,
photoURL: string | null,
emailVerified: boolean,
lastSeen?: Date
) {
this.id = id;
this.email = email;
this.displayName = displayName;
this.photoURL = photoURL;
this.emailVerified = emailVerified;
this.lastSeen = lastSeen || new Date();
}
}

View File

@@ -19,7 +19,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
}, { merge: true });
}
logger.debug("Stored show", res);
res.status(200).json({ status: "OK" });
res.status(200).json({ status: "OK", entries });
} catch (err) {
logger.error(err);
res.status(500).json({status: "Error"});

View File

@@ -32,7 +32,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const reminder = r.data() as Reminder;
for (let notification of reminder.notifications) {
const targetDate = addSeconds(new Date(), notification.secondsBefore);
const differenceInSeconds = dateDifferenceInSeconds(targetDate, show.date);
const differenceInSeconds = dateDifferenceInSeconds(targetDate, new Date(show.date));
if (differenceInSeconds >= 0) {
//time to fire off a notification
await sendSMS("353868065119", "New show starting in 1 hour");

View File

@@ -11,7 +11,7 @@ module.exports = {
// ],
plugins: [require("daisyui")],
daisyui: {
themes: ["fantasy", "luxury"],
// themes: ["fantasy", "luxury", "synthwave"],
darkTheme: "luxury",
},
};

183
yarn.lock
View File

@@ -488,10 +488,10 @@
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
"@next/env@13.2.0":
version "13.2.0"
resolved "https://registry.yarnpkg.com/@next/env/-/env-13.2.0.tgz#1a597a885ce11860446c88e1098fd517dc0e84b1"
integrity sha512-yv9oaRVa+AxFa27uQOVecS931NrE+GcQSqcL2HaRxL8NunStLtPiyNm/VixvdzfiWLabMz4dXvbXfwCNaECzcw==
"@next/env@13.2.1":
version "13.2.1"
resolved "https://registry.yarnpkg.com/@next/env/-/env-13.2.1.tgz#082d42cfc0c794e9185d7b4133d71440ba2e795d"
integrity sha512-Hq+6QZ6kgmloCg8Kgrix+4F0HtvLqVK3FZAnlAoS0eonaDemHe1Km4kwjSWRE3JNpJNcKxFHF+jsZrYo0SxWoQ==
"@next/eslint-plugin-next@13.1.5":
version "13.1.5"
@@ -505,70 +505,70 @@
resolved "https://registry.yarnpkg.com/@next/font/-/font-13.2.0.tgz#677b3fc67243bccbae94d7d1e96a494be98206c4"
integrity sha512-pWoegIxqegV+9+gFmRCZao6xhA2m3kKS34lMXqShJ5ibRuyHkP/tfDE82LzYZmVQ3p51ZrkwTugNwy/ohiE2cA==
"@next/swc-android-arm-eabi@13.2.0":
version "13.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.2.0.tgz#241d007fdb2f06f70ab21d5a333e08a29de9cd7f"
integrity sha512-VMetUwBWtDBGzNiOkhiWTP+99ZYW5NVRpIGlUsldEtY8IQIqleaUgW9iamsO0kDSjhWNdCQCB+xu5HcCvmDTww==
"@next/swc-android-arm-eabi@13.2.1":
version "13.2.1"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.2.1.tgz#67f2580fbbe05ee006220688972c5e3a555fc741"
integrity sha512-Yua7mUpEd1wzIT6Jjl3dpRizIfGp9NR4F2xeRuQv+ae+SDI1Em2WyM9m46UL+oeW5GpMiEHoaBagr47RScZFmQ==
"@next/swc-android-arm64@13.2.0":
version "13.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-13.2.0.tgz#924e79197f094a12ac3409b6a416f84c2f74341d"
integrity sha512-fAiP54Om3fSj5aKntxEvW5fWzyMUzLzjFrHuUt5jBnTRWM4QikhLy547OZDoxycyk4GoQVHmNMSA3hILsrV/dQ==
"@next/swc-android-arm64@13.2.1":
version "13.2.1"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-13.2.1.tgz#460a02b69eb23bb5f402266bcea9cadae59415c1"
integrity sha512-Bifcr2f6VwInOdq1uH/9lp8fH7Nf7XGkIx4XceVd32LPJqG2c6FZU8ZRBvTdhxzXVpt5TPtuXhOP4Ij9UPqsVw==
"@next/swc-darwin-arm64@13.2.0":
version "13.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.2.0.tgz#bfd3dfe90903b3bbf81f617f2b1d4f8b9e20e8aa"
integrity sha512-F4zbvPnq3zCTqyyM6WN8ledazzJx3OrxIdc2ewnqnfk6tjBZ/aq1M27GhEfylGjZG1KvbtJCxUqi7dR/6R94bA==
"@next/swc-darwin-arm64@13.2.1":
version "13.2.1"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.2.1.tgz#8b8530ff417802027471aee2419f78a58a863ccb"
integrity sha512-gvqm+fGMYxAkwBapH0Vvng5yrb6HTkIvZfY4oEdwwYrwuLdkjqnJygCMgpNqIFmAHSXgtlWxfYv1VC8sjN81Kw==
"@next/swc-darwin-x64@13.2.0":
version "13.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.2.0.tgz#3d159bb2889f093d173546a6e5edd6260df7e156"
integrity sha512-Y9+fB7TLAAnkCZQXWjwJg5bi1pT5NuNkI+HoKYp26U1J0SxW5vZWFGc31WFmmHIz3wA0zlaQfRa4mF7cpZL5yw==
"@next/swc-darwin-x64@13.2.1":
version "13.2.1"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.2.1.tgz#80aebb3329a1e4568a28de1ee177780b3d50330c"
integrity sha512-HGqVqmaZWj6zomqOZUVbO5NhlABL0iIaxTmd0O5B0MoMa5zpDGoaHSG+fxgcWMXcGcxmUNchv1NfNOYiTKoHOg==
"@next/swc-freebsd-x64@13.2.0":
version "13.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.2.0.tgz#33877ad933e1b3d7776dfb060f4e3b55f675523e"
integrity sha512-b9bCLlfznbV6e6Vg9wKYZJs7Uz8z/Py9105MYq95a3JlHiI3e/fvBpm1c7fe5QlvWJlqyNav6Clyu1W+lDk+IQ==
"@next/swc-freebsd-x64@13.2.1":
version "13.2.1"
resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.2.1.tgz#250ea2ab7e1734f22d11c677c463fab9ac33a516"
integrity sha512-N/a4JarAq+E+g+9K2ywJUmDIgU2xs2nA+BBldH0oq4zYJMRiUhL0iaN9G4e72VmGOJ61L/3W6VN8RIUOwTLoqQ==
"@next/swc-linux-arm-gnueabihf@13.2.0":
version "13.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.2.0.tgz#31b81ff368e5337019f858c4a0d7ae7f80310728"
integrity sha512-jY/2JjDVVyktzRtMclAIVLgOxk5Ut9NKu8kKMCPdKMf9/ila37UpRfIh2fOXtRhv8AK7Lq/iSI/v2vjopZxZgQ==
"@next/swc-linux-arm-gnueabihf@13.2.1":
version "13.2.1"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.2.1.tgz#fe6bb29ed348a5f8ecae3740df22a8d8130c474a"
integrity sha512-WaFoerF/eRbhbE57TaIGJXbQAERADZ/RZ45u6qox9beb5xnWsyYgzX+WuN7Tkhyvga0/aMuVYFzS9CEay7D+bw==
"@next/swc-linux-arm64-gnu@13.2.0":
version "13.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.2.0.tgz#e46bd73d1ccc38be46009b88dc87df88d8c44fa1"
integrity sha512-EKjWU3/lSBhOwPQRQLbySUnATnXygCjGd8ag3rP6d7kTIhfuPO4pY+DYW+wHOt5qB1ULNRmW0sXZ/ZKnQrVszw==
"@next/swc-linux-arm64-gnu@13.2.1":
version "13.2.1"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.2.1.tgz#4781b927fc5e421f3cea2b29e5d38e5e4837b198"
integrity sha512-R+Jhc1/RJTnncE9fkePboHDNOCm1WJ8daanWbjKhfPySMyeniKYRwGn5SLYW3S8YlRS0QVdZaaszDSZWgUcsmA==
"@next/swc-linux-arm64-musl@13.2.0":
version "13.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.2.0.tgz#54a4f0cc1431f3e4e24a5e017e473a5fc761b33b"
integrity sha512-T5R9r23Docwo6PYZRzndeFB5WUN3+smMbyk25K50MAngCiSydr82/YfAetcp7Ov7Shp4a8xXP9DHDIsBas6wbQ==
"@next/swc-linux-arm64-musl@13.2.1":
version "13.2.1"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.2.1.tgz#c2ba0a121b0255ba62450916bc70e6d0e26cbc98"
integrity sha512-oI1UfZPidGAVddlL2eOTmfsuKV9EaT1aktIzVIxIAgxzQSdwsV371gU3G55ggkurzfdlgF3GThFePDWF0d8dmw==
"@next/swc-linux-x64-gnu@13.2.0":
version "13.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.2.0.tgz#1c17a6121846decac2d701a040649f8f764ac671"
integrity sha512-FeXTc2KFvUSnTJmkpNMKoBHmNA1Ujr3QdfcKnVm/gXWqK+rfuEhAiRNOo+6mPcQ0noEge1j8Ai+W1LTbdDwPZQ==
"@next/swc-linux-x64-gnu@13.2.1":
version "13.2.1"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.2.1.tgz#573c220f8b087e5d131d1fba58d3e1a670b220ad"
integrity sha512-PCygPwrQmS+7WUuAWWioWMZCzZm4PG91lfRxToLDg7yIm/3YfAw5N2EK2TaM9pzlWdvHQAqRMX/oLvv027xUiA==
"@next/swc-linux-x64-musl@13.2.0":
version "13.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.2.0.tgz#a4f39cfeb19123196a2ebc2061e60897b29ffa3f"
integrity sha512-7Y0XMUzWDWI94pxC0xWGMWrgTFKHu/myc+GTNVEwvLtI9WA0brKqZrL1tCQW/+t6J+5XqS7w+AHbViaF+muu1A==
"@next/swc-linux-x64-musl@13.2.1":
version "13.2.1"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.2.1.tgz#950b5bb920b322ca7b447efbd12a9c7a10c3a642"
integrity sha512-sUAKxo7CFZYGHNxheGh9nIBElLYBM6md/liEGfOTwh/xna4/GTTcmkGWkF7PdnvaYNgcPIQgHIMYiAa6yBKAVw==
"@next/swc-win32-arm64-msvc@13.2.0":
version "13.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.2.0.tgz#d21ef0d0c2757cee9b1d723aafb9e02ca25852eb"
integrity sha512-NM5h2gEMe8EtvOeRU3vRM83tq1xo6Qvhuz0xJem/176SAMxbqzAz4LLP3l9VyUI3SIzGyiztvF/1c0jqeq7UEA==
"@next/swc-win32-arm64-msvc@13.2.1":
version "13.2.1"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.2.1.tgz#dbff3c4f5a3812a7059dac05804148a0f98682db"
integrity sha512-qDmyEjDBpl/vBXxuOOKKWmPQOcARcZIMach1s7kjzaien0SySut/PHRlj56sosa81Wt4hTGhfhZ1R7g1n7+B8w==
"@next/swc-win32-ia32-msvc@13.2.0":
version "13.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.2.0.tgz#529852721e3f00afb9385640cbac1a899342c6ba"
integrity sha512-G7YEJZX9wkcUaBOvXQSCF9Wb2sqP8hhsmFXF6po7M3llw4b+2ut2DXLf+UMdthOdUK0u+Ijhy5F7SbW9HOn2ig==
"@next/swc-win32-ia32-msvc@13.2.1":
version "13.2.1"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.2.1.tgz#7d2c17be7b8d9963984f5c15cc2588127101f620"
integrity sha512-2joqFQ81ZYPg6DcikIzQn3DgjKglNhPAozx6dL5sCNkr1CPMD0YIkJgT3CnYyMHQ04Qi3Npv0XX3MD6LJO8OCA==
"@next/swc-win32-x64-msvc@13.2.0":
version "13.2.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.2.0.tgz#49bc50b1865d20b29892a415fcbaab84217112a5"
integrity sha512-QTAjSuPevnZnlHfC4600+4NvxRuPar6tWdYbPum9vnk3OIH1xu9YLK+2ArPGFd0bB2K8AoY2SIMbs1dhK0GjQQ==
"@next/swc-win32-x64-msvc@13.2.1":
version "13.2.1"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.2.1.tgz#09713c6a925461f414e89422851326d1625bd4d2"
integrity sha512-r3+0fSaIZT6N237iMzwUhfNwjhAFvXjqB+4iuW+wcpxW+LHm1g/IoxN8eSRcb8jPItC86JxjAxpke0QL97qd6g==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
@@ -770,7 +770,12 @@
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10"
integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==
"@types/node@*", "@types/node@18.14.1", "@types/node@>=12.12.47", "@types/node@>=13.7.0":
"@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0":
version "18.14.2"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.2.tgz#c076ed1d7b6095078ad3cf21dfeea951842778b1"
integrity sha512-1uEQxww3DaghA0RxqHx0O0ppVlo43pJhepY51OxuQIKHpjbnYLA7vcdwioNPzIqmC2u3I/dmylcqjlh0e7AyUA==
"@types/node@18.14.1":
version "18.14.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.1.tgz#90dad8476f1e42797c49d6f8b69aaf9f876fc69f"
integrity sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ==
@@ -1215,9 +1220,9 @@ camelcase-css@^2.0.1:
integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001426, caniuse-lite@^1.0.30001449:
version "1.0.30001457"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001457.tgz#6af34bb5d720074e2099432aa522c21555a18301"
integrity sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA==
version "1.0.30001458"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001458.tgz#871e35866b4654a7d25eccca86864f411825540c"
integrity sha512-lQ1VlUUq5q9ro9X+5gOEyH7i3vm+AYVT1WDCVB69XOZ17KZRhnZ9J0Sqz7wTHQaLBJccNCHq8/Ww5LlOIZbB0w==
chalk@^2.0.0:
version "2.4.2"
@@ -1353,9 +1358,9 @@ cookie@0.5.0:
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
core-js@^3.1.3:
version "3.28.0"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.28.0.tgz#ed8b9e99c273879fdfff0edfc77ee709a5800e4a"
integrity sha512-GiZn9D4Z/rSYvTeg1ljAIsEqFm0LaN9gVtwDCrKL80zHtS31p9BAjmTxVqTQDMpwlMolJZOFntUG2uwyj7DAqw==
version "3.29.0"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.29.0.tgz#0273e142b67761058bcde5615c503c7406b572d6"
integrity sha512-VG23vuEisJNkGl6XQmFJd3rEG/so/CNatqeE+7uZAwTSwFeB/qaO0be8xZYUNWprJ/GIwL8aMt9cj1kvbpTZhg==
cors@^2.8.5:
version "2.8.5"
@@ -1404,9 +1409,9 @@ csstype@^3.0.2:
integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==
daisyui@^2.49.0:
version "2.51.0"
resolved "https://registry.yarnpkg.com/daisyui/-/daisyui-2.51.0.tgz#7ed95786a27a4ea044f14dc6b1423f98acb213bc"
integrity sha512-HGM89+VzZ/KDsH4cK6OhizIscXOVzkEENynovL6bXPfJDOKZQz0V2CuTGEoQmN8FeuGxrZiz/He1P9p+E9Qr5A==
version "2.51.1"
resolved "https://registry.yarnpkg.com/daisyui/-/daisyui-2.51.1.tgz#20fe01f3f3caa8628ebb30fcc1b99341183d1702"
integrity sha512-rMtdB8Rh8Ghd3+FDlMe63Caw+IopKIf7tviJGEx8gkjj5H+RCvU1bEbjx6DHsMsu477Gv5aafrLIdoUL+iMRrw==
dependencies:
color "^4.2"
css-selector-tokenizer "^0.8.0"
@@ -2826,7 +2831,7 @@ json-stable-stringify-without-jsonify@^1.0.1:
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
json5@^1.0.1:
json5@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593"
integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==
@@ -3086,30 +3091,30 @@ next-seo@^5.15.0:
resolved "https://registry.yarnpkg.com/next-seo/-/next-seo-5.15.0.tgz#b1a90508599774982909ea44803323c6fb7b50f4"
integrity sha512-LGbcY91yDKGMb7YI+28n3g+RuChUkt6pXNpa8FkfKkEmNiJkeRDEXTnnjVtwT9FmMhG6NH8qwHTelGrlYm9rgg==
next@13.2.0:
version "13.2.0"
resolved "https://registry.yarnpkg.com/next/-/next-13.2.0.tgz#100b2d1dca120a3460c767ccdad80fc8e2463e31"
integrity sha512-vhByvKHedsaMwNTwXKzK4IMmNp7XI7vN4etcGUoIpLrIuDfoYA3bS0ImS4X9F6lKzopG5aVp7a1CjuzF2NGkvA==
next@^13.2.1:
version "13.2.1"
resolved "https://registry.yarnpkg.com/next/-/next-13.2.1.tgz#34d823f518632b36379863228ed9f861c335b9c0"
integrity sha512-qhgJlDtG0xidNViJUPeQHLGJJoT4zDj/El7fP3D3OzpxJDUfxsm16cK4WTMyvSX1ciIfAq05u+0HqFAa+VJ+Hg==
dependencies:
"@next/env" "13.2.0"
"@next/env" "13.2.1"
"@swc/helpers" "0.4.14"
caniuse-lite "^1.0.30001406"
postcss "8.4.14"
styled-jsx "5.1.1"
optionalDependencies:
"@next/swc-android-arm-eabi" "13.2.0"
"@next/swc-android-arm64" "13.2.0"
"@next/swc-darwin-arm64" "13.2.0"
"@next/swc-darwin-x64" "13.2.0"
"@next/swc-freebsd-x64" "13.2.0"
"@next/swc-linux-arm-gnueabihf" "13.2.0"
"@next/swc-linux-arm64-gnu" "13.2.0"
"@next/swc-linux-arm64-musl" "13.2.0"
"@next/swc-linux-x64-gnu" "13.2.0"
"@next/swc-linux-x64-musl" "13.2.0"
"@next/swc-win32-arm64-msvc" "13.2.0"
"@next/swc-win32-ia32-msvc" "13.2.0"
"@next/swc-win32-x64-msvc" "13.2.0"
"@next/swc-android-arm-eabi" "13.2.1"
"@next/swc-android-arm64" "13.2.1"
"@next/swc-darwin-arm64" "13.2.1"
"@next/swc-darwin-x64" "13.2.1"
"@next/swc-freebsd-x64" "13.2.1"
"@next/swc-linux-arm-gnueabihf" "13.2.1"
"@next/swc-linux-arm64-gnu" "13.2.1"
"@next/swc-linux-arm64-musl" "13.2.1"
"@next/swc-linux-x64-gnu" "13.2.1"
"@next/swc-linux-x64-musl" "13.2.1"
"@next/swc-win32-arm64-msvc" "13.2.1"
"@next/swc-win32-ia32-msvc" "13.2.1"
"@next/swc-win32-x64-msvc" "13.2.1"
node-fetch@2.6.7:
version "2.6.7"
@@ -4241,12 +4246,12 @@ ts-morph@^10.0.2:
code-block-writer "^10.1.1"
tsconfig-paths@^3.14.1:
version "3.14.1"
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a"
integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==
version "3.14.2"
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088"
integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==
dependencies:
"@types/json5" "^0.0.29"
json5 "^1.0.1"
json5 "^1.0.2"
minimist "^1.2.6"
strip-bom "^3.0.0"