From 7af4d5edc03cb5c86be93276fbcbd451aaf1f8a4 Mon Sep 17 00:00:00 2001 From: Sewmina Date: Wed, 25 Jun 2025 01:10:53 +0530 Subject: [PATCH] ready to be demo --- app/api/add-inventory-item/route.ts | 63 +++++ app/api/get-inventory-items/route.ts | 46 +++ app/api/get-random-reward/route.ts | 33 +++ app/api/get-receipt-id/route.ts | 41 +++ app/api/get-reward-by-id/route.ts | 46 +++ app/api/webhooks/stripe/route.ts | 57 ++++ app/boxes/page.tsx | 28 +- app/boxes/success/page.tsx | 209 +++++++++++--- app/components/Header.tsx | 4 +- app/components/RewardCard.tsx | 42 +++ app/inventory/page.tsx | 290 +++++++++++++++++++ app/lib/rewards.ts | 206 ++++++++++++++ app/lib/stripe.ts | 2 +- app/test-reward/page.tsx | 244 ++++++++++++++++ package-lock.json | 399 ++++++++++++++------------- package.json | 4 +- 16 files changed, 1455 insertions(+), 259 deletions(-) create mode 100644 app/api/add-inventory-item/route.ts create mode 100644 app/api/get-inventory-items/route.ts create mode 100644 app/api/get-random-reward/route.ts create mode 100644 app/api/get-receipt-id/route.ts create mode 100644 app/api/get-reward-by-id/route.ts create mode 100644 app/api/webhooks/stripe/route.ts create mode 100644 app/components/RewardCard.tsx create mode 100644 app/inventory/page.tsx create mode 100644 app/lib/rewards.ts create mode 100644 app/test-reward/page.tsx diff --git a/app/api/add-inventory-item/route.ts b/app/api/add-inventory-item/route.ts new file mode 100644 index 0000000..fa5185f --- /dev/null +++ b/app/api/add-inventory-item/route.ts @@ -0,0 +1,63 @@ +import { NextResponse } from 'next/server'; + +export async function POST(req: Request) { + try { + console.log('Adding inventory item...'); + + const { receiptId, userId, rewardId } = await req.json(); + console.log('Add inventory request:', { receiptId, userId, rewardId }); + + if (!receiptId || !userId || !rewardId) { + console.error('Missing required parameters:', { receiptId, userId, rewardId }); + return NextResponse.json( + { error: 'Missing required parameters' }, + { status: 400 } + ); + } + + // Call the external inventory API + const url = `https://vps.playpoolstudios.com/boxy/api/add_inventory_item.php?id=${receiptId}&user_id=${userId}&reward_id=${rewardId}`; + const response = await fetch( + url, + { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + } + ); + console.log(`${url}:${response}`); + + if (!response.ok) { + console.error('Failed to add inventory item:', response.status, response.statusText); + return NextResponse.json( + { error: 'Failed to add inventory item' }, + { status: response.status } + ); + } + + const result = await response.json(); + console.log('Inventory API response:', result); + + // Check if the item was successfully added + if (result.success === false) { + console.error('Inventory item already exists or failed to add:', result); + return NextResponse.json( + { error: 'Something went wrong - item may already exist in inventory' }, + { status: 409 } + ); + } + + return NextResponse.json({ + success: true, + message: 'Item added to inventory successfully', + data: result, + }); + } catch (error) { + console.error('Error adding inventory item:', error); + return NextResponse.json( + { error: error instanceof Error ? error.message : 'Error adding inventory item' }, + { status: 500 } + ); + } +} \ No newline at end of file diff --git a/app/api/get-inventory-items/route.ts b/app/api/get-inventory-items/route.ts new file mode 100644 index 0000000..40f03c0 --- /dev/null +++ b/app/api/get-inventory-items/route.ts @@ -0,0 +1,46 @@ +import { NextResponse } from 'next/server'; + +export async function GET(req: Request) { + try { + const { searchParams } = new URL(req.url); + const userId = searchParams.get('userId'); + + if (!userId) { + return NextResponse.json( + { error: 'User ID is required' }, + { status: 400 } + ); + } + + console.log('Fetching inventory items for user:', userId); + + const response = await fetch( + `https://vps.playpoolstudios.com/boxy/api/get_inventory_items.php?user_id=${userId}`, + { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + } + ); + + if (!response.ok) { + console.error('Failed to fetch inventory items:', response.status, response.statusText); + return NextResponse.json( + { error: 'Failed to fetch inventory items' }, + { status: response.status } + ); + } + + const inventoryItems = await response.json(); + console.log('Inventory items fetched successfully:', inventoryItems); + + return NextResponse.json(inventoryItems); + } catch (error) { + console.error('Error fetching inventory items:', error); + return NextResponse.json( + { error: error instanceof Error ? error.message : 'Error fetching inventory items' }, + { status: 500 } + ); + } +} \ No newline at end of file diff --git a/app/api/get-random-reward/route.ts b/app/api/get-random-reward/route.ts new file mode 100644 index 0000000..d3e159d --- /dev/null +++ b/app/api/get-random-reward/route.ts @@ -0,0 +1,33 @@ +import { NextResponse } from 'next/server'; + +export async function GET() { + try { + console.log('Fetching random reward from external API...'); + + const response = await fetch('https://vps.playpoolstudios.com/boxy/api/get_random_reward.php', { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (!response.ok) { + console.error('Failed to fetch random reward:', response.status, response.statusText); + return NextResponse.json( + { error: 'Failed to fetch random reward' }, + { status: response.status } + ); + } + + const reward = await response.json(); + console.log('Random reward fetched successfully:', reward); + + return NextResponse.json(reward); + } catch (error) { + console.error('Error fetching random reward:', error); + return NextResponse.json( + { error: error instanceof Error ? error.message : 'Error fetching random reward' }, + { status: 500 } + ); + } +} \ No newline at end of file diff --git a/app/api/get-receipt-id/route.ts b/app/api/get-receipt-id/route.ts new file mode 100644 index 0000000..422db45 --- /dev/null +++ b/app/api/get-receipt-id/route.ts @@ -0,0 +1,41 @@ +import { NextResponse } from 'next/server'; +import { getReceiptId } from '../webhooks/stripe/route'; + +export async function GET(req: Request) { + try { + const { searchParams } = new URL(req.url); + const sessionId = searchParams.get('sessionId'); + + if (!sessionId) { + return NextResponse.json( + { error: 'Session ID is required' }, + { status: 400 } + ); + } + + console.log('Getting receipt ID for session:', sessionId); + + const receiptId = getReceiptId(sessionId); + + if (!receiptId) { + console.log('No receipt ID found for session:', sessionId); + return NextResponse.json( + { error: 'Receipt ID not found for this session' }, + { status: 404 } + ); + } + + console.log('Found receipt ID:', receiptId); + + return NextResponse.json({ + sessionId, + receiptId, + }); + } catch (error) { + console.error('Error getting receipt ID:', error); + return NextResponse.json( + { error: error instanceof Error ? error.message : 'Error getting receipt ID' }, + { status: 500 } + ); + } +} \ No newline at end of file diff --git a/app/api/get-reward-by-id/route.ts b/app/api/get-reward-by-id/route.ts new file mode 100644 index 0000000..a7e0e35 --- /dev/null +++ b/app/api/get-reward-by-id/route.ts @@ -0,0 +1,46 @@ +import { NextResponse } from 'next/server'; + +export async function GET(req: Request) { + try { + const { searchParams } = new URL(req.url); + const rewardId = searchParams.get('id'); + + if (!rewardId) { + return NextResponse.json( + { error: 'Reward ID is required' }, + { status: 400 } + ); + } + + console.log('Fetching reward by ID:', rewardId); + + const response = await fetch( + `https://vps.playpoolstudios.com/boxy/api/get_reward_by_id.php?id=${rewardId}`, + { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + } + ); + + if (!response.ok) { + console.error('Failed to fetch reward by ID:', response.status, response.statusText); + return NextResponse.json( + { error: 'Failed to fetch reward' }, + { status: response.status } + ); + } + + const reward = await response.json(); + console.log('Reward fetched successfully:', reward); + + return NextResponse.json(reward); + } catch (error) { + console.error('Error fetching reward by ID:', error); + return NextResponse.json( + { error: error instanceof Error ? error.message : 'Error fetching reward' }, + { status: 500 } + ); + } +} \ No newline at end of file diff --git a/app/api/webhooks/stripe/route.ts b/app/api/webhooks/stripe/route.ts new file mode 100644 index 0000000..934cdef --- /dev/null +++ b/app/api/webhooks/stripe/route.ts @@ -0,0 +1,57 @@ +import { NextResponse } from 'next/server'; +import { headers } from 'next/headers'; + +// In-memory storage for demo purposes - in production, use a database +const paymentReceipts = new Map(); + +export async function POST(req: Request) { + try { + const body = await req.text(); + const headersList = await headers(); + const signature = headersList.get('stripe-signature'); + + if (!signature) { + console.error('No Stripe signature found'); + return NextResponse.json({ error: 'No signature' }, { status: 400 }); + } + + // For now, we'll process the webhook without signature verification + // In production, you should verify the signature using Stripe's webhook secret + const event = JSON.parse(body); + console.log('Stripe webhook event:', event.type); + + if (event.type === 'checkout.session.completed') { + const session = event.data.object; + const sessionId = session.id; + const paymentIntentId = session.payment_intent; + const boxId = session.metadata?.boxId; + + console.log('Payment completed:', { + sessionId, + paymentIntentId, + boxId, + amount: session.amount_total, + currency: session.currency, + }); + + // Store the payment intent ID as the receipt ID + if (paymentIntentId) { + paymentReceipts.set(sessionId, paymentIntentId); + console.log(`Stored receipt ID ${paymentIntentId} for session ${sessionId}`); + } + } + + return NextResponse.json({ received: true }); + } catch (error) { + console.error('Webhook error:', error); + return NextResponse.json( + { error: 'Webhook handler failed' }, + { status: 400 } + ); + } +} + +// Helper function to get receipt ID for a session +export function getReceiptId(sessionId: string): string | null { + return paymentReceipts.get(sessionId) || null; +} \ No newline at end of file diff --git a/app/boxes/page.tsx b/app/boxes/page.tsx index 72dfa52..0b4ae18 100644 --- a/app/boxes/page.tsx +++ b/app/boxes/page.tsx @@ -12,8 +12,6 @@ const MOCK_BOXES = [ tier: 'Small', price: 100, color: 'from-blue-500 to-blue-600', - remaining: 2500, - total: 3000, image: '/box-small.png', description: 'Perfect for beginners. Contains common to rare items.', }, @@ -22,8 +20,6 @@ const MOCK_BOXES = [ tier: 'Medium', price: 1000, color: 'from-purple-500 to-purple-600', - remaining: 1500, - total: 2000, image: '/box-medium.png', description: 'For serious collectors. Contains rare to epic items.', }, @@ -32,14 +28,12 @@ const MOCK_BOXES = [ tier: 'Big', price: 10000, color: 'from-pink-500 to-pink-600', - remaining: 500, - total: 1000, image: '/box-big.png', description: 'Premium boxes with epic to legendary items.', }, ]; -type SortOption = 'price-asc' | 'price-desc' | 'remaining-asc' | 'remaining-desc'; +type SortOption = 'price-asc' | 'price-desc'; type FilterTier = 'all' | 'small' | 'medium' | 'big'; export default function BoxesPage() { @@ -57,10 +51,6 @@ export default function BoxesPage() { return a.price - b.price; case 'price-desc': return b.price - a.price; - case 'remaining-asc': - return a.remaining - b.remaining; - case 'remaining-desc': - return b.remaining - a.remaining; default: return 0; } @@ -147,8 +137,6 @@ export default function BoxesPage() { > - - @@ -173,20 +161,6 @@ export default function BoxesPage() {

{box.description}

- {/* Progress Bar */} -
-
- Remaining - {box.remaining}/{box.total} -
-
-
-
-
- {/* Price and Action */}
diff --git a/app/boxes/success/page.tsx b/app/boxes/success/page.tsx index d6f1fba..208afeb 100644 --- a/app/boxes/success/page.tsx +++ b/app/boxes/success/page.tsx @@ -4,37 +4,127 @@ import { useState, useEffect } from 'react'; import { useSearchParams } from 'next/navigation'; import { useAuth } from '../../context/AuthContext'; import Header from '../../components/Header'; - -// Mock prize data - replace with actual data from your backend -const MOCK_PRIZES = [ - { name: 'Rare NFT', rarity: 'rare', value: 500 }, - { name: 'Epic Collectible', rarity: 'epic', value: 1000 }, - { name: 'Legendary Item', rarity: 'legendary', value: 5000 }, - { name: 'Common Token', rarity: 'common', value: 50 }, -]; +import RewardCard from '../../components/RewardCard'; +import { fetchRandomReward, getReceiptId, addInventoryItem, type Reward } from '../../lib/rewards'; export default function SuccessPage() { const { user } = useAuth(); const searchParams = useSearchParams(); const [isOpening, setIsOpening] = useState(true); - const [prize, setPrize] = useState(null); - const [showPrize, setShowPrize] = useState(false); + const [reward, setReward] = useState(null); + const [showReward, setShowReward] = useState(false); + const [error, setError] = useState(null); + const [inventoryStatus, setInventoryStatus] = useState<'pending' | 'success' | 'error'>('pending'); + const [receiptId, setReceiptId] = useState(null); const boxId = searchParams.get('box_id'); const sessionId = searchParams.get('session_id'); useEffect(() => { // Simulate box opening animation - const timer = setTimeout(() => { + const timer = setTimeout(async () => { setIsOpening(false); - // Randomly select a prize (replace with actual logic) - const randomPrize = MOCK_PRIZES[Math.floor(Math.random() * MOCK_PRIZES.length)]; - setPrize(randomPrize); - setShowPrize(true); + + try { + // Fetch real random reward from API + const randomReward = await fetchRandomReward(); + if (randomReward) { + setReward(randomReward); + setShowReward(true); + + // Get receipt ID from Stripe if session ID is available + if (sessionId) { + try { + console.log('Getting receipt ID for session:', sessionId); + const stripeReceiptId = await getReceiptId(sessionId); + + if (stripeReceiptId) { + setReceiptId(stripeReceiptId); + console.log('Got receipt ID from Stripe:', stripeReceiptId); + + // Add reward to inventory with actual receipt ID + if (user?.uid) { + try { + console.log('Adding reward to inventory:', { + receiptId: stripeReceiptId, + userId: user.uid, + rewardId: randomReward.id + }); + + const success = await addInventoryItem(stripeReceiptId, user.uid, randomReward.id); + if (success) { + setInventoryStatus('success'); + console.log('Reward added to inventory successfully'); + } else { + setInventoryStatus('error'); + setError('Something went wrong'); + setShowReward(false); + setReward(null); + } + } catch (inventoryError) { + console.error('Error adding to inventory:', inventoryError); + setInventoryStatus('error'); + setError('Something went wrong'); + setShowReward(false); + setReward(null); + } + } + } else { + console.log('No receipt ID found for session, using session ID as fallback'); + // Fallback to using session ID if no receipt ID is found + if (user?.uid) { + try { + const success = await addInventoryItem(sessionId, user.uid, randomReward.id); + if (success) { + setInventoryStatus('success'); + } else { + setInventoryStatus('error'); + setError('Something went wrong'); + setShowReward(false); + setReward(null); + } + } catch (inventoryError) { + console.error('Error adding to inventory with fallback:', inventoryError); + setInventoryStatus('error'); + setError('Something went wrong'); + setShowReward(false); + setReward(null); + } + } + } + } catch (receiptError) { + console.error('Error getting receipt ID:', receiptError); + // Continue with fallback to session ID + if (user?.uid) { + try { + const success = await addInventoryItem(sessionId!, user.uid, randomReward.id); + if (success) { + setInventoryStatus('success'); + } else { + setInventoryStatus('error'); + setError('Something went wrong'); + setShowReward(false); + setReward(null); + } + } catch (inventoryError) { + console.error('Error adding to inventory with fallback:', inventoryError); + setInventoryStatus('error'); + setError('Something went wrong'); + setShowReward(false); + setReward(null); + } + } + } + } + } + } catch (err) { + console.error('Error fetching random reward:', err); + setError(err instanceof Error ? err.message : 'Failed to fetch reward'); + } }, 3000); return () => clearTimeout(timer); - }, []); + }, [sessionId, user?.uid]); if (!user) { return ( @@ -50,6 +140,38 @@ export default function SuccessPage() { ); } + // Show only error message if there's an error + if (error) { + return ( + <> +
+
+
+
+

Something went wrong

+

+ {error} +

+
+ + +
+
+
+ + ); + } + return ( <>
@@ -74,8 +196,8 @@ export default function SuccessPage() {
)} - {/* Prize Reveal */} - {showPrize && prize && ( + {/* Reward Reveal */} + {showReward && reward && (
@@ -84,24 +206,17 @@ export default function SuccessPage() { You found something amazing!

- {/* Prize Card */} -
-
🎯
-

{prize.name}

-
- - {prize.rarity.toUpperCase()} - -
-

- Estimated Value: ${prize.value} -

+ {/* Reward Card */} +
+
+ + {/* Inventory Status */} + {inventoryStatus === 'success' && ( +
+

✅ Added to your inventory!

+
+ )}
{/* Action Buttons */} @@ -130,6 +245,12 @@ export default function SuccessPage() { Session ID: {sessionId}
+ {receiptId && ( +
+ Receipt ID: + {receiptId} +
+ )}
Box ID: {boxId} @@ -138,6 +259,24 @@ export default function SuccessPage() { User: {user.email}
+ {reward && ( +
+ Reward ID: + {reward.id} +
+ )} +
+ Inventory Status: + + {inventoryStatus === 'success' ? 'Added' : + inventoryStatus === 'error' ? 'Failed' : + 'Pending'} + +
diff --git a/app/components/Header.tsx b/app/components/Header.tsx index 6ed259d..505fbcc 100644 --- a/app/components/Header.tsx +++ b/app/components/Header.tsx @@ -58,7 +58,7 @@ export default function Header() { {/* Profile Dropdown */} {isProfileMenuOpen && (
- setIsProfileMenuOpen(false)} @@ -71,7 +71,7 @@ export default function Header() { onClick={() => setIsProfileMenuOpen(false)} > Settings - + */}
+ ); +} \ No newline at end of file diff --git a/app/inventory/page.tsx b/app/inventory/page.tsx new file mode 100644 index 0000000..45d1695 --- /dev/null +++ b/app/inventory/page.tsx @@ -0,0 +1,290 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { useAuth } from '../context/AuthContext'; +import Header from '../components/Header'; +import RewardCard from '../components/RewardCard'; +import { + fetchInventoryItems, + getRewardById, + type InventoryItem, + type Reward, + formatDate +} from '../lib/rewards'; + +interface InventoryItemWithReward extends InventoryItem { + reward: Reward | null; +} + +export default function InventoryPage() { + const { user } = useAuth(); + const [inventoryItems, setInventoryItems] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + const [selectedItem, setSelectedItem] = useState(null); + const [showRedeemModal, setShowRedeemModal] = useState(false); + const [showTradeModal, setShowTradeModal] = useState(false); + + useEffect(() => { + const loadInventory = async () => { + if (!user?.uid) return; + + setIsLoading(true); + setError(null); + + try { + // Fetch inventory items + const items = await fetchInventoryItems(user.uid); + + // Fetch reward details for each item + const itemsWithRewards = await Promise.all( + items.map(async (item) => { + try { + const reward = await getRewardById(item.reward_id); + return { ...item, reward }; + } catch (error) { + console.error(`Error fetching reward ${item.reward_id}:`, error); + return { ...item, reward: null }; + } + }) + ); + + setInventoryItems(itemsWithRewards); + } catch (err) { + console.error('Error loading inventory:', err); + setError(err instanceof Error ? err.message : 'Failed to load inventory'); + } finally { + setIsLoading(false); + } + }; + + loadInventory(); + }, [user?.uid]); + + const handleRedeem = (item: InventoryItemWithReward) => { + setSelectedItem(item); + setShowRedeemModal(true); + }; + + const handleTrade = (item: InventoryItemWithReward) => { + setSelectedItem(item); + setShowTradeModal(true); + }; + + const handleRedeemConfirm = () => { + // TODO: Implement redeem functionality + console.log('Redeeming item:', selectedItem); + alert('Redeem functionality coming soon!'); + setShowRedeemModal(false); + setSelectedItem(null); + }; + + const handleTradeConfirm = () => { + // TODO: Implement trade functionality + console.log('Trading item:', selectedItem); + alert('Trade functionality coming soon!'); + setShowTradeModal(false); + setSelectedItem(null); + }; + + if (!user) { + return ( + <> +
+
+
+

Access Denied

+

Please sign in to view your inventory.

+
+
+ + ); + } + + return ( + <> +
+
+
+ {/* Page Header */} +
+

My Inventory

+

+ Manage your collected rewards and items +

+
+ + {/* Loading State */} + {isLoading && ( +
+
+

Loading your inventory...

+
+ )} + + {/* Error State */} + {error && ( +
+
+

Oops!

+

+ {error} +

+ +
+ )} + + {/* Inventory Grid */} + {!isLoading && !error && ( + <> + {inventoryItems.length === 0 ? ( +
+
📦
+

Empty Inventory

+

+ You haven't collected any rewards yet. +

+ +
+ ) : ( +
+ {inventoryItems.map((item) => ( +
+ {/* Reward Card */} + {item.reward ? ( + + ) : ( +
+
+

Reward details unavailable

+
+ )} + + {/* Item Details */} +
+
+ Receipt ID: + + {item.id} + +
+
+ Unlocked: + {formatDate(item.unlocked_on)} +
+
+ + {/* Action Buttons */} +
+ + +
+
+ ))} +
+ )} + + )} +
+
+ + {/* Redeem Modal */} + {showRedeemModal && selectedItem && ( +
+
+
+
🎁
+

Redeem Item

+

+ Are you sure you want to redeem this item? +

+ + {selectedItem.reward && ( +
+ +
+ )} + +
+ + +
+
+
+
+ )} + + {/* Trade Modal */} + {showTradeModal && selectedItem && ( +
+
+
+
🔄
+

Trade Item

+

+ Are you sure you want to trade this item? +

+ + {selectedItem.reward && ( +
+ +
+ )} + +
+ + +
+
+
+
+ )} + + ); +} \ No newline at end of file diff --git a/app/lib/rewards.ts b/app/lib/rewards.ts new file mode 100644 index 0000000..427d4e5 --- /dev/null +++ b/app/lib/rewards.ts @@ -0,0 +1,206 @@ +// Types for rewards +export interface Reward { + id: string; + name: string; + price: string; + image: string; +} + +// Types for inventory items +export interface InventoryItem { + id: string; + user_id: string; + reward_id: string; + unlocked_on: string; +} + +// Function to fetch a random reward from the API +export async function fetchRandomReward(): Promise { + try { + console.log('Fetching random reward from API...'); + + const response = await fetch('/api/get-random-reward', { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const reward = await response.json(); + console.log('Random reward fetched successfully:', reward); + + // Validate the reward data + if (!reward.id || !reward.name || !reward.price) { + throw new Error('Invalid reward data received'); + } + + return reward; + } catch (error) { + console.error('Error fetching random reward:', error); + throw error; + } +} + +// Function to get receipt ID from Stripe session +export async function getReceiptId(sessionId: string): Promise { + try { + console.log('Getting receipt ID for session:', sessionId); + + const response = await fetch(`/api/get-receipt-id?sessionId=${sessionId}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (!response.ok) { + if (response.status === 404) { + console.log('Receipt ID not found for session:', sessionId); + return null; + } + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + console.log('Receipt ID retrieved successfully:', data.receiptId); + + return data.receiptId; + } catch (error) { + console.error('Error getting receipt ID:', error); + throw error; + } +} + +// Function to add an item to inventory +export async function addInventoryItem(receiptId: string, userId: string, rewardId: string): Promise { + try { + console.log('Adding inventory item:', { receiptId, userId, rewardId }); + + const response = await fetch('/api/add-inventory-item', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + receiptId, + userId, + rewardId, + }), + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.error || `HTTP error! status: ${response.status}`); + } + + const result = await response.json(); + console.log('Inventory item added successfully:', result); + + return result.success === true; + } catch (error) { + console.error('Error adding inventory item:', error); + throw error; + } +} + +// Function to fetch inventory items for a user +export async function fetchInventoryItems(userId: string): Promise { + try { + console.log('Fetching inventory items for user:', userId); + + const response = await fetch(`/api/get-inventory-items?userId=${userId}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const inventoryItems = await response.json(); + console.log('Inventory items fetched successfully:', inventoryItems); + + return inventoryItems; + } catch (error) { + console.error('Error fetching inventory items:', error); + throw error; + } +} + +// Function to get reward details by ID +export async function getRewardById(rewardId: string): Promise { + try { + console.log('Getting reward details for ID:', rewardId); + + const response = await fetch(`/api/get-reward-by-id?id=${rewardId}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (!response.ok) { + if (response.status === 404) { + console.log('Reward not found for ID:', rewardId); + return null; + } + throw new Error(`HTTP error! status: ${response.status}`); + } + + const reward = await response.json(); + console.log('Reward details fetched successfully:', reward); + + // Validate the reward data + if (!reward.id || !reward.name || !reward.price) { + throw new Error('Invalid reward data received'); + } + + return reward; + } catch (error) { + console.error('Error getting reward by ID:', error); + throw error; + } +} + +// Function to clean image URL (remove escaped backslashes) +export function cleanImageUrl(url: string): string { + return url.replace(/\\/g, ''); +} + +// Function to get rarity color based on price +export function getRarityColor(price: string): string { + const numPrice = parseFloat(price); + + if (numPrice >= 1000) return 'bg-yellow-500/20 text-yellow-300'; // Legendary + if (numPrice >= 500) return 'bg-purple-500/20 text-purple-300'; // Epic + if (numPrice >= 100) return 'bg-blue-500/20 text-blue-300'; // Rare + return 'bg-gray-500/20 text-gray-300'; // Common +} + +// Function to get rarity label based on price +export function getRarityLabel(price: string): string { + const numPrice = parseFloat(price); + + if (numPrice >= 1000) return 'LEGENDARY'; + if (numPrice >= 500) return 'EPIC'; + if (numPrice >= 100) return 'RARE'; + return 'COMMON'; +} + +// Function to format date +export function formatDate(dateString: string): string { + const date = new Date(dateString); + return date.toLocaleDateString('en-US', { + year: 'numeric', + month: 'short', + day: 'numeric', + hour: '2-digit', + minute: '2-digit', + }); +} \ No newline at end of file diff --git a/app/lib/stripe.ts b/app/lib/stripe.ts index 257db3e..e9745b6 100644 --- a/app/lib/stripe.ts +++ b/app/lib/stripe.ts @@ -83,7 +83,7 @@ export async function createCheckoutSession( }, ], mode: 'payment', - success_url: `${process.env.NEXT_PUBLIC_BASE_URL}/boxes/success?box_id=${boxId}`, + success_url: `${process.env.NEXT_PUBLIC_BASE_URL}/boxes/success?box_id=${boxId}&session_id={CHECKOUT_SESSION_ID}`, cancel_url: `${process.env.NEXT_PUBLIC_BASE_URL}/boxes?canceled=true`, metadata: { boxId, diff --git a/app/test-reward/page.tsx b/app/test-reward/page.tsx new file mode 100644 index 0000000..5bd8f54 --- /dev/null +++ b/app/test-reward/page.tsx @@ -0,0 +1,244 @@ +'use client'; + +import { useState } from 'react'; +import Header from '../components/Header'; +import RewardCard from '../components/RewardCard'; +import { fetchRandomReward, getReceiptId, addInventoryItem, type Reward } from '../lib/rewards'; +import { useAuth } from '../context/AuthContext'; + +export default function TestRewardPage() { + const { user } = useAuth(); + const [reward, setReward] = useState(null); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + const [inventoryStatus, setInventoryStatus] = useState<'idle' | 'pending' | 'success' | 'error'>('idle'); + const [receiptId, setReceiptId] = useState('test-receipt-123'); + const [sessionId, setSessionId] = useState('cs_test_1234567890'); + const [stripeReceiptId, setStripeReceiptId] = useState(null); + + const handleGetRandomReward = async () => { + setIsLoading(true); + setError(null); + setReward(null); + setInventoryStatus('idle'); + setStripeReceiptId(null); + + try { + const randomReward = await fetchRandomReward(); + if (randomReward) { + setReward(randomReward); + } + } catch (err) { + console.error('Error fetching random reward:', err); + setError(err instanceof Error ? err.message : 'Failed to fetch reward'); + } finally { + setIsLoading(false); + } + }; + + const handleGetReceiptId = async () => { + if (!sessionId) { + setError('Please enter a session ID'); + return; + } + + try { + const receipt = await getReceiptId(sessionId); + setStripeReceiptId(receipt); + if (receipt) { + console.log('Got receipt ID from Stripe:', receipt); + } else { + console.log('No receipt ID found for session:', sessionId); + } + } catch (err) { + console.error('Error getting receipt ID:', err); + setError(err instanceof Error ? err.message : 'Failed to get receipt ID'); + } + }; + + const handleAddToInventory = async () => { + if (!reward || !user?.uid) { + setError('No reward or user available'); + return; + } + + setInventoryStatus('pending'); + setError(null); + + // Use Stripe receipt ID if available, otherwise use manual receipt ID + const finalReceiptId = stripeReceiptId || receiptId; + + try { + const success = await addInventoryItem(finalReceiptId, user.uid, reward.id); + if (success) { + setInventoryStatus('success'); + } else { + setInventoryStatus('error'); + setError('Failed to add to inventory'); + } + } catch (err) { + console.error('Error adding to inventory:', err); + setInventoryStatus('error'); + setError(err instanceof Error ? err.message : 'Failed to add to inventory'); + } + }; + + return ( + <> +
+
+
+ {/* Page Header */} +
+

Test Random Reward

+

+ Test the random reward API functionality with Stripe receipt IDs +

+
+ + {/* Input Fields */} +
+
+ + setSessionId(e.target.value)} + className="px-4 py-2 rounded-lg bg-foreground/5 border border-foreground/10 text-sm focus:outline-none focus:ring-2 focus:ring-purple-500" + placeholder="Enter Stripe session ID" + /> +
+ +
+ + setReceiptId(e.target.value)} + className="px-4 py-2 rounded-lg bg-foreground/5 border border-foreground/10 text-sm focus:outline-none focus:ring-2 focus:ring-purple-500" + placeholder="Enter manual receipt ID" + /> +
+
+ + {/* Test Buttons */} +
+ + + + + {reward && user && ( + + )} +
+ + {/* Receipt ID Display */} + {stripeReceiptId && ( +
+
+

+ ✅ Stripe Receipt ID: {stripeReceiptId} +

+
+
+ )} + + {/* Error Message */} + {error && ( +
+
+

{error}

+
+
+ )} + + {/* Inventory Status */} + {inventoryStatus !== 'idle' && ( +
+
+

+ {inventoryStatus === 'success' ? '✅ Added to inventory successfully!' : + inventoryStatus === 'error' ? '❌ Failed to add to inventory' : + '⏳ Adding to inventory...'} +

+
+
+ )} + + {/* Reward Display */} + {reward && ( +
+

Random Reward

+
+ +
+
+ )} + + {/* API Info */} +
+

API Information

+
+
+ Random Reward Endpoint: + /api/get-random-reward +
+
+ Get Receipt ID Endpoint: + /api/get-receipt-id +
+
+ Add Inventory Endpoint: + /api/add-inventory-item +
+
+ Stripe Webhook: + /api/webhooks/stripe +
+
+ External Reward API: + vps.playpoolstudios.com/boxy/api/get_random_reward.php +
+
+ External Inventory API: + vps.playpoolstudios.com/boxy/api/add_inventory_item.php +
+
+
+
+
+ + ); +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7be24f2..eadea53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1657,22 +1657,6 @@ "node": ">= 10" } }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.3.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.3.tgz", - "integrity": "sha512-4QZG6F8enl9/S2+yIiOiju0iCTFd93d8VC1q9LZS4p/Xuk81W2QDjCFeoogmrWWkAD59z8ZxepBQap2dKS5ruw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1810,9 +1794,9 @@ "license": "MIT" }, "node_modules/@stripe/stripe-js": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-7.3.1.tgz", - "integrity": "sha512-pTzb864TQWDRQBPLgSPFRoyjSDUqpCkbEgTzpsjiTjGz1Z5SxZNXJek28w1s6Dyry4CyW4/Izj5jHE/J9hCJYQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-7.4.0.tgz", + "integrity": "sha512-lQHQPfXPTBeh0XFjq6PqSBAyR7umwcJbvJhXV77uGCUDD6ymXJU/f2164ydLMLCCceNuPlbV9b+1smx98efwWQ==", "license": "MIT", "engines": { "node": ">=12.16" @@ -2078,7 +2062,7 @@ "node": ">= 10" } }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "node_modules/@tailwindcss/oxide/node_modules/@tailwindcss/oxide-win32-x64-msvc": { "version": "4.1.10", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.10.tgz", "integrity": "sha512-sGiJTjcBSfGq2DVRtaSljq5ZgZS2SDHSIfhOylkBvHVjwOsodBhnb3HdmiKkVuUGKD0I7G63abMOVaskj1KpOA==", @@ -2319,17 +2303,17 @@ "optional": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.34.0.tgz", - "integrity": "sha512-QXwAlHlbcAwNlEEMKQS2RCgJsgXrTJdjXT08xEgbPFa2yYQgVjBymxP5DrfrE7X7iodSzd9qBUHUycdyVJTW1w==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.35.0.tgz", + "integrity": "sha512-ijItUYaiWuce0N1SoSMrEd0b6b6lYkYt99pqCPfybd+HKVXtEvYhICfLdwp42MhiI5mp0oq7PKEL+g1cNiz/Eg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.34.0", - "@typescript-eslint/type-utils": "8.34.0", - "@typescript-eslint/utils": "8.34.0", - "@typescript-eslint/visitor-keys": "8.34.0", + "@typescript-eslint/scope-manager": "8.35.0", + "@typescript-eslint/type-utils": "8.35.0", + "@typescript-eslint/utils": "8.35.0", + "@typescript-eslint/visitor-keys": "8.35.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -2343,7 +2327,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.34.0", + "@typescript-eslint/parser": "^8.35.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } @@ -2359,16 +2343,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.34.0.tgz", - "integrity": "sha512-vxXJV1hVFx3IXz/oy2sICsJukaBrtDEQSBiV48/YIV5KWjX1dO+bcIr/kCPrW6weKXvsaGKFNlwH0v2eYdRRbA==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.35.0.tgz", + "integrity": "sha512-6sMvZePQrnZH2/cJkwRpkT7DxoAWh+g6+GFRK6bV3YQo7ogi3SX5rgF6099r5Q53Ma5qeT7LGmOmuIutF4t3lA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.34.0", - "@typescript-eslint/types": "8.34.0", - "@typescript-eslint/typescript-estree": "8.34.0", - "@typescript-eslint/visitor-keys": "8.34.0", + "@typescript-eslint/scope-manager": "8.35.0", + "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/typescript-estree": "8.35.0", + "@typescript-eslint/visitor-keys": "8.35.0", "debug": "^4.3.4" }, "engines": { @@ -2384,14 +2368,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.34.0.tgz", - "integrity": "sha512-iEgDALRf970/B2YExmtPMPF54NenZUf4xpL3wsCRx/lgjz6ul/l13R81ozP/ZNuXfnLCS+oPmG7JIxfdNYKELw==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.35.0.tgz", + "integrity": "sha512-41xatqRwWZuhUMF/aZm2fcUsOFKNcG28xqRSS6ZVr9BVJtGExosLAm5A1OxTjRMagx8nJqva+P5zNIGt8RIgbQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.34.0", - "@typescript-eslint/types": "^8.34.0", + "@typescript-eslint/tsconfig-utils": "^8.35.0", + "@typescript-eslint/types": "^8.35.0", "debug": "^4.3.4" }, "engines": { @@ -2406,14 +2390,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.34.0.tgz", - "integrity": "sha512-9Ac0X8WiLykl0aj1oYQNcLZjHgBojT6cW68yAgZ19letYu+Hxd0rE0veI1XznSSst1X5lwnxhPbVdwjDRIomRw==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.35.0.tgz", + "integrity": "sha512-+AgL5+mcoLxl1vGjwNfiWq5fLDZM1TmTPYs2UkyHfFhgERxBbqHlNjRzhThJqz+ktBqTChRYY6zwbMwy0591AA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.34.0", - "@typescript-eslint/visitor-keys": "8.34.0" + "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/visitor-keys": "8.35.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2424,9 +2408,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.34.0.tgz", - "integrity": "sha512-+W9VYHKFIzA5cBeooqQxqNriAP0QeQ7xTiDuIOr71hzgffm3EL2hxwWBIIj4GuofIbKxGNarpKqIq6Q6YrShOA==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.35.0.tgz", + "integrity": "sha512-04k/7247kZzFraweuEirmvUj+W3bJLI9fX6fbo1Qm2YykuBvEhRTPl8tcxlYO8kZZW+HIXfkZNoasVb8EV4jpA==", "dev": true, "license": "MIT", "engines": { @@ -2441,14 +2425,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.34.0.tgz", - "integrity": "sha512-n7zSmOcUVhcRYC75W2pnPpbO1iwhJY3NLoHEtbJwJSNlVAZuwqu05zY3f3s2SDWWDSo9FdN5szqc73DCtDObAg==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.35.0.tgz", + "integrity": "sha512-ceNNttjfmSEoM9PW87bWLDEIaLAyR+E6BoYJQ5PfaDau37UGca9Nyq3lBk8Bw2ad0AKvYabz6wxc7DMTO2jnNA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.34.0", - "@typescript-eslint/utils": "8.34.0", + "@typescript-eslint/typescript-estree": "8.35.0", + "@typescript-eslint/utils": "8.35.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -2465,9 +2449,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.34.0.tgz", - "integrity": "sha512-9V24k/paICYPniajHfJ4cuAWETnt7Ssy+R0Rbcqo5sSFr3QEZ/8TSoUi9XeXVBGXCaLtwTOKSLGcInCAvyZeMA==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.35.0.tgz", + "integrity": "sha512-0mYH3emanku0vHw2aRLNGqe7EXh9WHEhi7kZzscrMDf6IIRUQ5Jk4wp1QrledE/36KtdZrVfKnE32eZCf/vaVQ==", "dev": true, "license": "MIT", "engines": { @@ -2479,16 +2463,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.34.0.tgz", - "integrity": "sha512-rOi4KZxI7E0+BMqG7emPSK1bB4RICCpF7QD3KCLXn9ZvWoESsOMlHyZPAHyG04ujVplPaHbmEvs34m+wjgtVtg==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.35.0.tgz", + "integrity": "sha512-F+BhnaBemgu1Qf8oHrxyw14wq6vbL8xwWKKMwTMwYIRmFFY/1n/9T/jpbobZL8vp7QyEUcC6xGrnAO4ua8Kp7w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.34.0", - "@typescript-eslint/tsconfig-utils": "8.34.0", - "@typescript-eslint/types": "8.34.0", - "@typescript-eslint/visitor-keys": "8.34.0", + "@typescript-eslint/project-service": "8.35.0", + "@typescript-eslint/tsconfig-utils": "8.35.0", + "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/visitor-keys": "8.35.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2564,16 +2548,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.34.0.tgz", - "integrity": "sha512-8L4tWatGchV9A1cKbjaavS6mwYwp39jql8xUmIIKJdm+qiaeHy5KMKlBrf30akXAWBzn2SqKsNOtSENWUwg7XQ==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.35.0.tgz", + "integrity": "sha512-nqoMu7WWM7ki5tPgLVsmPM8CkqtoPUG6xXGeefM5t4x3XumOEKMoUZPdi+7F+/EotukN4R9OWdmDxN80fqoZeg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.34.0", - "@typescript-eslint/types": "8.34.0", - "@typescript-eslint/typescript-estree": "8.34.0" + "@typescript-eslint/scope-manager": "8.35.0", + "@typescript-eslint/types": "8.35.0", + "@typescript-eslint/typescript-estree": "8.35.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2588,14 +2572,14 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.34.0.tgz", - "integrity": "sha512-qHV7pW7E85A0x6qyrFn+O+q1k1p3tQCsqIZ1KZ5ESLXY57aTvUd3/a4rdPTeXisvhXn2VQG0VSKUqs8KHF2zcA==", + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.35.0.tgz", + "integrity": "sha512-zTh2+1Y8ZpmeQaQVIc/ZZxsx8UzgKJyNg1PTvjzC7WMhPSVS8bfDX34k1SrwOf016qd5RU3az2UxUNue3IfQ5g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.34.0", - "eslint-visitor-keys": "^4.2.0" + "@typescript-eslint/types": "8.35.0", + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2606,9 +2590,9 @@ } }, "node_modules/@unrs/resolver-binding-android-arm-eabi": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.9.0.tgz", - "integrity": "sha512-h1T2c2Di49ekF2TE8ZCoJkb+jwETKUIPDJ/nO3tJBKlLFPu+fyd93f0rGP/BvArKx2k2HlRM4kqkNarj3dvZlg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.9.2.tgz", + "integrity": "sha512-tS+lqTU3N0kkthU+rYp0spAYq15DU8ld9kXkaKg9sbQqJNF+WPMuNHZQGCgdxrUOEO0j22RKMwRVhF1HTl+X8A==", "cpu": [ "arm" ], @@ -2620,9 +2604,9 @@ ] }, "node_modules/@unrs/resolver-binding-android-arm64": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.9.0.tgz", - "integrity": "sha512-sG1NHtgXtX8owEkJ11yn34vt0Xqzi3k9TJ8zppDmyG8GZV4kVWw44FHwKwHeEFl07uKPeC4ZoyuQaGh5ruJYPA==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.9.2.tgz", + "integrity": "sha512-MffGiZULa/KmkNjHeuuflLVqfhqLv1vZLm8lWIyeADvlElJ/GLSOkoUX+5jf4/EGtfwrNFcEaB8BRas03KT0/Q==", "cpu": [ "arm64" ], @@ -2634,9 +2618,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.9.0.tgz", - "integrity": "sha512-nJ9z47kfFnCxN1z/oYZS7HSNsFh43y2asePzTEZpEvK7kGyuShSl3RRXnm/1QaqFL+iP+BjMwuB+DYUymOkA5A==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.9.2.tgz", + "integrity": "sha512-dzJYK5rohS1sYl1DHdJ3mwfwClJj5BClQnQSyAgEfggbUwA9RlROQSSbKBLqrGfsiC/VyrDPtbO8hh56fnkbsQ==", "cpu": [ "arm64" ], @@ -2648,9 +2632,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.9.0.tgz", - "integrity": "sha512-TK+UA1TTa0qS53rjWn7cVlEKVGz2B6JYe0C++TdQjvWYIyx83ruwh0wd4LRxYBM5HeuAzXcylA9BH2trARXJTw==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.9.2.tgz", + "integrity": "sha512-gaIMWK+CWtXcg9gUyznkdV54LzQ90S3X3dn8zlh+QR5Xy7Y+Efqw4Rs4im61K1juy4YNb67vmJsCDAGOnIeffQ==", "cpu": [ "x64" ], @@ -2662,9 +2646,9 @@ ] }, "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.9.0.tgz", - "integrity": "sha512-6uZwzMRFcD7CcCd0vz3Hp+9qIL2jseE/bx3ZjaLwn8t714nYGwiE84WpaMCYjU+IQET8Vu/+BNAGtYD7BG/0yA==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.9.2.tgz", + "integrity": "sha512-S7QpkMbVoVJb0xwHFwujnwCAEDe/596xqY603rpi/ioTn9VDgBHnCCxh+UFrr5yxuMH+dliHfjwCZJXOPJGPnw==", "cpu": [ "x64" ], @@ -2676,9 +2660,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.9.0.tgz", - "integrity": "sha512-bPUBksQfrgcfv2+mm+AZinaKq8LCFvt5PThYqRotqSuuZK1TVKkhbVMS/jvSRfYl7jr3AoZLYbDkItxgqMKRkg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.9.2.tgz", + "integrity": "sha512-+XPUMCuCCI80I46nCDFbGum0ZODP5NWGiwS3Pj8fOgsG5/ctz+/zzuBlq/WmGa+EjWZdue6CF0aWWNv84sE1uw==", "cpu": [ "arm" ], @@ -2690,9 +2674,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.9.0.tgz", - "integrity": "sha512-uT6E7UBIrTdCsFQ+y0tQd3g5oudmrS/hds5pbU3h4s2t/1vsGWbbSKhBSCD9mcqaqkBwoqlECpUrRJCmldl8PA==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.9.2.tgz", + "integrity": "sha512-sqvUyAd1JUpwbz33Ce2tuTLJKM+ucSsYpPGl2vuFwZnEIg0CmdxiZ01MHQ3j6ExuRqEDUCy8yvkDKvjYFPb8Zg==", "cpu": [ "arm" ], @@ -2704,9 +2688,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.9.0.tgz", - "integrity": "sha512-vdqBh911wc5awE2bX2zx3eflbyv8U9xbE/jVKAm425eRoOVv/VseGZsqi3A3SykckSpF4wSROkbQPvbQFn8EsA==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.9.2.tgz", + "integrity": "sha512-UYA0MA8ajkEDCFRQdng/FVx3F6szBvk3EPnkTTQuuO9lV1kPGuTB+V9TmbDxy5ikaEgyWKxa4CI3ySjklZ9lFA==", "cpu": [ "arm64" ], @@ -2718,9 +2702,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.9.0.tgz", - "integrity": "sha512-/8JFZ/SnuDr1lLEVsxsuVwrsGquTvT51RZGvyDB/dOK3oYK2UqeXzgeyq6Otp8FZXQcEYqJwxb9v+gtdXn03eQ==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.9.2.tgz", + "integrity": "sha512-P/CO3ODU9YJIHFqAkHbquKtFst0COxdphc8TKGL5yCX75GOiVpGqd1d15ahpqu8xXVsqP4MGFP2C3LRZnnL5MA==", "cpu": [ "arm64" ], @@ -2732,9 +2716,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.9.0.tgz", - "integrity": "sha512-FkJjybtrl+rajTw4loI3L6YqSOpeZfDls4SstL/5lsP2bka9TiHUjgMBjygeZEis1oC8LfJTS8FSgpKPaQx2tQ==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.9.2.tgz", + "integrity": "sha512-uKStFlOELBxBum2s1hODPtgJhY4NxYJE9pAeyBgNEzHgTqTiVBPjfTlPFJkfxyTjQEuxZbbJlJnMCrRgD7ubzw==", "cpu": [ "ppc64" ], @@ -2746,9 +2730,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.9.0.tgz", - "integrity": "sha512-w/NZfHNeDusbqSZ8r/hp8iL4S39h4+vQMc9/vvzuIKMWKppyUGKm3IST0Qv0aOZ1rzIbl9SrDeIqK86ZpUK37w==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.9.2.tgz", + "integrity": "sha512-LkbNnZlhINfY9gK30AHs26IIVEZ9PEl9qOScYdmY2o81imJYI4IMnJiW0vJVtXaDHvBvxeAgEy5CflwJFIl3tQ==", "cpu": [ "riscv64" ], @@ -2760,9 +2744,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.9.0.tgz", - "integrity": "sha512-bEPBosut8/8KQbUixPry8zg/fOzVOWyvwzOfz0C0Rw6dp+wIBseyiHKjkcSyZKv/98edrbMknBaMNJfA/UEdqw==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.9.2.tgz", + "integrity": "sha512-vI+e6FzLyZHSLFNomPi+nT+qUWN4YSj8pFtQZSFTtmgFoxqB6NyjxSjAxEC1m93qn6hUXhIsh8WMp+fGgxCoRg==", "cpu": [ "riscv64" ], @@ -2774,9 +2758,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.9.0.tgz", - "integrity": "sha512-LDtMT7moE3gK753gG4pc31AAqGUC86j3AplaFusc717EUGF9ZFJ356sdQzzZzkBk1XzMdxFyZ4f/i35NKM/lFA==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.9.2.tgz", + "integrity": "sha512-sSO4AlAYhSM2RAzBsRpahcJB1msc6uYLAtP6pesPbZtptF8OU/CbCPhSRW6cnYOGuVmEmWVW5xVboAqCnWTeHQ==", "cpu": [ "s390x" ], @@ -2788,9 +2772,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.9.0.tgz", - "integrity": "sha512-WmFd5KINHIXj8o1mPaT8QRjA9HgSXhN1gl9Da4IZihARihEnOylu4co7i/yeaIpcfsI6sYs33cNZKyHYDh0lrA==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.9.2.tgz", + "integrity": "sha512-jkSkwch0uPFva20Mdu8orbQjv2A3G88NExTN2oPTI1AJ+7mZfYW3cDCTyoH6OnctBKbBVeJCEqh0U02lTkqD5w==", "cpu": [ "x64" ], @@ -2802,9 +2786,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.9.0.tgz", - "integrity": "sha512-CYuXbANW+WgzVRIl8/QvZmDaZxrqvOldOwlbUjIM4pQ46FJ0W5cinJ/Ghwa/Ng1ZPMJMk1VFdsD/XwmCGIXBWg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.9.2.tgz", + "integrity": "sha512-Uk64NoiTpQbkpl+bXsbeyOPRpUoMdcUqa+hDC1KhMW7aN1lfW8PBlBH4mJ3n3Y47dYE8qi0XTxy1mBACruYBaw==", "cpu": [ "x64" ], @@ -2816,9 +2800,9 @@ ] }, "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.9.0.tgz", - "integrity": "sha512-6Rp2WH0OoitMYR57Z6VE8Y6corX8C6QEMWLgOV6qXiJIeZ1F9WGXY/yQ8yDC4iTraotyLOeJ2Asea0urWj2fKQ==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.9.2.tgz", + "integrity": "sha512-EpBGwkcjDicjR/ybC0g8wO5adPNdVuMrNalVgYcWi+gYtC1XYNuxe3rufcO7dA76OHGeVabcO6cSkPJKVcbCXQ==", "cpu": [ "wasm32" ], @@ -2833,9 +2817,9 @@ } }, "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.9.0.tgz", - "integrity": "sha512-rknkrTRuvujprrbPmGeHi8wYWxmNVlBoNW8+4XF2hXUnASOjmuC9FNF1tGbDiRQWn264q9U/oGtixyO3BT8adQ==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.9.2.tgz", + "integrity": "sha512-EdFbGn7o1SxGmN6aZw9wAkehZJetFPao0VGZ9OMBwKx6TkvDuj6cNeLimF/Psi6ts9lMOe+Dt6z19fZQ9Ye2fw==", "cpu": [ "arm64" ], @@ -2847,9 +2831,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.9.0.tgz", - "integrity": "sha512-Ceymm+iBl+bgAICtgiHyMLz6hjxmLJKqBim8tDzpX61wpZOx2bPK6Gjuor7I2RiUynVjvvkoRIkrPyMwzBzF3A==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.9.2.tgz", + "integrity": "sha512-JY9hi1p7AG+5c/dMU8o2kWemM8I6VZxfGwn1GCtf3c5i+IKcMo2NQ8OjZ4Z3/itvY/Si3K10jOBQn7qsD/whUA==", "cpu": [ "ia32" ], @@ -2861,9 +2845,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.9.0.tgz", - "integrity": "sha512-k59o9ZyeyS0hAlcaKFezYSH2agQeRFEB7KoQLXl3Nb3rgkqT1NY9Vwy+SqODiLmYnEjxWJVRE/yq2jFVqdIxZw==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.9.2.tgz", + "integrity": "sha512-ryoo+EB19lMxAd80ln9BVf8pdOAxLb97amrQ3SFN9OCRn/5M5wvwDgAe4i8ZjhpbiHoDeP8yavcTEnpKBo7lZg==", "cpu": [ "x64" ], @@ -3353,9 +3337,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001723", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz", - "integrity": "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==", + "version": "1.0.30001724", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001724.tgz", + "integrity": "sha512-WqJo7p0TbHDOythNTqYujmaJTvtYRZrjpP8TCvH6Vb9CYJerJNKamKzIWOM4BkQatWj9H2lYulpdAQNBe7QhNA==", "funding": [ { "type": "opencollective", @@ -3712,9 +3696,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.18.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", - "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", + "version": "5.18.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", + "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4068,9 +4052,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", - "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, "license": "MIT", "dependencies": { @@ -4096,30 +4080,30 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", - "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", "dependencies": { "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", + "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", - "is-core-module": "^2.15.1", + "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", - "object.values": "^1.2.0", + "object.values": "^1.2.1", "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", + "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "engines": { @@ -4569,9 +4553,9 @@ } }, "node_modules/firebase-admin/node_modules/@types/node": { - "version": "22.15.32", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.32.tgz", - "integrity": "sha512-3jigKqgSjsH6gYZv2nEsqdXfZqIFGAV36XYYjf9KGZ3PSG+IhLecqPnI310RvjutyMwifE2hhhNEklOUrvx/wA==", + "version": "22.15.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.33.tgz", + "integrity": "sha512-wzoocdnnpSxZ+6CjW4ADCK1jVmd1S/J3ArNWfn8FDDQtRm8dkDg7TA+mvek2wNrfCgwuZxqEOiB9B1XCJ6+dbw==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -6081,7 +6065,7 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/lightningcss-win32-x64-msvc": { + "node_modules/lightningcss/node_modules/lightningcss-win32-x64-msvc": { "version": "1.30.1", "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", @@ -6215,12 +6199,6 @@ "node": ">=10" } }, - "node_modules/lru-cache/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, "node_modules/lru-memoizer": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.3.0.tgz", @@ -6473,6 +6451,22 @@ } } }, + "node_modules/next/node_modules/@next/swc-win32-x64-msvc": { + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.3.tgz", + "integrity": "sha512-4QZG6F8enl9/S2+yIiOiju0iCTFd93d8VC1q9LZS4p/Xuk81W2QDjCFeoogmrWWkAD59z8ZxepBQap2dKS5ruw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -7785,6 +7779,16 @@ "node": ">=18" } }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/teeny-request": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", @@ -8070,38 +8074,38 @@ "license": "MIT" }, "node_modules/unrs-resolver": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.9.0.tgz", - "integrity": "sha512-wqaRu4UnzBD2ABTC1kLfBjAqIDZ5YUTr/MLGa7By47JV1bJDSW7jq/ZSLigB7enLe7ubNaJhtnBXgrc/50cEhg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.9.2.tgz", + "integrity": "sha512-VUyWiTNQD7itdiMuJy+EuLEErLj3uwX/EpHQF8EOf33Dq3Ju6VW1GXm+swk6+1h7a49uv9fKZ+dft9jU7esdLA==", "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { - "napi-postinstall": "^0.2.2" + "napi-postinstall": "^0.2.4" }, "funding": { "url": "https://opencollective.com/unrs-resolver" }, "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.9.0", - "@unrs/resolver-binding-android-arm64": "1.9.0", - "@unrs/resolver-binding-darwin-arm64": "1.9.0", - "@unrs/resolver-binding-darwin-x64": "1.9.0", - "@unrs/resolver-binding-freebsd-x64": "1.9.0", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.9.0", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.9.0", - "@unrs/resolver-binding-linux-arm64-gnu": "1.9.0", - "@unrs/resolver-binding-linux-arm64-musl": "1.9.0", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.9.0", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.9.0", - "@unrs/resolver-binding-linux-riscv64-musl": "1.9.0", - "@unrs/resolver-binding-linux-s390x-gnu": "1.9.0", - "@unrs/resolver-binding-linux-x64-gnu": "1.9.0", - "@unrs/resolver-binding-linux-x64-musl": "1.9.0", - "@unrs/resolver-binding-wasm32-wasi": "1.9.0", - "@unrs/resolver-binding-win32-arm64-msvc": "1.9.0", - "@unrs/resolver-binding-win32-ia32-msvc": "1.9.0", - "@unrs/resolver-binding-win32-x64-msvc": "1.9.0" + "@unrs/resolver-binding-android-arm-eabi": "1.9.2", + "@unrs/resolver-binding-android-arm64": "1.9.2", + "@unrs/resolver-binding-darwin-arm64": "1.9.2", + "@unrs/resolver-binding-darwin-x64": "1.9.2", + "@unrs/resolver-binding-freebsd-x64": "1.9.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.9.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.9.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.9.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.9.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.9.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.9.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.9.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.9.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.9.2", + "@unrs/resolver-binding-linux-x64-musl": "1.9.2", + "@unrs/resolver-binding-wasm32-wasi": "1.9.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.9.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.9.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.9.2" } }, "node_modules/uri-js": { @@ -8328,14 +8332,10 @@ } }, "node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" }, "node_modules/yargs": { "version": "17.7.2", @@ -8376,6 +8376,21 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.3.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.3.tgz", + "integrity": "sha512-4QZG6F8enl9/S2+yIiOiju0iCTFd93d8VC1q9LZS4p/Xuk81W2QDjCFeoogmrWWkAD59z8ZxepBQap2dKS5ruw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } } } } diff --git a/package.json b/package.json index 339cad8..738add2 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,9 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev --turbopack", + "dev": "next dev --turbopack -p 6014", "build": "next build", - "start": "next start", + "start": "next start -p 6014", "lint": "next lint" }, "dependencies": {