From fcc43c305c2600a9c65f7d8de891e8e48af07cb6 Mon Sep 17 00:00:00 2001 From: Aaron William Po Date: Sun, 5 Nov 2023 18:00:40 -0500 Subject: [PATCH 01/13] Feat: begin user page --- src/pages/users/[id].tsx | 44 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/pages/users/[id].tsx b/src/pages/users/[id].tsx index f7550d1..c180656 100644 --- a/src/pages/users/[id].tsx +++ b/src/pages/users/[id].tsx @@ -1,5 +1,47 @@ +import useTimeDistance from '@/hooks/utilities/useTimeDistance'; +import findUserById from '@/services/User/findUserById'; +import GetUserSchema from '@/services/User/schema/GetUserSchema'; +import { format } from 'date-fns'; +import { GetServerSideProps } from 'next'; import { FC } from 'react'; +import { z } from 'zod'; -const UserInfoPage: FC = () => null; +interface UserInfoPageProps { + user: z.infer; +} + +const UserInfoPage: FC = ({ user }) => { + const timeDistance = useTimeDistance(new Date(user.createdAt)); + return ( +
+

+ {user.firstName} {user.lastName} +

+

+ joined{' '} + {' '} + ago +

+
+ ); +}; export default UserInfoPage; + +export const getServerSideProps: GetServerSideProps = async ( + context, +) => { + const { id } = context.params!; + const user = await findUserById(id as string); + + if (!user) { + return { notFound: true }; + } + + return { props: { user: JSON.parse(JSON.stringify(user)) } }; +}; From 7f9ddb40a1b920d2b1ec769e686ccab746246f34 Mon Sep 17 00:00:00 2001 From: Aaron William Po Date: Sun, 5 Nov 2023 21:54:09 -0500 Subject: [PATCH 02/13] Feat: create user page, add user bio and avatar --- .../CommentContentBody.tsx | 91 ++++++++++++------- src/pages/api/beers/index.ts | 1 + src/pages/api/breweries/create.ts | 2 +- src/pages/users/[id].tsx | 68 ++++++++++---- .../migrations/20231106024511_/migration.sql | 57 ++++++++++++ src/prisma/schema.prisma | 43 ++++++--- src/prisma/seed/create/createAdminUser.ts | 11 +++ .../seed/create/createNewBreweryPosts.ts | 4 +- src/prisma/seed/create/createNewLocations.ts | 4 +- .../seed/create/createNewUserAvatars.ts | 38 ++++++++ src/prisma/seed/create/createNewUsers.ts | 4 +- src/prisma/seed/index.ts | 5 + .../BeerComment/createNewBeerComment.ts | 2 +- .../BeerComment/editBeerCommentById.ts | 4 +- .../BeerComment/findBeerCommentById.ts | 4 +- .../BeerComment/getAllBeerComments.ts | 4 +- .../createNewBeerStyleComment.ts | 4 +- .../getAllBeerStyleComments.ts | 4 +- .../BreweryComment/createNewBreweryComment.ts | 4 +- .../BreweryComment/getAllBreweryComments.ts | 4 +- src/services/User/createNewUser.ts | 2 + src/services/User/deleteUserById.ts | 2 + src/services/User/findUserById.ts | 11 +++ src/services/User/schema/GetUserSchema.ts | 11 +++ .../User/updateUserToBeConfirmedById.ts | 11 +++ .../CommentSchema/CommentQueryResult.ts | 8 ++ 26 files changed, 324 insertions(+), 79 deletions(-) create mode 100644 src/prisma/migrations/20231106024511_/migration.sql create mode 100644 src/prisma/seed/create/createNewUserAvatars.ts diff --git a/src/components/BeerBreweryComments/CommentContentBody.tsx b/src/components/BeerBreweryComments/CommentContentBody.tsx index 0864c39..747c43a 100644 --- a/src/components/BeerBreweryComments/CommentContentBody.tsx +++ b/src/components/BeerBreweryComments/CommentContentBody.tsx @@ -5,7 +5,7 @@ import { Dispatch, FC, SetStateAction, useContext } from 'react'; import { Rating } from 'react-daisyui'; import Link from 'next/link'; import CommentQueryResult from '@/services/schema/CommentSchema/CommentQueryResult'; - +import Image from 'next/image'; import { z } from 'zod'; import CommentCardDropdown from './CommentCardDropdown'; @@ -20,41 +20,64 @@ const CommentContentBody: FC = ({ comment, setInEditMod return (
-
-
-

- - {comment.postedBy.username} - -

- - posted{' '} - {' '} - ago - +
+
+
+ {comment.postedBy.userAvatar ? ( + {comment.postedBy.userAvatar.alt} + ) : ( +
+ {comment.postedBy.username[0]} +
+ )} +
+
+
+
+

+ + {comment.postedBy.username} + +

+ + posted{' '} + {' '} + ago + +
- {user && } -
- -
- - {Array.from({ length: 5 }).map((val, index) => ( - - ))} - -

{comment.content}

+ {user && ( + + )} +
+
+ + {Array.from({ length: 5 }).map((val, index) => ( + + ))} + +
+
+

{comment.content}

+
+
); diff --git a/src/pages/api/beers/index.ts b/src/pages/api/beers/index.ts index 8e6f919..6a5aa0a 100644 --- a/src/pages/api/beers/index.ts +++ b/src/pages/api/beers/index.ts @@ -20,6 +20,7 @@ const getBeerPosts = async ( const pageSize = parseInt(req.query.page_size, 10); const beerPosts = await getAllBeerPosts({ pageNum, pageSize }); + const beerPostCount = await DBClient.instance.beerPost.count(); res.setHeader('X-Total-Count', beerPostCount); diff --git a/src/pages/api/breweries/create.ts b/src/pages/api/breweries/create.ts index 07308f1..8cf3e04 100644 --- a/src/pages/api/breweries/create.ts +++ b/src/pages/api/breweries/create.ts @@ -33,7 +33,7 @@ const createBreweryPost = async ( const [latitude, longitude] = geocoded.center; - const location = await DBClient.instance.location.create({ + const location = await DBClient.instance.breweryLocation.create({ data: { address, city, diff --git a/src/pages/users/[id].tsx b/src/pages/users/[id].tsx index c180656..811ec10 100644 --- a/src/pages/users/[id].tsx +++ b/src/pages/users/[id].tsx @@ -1,33 +1,69 @@ +import useMediaQuery from '@/hooks/utilities/useMediaQuery'; import useTimeDistance from '@/hooks/utilities/useTimeDistance'; import findUserById from '@/services/User/findUserById'; import GetUserSchema from '@/services/User/schema/GetUserSchema'; import { format } from 'date-fns'; import { GetServerSideProps } from 'next'; +import Head from 'next/head'; import { FC } from 'react'; import { z } from 'zod'; +import Image from 'next/image'; interface UserInfoPageProps { user: z.infer; } -const UserInfoPage: FC = ({ user }) => { +const UserHeader: FC<{ user: z.infer }> = ({ user }) => { const timeDistance = useTimeDistance(new Date(user.createdAt)); + return ( -
-

- {user.firstName} {user.lastName} -

-

- joined{' '} - {' '} - ago -

-
+
+
+
+
+
+

+ {user.firstName} {user.lastName} +

+ +

+ joined{' '} + {timeDistance && ( + + {`${timeDistance} ago`} + + )} +

+
+
+
+
+
+ ); +}; + +const UserInfoPage: FC = ({ user }) => { + const isDesktop = useMediaQuery('(min-width: 1024px)'); + return ( + <> + + {user ? `${user.firstName} ${user.lastName}` : 'User Info'} + + + <> +
+ avatar +
+ + + {isDesktop ? <> : <> } +
+
+ + ); }; diff --git a/src/prisma/migrations/20231106024511_/migration.sql b/src/prisma/migrations/20231106024511_/migration.sql new file mode 100644 index 0000000..5dc7021 --- /dev/null +++ b/src/prisma/migrations/20231106024511_/migration.sql @@ -0,0 +1,57 @@ +/* + Warnings: + + - You are about to drop the `Location` table. If the table is not empty, all the data it contains will be lost. + +*/ +-- DropForeignKey +ALTER TABLE "BreweryPost" DROP CONSTRAINT "BreweryPost_locationId_fkey"; + +-- DropForeignKey +ALTER TABLE "Location" DROP CONSTRAINT "Location_postedById_fkey"; + +-- AlterTable +ALTER TABLE "User" ADD COLUMN "bio" TEXT; + +-- DropTable +DROP TABLE "Location"; + +-- CreateTable +CREATE TABLE "UserAvatar" ( + "id" TEXT NOT NULL, + "path" TEXT NOT NULL, + "alt" TEXT NOT NULL, + "caption" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMPTZ(3), + + CONSTRAINT "UserAvatar_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "BreweryLocation" ( + "id" TEXT NOT NULL, + "city" TEXT NOT NULL, + "stateOrProvince" TEXT, + "country" TEXT, + "coordinates" DOUBLE PRECISION[], + "address" TEXT NOT NULL, + "postedById" TEXT NOT NULL, + "createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMPTZ(3), + + CONSTRAINT "BreweryLocation_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "UserAvatar_userId_key" ON "UserAvatar"("userId"); + +-- AddForeignKey +ALTER TABLE "UserAvatar" ADD CONSTRAINT "UserAvatar_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "BreweryLocation" ADD CONSTRAINT "BreweryLocation_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "BreweryPost" ADD CONSTRAINT "BreweryPost_locationId_fkey" FOREIGN KEY ("locationId") REFERENCES "BreweryLocation"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/src/prisma/schema.prisma b/src/prisma/schema.prisma index 781e61b..e485041 100644 --- a/src/prisma/schema.prisma +++ b/src/prisma/schema.prisma @@ -29,19 +29,32 @@ model User { accountIsVerified Boolean @default(false) dateOfBirth DateTime role Role @default(USER) + bio String? beerPosts BeerPost[] beerStyles BeerStyle[] breweryPosts BreweryPost[] beerComments BeerComment[] breweryComments BreweryComment[] - BeerPostLikes BeerPostLike[] - BeerImage BeerImage[] - BreweryImage BreweryImage[] - BreweryPostLike BreweryPostLike[] - Location Location[] - Glassware Glassware[] - BeerStyleLike BeerStyleLike[] - BeerStyleComment BeerStyleComment[] + beerPostLikes BeerPostLike[] + beerImages BeerImage[] + breweryImages BreweryImage[] + breweryPostLikes BreweryPostLike[] + locations BreweryLocation[] + glasswares Glassware[] + beerStyleLikes BeerStyleLike[] + beerStyleComments BeerStyleComment[] + userAvatar UserAvatar? +} + +model UserAvatar { + id String @id @default(cuid()) + path String + alt String + caption String + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + userId String @unique + createdAt DateTime @default(now()) @db.Timestamptz(3) + updatedAt DateTime? @updatedAt @db.Timestamptz(3) } model BeerPost { @@ -60,7 +73,7 @@ model BeerPost { updatedAt DateTime? @updatedAt @db.Timestamptz(3) beerComments BeerComment[] beerImages BeerImage[] - BeerPostLikes BeerPostLike[] + beerPostLikes BeerPostLike[] } model BeerPostLike { @@ -108,8 +121,8 @@ model BeerStyle { abvRange Float[] ibuRange Float[] beerPosts BeerPost[] - BeerStyleLike BeerStyleLike[] - BeerStyleComment BeerStyleComment[] + beerStyleLike BeerStyleLike[] + beerStyleComment BeerStyleComment[] } model BeerStyleLike { @@ -142,10 +155,10 @@ model Glassware { updatedAt DateTime? @updatedAt @db.Timestamptz(3) postedBy User @relation(fields: [postedById], references: [id], onDelete: Cascade) postedById String - BeerStyle BeerStyle[] + beerStyle BeerStyle[] } -model Location { +model BreweryLocation { id String @id @default(cuid()) city String stateOrProvince String? @@ -154,7 +167,7 @@ model Location { address String postedBy User @relation(fields: [postedById], references: [id], onDelete: Cascade) postedById String - BreweryPost BreweryPost? + breweryPost BreweryPost? createdAt DateTime @default(now()) @db.Timestamptz(3) updatedAt DateTime? @updatedAt @db.Timestamptz(3) } @@ -162,7 +175,7 @@ model Location { model BreweryPost { id String @id @default(cuid()) name String - location Location @relation(fields: [locationId], references: [id]) + location BreweryLocation @relation(fields: [locationId], references: [id]) locationId String @unique beers BeerPost[] description String diff --git a/src/prisma/seed/create/createAdminUser.ts b/src/prisma/seed/create/createAdminUser.ts index 7de97ff..eeb3739 100644 --- a/src/prisma/seed/create/createAdminUser.ts +++ b/src/prisma/seed/create/createAdminUser.ts @@ -3,6 +3,7 @@ import { z } from 'zod'; import { hashPassword } from '../../../config/auth/passwordFns'; import DBClient from '../../DBClient'; import GetUserSchema from '../../../services/User/schema/GetUserSchema'; +import imageUrls from '../util/imageUrls'; const createAdminUser = async () => { const hash = await hashPassword('Pas!3word'); @@ -15,6 +16,14 @@ const createAdminUser = async () => { dateOfBirth: new Date('1990-01-01'), role: 'ADMIN', hash, + userAvatar: { + create: { + path: imageUrls[Math.floor(Math.random() * imageUrls.length)], + alt: 'Admin User', + caption: 'Admin User', + createdAt: new Date(), + }, + }, }, select: { id: true, @@ -27,6 +36,8 @@ const createAdminUser = async () => { accountIsVerified: true, updatedAt: true, role: true, + bio: true, + userAvatar: true, }, }); diff --git a/src/prisma/seed/create/createNewBreweryPosts.ts b/src/prisma/seed/create/createNewBreweryPosts.ts index 7e38426..016ae51 100644 --- a/src/prisma/seed/create/createNewBreweryPosts.ts +++ b/src/prisma/seed/create/createNewBreweryPosts.ts @@ -1,13 +1,13 @@ // eslint-disable-next-line import/no-extraneous-dependencies import { faker } from '@faker-js/faker'; -import { Location, User } from '@prisma/client'; +import { BreweryLocation, User } from '@prisma/client'; import DBClient from '../../DBClient'; interface CreateNewBreweryPostsArgs { numberOfPosts: number; joinData: { users: User[]; - locations: Location[]; + locations: BreweryLocation[]; }; } diff --git a/src/prisma/seed/create/createNewLocations.ts b/src/prisma/seed/create/createNewLocations.ts index 1b09815..3341f42 100644 --- a/src/prisma/seed/create/createNewLocations.ts +++ b/src/prisma/seed/create/createNewLocations.ts @@ -47,9 +47,9 @@ const createNewLocations = async ({ }); } - await prisma.location.createMany({ data: locationData, skipDuplicates: true }); + await prisma.breweryLocation.createMany({ data: locationData, skipDuplicates: true }); - return prisma.location.findMany(); + return prisma.breweryLocation.findMany(); }; export default createNewLocations; diff --git a/src/prisma/seed/create/createNewUserAvatars.ts b/src/prisma/seed/create/createNewUserAvatars.ts new file mode 100644 index 0000000..84363e3 --- /dev/null +++ b/src/prisma/seed/create/createNewUserAvatars.ts @@ -0,0 +1,38 @@ +import { User } from '@prisma/client'; +import DBClient from '../../DBClient'; +import imageUrls from '../util/imageUrls'; + +interface CreateNewUserAvatarsArgs { + joinData: { users: User[] }; +} +interface UserAvatarData { + path: string; + alt: string; + caption: string; + userId: string; + createdAt: Date; +} + +const createNewUserAvatars = async ({ + joinData: { users }, +}: CreateNewUserAvatarsArgs) => { + const userAvatars: UserAvatarData[] = []; + + const path = imageUrls[Math.floor(Math.random() * imageUrls.length)]; + users.forEach((user) => { + userAvatars.push({ + path, + alt: `${user.firstName} ${user.lastName}`, + caption: `${user.firstName} ${user.lastName}`, + userId: user.id, + createdAt: new Date(), + }); + }); + + await DBClient.instance.userAvatar.createMany({ data: userAvatars }); + return DBClient.instance.userAvatar.findMany({ + where: { user: { role: { not: 'ADMIN' } } }, + }); +}; + +export default createNewUserAvatars; diff --git a/src/prisma/seed/create/createNewUsers.ts b/src/prisma/seed/create/createNewUsers.ts index c9c81f3..e61fcf6 100644 --- a/src/prisma/seed/create/createNewUsers.ts +++ b/src/prisma/seed/create/createNewUsers.ts @@ -71,7 +71,9 @@ const createNewUsers = async ({ numberOfUsers }: CreateNewUsersArgs) => { } await prisma.user.createMany({ data, skipDuplicates: true }); - return prisma.user.findMany(); + return prisma.user.findMany({ + where: { role: { not: 'ADMIN' } }, + }); }; export default createNewUsers; diff --git a/src/prisma/seed/index.ts b/src/prisma/seed/index.ts index 4377655..4139ba2 100644 --- a/src/prisma/seed/index.ts +++ b/src/prisma/seed/index.ts @@ -18,6 +18,7 @@ import logger from '../../config/pino/logger'; import createAdminUser from './create/createAdminUser'; import createNewBeerStyleComments from './create/createNewBeerStyleComments'; import createNewBeerStyleLikes from './create/createNewBeerStyleLikes'; +import createNewUserAvatars from './create/createNewUserAvatars'; (async () => { try { @@ -33,6 +34,9 @@ import createNewBeerStyleLikes from './create/createNewBeerStyleLikes'; const users = await createNewUsers({ numberOfUsers: 10000 }); logger.info('Users created successfully.'); + const userAvatars = await createNewUserAvatars({ joinData: { users } }); + logger.info('User avatars created successfully.'); + const locations = await createNewLocations({ numberOfLocations: 500, joinData: { users }, @@ -103,6 +107,7 @@ import createNewBeerStyleLikes from './create/createNewBeerStyleLikes'; logger.info('Database seeded successfully.'); logger.info({ numberOfUsers: users.length, + numberOfUserAvatars: userAvatars.length, numberOfBreweryPosts: breweryPosts.length, numberOfBeerPosts: beerPosts.length, numberOfBeerStyles: beerStyles.length, diff --git a/src/services/BeerComment/createNewBeerComment.ts b/src/services/BeerComment/createNewBeerComment.ts index dc65f90..9abba2b 100644 --- a/src/services/BeerComment/createNewBeerComment.ts +++ b/src/services/BeerComment/createNewBeerComment.ts @@ -27,7 +27,7 @@ const createNewBeerComment = async ({ id: true, content: true, rating: true, - postedBy: { select: { id: true, username: true } }, + postedBy: { select: { id: true, username: true, userAvatar: true } }, createdAt: true, updatedAt: true, }, diff --git a/src/services/BeerComment/editBeerCommentById.ts b/src/services/BeerComment/editBeerCommentById.ts index 42ec67f..2aa4e3c 100644 --- a/src/services/BeerComment/editBeerCommentById.ts +++ b/src/services/BeerComment/editBeerCommentById.ts @@ -22,7 +22,9 @@ const editBeerCommentById = async ({ rating: true, createdAt: true, updatedAt: true, - postedBy: { select: { id: true, username: true, createdAt: true } }, + postedBy: { + select: { id: true, username: true, createdAt: true, userAvatar: true }, + }, }, }); }; diff --git a/src/services/BeerComment/findBeerCommentById.ts b/src/services/BeerComment/findBeerCommentById.ts index 0fb030b..f985414 100644 --- a/src/services/BeerComment/findBeerCommentById.ts +++ b/src/services/BeerComment/findBeerCommentById.ts @@ -17,7 +17,9 @@ const findBeerCommentById = async ({ rating: true, createdAt: true, updatedAt: true, - postedBy: { select: { id: true, username: true, createdAt: true } }, + postedBy: { + select: { id: true, username: true, createdAt: true, userAvatar: true }, + }, }, }); }; diff --git a/src/services/BeerComment/getAllBeerComments.ts b/src/services/BeerComment/getAllBeerComments.ts index 92b5357..c7a30bd 100644 --- a/src/services/BeerComment/getAllBeerComments.ts +++ b/src/services/BeerComment/getAllBeerComments.ts @@ -24,7 +24,9 @@ const getAllBeerComments = async ({ rating: true, createdAt: true, updatedAt: true, - postedBy: { select: { id: true, username: true, createdAt: true } }, + postedBy: { + select: { id: true, username: true, createdAt: true, userAvatar: true }, + }, }, }); }; diff --git a/src/services/BeerStyleComment/createNewBeerStyleComment.ts b/src/services/BeerStyleComment/createNewBeerStyleComment.ts index 0d84586..9d29ee2 100644 --- a/src/services/BeerStyleComment/createNewBeerStyleComment.ts +++ b/src/services/BeerStyleComment/createNewBeerStyleComment.ts @@ -27,9 +27,11 @@ const createNewBeerStyleComment = async ({ id: true, content: true, rating: true, - postedBy: { select: { id: true, username: true } }, createdAt: true, updatedAt: true, + postedBy: { + select: { id: true, username: true, createdAt: true, userAvatar: true }, + }, }, }); }; diff --git a/src/services/BeerStyleComment/getAllBeerStyleComments.ts b/src/services/BeerStyleComment/getAllBeerStyleComments.ts index e8bdeff..77deced 100644 --- a/src/services/BeerStyleComment/getAllBeerStyleComments.ts +++ b/src/services/BeerStyleComment/getAllBeerStyleComments.ts @@ -24,7 +24,9 @@ const getAllBeerStyleComments = async ({ rating: true, createdAt: true, updatedAt: true, - postedBy: { select: { id: true, username: true, createdAt: true } }, + postedBy: { + select: { id: true, username: true, createdAt: true, userAvatar: true }, + }, }, }); }; diff --git a/src/services/BreweryComment/createNewBreweryComment.ts b/src/services/BreweryComment/createNewBreweryComment.ts index 5687864..d161292 100644 --- a/src/services/BreweryComment/createNewBreweryComment.ts +++ b/src/services/BreweryComment/createNewBreweryComment.ts @@ -27,9 +27,11 @@ const createNewBreweryComment = async ({ id: true, content: true, rating: true, - postedBy: { select: { id: true, username: true } }, createdAt: true, updatedAt: true, + postedBy: { + select: { id: true, username: true, createdAt: true, userAvatar: true }, + }, }, }); }; diff --git a/src/services/BreweryComment/getAllBreweryComments.ts b/src/services/BreweryComment/getAllBreweryComments.ts index 57f7f7d..766f68d 100644 --- a/src/services/BreweryComment/getAllBreweryComments.ts +++ b/src/services/BreweryComment/getAllBreweryComments.ts @@ -23,7 +23,9 @@ const getAllBreweryComments = async ({ rating: true, createdAt: true, updatedAt: true, - postedBy: { select: { id: true, username: true, createdAt: true } }, + postedBy: { + select: { id: true, username: true, createdAt: true, userAvatar: true }, + }, }, orderBy: { createdAt: 'desc' }, }); diff --git a/src/services/User/createNewUser.ts b/src/services/User/createNewUser.ts index 4f84366..b34c61a 100644 --- a/src/services/User/createNewUser.ts +++ b/src/services/User/createNewUser.ts @@ -33,6 +33,8 @@ const createNewUser = async ({ accountIsVerified: true, updatedAt: true, role: true, + userAvatar: true, + bio: true, }, }); diff --git a/src/services/User/deleteUserById.ts b/src/services/User/deleteUserById.ts index b743772..dd62693 100644 --- a/src/services/User/deleteUserById.ts +++ b/src/services/User/deleteUserById.ts @@ -17,6 +17,8 @@ const deleteUserById = async (id: string) => { accountIsVerified: true, updatedAt: true, role: true, + userAvatar: true, + bio: true, }, }); diff --git a/src/services/User/findUserById.ts b/src/services/User/findUserById.ts index dbd4311..05b1182 100644 --- a/src/services/User/findUserById.ts +++ b/src/services/User/findUserById.ts @@ -17,6 +17,17 @@ const findUserById = async (id: string) => { accountIsVerified: true, updatedAt: true, role: true, + userAvatar: { + select: { + path: true, + alt: true, + caption: true, + createdAt: true, + id: true, + updatedAt: true, + }, + }, + bio: true, }, }); diff --git a/src/services/User/schema/GetUserSchema.ts b/src/services/User/schema/GetUserSchema.ts index 92c7789..eaf21b7 100644 --- a/src/services/User/schema/GetUserSchema.ts +++ b/src/services/User/schema/GetUserSchema.ts @@ -11,6 +11,17 @@ const GetUserSchema = z.object({ dateOfBirth: z.coerce.date(), accountIsVerified: z.boolean(), role: z.enum(['USER', 'ADMIN']), + bio: z.string().nullable(), + userAvatar: z + .object({ + id: z.string().cuid(), + path: z.string().url(), + alt: z.string(), + caption: z.string(), + createdAt: z.coerce.date(), + updatedAt: z.coerce.date().nullable(), + }) + .nullable(), }); export default GetUserSchema; diff --git a/src/services/User/updateUserToBeConfirmedById.ts b/src/services/User/updateUserToBeConfirmedById.ts index 3cb6425..4a8e7f3 100644 --- a/src/services/User/updateUserToBeConfirmedById.ts +++ b/src/services/User/updateUserToBeConfirmedById.ts @@ -17,6 +17,17 @@ const updateUserToBeConfirmedById = async (id: string) => { updatedAt: true, dateOfBirth: true, role: true, + bio: true, + userAvatar: { + select: { + id: true, + path: true, + alt: true, + caption: true, + createdAt: true, + updatedAt: true, + }, + }, }, }); diff --git a/src/services/schema/CommentSchema/CommentQueryResult.ts b/src/services/schema/CommentSchema/CommentQueryResult.ts index b03acde..bf94cd9 100644 --- a/src/services/schema/CommentSchema/CommentQueryResult.ts +++ b/src/services/schema/CommentSchema/CommentQueryResult.ts @@ -8,6 +8,14 @@ const CommentQueryResult = z.object({ postedBy: z.object({ id: z.string().cuid(), username: z.string().min(1).max(50), + userAvatar: z + .object({ + id: z.string().cuid(), + path: z.string().url(), + alt: z.string().min(1).max(50), + caption: z.string().min(1).max(50), + }) + .nullable(), }), updatedAt: z.coerce.date().nullable(), }); From fe778f83e1e2b1188be9d669be9cdece9f553821 Mon Sep 17 00:00:00 2001 From: Aaron William Po Date: Sun, 5 Nov 2023 22:27:48 -0500 Subject: [PATCH 03/13] docs: update readme and db schema --- README.md | 2 +- schema.svg | 3018 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 1739 insertions(+), 1281 deletions(-) diff --git a/README.md b/README.md index ace2c15..54c41b4 100644 --- a/README.md +++ b/README.md @@ -163,7 +163,7 @@ SPARKPOST_SENDER_ADDRESS=" > .env database used for migrations. - `SHADOW_DATABASE_URL` is a connection string for a secondary database used for migrations to detect schema drift. - - You can create a free account [here](https://neon.tech) + - You can create a free account [here](https://neon.tech). - Consult the [docs](https://neon.tech/docs/guides/prisma) for more information. - `MAPBOX_ACCESS_TOKEN` and `NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN` are the access tokens for your Mapbox account. diff --git a/schema.svg b/schema.svg index 37c0e2f..5b6d38a 100644 --- a/schema.svg +++ b/schema.svg @@ -1,2103 +1,2561 @@ - - + + + d="M4,22L19,22Q29,22,29,32L29,172Q29,182,39,182L54,182L39,182Q29,182,29,172L29,32Q29,22,19,22L4,22L4,22M14,18L14,26M44,178L44,186" + fill="none" stroke="#D3D3D3" stroke-width="1"> 1 - - * - - - - - 1 - - * - - - - - * - 1 - + + d="M4,22L163.75,22Q173.75,22,173.75,32L173.75,204Q173.75,214,183.75,214L343.5,214L183.75,214Q173.75,214,173.75,204L173.75,32Q173.75,22,163.75,22L4,22L4,22M14,18L14,26M343.5,210L333.5,214L343.5,218" + fill="none" stroke="#D3D3D3" stroke-width="1"> 1 - * - + + d="M4,22L47.599998474121094,22Q57.599998474121094,22,57.599998474121094,32L57.599998474121094,368Q57.599998474121094,378,67.5999984741211,378L111.19999694824219,378L67.5999984741211,378Q57.599998474121094,378,57.599998474121094,368L57.599998474121094,32Q57.599998474121094,22,47.599998474121094,22L4,22L4,22M4,18L14,22L4,26M101.19999694824219,374L101.19999694824219,382" + fill="none" stroke="#D3D3D3" stroke-width="1"> + + * + + 1 + + + + + * + + 1 + + + 1 - * - + - - 1 - - * - - - + d="M4,22L363,22Q373,22,373,32L373,140Q373,150,383,150L742,150L383,150Q373,150,373,140L373,32Q373,22,363,22L4,22L4,22M14,18L14,26M742,146L732,150L742,154" + fill="none" stroke="#D3D3D3" stroke-width="1"> 1 - * - + - + * - 1 - + - + * - 1 - + + d="M4,456L19,456Q29,456,29,446L29,32Q29,22,39,22L54,22L39,22Q29,22,29,32L29,446Q29,456,19,456L4,456L4,456M4,452L14,456L4,460M44,18L44,26" + fill="none" stroke="#D3D3D3" stroke-width="1"> + + * + + 1 + + + 1 - * - + - - * - - 1 - - - + d="M4,22L163.75,22Q173.75,22,173.75,32L173.75,862Q173.75,872,183.75,872L343.5,872L183.75,872Q173.75,872,173.75,862L173.75,32Q173.75,22,163.75,22L4,22L4,22M14,18L14,26M343.5,868L333.5,872L343.5,876" + fill="none" stroke="#D3D3D3" stroke-width="1"> 1 - * - + + d="M4,22L19,22Q29,22,29,32L29,122Q29,132,39,132L54,132L39,132Q29,132,29,122L29,32Q29,22,19,22L4,22L4,22M14,18L14,26M54,128L44,132L54,136" + fill="none" stroke="#D3D3D3" stroke-width="1"> 1 - * - + - + 1 - - 1 - - - - * + + + 1 - - - - - 1 - * - + + d="M4,744L221.48333740234375,744Q231.48333740234375,744,231.48333740234375,734L231.48333740234375,32Q231.48333740234375,22,241.48333740234375,22L458.9666748046875,22L241.48333740234375,22Q231.48333740234375,22,231.48333740234375,32L231.48333740234375,734Q231.48333740234375,744,221.48333740234375,744L4,744L4,744M4,740L14,744L4,748M448.9666748046875,18L448.9666748046875,26" + fill="none" stroke="#D3D3D3" stroke-width="1"> + + * + + 1 + + + + + * + + 1 + + + 1 - * - + + d="M4,22L163.75,22Q173.75,22,173.75,32L173.75,1360Q173.75,1370,183.75,1370L343.5,1370L183.75,1370Q173.75,1370,173.75,1360L173.75,32Q173.75,22,163.75,22L4,22L4,22M14,18L14,26M343.5,1366L333.5,1370L343.5,1374" + fill="none" stroke="#D3D3D3" stroke-width="1"> 1 - * - + + d="M4,438L73.5,438Q83.5,438,83.5,428L83.5,32Q83.5,22,93.5,22L163,22L93.5,22Q83.5,22,83.5,32L83.5,428Q83.5,438,73.5,438L4,438L4,438M14,434L14,442M153,18L153,26" + fill="none" stroke="#D3D3D3" stroke-width="1"> + + 1 + + 1 + + + 1 - * - + - + + * + 1 - + + + * + + 1 - + + d="M4,1132L19,1132Q29,1132,29,1122L29,32Q29,22,39,22L54,22L39,22Q29,22,29,32L29,1122Q29,1132,19,1132L4,1132L4,1132M4,1128L14,1132L4,1136M44,18L44,26" + fill="none" stroke="#D3D3D3" stroke-width="1"> + + * + + 1 + + + 1 - + * + + + + + * + + 1 + + + + + 1 + * - - + User - - - + + + id - - String - - - + + + username - - - - String - - - + + + firstName - - - - String - - - + + + lastName - - - - String - - - hash - + + hash + - - - String - - - email - + + email + - - - String - - - + + + createdAt - - - - DateTime - - - + + + updatedAt - DateTime - - - + + + accountIsVerified - - - - Boolean - - - + + + dateOfBirth - - - - DateTime - - - role - + + role + - - - - - Role - - - + + + bio + String + + + + beerPosts - - - - BeerPost - - - + + + beerStyles - - - - BeerStyle - - - + + + breweryPosts - - - - BreweryPost - - - + + + beerComments - - - - BeerComment - - - + + + breweryComments - - - - BreweryComment - - - - BeerPostLikes - + + + beerPostLikes + - - - BeerPostLike - - - - BeerImage - + + + beerImages + - - - BeerImage - - - - BreweryImage - + + + breweryImages + - - - BreweryImage - - - - BreweryPostLike - + + + breweryPostLikes + - - - BreweryPostLike - - - - Location - + + + locations + - - - - Location + BreweryLocation - - - - Glassware - + + + glasswares + - - - Glassware - - - + + + beerStyleLikes + + + + + BeerStyleLike + + + + + beerStyleComments + + + + + BeerStyleComment + + + + + userAvatar + + UserAvatar + + + + - BeerPost + UserAvatar - - - + + + id - - String - - - name - + + path + - - - String - - - ibu - + + alt + - - - Float - - - - abv - - - - Float - - - - - description - - - - String - - - - postedBy - + + caption + - - - String + + + + user + + + + User - - - - postedById - + + userId + - - - String - - - brewery - + + + createdAt + - - - + DateTime + + + + + updatedAt + + DateTime + + + + + BeerPost + + + + + id + + + String + + + + name + + + + String + + + + ibu + + + + Float + + + + abv + + + + Float + + + + + description + + + + String + + + + + postedBy + + + + User + + + + + postedById + + + + String + + + + brewery + + + + BreweryPost - - - + + + breweryId - - - - String - - - style - + + style + - - - BeerStyle - - - styleId - + + styleId + - - - String - - - + + + createdAt - - - - DateTime - - - + + + updatedAt - DateTime - - - + + + beerComments - - - - BeerComment - - - + + + beerImages - - - - BeerImage - - - - BeerPostLikes - + + + beerPostLikes + - - - BeerPostLike - - - + + BeerPostLike - - - + + + id - - String - - - + + + beerPost - - - - BeerPost - - - + + + beerPostId - - - - String - - - likedBy - + + likedBy + - - - User - - - + + + likedById - - - - String - - - + + + createdAt - - - - DateTime - - - + + + updatedAt - DateTime - - - + + BreweryPostLike - - - + + + id - - String - - - + + + breweryPost - - - - BreweryPost - - - + + + breweryPostId - - - - String - - - likedBy - + + likedBy + - - - User - - - + + + likedById - - - - String - - - - createdAt - - - - - DateTime - - - - - updatedAt - - DateTime - - - - - BeerComment - - - - - id - - - String - - - - rating - - - - Int - - - - - beerPost - - - - - BeerPost - - - - - beerPostId - - - - String - - - - - postedBy - - - - User - - - - - postedById - - - - String - - - - content - - - - String - - - - - createdAt - - - - - DateTime - - - - updatedAt - + + createdAt + + + + DateTime - - - - BeerStyle + + + + updatedAt + + DateTime - - - + + + + BeerComment + + + + id - - String - - - name - + + rating + - - - Int + + + + + beerPost + + + + + BeerPost + + + + + beerPostId + + + + String - - - - description - - - - String - - - - - createdAt - - - - - DateTime - - - - - updatedAt - - DateTime - - - - + + + postedBy - - - - User - - - + + + + postedById + + + + String + + + + content + + + + String + + + + + createdAt + + + + + DateTime + + + + + updatedAt + + DateTime + + + + + BeerStyle + + + + + id + + + String + + + + name + + + + String + + + + + description + + + + String + + + + + createdAt + + + + + DateTime + + + + + updatedAt + + DateTime + + + + + postedBy + + + + User + + + + glassware - - - - Glassware - - - + + + glasswareId - - - - String - - - + + + postedById - - - - String - - - + + + abvRange - - - - Float[] - - - + + + ibuRange - - - - Float[] - - - + + + beerPosts - - - - BeerPost - - - + + + beerStyleLike + + + + + BeerStyleLike + + + + + beerStyleComment + + + + + BeerStyleComment + + + + + BeerStyleLike + + + + + id + + + String + + + + + beerStyle + + + + + BeerStyle + + + + + beerStyleId + + + + String + + + + likedBy + + + + User + + + + + likedById + + + + String + + + + + createdAt + + + + + DateTime + + + + + updatedAt + + DateTime + + + + + BeerStyleComment + + + + + id + + + String + + + + rating + + + + Int + + + + + beerStyle + + + + + BeerStyle + + + + + beerStyleId + + + + String + + + + + postedBy + + + + User + + + + + postedById + + + + String + + + + content + + + + String + + + + + createdAt + + + + + DateTime + + + + + updatedAt + + DateTime + + + + Glassware - - - + + + id - - String - - - name - + + name + - - - String - - - + + + description - - - - String - - - + + + createdAt - - - - DateTime - - - + + + updatedAt - DateTime - - - + + + postedBy - - - - User - - - + + + postedById - - - - String - - - - BeerStyle - + + + beerStyle + - - - BeerStyle - - - + + - Location + BreweryLocation - - - + + + id - - String - - - city - + + city + - - - String - - - + + + stateOrProvince - String - - - country - + + country + String - - - + + + coordinates - - - - Float[] - - - address - + + address + - - - String - - - + + + postedBy - - - - User - - - + + + postedById - - - - String - - - - BreweryPost - + + + breweryPost + BreweryPost - - - + + + createdAt - - - - DateTime - - - + + + updatedAt - DateTime - - - + + BreweryPost - - - + + + id - - String - - - name - + + name + - - - String - - - + + + location - - - - - Location + BreweryLocation - - - + + + locationId - - - - String - - - beers - + + beers + - - - BeerPost - - - + + + description - - - - String - - - + + + createdAt - - - - DateTime - - - + + + updatedAt - DateTime - - - + + + postedBy - - - - User - - - + + + postedById - - - - String - - - + + + breweryComments - - - - BreweryComment - - - + + + breweryImages - - - - BreweryImage - - - + + + breweryPostLike - - - - BreweryPostLike - - - + + + dateEstablished - - - - DateTime - - - + + BreweryComment - - - + + + id - - String - - - rating - + + rating + - - - Int - - - + + + breweryPost - - - - BreweryPost - - - + + + breweryPostId - - - - String - - - + + + postedBy - - - - User - - - + + + postedById - - - - String - - - content - + + content + - - - String - - - + + + createdAt - - - - DateTime - - - + + + updatedAt - DateTime - - - + + BeerImage - - - + + + id - - String - - - + + + beerPost - - - - BeerPost - - - + + + beerPostId - - - - String - - - path - + + path + - - - String - - - alt - + + alt + - - - String - - - caption - + + caption + - - - String - - - + + + createdAt - - - - DateTime - - - + + + updatedAt - DateTime - - - + + + postedBy - - - - User - - - + + + postedById - - - - String - - - + + BreweryImage - - - + + + id - - String - - - + + + breweryPost - - - - BreweryPost - - - + + + breweryPostId - - - - String - - - path - + + path + - - - String - - - + + + createdAt - - - - DateTime - - - + + + updatedAt - DateTime - - - caption - + + caption + - - - String - - - alt - + + alt + - - - String - - - + + + postedBy - - - - User - - - + + + postedById - - - - String \ No newline at end of file From 3b973252fc13aaa93f0fafc7fa05de3c077f8685 Mon Sep 17 00:00:00 2001 From: Aaron William Po Date: Mon, 6 Nov 2023 15:56:25 -0500 Subject: [PATCH 04/13] Feat: fix profile avatars in comments This reverts the change to the comment content body component in the previous commit. --- .../BeerBreweryComments/CommentCardBody.tsx | 43 ++++++--- .../CommentContentBody.tsx | 96 ++++++++----------- .../BeerBreweryComments/EditCommentBody.tsx | 2 +- .../seed/create/createNewUserAvatars.ts | 3 +- 4 files changed, 72 insertions(+), 72 deletions(-) diff --git a/src/components/BeerBreweryComments/CommentCardBody.tsx b/src/components/BeerBreweryComments/CommentCardBody.tsx index f7ae738..2191983 100644 --- a/src/components/BeerBreweryComments/CommentCardBody.tsx +++ b/src/components/BeerBreweryComments/CommentCardBody.tsx @@ -4,7 +4,7 @@ import { FC, useState } from 'react'; import { useInView } from 'react-intersection-observer'; import { z } from 'zod'; import CreateCommentValidationSchema from '@/services/schema/CommentSchema/CreateCommentValidationSchema'; - +import Image from 'next/image'; import CommentContentBody from './CommentContentBody'; import EditCommentBody from './EditCommentBody'; @@ -28,19 +28,36 @@ const CommentCardBody: FC = ({ }) => { const [inEditMode, setInEditMode] = useState(false); + const { userAvatar } = comment.postedBy; return ( -
- {!inEditMode ? ( - - ) : ( - - )} +
+
+
+ {!userAvatar ? null : ( + user avatar + )} +
+
+ +
+ {!inEditMode ? ( + + ) : ( + + )} +
); }; diff --git a/src/components/BeerBreweryComments/CommentContentBody.tsx b/src/components/BeerBreweryComments/CommentContentBody.tsx index 747c43a..1b014c9 100644 --- a/src/components/BeerBreweryComments/CommentContentBody.tsx +++ b/src/components/BeerBreweryComments/CommentContentBody.tsx @@ -5,7 +5,7 @@ import { Dispatch, FC, SetStateAction, useContext } from 'react'; import { Rating } from 'react-daisyui'; import Link from 'next/link'; import CommentQueryResult from '@/services/schema/CommentSchema/CommentQueryResult'; -import Image from 'next/image'; + import { z } from 'zod'; import CommentCardDropdown from './CommentCardDropdown'; @@ -19,65 +19,47 @@ const CommentContentBody: FC = ({ comment, setInEditMod const timeDistance = useTimeDistance(new Date(comment.createdAt)); return ( -
-
-
-
- {comment.postedBy.userAvatar ? ( - {comment.postedBy.userAvatar.alt} - ) : ( -
- {comment.postedBy.username[0]} -
- )} -
-
-
-
-
-

- - {comment.postedBy.username} - -

- - posted{' '} - {' '} - ago - -
- - {user && ( - - )} -
-
- - {Array.from({ length: 5 }).map((val, index) => ( - - ))} - -
+
+
+
-

{comment.content}

+

+ + {comment.postedBy.username} + +

+ + posted{' '} + {' '} + ago +
+ + {user && ( + + )}
+
+ + {Array.from({ length: 5 }).map((val, index) => ( + + ))} + +
+
+
+

{comment.content}

); diff --git a/src/components/BeerBreweryComments/EditCommentBody.tsx b/src/components/BeerBreweryComments/EditCommentBody.tsx index f9439e4..8d18c3f 100644 --- a/src/components/BeerBreweryComments/EditCommentBody.tsx +++ b/src/components/BeerBreweryComments/EditCommentBody.tsx @@ -81,7 +81,7 @@ const EditCommentBody: FC = ({ }; return ( -
+
diff --git a/src/prisma/seed/create/createNewUserAvatars.ts b/src/prisma/seed/create/createNewUserAvatars.ts index 84363e3..0c92b40 100644 --- a/src/prisma/seed/create/createNewUserAvatars.ts +++ b/src/prisma/seed/create/createNewUserAvatars.ts @@ -18,8 +18,9 @@ const createNewUserAvatars = async ({ }: CreateNewUserAvatarsArgs) => { const userAvatars: UserAvatarData[] = []; - const path = imageUrls[Math.floor(Math.random() * imageUrls.length)]; users.forEach((user) => { + const path = imageUrls[Math.floor(Math.random() * imageUrls.length)]; + userAvatars.push({ path, alt: `${user.firstName} ${user.lastName}`, From 3ea9f67f16d2458db7380d73bb1346a18e96420e Mon Sep 17 00:00:00 2001 From: Aaron William Po Date: Tue, 7 Nov 2023 21:26:51 -0500 Subject: [PATCH 05/13] Fix: remove console.log to appease linter --- src/hooks/data-fetching/beer-posts/useBeerPostsByBeerStyles.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/hooks/data-fetching/beer-posts/useBeerPostsByBeerStyles.ts b/src/hooks/data-fetching/beer-posts/useBeerPostsByBeerStyles.ts index c11845c..05879fc 100644 --- a/src/hooks/data-fetching/beer-posts/useBeerPostsByBeerStyles.ts +++ b/src/hooks/data-fetching/beer-posts/useBeerPostsByBeerStyles.ts @@ -46,8 +46,6 @@ const useBeerPostsByBeerStyle = ({ fetcher, ); - console.log(error); - const beerPosts = data?.flatMap((d) => d.beerPosts) ?? []; const pageCount = data?.[0].pageCount ?? 0; const isLoadingMore = size > 0 && data && typeof data[size - 1] === 'undefined'; From d48d9a88860a8ca7194c8894c953509d1bd32fa3 Mon Sep 17 00:00:00 2001 From: Aaron William Po Date: Sat, 11 Nov 2023 20:30:07 -0500 Subject: [PATCH 06/13] Update: all queries involving image now use ImageQueryValidationSchema --- src/components/Account/UserAvatar.tsx | 27 +++++++++++++++++++ .../BeerBreweryComments/CommentCardBody.tsx | 13 ++------- src/pages/api/beers/search.ts | 11 +++++++- src/pages/api/breweries/[id]/beers/index.ts | 11 +++++++- src/services/BeerPost/createNewBeerPost.ts | 11 +++++++- src/services/BeerPost/deleteBeerPostById.ts | 11 +++++++- src/services/BeerPost/editBeerPostById.ts | 11 +++++++- src/services/BeerPost/getAllBeerPosts.ts | 11 +++++++- src/services/BeerPost/getBeerPostById.ts | 11 +++++++- .../BeerPost/getBeerPostsByBeerStyleId.ts | 11 +++++++- .../BeerPost/getBeerPostsByBreweryId.ts | 11 +++++++- .../BeerPost/getBeerRecommendations.ts | 11 +++++++- .../BeerPost/schema/BeerPostQueryResult.ts | 5 ++-- .../BreweryPost/createNewBreweryPost.ts | 11 +++++++- .../BreweryPost/getAllBreweryPosts.ts | 11 +++++++- .../BreweryPost/getBreweryPostById.ts | 11 +++++++- .../schema/BreweryPostQueryResult.ts | 5 ++-- src/services/User/schema/GetUserSchema.ts | 12 ++------- ...blicUserSchema.tsx => PublicUserSchema.ts} | 0 .../CommentSchema/CommentQueryResult.ts | 12 +++------ .../ImageSchema/ImageQueryValidationSchema.ts | 12 +++++++++ 21 files changed, 180 insertions(+), 49 deletions(-) create mode 100644 src/components/Account/UserAvatar.tsx rename src/services/User/schema/{PublicUserSchema.tsx => PublicUserSchema.ts} (100%) create mode 100644 src/services/schema/ImageSchema/ImageQueryValidationSchema.ts diff --git a/src/components/Account/UserAvatar.tsx b/src/components/Account/UserAvatar.tsx new file mode 100644 index 0000000..42e837c --- /dev/null +++ b/src/components/Account/UserAvatar.tsx @@ -0,0 +1,27 @@ +import { FC } from 'react'; +import Image from 'next/image'; +import { z } from 'zod'; +import GetUserSchema from '@/services/User/schema/GetUserSchema'; + +interface UserAvatarProps { + user: { + username: z.infer['username']; + userAvatar: z.infer['userAvatar']; + id: z.infer['id']; + }; +} + +const UserAvatar: FC = ({ user }) => { + const { userAvatar } = user; + return !userAvatar ? null : ( + user avatar + ); +}; + +export default UserAvatar; diff --git a/src/components/BeerBreweryComments/CommentCardBody.tsx b/src/components/BeerBreweryComments/CommentCardBody.tsx index 2191983..c874a7f 100644 --- a/src/components/BeerBreweryComments/CommentCardBody.tsx +++ b/src/components/BeerBreweryComments/CommentCardBody.tsx @@ -4,9 +4,9 @@ import { FC, useState } from 'react'; import { useInView } from 'react-intersection-observer'; import { z } from 'zod'; import CreateCommentValidationSchema from '@/services/schema/CommentSchema/CreateCommentValidationSchema'; -import Image from 'next/image'; import CommentContentBody from './CommentContentBody'; import EditCommentBody from './EditCommentBody'; +import UserAvatar from '../Account/UserAvatar'; interface CommentCardProps { comment: z.infer; @@ -28,20 +28,11 @@ const CommentCardBody: FC = ({ }) => { const [inEditMode, setInEditMode] = useState(false); - const { userAvatar } = comment.postedBy; return (
- {!userAvatar ? null : ( - user avatar - )} +
diff --git a/src/pages/api/beers/search.ts b/src/pages/api/beers/search.ts index 80ea329..e088143 100644 --- a/src/pages/api/beers/search.ts +++ b/src/pages/api/beers/search.ts @@ -31,7 +31,16 @@ const search = async (req: SearchAPIRequest, res: NextApiResponse) => { postedBy: { select: { username: true, id: true } }, brewery: { select: { name: true, id: true } }, style: { select: { name: true, id: true, description: true } }, - beerImages: { select: { alt: true, path: true, caption: true, id: true } }, + beerImages: { + select: { + alt: true, + path: true, + caption: true, + id: true, + createdAt: true, + updatedAt: true, + }, + }, }, where: { OR: [ diff --git a/src/pages/api/breweries/[id]/beers/index.ts b/src/pages/api/breweries/[id]/beers/index.ts index 7b213c5..a7fe24c 100644 --- a/src/pages/api/breweries/[id]/beers/index.ts +++ b/src/pages/api/breweries/[id]/beers/index.ts @@ -34,7 +34,16 @@ const getAllBeersByBrewery = async ( postedBy: { select: { username: true, id: true } }, brewery: { select: { name: true, id: true } }, style: { select: { name: true, id: true, description: true } }, - beerImages: { select: { alt: true, path: true, caption: true, id: true } }, + beerImages: { + select: { + alt: true, + path: true, + caption: true, + id: true, + createdAt: true, + updatedAt: true, + }, + }, }, }); diff --git a/src/services/BeerPost/createNewBeerPost.ts b/src/services/BeerPost/createNewBeerPost.ts index 97475e2..87d19ba 100644 --- a/src/services/BeerPost/createNewBeerPost.ts +++ b/src/services/BeerPost/createNewBeerPost.ts @@ -36,7 +36,16 @@ const createNewBeerPost = ({ ibu: true, createdAt: true, updatedAt: true, - beerImages: { select: { id: true, path: true, caption: true, alt: true } }, + beerImages: { + select: { + alt: true, + path: true, + caption: true, + id: true, + createdAt: true, + updatedAt: true, + }, + }, brewery: { select: { id: true, name: true } }, style: { select: { id: true, name: true, description: true } }, postedBy: { select: { id: true, username: true } }, diff --git a/src/services/BeerPost/deleteBeerPostById.ts b/src/services/BeerPost/deleteBeerPostById.ts index 2344f9b..634712a 100644 --- a/src/services/BeerPost/deleteBeerPostById.ts +++ b/src/services/BeerPost/deleteBeerPostById.ts @@ -19,7 +19,16 @@ const deleteBeerPostById = ({ id: true, name: true, updatedAt: true, - beerImages: { select: { id: true, path: true, caption: true, alt: true } }, + beerImages: { + select: { + alt: true, + path: true, + caption: true, + id: true, + createdAt: true, + updatedAt: true, + }, + }, style: { select: { id: true, name: true, description: true } }, postedBy: { select: { id: true, username: true } }, brewery: { select: { id: true, name: true } }, diff --git a/src/services/BeerPost/editBeerPostById.ts b/src/services/BeerPost/editBeerPostById.ts index bed2629..7f4ae0a 100644 --- a/src/services/BeerPost/editBeerPostById.ts +++ b/src/services/BeerPost/editBeerPostById.ts @@ -25,7 +25,16 @@ const editBeerPostById = ({ ibu: true, createdAt: true, updatedAt: true, - beerImages: { select: { id: true, path: true, caption: true, alt: true } }, + beerImages: { + select: { + alt: true, + path: true, + caption: true, + id: true, + createdAt: true, + updatedAt: true, + }, + }, brewery: { select: { id: true, name: true } }, style: { select: { id: true, name: true, description: true } }, postedBy: { select: { id: true, username: true } }, diff --git a/src/services/BeerPost/getAllBeerPosts.ts b/src/services/BeerPost/getAllBeerPosts.ts index c04ee9e..483f02c 100644 --- a/src/services/BeerPost/getAllBeerPosts.ts +++ b/src/services/BeerPost/getAllBeerPosts.ts @@ -25,7 +25,16 @@ const getAllBeerPosts = ({ style: { select: { name: true, id: true, description: true } }, brewery: { select: { name: true, id: true } }, postedBy: { select: { id: true, username: true } }, - beerImages: { select: { path: true, caption: true, id: true, alt: true } }, + beerImages: { + select: { + alt: true, + path: true, + caption: true, + id: true, + createdAt: true, + updatedAt: true, + }, + }, }, take: pageSize, skip: (pageNum - 1) * pageSize, diff --git a/src/services/BeerPost/getBeerPostById.ts b/src/services/BeerPost/getBeerPostById.ts index 57b3759..407c143 100644 --- a/src/services/BeerPost/getBeerPostById.ts +++ b/src/services/BeerPost/getBeerPostById.ts @@ -19,7 +19,16 @@ const getBeerPostById = async ( postedBy: { select: { username: true, id: true } }, brewery: { select: { name: true, id: true } }, style: { select: { name: true, id: true, description: true } }, - beerImages: { select: { alt: true, path: true, caption: true, id: true } }, + beerImages: { + select: { + alt: true, + path: true, + caption: true, + id: true, + createdAt: true, + updatedAt: true, + }, + }, }, where: { id }, }); diff --git a/src/services/BeerPost/getBeerPostsByBeerStyleId.ts b/src/services/BeerPost/getBeerPostsByBeerStyleId.ts index adc1fc7..6fabe91 100644 --- a/src/services/BeerPost/getBeerPostsByBeerStyleId.ts +++ b/src/services/BeerPost/getBeerPostsByBeerStyleId.ts @@ -28,7 +28,16 @@ const getBeerPostsByBeerStyleId = async ({ postedBy: { select: { username: true, id: true } }, brewery: { select: { name: true, id: true } }, style: { select: { name: true, id: true, description: true } }, - beerImages: { select: { alt: true, path: true, caption: true, id: true } }, + beerImages: { + select: { + alt: true, + path: true, + caption: true, + id: true, + createdAt: true, + updatedAt: true, + }, + }, }, }); diff --git a/src/services/BeerPost/getBeerPostsByBreweryId.ts b/src/services/BeerPost/getBeerPostsByBreweryId.ts index 910391b..2d69ecb 100644 --- a/src/services/BeerPost/getBeerPostsByBreweryId.ts +++ b/src/services/BeerPost/getBeerPostsByBreweryId.ts @@ -28,7 +28,16 @@ const getBeerPostsByBeerStyleId = async ({ postedBy: { select: { username: true, id: true } }, brewery: { select: { name: true, id: true } }, style: { select: { name: true, id: true, description: true } }, - beerImages: { select: { alt: true, path: true, caption: true, id: true } }, + beerImages: { + select: { + alt: true, + path: true, + caption: true, + id: true, + createdAt: true, + updatedAt: true, + }, + }, }, }); diff --git a/src/services/BeerPost/getBeerRecommendations.ts b/src/services/BeerPost/getBeerRecommendations.ts index e855548..2fce906 100644 --- a/src/services/BeerPost/getBeerRecommendations.ts +++ b/src/services/BeerPost/getBeerRecommendations.ts @@ -37,7 +37,16 @@ const getBeerRecommendations = async ({ style: { select: { name: true, id: true, description: true } }, brewery: { select: { name: true, id: true } }, postedBy: { select: { id: true, username: true } }, - beerImages: { select: { path: true, caption: true, id: true, alt: true } }, + beerImages: { + select: { + alt: true, + path: true, + caption: true, + id: true, + createdAt: true, + updatedAt: true, + }, + }, }, take, skip, diff --git a/src/services/BeerPost/schema/BeerPostQueryResult.ts b/src/services/BeerPost/schema/BeerPostQueryResult.ts index 9fca4cd..b19441a 100644 --- a/src/services/BeerPost/schema/BeerPostQueryResult.ts +++ b/src/services/BeerPost/schema/BeerPostQueryResult.ts @@ -1,3 +1,4 @@ +import ImageQueryValidationSchema from '@/services/schema/ImageSchema/ImageQueryValidationSchema'; import { z } from 'zod'; const BeerPostQueryResult = z.object({ @@ -5,9 +6,7 @@ const BeerPostQueryResult = z.object({ name: z.string(), brewery: z.object({ id: z.string(), name: z.string() }), description: z.string(), - beerImages: z.array( - z.object({ path: z.string(), caption: z.string(), id: z.string(), alt: z.string() }), - ), + beerImages: z.array(ImageQueryValidationSchema), ibu: z.number(), abv: z.number(), style: z.object({ id: z.string(), name: z.string(), description: z.string() }), diff --git a/src/services/BreweryPost/createNewBreweryPost.ts b/src/services/BreweryPost/createNewBreweryPost.ts index 2d60a3b..cdcc66a 100644 --- a/src/services/BreweryPost/createNewBreweryPost.ts +++ b/src/services/BreweryPost/createNewBreweryPost.ts @@ -37,7 +37,16 @@ const createNewBreweryPost = async ({ createdAt: true, dateEstablished: true, postedBy: { select: { id: true, username: true } }, - breweryImages: { select: { path: true, caption: true, id: true, alt: true } }, + breweryImages: { + select: { + path: true, + caption: true, + id: true, + alt: true, + createdAt: true, + updatedAt: true, + }, + }, location: { select: { city: true, diff --git a/src/services/BreweryPost/getAllBreweryPosts.ts b/src/services/BreweryPost/getAllBreweryPosts.ts index d913aa9..c83883c 100644 --- a/src/services/BreweryPost/getAllBreweryPosts.ts +++ b/src/services/BreweryPost/getAllBreweryPosts.ts @@ -29,7 +29,16 @@ const getAllBreweryPosts = async ({ description: true, name: true, postedBy: { select: { username: true, id: true } }, - breweryImages: { select: { path: true, caption: true, id: true, alt: true } }, + breweryImages: { + select: { + path: true, + caption: true, + id: true, + alt: true, + createdAt: true, + updatedAt: true, + }, + }, createdAt: true, dateEstablished: true, }, diff --git a/src/services/BreweryPost/getBreweryPostById.ts b/src/services/BreweryPost/getBreweryPostById.ts index 55509a4..51b5db9 100644 --- a/src/services/BreweryPost/getBreweryPostById.ts +++ b/src/services/BreweryPost/getBreweryPostById.ts @@ -19,7 +19,16 @@ const getBreweryPostById = async (id: string) => { }, description: true, name: true, - breweryImages: { select: { path: true, caption: true, id: true, alt: true } }, + breweryImages: { + select: { + path: true, + caption: true, + id: true, + alt: true, + createdAt: true, + updatedAt: true, + }, + }, postedBy: { select: { username: true, id: true } }, createdAt: true, dateEstablished: true, diff --git a/src/services/BreweryPost/schema/BreweryPostQueryResult.ts b/src/services/BreweryPost/schema/BreweryPostQueryResult.ts index 21b1874..98ecac0 100644 --- a/src/services/BreweryPost/schema/BreweryPostQueryResult.ts +++ b/src/services/BreweryPost/schema/BreweryPostQueryResult.ts @@ -1,3 +1,4 @@ +import ImageQueryValidationSchema from '@/services/schema/ImageSchema/ImageQueryValidationSchema'; import { z } from 'zod'; const BreweryPostQueryResult = z.object({ @@ -12,9 +13,7 @@ const BreweryPostQueryResult = z.object({ stateOrProvince: z.string().nullable(), }), postedBy: z.object({ id: z.string(), username: z.string() }), - breweryImages: z.array( - z.object({ path: z.string(), caption: z.string(), id: z.string(), alt: z.string() }), - ), + breweryImages: z.array(ImageQueryValidationSchema), createdAt: z.coerce.date(), dateEstablished: z.coerce.date(), }); diff --git a/src/services/User/schema/GetUserSchema.ts b/src/services/User/schema/GetUserSchema.ts index eaf21b7..eca414d 100644 --- a/src/services/User/schema/GetUserSchema.ts +++ b/src/services/User/schema/GetUserSchema.ts @@ -1,3 +1,4 @@ +import ImageQueryValidationSchema from '@/services/schema/ImageSchema/ImageQueryValidationSchema'; import { z } from 'zod'; const GetUserSchema = z.object({ @@ -12,16 +13,7 @@ const GetUserSchema = z.object({ accountIsVerified: z.boolean(), role: z.enum(['USER', 'ADMIN']), bio: z.string().nullable(), - userAvatar: z - .object({ - id: z.string().cuid(), - path: z.string().url(), - alt: z.string(), - caption: z.string(), - createdAt: z.coerce.date(), - updatedAt: z.coerce.date().nullable(), - }) - .nullable(), + userAvatar: ImageQueryValidationSchema.nullable(), }); export default GetUserSchema; diff --git a/src/services/User/schema/PublicUserSchema.tsx b/src/services/User/schema/PublicUserSchema.ts similarity index 100% rename from src/services/User/schema/PublicUserSchema.tsx rename to src/services/User/schema/PublicUserSchema.ts diff --git a/src/services/schema/CommentSchema/CommentQueryResult.ts b/src/services/schema/CommentSchema/CommentQueryResult.ts index bf94cd9..f784076 100644 --- a/src/services/schema/CommentSchema/CommentQueryResult.ts +++ b/src/services/schema/CommentSchema/CommentQueryResult.ts @@ -1,23 +1,17 @@ import { z } from 'zod'; +import ImageQueryValidationSchema from '../ImageSchema/ImageQueryValidationSchema'; const CommentQueryResult = z.object({ id: z.string().cuid(), content: z.string().min(1).max(500), rating: z.number().int().min(1).max(5), createdAt: z.coerce.date(), + updatedAt: z.coerce.date().nullable(), postedBy: z.object({ id: z.string().cuid(), username: z.string().min(1).max(50), - userAvatar: z - .object({ - id: z.string().cuid(), - path: z.string().url(), - alt: z.string().min(1).max(50), - caption: z.string().min(1).max(50), - }) - .nullable(), + userAvatar: ImageQueryValidationSchema.nullable(), }), - updatedAt: z.coerce.date().nullable(), }); export default CommentQueryResult; diff --git a/src/services/schema/ImageSchema/ImageQueryValidationSchema.ts b/src/services/schema/ImageSchema/ImageQueryValidationSchema.ts new file mode 100644 index 0000000..fa6fcb7 --- /dev/null +++ b/src/services/schema/ImageSchema/ImageQueryValidationSchema.ts @@ -0,0 +1,12 @@ +import { z } from 'zod'; + +const ImageQueryValidationSchema = z.object({ + id: z.string().cuid(), + path: z.string().url(), + alt: z.string(), + caption: z.string(), + createdAt: z.coerce.date(), + updatedAt: z.coerce.date().nullable(), +}); + +export default ImageQueryValidationSchema; From 24e245fc6fa9ecdd6a54536a4ecaf893b4e1728f Mon Sep 17 00:00:00 2001 From: Aaron William Po Date: Sun, 12 Nov 2023 17:32:43 -0500 Subject: [PATCH 07/13] feat: implement user follow system --- .../migrations/20231112221155_/migration.sql | 14 +++++ src/prisma/schema.prisma | 12 +++++ .../seed/create/createNewUserFollows.ts | 54 +++++++++++++++++++ src/prisma/seed/create/createNewUsers.ts | 3 ++ src/prisma/seed/index.ts | 5 ++ 5 files changed, 88 insertions(+) create mode 100644 src/prisma/migrations/20231112221155_/migration.sql create mode 100644 src/prisma/seed/create/createNewUserFollows.ts diff --git a/src/prisma/migrations/20231112221155_/migration.sql b/src/prisma/migrations/20231112221155_/migration.sql new file mode 100644 index 0000000..ade0a10 --- /dev/null +++ b/src/prisma/migrations/20231112221155_/migration.sql @@ -0,0 +1,14 @@ +-- CreateTable +CREATE TABLE "UserFollow" ( + "followerId" TEXT NOT NULL, + "followingId" TEXT NOT NULL, + "followedAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "UserFollow_pkey" PRIMARY KEY ("followerId","followingId") +); + +-- AddForeignKey +ALTER TABLE "UserFollow" ADD CONSTRAINT "UserFollow_followerId_fkey" FOREIGN KEY ("followerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "UserFollow" ADD CONSTRAINT "UserFollow_followingId_fkey" FOREIGN KEY ("followingId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/src/prisma/schema.prisma b/src/prisma/schema.prisma index e485041..42b7ec6 100644 --- a/src/prisma/schema.prisma +++ b/src/prisma/schema.prisma @@ -44,6 +44,18 @@ model User { beerStyleLikes BeerStyleLike[] beerStyleComments BeerStyleComment[] userAvatar UserAvatar? + followedBy UserFollow[] @relation("following") + following UserFollow[] @relation("follower") +} + +model UserFollow { + follower User @relation("follower", fields: [followerId], references: [id]) + followerId String + following User @relation("following", fields: [followingId], references: [id]) + followingId String + followedAt DateTime @default(now()) @db.Timestamptz(3) + + @@id([followerId, followingId]) } model UserAvatar { diff --git a/src/prisma/seed/create/createNewUserFollows.ts b/src/prisma/seed/create/createNewUserFollows.ts new file mode 100644 index 0000000..aa87f0b --- /dev/null +++ b/src/prisma/seed/create/createNewUserFollows.ts @@ -0,0 +1,54 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import { faker } from '@faker-js/faker'; +import type { User } from '@prisma/client'; + +import DBClient from '../../DBClient'; + +interface CreateNewUserFollowsArgs { + joinData: { users: User[] }; +} + +interface UserFollowData { + followerId: string; + followingId: string; + followedAt: Date; +} + +const createNewUserFollows = async ({ + joinData: { users }, +}: CreateNewUserFollowsArgs) => { + const userFollows: UserFollowData[] = []; + + users.forEach((user) => { + // Get 20 random users to follow. + const randomUsers = users + .filter((randomUser) => randomUser.id !== user.id) + .sort(() => Math.random() - Math.random()) + .slice(0, 20); + + // Get the user to follow the random users, and the random users to follow the user. + const data = randomUsers.flatMap((randomUser) => [ + { + followerId: user.id, + followingId: randomUser.id, + followedAt: faker.date.between({ from: user.createdAt, to: new Date() }), + }, + { + followerId: randomUser.id, + followingId: user.id, + followedAt: faker.date.between({ from: randomUser.createdAt, to: new Date() }), + }, + ]); + + userFollows.push(...data); + }); + + await DBClient.instance.userFollow.createMany({ + data: userFollows, + skipDuplicates: true, + }); + + return DBClient.instance.userFollow.findMany(); +}; + +export default createNewUserFollows; diff --git a/src/prisma/seed/create/createNewUsers.ts b/src/prisma/seed/create/createNewUsers.ts index e61fcf6..96f6a2f 100644 --- a/src/prisma/seed/create/createNewUsers.ts +++ b/src/prisma/seed/create/createNewUsers.ts @@ -18,6 +18,7 @@ interface UserData { hash: string; accountIsVerified: boolean; role: 'USER' | 'ADMIN'; + bio: string; } const createNewUsers = async ({ numberOfUsers }: CreateNewUsersArgs) => { @@ -54,6 +55,7 @@ const createNewUsers = async ({ numberOfUsers }: CreateNewUsersArgs) => { const dateOfBirth = faker.date.birthdate({ mode: 'age', min: 19 }); const createdAt = faker.date.past({ years: 4 }); + const bio = faker.lorem.paragraphs(3).replace(/\n/g, ' '); const user: UserData = { firstName, @@ -63,6 +65,7 @@ const createNewUsers = async ({ numberOfUsers }: CreateNewUsersArgs) => { dateOfBirth, createdAt, hash, + bio, accountIsVerified: true, role: 'USER', }; diff --git a/src/prisma/seed/index.ts b/src/prisma/seed/index.ts index 4139ba2..e4d4420 100644 --- a/src/prisma/seed/index.ts +++ b/src/prisma/seed/index.ts @@ -19,6 +19,7 @@ import createAdminUser from './create/createAdminUser'; import createNewBeerStyleComments from './create/createNewBeerStyleComments'; import createNewBeerStyleLikes from './create/createNewBeerStyleLikes'; import createNewUserAvatars from './create/createNewUserAvatars'; +import createNewUserFollows from './create/createNewUserFollows'; (async () => { try { @@ -37,6 +38,9 @@ import createNewUserAvatars from './create/createNewUserAvatars'; const userAvatars = await createNewUserAvatars({ joinData: { users } }); logger.info('User avatars created successfully.'); + const userFollows = await createNewUserFollows({ joinData: { users } }); + logger.info('User follows created successfully.'); + const locations = await createNewLocations({ numberOfLocations: 500, joinData: { users }, @@ -108,6 +112,7 @@ import createNewUserAvatars from './create/createNewUserAvatars'; logger.info({ numberOfUsers: users.length, numberOfUserAvatars: userAvatars.length, + numberOfUserFollows: userFollows.length, numberOfBreweryPosts: breweryPosts.length, numberOfBeerPosts: beerPosts.length, numberOfBeerStyles: beerStyles.length, From b939219c67edbbe407ef6a8da4ce2732ade29e82 Mon Sep 17 00:00:00 2001 From: Aaron William Po Date: Sun, 12 Nov 2023 17:43:48 -0500 Subject: [PATCH 08/13] Fix: update dependencies, remove sparkpost-node This commit removes the sparkpost-node and switches to using a raw api call using fetch. This commit also updates the dependency react-email. --- package-lock.json | 1648 ++++++++--------------------- package.json | 9 +- src/config/sparkpost/client.ts | 6 - src/config/sparkpost/sendEmail.ts | 23 +- 4 files changed, 448 insertions(+), 1238 deletions(-) delete mode 100644 src/config/sparkpost/client.ts diff --git a/package-lock.json b/package-lock.json index cf6eeab..ffd63d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,9 +17,9 @@ "@mapbox/search-js-react": "^1.0.0-beta.17", "@next/bundle-analyzer": "^13.4.10", "@prisma/client": "^5.0.0", - "@react-email/components": "^0.0.7", - "@react-email/render": "^0.0.7", - "@react-email/tailwind": "^0.0.8", + "@react-email/components": "^0.0.11", + "@react-email/render": "^0.0.9", + "@react-email/tailwind": "^0.0.12", "@vercel/analytics": "^1.1.0", "argon2": "^0.31.1", "cloudinary": "^1.41.0", @@ -40,14 +40,13 @@ "react": "^18.2.0", "react-daisyui": "^4.0.0", "react-dom": "^18.2.0", - "react-email": "^1.9.4", + "react-email": "^1.9.5", "react-hook-form": "^7.45.2", "react-hot-toast": "^2.4.1", "react-icons": "^4.10.1", "react-intersection-observer": "^9.5.2", "react-map-gl": "^7.1.2", "react-responsive-carousel": "^3.2.23", - "sparkpost": "^2.1.4", "swr": "^2.2.0", "theme-change": "^2.5.0", "zod": "^3.21.4" @@ -84,6 +83,9 @@ "tailwindcss-animate": "^1.0.6", "ts-node": "^10.9.1", "typescript": "^5.2.2" + }, + "engines": { + "node": ">=20.0.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -1635,122 +1637,136 @@ "integrity": "sha512-+nUQM/y8C+1GG5Ioeqcu6itFslCfxvQSAUVSMC9XM2G2Fcq0F4Afnp6m0pXF6X6iUBWen7jZBPmM9Qlq4Nr3/A==" }, "node_modules/@radix-ui/react-compose-refs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.0.tgz", - "integrity": "sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", "dependencies": { "@babel/runtime": "^7.13.10" }, "peerDependencies": { + "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, "node_modules/@radix-ui/react-slot": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.0.tgz", - "integrity": "sha512-3mrKauI/tWXo1Ll+gN5dHcxDPdm/Df1ufcDLCecn+pnCIVcdWE7CujXo8QaXOWRJyZyQWWbpB8eFwHzWXlv5mQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", "dependencies": { "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.0" + "@radix-ui/react-compose-refs": "1.0.1" }, "peerDependencies": { + "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, "node_modules/@react-email/body": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@react-email/body/-/body-0.0.2.tgz", - "integrity": "sha512-SqZrZdxZlH7viwnrLvrMnVzOKpiofVAtho09bmm2siDzy0VMDGItXRzUPLcpg9vcbVJCHZRCIKoNXqA+PtokzQ==", - "dependencies": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@react-email/body/-/body-0.0.4.tgz", + "integrity": "sha512-NmHOumdmyjWvOXomqhQt06KbgRxhHrVznxQp/oWiPWes8nAJo2Y4L27aPHR9nTcs7JF7NmcJe9YSN42pswK+GQ==", + "peerDependencies": { "react": "18.2.0" } }, "node_modules/@react-email/button": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@react-email/button/-/button-0.0.9.tgz", - "integrity": "sha512-eYWQ1X4RFlkKYYSPgSrT6rk98wuLOieEAGENrp9j37t1v/1C+jMmBu0UjZvwHsHWdbOMRjbVDFeMI/+MxWKSEg==", - "dependencies": { - "react": "18.2.0" - }, + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@react-email/button/-/button-0.0.11.tgz", + "integrity": "sha512-mB5ySfZifwE5ybtIWwXGbmKk1uKkH4655gftL4+mMxZAZCkINVa2KXTi5pO+xZhMtJI9xtAsikOrOEU1gTDoww==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": "18.2.0" } }, "node_modules/@react-email/column": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@react-email/column/-/column-0.0.7.tgz", - "integrity": "sha512-B29wVXyIcuVprgGpLkR23waPh/twlqmugZQsCKk05JlMCQ80/Puv4Lgj4dRsIJzgyTLMwG6xq17+Uxc5iGfuaQ==", - "dependencies": { - "react": "18.2.0" - }, + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@react-email/column/-/column-0.0.8.tgz", + "integrity": "sha512-blChqGU8e/L6KZiB5EPww8bkZfdyHDuS0vKIvU+iS14uK+xfAw+5P5CU9BYXccEuJh2Gftfngu1bWMFp2Sc6ag==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": "18.2.0" } }, "node_modules/@react-email/components": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@react-email/components/-/components-0.0.7.tgz", - "integrity": "sha512-GpRKV8E7EvK9OPf61f5Z8hliB3p0hTot8tslmEUVCTtX7tdL0wM2YEcZiDWU4PJcudJ/QWHJ7Y5wGzNEARcooA==", + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@react-email/components/-/components-0.0.11.tgz", + "integrity": "sha512-wj9Sra/AGQvadb3ZABz44ll9Fb9FvXPEmODXRWbNRSc8pJTFGWorrsm4M/yj8dnewd4HtnbLkV1eDOvuiLAVLA==", "dependencies": { - "@react-email/body": "0.0.2", - "@react-email/button": "0.0.9", - "@react-email/column": "0.0.7", - "@react-email/container": "0.0.8", - "@react-email/font": "0.0.2", - "@react-email/head": "0.0.5", - "@react-email/heading": "0.0.8", - "@react-email/hr": "0.0.5", - "@react-email/html": "0.0.4", - "@react-email/img": "0.0.5", - "@react-email/link": "0.0.5", - "@react-email/preview": "0.0.6", - "@react-email/render": "0.0.7", - "@react-email/row": "0.0.5", - "@react-email/section": "0.0.9", - "@react-email/tailwind": "0.0.8", - "@react-email/text": "0.0.5", - "react": "18.2.0" + "@react-email/body": "0.0.4", + "@react-email/button": "0.0.11", + "@react-email/column": "0.0.8", + "@react-email/container": "0.0.10", + "@react-email/font": "0.0.4", + "@react-email/head": "0.0.6", + "@react-email/heading": "0.0.9", + "@react-email/hr": "0.0.6", + "@react-email/html": "0.0.6", + "@react-email/img": "0.0.6", + "@react-email/link": "0.0.6", + "@react-email/preview": "0.0.7", + "@react-email/render": "0.0.9", + "@react-email/row": "0.0.6", + "@react-email/section": "0.0.10", + "@react-email/tailwind": "0.0.12", + "@react-email/text": "0.0.6" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": "18.2.0" } }, "node_modules/@react-email/container": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@react-email/container/-/container-0.0.8.tgz", - "integrity": "sha512-MQZQxvTOoLWjJR+Jm689jltm0I/mtZbEaDnwZbNkkHKgccr++wwb9kOKMgXG777Y7tGa1JATAsZpvFYiCITwUg==", - "dependencies": { - "react": "18.2.0" - }, + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@react-email/container/-/container-0.0.10.tgz", + "integrity": "sha512-goishY7ocq+lord0043/LZK268bqvMFW/sxpUt/dSCPJyrrZZNCbpW2t8w8HztU38cYj0qGQLxO5Qvpn/RER3w==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": "18.2.0" } }, "node_modules/@react-email/font": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@react-email/font/-/font-0.0.2.tgz", - "integrity": "sha512-mmkyOCAcbgytE7DfIuOBVG1YVDUZY9rPCor4o7pUEzGJiU2y/TNuV8CgNPSU/VgXeBKL/94QDjB62OrGHlFNMQ==", - "dependencies": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@react-email/font/-/font-0.0.4.tgz", + "integrity": "sha512-rN/pFlAcDNmfYFxpufT/rFRrM5KYBJM4nTA2uylTehlVOro6fb/q6n0zUwLF6OmQ4QIuRbqdEy7DI9mmJiNHxA==", + "peerDependencies": { "react": "18.2.0" } }, "node_modules/@react-email/head": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@react-email/head/-/head-0.0.5.tgz", - "integrity": "sha512-s84OxJxZMee2z5b1a+RVwY1NOSUNNf1ecjPf6n64aZmMNcNUyn4gOl7RO6xbfBrZko7TigBwsFB1Cgjxtn/ydg==", - "dependencies": { - "react": "18.2.0" - }, + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@react-email/head/-/head-0.0.6.tgz", + "integrity": "sha512-9BrBDalb34nBOmmQVQc7/pjJotcuAeC3rhBl4G88Ohiipuv15vPIKqwy8vPJcFNi4l7yGlitfG3EESIjkLkoIw==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": "18.2.0" } }, "node_modules/@react-email/heading": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@react-email/heading/-/heading-0.0.8.tgz", - "integrity": "sha512-7atATmoHBHTk7hFYFsFFzOIBV3u1zPpsSOWkLBojdjSUdenpk2SbX8GP8/3aBhWl/tuFX9RBGcu1Xes+ZijFLg==", + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@react-email/heading/-/heading-0.0.9.tgz", + "integrity": "sha512-xzkcGlm+/aFrNlJZBKzxRKkRYJ2cRx92IqmSKAuGnwuKQ/uMKomXzPsHPu3Dclmnhn3wVKj4uprkgQOoxP6uXQ==", "dependencies": { - "@radix-ui/react-slot": "1.0.0", + "@radix-ui/react-slot": "1.0.2", "react": "18.2.0" }, "engines": { @@ -1758,113 +1774,179 @@ } }, "node_modules/@react-email/hr": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@react-email/hr/-/hr-0.0.5.tgz", - "integrity": "sha512-nwB8GmSdvPlR/bWjDS07yHtgdfJqtvCaPXee3SVUY69YYP7NeDO/VACJlgrS9V2l79bj1lUpH0MJMU6MNAk5FQ==", - "dependencies": { - "react": "18.2.0" - }, + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@react-email/hr/-/hr-0.0.6.tgz", + "integrity": "sha512-W+wINBz7z7BRv3i9GS+QoJBae1PESNhv6ZY6eLnEpqtBI/2++suuRNJOU/KpZzE6pykeTp6I/Z7UcL0LEYKgyg==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": "18.2.0" } }, "node_modules/@react-email/html": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@react-email/html/-/html-0.0.4.tgz", - "integrity": "sha512-7tRYSnudYAWez+NkPWOM8yLZH7EuYFtYdiLPnzpD+pf4cdk16Gz4up531DaIX6dNBbfbyEFpQxhXZxGeJ5ZkfQ==", + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@react-email/html/-/html-0.0.6.tgz", + "integrity": "sha512-8Fo20VOqxqc087gGEPjT8uos06fTXIC8NSoiJxpiwAkwiKtQnQH/jOdoLv6XaWh5Zt2clj1uokaoklnaM5rY1w==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": "18.2.0" } }, "node_modules/@react-email/img": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@react-email/img/-/img-0.0.5.tgz", - "integrity": "sha512-9ziFgBfrIAL+DpVlsraFcd2KwsTRyobLpqTnoiBYCcVZGod59xbYkmsmB3CbUosmLwPYg6AeD7Q7e+hCiwkWgg==", - "dependencies": { - "react": "18.2.0" - }, + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@react-email/img/-/img-0.0.6.tgz", + "integrity": "sha512-Wd7xKI3b1Jvb2ZEHyVpJ9D98u0GHrRl+578b8LV24PavM/65V61Q5LN5Fr9sAhj+4VGqnHDIVeXIYEzVbWaa3Q==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": "18.2.0" } }, "node_modules/@react-email/link": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@react-email/link/-/link-0.0.5.tgz", - "integrity": "sha512-z+QW9f4gXBdyfhl7iYMY3td+rXKeZYK/2AGElEMsxVoywn5D0b6cF8m5w2jbf0U2V3enT+zy9yc1R6AyT59NOg==", - "dependencies": { - "react": "18.2.0" - }, + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@react-email/link/-/link-0.0.6.tgz", + "integrity": "sha512-bYYHroWGS//nDl9yhh8V6K2BrNwAsyX7N/XClSCRku3x56NrZ6D0nBKWewYDPlJ9rW9TIaJm1jDYtO9XBzLlkQ==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": "18.2.0" } }, "node_modules/@react-email/preview": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@react-email/preview/-/preview-0.0.6.tgz", - "integrity": "sha512-mXDCc3NGpm/4W7gowBtjsTxYXowLNOLsJsYhIfrsjNJWGlVhVFB9uEHm55LjBLpxSG020g6/8LIrpJU6g22qvg==", - "dependencies": { - "react": "18.2.0" - }, + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@react-email/preview/-/preview-0.0.7.tgz", + "integrity": "sha512-YLfIwHdexPi8IgP1pSuVXdAmKzMQ8ctCCLEjkMttT2vkSFqT6m/e6UFWK2l30rKm2dDsLvQyEvo923mPXjnNzg==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": "18.2.0" } }, "node_modules/@react-email/render": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@react-email/render/-/render-0.0.7.tgz", - "integrity": "sha512-hMMhxk6TpOcDC5qnKzXPVJoVGEwfm+U5bGOPH+MyTTlx0F02RLQygcATBKsbP7aI/mvkmBAZoFbgPIHop7ovug==", + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@react-email/render/-/render-0.0.9.tgz", + "integrity": "sha512-nrim7wiACnaXsGtL7GF6jp3Qmml8J6vAjAH88jkC8lIbfNZaCyuPQHANjyYIXlvQeAbsWADQJFZgOHUqFqjh/A==", "dependencies": { - "html-to-text": "9.0.3", + "html-to-text": "9.0.5", "pretty": "2.0.0", "react": "18.2.0", "react-dom": "18.2.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/@react-email/render/node_modules/@selderee/plugin-htmlparser2": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", + "integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==", + "dependencies": { + "domhandler": "^5.0.3", + "selderee": "^0.11.0" + }, + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, + "node_modules/@react-email/render/node_modules/html-to-text": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz", + "integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==", + "dependencies": { + "@selderee/plugin-htmlparser2": "^0.11.0", + "deepmerge": "^4.3.1", + "dom-serializer": "^2.0.0", + "htmlparser2": "^8.0.2", + "selderee": "^0.11.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@react-email/render/node_modules/parseley": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz", + "integrity": "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==", + "dependencies": { + "leac": "^0.6.0", + "peberminta": "^0.9.0" + }, + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, + "node_modules/@react-email/render/node_modules/peberminta": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz", + "integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==", + "funding": { + "url": "https://ko-fi.com/killymxi" + } + }, + "node_modules/@react-email/render/node_modules/selderee": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz", + "integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==", + "dependencies": { + "parseley": "^0.12.0" + }, + "funding": { + "url": "https://ko-fi.com/killymxi" } }, "node_modules/@react-email/row": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@react-email/row/-/row-0.0.5.tgz", - "integrity": "sha512-dir5l1M7Z/1BQqQkUrKUPIIDPt6ueEf6ScMGoBOcUh+VNNqmnqJE2Q2CH5X3w2uo6a5X7tnVhoJHGa2KTKe8Sw==", + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@react-email/row/-/row-0.0.6.tgz", + "integrity": "sha512-msJ2TnDJNwpgDfDzUO63CvhusJHeaGLMM+8Zz86VPvxzwe/DkT7N48QKRWRCkt8urxVz5U+EgivORA9Dum9p3Q==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": "18.2.0" } }, "node_modules/@react-email/section": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@react-email/section/-/section-0.0.9.tgz", - "integrity": "sha512-3EbcWJ1jUZrzquWSvXrv8Hbk9V+BGvLcMWQIli4NdIpQlddmlGKUYfXU2mB2d2pf+5ojqkGcFZZ9fWxycB84jQ==", - "dependencies": { - "react": "18.2.0" - }, + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@react-email/section/-/section-0.0.10.tgz", + "integrity": "sha512-x9B2KYFqj+d8I1fK9bgeVm/3mLE4Qgn4mm/GbDtcJeSzKU/G7bTb7/3+BMDk9SARPGkg5XAuZm1XgcqQQutt2A==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": "18.2.0" } }, "node_modules/@react-email/tailwind": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@react-email/tailwind/-/tailwind-0.0.8.tgz", - "integrity": "sha512-0BLjD5GpiyBK7YDlaDrjHIpj9eTrrZrMJud3f1UPoCZhS+0S/M8LcR8WMbQsR+8/aLGmiy4F4TGZuRQcsJEsFw==", + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@react-email/tailwind/-/tailwind-0.0.12.tgz", + "integrity": "sha512-s8Ch7GL30qRKScn9NWwItMqxjtzbyUtCnXfC6sL2YTVtulbfvZZ06W+aA0S6f7fdrVlOOlQzZuK/sVaQCHhcSw==", "dependencies": { - "html-react-parser": "3.0.9", "react": "18.2.0", "react-dom": "18.2.0", - "tw-to-css": "0.0.11" + "tw-to-css": "0.0.12" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": "18.2.0" } }, "node_modules/@react-email/text": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@react-email/text/-/text-0.0.5.tgz", - "integrity": "sha512-LXhHiaC6oRRsNAfOzJDos4wQA22eIdVJvR6G7uu4QzUvYNOAatDMf89jRQcKGrxX7InkS640v8sHd9jl5ztM5w==", - "dependencies": { - "react": "18.2.0" - }, + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@react-email/text/-/text-0.0.6.tgz", + "integrity": "sha512-PDUTAD1PjlzXFOIUrR1zuV2xxguL62yne5YLcn1k+u/dVUyzn6iU/5lFShxCfzuh3QDWCf4+JRNnXN9rmV6jzw==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": "18.2.0" } }, "node_modules/@rushstack/eslint-patch": { @@ -2219,7 +2301,7 @@ "version": "18.2.25", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.25.tgz", "integrity": "sha512-24xqse6+VByVLIr+xWaQ9muX1B4bXJKXBbjszbld/UEDslGLY53+ZucF44HCmLbMPejTzGG9XgR+3m2/Wqu1kw==", - "dev": true, + "devOptional": true, "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -2652,35 +2734,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "dependencies": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - } - }, - "node_modules/acorn-node/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-node/node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/acorn-walk": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", @@ -2716,6 +2769,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2981,22 +3035,6 @@ "node": ">=0.10.0" } }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "engines": { - "node": ">=0.8" - } - }, "node_modules/assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -3091,19 +3129,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" - }, "node_modules/axe-core": { "version": "4.8.2", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.8.2.tgz", @@ -3151,14 +3176,6 @@ } ] }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, "node_modules/before-after-hook": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", @@ -3461,11 +3478,6 @@ } ] }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, "node_modules/chainsaw": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", @@ -3842,17 +3854,6 @@ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/date-fns": { "version": "2.30.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", @@ -4025,14 +4026,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/defined": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", - "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -4079,22 +4072,6 @@ "node": ">=12" } }, - "node_modules/detective": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", - "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", - "dependencies": { - "acorn-node": "^1.8.2", - "defined": "^1.0.0", - "minimist": "^1.2.6" - }, - "bin": { - "detective": "bin/detective.js" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/devlop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", @@ -4254,15 +4231,6 @@ "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==" }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -5089,14 +5057,6 @@ "node": ">=0.10.0" } }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "engines": [ - "node >=0.6.0" - ] - }, "node_modules/fast-copy": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", @@ -5105,7 +5065,8 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, "node_modules/fast-folder-size": { "version": "1.6.1", @@ -5148,7 +5109,8 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -5258,14 +5220,6 @@ "is-callable": "^1.1.3" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "engines": { - "node": "*" - } - }, "node_modules/form-data": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", @@ -5497,14 +5451,6 @@ "node": ">=0.10.0" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/gl-matrix": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz", @@ -5668,27 +5614,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", @@ -5864,29 +5789,6 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, - "node_modules/html-dom-parser": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/html-dom-parser/-/html-dom-parser-3.1.3.tgz", - "integrity": "sha512-fI0yyNlIeSboxU+jnrA4v8qj4+M8SI9/q6AKYdwCY2qki22UtKCDTxvagHniECu7sa5/o2zFRdLleA67035lsA==", - "dependencies": { - "domhandler": "5.0.3", - "htmlparser2": "8.0.1" - } - }, - "node_modules/html-react-parser": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/html-react-parser/-/html-react-parser-3.0.9.tgz", - "integrity": "sha512-gOPZmaCMXNYu7Y9+58k2tLhTMXQ+QN8ctNFijzLuBxJaLZ6TsN+tUpN+MhbI+6nGaBCRGT2rpw6y/AqkTFZckg==", - "dependencies": { - "domhandler": "5.0.3", - "html-dom-parser": "3.1.3", - "react-property": "2.0.0", - "style-to-js": "1.1.3" - }, - "peerDependencies": { - "react": "0.14 || 15 || 16 || 17 || 18" - } - }, "node_modules/html-to-text": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.3.tgz", @@ -5903,9 +5805,9 @@ } }, "node_modules/htmlparser2": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", - "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -5915,9 +5817,9 @@ ], "dependencies": { "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", + "domhandler": "^5.0.3", "domutils": "^3.0.1", - "entities": "^4.3.0" + "entities": "^4.4.0" } }, "node_modules/http-cache-semantics": { @@ -5925,20 +5827,6 @@ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/http2-wrapper": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", @@ -6059,11 +5947,6 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, - "node_modules/inline-style-parser": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", - "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" - }, "node_modules/internal-slot": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", @@ -6434,11 +6317,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -6510,11 +6388,6 @@ "node": ">=0.10.0" } }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" - }, "node_modules/iterator.prototype": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", @@ -6636,11 +6509,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -6651,15 +6519,11 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -6672,11 +6536,6 @@ "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz", "integrity": "sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA==" }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, "node_modules/json5": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", @@ -6721,20 +6580,6 @@ "npm": ">=6" } }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -7932,14 +7777,6 @@ "set-blocking": "^2.0.0" } }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -8345,11 +8182,6 @@ "url": "https://ko-fi.com/killymxi" } }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -8876,11 +8708,6 @@ "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -8894,6 +8721,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, "engines": { "node": ">=6" } @@ -8907,14 +8735,6 @@ "teleport": ">=0.2.0" } }, - "node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "engines": { - "node": ">=0.6" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -9170,11 +8990,6 @@ } } }, - "node_modules/react-property": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.0.tgz", - "integrity": "sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw==" - }, "node_modules/react-responsive-carousel": { "version": "3.2.23", "resolved": "https://registry.npmjs.org/react-responsive-carousel/-/react-responsive-carousel-3.2.23.tgz", @@ -9464,50 +9279,6 @@ "node": ">=8" } }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/resolve": { "version": "1.22.6", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", @@ -9702,11 +9473,6 @@ "node": ">=10" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, "node_modules/scheduler": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", @@ -9938,18 +9704,6 @@ "node": ">=0.10.0" } }, - "node_modules/sparkpost": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/sparkpost/-/sparkpost-2.1.4.tgz", - "integrity": "sha512-7yvpfLVCnCVaE1yexemHNDX2bLkG3Lel14aCwj1ZCAX8Aa4OjYCP7uWPOkSwwXLYfQZRUgdwxgzXwaIDiYVx7A==", - "dependencies": { - "lodash": "^4.17.2", - "request": "^2.79.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -10036,30 +9790,6 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, - "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -10213,22 +9943,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/style-to-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.3.tgz", - "integrity": "sha512-zKI5gN/zb7LS/Vm0eUwjmjrXWw8IMtyA8aPBJZdYiQTXj4+wQ3IucOLIOnF7zCHxvW8UhIGh/uZh/t9zEHXNTQ==", - "dependencies": { - "style-to-object": "0.4.1" - } - }, - "node_modules/style-to-object": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.1.tgz", - "integrity": "sha512-HFpbb5gr2ypci7Qw+IOhnP2zOU7e77b+rzM+wTzXzfi1PrtBCX0E7Pk4wL4iTLnhzZ+JgEGAhX81ebTg/aYjQw==", - "dependencies": { - "inline-style-parser": "0.1.1" - } - }, "node_modules/styled-jsx": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", @@ -10504,18 +10218,6 @@ "node": ">=6" } }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -10645,25 +10347,14 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, "node_modules/tw-to-css": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/tw-to-css/-/tw-to-css-0.0.11.tgz", - "integrity": "sha512-uIJuEBIwyHzZg9xyGyEgDWHIkbAwEC4bhEHQ4THPuN5SToR7Zlhes5ffMjqtrv+WdtTmudTHTdc9VwUldy0FxQ==", + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/tw-to-css/-/tw-to-css-0.0.12.tgz", + "integrity": "sha512-rQAsQvOtV1lBkyCw+iypMygNHrShYAItES5r8fMsrhhaj5qrV2LkZyXc8ccEH+u5bFjHjQ9iuxe90I7Kykf6pw==", "dependencies": { - "postcss": "8.4.21", + "postcss": "8.4.31", "postcss-css-variables": "0.18.0", - "tailwindcss": "3.2.7" + "tailwindcss": "3.3.2" }, "engines": { "node": ">=16.0.0" @@ -10674,144 +10365,43 @@ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" }, - "node_modules/tw-to-css/node_modules/postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/tw-to-css/node_modules/postcss-import": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", - "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/tw-to-css/node_modules/postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/tw-to-css/node_modules/postcss-nested": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", - "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, "node_modules/tw-to-css/node_modules/tailwindcss": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.7.tgz", - "integrity": "sha512-B6DLqJzc21x7wntlH/GsZwEXTBttVSl1FtCzC8WP4oBc/NKef7kaax5jeihkkCEWc831/5NDJ9gRNDK6NEioQQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.2.tgz", + "integrity": "sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==", "dependencies": { + "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.5.3", - "color-name": "^1.1.4", - "detective": "^5.2.1", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.2.12", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "lilconfig": "^2.0.6", + "jiti": "^1.18.2", + "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.0.9", - "postcss-import": "^14.1.0", - "postcss-js": "^4.0.0", - "postcss-load-config": "^3.1.4", - "postcss-nested": "6.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", "postcss-selector-parser": "^6.0.11", "postcss-value-parser": "^4.2.0", - "quick-lru": "^5.1.1", - "resolve": "^1.22.1" + "resolve": "^1.22.2", + "sucrase": "^3.32.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" }, "engines": { - "node": ">=12.13.0" - }, - "peerDependencies": { - "postcss": "^8.0.9" + "node": ">=14.0.0" } }, - "node_modules/tw-to-css/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -11050,6 +10640,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -11075,15 +10666,6 @@ "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -11099,24 +10681,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" - }, "node_modules/vt-pbf": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/vt-pbf/-/vt-pbf-3.1.3.tgz", @@ -12405,183 +11969,204 @@ "integrity": "sha512-+nUQM/y8C+1GG5Ioeqcu6itFslCfxvQSAUVSMC9XM2G2Fcq0F4Afnp6m0pXF6X6iUBWen7jZBPmM9Qlq4Nr3/A==" }, "@radix-ui/react-compose-refs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.0.tgz", - "integrity": "sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", "requires": { "@babel/runtime": "^7.13.10" } }, "@radix-ui/react-slot": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.0.tgz", - "integrity": "sha512-3mrKauI/tWXo1Ll+gN5dHcxDPdm/Df1ufcDLCecn+pnCIVcdWE7CujXo8QaXOWRJyZyQWWbpB8eFwHzWXlv5mQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", "requires": { "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.0" + "@radix-ui/react-compose-refs": "1.0.1" } }, "@react-email/body": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@react-email/body/-/body-0.0.2.tgz", - "integrity": "sha512-SqZrZdxZlH7viwnrLvrMnVzOKpiofVAtho09bmm2siDzy0VMDGItXRzUPLcpg9vcbVJCHZRCIKoNXqA+PtokzQ==", - "requires": { - "react": "18.2.0" - } + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@react-email/body/-/body-0.0.4.tgz", + "integrity": "sha512-NmHOumdmyjWvOXomqhQt06KbgRxhHrVznxQp/oWiPWes8nAJo2Y4L27aPHR9nTcs7JF7NmcJe9YSN42pswK+GQ==", + "requires": {} }, "@react-email/button": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@react-email/button/-/button-0.0.9.tgz", - "integrity": "sha512-eYWQ1X4RFlkKYYSPgSrT6rk98wuLOieEAGENrp9j37t1v/1C+jMmBu0UjZvwHsHWdbOMRjbVDFeMI/+MxWKSEg==", - "requires": { - "react": "18.2.0" - } + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@react-email/button/-/button-0.0.11.tgz", + "integrity": "sha512-mB5ySfZifwE5ybtIWwXGbmKk1uKkH4655gftL4+mMxZAZCkINVa2KXTi5pO+xZhMtJI9xtAsikOrOEU1gTDoww==", + "requires": {} }, "@react-email/column": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@react-email/column/-/column-0.0.7.tgz", - "integrity": "sha512-B29wVXyIcuVprgGpLkR23waPh/twlqmugZQsCKk05JlMCQ80/Puv4Lgj4dRsIJzgyTLMwG6xq17+Uxc5iGfuaQ==", - "requires": { - "react": "18.2.0" - } + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@react-email/column/-/column-0.0.8.tgz", + "integrity": "sha512-blChqGU8e/L6KZiB5EPww8bkZfdyHDuS0vKIvU+iS14uK+xfAw+5P5CU9BYXccEuJh2Gftfngu1bWMFp2Sc6ag==", + "requires": {} }, "@react-email/components": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@react-email/components/-/components-0.0.7.tgz", - "integrity": "sha512-GpRKV8E7EvK9OPf61f5Z8hliB3p0hTot8tslmEUVCTtX7tdL0wM2YEcZiDWU4PJcudJ/QWHJ7Y5wGzNEARcooA==", + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@react-email/components/-/components-0.0.11.tgz", + "integrity": "sha512-wj9Sra/AGQvadb3ZABz44ll9Fb9FvXPEmODXRWbNRSc8pJTFGWorrsm4M/yj8dnewd4HtnbLkV1eDOvuiLAVLA==", "requires": { - "@react-email/body": "0.0.2", - "@react-email/button": "0.0.9", - "@react-email/column": "0.0.7", - "@react-email/container": "0.0.8", - "@react-email/font": "0.0.2", - "@react-email/head": "0.0.5", - "@react-email/heading": "0.0.8", - "@react-email/hr": "0.0.5", - "@react-email/html": "0.0.4", - "@react-email/img": "0.0.5", - "@react-email/link": "0.0.5", - "@react-email/preview": "0.0.6", - "@react-email/render": "0.0.7", - "@react-email/row": "0.0.5", - "@react-email/section": "0.0.9", - "@react-email/tailwind": "0.0.8", - "@react-email/text": "0.0.5", - "react": "18.2.0" + "@react-email/body": "0.0.4", + "@react-email/button": "0.0.11", + "@react-email/column": "0.0.8", + "@react-email/container": "0.0.10", + "@react-email/font": "0.0.4", + "@react-email/head": "0.0.6", + "@react-email/heading": "0.0.9", + "@react-email/hr": "0.0.6", + "@react-email/html": "0.0.6", + "@react-email/img": "0.0.6", + "@react-email/link": "0.0.6", + "@react-email/preview": "0.0.7", + "@react-email/render": "0.0.9", + "@react-email/row": "0.0.6", + "@react-email/section": "0.0.10", + "@react-email/tailwind": "0.0.12", + "@react-email/text": "0.0.6" } }, "@react-email/container": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@react-email/container/-/container-0.0.8.tgz", - "integrity": "sha512-MQZQxvTOoLWjJR+Jm689jltm0I/mtZbEaDnwZbNkkHKgccr++wwb9kOKMgXG777Y7tGa1JATAsZpvFYiCITwUg==", - "requires": { - "react": "18.2.0" - } + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@react-email/container/-/container-0.0.10.tgz", + "integrity": "sha512-goishY7ocq+lord0043/LZK268bqvMFW/sxpUt/dSCPJyrrZZNCbpW2t8w8HztU38cYj0qGQLxO5Qvpn/RER3w==", + "requires": {} }, "@react-email/font": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@react-email/font/-/font-0.0.2.tgz", - "integrity": "sha512-mmkyOCAcbgytE7DfIuOBVG1YVDUZY9rPCor4o7pUEzGJiU2y/TNuV8CgNPSU/VgXeBKL/94QDjB62OrGHlFNMQ==", - "requires": { - "react": "18.2.0" - } + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@react-email/font/-/font-0.0.4.tgz", + "integrity": "sha512-rN/pFlAcDNmfYFxpufT/rFRrM5KYBJM4nTA2uylTehlVOro6fb/q6n0zUwLF6OmQ4QIuRbqdEy7DI9mmJiNHxA==", + "requires": {} }, "@react-email/head": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@react-email/head/-/head-0.0.5.tgz", - "integrity": "sha512-s84OxJxZMee2z5b1a+RVwY1NOSUNNf1ecjPf6n64aZmMNcNUyn4gOl7RO6xbfBrZko7TigBwsFB1Cgjxtn/ydg==", - "requires": { - "react": "18.2.0" - } + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@react-email/head/-/head-0.0.6.tgz", + "integrity": "sha512-9BrBDalb34nBOmmQVQc7/pjJotcuAeC3rhBl4G88Ohiipuv15vPIKqwy8vPJcFNi4l7yGlitfG3EESIjkLkoIw==", + "requires": {} }, "@react-email/heading": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@react-email/heading/-/heading-0.0.8.tgz", - "integrity": "sha512-7atATmoHBHTk7hFYFsFFzOIBV3u1zPpsSOWkLBojdjSUdenpk2SbX8GP8/3aBhWl/tuFX9RBGcu1Xes+ZijFLg==", + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@react-email/heading/-/heading-0.0.9.tgz", + "integrity": "sha512-xzkcGlm+/aFrNlJZBKzxRKkRYJ2cRx92IqmSKAuGnwuKQ/uMKomXzPsHPu3Dclmnhn3wVKj4uprkgQOoxP6uXQ==", "requires": { - "@radix-ui/react-slot": "1.0.0", + "@radix-ui/react-slot": "1.0.2", "react": "18.2.0" } }, "@react-email/hr": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@react-email/hr/-/hr-0.0.5.tgz", - "integrity": "sha512-nwB8GmSdvPlR/bWjDS07yHtgdfJqtvCaPXee3SVUY69YYP7NeDO/VACJlgrS9V2l79bj1lUpH0MJMU6MNAk5FQ==", - "requires": { - "react": "18.2.0" - } + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@react-email/hr/-/hr-0.0.6.tgz", + "integrity": "sha512-W+wINBz7z7BRv3i9GS+QoJBae1PESNhv6ZY6eLnEpqtBI/2++suuRNJOU/KpZzE6pykeTp6I/Z7UcL0LEYKgyg==", + "requires": {} }, "@react-email/html": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@react-email/html/-/html-0.0.4.tgz", - "integrity": "sha512-7tRYSnudYAWez+NkPWOM8yLZH7EuYFtYdiLPnzpD+pf4cdk16Gz4up531DaIX6dNBbfbyEFpQxhXZxGeJ5ZkfQ==" + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@react-email/html/-/html-0.0.6.tgz", + "integrity": "sha512-8Fo20VOqxqc087gGEPjT8uos06fTXIC8NSoiJxpiwAkwiKtQnQH/jOdoLv6XaWh5Zt2clj1uokaoklnaM5rY1w==", + "requires": {} }, "@react-email/img": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@react-email/img/-/img-0.0.5.tgz", - "integrity": "sha512-9ziFgBfrIAL+DpVlsraFcd2KwsTRyobLpqTnoiBYCcVZGod59xbYkmsmB3CbUosmLwPYg6AeD7Q7e+hCiwkWgg==", - "requires": { - "react": "18.2.0" - } + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@react-email/img/-/img-0.0.6.tgz", + "integrity": "sha512-Wd7xKI3b1Jvb2ZEHyVpJ9D98u0GHrRl+578b8LV24PavM/65V61Q5LN5Fr9sAhj+4VGqnHDIVeXIYEzVbWaa3Q==", + "requires": {} }, "@react-email/link": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@react-email/link/-/link-0.0.5.tgz", - "integrity": "sha512-z+QW9f4gXBdyfhl7iYMY3td+rXKeZYK/2AGElEMsxVoywn5D0b6cF8m5w2jbf0U2V3enT+zy9yc1R6AyT59NOg==", - "requires": { - "react": "18.2.0" - } + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@react-email/link/-/link-0.0.6.tgz", + "integrity": "sha512-bYYHroWGS//nDl9yhh8V6K2BrNwAsyX7N/XClSCRku3x56NrZ6D0nBKWewYDPlJ9rW9TIaJm1jDYtO9XBzLlkQ==", + "requires": {} }, "@react-email/preview": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@react-email/preview/-/preview-0.0.6.tgz", - "integrity": "sha512-mXDCc3NGpm/4W7gowBtjsTxYXowLNOLsJsYhIfrsjNJWGlVhVFB9uEHm55LjBLpxSG020g6/8LIrpJU6g22qvg==", - "requires": { - "react": "18.2.0" - } + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@react-email/preview/-/preview-0.0.7.tgz", + "integrity": "sha512-YLfIwHdexPi8IgP1pSuVXdAmKzMQ8ctCCLEjkMttT2vkSFqT6m/e6UFWK2l30rKm2dDsLvQyEvo923mPXjnNzg==", + "requires": {} }, "@react-email/render": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@react-email/render/-/render-0.0.7.tgz", - "integrity": "sha512-hMMhxk6TpOcDC5qnKzXPVJoVGEwfm+U5bGOPH+MyTTlx0F02RLQygcATBKsbP7aI/mvkmBAZoFbgPIHop7ovug==", + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@react-email/render/-/render-0.0.9.tgz", + "integrity": "sha512-nrim7wiACnaXsGtL7GF6jp3Qmml8J6vAjAH88jkC8lIbfNZaCyuPQHANjyYIXlvQeAbsWADQJFZgOHUqFqjh/A==", "requires": { - "html-to-text": "9.0.3", + "html-to-text": "9.0.5", "pretty": "2.0.0", "react": "18.2.0", "react-dom": "18.2.0" + }, + "dependencies": { + "@selderee/plugin-htmlparser2": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz", + "integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==", + "requires": { + "domhandler": "^5.0.3", + "selderee": "^0.11.0" + } + }, + "html-to-text": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz", + "integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==", + "requires": { + "@selderee/plugin-htmlparser2": "^0.11.0", + "deepmerge": "^4.3.1", + "dom-serializer": "^2.0.0", + "htmlparser2": "^8.0.2", + "selderee": "^0.11.0" + } + }, + "parseley": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz", + "integrity": "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==", + "requires": { + "leac": "^0.6.0", + "peberminta": "^0.9.0" + } + }, + "peberminta": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz", + "integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==" + }, + "selderee": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz", + "integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==", + "requires": { + "parseley": "^0.12.0" + } + } } }, "@react-email/row": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@react-email/row/-/row-0.0.5.tgz", - "integrity": "sha512-dir5l1M7Z/1BQqQkUrKUPIIDPt6ueEf6ScMGoBOcUh+VNNqmnqJE2Q2CH5X3w2uo6a5X7tnVhoJHGa2KTKe8Sw==" + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@react-email/row/-/row-0.0.6.tgz", + "integrity": "sha512-msJ2TnDJNwpgDfDzUO63CvhusJHeaGLMM+8Zz86VPvxzwe/DkT7N48QKRWRCkt8urxVz5U+EgivORA9Dum9p3Q==", + "requires": {} }, "@react-email/section": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@react-email/section/-/section-0.0.9.tgz", - "integrity": "sha512-3EbcWJ1jUZrzquWSvXrv8Hbk9V+BGvLcMWQIli4NdIpQlddmlGKUYfXU2mB2d2pf+5ojqkGcFZZ9fWxycB84jQ==", - "requires": { - "react": "18.2.0" - } + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@react-email/section/-/section-0.0.10.tgz", + "integrity": "sha512-x9B2KYFqj+d8I1fK9bgeVm/3mLE4Qgn4mm/GbDtcJeSzKU/G7bTb7/3+BMDk9SARPGkg5XAuZm1XgcqQQutt2A==", + "requires": {} }, "@react-email/tailwind": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@react-email/tailwind/-/tailwind-0.0.8.tgz", - "integrity": "sha512-0BLjD5GpiyBK7YDlaDrjHIpj9eTrrZrMJud3f1UPoCZhS+0S/M8LcR8WMbQsR+8/aLGmiy4F4TGZuRQcsJEsFw==", + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@react-email/tailwind/-/tailwind-0.0.12.tgz", + "integrity": "sha512-s8Ch7GL30qRKScn9NWwItMqxjtzbyUtCnXfC6sL2YTVtulbfvZZ06W+aA0S6f7fdrVlOOlQzZuK/sVaQCHhcSw==", "requires": { - "html-react-parser": "3.0.9", "react": "18.2.0", "react-dom": "18.2.0", - "tw-to-css": "0.0.11" + "tw-to-css": "0.0.12" } }, "@react-email/text": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@react-email/text/-/text-0.0.5.tgz", - "integrity": "sha512-LXhHiaC6oRRsNAfOzJDos4wQA22eIdVJvR6G7uu4QzUvYNOAatDMf89jRQcKGrxX7InkS640v8sHd9jl5ztM5w==", - "requires": { - "react": "18.2.0" - } + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@react-email/text/-/text-0.0.6.tgz", + "integrity": "sha512-PDUTAD1PjlzXFOIUrR1zuV2xxguL62yne5YLcn1k+u/dVUyzn6iU/5lFShxCfzuh3QDWCf4+JRNnXN9rmV6jzw==", + "requires": {} }, "@rushstack/eslint-patch": { "version": "1.5.1", @@ -12922,7 +12507,7 @@ "version": "18.2.25", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.25.tgz", "integrity": "sha512-24xqse6+VByVLIr+xWaQ9muX1B4bXJKXBbjszbld/UEDslGLY53+ZucF44HCmLbMPejTzGG9XgR+3m2/Wqu1kw==", - "dev": true, + "devOptional": true, "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -13243,28 +12828,6 @@ "dev": true, "requires": {} }, - "acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "requires": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" - } - } - }, "acorn-walk": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", @@ -13291,6 +12854,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -13490,19 +13054,6 @@ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==" }, - "asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" - }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -13562,16 +13113,6 @@ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", "dev": true }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==" - }, - "aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" - }, "axe-core": { "version": "4.8.2", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.8.2.tgz", @@ -13602,14 +13143,6 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "requires": { - "tweetnacl": "^0.14.3" - } - }, "before-after-hook": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", @@ -13817,11 +13350,6 @@ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001546.tgz", "integrity": "sha512-zvtSJwuQFpewSyRrI3AsftF6rM0X80mZkChIt1spBGEvRglCrjTniXvinc8JKRoqTwXAgvqTImaN9igfSMtUBw==" }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, "chainsaw": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", @@ -14104,14 +13632,6 @@ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "requires": { - "assert-plus": "^1.0.0" - } - }, "date-fns": { "version": "2.30.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", @@ -14224,11 +13744,6 @@ "object-keys": "^1.1.1" } }, - "defined": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", - "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==" - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -14263,16 +13778,6 @@ "execa": "^5.1.1" } }, - "detective": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", - "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", - "requires": { - "acorn-node": "^1.8.2", - "defined": "^1.0.0", - "minimist": "^1.2.6" - } - }, "devlop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", @@ -14389,15 +13894,6 @@ "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==" }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -15029,11 +14525,6 @@ "is-extendable": "^0.1.0" } }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==" - }, "fast-copy": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", @@ -15042,7 +14533,8 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, "fast-folder-size": { "version": "1.6.1", @@ -15077,7 +14569,8 @@ "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", @@ -15169,11 +14662,6 @@ "is-callable": "^1.1.3" } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==" - }, "form-data": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", @@ -15344,14 +14832,6 @@ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==" }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "requires": { - "assert-plus": "^1.0.0" - } - }, "gl-matrix": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz", @@ -15471,20 +14951,6 @@ "duplexer": "^0.1.2" } }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, "hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", @@ -15613,26 +15079,6 @@ } } }, - "html-dom-parser": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/html-dom-parser/-/html-dom-parser-3.1.3.tgz", - "integrity": "sha512-fI0yyNlIeSboxU+jnrA4v8qj4+M8SI9/q6AKYdwCY2qki22UtKCDTxvagHniECu7sa5/o2zFRdLleA67035lsA==", - "requires": { - "domhandler": "5.0.3", - "htmlparser2": "8.0.1" - } - }, - "html-react-parser": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/html-react-parser/-/html-react-parser-3.0.9.tgz", - "integrity": "sha512-gOPZmaCMXNYu7Y9+58k2tLhTMXQ+QN8ctNFijzLuBxJaLZ6TsN+tUpN+MhbI+6nGaBCRGT2rpw6y/AqkTFZckg==", - "requires": { - "domhandler": "5.0.3", - "html-dom-parser": "3.1.3", - "react-property": "2.0.0", - "style-to-js": "1.1.3" - } - }, "html-to-text": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.3.tgz", @@ -15646,14 +15092,14 @@ } }, "htmlparser2": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", - "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", "requires": { "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", + "domhandler": "^5.0.3", "domutils": "^3.0.1", - "entities": "^4.3.0" + "entities": "^4.4.0" } }, "http-cache-semantics": { @@ -15661,16 +15107,6 @@ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "http2-wrapper": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", @@ -15753,11 +15189,6 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, - "inline-style-parser": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", - "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" - }, "internal-slot": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", @@ -15999,11 +15430,6 @@ "which-typed-array": "^1.1.11" } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, "is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -16054,11 +15480,6 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" - }, "iterator.prototype": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", @@ -16150,11 +15571,6 @@ "argparse": "^2.0.1" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, "json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -16165,15 +15581,11 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -16186,11 +15598,6 @@ "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz", "integrity": "sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA==" }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, "json5": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", @@ -16226,17 +15633,6 @@ "semver": "^7.5.4" } }, - "jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, "jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -17037,11 +16433,6 @@ "set-blocking": "^2.0.0" } }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -17326,11 +16717,6 @@ "resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.8.0.tgz", "integrity": "sha512-YYEs+eauIjDH5nUEGi18EohWE0nV2QbGTqmxQcqgZ/0g+laPCQmuIqq7EBLVi9uim9zMgfJv0QBZEnQ3uHw/Tw==" }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -17636,11 +17022,6 @@ "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" }, - "psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -17653,18 +17034,14 @@ "punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==" }, - "qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" - }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -17831,11 +17208,6 @@ "@types/mapbox-gl": ">=1.0.0" } }, - "react-property": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.0.tgz", - "integrity": "sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw==" - }, "react-responsive-carousel": { "version": "3.2.23", "resolved": "https://registry.npmjs.org/react-responsive-carousel/-/react-responsive-carousel-3.2.23.tgz", @@ -18066,45 +17438,6 @@ "resolved": "https://registry.npmjs.org/regexparam/-/regexparam-2.0.1.tgz", "integrity": "sha512-zRgSaYemnNYxUv+/5SeoHI0eJIgTL/A2pUtXUPLHQxUldagouJ9p+K6IbIZ/JiQuCEv2E2B1O11SjVQy3aMCkw==" }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - } - } - }, "resolve": { "version": "1.22.6", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", @@ -18230,11 +17563,6 @@ "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==" }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, "scheduler": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", @@ -18416,15 +17744,6 @@ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" }, - "sparkpost": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/sparkpost/-/sparkpost-2.1.4.tgz", - "integrity": "sha512-7yvpfLVCnCVaE1yexemHNDX2bLkG3Lel14aCwj1ZCAX8Aa4OjYCP7uWPOkSwwXLYfQZRUgdwxgzXwaIDiYVx7A==", - "requires": { - "lodash": "^4.17.2", - "request": "^2.79.0" - } - }, "spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -18498,22 +17817,6 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, - "sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -18632,22 +17935,6 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, - "style-to-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.3.tgz", - "integrity": "sha512-zKI5gN/zb7LS/Vm0eUwjmjrXWw8IMtyA8aPBJZdYiQTXj4+wQ3IucOLIOnF7zCHxvW8UhIGh/uZh/t9zEHXNTQ==", - "requires": { - "style-to-object": "0.4.1" - } - }, - "style-to-object": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.1.tgz", - "integrity": "sha512-HFpbb5gr2ypci7Qw+IOhnP2zOU7e77b+rzM+wTzXzfi1PrtBCX0E7Pk4wL4iTLnhzZ+JgEGAhX81ebTg/aYjQw==", - "requires": { - "inline-style-parser": "0.1.1" - } - }, "styled-jsx": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", @@ -18857,15 +18144,6 @@ "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==" }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -18954,22 +18232,14 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, "tw-to-css": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/tw-to-css/-/tw-to-css-0.0.11.tgz", - "integrity": "sha512-uIJuEBIwyHzZg9xyGyEgDWHIkbAwEC4bhEHQ4THPuN5SToR7Zlhes5ffMjqtrv+WdtTmudTHTdc9VwUldy0FxQ==", + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/tw-to-css/-/tw-to-css-0.0.12.tgz", + "integrity": "sha512-rQAsQvOtV1lBkyCw+iypMygNHrShYAItES5r8fMsrhhaj5qrV2LkZyXc8ccEH+u5bFjHjQ9iuxe90I7Kykf6pw==", "requires": { - "postcss": "8.4.21", + "postcss": "8.4.31", "postcss-css-variables": "0.18.0", - "tailwindcss": "3.2.7" + "tailwindcss": "3.3.2" }, "dependencies": { "arg": { @@ -18977,85 +18247,38 @@ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" }, - "postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", - "requires": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "postcss-import": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", - "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", - "requires": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - } - }, - "postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "requires": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - } - }, - "postcss-nested": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", - "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", - "requires": { - "postcss-selector-parser": "^6.0.10" - } - }, "tailwindcss": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.7.tgz", - "integrity": "sha512-B6DLqJzc21x7wntlH/GsZwEXTBttVSl1FtCzC8WP4oBc/NKef7kaax5jeihkkCEWc831/5NDJ9gRNDK6NEioQQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.2.tgz", + "integrity": "sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==", "requires": { + "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.5.3", - "color-name": "^1.1.4", - "detective": "^5.2.1", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.2.12", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "lilconfig": "^2.0.6", + "jiti": "^1.18.2", + "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.0.9", - "postcss-import": "^14.1.0", - "postcss-js": "^4.0.0", - "postcss-load-config": "^3.1.4", - "postcss-nested": "6.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", "postcss-selector-parser": "^6.0.11", "postcss-value-parser": "^4.2.0", - "quick-lru": "^5.1.1", - "resolve": "^1.22.1" + "resolve": "^1.22.2", + "sucrase": "^3.32.0" } - }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" } } }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -19224,6 +18447,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "requires": { "punycode": "^2.1.0" } @@ -19244,11 +18468,6 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - }, "v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -19264,23 +18483,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" - } - } - }, "vt-pbf": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/vt-pbf/-/vt-pbf-3.1.3.tgz", diff --git a/package.json b/package.json index 8214160..c1eafe4 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,9 @@ "@mapbox/search-js-react": "^1.0.0-beta.17", "@next/bundle-analyzer": "^13.4.10", "@prisma/client": "^5.0.0", - "@react-email/components": "^0.0.7", - "@react-email/render": "^0.0.7", - "@react-email/tailwind": "^0.0.8", + "@react-email/components": "^0.0.11", + "@react-email/render": "^0.0.9", + "@react-email/tailwind": "^0.0.12", "@vercel/analytics": "^1.1.0", "argon2": "^0.31.1", "cloudinary": "^1.41.0", @@ -44,14 +44,13 @@ "react": "^18.2.0", "react-daisyui": "^4.0.0", "react-dom": "^18.2.0", - "react-email": "^1.9.4", + "react-email": "^1.9.5", "react-hook-form": "^7.45.2", "react-hot-toast": "^2.4.1", "react-icons": "^4.10.1", "react-intersection-observer": "^9.5.2", "react-map-gl": "^7.1.2", "react-responsive-carousel": "^3.2.23", - "sparkpost": "^2.1.4", "swr": "^2.2.0", "theme-change": "^2.5.0", "zod": "^3.21.4" diff --git a/src/config/sparkpost/client.ts b/src/config/sparkpost/client.ts deleted file mode 100644 index 2e1c426..0000000 --- a/src/config/sparkpost/client.ts +++ /dev/null @@ -1,6 +0,0 @@ -import SparkPost from 'sparkpost'; -import { SPARKPOST_API_KEY } from '../env'; - -const client = new SparkPost(SPARKPOST_API_KEY); - -export default client; diff --git a/src/config/sparkpost/sendEmail.ts b/src/config/sparkpost/sendEmail.ts index 78c1f9d..bc74620 100644 --- a/src/config/sparkpost/sendEmail.ts +++ b/src/config/sparkpost/sendEmail.ts @@ -1,5 +1,4 @@ -import { SPARKPOST_SENDER_ADDRESS } from '../env'; -import client from './client'; +import { SPARKPOST_API_KEY, SPARKPOST_SENDER_ADDRESS } from '../env'; interface EmailParams { address: string; @@ -11,10 +10,26 @@ interface EmailParams { const sendEmail = async ({ address, text, html, subject }: EmailParams) => { const from = SPARKPOST_SENDER_ADDRESS; - await client.transmissions.send({ - content: { from, html, subject, text }, + const data = { recipients: [{ address }], + content: { from, subject, text, html }, + }; + + const transmissionsEndpoint = 'https://api.sparkpost.com/api/v1/transmissions'; + + const response = await fetch(transmissionsEndpoint, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + Authorization: SPARKPOST_API_KEY, + }, + body: JSON.stringify(data), }); + + if (response.status !== 200) { + throw new Error(`Sparkpost API returned status code ${response.status}`); + } }; export default sendEmail; From fd1f2b101f53f143ae74f097d08897e3fa8e397e Mon Sep 17 00:00:00 2001 From: Aaron William Po Date: Sun, 12 Nov 2023 23:24:33 -0500 Subject: [PATCH 09/13] Feat: add user header with follow info --- src/components/Account/UserAvatar.tsx | 2 +- .../BeerBreweryComments/CommentCardBody.tsx | 2 +- .../user-follows/useGetUsersFollowedByUser.ts | 64 ++++++++++++++++ .../user-follows/useGetUsersFollowingUser.ts | 64 ++++++++++++++++ src/pages/api/users/[id]/followers.ts | 70 ++++++++++++++++++ src/pages/api/users/[id]/following.ts | 70 ++++++++++++++++++ src/pages/users/[id].tsx | 73 +++++++++++-------- .../seed/create/createNewUserFollows.ts | 9 +-- .../UserFollows/getUsersFollowedByUser.ts | 27 +++++++ .../UserFollows/getUsersFollowingUser.ts | 27 +++++++ .../UserFollows/schema/FollowInfoSchema.ts | 9 +++ 11 files changed, 379 insertions(+), 38 deletions(-) create mode 100644 src/hooks/data-fetching/user-follows/useGetUsersFollowedByUser.ts create mode 100644 src/hooks/data-fetching/user-follows/useGetUsersFollowingUser.ts create mode 100644 src/pages/api/users/[id]/followers.ts create mode 100644 src/pages/api/users/[id]/following.ts create mode 100644 src/services/UserFollows/getUsersFollowedByUser.ts create mode 100644 src/services/UserFollows/getUsersFollowingUser.ts create mode 100644 src/services/UserFollows/schema/FollowInfoSchema.ts diff --git a/src/components/Account/UserAvatar.tsx b/src/components/Account/UserAvatar.tsx index 42e837c..949ed03 100644 --- a/src/components/Account/UserAvatar.tsx +++ b/src/components/Account/UserAvatar.tsx @@ -19,7 +19,7 @@ const UserAvatar: FC = ({ user }) => { alt="user avatar" width={1000} height={1000} - className="h-full w-full" + className="h-full w-full object-cover mask mask-circle ring ring-primary ring-offset-base-100 ring-offset-2" /> ); }; diff --git a/src/components/BeerBreweryComments/CommentCardBody.tsx b/src/components/BeerBreweryComments/CommentCardBody.tsx index c874a7f..f4887dc 100644 --- a/src/components/BeerBreweryComments/CommentCardBody.tsx +++ b/src/components/BeerBreweryComments/CommentCardBody.tsx @@ -31,7 +31,7 @@ const CommentCardBody: FC = ({ return (
-
+
diff --git a/src/hooks/data-fetching/user-follows/useGetUsersFollowedByUser.ts b/src/hooks/data-fetching/user-follows/useGetUsersFollowedByUser.ts new file mode 100644 index 0000000..a09e78a --- /dev/null +++ b/src/hooks/data-fetching/user-follows/useGetUsersFollowedByUser.ts @@ -0,0 +1,64 @@ +import FollowInfoSchema from '@/services/UserFollows/schema/FollowInfoSchema'; +import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; +import useSWRInfinite from 'swr/infinite'; +import { z } from 'zod'; + +const useGetUsersFollowingUser = ({ + pageSize, + userId, +}: { + pageSize: number; + userId: string; +}) => { + const fetcher = async (url: string) => { + const response = await fetch(url); + if (!response.ok) { + throw new Error(response.statusText); + } + + const json = await response.json(); + const count = response.headers.get('X-Total-Count'); + + const parsed = APIResponseValidationSchema.safeParse(json); + if (!parsed.success) { + throw new Error('API response validation failed'); + } + + const parsedPayload = z.array(FollowInfoSchema).safeParse(parsed.data.payload); + if (!parsedPayload.success) { + throw new Error('API response validation failed'); + } + + const pageCount = Math.ceil(parseInt(count as string, 10) / pageSize); + + return { following: parsedPayload.data, pageCount, followingCount: count }; + }; + + const { data, error, isLoading, setSize, size } = useSWRInfinite( + (index) => + `/api/users/${userId}/following?page_num=${index + 1}&page_size=${pageSize}`, + fetcher, + { parallel: true }, + ); + + const following = data?.flatMap((d) => d.following) ?? []; + const followingCount = data?.[0].followingCount ?? 0; + + const pageCount = data?.[0].pageCount ?? 0; + const isLoadingMore = size > 0 && data && typeof data[size - 1] === 'undefined'; + const isAtEnd = !(size < data?.[0].pageCount!); + + return { + following, + followingCount, + pageCount, + size, + setSize, + isLoading, + isLoadingMore, + isAtEnd, + error: error as unknown, + }; +}; + +export default useGetUsersFollowingUser; diff --git a/src/hooks/data-fetching/user-follows/useGetUsersFollowingUser.ts b/src/hooks/data-fetching/user-follows/useGetUsersFollowingUser.ts new file mode 100644 index 0000000..a9b4763 --- /dev/null +++ b/src/hooks/data-fetching/user-follows/useGetUsersFollowingUser.ts @@ -0,0 +1,64 @@ +import FollowInfoSchema from '@/services/UserFollows/schema/FollowInfoSchema'; +import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; +import useSWRInfinite from 'swr/infinite'; +import { z } from 'zod'; + +const useGetUsersFollowingUser = ({ + pageSize, + userId, +}: { + pageSize: number; + userId: string; +}) => { + const fetcher = async (url: string) => { + const response = await fetch(url); + if (!response.ok) { + throw new Error(response.statusText); + } + + const json = await response.json(); + const count = response.headers.get('X-Total-Count'); + + const parsed = APIResponseValidationSchema.safeParse(json); + if (!parsed.success) { + throw new Error('API response validation failed'); + } + + const parsedPayload = z.array(FollowInfoSchema).safeParse(parsed.data.payload); + if (!parsedPayload.success) { + throw new Error('API response validation failed'); + } + + const pageCount = Math.ceil(parseInt(count as string, 10) / pageSize); + + return { followers: parsedPayload.data, pageCount, followerCount: count }; + }; + + const { data, error, isLoading, setSize, size } = useSWRInfinite( + (index) => + `/api/users/${userId}/followers?page_num=${index + 1}&page_size=${pageSize}`, + fetcher, + { parallel: true }, + ); + + const followers = data?.flatMap((d) => d.followers) ?? []; + const followerCount = data?.[0].followerCount ?? 0; + + const pageCount = data?.[0].pageCount ?? 0; + const isLoadingMore = size > 0 && data && typeof data[size - 1] === 'undefined'; + const isAtEnd = !(size < data?.[0].pageCount!); + + return { + followers, + followerCount, + pageCount, + size, + setSize, + isLoading, + isLoadingMore, + isAtEnd, + error: error as unknown, + }; +}; + +export default useGetUsersFollowingUser; diff --git a/src/pages/api/users/[id]/followers.ts b/src/pages/api/users/[id]/followers.ts new file mode 100644 index 0000000..2917802 --- /dev/null +++ b/src/pages/api/users/[id]/followers.ts @@ -0,0 +1,70 @@ +import { UserExtendedNextApiRequest } from '@/config/auth/types'; +import NextConnectOptions from '@/config/nextConnect/NextConnectOptions'; +import validateRequest from '@/config/nextConnect/middleware/validateRequest'; +import ServerError from '@/config/util/ServerError'; +import DBClient from '@/prisma/DBClient'; +import findUserById from '@/services/User/findUserById'; +import getUsersFollowingUser from '@/services/UserFollows/getUsersFollowingUser'; +import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; + +import { NextApiResponse } from 'next'; +import { createRouter } from 'next-connect'; +import { z } from 'zod'; + +interface GetUserFollowInfoRequest extends UserExtendedNextApiRequest { + query: { id: string; page_size: string; page_num: string }; +} + +const router = createRouter< + GetUserFollowInfoRequest, + NextApiResponse> +>(); + +const getFollowingInfo = async ( + req: GetUserFollowInfoRequest, + res: NextApiResponse>, +) => { + // eslint-disable-next-line @typescript-eslint/naming-convention + const { id, page_num, page_size } = req.query; + + const user = await findUserById(id); + if (!user) { + throw new ServerError('User not found', 404); + } + + const pageNum = parseInt(page_num, 10); + const pageSize = parseInt(page_size, 10); + + const following = await getUsersFollowingUser({ + userId: id, + pageNum, + pageSize, + }); + const followingCount = await DBClient.instance.userFollow.count({ + where: { following: { id } }, + }); + + res.setHeader('X-Total-Count', followingCount); + + res.json({ + message: 'Retrieved users that are followed by queried user', + payload: following, + success: true, + statusCode: 200, + }); +}; + +router.get( + validateRequest({ + querySchema: z.object({ + id: z.string().cuid(), + page_size: z.string().regex(/^\d+$/), + page_num: z.string().regex(/^\d+$/), + }), + }), + getFollowingInfo, +); + +const handler = router.handler(NextConnectOptions); + +export default handler; diff --git a/src/pages/api/users/[id]/following.ts b/src/pages/api/users/[id]/following.ts new file mode 100644 index 0000000..1c3fa61 --- /dev/null +++ b/src/pages/api/users/[id]/following.ts @@ -0,0 +1,70 @@ +import { UserExtendedNextApiRequest } from '@/config/auth/types'; +import NextConnectOptions from '@/config/nextConnect/NextConnectOptions'; +import validateRequest from '@/config/nextConnect/middleware/validateRequest'; +import ServerError from '@/config/util/ServerError'; +import DBClient from '@/prisma/DBClient'; +import findUserById from '@/services/User/findUserById'; +import getUsersFollowedByUser from '@/services/UserFollows/getUsersFollowedByUser'; +import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; + +import { NextApiResponse } from 'next'; +import { createRouter } from 'next-connect'; +import { z } from 'zod'; + +interface GetUserFollowInfoRequest extends UserExtendedNextApiRequest { + query: { id: string; page_size: string; page_num: string }; +} + +const router = createRouter< + GetUserFollowInfoRequest, + NextApiResponse> +>(); + +const getFollowingInfo = async ( + req: GetUserFollowInfoRequest, + res: NextApiResponse>, +) => { + // eslint-disable-next-line @typescript-eslint/naming-convention + const { id, page_num, page_size } = req.query; + + const user = await findUserById(id); + if (!user) { + throw new ServerError('User not found', 404); + } + + const pageNum = parseInt(page_num, 10); + const pageSize = parseInt(page_size, 10); + + const following = await getUsersFollowedByUser({ + userId: id, + pageNum, + pageSize, + }); + const followingCount = await DBClient.instance.userFollow.count({ + where: { follower: { id } }, + }); + + res.setHeader('X-Total-Count', followingCount); + + res.json({ + message: 'Retrieved users that are followed by queried user', + payload: following, + success: true, + statusCode: 200, + }); +}; + +router.get( + validateRequest({ + querySchema: z.object({ + id: z.string().cuid(), + page_size: z.string().regex(/^\d+$/), + page_num: z.string().regex(/^\d+$/), + }), + }), + getFollowingInfo, +); + +const handler = router.handler(NextConnectOptions); + +export default handler; diff --git a/src/pages/users/[id].tsx b/src/pages/users/[id].tsx index 811ec10..795acef 100644 --- a/src/pages/users/[id].tsx +++ b/src/pages/users/[id].tsx @@ -7,7 +7,9 @@ import { GetServerSideProps } from 'next'; import Head from 'next/head'; import { FC } from 'react'; import { z } from 'zod'; -import Image from 'next/image'; +import UserAvatar from '@/components/Account/UserAvatar'; +import useGetUsersFollowedByUser from '@/hooks/data-fetching/user-follows/useGetUsersFollowedByUser'; +import useGetUsersFollowingUser from '@/hooks/data-fetching/user-follows/useGetUsersFollowingUser'; interface UserInfoPageProps { user: z.infer; @@ -16,50 +18,63 @@ interface UserInfoPageProps { const UserHeader: FC<{ user: z.infer }> = ({ user }) => { const timeDistance = useTimeDistance(new Date(user.createdAt)); - return ( -
-
-
-
-
-

- {user.firstName} {user.lastName} -

+ const { followingCount } = useGetUsersFollowedByUser({ + userId: user.id, + pageSize: 10, + }); -

- joined{' '} - {timeDistance && ( - - {`${timeDistance} ago`} - - )} -

-
-
-
+ const { followerCount } = useGetUsersFollowingUser({ + userId: user.id, + pageSize: 10, + }); + + return ( +
+
+
+ +
+ +
+

{user.username}

+
+ +
+ {followingCount} Following + {followerCount} Followers +
+ + + joined{' '} + {timeDistance && ( + + {`${timeDistance} ago`} + + )} +
-
+ ); }; const UserInfoPage: FC = ({ user }) => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars const isDesktop = useMediaQuery('(min-width: 1024px)'); + const title = `${user.username} | The Biergarten App`; + return ( <> - {user ? `${user.firstName} ${user.lastName}` : 'User Info'} + {title} <>
- avatar
- - {isDesktop ? <> : <> }
diff --git a/src/prisma/seed/create/createNewUserFollows.ts b/src/prisma/seed/create/createNewUserFollows.ts index aa87f0b..6834c48 100644 --- a/src/prisma/seed/create/createNewUserFollows.ts +++ b/src/prisma/seed/create/createNewUserFollows.ts @@ -24,20 +24,15 @@ const createNewUserFollows = async ({ const randomUsers = users .filter((randomUser) => randomUser.id !== user.id) .sort(() => Math.random() - Math.random()) - .slice(0, 20); + .slice(0, 100); - // Get the user to follow the random users, and the random users to follow the user. + // Get the user to follow the random users const data = randomUsers.flatMap((randomUser) => [ { followerId: user.id, followingId: randomUser.id, followedAt: faker.date.between({ from: user.createdAt, to: new Date() }), }, - { - followerId: randomUser.id, - followingId: user.id, - followedAt: faker.date.between({ from: randomUser.createdAt, to: new Date() }), - }, ]); userFollows.push(...data); diff --git a/src/services/UserFollows/getUsersFollowedByUser.ts b/src/services/UserFollows/getUsersFollowedByUser.ts new file mode 100644 index 0000000..3f58d19 --- /dev/null +++ b/src/services/UserFollows/getUsersFollowedByUser.ts @@ -0,0 +1,27 @@ +import DBClient from '@/prisma/DBClient'; +import { z } from 'zod'; +import FollowInfoSchema from './schema/FollowInfoSchema'; + +interface GetFollowingInfoByUserIdArgs { + userId: string; + pageNum: number; + pageSize: number; +} +const getUsersFollowedByUser = async ({ + userId, + pageNum, + pageSize, +}: GetFollowingInfoByUserIdArgs): Promise[]> => { + const usersFollowedByQueriedUser = await DBClient.instance.userFollow.findMany({ + take: pageSize, + skip: (pageNum - 1) * pageSize, + where: { following: { id: userId } }, + select: { + follower: { select: { username: true, userAvatar: true, id: true } }, + }, + }); + + return usersFollowedByQueriedUser.map((u) => u.follower); +}; + +export default getUsersFollowedByUser; diff --git a/src/services/UserFollows/getUsersFollowingUser.ts b/src/services/UserFollows/getUsersFollowingUser.ts new file mode 100644 index 0000000..5379b7f --- /dev/null +++ b/src/services/UserFollows/getUsersFollowingUser.ts @@ -0,0 +1,27 @@ +import DBClient from '@/prisma/DBClient'; +import { z } from 'zod'; +import FollowInfoSchema from './schema/FollowInfoSchema'; + +interface GetFollowingInfoByUserIdArgs { + userId: string; + pageNum: number; + pageSize: number; +} +const getUsersFollowingUser = async ({ + userId, + pageNum, + pageSize, +}: GetFollowingInfoByUserIdArgs): Promise[]> => { + const usersFollowingQueriedUser = await DBClient.instance.userFollow.findMany({ + take: pageSize, + skip: (pageNum - 1) * pageSize, + where: { follower: { id: userId } }, + select: { + following: { select: { username: true, userAvatar: true, id: true } }, + }, + }); + + return usersFollowingQueriedUser.map((u) => u.following); +}; + +export default getUsersFollowingUser; diff --git a/src/services/UserFollows/schema/FollowInfoSchema.ts b/src/services/UserFollows/schema/FollowInfoSchema.ts new file mode 100644 index 0000000..86ff7d4 --- /dev/null +++ b/src/services/UserFollows/schema/FollowInfoSchema.ts @@ -0,0 +1,9 @@ +import GetUserSchema from '@/services/User/schema/GetUserSchema'; + +const FollowInfoSchema = GetUserSchema.pick({ + userAvatar: true, + id: true, + username: true, +}); + +export default FollowInfoSchema; From f55570fc1c0be6c4d86db391e3ec5bc3894887d0 Mon Sep 17 00:00:00 2001 From: Aaron William Po Date: Sun, 12 Nov 2023 23:37:32 -0500 Subject: [PATCH 10/13] fix: add await to beer style api route to fix api response parse error --- src/pages/api/beers/styles/[id]/beers/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/api/beers/styles/[id]/beers/index.ts b/src/pages/api/beers/styles/[id]/beers/index.ts index 41e5fb8..19d3c86 100644 --- a/src/pages/api/beers/styles/[id]/beers/index.ts +++ b/src/pages/api/beers/styles/[id]/beers/index.ts @@ -19,7 +19,7 @@ const getAllBeersByBeerStyle = async ( // eslint-disable-next-line @typescript-eslint/naming-convention const { page_size, page_num, id } = req.query; - const beers = getBeerPostsByBeerStyleId({ + const beers = await getBeerPostsByBeerStyleId({ pageNum: parseInt(page_num, 10), pageSize: parseInt(page_size, 10), styleId: id, From 6641a457050a616e155fde7a65e0e0cd793c9ee1 Mon Sep 17 00:00:00 2001 From: Aaron William Po Date: Mon, 13 Nov 2023 14:57:15 -0500 Subject: [PATCH 11/13] fix: use term 'count' for X-Total-Count header --- src/pages/api/beers/[id]/comments/index.ts | 4 ++-- src/pages/api/beers/styles/[id]/beers/index.ts | 4 ++-- src/pages/api/beers/styles/[id]/comments/index.ts | 4 ++-- src/pages/api/breweries/[id]/beers/index.ts | 4 ++-- src/pages/api/breweries/[id]/comments/index.ts | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/pages/api/beers/[id]/comments/index.ts b/src/pages/api/beers/[id]/comments/index.ts index e3741d7..52cb298 100644 --- a/src/pages/api/beers/[id]/comments/index.ts +++ b/src/pages/api/beers/[id]/comments/index.ts @@ -59,9 +59,9 @@ const getAll = async ( pageSize: parseInt(page_size, 10), }); - const pageCount = await DBClient.instance.beerComment.count({ where: { beerPostId } }); + const count = await DBClient.instance.beerComment.count({ where: { beerPostId } }); - res.setHeader('X-Total-Count', pageCount); + res.setHeader('X-Total-Count', count); res.status(200).json({ message: 'Beer comments fetched successfully', diff --git a/src/pages/api/beers/styles/[id]/beers/index.ts b/src/pages/api/beers/styles/[id]/beers/index.ts index 19d3c86..18f82d8 100644 --- a/src/pages/api/beers/styles/[id]/beers/index.ts +++ b/src/pages/api/beers/styles/[id]/beers/index.ts @@ -25,9 +25,9 @@ const getAllBeersByBeerStyle = async ( styleId: id, }); - const pageCount = await DBClient.instance.beerPost.count({ where: { styleId: id } }); + const count = await DBClient.instance.beerPost.count({ where: { styleId: id } }); - res.setHeader('X-Total-Count', pageCount); + res.setHeader('X-Total-Count', count); res.status(200).json({ message: 'Beers fetched successfully', diff --git a/src/pages/api/beers/styles/[id]/comments/index.ts b/src/pages/api/beers/styles/[id]/comments/index.ts index 6a1f714..4e44ac2 100644 --- a/src/pages/api/beers/styles/[id]/comments/index.ts +++ b/src/pages/api/beers/styles/[id]/comments/index.ts @@ -59,11 +59,11 @@ const getAll = async ( pageSize: parseInt(page_size, 10), }); - const pageCount = await DBClient.instance.beerStyleComment.count({ + const count = await DBClient.instance.beerStyleComment.count({ where: { beerStyleId }, }); - res.setHeader('X-Total-Count', pageCount); + res.setHeader('X-Total-Count', count); res.status(200).json({ message: 'Beer comments fetched successfully', diff --git a/src/pages/api/breweries/[id]/beers/index.ts b/src/pages/api/breweries/[id]/beers/index.ts index a7fe24c..943d9ca 100644 --- a/src/pages/api/breweries/[id]/beers/index.ts +++ b/src/pages/api/breweries/[id]/beers/index.ts @@ -47,11 +47,11 @@ const getAllBeersByBrewery = async ( }, }); - const pageCount = await DBClient.instance.beerPost.count({ + const count = await DBClient.instance.beerPost.count({ where: { breweryId: id }, }); - res.setHeader('X-Total-Count', pageCount); + res.setHeader('X-Total-Count', count); res.status(200).json({ message: 'Beers fetched successfully', diff --git a/src/pages/api/breweries/[id]/comments/index.ts b/src/pages/api/breweries/[id]/comments/index.ts index c2812bf..00f4e12 100644 --- a/src/pages/api/breweries/[id]/comments/index.ts +++ b/src/pages/api/breweries/[id]/comments/index.ts @@ -67,11 +67,11 @@ const getAll = async ( pageSize: parseInt(page_size, 10), }); - const pageCount = await DBClient.instance.breweryComment.count({ + const count = await DBClient.instance.breweryComment.count({ where: { breweryPostId }, }); - res.setHeader('X-Total-Count', pageCount); + res.setHeader('X-Total-Count', count); res.status(200).json({ message: 'Beer comments fetched successfully', From f7227519b600be2a3cb8d84c4d6635f79f7ba3f0 Mon Sep 17 00:00:00 2001 From: Aaron William Po Date: Mon, 20 Nov 2023 14:44:03 -0500 Subject: [PATCH 12/13] feat: extract user header --- src/components/UserPage/UserHeader.tsx | 50 ++++++++++ .../user-follows/useGetUsersFollowedByUser.ts | 4 +- src/pages/users/[id].tsx | 98 ++++++++----------- 3 files changed, 94 insertions(+), 58 deletions(-) create mode 100644 src/components/UserPage/UserHeader.tsx diff --git a/src/components/UserPage/UserHeader.tsx b/src/components/UserPage/UserHeader.tsx new file mode 100644 index 0000000..be41117 --- /dev/null +++ b/src/components/UserPage/UserHeader.tsx @@ -0,0 +1,50 @@ +import useTimeDistance from '@/hooks/utilities/useTimeDistance'; +import useGetUsersFollowedByUser from '@/hooks/data-fetching/user-follows/useGetUsersFollowedByUser'; +import useGetUsersFollowingUser from '@/hooks/data-fetching/user-follows/useGetUsersFollowingUser'; +import { FC } from 'react'; +import { z } from 'zod'; +import { format } from 'date-fns'; +import GetUserSchema from '@/services/User/schema/GetUserSchema'; +import UserAvatar from '../Account/UserAvatar'; + +interface UserHeaderProps { + user: z.infer; + followerCount: ReturnType['followerCount']; + followingCount: ReturnType['followingCount']; +} +const UserHeader: FC = ({ user, followerCount, followingCount }) => { + const timeDistance = useTimeDistance(new Date(user.createdAt)); + + return ( +
+
+
+ +
+ +
+

{user.username}

+
+ +
+ {followingCount} Following + {followerCount} Followers +
+ + + joined{' '} + {timeDistance && ( + + {`${timeDistance} ago`} + + )} + +
+
+ ); +}; + +export default UserHeader; diff --git a/src/hooks/data-fetching/user-follows/useGetUsersFollowedByUser.ts b/src/hooks/data-fetching/user-follows/useGetUsersFollowedByUser.ts index a09e78a..d3a3c4a 100644 --- a/src/hooks/data-fetching/user-follows/useGetUsersFollowedByUser.ts +++ b/src/hooks/data-fetching/user-follows/useGetUsersFollowedByUser.ts @@ -3,7 +3,7 @@ import APIResponseValidationSchema from '@/validation/APIResponseValidationSchem import useSWRInfinite from 'swr/infinite'; import { z } from 'zod'; -const useGetUsersFollowingUser = ({ +const useGetUsersFollowedByUser = ({ pageSize, userId, }: { @@ -61,4 +61,4 @@ const useGetUsersFollowingUser = ({ }; }; -export default useGetUsersFollowingUser; +export default useGetUsersFollowedByUser; diff --git a/src/pages/users/[id].tsx b/src/pages/users/[id].tsx index 795acef..a25bff7 100644 --- a/src/pages/users/[id].tsx +++ b/src/pages/users/[id].tsx @@ -1,13 +1,12 @@ import useMediaQuery from '@/hooks/utilities/useMediaQuery'; -import useTimeDistance from '@/hooks/utilities/useTimeDistance'; import findUserById from '@/services/User/findUserById'; import GetUserSchema from '@/services/User/schema/GetUserSchema'; -import { format } from 'date-fns'; -import { GetServerSideProps } from 'next'; + import Head from 'next/head'; import { FC } from 'react'; import { z } from 'zod'; -import UserAvatar from '@/components/Account/UserAvatar'; +import withPageAuthRequired from '@/util/withPageAuthRequired'; +import UserHeader from '@/components/UserPage/UserHeader'; import useGetUsersFollowedByUser from '@/hooks/data-fetching/user-follows/useGetUsersFollowedByUser'; import useGetUsersFollowingUser from '@/hooks/data-fetching/user-follows/useGetUsersFollowingUser'; @@ -15,8 +14,10 @@ interface UserInfoPageProps { user: z.infer; } -const UserHeader: FC<{ user: z.infer }> = ({ user }) => { - const timeDistance = useTimeDistance(new Date(user.createdAt)); +const UserInfoPage: FC = ({ user }) => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const isDesktop = useMediaQuery('(min-width: 1024px)'); + const title = `${user.username} | The Biergarten App`; const { followingCount } = useGetUsersFollowedByUser({ userId: user.id, @@ -28,43 +29,6 @@ const UserHeader: FC<{ user: z.infer }> = ({ user }) => { pageSize: 10, }); - return ( -
-
-
- -
- -
-

{user.username}

-
- -
- {followingCount} Following - {followerCount} Followers -
- - - joined{' '} - {timeDistance && ( - - {`${timeDistance} ago`} - - )} - -
-
- ); -}; - -const UserInfoPage: FC = ({ user }) => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const isDesktop = useMediaQuery('(min-width: 1024px)'); - const title = `${user.username} | The Biergarten App`; - return ( <> @@ -74,7 +38,32 @@ const UserInfoPage: FC = ({ user }) => { <>
- + + + {isDesktop ? ( +
+
+
+
+

About Me

+

{user.bio}

+
+
+
+ +
+
+
+
+
+
+ ) : ( + <> + )}
@@ -84,15 +73,12 @@ const UserInfoPage: FC = ({ user }) => { export default UserInfoPage; -export const getServerSideProps: GetServerSideProps = async ( - context, -) => { - const { id } = context.params!; - const user = await findUserById(id as string); - - if (!user) { - return { notFound: true }; - } - - return { props: { user: JSON.parse(JSON.stringify(user)) } }; -}; +export const getServerSideProps = withPageAuthRequired( + async (context) => { + const { id } = context.params!; + const user = await findUserById(id as string); + return user + ? { props: { user: JSON.parse(JSON.stringify(user)) } } + : { notFound: true }; + }, +); From dddc48b4037a265e28004143fa9c66c9e91b5c1d Mon Sep 17 00:00:00 2001 From: Aaron William Po Date: Mon, 20 Nov 2023 14:55:33 -0500 Subject: [PATCH 13/13] style: fix beer card image and update user page --- src/components/BeerIndex/BeerCard.tsx | 5 +++-- src/pages/users/[id].tsx | 14 +++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/components/BeerIndex/BeerCard.tsx b/src/components/BeerIndex/BeerCard.tsx index 962829e..0d22fb8 100644 --- a/src/components/BeerIndex/BeerCard.tsx +++ b/src/components/BeerIndex/BeerCard.tsx @@ -18,8 +18,9 @@ const BeerCard: FC<{ post: z.infer }> = ({ post }) = {post.name} )} diff --git a/src/pages/users/[id].tsx b/src/pages/users/[id].tsx index a25bff7..60f188a 100644 --- a/src/pages/users/[id].tsx +++ b/src/pages/users/[id].tsx @@ -36,8 +36,8 @@ const UserInfoPage: FC = ({ user }) => { <> -
-
+
+
= ({ user }) => { /> {isDesktop ? ( -
-
-
+
+
+

About Me

{user.bio}

@@ -56,8 +56,8 @@ const UserInfoPage: FC = ({ user }) => {
-
-
+
+