From aa0f1a3f20d7341973e56db48b61e1156c7f5185 Mon Sep 17 00:00:00 2001 From: "serafim.eth" Date: Thu, 8 May 2025 21:45:34 +0300 Subject: [PATCH 1/3] feat: vote from home page --- .../components/features/home/home-layout.tsx | 155 +++++++++++++++++- .../features/home/horizontal-slider.tsx | 6 + .../components/features/list-card/card.tsx | 117 ++++++++++++- apps/web/lib/queries.ts | 1 + 4 files changed, 263 insertions(+), 16 deletions(-) diff --git a/apps/web/components/features/home/home-layout.tsx b/apps/web/components/features/home/home-layout.tsx index 368dae52..1787612d 100644 --- a/apps/web/components/features/home/home-layout.tsx +++ b/apps/web/components/features/home/home-layout.tsx @@ -11,10 +11,14 @@ import { import { HorizontalSlider } from "./horizontal-slider" import { SortOption } from "@/types/global" import { DemoWithComponent } from "@/types/global" -import { useMemo, useEffect, useState } from "react" +import { useMemo, useEffect, useState, useRef } from "react" import { useNavigation } from "@/hooks/use-navigation" import { useRouter } from "next/navigation" import { shouldHideLeaderboardRankings } from "@/lib/utils" +import { toast } from "sonner" +import { useClerkSupabaseClient } from "@/lib/clerk" +import { useUser } from "@clerk/nextjs" +import { useQueryClient } from "@tanstack/react-query" interface HomeTabLayoutProps { sortBy?: SortOption @@ -33,6 +37,13 @@ interface SliderGroup { isLeaderboard?: boolean } +// Extended type to include leaderboard fields +type LeaderboardDemoWithComponent = DemoWithComponent & { + global_rank?: number + votes_count?: number + has_voted?: boolean +} + // Helper to check if we need to randomize leaderboard const shouldRandomizeLeaderboard = () => { const now = new Date() @@ -48,12 +59,22 @@ export function HomeTabLayout({ sortBy = "recommended" }: HomeTabLayoutProps) { const popularDemosQuery = useMainDemosExcludingFeatured() const latestDemosQuery = useLatestDemos() const leaderboardDemosQuery = useLeaderboardDemosForHome() + const router = useRouter() + const supabase = useClerkSupabaseClient() + const { user } = useUser() + const queryClient = useQueryClient() + + // Keep track of component order by ID + const leaderboardItemOrderRef = useRef([]) // State to store the already randomized leaderboard items const [randomizedLeaderboardItems, setRandomizedLeaderboardItems] = useState< - DemoWithComponent[] + LeaderboardDemoWithComponent[] >([]) + // Add state to track if initial randomization is done + const [isRandomizationDone, setIsRandomizationDone] = useState(false) + // Process leaderboard data once when it arrives useEffect(() => { if ( @@ -64,23 +85,61 @@ export function HomeTabLayout({ sortBy = "recommended" }: HomeTabLayoutProps) { return } + // If we already have an order and randomization is done, maintain the order + if (isRandomizationDone && leaderboardItemOrderRef.current.length > 0) { + // Create a map for quick lookups + const itemsMap = new Map( + leaderboardDemosQuery.data.map((item) => [item.id, item]), + ) + + // Maintain the same order as before, but with updated data + const orderedItems = leaderboardItemOrderRef.current + .map((id) => itemsMap.get(id)) + .filter(Boolean) as LeaderboardDemoWithComponent[] + + // Add any new items that might not be in our order yet + const existingIds = new Set(leaderboardItemOrderRef.current) + const newItems = leaderboardDemosQuery.data.filter( + (item) => !existingIds.has(item.id), + ) as LeaderboardDemoWithComponent[] + + setRandomizedLeaderboardItems([...orderedItems, ...newItems]) + return + } + + // Initial randomization if (shouldRandomizeLeaderboard()) { // Create a new array to avoid mutating the original - const shuffled = [...leaderboardDemosQuery.data] + const shuffled = [ + ...leaderboardDemosQuery.data, + ] as LeaderboardDemoWithComponent[] // Fisher-Yates shuffle algorithm for (let i = shuffled.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)) const temp = shuffled[i] - shuffled[i] = shuffled[j] as DemoWithComponent - shuffled[j] = temp as DemoWithComponent + shuffled[i] = shuffled[j] as LeaderboardDemoWithComponent + shuffled[j] = temp as LeaderboardDemoWithComponent } + // Store the order of IDs for future reference + leaderboardItemOrderRef.current = shuffled.map((item) => item.id) + setRandomizedLeaderboardItems(shuffled) } else { - setRandomizedLeaderboardItems(leaderboardDemosQuery.data) + // If not randomizing, still store the original order + leaderboardItemOrderRef.current = leaderboardDemosQuery.data.map( + (item) => item.id, + ) + + setRandomizedLeaderboardItems( + leaderboardDemosQuery.data as LeaderboardDemoWithComponent[], + ) } - }, [leaderboardDemosQuery.data]) + + // Mark randomization as done after initial load + setIsRandomizationDone(true) + }, [leaderboardDemosQuery.data, isRandomizationDone]) const tagCategories = useMemo( () => [ @@ -104,7 +163,6 @@ export function HomeTabLayout({ sortBy = "recommended" }: HomeTabLayoutProps) { ) const { navigateToTab, handleSortChange } = useNavigation() - const router = useRouter() const filteredPopularDemos = useMemo(() => { if (!popularDemosQuery.data) return [] @@ -182,6 +240,86 @@ export function HomeTabLayout({ sortBy = "recommended" }: HomeTabLayoutProps) { } } + // Handle voting for leaderboard items + const handleVote = async (demoId: number) => { + if (!user) { + toast.error("You must be logged in to vote") + return + } + + if (!leaderboardDemosQuery.roundId) { + toast.error("Could not determine current contest round") + return + } + + // Find the demo being voted on + const demoIndex = randomizedLeaderboardItems.findIndex( + (demo) => demo.id === demoId, + ) + if (demoIndex === -1) return + + // Get the current vote state + const currentItem = randomizedLeaderboardItems[demoIndex] + if (!currentItem) return + + const currentVoteState = currentItem.has_voted || false + + // Apply optimistic update + const updatedItems = [...randomizedLeaderboardItems] + const updatedItem = { + ...updatedItems[demoIndex], + } as LeaderboardDemoWithComponent + + updatedItem.has_voted = !currentVoteState + updatedItem.votes_count = + (updatedItem.votes_count || 0) + (currentVoteState ? -1 : 1) + updatedItems[demoIndex] = updatedItem + + setRandomizedLeaderboardItems(updatedItems) + + try { + // Call the backend API + const { data, error } = await supabase.rpc("hunt_toggle_demo_vote", { + p_round_id: leaderboardDemosQuery.roundId, + p_demo_id: demoId, + }) + + if (error) throw error + + toast.success(currentVoteState ? "Vote removed" : "Vote added!") + + // Custom update approach instead of invalidating query + // This prevents full re-randomization + queryClient.setQueryData( + ["leaderboard-demos-home", leaderboardDemosQuery.roundId], + (oldData: any) => { + if (!oldData || !Array.isArray(oldData)) return oldData + + return oldData.map((item) => { + if (item.id === demoId) { + return { + ...item, + has_voted: !currentVoteState, + votes_count: + (item.votes_count || 0) + (currentVoteState ? -1 : 1), + } + } + return item + }) + }, + ) + } catch (error) { + console.error("Error toggling vote:", error) + toast.error("Failed to update vote") + + // Revert the optimistic update on error + setRandomizedLeaderboardItems([ + ...((leaderboardDemosQuery.data || + []) as LeaderboardDemoWithComponent[]), + ]) + } + } + // Check if we need to hide rankings and votes const shouldHideRankings = shouldHideLeaderboardRankings() @@ -197,6 +335,7 @@ export function HomeTabLayout({ sortBy = "recommended" }: HomeTabLayoutProps) { totalCount={group.totalCount} viewAllUrl={group.viewAllUrl} isLeaderboard={group.isLeaderboard} + onVote={group.isLeaderboard ? handleVote : undefined} /> ))} diff --git a/apps/web/components/features/home/horizontal-slider.tsx b/apps/web/components/features/home/horizontal-slider.tsx index 7d408545..e35dc4d4 100644 --- a/apps/web/components/features/home/horizontal-slider.tsx +++ b/apps/web/components/features/home/horizontal-slider.tsx @@ -11,6 +11,7 @@ import { useRouter } from "next/navigation" import { toast } from "sonner" import { ComponentCardSkeleton } from "@/components/ui/skeletons" import { ComponentPreviewDialog } from "@/components/features/component-page/preview-dialog" +import { useUser } from "@clerk/nextjs" interface HorizontalSliderProps { title: string @@ -22,6 +23,7 @@ interface HorizontalSliderProps { className?: string totalCount?: number isLeaderboard?: boolean + onVote?: (demoId: number) => Promise } export function HorizontalSlider({ @@ -34,8 +36,10 @@ export function HorizontalSlider({ className, totalCount, isLeaderboard = false, + onVote, }: HorizontalSliderProps) { const router = useRouter() + const { user } = useUser() const [showLeftButton, setShowLeftButton] = useState(false) const [showRightButton, setShowRightButton] = useState(true) const scrollAreaRef = useRef(null) @@ -213,6 +217,8 @@ export function HorizontalSlider({ ) }} hideVotes={isLeaderboard && hideLeaderboardRankings} + isLeaderboard={isLeaderboard} + onVote={isLeaderboard && user ? onVote : undefined} /> )) diff --git a/apps/web/components/features/list-card/card.tsx b/apps/web/components/features/list-card/card.tsx index 807b74f1..00246414 100644 --- a/apps/web/components/features/list-card/card.tsx +++ b/apps/web/components/features/list-card/card.tsx @@ -27,11 +27,23 @@ import { UserAvatar } from "../../ui/user-avatar" import ComponentPreviewImage from "./card-image" import { ComponentVideoPreview } from "./card-video" import { shouldHideLeaderboardRankings } from "@/lib/utils" +import { UpvoteIcon } from "../../icons/upvote-icon" +import { motion } from "motion/react" +import { useState } from "react" +import { cn } from "@/lib/utils" +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip" +import NumberFlow from "@number-flow/react" // Extended type to include leaderboard fields type LeaderboardDemoWithComponent = DemoWithComponent & { global_rank?: number votes_count?: number + has_voted?: boolean } export function ComponentCard({ @@ -41,6 +53,8 @@ export function ComponentCard({ onClick, onCtrlClick, hideVotes, + isLeaderboard, + onVote, }: { demo?: DemoWithComponent | (Component & { user: User }) isLoading?: boolean @@ -48,6 +62,8 @@ export function ComponentCard({ onClick?: () => void onCtrlClick?: (url: string) => void hideVotes?: boolean + isLeaderboard?: boolean + onVote?: (demoId: number) => Promise }) { if (isLoading || !demo) { return @@ -92,6 +108,12 @@ export function ComponentCard({ ? (demo as LeaderboardDemoWithComponent).votes_count || 0 : 0 + // Check if the user has voted for this item (only for leaderboard items) + const hasVoted = + isDemo && "has_voted" in demo + ? (demo as LeaderboardDemoWithComponent).has_voted + : false + const formatNumber = (num: number) => { if (num >= 1000) { return `${(num / 1000).toFixed(1)}k` @@ -184,6 +206,45 @@ export function ComponentCard({ } } + const handleVote = async (e: React.MouseEvent) => { + e.preventDefault() + e.stopPropagation() + + if (!user) { + toast( +
+
+

Authentication required

+

+ Please sign in to vote +

+
+ + + +
, + { + duration: 5000, + }, + ) + return + } + + if (onVote && demo.id) { + try { + await onVote(demo.id) + } catch (error) { + console.error("Error voting:", error) + toast.error("Failed to update vote") + } + } + } + + // Hide rankings on weekdays + const hideRankings = shouldHideLeaderboardRankings() + return ( @@ -236,6 +297,46 @@ export function ComponentCard({ )} + {/* Vote button for leaderboard items - Always show when isLeaderboard, but hide count when hideRankings */} + {isLeaderboard && onVote && ( +
e.stopPropagation()} + > + + + +
+ +
+
+ +

+ {hasVoted ? "Remove vote" : "Vote for this component"} +

+
+
+
+
+ )} {/* Add Top of Week badge for top 3 leaderboard components */} {isLeaderboardComponent && typeof demo.global_rank === "number" && @@ -277,22 +378,22 @@ export function ComponentCard({
- {votesCount > 0 && !hideVotes && ( -
- - {formatNumber(votesCount)} -
- )} {viewCount > 0 && (
- {formatNumber(viewCount)} + + +
)} {bookmarksCount > 0 && (
- {formatNumber(bookmarksCount)} + + +
)}
diff --git a/apps/web/lib/queries.ts b/apps/web/lib/queries.ts index 9a0be19e..6a284080 100644 --- a/apps/web/lib/queries.ts +++ b/apps/web/lib/queries.ts @@ -1514,6 +1514,7 @@ export function useLeaderboardDemosForHome() { bookmarks_count: submission.bookmarks_count || 0, view_count: submission.view_count || 0, votes_count: submission.votes || 0, + has_voted: submission.has_voted || false, bundle_url: submission.bundle_url || null, global_rank: submission.global_rank || null, compiled_css: null, From 6e7b056b3072de3fe864914a996cea87ad323ea0 Mon Sep 17 00:00:00 2001 From: Serge Bunas Date: Fri, 9 May 2025 02:25:02 +0700 Subject: [PATCH 2/3] Revert "feat: vote from home page" This reverts commit aa0f1a3f20d7341973e56db48b61e1156c7f5185. --- .../components/features/home/home-layout.tsx | 155 +----------------- .../features/home/horizontal-slider.tsx | 6 - .../components/features/list-card/card.tsx | 117 +------------ apps/web/lib/queries.ts | 1 - 4 files changed, 16 insertions(+), 263 deletions(-) diff --git a/apps/web/components/features/home/home-layout.tsx b/apps/web/components/features/home/home-layout.tsx index 1787612d..368dae52 100644 --- a/apps/web/components/features/home/home-layout.tsx +++ b/apps/web/components/features/home/home-layout.tsx @@ -11,14 +11,10 @@ import { import { HorizontalSlider } from "./horizontal-slider" import { SortOption } from "@/types/global" import { DemoWithComponent } from "@/types/global" -import { useMemo, useEffect, useState, useRef } from "react" +import { useMemo, useEffect, useState } from "react" import { useNavigation } from "@/hooks/use-navigation" import { useRouter } from "next/navigation" import { shouldHideLeaderboardRankings } from "@/lib/utils" -import { toast } from "sonner" -import { useClerkSupabaseClient } from "@/lib/clerk" -import { useUser } from "@clerk/nextjs" -import { useQueryClient } from "@tanstack/react-query" interface HomeTabLayoutProps { sortBy?: SortOption @@ -37,13 +33,6 @@ interface SliderGroup { isLeaderboard?: boolean } -// Extended type to include leaderboard fields -type LeaderboardDemoWithComponent = DemoWithComponent & { - global_rank?: number - votes_count?: number - has_voted?: boolean -} - // Helper to check if we need to randomize leaderboard const shouldRandomizeLeaderboard = () => { const now = new Date() @@ -59,22 +48,12 @@ export function HomeTabLayout({ sortBy = "recommended" }: HomeTabLayoutProps) { const popularDemosQuery = useMainDemosExcludingFeatured() const latestDemosQuery = useLatestDemos() const leaderboardDemosQuery = useLeaderboardDemosForHome() - const router = useRouter() - const supabase = useClerkSupabaseClient() - const { user } = useUser() - const queryClient = useQueryClient() - - // Keep track of component order by ID - const leaderboardItemOrderRef = useRef([]) // State to store the already randomized leaderboard items const [randomizedLeaderboardItems, setRandomizedLeaderboardItems] = useState< - LeaderboardDemoWithComponent[] + DemoWithComponent[] >([]) - // Add state to track if initial randomization is done - const [isRandomizationDone, setIsRandomizationDone] = useState(false) - // Process leaderboard data once when it arrives useEffect(() => { if ( @@ -85,61 +64,23 @@ export function HomeTabLayout({ sortBy = "recommended" }: HomeTabLayoutProps) { return } - // If we already have an order and randomization is done, maintain the order - if (isRandomizationDone && leaderboardItemOrderRef.current.length > 0) { - // Create a map for quick lookups - const itemsMap = new Map( - leaderboardDemosQuery.data.map((item) => [item.id, item]), - ) - - // Maintain the same order as before, but with updated data - const orderedItems = leaderboardItemOrderRef.current - .map((id) => itemsMap.get(id)) - .filter(Boolean) as LeaderboardDemoWithComponent[] - - // Add any new items that might not be in our order yet - const existingIds = new Set(leaderboardItemOrderRef.current) - const newItems = leaderboardDemosQuery.data.filter( - (item) => !existingIds.has(item.id), - ) as LeaderboardDemoWithComponent[] - - setRandomizedLeaderboardItems([...orderedItems, ...newItems]) - return - } - - // Initial randomization if (shouldRandomizeLeaderboard()) { // Create a new array to avoid mutating the original - const shuffled = [ - ...leaderboardDemosQuery.data, - ] as LeaderboardDemoWithComponent[] + const shuffled = [...leaderboardDemosQuery.data] // Fisher-Yates shuffle algorithm for (let i = shuffled.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)) const temp = shuffled[i] - shuffled[i] = shuffled[j] as LeaderboardDemoWithComponent - shuffled[j] = temp as LeaderboardDemoWithComponent + shuffled[i] = shuffled[j] as DemoWithComponent + shuffled[j] = temp as DemoWithComponent } - // Store the order of IDs for future reference - leaderboardItemOrderRef.current = shuffled.map((item) => item.id) - setRandomizedLeaderboardItems(shuffled) } else { - // If not randomizing, still store the original order - leaderboardItemOrderRef.current = leaderboardDemosQuery.data.map( - (item) => item.id, - ) - - setRandomizedLeaderboardItems( - leaderboardDemosQuery.data as LeaderboardDemoWithComponent[], - ) + setRandomizedLeaderboardItems(leaderboardDemosQuery.data) } - - // Mark randomization as done after initial load - setIsRandomizationDone(true) - }, [leaderboardDemosQuery.data, isRandomizationDone]) + }, [leaderboardDemosQuery.data]) const tagCategories = useMemo( () => [ @@ -163,6 +104,7 @@ export function HomeTabLayout({ sortBy = "recommended" }: HomeTabLayoutProps) { ) const { navigateToTab, handleSortChange } = useNavigation() + const router = useRouter() const filteredPopularDemos = useMemo(() => { if (!popularDemosQuery.data) return [] @@ -240,86 +182,6 @@ export function HomeTabLayout({ sortBy = "recommended" }: HomeTabLayoutProps) { } } - // Handle voting for leaderboard items - const handleVote = async (demoId: number) => { - if (!user) { - toast.error("You must be logged in to vote") - return - } - - if (!leaderboardDemosQuery.roundId) { - toast.error("Could not determine current contest round") - return - } - - // Find the demo being voted on - const demoIndex = randomizedLeaderboardItems.findIndex( - (demo) => demo.id === demoId, - ) - if (demoIndex === -1) return - - // Get the current vote state - const currentItem = randomizedLeaderboardItems[demoIndex] - if (!currentItem) return - - const currentVoteState = currentItem.has_voted || false - - // Apply optimistic update - const updatedItems = [...randomizedLeaderboardItems] - const updatedItem = { - ...updatedItems[demoIndex], - } as LeaderboardDemoWithComponent - - updatedItem.has_voted = !currentVoteState - updatedItem.votes_count = - (updatedItem.votes_count || 0) + (currentVoteState ? -1 : 1) - updatedItems[demoIndex] = updatedItem - - setRandomizedLeaderboardItems(updatedItems) - - try { - // Call the backend API - const { data, error } = await supabase.rpc("hunt_toggle_demo_vote", { - p_round_id: leaderboardDemosQuery.roundId, - p_demo_id: demoId, - }) - - if (error) throw error - - toast.success(currentVoteState ? "Vote removed" : "Vote added!") - - // Custom update approach instead of invalidating query - // This prevents full re-randomization - queryClient.setQueryData( - ["leaderboard-demos-home", leaderboardDemosQuery.roundId], - (oldData: any) => { - if (!oldData || !Array.isArray(oldData)) return oldData - - return oldData.map((item) => { - if (item.id === demoId) { - return { - ...item, - has_voted: !currentVoteState, - votes_count: - (item.votes_count || 0) + (currentVoteState ? -1 : 1), - } - } - return item - }) - }, - ) - } catch (error) { - console.error("Error toggling vote:", error) - toast.error("Failed to update vote") - - // Revert the optimistic update on error - setRandomizedLeaderboardItems([ - ...((leaderboardDemosQuery.data || - []) as LeaderboardDemoWithComponent[]), - ]) - } - } - // Check if we need to hide rankings and votes const shouldHideRankings = shouldHideLeaderboardRankings() @@ -335,7 +197,6 @@ export function HomeTabLayout({ sortBy = "recommended" }: HomeTabLayoutProps) { totalCount={group.totalCount} viewAllUrl={group.viewAllUrl} isLeaderboard={group.isLeaderboard} - onVote={group.isLeaderboard ? handleVote : undefined} /> ))} diff --git a/apps/web/components/features/home/horizontal-slider.tsx b/apps/web/components/features/home/horizontal-slider.tsx index e35dc4d4..7d408545 100644 --- a/apps/web/components/features/home/horizontal-slider.tsx +++ b/apps/web/components/features/home/horizontal-slider.tsx @@ -11,7 +11,6 @@ import { useRouter } from "next/navigation" import { toast } from "sonner" import { ComponentCardSkeleton } from "@/components/ui/skeletons" import { ComponentPreviewDialog } from "@/components/features/component-page/preview-dialog" -import { useUser } from "@clerk/nextjs" interface HorizontalSliderProps { title: string @@ -23,7 +22,6 @@ interface HorizontalSliderProps { className?: string totalCount?: number isLeaderboard?: boolean - onVote?: (demoId: number) => Promise } export function HorizontalSlider({ @@ -36,10 +34,8 @@ export function HorizontalSlider({ className, totalCount, isLeaderboard = false, - onVote, }: HorizontalSliderProps) { const router = useRouter() - const { user } = useUser() const [showLeftButton, setShowLeftButton] = useState(false) const [showRightButton, setShowRightButton] = useState(true) const scrollAreaRef = useRef(null) @@ -217,8 +213,6 @@ export function HorizontalSlider({ ) }} hideVotes={isLeaderboard && hideLeaderboardRankings} - isLeaderboard={isLeaderboard} - onVote={isLeaderboard && user ? onVote : undefined} /> )) diff --git a/apps/web/components/features/list-card/card.tsx b/apps/web/components/features/list-card/card.tsx index 00246414..807b74f1 100644 --- a/apps/web/components/features/list-card/card.tsx +++ b/apps/web/components/features/list-card/card.tsx @@ -27,23 +27,11 @@ import { UserAvatar } from "../../ui/user-avatar" import ComponentPreviewImage from "./card-image" import { ComponentVideoPreview } from "./card-video" import { shouldHideLeaderboardRankings } from "@/lib/utils" -import { UpvoteIcon } from "../../icons/upvote-icon" -import { motion } from "motion/react" -import { useState } from "react" -import { cn } from "@/lib/utils" -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from "@/components/ui/tooltip" -import NumberFlow from "@number-flow/react" // Extended type to include leaderboard fields type LeaderboardDemoWithComponent = DemoWithComponent & { global_rank?: number votes_count?: number - has_voted?: boolean } export function ComponentCard({ @@ -53,8 +41,6 @@ export function ComponentCard({ onClick, onCtrlClick, hideVotes, - isLeaderboard, - onVote, }: { demo?: DemoWithComponent | (Component & { user: User }) isLoading?: boolean @@ -62,8 +48,6 @@ export function ComponentCard({ onClick?: () => void onCtrlClick?: (url: string) => void hideVotes?: boolean - isLeaderboard?: boolean - onVote?: (demoId: number) => Promise }) { if (isLoading || !demo) { return @@ -108,12 +92,6 @@ export function ComponentCard({ ? (demo as LeaderboardDemoWithComponent).votes_count || 0 : 0 - // Check if the user has voted for this item (only for leaderboard items) - const hasVoted = - isDemo && "has_voted" in demo - ? (demo as LeaderboardDemoWithComponent).has_voted - : false - const formatNumber = (num: number) => { if (num >= 1000) { return `${(num / 1000).toFixed(1)}k` @@ -206,45 +184,6 @@ export function ComponentCard({ } } - const handleVote = async (e: React.MouseEvent) => { - e.preventDefault() - e.stopPropagation() - - if (!user) { - toast( -
-
-

Authentication required

-

- Please sign in to vote -

-
- - - -
, - { - duration: 5000, - }, - ) - return - } - - if (onVote && demo.id) { - try { - await onVote(demo.id) - } catch (error) { - console.error("Error voting:", error) - toast.error("Failed to update vote") - } - } - } - - // Hide rankings on weekdays - const hideRankings = shouldHideLeaderboardRankings() - return ( @@ -297,46 +236,6 @@ export function ComponentCard({ )} - {/* Vote button for leaderboard items - Always show when isLeaderboard, but hide count when hideRankings */} - {isLeaderboard && onVote && ( -
e.stopPropagation()} - > - - - -
- -
-
- -

- {hasVoted ? "Remove vote" : "Vote for this component"} -

-
-
-
-
- )} {/* Add Top of Week badge for top 3 leaderboard components */} {isLeaderboardComponent && typeof demo.global_rank === "number" && @@ -378,22 +277,22 @@ export function ComponentCard({
+ {votesCount > 0 && !hideVotes && ( +
+ + {formatNumber(votesCount)} +
+ )} {viewCount > 0 && (
- - - + {formatNumber(viewCount)}
)} {bookmarksCount > 0 && (
- - - + {formatNumber(bookmarksCount)}
)}
diff --git a/apps/web/lib/queries.ts b/apps/web/lib/queries.ts index 6a284080..9a0be19e 100644 --- a/apps/web/lib/queries.ts +++ b/apps/web/lib/queries.ts @@ -1514,7 +1514,6 @@ export function useLeaderboardDemosForHome() { bookmarks_count: submission.bookmarks_count || 0, view_count: submission.view_count || 0, votes_count: submission.votes || 0, - has_voted: submission.has_voted || false, bundle_url: submission.bundle_url || null, global_rank: submission.global_rank || null, compiled_css: null, From ff3098b060ce73358e9391de3b4a417309799466 Mon Sep 17 00:00:00 2001 From: Serge Bunas Date: Fri, 9 May 2025 15:40:00 +0700 Subject: [PATCH 3/3] init cypress --- .../[username]/sandbox/[sandboxId]/page.tsx | 5 +- apps/web/cypress.config.ts | 9 + apps/web/cypress/e2e/sandbox_basic.cy.ts | 24 + apps/web/cypress/fixtures/example.json | 5 + apps/web/cypress/support/commands.ts | 37 + apps/web/cypress/support/e2e.ts | 17 + apps/web/package.json | 2 + pnpm-lock.yaml | 672 +++++++++++++++++- 8 files changed, 730 insertions(+), 41 deletions(-) create mode 100644 apps/web/cypress.config.ts create mode 100644 apps/web/cypress/e2e/sandbox_basic.cy.ts create mode 100644 apps/web/cypress/fixtures/example.json create mode 100644 apps/web/cypress/support/commands.ts create mode 100644 apps/web/cypress/support/e2e.ts diff --git a/apps/web/app/studio/[username]/sandbox/[sandboxId]/page.tsx b/apps/web/app/studio/[username]/sandbox/[sandboxId]/page.tsx index 03131016..82381d93 100644 --- a/apps/web/app/studio/[username]/sandbox/[sandboxId]/page.tsx +++ b/apps/web/app/studio/[username]/sandbox/[sandboxId]/page.tsx @@ -4,10 +4,7 @@ import { useParams } from "next/navigation" import { SandboxHeader } from "@/components/features/studio/sandbox/components/sandbox-header" import { useRouter, usePathname } from "next/navigation" import { useState } from "react" -import { - ServerSandbox, - useSandbox, -} from "@/components/features/studio/sandbox/hooks/use-sandbox" +import { ServerSandbox } from "@/components/features/studio/sandbox/hooks/use-sandbox" import PageClient from "./page.client" export default function Page() { diff --git a/apps/web/cypress.config.ts b/apps/web/cypress.config.ts new file mode 100644 index 00000000..17161e32 --- /dev/null +++ b/apps/web/cypress.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from "cypress"; + +export default defineConfig({ + e2e: { + setupNodeEvents(on, config) { + // implement node event listeners here + }, + }, +}); diff --git a/apps/web/cypress/e2e/sandbox_basic.cy.ts b/apps/web/cypress/e2e/sandbox_basic.cy.ts new file mode 100644 index 00000000..53e03793 --- /dev/null +++ b/apps/web/cypress/e2e/sandbox_basic.cy.ts @@ -0,0 +1,24 @@ +describe("Home Page Portal Interaction", () => { + it("should open the portal after clicking Browse Component and restrict interaction to the portal", () => { + cy.visit("http://localhost:3000/") + cy.contains(/browse component/i).click() + cy.get("[data-portal]").should("be.visible") + cy.get("body").then(($body) => { + if ($body.find("[data-portal]").length) { + cy.get("[data-portal]").should("be.visible") + cy.get("main, header, footer").should( + "have.css", + "pointer-events", + "none", + ) + } + }) + }) +}) + +describe("Studio Page Basic Load", () => { + it("should load the studio page for serjobasDEV", () => { + cy.visit("http://localhost:3000/studio/serjobasDEV") + cy.contains("serjobasDEV").should("be.visible") + }) +}) diff --git a/apps/web/cypress/fixtures/example.json b/apps/web/cypress/fixtures/example.json new file mode 100644 index 00000000..02e42543 --- /dev/null +++ b/apps/web/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/apps/web/cypress/support/commands.ts b/apps/web/cypress/support/commands.ts new file mode 100644 index 00000000..698b01a4 --- /dev/null +++ b/apps/web/cypress/support/commands.ts @@ -0,0 +1,37 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } \ No newline at end of file diff --git a/apps/web/cypress/support/e2e.ts b/apps/web/cypress/support/e2e.ts new file mode 100644 index 00000000..e4e246ec --- /dev/null +++ b/apps/web/cypress/support/e2e.ts @@ -0,0 +1,17 @@ +// *********************************************************** +// This example support/e2e.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' \ No newline at end of file diff --git a/apps/web/package.json b/apps/web/package.json index 29250dfb..d07ff7b8 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -10,6 +10,7 @@ "start": "next start", "lint": "next lint", "test": "vitest run", + "cypress:open": "cypress open", "build:css": "tailwindcss -i ./input.css -o ./public/compiled-tailwind.css --minify", "combine-css": "node css/combinedCSS.js", "generate-embeddings": "ts-node --project scripts/tsconfig.json scripts/generate-embeddings.ts" @@ -115,6 +116,7 @@ "@types/react": "19.1.1", "@types/react-dom": "19.1.2", "@types/react-syntax-highlighter": "^15.5.13", + "cypress": "^14.3.3", "dotenv": "^16.4.5", "eslint": "^8", "eslint-config-next": "15.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 95714b9b..f11b4698 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -398,6 +398,9 @@ importers: '@types/react-syntax-highlighter': specifier: ^15.5.13 version: 15.5.13 + cypress: + specifier: ^14.3.3 + version: 14.3.3 dotenv: specifier: ^16.4.5 version: 16.5.0 @@ -1359,7 +1362,7 @@ packages: '@babel/traverse': 7.27.0 '@babel/types': 7.27.0 convert-source-map: 2.0.0 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -1702,7 +1705,7 @@ packages: '@babel/parser': 7.27.0 '@babel/template': 7.27.0 '@babel/types': 7.27.0 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -1952,6 +1955,39 @@ packages: dependencies: '@jridgewell/trace-mapping': 0.3.9 + /@cypress/request@3.0.8: + resolution: {integrity: sha512-h0NFgh1mJmm1nr4jCwkGHwKneVYKghUyWe6TMNrk0B9zsjAJxpg8C4/+BAcmLgCPa1vj1V8rNUaILl+zYRUWBQ==} + engines: {node: '>= 6'} + dependencies: + aws-sign2: 0.7.0 + aws4: 1.13.2 + caseless: 0.12.0 + combined-stream: 1.0.8 + extend: 3.0.2 + forever-agent: 0.6.1 + form-data: 4.0.2 + http-signature: 1.4.0 + is-typedarray: 1.0.0 + isstream: 0.1.2 + json-stringify-safe: 5.0.1 + mime-types: 2.1.35 + performance-now: 2.1.0 + qs: 6.14.0 + safe-buffer: 5.2.1 + tough-cookie: 5.1.2 + tunnel-agent: 0.6.0 + uuid: 8.3.2 + dev: true + + /@cypress/xvfb@1.2.4(supports-color@8.1.1): + resolution: {integrity: sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==} + dependencies: + debug: 3.2.7(supports-color@8.1.1) + lodash.once: 4.1.1 + transitivePeerDependencies: + - supports-color + dev: true + /@emnapi/core@1.4.3: resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==} requiresBuild: true @@ -2196,7 +2232,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) espree: 9.6.1 globals: 13.24.0 ignore: 5.3.2 @@ -2266,7 +2302,7 @@ packages: deprecated: Use @eslint/config-array instead dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -6385,6 +6421,14 @@ packages: resolution: {integrity: sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==} dev: true + /@types/sinonjs__fake-timers@8.1.1: + resolution: {integrity: sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==} + dev: true + + /@types/sizzle@2.3.9: + resolution: {integrity: sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w==} + dev: true + /@types/through@0.0.33: resolution: {integrity: sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==} dependencies: @@ -6405,6 +6449,14 @@ packages: '@types/node': 20.17.32 dev: false + /@types/yauzl@2.10.3: + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + requiresBuild: true + dependencies: + '@types/node': 20.17.32 + dev: true + optional: true + /@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.57.1)(typescript@5.8.3): resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} engines: {node: ^16.0.0 || >=18.0.0} @@ -6422,7 +6474,7 @@ packages: '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.1)(typescript@5.8.3) '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.8.3) '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) eslint: 8.57.1 graphemer: 1.4.0 ignore: 5.3.2 @@ -6475,7 +6527,7 @@ packages: '@typescript-eslint/types': 6.21.0 '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.8.3) '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) eslint: 8.57.1 typescript: 5.8.3 transitivePeerDependencies: @@ -6496,7 +6548,7 @@ packages: '@typescript-eslint/types': 7.18.0 '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.8.3) '@typescript-eslint/visitor-keys': 7.18.0 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) eslint: 8.57.1 typescript: 5.8.3 transitivePeerDependencies: @@ -6539,7 +6591,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.8.3) '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.8.3) - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) eslint: 8.57.1 ts-api-utils: 1.4.3(typescript@5.8.3) typescript: 5.8.3 @@ -6559,7 +6611,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.8.3) '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.8.3) - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) eslint: 8.57.1 ts-api-utils: 1.4.3(typescript@5.8.3) typescript: 5.8.3 @@ -6593,7 +6645,7 @@ packages: dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 semver: 7.7.1 @@ -6614,7 +6666,7 @@ packages: dependencies: '@typescript-eslint/types': 6.21.0 '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -6636,7 +6688,7 @@ packages: dependencies: '@typescript-eslint/types': 7.18.0 '@typescript-eslint/visitor-keys': 7.18.0 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.5 @@ -7054,6 +7106,11 @@ packages: resolution: {integrity: sha512-PMqBCBvrOVDRqLGooQb+z+t1Q0PiPyurUQeZRR5uHBOVZcW8B04KMmnT12USnhpNX2wCPagWzLVppQMUG3u0Dw==} dev: false + /ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + dev: true + /ansi-escapes@3.2.0: resolution: {integrity: sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==} engines: {node: '>=4'} @@ -7119,6 +7176,10 @@ packages: picomatch: 2.3.1 dev: false + /arch@2.2.0: + resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + dev: true + /arg@4.1.0: resolution: {integrity: sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==} dev: false @@ -7245,6 +7306,17 @@ packages: is-array-buffer: 3.0.5 dev: true + /asn1@0.2.6: + resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /assert-plus@1.0.0: + resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} + engines: {node: '>=0.8'} + dev: true + /assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -7261,14 +7333,27 @@ packages: tslib: 2.8.1 dev: true + /astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + dev: true + /async-function@1.0.0: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} dev: true + /async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + dev: true + /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: false + + /at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + dev: true /attr-accept@2.2.5: resolution: {integrity: sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ==} @@ -7298,6 +7383,14 @@ packages: possible-typed-array-names: 1.1.0 dev: true + /aws-sign2@0.7.0: + resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} + dev: true + + /aws4@1.13.2: + resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==} + dev: true + /axe-core@4.10.3: resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==} engines: {node: '>=4'} @@ -7324,6 +7417,12 @@ packages: engines: {node: '>=10.0.0'} dev: true + /bcrypt-pbkdf@1.0.2: + resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} + dependencies: + tweetnacl: 0.14.5 + dev: true + /bin-links@5.0.0: resolution: {integrity: sha512-sdleLVfCjBtgO5cNjA2HVRvWBJAHs4zwenaCPMNJAJU0yNxpzj80IpjOIimkpkr+mhlA+how5poQtt53PygbHA==} engines: {node: ^18.17.0 || >=20.5.0} @@ -7348,6 +7447,14 @@ packages: readable-stream: 3.6.2 dev: true + /blob-util@2.0.2: + resolution: {integrity: sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==} + dev: true + + /bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + dev: true + /boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} dev: false @@ -7384,6 +7491,10 @@ packages: node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.24.4) + /buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + dev: true + /buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} dependencies: @@ -7426,6 +7537,11 @@ packages: engines: {node: '>=8'} dev: true + /cachedir@2.4.0: + resolution: {integrity: sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==} + engines: {node: '>=6'} + dev: true + /call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -7470,6 +7586,10 @@ packages: /caniuse-lite@1.0.30001715: resolution: {integrity: sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==} + /caseless@0.12.0: + resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} + dev: true + /ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} dev: false @@ -7563,6 +7683,11 @@ packages: engines: {node: '>= 16'} dev: true + /check-more-types@2.24.0: + resolution: {integrity: sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==} + engines: {node: '>= 0.8.0'} + dev: true + /cheerio-select@2.1.0: resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} dependencies: @@ -7616,6 +7741,11 @@ packages: engines: {node: '>=8'} dev: true + /ci-info@4.2.0: + resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==} + engines: {node: '>=8'} + dev: true + /class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} dependencies: @@ -7670,6 +7800,23 @@ packages: engines: {node: '>=6'} dev: true + /cli-table3@0.6.1: + resolution: {integrity: sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==} + engines: {node: 10.* || >= 12.*} + dependencies: + string-width: 4.2.3 + optionalDependencies: + colors: 1.4.0 + dev: true + + /cli-truncate@2.1.0: + resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} + engines: {node: '>=8'} + dependencies: + slice-ansi: 3.0.0 + string-width: 4.2.3 + dev: true + /cli-width@2.2.1: resolution: {integrity: sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==} dev: true @@ -7770,12 +7917,22 @@ packages: dev: false optional: true + /colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + dev: true + + /colors@1.4.0: + resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} + engines: {node: '>=0.1.90'} + requiresBuild: true + dev: true + optional: true + /combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} dependencies: delayed-stream: 1.0.0 - dev: false /comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} @@ -7791,6 +7948,16 @@ packages: engines: {node: '>= 6'} dev: false + /commander@6.2.1: + resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} + engines: {node: '>= 6'} + dev: true + + /common-tags@1.8.2: + resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} + engines: {node: '>=4.0.0'} + dev: true + /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: true @@ -7837,6 +8004,10 @@ packages: requiresBuild: true dev: false + /core-util-is@1.0.2: + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} + dev: true + /create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} @@ -7881,6 +8052,57 @@ packages: /csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + /cypress@14.3.3: + resolution: {integrity: sha512-1Rz7zc9iqLww6BysaESqUhtIuaFHS7nL3wREovAKYsNhLTfX3TbcBWHWgEz70YimH2NkSOsm4oIcJJ9HYHOlew==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + requiresBuild: true + dependencies: + '@cypress/request': 3.0.8 + '@cypress/xvfb': 1.2.4(supports-color@8.1.1) + '@types/sinonjs__fake-timers': 8.1.1 + '@types/sizzle': 2.3.9 + arch: 2.2.0 + blob-util: 2.0.2 + bluebird: 3.7.2 + buffer: 5.7.1 + cachedir: 2.4.0 + chalk: 4.1.2 + check-more-types: 2.24.0 + ci-info: 4.2.0 + cli-cursor: 3.1.0 + cli-table3: 0.6.1 + commander: 6.2.1 + common-tags: 1.8.2 + dayjs: 1.11.13 + debug: 4.4.0(supports-color@8.1.1) + enquirer: 2.4.1 + eventemitter2: 6.4.7 + execa: 4.1.0 + executable: 4.1.1 + extract-zip: 2.0.1(supports-color@8.1.1) + figures: 3.2.0 + fs-extra: 9.1.0 + getos: 3.2.1 + is-installed-globally: 0.4.0 + lazy-ass: 1.6.0 + listr2: 3.14.0(enquirer@2.4.1) + lodash: 4.17.21 + log-symbols: 4.1.0 + minimist: 1.2.8 + ospath: 1.2.2 + pretty-bytes: 5.6.0 + process: 0.11.10 + proxy-from-env: 1.0.0 + request-progress: 3.0.0 + semver: 7.7.1 + supports-color: 8.1.1 + tmp: 0.2.3 + tree-kill: 1.2.2 + untildify: 4.0.0 + yauzl: 2.10.0 + dev: true + /d3-array@3.2.4: resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} engines: {node: '>=12'} @@ -7969,6 +8191,13 @@ packages: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} dev: true + /dashdash@1.14.1: + resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} + engines: {node: '>=0.10'} + dependencies: + assert-plus: 1.0.0 + dev: true + /data-uri-to-buffer@4.0.1: resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} engines: {node: '>= 12'} @@ -8009,7 +8238,11 @@ packages: resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} dev: false - /debug@3.2.7: + /dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + dev: true + + /debug@3.2.7(supports-color@8.1.1): resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: supports-color: '*' @@ -8018,9 +8251,10 @@ packages: optional: true dependencies: ms: 2.1.3 + supports-color: 8.1.1 dev: true - /debug@4.4.0: + /debug@4.4.0(supports-color@8.1.1): resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} engines: {node: '>=6.0'} peerDependencies: @@ -8030,6 +8264,7 @@ packages: optional: true dependencies: ms: 2.1.3 + supports-color: 8.1.1 /decimal.js-light@2.5.1: resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==} @@ -8115,7 +8350,6 @@ packages: /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - dev: false /depd@1.1.2: resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} @@ -8262,6 +8496,13 @@ packages: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: false + /ecc-jsbn@0.1.2: + resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} + dependencies: + jsbn: 0.1.1 + safer-buffer: 2.1.2 + dev: true + /electron-to-chromium@1.5.144: resolution: {integrity: sha512-eJIaMRKeAzxfBSxtjYnoIAw/tdD6VIH6tHBZepZnAbE3Gyqqs5mGN87DvcldPUbVkIljTK8pY0CMcUljP64lfQ==} @@ -8299,6 +8540,12 @@ packages: whatwg-encoding: 3.1.1 dev: false + /end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + dev: true + /endent@2.1.0: resolution: {integrity: sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==} dependencies: @@ -8307,6 +8554,14 @@ packages: objectorarray: 1.0.5 dev: false + /enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + dev: true + /entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -8618,7 +8873,7 @@ packages: /eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} dependencies: - debug: 3.2.7 + debug: 3.2.7(supports-color@8.1.1) is-core-module: 2.16.1 resolve: 1.22.10 transitivePeerDependencies: @@ -8639,7 +8894,7 @@ packages: optional: true dependencies: '@nolyfill/is-core-module': 1.0.39 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) eslint: 8.57.1 eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) get-tsconfig: 4.10.0 @@ -8673,7 +8928,7 @@ packages: optional: true dependencies: '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.8.3) - debug: 3.2.7 + debug: 3.2.7(supports-color@8.1.1) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0)(eslint@8.57.1) @@ -8708,7 +8963,7 @@ packages: array.prototype.findlastindex: 1.2.6 array.prototype.flat: 1.3.3 array.prototype.flatmap: 1.3.3 - debug: 3.2.7 + debug: 3.2.7(supports-color@8.1.1) doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 @@ -8935,7 +9190,7 @@ packages: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -9044,10 +9299,29 @@ packages: engines: {node: '>=6'} dev: false + /eventemitter2@6.4.7: + resolution: {integrity: sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==} + dev: true + /eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} dev: false + /execa@4.1.0: + resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.6 + get-stream: 5.2.0 + human-signals: 1.1.1 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + /execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -9063,6 +9337,13 @@ packages: strip-final-newline: 2.0.0 dev: true + /executable@4.1.1: + resolution: {integrity: sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==} + engines: {node: '>=4'} + dependencies: + pify: 2.3.0 + dev: true + /expect-type@1.2.1: resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==} engines: {node: '>=12.0.0'} @@ -9073,6 +9354,10 @@ packages: dependencies: type: 2.7.3 + /extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + dev: true + /external-editor@3.1.0: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} @@ -9082,6 +9367,25 @@ packages: tmp: 0.0.33 dev: true + /extract-zip@2.0.1(supports-color@8.1.1): + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + dependencies: + debug: 4.4.0(supports-color@8.1.1) + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + dev: true + + /extsprintf@1.3.0: + resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} + engines: {'0': node >=0.6.0} + dev: true + /fast-deep-equal@2.0.1: resolution: {integrity: sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==} dev: false @@ -9144,6 +9448,12 @@ packages: dependencies: reusify: 1.1.0 + /fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + dependencies: + pend: 1.2.0 + dev: true + /fdir@6.4.4(picomatch@4.0.2): resolution: {integrity: sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==} peerDependencies: @@ -9255,6 +9565,10 @@ packages: signal-exit: 4.1.0 dev: false + /forever-agent@0.6.1: + resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} + dev: true + /form-data-encoder@1.7.2: resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} dev: false @@ -9267,7 +9581,6 @@ packages: combined-stream: 1.0.8 es-set-tostringtag: 2.1.0 mime-types: 2.1.35 - dev: false /formdata-node@4.4.1: resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} @@ -9317,6 +9630,16 @@ packages: universalify: 2.0.1 dev: true + /fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: true + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true @@ -9395,6 +9718,13 @@ packages: engines: {node: '>=12'} dev: true + /get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + dependencies: + pump: 3.0.2 + dev: true + /get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -9421,11 +9751,23 @@ packages: dependencies: basic-ftp: 5.0.5 data-uri-to-buffer: 6.0.2 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true + /getos@3.2.1: + resolution: {integrity: sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==} + dependencies: + async: 3.2.6 + dev: true + + /getpass@0.1.7: + resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} + dependencies: + assert-plus: 1.0.0 + dev: true + /git-hooks-list@3.2.0: resolution: {integrity: sha512-ZHG9a1gEhUMX1TvGrLdyWb9kDopCBbTnI8z4JgRMYxsijWipgjSEYoPWqBuIB0DnRnvqlQSEeVmzpeuPm7NdFQ==} dev: true @@ -9470,6 +9812,13 @@ packages: path-is-absolute: 1.0.1 dev: true + /global-dirs@3.0.1: + resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} + engines: {node: '>=10'} + dependencies: + ini: 2.0.0 + dev: true + /globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -9565,7 +9914,6 @@ packages: /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - dev: true /has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} @@ -9678,21 +10026,35 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.3 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true + /http-signature@1.4.0: + resolution: {integrity: sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==} + engines: {node: '>=0.10'} + dependencies: + assert-plus: 1.0.0 + jsprim: 2.0.2 + sshpk: 1.18.0 + dev: true + /https-proxy-agent@7.0.6: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} dependencies: agent-base: 7.1.3 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true + /human-signals@1.1.1: + resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} + engines: {node: '>=8.12.0'} + dev: true + /human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -9766,6 +10128,11 @@ packages: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} dev: true + /ini@2.0.0: + resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} + engines: {node: '>=10'} + dev: true + /inquirer@6.5.2: resolution: {integrity: sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==} engines: {node: '>=6.0.0'} @@ -10006,6 +10373,14 @@ packages: dependencies: is-extglob: 2.1.1 + /is-installed-globally@0.4.0: + resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==} + engines: {node: '>=10'} + dependencies: + global-dirs: 3.0.1 + is-path-inside: 3.0.3 + dev: true + /is-interactive@1.0.0: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} @@ -10112,6 +10487,10 @@ packages: which-typed-array: 1.1.19 dev: true + /is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + dev: true + /is-unicode-supported@0.1.0: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} @@ -10155,6 +10534,10 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + /isstream@0.1.2: + resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} + dev: true + /iterator.prototype@1.1.5: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} @@ -10218,6 +10601,10 @@ packages: argparse: 2.0.1 dev: true + /jsbn@0.1.1: + resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} + dev: true + /jsbn@1.1.0: resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} dev: true @@ -10244,10 +10631,18 @@ packages: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: true + /json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + dev: true + /json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true + /json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + dev: true + /json5@1.0.2: resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} hasBin: true @@ -10268,6 +10663,16 @@ packages: graceful-fs: 4.2.11 dev: true + /jsprim@2.0.2: + resolution: {integrity: sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==} + engines: {'0': node >=0.6.0} + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.4.0 + verror: 1.10.0 + dev: true + /jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} @@ -10302,6 +10707,11 @@ packages: language-subtag-registry: 0.3.23 dev: true + /lazy-ass@1.6.0: + resolution: {integrity: sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==} + engines: {node: '> 0.8'} + dev: true + /leac@0.6.0: resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==} dev: false @@ -10322,6 +10732,26 @@ packages: /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + /listr2@3.14.0(enquirer@2.4.1): + resolution: {integrity: sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==} + engines: {node: '>=10.0.0'} + peerDependencies: + enquirer: '>= 2.3.0 < 3' + peerDependenciesMeta: + enquirer: + optional: true + dependencies: + cli-truncate: 2.1.0 + colorette: 2.0.20 + enquirer: 2.4.1 + log-update: 4.0.0 + p-map: 4.0.0 + rfdc: 1.4.1 + rxjs: 7.8.2 + through: 2.3.8 + wrap-ansi: 7.0.0 + dev: true + /locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -10351,6 +10781,10 @@ packages: /lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + /lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + dev: true + /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -10369,6 +10803,16 @@ packages: is-unicode-supported: 0.1.0 dev: true + /log-update@4.0.0: + resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} + engines: {node: '>=10'} + dependencies: + ansi-escapes: 4.3.2 + cli-cursor: 3.1.0 + slice-ansi: 4.0.0 + wrap-ansi: 6.2.0 + dev: true + /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -10563,7 +11007,6 @@ packages: /mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} - dev: false /mime-db@1.54.0: resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} @@ -10575,7 +11018,6 @@ packages: engines: {node: '>= 0.6'} dependencies: mime-db: 1.52.0 - dev: false /mimic-fn@1.2.0: resolution: {integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==} @@ -11116,6 +11558,10 @@ packages: engines: {node: '>=0.10.0'} dev: true + /ospath@1.2.2: + resolution: {integrity: sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==} + dev: true + /outvariant@1.4.0: resolution: {integrity: sha512-AlWY719RF02ujitly7Kk/0QlV+pXGFDHrHf9O2OKqyqgBieaPOIeuSkL8sRK6j2WK+/ZAURq2kZsY0d8JapUiw==} dev: false @@ -11164,6 +11610,13 @@ packages: aggregate-error: 3.1.0 dev: true + /p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + dependencies: + aggregate-error: 3.1.0 + dev: true + /p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -11175,7 +11628,7 @@ packages: dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 agent-base: 7.1.3 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) get-uri: 6.0.4 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 @@ -11302,6 +11755,14 @@ packages: resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==} dev: false + /pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + dev: true + + /performance-now@2.1.0: + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + dev: true + /picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -11316,7 +11777,6 @@ packages: /pify@2.3.0: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} - dev: false /pify@3.0.0: resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} @@ -11475,6 +11935,11 @@ packages: engines: {node: '>=14'} hasBin: true + /pretty-bytes@5.6.0: + resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} + engines: {node: '>=6'} + dev: true + /prismjs@1.29.0: resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} engines: {node: '>=6'} @@ -11485,6 +11950,11 @@ packages: engines: {node: ^18.17.0 || >=20.5.0} dev: true + /process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + dev: true + /prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} dependencies: @@ -11501,7 +11971,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.3 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 lru-cache: 7.18.3 @@ -11512,10 +11982,21 @@ packages: - supports-color dev: true + /proxy-from-env@1.0.0: + resolution: {integrity: sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==} + dev: true + /proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} dev: true + /pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: true + /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -12042,6 +12523,12 @@ packages: jsesc: 0.5.0 dev: true + /request-progress@3.0.0: + resolution: {integrity: sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==} + dependencies: + throttleit: 1.0.1 + dev: true + /requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} dev: false @@ -12110,6 +12597,10 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + /rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + dev: true + /rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} deprecated: Rimraf versions prior to v4 are no longer supported @@ -12412,6 +12903,24 @@ packages: engines: {node: '>=8'} dev: true + /slice-ansi@3.0.0: + resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: true + + /slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: true + /smart-buffer@4.2.0: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} @@ -12444,7 +12953,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.3 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) socks: 2.8.4 transitivePeerDependencies: - supports-color @@ -12525,6 +13034,22 @@ packages: resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} dev: true + /sshpk@1.18.0: + resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + asn1: 0.2.6 + assert-plus: 1.0.0 + bcrypt-pbkdf: 1.0.2 + dashdash: 1.14.1 + ecc-jsbn: 0.1.2 + getpass: 0.1.7 + jsbn: 0.1.1 + safer-buffer: 2.1.2 + tweetnacl: 0.14.5 + dev: true + /stable-hash@0.0.5: resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} dev: true @@ -12839,6 +13364,12 @@ packages: has-flag: 4.0.0 dev: true + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -12970,6 +13501,10 @@ packages: resolution: {integrity: sha512-oB7yIimd8SuGptespDAZnNkzIz+NWaJCu2RMsbs4Wmp9zSDUM8Nhi3s2OOcqYuv3mN4hitXc8DVx+LyUmbUDiA==} dev: false + /throttleit@1.0.1: + resolution: {integrity: sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==} + dev: true + /through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} dev: true @@ -13034,6 +13569,17 @@ packages: upper-case: 1.1.3 dev: true + /tldts-core@6.1.86: + resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} + dev: true + + /tldts@6.1.86: + resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} + hasBin: true + dependencies: + tldts-core: 6.1.86 + dev: true + /tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -13041,6 +13587,11 @@ packages: os-tmpdir: 1.0.2 dev: true + /tmp@0.2.3: + resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} + engines: {node: '>=14.14'} + dev: true + /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -13052,10 +13603,22 @@ packages: engines: {node: '>=0.6'} dev: false + /tough-cookie@5.1.2: + resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} + engines: {node: '>=16'} + dependencies: + tldts: 6.1.86 + dev: true + /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} dev: false + /tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + dev: true + /trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} dev: false @@ -13146,6 +13709,12 @@ packages: typescript: 5.8.3 dev: true + /tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + dependencies: + safe-buffer: 5.2.1 + dev: true + /turbo-darwin-64@2.5.2: resolution: {integrity: sha512-2aIl0Sx230nLk+Cg2qSVxvPOBWCZpwKNuAMKoROTvWKif6VMpkWWiR9XEPoz7sHeLmCOed4GYGMjL1bqAiIS/g==} cpu: [x64] @@ -13206,6 +13775,10 @@ packages: turbo-windows-arm64: 2.5.2 dev: true + /tweetnacl@0.14.5: + resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} + dev: true + /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -13400,6 +13973,11 @@ packages: '@unrs/resolver-binding-win32-x64-msvc': 1.7.2 dev: true + /untildify@4.0.0: + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} + dev: true + /update-browserslist-db@1.1.3(browserslist@4.24.4): resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} hasBin: true @@ -13517,6 +14095,11 @@ packages: hasBin: true dev: true + /uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + dev: true + /uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true @@ -13551,6 +14134,15 @@ packages: - '@types/react-dom' dev: false + /verror@1.10.0: + resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} + engines: {'0': node >=0.6.0} + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.3.0 + dev: true + /vfile-message@4.0.2: resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} dependencies: @@ -13590,7 +14182,7 @@ packages: hasBin: true dependencies: cac: 6.7.14 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) es-module-lexer: 1.7.0 pathe: 2.0.3 vite: 6.3.3(@types/node@20.17.32) @@ -13629,7 +14221,7 @@ packages: vite: optional: true dependencies: - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) globrex: 0.1.2 tsconfck: 3.1.5(typescript@5.8.3) transitivePeerDependencies: @@ -13724,7 +14316,7 @@ packages: '@vitest/spy': 3.1.3 '@vitest/utils': 3.1.3 chai: 5.2.0 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) expect-type: 1.2.1 magic-string: 0.30.17 pathe: 2.0.3 @@ -13909,7 +14501,6 @@ packages: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: false /wrap-ansi@8.1.0: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} @@ -13972,6 +14563,13 @@ packages: hasBin: true dev: false + /yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + dev: true + /yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'}