app for refbot stuff
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

init: vue3 + vite web ui for refbot match management

alpinesystem 4e4f5295

+5483
+4
.env.example
··· 1 + MONGODB_URI=mongodb://localhost:27017/refbot 2 + MONGODB_TEST_URI=mongodb://localhost:27017/refbot-test 3 + PORT=3001 4 + NODE_ENV=development
+4
.gitignore
··· 1 + node_modules/ 2 + dist/ 3 + .env 4 + .env.local
+13
api/db.js
··· 1 + import mongoose from 'mongoose' 2 + 3 + async function connectDB() { 4 + const uri = process.env.NODE_ENV === 'development' 5 + ? process.env.MONGODB_TEST_URI 6 + : process.env.MONGODB_URI 7 + if (!uri) throw new Error('mongodb uri not set in .env') 8 + await mongoose.connect(uri) 9 + const which = process.env.NODE_ENV === 'development' ? 'test' : 'production' 10 + console.log(`connected to mongodb (${which})`) 11 + } 12 + 13 + export { connectDB }
+35
api/index.js
··· 1 + import express from 'express' 2 + import cors from 'cors' 3 + import { connectDB } from './db.js' 4 + import matchRoutes from './routes/matches.js' 5 + import eventRoutes from './routes/events.js' 6 + import playerRoutes from './routes/players.js' 7 + import chartRoutes from './routes/charts.js' 8 + 9 + const app = express() 10 + const PORT = process.env.PORT ?? 3001 11 + 12 + app.use(cors()) 13 + app.use(express.json()) 14 + 15 + app.use('/api/matches', matchRoutes) 16 + app.use('/api/events', eventRoutes) 17 + app.use('/api/players', playerRoutes) 18 + app.use('/api/charts', chartRoutes) 19 + 20 + // serve built frontend in production 21 + if (process.env.NODE_ENV !== 'development') { 22 + const { default: path } = await import('node:path') 23 + const { fileURLToPath } = await import('node:url') 24 + const __dirname = path.dirname(fileURLToPath(import.meta.url)) 25 + const distPath = path.join(__dirname, '../dist') 26 + app.use(express.static(distPath)) 27 + app.get('*', (_req, res) => res.sendFile(path.join(distPath, 'index.html'))) 28 + } 29 + 30 + connectDB().then(() => { 31 + app.listen(PORT, () => console.log(`refapp api running on :${PORT}`)) 32 + }).catch(err => { 33 + console.error('failed to connect to db:', err) 34 + process.exit(1) 35 + })
+20
api/models/Chart.js
··· 1 + import { Schema, model } from 'mongoose' 2 + 3 + const chartSchema = new Schema({ 4 + songId: { type: Number, required: true, unique: true }, 5 + title: String, 6 + artist: String, 7 + charter: String, 8 + cover: String, 9 + thumbnailUrl: String, 10 + difficulty: Number, 11 + tags: [String], 12 + maxScore: Number, 13 + fetchedAt: { type: Date, default: Date.now }, 14 + }) 15 + 16 + chartSchema.virtual('displayName').get(function() { 17 + return `${this.title} - ${this.charter}` 18 + }) 19 + 20 + export default model('Chart', chartSchema)
+10
api/models/Event.js
··· 1 + import { Schema, model } from 'mongoose' 2 + 3 + const eventSchema = new Schema({ 4 + name: { type: String, required: true, unique: true }, 5 + createdAt: { type: Date, default: Date.now }, 6 + active: { type: Boolean, default: false }, 7 + tournamentSlug: { type: String, default: null }, 8 + }) 9 + 10 + export default model('Event', eventSchema)
+109
api/models/Match.js
··· 1 + import { Schema, model } from 'mongoose' 2 + 3 + const feedEventSchema = new Schema({ 4 + type: { type: String, required: true }, 5 + timestamp: { type: Date, default: Date.now }, 6 + message: { type: String, default: null }, 7 + data: { type: Schema.Types.Mixed, default: {} }, 8 + }, { _id: false }) 9 + 10 + const chartResultSchema = new Schema({ 11 + score1: { type: Number, default: null }, 12 + score2: { type: Number, default: null }, 13 + fc1: { type: Boolean, default: false }, 14 + fc2: { type: Boolean, default: false }, 15 + pfc1: { type: Boolean, default: false }, 16 + pfc2: { type: Boolean, default: false }, 17 + winnerDiscordId: { type: String, default: null }, 18 + winnerSlot: { type: Number, default: null }, 19 + rank1: { type: String, default: null }, 20 + rank2: { type: String, default: null }, 21 + pct1: { type: Number, default: null }, 22 + pct2: { type: Number, default: null }, 23 + }, { _id: false }) 24 + 25 + const chartStatusSchema = new Schema({ 26 + banned: { type: Boolean, default: false }, 27 + bannedByDiscordId: { type: String, default: null }, 28 + bannedAt: { type: Date, default: null }, 29 + played: { type: Boolean, default: false }, 30 + playedAt: { type: Date, default: null }, 31 + inCurrentPool: { type: Boolean, default: true }, 32 + isBeingPlayed: { type: Boolean, default: false }, 33 + }, { _id: false }) 34 + 35 + const mappoolEntrySchema = new Schema({ 36 + songId: { type: Number, default: null }, 37 + title: { type: String, default: null }, 38 + artist: { type: String, default: null }, 39 + charter: { type: String, default: null }, 40 + cover: { type: String, default: null }, 41 + thumbnailUrl: { type: String, default: null }, 42 + difficulty: { type: Number, default: null }, 43 + tags: { type: [String], default: [] }, 44 + displayName: { type: String, default: null }, 45 + status: { type: chartStatusSchema, default: () => ({}) }, 46 + result: { type: chartResultSchema, default: null }, 47 + isTiebreaker: { type: Boolean, default: false }, 48 + }, { _id: false }) 49 + 50 + const playerSchema = new Schema({ 51 + slot: { type: Number, required: true }, 52 + displayName: { type: String, default: null }, 53 + discordId: { type: String, default: null }, 54 + discordUsername: { type: String, default: null }, 55 + discordDisplayName: { type: String, default: null }, 56 + serverNickname: { type: String, default: null }, 57 + avatarUrl: { type: String, default: null }, 58 + points: { type: Number, default: 0 }, 59 + ready: { type: Boolean, default: false }, 60 + winner: { type: Boolean, default: false }, 61 + spinshareId: { type: Number, default: null }, 62 + spinshareUsername: { type: String, default: null }, 63 + spinshareAvatarUrl: { type: String, default: null }, 64 + pronouns: { type: String, default: null }, 65 + }, { _id: false }) 66 + 67 + const banPhaseSchema = new Schema({ 68 + banOrder: { type: [String], default: [] }, 69 + currentBannerDiscordId: { type: String, default: null }, 70 + bansCompleted: { type: Number, default: 0 }, 71 + totalBans: { type: Number, default: 0 }, 72 + }, { _id: false }) 73 + 74 + const matchSchema = new Schema({ 75 + matchId: { type: String, index: true, default: null }, 76 + progressLevel: { 77 + type: String, 78 + enum: ['check-in', 'ban-phase', 'ready-check', 'playing', 'picking-post-result', 'finished'], 79 + default: 'check-in', 80 + }, 81 + meta: { 82 + name: { type: String, default: null }, 83 + round: { type: String, default: null }, 84 + matchNumber: { type: Number, default: null }, 85 + bestOf: { type: Number, default: null }, 86 + winsNeeded: { type: Number, default: null }, 87 + tier: { type: Number, default: null }, 88 + channelId: { type: String, required: true }, 89 + eventId: { type: Schema.Types.ObjectId, ref: 'Event', required: true }, 90 + startedAt: { type: Date, default: Date.now }, 91 + completedAt: { type: Date, default: null }, 92 + startggSetId: { type: String, default: null }, 93 + type: { type: String, enum: ['tournament', 'friendly'], default: 'tournament' }, 94 + }, 95 + players: { type: [playerSchema], default: [] }, 96 + mappool: { type: [mappoolEntrySchema], default: [] }, 97 + banPhase: { type: banPhaseSchema, default: () => ({}) }, 98 + currentPickerDiscordId: { type: String, default: null }, 99 + currentChart: { type: Number, default: null }, 100 + refereeDiscordId: { type: String, default: null }, 101 + feed: { type: [feedEventSchema], default: [] }, 102 + status: { 103 + type: String, 104 + enum: ['in_progress', 'completed', 'restarted', 'abandoned'], 105 + default: 'in_progress', 106 + }, 107 + }) 108 + 109 + export default model('Match', matchSchema)
+20
api/models/Player.js
··· 1 + import { Schema, model } from 'mongoose' 2 + 3 + const playerSchema = new Schema({ 4 + discordId: { type: String, required: true, unique: true }, 5 + startggParticipantId: { type: Number, default: null }, 6 + gamerTag: { type: String, default: null }, 7 + csvPronouns: { type: String, default: null }, 8 + spinshareId: { type: Number, required: true }, 9 + spinshareUsername: { type: String, default: null }, 10 + spinshareAvatarUrl: { type: String, default: null }, 11 + spinsharePronouns: { type: String, default: null }, 12 + spinshareProfileFetchedAt: { type: Date, default: null }, 13 + events: [{ type: Schema.Types.ObjectId, ref: 'Event' }], 14 + }) 15 + 16 + playerSchema.virtual('pronouns').get(function() { 17 + return this.spinsharePronouns || this.csvPronouns || null 18 + }) 19 + 20 + export default model('Player', playerSchema)
+28
api/routes/charts.js
··· 1 + import { Router } from 'express' 2 + import Chart from '../models/Chart.js' 3 + 4 + const router = Router() 5 + 6 + router.get('/', async (req, res) => { 7 + try { 8 + const { search, limit = 50, skip = 0 } = req.query 9 + const query = {} 10 + if (search) { 11 + query.$or = [ 12 + { title: { $regex: search, $options: 'i' } }, 13 + { charter: { $regex: search, $options: 'i' } }, 14 + { artist: { $regex: search, $options: 'i' } }, 15 + ] 16 + } 17 + const [charts, total] = await Promise.all([ 18 + Chart.find(query).sort({ title: 1 }).limit(Number(limit)).skip(Number(skip)).lean(), 19 + Chart.countDocuments(query), 20 + ]) 21 + res.json({ charts, total }) 22 + } 23 + catch (err) { 24 + res.status(500).json({ error: err.message }) 25 + } 26 + }) 27 + 28 + export default router
+66
api/routes/events.js
··· 1 + import { Router } from 'express' 2 + import Event from '../models/Event.js' 3 + import Match from '../models/Match.js' 4 + import Player from '../models/Player.js' 5 + 6 + const router = Router() 7 + 8 + router.get('/', async (req, res) => { 9 + try { 10 + const events = await Event.find().sort({ createdAt: -1 }).lean() 11 + const withCounts = await Promise.all(events.map(async evt => { 12 + const [matchCount, activeMatchCount, playerCount] = await Promise.all([ 13 + Match.countDocuments({ 'meta.eventId': evt._id }), 14 + Match.countDocuments({ 'meta.eventId': evt._id, status: 'in_progress' }), 15 + Player.countDocuments({ events: evt._id }), 16 + ]) 17 + return { ...evt, matchCount, activeMatchCount, playerCount } 18 + })) 19 + res.json(withCounts) 20 + } 21 + catch (err) { 22 + res.status(500).json({ error: err.message }) 23 + } 24 + }) 25 + 26 + router.get('/:id', async (req, res) => { 27 + try { 28 + const event = await Event.findById(req.params.id).lean() 29 + if (!event) return res.status(404).json({ error: 'not found' }) 30 + const [matchCount, activeMatchCount, playerCount] = await Promise.all([ 31 + Match.countDocuments({ 'meta.eventId': event._id }), 32 + Match.countDocuments({ 'meta.eventId': event._id, status: 'in_progress' }), 33 + Player.countDocuments({ events: event._id }), 34 + ]) 35 + res.json({ ...event, matchCount, activeMatchCount, playerCount }) 36 + } 37 + catch (err) { 38 + res.status(500).json({ error: err.message }) 39 + } 40 + }) 41 + 42 + // set as active event (deactivates all others first) 43 + router.patch('/:id/activate', async (req, res) => { 44 + try { 45 + await Event.updateMany({}, { active: false }) 46 + const event = await Event.findByIdAndUpdate(req.params.id, { active: true }, { new: true }) 47 + if (!event) return res.status(404).json({ error: 'not found' }) 48 + res.json(event) 49 + } 50 + catch (err) { 51 + res.status(500).json({ error: err.message }) 52 + } 53 + }) 54 + 55 + router.patch('/:id/deactivate', async (req, res) => { 56 + try { 57 + const event = await Event.findByIdAndUpdate(req.params.id, { active: false }, { new: true }) 58 + if (!event) return res.status(404).json({ error: 'not found' }) 59 + res.json(event) 60 + } 61 + catch (err) { 62 + res.status(500).json({ error: err.message }) 63 + } 64 + }) 65 + 66 + export default router
+58
api/routes/matches.js
··· 1 + import { Router } from 'express' 2 + import Match from '../models/Match.js' 3 + 4 + const router = Router() 5 + 6 + // GET /api/matches?status=in_progress&eventId=xxx&limit=50&skip=0 7 + router.get('/', async (req, res) => { 8 + try { 9 + const { status, eventId, progressLevel, limit = 50, skip = 0 } = req.query 10 + const query = {} 11 + if (status) query.status = status 12 + if (eventId) query['meta.eventId'] = eventId 13 + if (progressLevel) query.progressLevel = progressLevel 14 + 15 + const [matches, total] = await Promise.all([ 16 + Match.find(query) 17 + .sort({ 'meta.startedAt': -1 }) 18 + .limit(Number(limit)) 19 + .skip(Number(skip)) 20 + .populate('meta.eventId', 'name') 21 + .lean(), 22 + Match.countDocuments(query), 23 + ]) 24 + 25 + res.json({ matches, total }) 26 + } 27 + catch (err) { 28 + res.status(500).json({ error: err.message }) 29 + } 30 + }) 31 + 32 + // GET /api/matches/:id 33 + router.get('/:id', async (req, res) => { 34 + try { 35 + const match = await Match.findById(req.params.id) 36 + .populate('meta.eventId', 'name') 37 + .lean() 38 + if (!match) return res.status(404).json({ error: 'not found' }) 39 + res.json(match) 40 + } 41 + catch (err) { 42 + res.status(500).json({ error: err.message }) 43 + } 44 + }) 45 + 46 + // PATCH /api/matches/:id -- for manual referee overrides 47 + router.patch('/:id', async (req, res) => { 48 + try { 49 + const match = await Match.findByIdAndUpdate(req.params.id, req.body, { new: true }) 50 + if (!match) return res.status(404).json({ error: 'not found' }) 51 + res.json(match) 52 + } 53 + catch (err) { 54 + res.status(500).json({ error: err.message }) 55 + } 56 + }) 57 + 58 + export default router
+38
api/routes/players.js
··· 1 + import { Router } from 'express' 2 + import Player from '../models/Player.js' 3 + 4 + const router = Router() 5 + 6 + router.get('/', async (req, res) => { 7 + try { 8 + const { search, limit = 50, skip = 0 } = req.query 9 + const query = {} 10 + if (search) { 11 + query.$or = [ 12 + { gamerTag: { $regex: search, $options: 'i' } }, 13 + { spinshareUsername: { $regex: search, $options: 'i' } }, 14 + ] 15 + } 16 + const [players, total] = await Promise.all([ 17 + Player.find(query).sort({ gamerTag: 1 }).limit(Number(limit)).skip(Number(skip)).lean(), 18 + Player.countDocuments(query), 19 + ]) 20 + res.json({ players, total }) 21 + } 22 + catch (err) { 23 + res.status(500).json({ error: err.message }) 24 + } 25 + }) 26 + 27 + router.get('/:id', async (req, res) => { 28 + try { 29 + const player = await Player.findById(req.params.id).populate('events', 'name').lean() 30 + if (!player) return res.status(404).json({ error: 'not found' }) 31 + res.json(player) 32 + } 33 + catch (err) { 34 + res.status(500).json({ error: err.message }) 35 + } 36 + }) 37 + 38 + export default router
+15
index.html
··· 1 + <!DOCTYPE html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="UTF-8" /> 5 + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 + <title>refapp</title> 7 + <link rel="preconnect" href="https://fonts.googleapis.com" /> 8 + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> 9 + <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" /> 10 + </head> 11 + <body> 12 + <div id="app"></div> 13 + <script type="module" src="/src/main.js"></script> 14 + </body> 15 + </html>
+5
nodemon.json
··· 1 + { 2 + "watch": ["api"], 3 + "ext": "js", 4 + "exec": "node --env-file=.env api/index.js" 5 + }
+3962
package-lock.json
··· 1 + { 2 + "name": "refapp", 3 + "version": "1.0.0", 4 + "lockfileVersion": 3, 5 + "requires": true, 6 + "packages": { 7 + "": { 8 + "name": "refapp", 9 + "version": "1.0.0", 10 + "dependencies": { 11 + "cors": "^2.8.5", 12 + "express": "^4.21.2", 13 + "mongoose": "^9.0.2", 14 + "pinia": "^2.3.1", 15 + "vue": "^3.5.13", 16 + "vue-router": "^4.5.0" 17 + }, 18 + "devDependencies": { 19 + "@vitejs/plugin-vue": "^5.2.1", 20 + "autoprefixer": "^10.4.20", 21 + "concurrently": "^9.1.2", 22 + "nodemon": "^3.1.9", 23 + "postcss": "^8.5.3", 24 + "tailwindcss": "^3.4.17", 25 + "vite": "^6.2.6" 26 + } 27 + }, 28 + "node_modules/@alloc/quick-lru": { 29 + "version": "5.2.0", 30 + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", 31 + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", 32 + "dev": true, 33 + "license": "MIT", 34 + "engines": { 35 + "node": ">=10" 36 + }, 37 + "funding": { 38 + "url": "https://github.com/sponsors/sindresorhus" 39 + } 40 + }, 41 + "node_modules/@babel/helper-string-parser": { 42 + "version": "7.27.1", 43 + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", 44 + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", 45 + "license": "MIT", 46 + "engines": { 47 + "node": ">=6.9.0" 48 + } 49 + }, 50 + "node_modules/@babel/helper-validator-identifier": { 51 + "version": "7.28.5", 52 + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", 53 + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", 54 + "license": "MIT", 55 + "engines": { 56 + "node": ">=6.9.0" 57 + } 58 + }, 59 + "node_modules/@babel/parser": { 60 + "version": "7.29.2", 61 + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", 62 + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", 63 + "license": "MIT", 64 + "dependencies": { 65 + "@babel/types": "^7.29.0" 66 + }, 67 + "bin": { 68 + "parser": "bin/babel-parser.js" 69 + }, 70 + "engines": { 71 + "node": ">=6.0.0" 72 + } 73 + }, 74 + "node_modules/@babel/types": { 75 + "version": "7.29.0", 76 + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", 77 + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", 78 + "license": "MIT", 79 + "dependencies": { 80 + "@babel/helper-string-parser": "^7.27.1", 81 + "@babel/helper-validator-identifier": "^7.28.5" 82 + }, 83 + "engines": { 84 + "node": ">=6.9.0" 85 + } 86 + }, 87 + "node_modules/@esbuild/aix-ppc64": { 88 + "version": "0.25.12", 89 + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", 90 + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", 91 + "cpu": [ 92 + "ppc64" 93 + ], 94 + "dev": true, 95 + "license": "MIT", 96 + "optional": true, 97 + "os": [ 98 + "aix" 99 + ], 100 + "engines": { 101 + "node": ">=18" 102 + } 103 + }, 104 + "node_modules/@esbuild/android-arm": { 105 + "version": "0.25.12", 106 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", 107 + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", 108 + "cpu": [ 109 + "arm" 110 + ], 111 + "dev": true, 112 + "license": "MIT", 113 + "optional": true, 114 + "os": [ 115 + "android" 116 + ], 117 + "engines": { 118 + "node": ">=18" 119 + } 120 + }, 121 + "node_modules/@esbuild/android-arm64": { 122 + "version": "0.25.12", 123 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", 124 + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", 125 + "cpu": [ 126 + "arm64" 127 + ], 128 + "dev": true, 129 + "license": "MIT", 130 + "optional": true, 131 + "os": [ 132 + "android" 133 + ], 134 + "engines": { 135 + "node": ">=18" 136 + } 137 + }, 138 + "node_modules/@esbuild/android-x64": { 139 + "version": "0.25.12", 140 + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", 141 + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", 142 + "cpu": [ 143 + "x64" 144 + ], 145 + "dev": true, 146 + "license": "MIT", 147 + "optional": true, 148 + "os": [ 149 + "android" 150 + ], 151 + "engines": { 152 + "node": ">=18" 153 + } 154 + }, 155 + "node_modules/@esbuild/darwin-arm64": { 156 + "version": "0.25.12", 157 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", 158 + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", 159 + "cpu": [ 160 + "arm64" 161 + ], 162 + "dev": true, 163 + "license": "MIT", 164 + "optional": true, 165 + "os": [ 166 + "darwin" 167 + ], 168 + "engines": { 169 + "node": ">=18" 170 + } 171 + }, 172 + "node_modules/@esbuild/darwin-x64": { 173 + "version": "0.25.12", 174 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", 175 + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", 176 + "cpu": [ 177 + "x64" 178 + ], 179 + "dev": true, 180 + "license": "MIT", 181 + "optional": true, 182 + "os": [ 183 + "darwin" 184 + ], 185 + "engines": { 186 + "node": ">=18" 187 + } 188 + }, 189 + "node_modules/@esbuild/freebsd-arm64": { 190 + "version": "0.25.12", 191 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", 192 + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", 193 + "cpu": [ 194 + "arm64" 195 + ], 196 + "dev": true, 197 + "license": "MIT", 198 + "optional": true, 199 + "os": [ 200 + "freebsd" 201 + ], 202 + "engines": { 203 + "node": ">=18" 204 + } 205 + }, 206 + "node_modules/@esbuild/freebsd-x64": { 207 + "version": "0.25.12", 208 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", 209 + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", 210 + "cpu": [ 211 + "x64" 212 + ], 213 + "dev": true, 214 + "license": "MIT", 215 + "optional": true, 216 + "os": [ 217 + "freebsd" 218 + ], 219 + "engines": { 220 + "node": ">=18" 221 + } 222 + }, 223 + "node_modules/@esbuild/linux-arm": { 224 + "version": "0.25.12", 225 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", 226 + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", 227 + "cpu": [ 228 + "arm" 229 + ], 230 + "dev": true, 231 + "license": "MIT", 232 + "optional": true, 233 + "os": [ 234 + "linux" 235 + ], 236 + "engines": { 237 + "node": ">=18" 238 + } 239 + }, 240 + "node_modules/@esbuild/linux-arm64": { 241 + "version": "0.25.12", 242 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", 243 + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", 244 + "cpu": [ 245 + "arm64" 246 + ], 247 + "dev": true, 248 + "license": "MIT", 249 + "optional": true, 250 + "os": [ 251 + "linux" 252 + ], 253 + "engines": { 254 + "node": ">=18" 255 + } 256 + }, 257 + "node_modules/@esbuild/linux-ia32": { 258 + "version": "0.25.12", 259 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", 260 + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", 261 + "cpu": [ 262 + "ia32" 263 + ], 264 + "dev": true, 265 + "license": "MIT", 266 + "optional": true, 267 + "os": [ 268 + "linux" 269 + ], 270 + "engines": { 271 + "node": ">=18" 272 + } 273 + }, 274 + "node_modules/@esbuild/linux-loong64": { 275 + "version": "0.25.12", 276 + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", 277 + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", 278 + "cpu": [ 279 + "loong64" 280 + ], 281 + "dev": true, 282 + "license": "MIT", 283 + "optional": true, 284 + "os": [ 285 + "linux" 286 + ], 287 + "engines": { 288 + "node": ">=18" 289 + } 290 + }, 291 + "node_modules/@esbuild/linux-mips64el": { 292 + "version": "0.25.12", 293 + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", 294 + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", 295 + "cpu": [ 296 + "mips64el" 297 + ], 298 + "dev": true, 299 + "license": "MIT", 300 + "optional": true, 301 + "os": [ 302 + "linux" 303 + ], 304 + "engines": { 305 + "node": ">=18" 306 + } 307 + }, 308 + "node_modules/@esbuild/linux-ppc64": { 309 + "version": "0.25.12", 310 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", 311 + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", 312 + "cpu": [ 313 + "ppc64" 314 + ], 315 + "dev": true, 316 + "license": "MIT", 317 + "optional": true, 318 + "os": [ 319 + "linux" 320 + ], 321 + "engines": { 322 + "node": ">=18" 323 + } 324 + }, 325 + "node_modules/@esbuild/linux-riscv64": { 326 + "version": "0.25.12", 327 + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", 328 + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", 329 + "cpu": [ 330 + "riscv64" 331 + ], 332 + "dev": true, 333 + "license": "MIT", 334 + "optional": true, 335 + "os": [ 336 + "linux" 337 + ], 338 + "engines": { 339 + "node": ">=18" 340 + } 341 + }, 342 + "node_modules/@esbuild/linux-s390x": { 343 + "version": "0.25.12", 344 + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", 345 + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", 346 + "cpu": [ 347 + "s390x" 348 + ], 349 + "dev": true, 350 + "license": "MIT", 351 + "optional": true, 352 + "os": [ 353 + "linux" 354 + ], 355 + "engines": { 356 + "node": ">=18" 357 + } 358 + }, 359 + "node_modules/@esbuild/linux-x64": { 360 + "version": "0.25.12", 361 + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", 362 + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", 363 + "cpu": [ 364 + "x64" 365 + ], 366 + "dev": true, 367 + "license": "MIT", 368 + "optional": true, 369 + "os": [ 370 + "linux" 371 + ], 372 + "engines": { 373 + "node": ">=18" 374 + } 375 + }, 376 + "node_modules/@esbuild/netbsd-arm64": { 377 + "version": "0.25.12", 378 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", 379 + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", 380 + "cpu": [ 381 + "arm64" 382 + ], 383 + "dev": true, 384 + "license": "MIT", 385 + "optional": true, 386 + "os": [ 387 + "netbsd" 388 + ], 389 + "engines": { 390 + "node": ">=18" 391 + } 392 + }, 393 + "node_modules/@esbuild/netbsd-x64": { 394 + "version": "0.25.12", 395 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", 396 + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", 397 + "cpu": [ 398 + "x64" 399 + ], 400 + "dev": true, 401 + "license": "MIT", 402 + "optional": true, 403 + "os": [ 404 + "netbsd" 405 + ], 406 + "engines": { 407 + "node": ">=18" 408 + } 409 + }, 410 + "node_modules/@esbuild/openbsd-arm64": { 411 + "version": "0.25.12", 412 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", 413 + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", 414 + "cpu": [ 415 + "arm64" 416 + ], 417 + "dev": true, 418 + "license": "MIT", 419 + "optional": true, 420 + "os": [ 421 + "openbsd" 422 + ], 423 + "engines": { 424 + "node": ">=18" 425 + } 426 + }, 427 + "node_modules/@esbuild/openbsd-x64": { 428 + "version": "0.25.12", 429 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", 430 + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", 431 + "cpu": [ 432 + "x64" 433 + ], 434 + "dev": true, 435 + "license": "MIT", 436 + "optional": true, 437 + "os": [ 438 + "openbsd" 439 + ], 440 + "engines": { 441 + "node": ">=18" 442 + } 443 + }, 444 + "node_modules/@esbuild/openharmony-arm64": { 445 + "version": "0.25.12", 446 + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", 447 + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", 448 + "cpu": [ 449 + "arm64" 450 + ], 451 + "dev": true, 452 + "license": "MIT", 453 + "optional": true, 454 + "os": [ 455 + "openharmony" 456 + ], 457 + "engines": { 458 + "node": ">=18" 459 + } 460 + }, 461 + "node_modules/@esbuild/sunos-x64": { 462 + "version": "0.25.12", 463 + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", 464 + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", 465 + "cpu": [ 466 + "x64" 467 + ], 468 + "dev": true, 469 + "license": "MIT", 470 + "optional": true, 471 + "os": [ 472 + "sunos" 473 + ], 474 + "engines": { 475 + "node": ">=18" 476 + } 477 + }, 478 + "node_modules/@esbuild/win32-arm64": { 479 + "version": "0.25.12", 480 + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", 481 + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", 482 + "cpu": [ 483 + "arm64" 484 + ], 485 + "dev": true, 486 + "license": "MIT", 487 + "optional": true, 488 + "os": [ 489 + "win32" 490 + ], 491 + "engines": { 492 + "node": ">=18" 493 + } 494 + }, 495 + "node_modules/@esbuild/win32-ia32": { 496 + "version": "0.25.12", 497 + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", 498 + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", 499 + "cpu": [ 500 + "ia32" 501 + ], 502 + "dev": true, 503 + "license": "MIT", 504 + "optional": true, 505 + "os": [ 506 + "win32" 507 + ], 508 + "engines": { 509 + "node": ">=18" 510 + } 511 + }, 512 + "node_modules/@esbuild/win32-x64": { 513 + "version": "0.25.12", 514 + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", 515 + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", 516 + "cpu": [ 517 + "x64" 518 + ], 519 + "dev": true, 520 + "license": "MIT", 521 + "optional": true, 522 + "os": [ 523 + "win32" 524 + ], 525 + "engines": { 526 + "node": ">=18" 527 + } 528 + }, 529 + "node_modules/@jridgewell/gen-mapping": { 530 + "version": "0.3.13", 531 + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", 532 + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", 533 + "dev": true, 534 + "license": "MIT", 535 + "dependencies": { 536 + "@jridgewell/sourcemap-codec": "^1.5.0", 537 + "@jridgewell/trace-mapping": "^0.3.24" 538 + } 539 + }, 540 + "node_modules/@jridgewell/resolve-uri": { 541 + "version": "3.1.2", 542 + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 543 + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 544 + "dev": true, 545 + "license": "MIT", 546 + "engines": { 547 + "node": ">=6.0.0" 548 + } 549 + }, 550 + "node_modules/@jridgewell/sourcemap-codec": { 551 + "version": "1.5.5", 552 + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", 553 + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", 554 + "license": "MIT" 555 + }, 556 + "node_modules/@jridgewell/trace-mapping": { 557 + "version": "0.3.31", 558 + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", 559 + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", 560 + "dev": true, 561 + "license": "MIT", 562 + "dependencies": { 563 + "@jridgewell/resolve-uri": "^3.1.0", 564 + "@jridgewell/sourcemap-codec": "^1.4.14" 565 + } 566 + }, 567 + "node_modules/@mongodb-js/saslprep": { 568 + "version": "1.4.6", 569 + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.6.tgz", 570 + "integrity": "sha512-y+x3H1xBZd38n10NZF/rEBlvDOOMQ6LKUTHqr8R9VkJ+mmQOYtJFxIlkkK8fZrtOiL6VixbOBWMbZGBdal3Z1g==", 571 + "license": "MIT", 572 + "dependencies": { 573 + "sparse-bitfield": "^3.0.3" 574 + } 575 + }, 576 + "node_modules/@nodelib/fs.scandir": { 577 + "version": "2.1.5", 578 + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 579 + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 580 + "dev": true, 581 + "license": "MIT", 582 + "dependencies": { 583 + "@nodelib/fs.stat": "2.0.5", 584 + "run-parallel": "^1.1.9" 585 + }, 586 + "engines": { 587 + "node": ">= 8" 588 + } 589 + }, 590 + "node_modules/@nodelib/fs.stat": { 591 + "version": "2.0.5", 592 + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 593 + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 594 + "dev": true, 595 + "license": "MIT", 596 + "engines": { 597 + "node": ">= 8" 598 + } 599 + }, 600 + "node_modules/@nodelib/fs.walk": { 601 + "version": "1.2.8", 602 + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 603 + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 604 + "dev": true, 605 + "license": "MIT", 606 + "dependencies": { 607 + "@nodelib/fs.scandir": "2.1.5", 608 + "fastq": "^1.6.0" 609 + }, 610 + "engines": { 611 + "node": ">= 8" 612 + } 613 + }, 614 + "node_modules/@rollup/rollup-android-arm-eabi": { 615 + "version": "4.60.1", 616 + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", 617 + "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", 618 + "cpu": [ 619 + "arm" 620 + ], 621 + "dev": true, 622 + "license": "MIT", 623 + "optional": true, 624 + "os": [ 625 + "android" 626 + ] 627 + }, 628 + "node_modules/@rollup/rollup-android-arm64": { 629 + "version": "4.60.1", 630 + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", 631 + "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", 632 + "cpu": [ 633 + "arm64" 634 + ], 635 + "dev": true, 636 + "license": "MIT", 637 + "optional": true, 638 + "os": [ 639 + "android" 640 + ] 641 + }, 642 + "node_modules/@rollup/rollup-darwin-arm64": { 643 + "version": "4.60.1", 644 + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz", 645 + "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", 646 + "cpu": [ 647 + "arm64" 648 + ], 649 + "dev": true, 650 + "license": "MIT", 651 + "optional": true, 652 + "os": [ 653 + "darwin" 654 + ] 655 + }, 656 + "node_modules/@rollup/rollup-darwin-x64": { 657 + "version": "4.60.1", 658 + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz", 659 + "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", 660 + "cpu": [ 661 + "x64" 662 + ], 663 + "dev": true, 664 + "license": "MIT", 665 + "optional": true, 666 + "os": [ 667 + "darwin" 668 + ] 669 + }, 670 + "node_modules/@rollup/rollup-freebsd-arm64": { 671 + "version": "4.60.1", 672 + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz", 673 + "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", 674 + "cpu": [ 675 + "arm64" 676 + ], 677 + "dev": true, 678 + "license": "MIT", 679 + "optional": true, 680 + "os": [ 681 + "freebsd" 682 + ] 683 + }, 684 + "node_modules/@rollup/rollup-freebsd-x64": { 685 + "version": "4.60.1", 686 + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz", 687 + "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", 688 + "cpu": [ 689 + "x64" 690 + ], 691 + "dev": true, 692 + "license": "MIT", 693 + "optional": true, 694 + "os": [ 695 + "freebsd" 696 + ] 697 + }, 698 + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 699 + "version": "4.60.1", 700 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz", 701 + "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", 702 + "cpu": [ 703 + "arm" 704 + ], 705 + "dev": true, 706 + "license": "MIT", 707 + "optional": true, 708 + "os": [ 709 + "linux" 710 + ] 711 + }, 712 + "node_modules/@rollup/rollup-linux-arm-musleabihf": { 713 + "version": "4.60.1", 714 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz", 715 + "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", 716 + "cpu": [ 717 + "arm" 718 + ], 719 + "dev": true, 720 + "license": "MIT", 721 + "optional": true, 722 + "os": [ 723 + "linux" 724 + ] 725 + }, 726 + "node_modules/@rollup/rollup-linux-arm64-gnu": { 727 + "version": "4.60.1", 728 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz", 729 + "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", 730 + "cpu": [ 731 + "arm64" 732 + ], 733 + "dev": true, 734 + "license": "MIT", 735 + "optional": true, 736 + "os": [ 737 + "linux" 738 + ] 739 + }, 740 + "node_modules/@rollup/rollup-linux-arm64-musl": { 741 + "version": "4.60.1", 742 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz", 743 + "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", 744 + "cpu": [ 745 + "arm64" 746 + ], 747 + "dev": true, 748 + "license": "MIT", 749 + "optional": true, 750 + "os": [ 751 + "linux" 752 + ] 753 + }, 754 + "node_modules/@rollup/rollup-linux-loong64-gnu": { 755 + "version": "4.60.1", 756 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz", 757 + "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", 758 + "cpu": [ 759 + "loong64" 760 + ], 761 + "dev": true, 762 + "license": "MIT", 763 + "optional": true, 764 + "os": [ 765 + "linux" 766 + ] 767 + }, 768 + "node_modules/@rollup/rollup-linux-loong64-musl": { 769 + "version": "4.60.1", 770 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz", 771 + "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", 772 + "cpu": [ 773 + "loong64" 774 + ], 775 + "dev": true, 776 + "license": "MIT", 777 + "optional": true, 778 + "os": [ 779 + "linux" 780 + ] 781 + }, 782 + "node_modules/@rollup/rollup-linux-ppc64-gnu": { 783 + "version": "4.60.1", 784 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz", 785 + "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", 786 + "cpu": [ 787 + "ppc64" 788 + ], 789 + "dev": true, 790 + "license": "MIT", 791 + "optional": true, 792 + "os": [ 793 + "linux" 794 + ] 795 + }, 796 + "node_modules/@rollup/rollup-linux-ppc64-musl": { 797 + "version": "4.60.1", 798 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz", 799 + "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", 800 + "cpu": [ 801 + "ppc64" 802 + ], 803 + "dev": true, 804 + "license": "MIT", 805 + "optional": true, 806 + "os": [ 807 + "linux" 808 + ] 809 + }, 810 + "node_modules/@rollup/rollup-linux-riscv64-gnu": { 811 + "version": "4.60.1", 812 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz", 813 + "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", 814 + "cpu": [ 815 + "riscv64" 816 + ], 817 + "dev": true, 818 + "license": "MIT", 819 + "optional": true, 820 + "os": [ 821 + "linux" 822 + ] 823 + }, 824 + "node_modules/@rollup/rollup-linux-riscv64-musl": { 825 + "version": "4.60.1", 826 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz", 827 + "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", 828 + "cpu": [ 829 + "riscv64" 830 + ], 831 + "dev": true, 832 + "license": "MIT", 833 + "optional": true, 834 + "os": [ 835 + "linux" 836 + ] 837 + }, 838 + "node_modules/@rollup/rollup-linux-s390x-gnu": { 839 + "version": "4.60.1", 840 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz", 841 + "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", 842 + "cpu": [ 843 + "s390x" 844 + ], 845 + "dev": true, 846 + "license": "MIT", 847 + "optional": true, 848 + "os": [ 849 + "linux" 850 + ] 851 + }, 852 + "node_modules/@rollup/rollup-linux-x64-gnu": { 853 + "version": "4.60.1", 854 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz", 855 + "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==", 856 + "cpu": [ 857 + "x64" 858 + ], 859 + "dev": true, 860 + "license": "MIT", 861 + "optional": true, 862 + "os": [ 863 + "linux" 864 + ] 865 + }, 866 + "node_modules/@rollup/rollup-linux-x64-musl": { 867 + "version": "4.60.1", 868 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz", 869 + "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", 870 + "cpu": [ 871 + "x64" 872 + ], 873 + "dev": true, 874 + "license": "MIT", 875 + "optional": true, 876 + "os": [ 877 + "linux" 878 + ] 879 + }, 880 + "node_modules/@rollup/rollup-openbsd-x64": { 881 + "version": "4.60.1", 882 + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz", 883 + "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", 884 + "cpu": [ 885 + "x64" 886 + ], 887 + "dev": true, 888 + "license": "MIT", 889 + "optional": true, 890 + "os": [ 891 + "openbsd" 892 + ] 893 + }, 894 + "node_modules/@rollup/rollup-openharmony-arm64": { 895 + "version": "4.60.1", 896 + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz", 897 + "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", 898 + "cpu": [ 899 + "arm64" 900 + ], 901 + "dev": true, 902 + "license": "MIT", 903 + "optional": true, 904 + "os": [ 905 + "openharmony" 906 + ] 907 + }, 908 + "node_modules/@rollup/rollup-win32-arm64-msvc": { 909 + "version": "4.60.1", 910 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz", 911 + "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", 912 + "cpu": [ 913 + "arm64" 914 + ], 915 + "dev": true, 916 + "license": "MIT", 917 + "optional": true, 918 + "os": [ 919 + "win32" 920 + ] 921 + }, 922 + "node_modules/@rollup/rollup-win32-ia32-msvc": { 923 + "version": "4.60.1", 924 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz", 925 + "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", 926 + "cpu": [ 927 + "ia32" 928 + ], 929 + "dev": true, 930 + "license": "MIT", 931 + "optional": true, 932 + "os": [ 933 + "win32" 934 + ] 935 + }, 936 + "node_modules/@rollup/rollup-win32-x64-gnu": { 937 + "version": "4.60.1", 938 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz", 939 + "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", 940 + "cpu": [ 941 + "x64" 942 + ], 943 + "dev": true, 944 + "license": "MIT", 945 + "optional": true, 946 + "os": [ 947 + "win32" 948 + ] 949 + }, 950 + "node_modules/@rollup/rollup-win32-x64-msvc": { 951 + "version": "4.60.1", 952 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz", 953 + "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", 954 + "cpu": [ 955 + "x64" 956 + ], 957 + "dev": true, 958 + "license": "MIT", 959 + "optional": true, 960 + "os": [ 961 + "win32" 962 + ] 963 + }, 964 + "node_modules/@types/estree": { 965 + "version": "1.0.8", 966 + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", 967 + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", 968 + "dev": true, 969 + "license": "MIT" 970 + }, 971 + "node_modules/@types/webidl-conversions": { 972 + "version": "7.0.3", 973 + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", 974 + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", 975 + "license": "MIT" 976 + }, 977 + "node_modules/@types/whatwg-url": { 978 + "version": "13.0.0", 979 + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-13.0.0.tgz", 980 + "integrity": "sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q==", 981 + "license": "MIT", 982 + "dependencies": { 983 + "@types/webidl-conversions": "*" 984 + } 985 + }, 986 + "node_modules/@vitejs/plugin-vue": { 987 + "version": "5.2.4", 988 + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", 989 + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", 990 + "dev": true, 991 + "license": "MIT", 992 + "engines": { 993 + "node": "^18.0.0 || >=20.0.0" 994 + }, 995 + "peerDependencies": { 996 + "vite": "^5.0.0 || ^6.0.0", 997 + "vue": "^3.2.25" 998 + } 999 + }, 1000 + "node_modules/@vue/compiler-core": { 1001 + "version": "3.5.32", 1002 + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.32.tgz", 1003 + "integrity": "sha512-4x74Tbtqnda8s/NSD6e1Dr5p1c8HdMU5RWSjMSUzb8RTcUQqevDCxVAitcLBKT+ie3o0Dl9crc/S/opJM7qBGQ==", 1004 + "license": "MIT", 1005 + "dependencies": { 1006 + "@babel/parser": "^7.29.2", 1007 + "@vue/shared": "3.5.32", 1008 + "entities": "^7.0.1", 1009 + "estree-walker": "^2.0.2", 1010 + "source-map-js": "^1.2.1" 1011 + } 1012 + }, 1013 + "node_modules/@vue/compiler-dom": { 1014 + "version": "3.5.32", 1015 + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.32.tgz", 1016 + "integrity": "sha512-ybHAu70NtiEI1fvAUz3oXZqkUYEe5J98GjMDpTGl5iHb0T15wQYLR4wE3h9xfuTNA+Cm2f4czfe8B4s+CCH57Q==", 1017 + "license": "MIT", 1018 + "dependencies": { 1019 + "@vue/compiler-core": "3.5.32", 1020 + "@vue/shared": "3.5.32" 1021 + } 1022 + }, 1023 + "node_modules/@vue/compiler-sfc": { 1024 + "version": "3.5.32", 1025 + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.32.tgz", 1026 + "integrity": "sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==", 1027 + "license": "MIT", 1028 + "dependencies": { 1029 + "@babel/parser": "^7.29.2", 1030 + "@vue/compiler-core": "3.5.32", 1031 + "@vue/compiler-dom": "3.5.32", 1032 + "@vue/compiler-ssr": "3.5.32", 1033 + "@vue/shared": "3.5.32", 1034 + "estree-walker": "^2.0.2", 1035 + "magic-string": "^0.30.21", 1036 + "postcss": "^8.5.8", 1037 + "source-map-js": "^1.2.1" 1038 + } 1039 + }, 1040 + "node_modules/@vue/compiler-ssr": { 1041 + "version": "3.5.32", 1042 + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.32.tgz", 1043 + "integrity": "sha512-Gp4gTs22T3DgRotZ8aA/6m2jMR+GMztvBXUBEUOYOcST+giyGWJ4WvFd7QLHBkzTxkfOt8IELKNdpzITLbA2rw==", 1044 + "license": "MIT", 1045 + "dependencies": { 1046 + "@vue/compiler-dom": "3.5.32", 1047 + "@vue/shared": "3.5.32" 1048 + } 1049 + }, 1050 + "node_modules/@vue/devtools-api": { 1051 + "version": "6.6.4", 1052 + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", 1053 + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", 1054 + "license": "MIT" 1055 + }, 1056 + "node_modules/@vue/reactivity": { 1057 + "version": "3.5.32", 1058 + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.32.tgz", 1059 + "integrity": "sha512-/ORasxSGvZ6MN5gc+uE364SxFdJ0+WqVG0CENXaGW58TOCdrAW76WWaplDtECeS1qphvtBZtR+3/o1g1zL4xPQ==", 1060 + "license": "MIT", 1061 + "dependencies": { 1062 + "@vue/shared": "3.5.32" 1063 + } 1064 + }, 1065 + "node_modules/@vue/runtime-core": { 1066 + "version": "3.5.32", 1067 + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.32.tgz", 1068 + "integrity": "sha512-pDrXCejn4UpFDFmMd27AcJEbHaLemaE5o4pbb7sLk79SRIhc6/t34BQA7SGNgYtbMnvbF/HHOftYBgFJtUoJUQ==", 1069 + "license": "MIT", 1070 + "dependencies": { 1071 + "@vue/reactivity": "3.5.32", 1072 + "@vue/shared": "3.5.32" 1073 + } 1074 + }, 1075 + "node_modules/@vue/runtime-dom": { 1076 + "version": "3.5.32", 1077 + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.32.tgz", 1078 + "integrity": "sha512-1CDVv7tv/IV13V8Nip1k/aaObVbWqRlVCVezTwx3K07p7Vxossp5JU1dcPNhJk3w347gonIUT9jQOGutyJrSVQ==", 1079 + "license": "MIT", 1080 + "dependencies": { 1081 + "@vue/reactivity": "3.5.32", 1082 + "@vue/runtime-core": "3.5.32", 1083 + "@vue/shared": "3.5.32", 1084 + "csstype": "^3.2.3" 1085 + } 1086 + }, 1087 + "node_modules/@vue/server-renderer": { 1088 + "version": "3.5.32", 1089 + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.32.tgz", 1090 + "integrity": "sha512-IOjm2+JQwRFS7W28HNuJeXQle9KdZbODFY7hFGVtnnghF51ta20EWAZJHX+zLGtsHhaU6uC9BGPV52KVpYryMQ==", 1091 + "license": "MIT", 1092 + "dependencies": { 1093 + "@vue/compiler-ssr": "3.5.32", 1094 + "@vue/shared": "3.5.32" 1095 + }, 1096 + "peerDependencies": { 1097 + "vue": "3.5.32" 1098 + } 1099 + }, 1100 + "node_modules/@vue/shared": { 1101 + "version": "3.5.32", 1102 + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.32.tgz", 1103 + "integrity": "sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg==", 1104 + "license": "MIT" 1105 + }, 1106 + "node_modules/accepts": { 1107 + "version": "1.3.8", 1108 + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 1109 + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 1110 + "license": "MIT", 1111 + "dependencies": { 1112 + "mime-types": "~2.1.34", 1113 + "negotiator": "0.6.3" 1114 + }, 1115 + "engines": { 1116 + "node": ">= 0.6" 1117 + } 1118 + }, 1119 + "node_modules/ansi-regex": { 1120 + "version": "5.0.1", 1121 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1122 + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1123 + "dev": true, 1124 + "license": "MIT", 1125 + "engines": { 1126 + "node": ">=8" 1127 + } 1128 + }, 1129 + "node_modules/ansi-styles": { 1130 + "version": "4.3.0", 1131 + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1132 + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1133 + "dev": true, 1134 + "license": "MIT", 1135 + "dependencies": { 1136 + "color-convert": "^2.0.1" 1137 + }, 1138 + "engines": { 1139 + "node": ">=8" 1140 + }, 1141 + "funding": { 1142 + "url": "https://github.com/chalk/ansi-styles?sponsor=1" 1143 + } 1144 + }, 1145 + "node_modules/any-promise": { 1146 + "version": "1.3.0", 1147 + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", 1148 + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", 1149 + "dev": true, 1150 + "license": "MIT" 1151 + }, 1152 + "node_modules/anymatch": { 1153 + "version": "3.1.3", 1154 + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 1155 + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 1156 + "dev": true, 1157 + "license": "ISC", 1158 + "dependencies": { 1159 + "normalize-path": "^3.0.0", 1160 + "picomatch": "^2.0.4" 1161 + }, 1162 + "engines": { 1163 + "node": ">= 8" 1164 + } 1165 + }, 1166 + "node_modules/arg": { 1167 + "version": "5.0.2", 1168 + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", 1169 + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", 1170 + "dev": true, 1171 + "license": "MIT" 1172 + }, 1173 + "node_modules/array-flatten": { 1174 + "version": "1.1.1", 1175 + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 1176 + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", 1177 + "license": "MIT" 1178 + }, 1179 + "node_modules/autoprefixer": { 1180 + "version": "10.5.0", 1181 + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", 1182 + "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", 1183 + "dev": true, 1184 + "funding": [ 1185 + { 1186 + "type": "opencollective", 1187 + "url": "https://opencollective.com/postcss/" 1188 + }, 1189 + { 1190 + "type": "tidelift", 1191 + "url": "https://tidelift.com/funding/github/npm/autoprefixer" 1192 + }, 1193 + { 1194 + "type": "github", 1195 + "url": "https://github.com/sponsors/ai" 1196 + } 1197 + ], 1198 + "license": "MIT", 1199 + "dependencies": { 1200 + "browserslist": "^4.28.2", 1201 + "caniuse-lite": "^1.0.30001787", 1202 + "fraction.js": "^5.3.4", 1203 + "picocolors": "^1.1.1", 1204 + "postcss-value-parser": "^4.2.0" 1205 + }, 1206 + "bin": { 1207 + "autoprefixer": "bin/autoprefixer" 1208 + }, 1209 + "engines": { 1210 + "node": "^10 || ^12 || >=14" 1211 + }, 1212 + "peerDependencies": { 1213 + "postcss": "^8.1.0" 1214 + } 1215 + }, 1216 + "node_modules/balanced-match": { 1217 + "version": "4.0.4", 1218 + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", 1219 + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", 1220 + "dev": true, 1221 + "license": "MIT", 1222 + "engines": { 1223 + "node": "18 || 20 || >=22" 1224 + } 1225 + }, 1226 + "node_modules/baseline-browser-mapping": { 1227 + "version": "2.10.19", 1228 + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.19.tgz", 1229 + "integrity": "sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==", 1230 + "dev": true, 1231 + "license": "Apache-2.0", 1232 + "bin": { 1233 + "baseline-browser-mapping": "dist/cli.cjs" 1234 + }, 1235 + "engines": { 1236 + "node": ">=6.0.0" 1237 + } 1238 + }, 1239 + "node_modules/binary-extensions": { 1240 + "version": "2.3.0", 1241 + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", 1242 + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", 1243 + "dev": true, 1244 + "license": "MIT", 1245 + "engines": { 1246 + "node": ">=8" 1247 + }, 1248 + "funding": { 1249 + "url": "https://github.com/sponsors/sindresorhus" 1250 + } 1251 + }, 1252 + "node_modules/body-parser": { 1253 + "version": "1.20.4", 1254 + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", 1255 + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", 1256 + "license": "MIT", 1257 + "dependencies": { 1258 + "bytes": "~3.1.2", 1259 + "content-type": "~1.0.5", 1260 + "debug": "2.6.9", 1261 + "depd": "2.0.0", 1262 + "destroy": "~1.2.0", 1263 + "http-errors": "~2.0.1", 1264 + "iconv-lite": "~0.4.24", 1265 + "on-finished": "~2.4.1", 1266 + "qs": "~6.14.0", 1267 + "raw-body": "~2.5.3", 1268 + "type-is": "~1.6.18", 1269 + "unpipe": "~1.0.0" 1270 + }, 1271 + "engines": { 1272 + "node": ">= 0.8", 1273 + "npm": "1.2.8000 || >= 1.4.16" 1274 + } 1275 + }, 1276 + "node_modules/brace-expansion": { 1277 + "version": "5.0.5", 1278 + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", 1279 + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", 1280 + "dev": true, 1281 + "license": "MIT", 1282 + "dependencies": { 1283 + "balanced-match": "^4.0.2" 1284 + }, 1285 + "engines": { 1286 + "node": "18 || 20 || >=22" 1287 + } 1288 + }, 1289 + "node_modules/braces": { 1290 + "version": "3.0.3", 1291 + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 1292 + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 1293 + "dev": true, 1294 + "license": "MIT", 1295 + "dependencies": { 1296 + "fill-range": "^7.1.1" 1297 + }, 1298 + "engines": { 1299 + "node": ">=8" 1300 + } 1301 + }, 1302 + "node_modules/browserslist": { 1303 + "version": "4.28.2", 1304 + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", 1305 + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", 1306 + "dev": true, 1307 + "funding": [ 1308 + { 1309 + "type": "opencollective", 1310 + "url": "https://opencollective.com/browserslist" 1311 + }, 1312 + { 1313 + "type": "tidelift", 1314 + "url": "https://tidelift.com/funding/github/npm/browserslist" 1315 + }, 1316 + { 1317 + "type": "github", 1318 + "url": "https://github.com/sponsors/ai" 1319 + } 1320 + ], 1321 + "license": "MIT", 1322 + "peer": true, 1323 + "dependencies": { 1324 + "baseline-browser-mapping": "^2.10.12", 1325 + "caniuse-lite": "^1.0.30001782", 1326 + "electron-to-chromium": "^1.5.328", 1327 + "node-releases": "^2.0.36", 1328 + "update-browserslist-db": "^1.2.3" 1329 + }, 1330 + "bin": { 1331 + "browserslist": "cli.js" 1332 + }, 1333 + "engines": { 1334 + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" 1335 + } 1336 + }, 1337 + "node_modules/bson": { 1338 + "version": "7.2.0", 1339 + "resolved": "https://registry.npmjs.org/bson/-/bson-7.2.0.tgz", 1340 + "integrity": "sha512-YCEo7KjMlbNlyHhz7zAZNDpIpQbd+wOEHJYezv0nMYTn4x31eIUM2yomNNubclAt63dObUzKHWsBLJ9QcZNSnQ==", 1341 + "license": "Apache-2.0", 1342 + "engines": { 1343 + "node": ">=20.19.0" 1344 + } 1345 + }, 1346 + "node_modules/bytes": { 1347 + "version": "3.1.2", 1348 + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 1349 + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 1350 + "license": "MIT", 1351 + "engines": { 1352 + "node": ">= 0.8" 1353 + } 1354 + }, 1355 + "node_modules/call-bind-apply-helpers": { 1356 + "version": "1.0.2", 1357 + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", 1358 + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", 1359 + "license": "MIT", 1360 + "dependencies": { 1361 + "es-errors": "^1.3.0", 1362 + "function-bind": "^1.1.2" 1363 + }, 1364 + "engines": { 1365 + "node": ">= 0.4" 1366 + } 1367 + }, 1368 + "node_modules/call-bound": { 1369 + "version": "1.0.4", 1370 + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", 1371 + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", 1372 + "license": "MIT", 1373 + "dependencies": { 1374 + "call-bind-apply-helpers": "^1.0.2", 1375 + "get-intrinsic": "^1.3.0" 1376 + }, 1377 + "engines": { 1378 + "node": ">= 0.4" 1379 + }, 1380 + "funding": { 1381 + "url": "https://github.com/sponsors/ljharb" 1382 + } 1383 + }, 1384 + "node_modules/camelcase-css": { 1385 + "version": "2.0.1", 1386 + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", 1387 + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", 1388 + "dev": true, 1389 + "license": "MIT", 1390 + "engines": { 1391 + "node": ">= 6" 1392 + } 1393 + }, 1394 + "node_modules/caniuse-lite": { 1395 + "version": "1.0.30001788", 1396 + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001788.tgz", 1397 + "integrity": "sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==", 1398 + "dev": true, 1399 + "funding": [ 1400 + { 1401 + "type": "opencollective", 1402 + "url": "https://opencollective.com/browserslist" 1403 + }, 1404 + { 1405 + "type": "tidelift", 1406 + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" 1407 + }, 1408 + { 1409 + "type": "github", 1410 + "url": "https://github.com/sponsors/ai" 1411 + } 1412 + ], 1413 + "license": "CC-BY-4.0" 1414 + }, 1415 + "node_modules/chalk": { 1416 + "version": "4.1.2", 1417 + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 1418 + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 1419 + "dev": true, 1420 + "license": "MIT", 1421 + "dependencies": { 1422 + "ansi-styles": "^4.1.0", 1423 + "supports-color": "^7.1.0" 1424 + }, 1425 + "engines": { 1426 + "node": ">=10" 1427 + }, 1428 + "funding": { 1429 + "url": "https://github.com/chalk/chalk?sponsor=1" 1430 + } 1431 + }, 1432 + "node_modules/chalk/node_modules/supports-color": { 1433 + "version": "7.2.0", 1434 + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1435 + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1436 + "dev": true, 1437 + "license": "MIT", 1438 + "dependencies": { 1439 + "has-flag": "^4.0.0" 1440 + }, 1441 + "engines": { 1442 + "node": ">=8" 1443 + } 1444 + }, 1445 + "node_modules/chokidar": { 1446 + "version": "3.6.0", 1447 + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", 1448 + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", 1449 + "dev": true, 1450 + "license": "MIT", 1451 + "dependencies": { 1452 + "anymatch": "~3.1.2", 1453 + "braces": "~3.0.2", 1454 + "glob-parent": "~5.1.2", 1455 + "is-binary-path": "~2.1.0", 1456 + "is-glob": "~4.0.1", 1457 + "normalize-path": "~3.0.0", 1458 + "readdirp": "~3.6.0" 1459 + }, 1460 + "engines": { 1461 + "node": ">= 8.10.0" 1462 + }, 1463 + "funding": { 1464 + "url": "https://paulmillr.com/funding/" 1465 + }, 1466 + "optionalDependencies": { 1467 + "fsevents": "~2.3.2" 1468 + } 1469 + }, 1470 + "node_modules/cliui": { 1471 + "version": "8.0.1", 1472 + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", 1473 + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", 1474 + "dev": true, 1475 + "license": "ISC", 1476 + "dependencies": { 1477 + "string-width": "^4.2.0", 1478 + "strip-ansi": "^6.0.1", 1479 + "wrap-ansi": "^7.0.0" 1480 + }, 1481 + "engines": { 1482 + "node": ">=12" 1483 + } 1484 + }, 1485 + "node_modules/color-convert": { 1486 + "version": "2.0.1", 1487 + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1488 + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1489 + "dev": true, 1490 + "license": "MIT", 1491 + "dependencies": { 1492 + "color-name": "~1.1.4" 1493 + }, 1494 + "engines": { 1495 + "node": ">=7.0.0" 1496 + } 1497 + }, 1498 + "node_modules/color-name": { 1499 + "version": "1.1.4", 1500 + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1501 + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1502 + "dev": true, 1503 + "license": "MIT" 1504 + }, 1505 + "node_modules/commander": { 1506 + "version": "4.1.1", 1507 + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", 1508 + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", 1509 + "dev": true, 1510 + "license": "MIT", 1511 + "engines": { 1512 + "node": ">= 6" 1513 + } 1514 + }, 1515 + "node_modules/concurrently": { 1516 + "version": "9.2.1", 1517 + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz", 1518 + "integrity": "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==", 1519 + "dev": true, 1520 + "license": "MIT", 1521 + "dependencies": { 1522 + "chalk": "4.1.2", 1523 + "rxjs": "7.8.2", 1524 + "shell-quote": "1.8.3", 1525 + "supports-color": "8.1.1", 1526 + "tree-kill": "1.2.2", 1527 + "yargs": "17.7.2" 1528 + }, 1529 + "bin": { 1530 + "conc": "dist/bin/concurrently.js", 1531 + "concurrently": "dist/bin/concurrently.js" 1532 + }, 1533 + "engines": { 1534 + "node": ">=18" 1535 + }, 1536 + "funding": { 1537 + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" 1538 + } 1539 + }, 1540 + "node_modules/content-disposition": { 1541 + "version": "0.5.4", 1542 + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 1543 + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 1544 + "license": "MIT", 1545 + "dependencies": { 1546 + "safe-buffer": "5.2.1" 1547 + }, 1548 + "engines": { 1549 + "node": ">= 0.6" 1550 + } 1551 + }, 1552 + "node_modules/content-type": { 1553 + "version": "1.0.5", 1554 + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 1555 + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 1556 + "license": "MIT", 1557 + "engines": { 1558 + "node": ">= 0.6" 1559 + } 1560 + }, 1561 + "node_modules/cookie": { 1562 + "version": "0.7.2", 1563 + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", 1564 + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", 1565 + "license": "MIT", 1566 + "engines": { 1567 + "node": ">= 0.6" 1568 + } 1569 + }, 1570 + "node_modules/cookie-signature": { 1571 + "version": "1.0.7", 1572 + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", 1573 + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", 1574 + "license": "MIT" 1575 + }, 1576 + "node_modules/cors": { 1577 + "version": "2.8.6", 1578 + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", 1579 + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", 1580 + "license": "MIT", 1581 + "dependencies": { 1582 + "object-assign": "^4", 1583 + "vary": "^1" 1584 + }, 1585 + "engines": { 1586 + "node": ">= 0.10" 1587 + }, 1588 + "funding": { 1589 + "type": "opencollective", 1590 + "url": "https://opencollective.com/express" 1591 + } 1592 + }, 1593 + "node_modules/cssesc": { 1594 + "version": "3.0.0", 1595 + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", 1596 + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", 1597 + "dev": true, 1598 + "license": "MIT", 1599 + "bin": { 1600 + "cssesc": "bin/cssesc" 1601 + }, 1602 + "engines": { 1603 + "node": ">=4" 1604 + } 1605 + }, 1606 + "node_modules/csstype": { 1607 + "version": "3.2.3", 1608 + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", 1609 + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", 1610 + "license": "MIT" 1611 + }, 1612 + "node_modules/debug": { 1613 + "version": "2.6.9", 1614 + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1615 + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1616 + "license": "MIT", 1617 + "dependencies": { 1618 + "ms": "2.0.0" 1619 + } 1620 + }, 1621 + "node_modules/depd": { 1622 + "version": "2.0.0", 1623 + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 1624 + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 1625 + "license": "MIT", 1626 + "engines": { 1627 + "node": ">= 0.8" 1628 + } 1629 + }, 1630 + "node_modules/destroy": { 1631 + "version": "1.2.0", 1632 + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 1633 + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 1634 + "license": "MIT", 1635 + "engines": { 1636 + "node": ">= 0.8", 1637 + "npm": "1.2.8000 || >= 1.4.16" 1638 + } 1639 + }, 1640 + "node_modules/didyoumean": { 1641 + "version": "1.2.2", 1642 + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", 1643 + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", 1644 + "dev": true, 1645 + "license": "Apache-2.0" 1646 + }, 1647 + "node_modules/dlv": { 1648 + "version": "1.1.3", 1649 + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", 1650 + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", 1651 + "dev": true, 1652 + "license": "MIT" 1653 + }, 1654 + "node_modules/dunder-proto": { 1655 + "version": "1.0.1", 1656 + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 1657 + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 1658 + "license": "MIT", 1659 + "dependencies": { 1660 + "call-bind-apply-helpers": "^1.0.1", 1661 + "es-errors": "^1.3.0", 1662 + "gopd": "^1.2.0" 1663 + }, 1664 + "engines": { 1665 + "node": ">= 0.4" 1666 + } 1667 + }, 1668 + "node_modules/ee-first": { 1669 + "version": "1.1.1", 1670 + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 1671 + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", 1672 + "license": "MIT" 1673 + }, 1674 + "node_modules/electron-to-chromium": { 1675 + "version": "1.5.336", 1676 + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.336.tgz", 1677 + "integrity": "sha512-AbH9q9J455r/nLmdNZes0G0ZKcRX73FicwowalLs6ijwOmCJSRRrLX63lcAlzy9ux3dWK1w1+1nsBJEWN11hcQ==", 1678 + "dev": true, 1679 + "license": "ISC" 1680 + }, 1681 + "node_modules/emoji-regex": { 1682 + "version": "8.0.0", 1683 + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1684 + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1685 + "dev": true, 1686 + "license": "MIT" 1687 + }, 1688 + "node_modules/encodeurl": { 1689 + "version": "2.0.0", 1690 + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 1691 + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 1692 + "license": "MIT", 1693 + "engines": { 1694 + "node": ">= 0.8" 1695 + } 1696 + }, 1697 + "node_modules/entities": { 1698 + "version": "7.0.1", 1699 + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", 1700 + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", 1701 + "license": "BSD-2-Clause", 1702 + "engines": { 1703 + "node": ">=0.12" 1704 + }, 1705 + "funding": { 1706 + "url": "https://github.com/fb55/entities?sponsor=1" 1707 + } 1708 + }, 1709 + "node_modules/es-define-property": { 1710 + "version": "1.0.1", 1711 + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 1712 + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 1713 + "license": "MIT", 1714 + "engines": { 1715 + "node": ">= 0.4" 1716 + } 1717 + }, 1718 + "node_modules/es-errors": { 1719 + "version": "1.3.0", 1720 + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 1721 + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 1722 + "license": "MIT", 1723 + "engines": { 1724 + "node": ">= 0.4" 1725 + } 1726 + }, 1727 + "node_modules/es-object-atoms": { 1728 + "version": "1.1.1", 1729 + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", 1730 + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", 1731 + "license": "MIT", 1732 + "dependencies": { 1733 + "es-errors": "^1.3.0" 1734 + }, 1735 + "engines": { 1736 + "node": ">= 0.4" 1737 + } 1738 + }, 1739 + "node_modules/esbuild": { 1740 + "version": "0.25.12", 1741 + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", 1742 + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", 1743 + "dev": true, 1744 + "hasInstallScript": true, 1745 + "license": "MIT", 1746 + "bin": { 1747 + "esbuild": "bin/esbuild" 1748 + }, 1749 + "engines": { 1750 + "node": ">=18" 1751 + }, 1752 + "optionalDependencies": { 1753 + "@esbuild/aix-ppc64": "0.25.12", 1754 + "@esbuild/android-arm": "0.25.12", 1755 + "@esbuild/android-arm64": "0.25.12", 1756 + "@esbuild/android-x64": "0.25.12", 1757 + "@esbuild/darwin-arm64": "0.25.12", 1758 + "@esbuild/darwin-x64": "0.25.12", 1759 + "@esbuild/freebsd-arm64": "0.25.12", 1760 + "@esbuild/freebsd-x64": "0.25.12", 1761 + "@esbuild/linux-arm": "0.25.12", 1762 + "@esbuild/linux-arm64": "0.25.12", 1763 + "@esbuild/linux-ia32": "0.25.12", 1764 + "@esbuild/linux-loong64": "0.25.12", 1765 + "@esbuild/linux-mips64el": "0.25.12", 1766 + "@esbuild/linux-ppc64": "0.25.12", 1767 + "@esbuild/linux-riscv64": "0.25.12", 1768 + "@esbuild/linux-s390x": "0.25.12", 1769 + "@esbuild/linux-x64": "0.25.12", 1770 + "@esbuild/netbsd-arm64": "0.25.12", 1771 + "@esbuild/netbsd-x64": "0.25.12", 1772 + "@esbuild/openbsd-arm64": "0.25.12", 1773 + "@esbuild/openbsd-x64": "0.25.12", 1774 + "@esbuild/openharmony-arm64": "0.25.12", 1775 + "@esbuild/sunos-x64": "0.25.12", 1776 + "@esbuild/win32-arm64": "0.25.12", 1777 + "@esbuild/win32-ia32": "0.25.12", 1778 + "@esbuild/win32-x64": "0.25.12" 1779 + } 1780 + }, 1781 + "node_modules/escalade": { 1782 + "version": "3.2.0", 1783 + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", 1784 + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", 1785 + "dev": true, 1786 + "license": "MIT", 1787 + "engines": { 1788 + "node": ">=6" 1789 + } 1790 + }, 1791 + "node_modules/escape-html": { 1792 + "version": "1.0.3", 1793 + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 1794 + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", 1795 + "license": "MIT" 1796 + }, 1797 + "node_modules/estree-walker": { 1798 + "version": "2.0.2", 1799 + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", 1800 + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", 1801 + "license": "MIT" 1802 + }, 1803 + "node_modules/etag": { 1804 + "version": "1.8.1", 1805 + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 1806 + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 1807 + "license": "MIT", 1808 + "engines": { 1809 + "node": ">= 0.6" 1810 + } 1811 + }, 1812 + "node_modules/express": { 1813 + "version": "4.22.1", 1814 + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", 1815 + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", 1816 + "license": "MIT", 1817 + "dependencies": { 1818 + "accepts": "~1.3.8", 1819 + "array-flatten": "1.1.1", 1820 + "body-parser": "~1.20.3", 1821 + "content-disposition": "~0.5.4", 1822 + "content-type": "~1.0.4", 1823 + "cookie": "~0.7.1", 1824 + "cookie-signature": "~1.0.6", 1825 + "debug": "2.6.9", 1826 + "depd": "2.0.0", 1827 + "encodeurl": "~2.0.0", 1828 + "escape-html": "~1.0.3", 1829 + "etag": "~1.8.1", 1830 + "finalhandler": "~1.3.1", 1831 + "fresh": "~0.5.2", 1832 + "http-errors": "~2.0.0", 1833 + "merge-descriptors": "1.0.3", 1834 + "methods": "~1.1.2", 1835 + "on-finished": "~2.4.1", 1836 + "parseurl": "~1.3.3", 1837 + "path-to-regexp": "~0.1.12", 1838 + "proxy-addr": "~2.0.7", 1839 + "qs": "~6.14.0", 1840 + "range-parser": "~1.2.1", 1841 + "safe-buffer": "5.2.1", 1842 + "send": "~0.19.0", 1843 + "serve-static": "~1.16.2", 1844 + "setprototypeof": "1.2.0", 1845 + "statuses": "~2.0.1", 1846 + "type-is": "~1.6.18", 1847 + "utils-merge": "1.0.1", 1848 + "vary": "~1.1.2" 1849 + }, 1850 + "engines": { 1851 + "node": ">= 0.10.0" 1852 + }, 1853 + "funding": { 1854 + "type": "opencollective", 1855 + "url": "https://opencollective.com/express" 1856 + } 1857 + }, 1858 + "node_modules/fast-glob": { 1859 + "version": "3.3.3", 1860 + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", 1861 + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", 1862 + "dev": true, 1863 + "license": "MIT", 1864 + "dependencies": { 1865 + "@nodelib/fs.stat": "^2.0.2", 1866 + "@nodelib/fs.walk": "^1.2.3", 1867 + "glob-parent": "^5.1.2", 1868 + "merge2": "^1.3.0", 1869 + "micromatch": "^4.0.8" 1870 + }, 1871 + "engines": { 1872 + "node": ">=8.6.0" 1873 + } 1874 + }, 1875 + "node_modules/fastq": { 1876 + "version": "1.20.1", 1877 + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", 1878 + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", 1879 + "dev": true, 1880 + "license": "ISC", 1881 + "dependencies": { 1882 + "reusify": "^1.0.4" 1883 + } 1884 + }, 1885 + "node_modules/fill-range": { 1886 + "version": "7.1.1", 1887 + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 1888 + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 1889 + "dev": true, 1890 + "license": "MIT", 1891 + "dependencies": { 1892 + "to-regex-range": "^5.0.1" 1893 + }, 1894 + "engines": { 1895 + "node": ">=8" 1896 + } 1897 + }, 1898 + "node_modules/finalhandler": { 1899 + "version": "1.3.2", 1900 + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", 1901 + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", 1902 + "license": "MIT", 1903 + "dependencies": { 1904 + "debug": "2.6.9", 1905 + "encodeurl": "~2.0.0", 1906 + "escape-html": "~1.0.3", 1907 + "on-finished": "~2.4.1", 1908 + "parseurl": "~1.3.3", 1909 + "statuses": "~2.0.2", 1910 + "unpipe": "~1.0.0" 1911 + }, 1912 + "engines": { 1913 + "node": ">= 0.8" 1914 + } 1915 + }, 1916 + "node_modules/forwarded": { 1917 + "version": "0.2.0", 1918 + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 1919 + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 1920 + "license": "MIT", 1921 + "engines": { 1922 + "node": ">= 0.6" 1923 + } 1924 + }, 1925 + "node_modules/fraction.js": { 1926 + "version": "5.3.4", 1927 + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", 1928 + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", 1929 + "dev": true, 1930 + "license": "MIT", 1931 + "engines": { 1932 + "node": "*" 1933 + }, 1934 + "funding": { 1935 + "type": "github", 1936 + "url": "https://github.com/sponsors/rawify" 1937 + } 1938 + }, 1939 + "node_modules/fresh": { 1940 + "version": "0.5.2", 1941 + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 1942 + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 1943 + "license": "MIT", 1944 + "engines": { 1945 + "node": ">= 0.6" 1946 + } 1947 + }, 1948 + "node_modules/fsevents": { 1949 + "version": "2.3.3", 1950 + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1951 + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1952 + "dev": true, 1953 + "hasInstallScript": true, 1954 + "license": "MIT", 1955 + "optional": true, 1956 + "os": [ 1957 + "darwin" 1958 + ], 1959 + "engines": { 1960 + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1961 + } 1962 + }, 1963 + "node_modules/function-bind": { 1964 + "version": "1.1.2", 1965 + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 1966 + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 1967 + "license": "MIT", 1968 + "funding": { 1969 + "url": "https://github.com/sponsors/ljharb" 1970 + } 1971 + }, 1972 + "node_modules/get-caller-file": { 1973 + "version": "2.0.5", 1974 + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 1975 + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 1976 + "dev": true, 1977 + "license": "ISC", 1978 + "engines": { 1979 + "node": "6.* || 8.* || >= 10.*" 1980 + } 1981 + }, 1982 + "node_modules/get-intrinsic": { 1983 + "version": "1.3.0", 1984 + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", 1985 + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", 1986 + "license": "MIT", 1987 + "dependencies": { 1988 + "call-bind-apply-helpers": "^1.0.2", 1989 + "es-define-property": "^1.0.1", 1990 + "es-errors": "^1.3.0", 1991 + "es-object-atoms": "^1.1.1", 1992 + "function-bind": "^1.1.2", 1993 + "get-proto": "^1.0.1", 1994 + "gopd": "^1.2.0", 1995 + "has-symbols": "^1.1.0", 1996 + "hasown": "^2.0.2", 1997 + "math-intrinsics": "^1.1.0" 1998 + }, 1999 + "engines": { 2000 + "node": ">= 0.4" 2001 + }, 2002 + "funding": { 2003 + "url": "https://github.com/sponsors/ljharb" 2004 + } 2005 + }, 2006 + "node_modules/get-proto": { 2007 + "version": "1.0.1", 2008 + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", 2009 + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", 2010 + "license": "MIT", 2011 + "dependencies": { 2012 + "dunder-proto": "^1.0.1", 2013 + "es-object-atoms": "^1.0.0" 2014 + }, 2015 + "engines": { 2016 + "node": ">= 0.4" 2017 + } 2018 + }, 2019 + "node_modules/glob-parent": { 2020 + "version": "5.1.2", 2021 + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 2022 + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 2023 + "dev": true, 2024 + "license": "ISC", 2025 + "dependencies": { 2026 + "is-glob": "^4.0.1" 2027 + }, 2028 + "engines": { 2029 + "node": ">= 6" 2030 + } 2031 + }, 2032 + "node_modules/gopd": { 2033 + "version": "1.2.0", 2034 + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 2035 + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 2036 + "license": "MIT", 2037 + "engines": { 2038 + "node": ">= 0.4" 2039 + }, 2040 + "funding": { 2041 + "url": "https://github.com/sponsors/ljharb" 2042 + } 2043 + }, 2044 + "node_modules/has-flag": { 2045 + "version": "4.0.0", 2046 + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 2047 + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 2048 + "dev": true, 2049 + "license": "MIT", 2050 + "engines": { 2051 + "node": ">=8" 2052 + } 2053 + }, 2054 + "node_modules/has-symbols": { 2055 + "version": "1.1.0", 2056 + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 2057 + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 2058 + "license": "MIT", 2059 + "engines": { 2060 + "node": ">= 0.4" 2061 + }, 2062 + "funding": { 2063 + "url": "https://github.com/sponsors/ljharb" 2064 + } 2065 + }, 2066 + "node_modules/hasown": { 2067 + "version": "2.0.2", 2068 + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 2069 + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 2070 + "license": "MIT", 2071 + "dependencies": { 2072 + "function-bind": "^1.1.2" 2073 + }, 2074 + "engines": { 2075 + "node": ">= 0.4" 2076 + } 2077 + }, 2078 + "node_modules/http-errors": { 2079 + "version": "2.0.1", 2080 + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", 2081 + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", 2082 + "license": "MIT", 2083 + "dependencies": { 2084 + "depd": "~2.0.0", 2085 + "inherits": "~2.0.4", 2086 + "setprototypeof": "~1.2.0", 2087 + "statuses": "~2.0.2", 2088 + "toidentifier": "~1.0.1" 2089 + }, 2090 + "engines": { 2091 + "node": ">= 0.8" 2092 + }, 2093 + "funding": { 2094 + "type": "opencollective", 2095 + "url": "https://opencollective.com/express" 2096 + } 2097 + }, 2098 + "node_modules/iconv-lite": { 2099 + "version": "0.4.24", 2100 + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 2101 + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 2102 + "license": "MIT", 2103 + "dependencies": { 2104 + "safer-buffer": ">= 2.1.2 < 3" 2105 + }, 2106 + "engines": { 2107 + "node": ">=0.10.0" 2108 + } 2109 + }, 2110 + "node_modules/ignore-by-default": { 2111 + "version": "1.0.1", 2112 + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 2113 + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", 2114 + "dev": true, 2115 + "license": "ISC" 2116 + }, 2117 + "node_modules/inherits": { 2118 + "version": "2.0.4", 2119 + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 2120 + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 2121 + "license": "ISC" 2122 + }, 2123 + "node_modules/ipaddr.js": { 2124 + "version": "1.9.1", 2125 + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 2126 + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 2127 + "license": "MIT", 2128 + "engines": { 2129 + "node": ">= 0.10" 2130 + } 2131 + }, 2132 + "node_modules/is-binary-path": { 2133 + "version": "2.1.0", 2134 + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 2135 + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 2136 + "dev": true, 2137 + "license": "MIT", 2138 + "dependencies": { 2139 + "binary-extensions": "^2.0.0" 2140 + }, 2141 + "engines": { 2142 + "node": ">=8" 2143 + } 2144 + }, 2145 + "node_modules/is-core-module": { 2146 + "version": "2.16.1", 2147 + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", 2148 + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", 2149 + "dev": true, 2150 + "license": "MIT", 2151 + "dependencies": { 2152 + "hasown": "^2.0.2" 2153 + }, 2154 + "engines": { 2155 + "node": ">= 0.4" 2156 + }, 2157 + "funding": { 2158 + "url": "https://github.com/sponsors/ljharb" 2159 + } 2160 + }, 2161 + "node_modules/is-extglob": { 2162 + "version": "2.1.1", 2163 + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 2164 + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 2165 + "dev": true, 2166 + "license": "MIT", 2167 + "engines": { 2168 + "node": ">=0.10.0" 2169 + } 2170 + }, 2171 + "node_modules/is-fullwidth-code-point": { 2172 + "version": "3.0.0", 2173 + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 2174 + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 2175 + "dev": true, 2176 + "license": "MIT", 2177 + "engines": { 2178 + "node": ">=8" 2179 + } 2180 + }, 2181 + "node_modules/is-glob": { 2182 + "version": "4.0.3", 2183 + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 2184 + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 2185 + "dev": true, 2186 + "license": "MIT", 2187 + "dependencies": { 2188 + "is-extglob": "^2.1.1" 2189 + }, 2190 + "engines": { 2191 + "node": ">=0.10.0" 2192 + } 2193 + }, 2194 + "node_modules/is-number": { 2195 + "version": "7.0.0", 2196 + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 2197 + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 2198 + "dev": true, 2199 + "license": "MIT", 2200 + "engines": { 2201 + "node": ">=0.12.0" 2202 + } 2203 + }, 2204 + "node_modules/jiti": { 2205 + "version": "1.21.7", 2206 + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", 2207 + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", 2208 + "dev": true, 2209 + "license": "MIT", 2210 + "peer": true, 2211 + "bin": { 2212 + "jiti": "bin/jiti.js" 2213 + } 2214 + }, 2215 + "node_modules/kareem": { 2216 + "version": "3.2.0", 2217 + "resolved": "https://registry.npmjs.org/kareem/-/kareem-3.2.0.tgz", 2218 + "integrity": "sha512-VS8MWZz/cT+SqBCpVfNN4zoVz5VskR3N4+sTmUXme55e9avQHntpwpNq0yjnosISXqwJ3AQVjlbI4Dyzv//JtA==", 2219 + "license": "Apache-2.0", 2220 + "engines": { 2221 + "node": ">=18.0.0" 2222 + } 2223 + }, 2224 + "node_modules/lilconfig": { 2225 + "version": "3.1.3", 2226 + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", 2227 + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", 2228 + "dev": true, 2229 + "license": "MIT", 2230 + "engines": { 2231 + "node": ">=14" 2232 + }, 2233 + "funding": { 2234 + "url": "https://github.com/sponsors/antonk52" 2235 + } 2236 + }, 2237 + "node_modules/lines-and-columns": { 2238 + "version": "1.2.4", 2239 + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", 2240 + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", 2241 + "dev": true, 2242 + "license": "MIT" 2243 + }, 2244 + "node_modules/magic-string": { 2245 + "version": "0.30.21", 2246 + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", 2247 + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", 2248 + "license": "MIT", 2249 + "dependencies": { 2250 + "@jridgewell/sourcemap-codec": "^1.5.5" 2251 + } 2252 + }, 2253 + "node_modules/math-intrinsics": { 2254 + "version": "1.1.0", 2255 + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 2256 + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 2257 + "license": "MIT", 2258 + "engines": { 2259 + "node": ">= 0.4" 2260 + } 2261 + }, 2262 + "node_modules/media-typer": { 2263 + "version": "0.3.0", 2264 + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 2265 + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 2266 + "license": "MIT", 2267 + "engines": { 2268 + "node": ">= 0.6" 2269 + } 2270 + }, 2271 + "node_modules/memory-pager": { 2272 + "version": "1.5.0", 2273 + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", 2274 + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", 2275 + "license": "MIT" 2276 + }, 2277 + "node_modules/merge-descriptors": { 2278 + "version": "1.0.3", 2279 + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", 2280 + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", 2281 + "license": "MIT", 2282 + "funding": { 2283 + "url": "https://github.com/sponsors/sindresorhus" 2284 + } 2285 + }, 2286 + "node_modules/merge2": { 2287 + "version": "1.4.1", 2288 + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 2289 + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 2290 + "dev": true, 2291 + "license": "MIT", 2292 + "engines": { 2293 + "node": ">= 8" 2294 + } 2295 + }, 2296 + "node_modules/methods": { 2297 + "version": "1.1.2", 2298 + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 2299 + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 2300 + "license": "MIT", 2301 + "engines": { 2302 + "node": ">= 0.6" 2303 + } 2304 + }, 2305 + "node_modules/micromatch": { 2306 + "version": "4.0.8", 2307 + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", 2308 + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", 2309 + "dev": true, 2310 + "license": "MIT", 2311 + "dependencies": { 2312 + "braces": "^3.0.3", 2313 + "picomatch": "^2.3.1" 2314 + }, 2315 + "engines": { 2316 + "node": ">=8.6" 2317 + } 2318 + }, 2319 + "node_modules/mime": { 2320 + "version": "1.6.0", 2321 + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 2322 + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 2323 + "license": "MIT", 2324 + "bin": { 2325 + "mime": "cli.js" 2326 + }, 2327 + "engines": { 2328 + "node": ">=4" 2329 + } 2330 + }, 2331 + "node_modules/mime-db": { 2332 + "version": "1.52.0", 2333 + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 2334 + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 2335 + "license": "MIT", 2336 + "engines": { 2337 + "node": ">= 0.6" 2338 + } 2339 + }, 2340 + "node_modules/mime-types": { 2341 + "version": "2.1.35", 2342 + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 2343 + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 2344 + "license": "MIT", 2345 + "dependencies": { 2346 + "mime-db": "1.52.0" 2347 + }, 2348 + "engines": { 2349 + "node": ">= 0.6" 2350 + } 2351 + }, 2352 + "node_modules/minimatch": { 2353 + "version": "10.2.5", 2354 + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", 2355 + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", 2356 + "dev": true, 2357 + "license": "BlueOak-1.0.0", 2358 + "dependencies": { 2359 + "brace-expansion": "^5.0.5" 2360 + }, 2361 + "engines": { 2362 + "node": "18 || 20 || >=22" 2363 + }, 2364 + "funding": { 2365 + "url": "https://github.com/sponsors/isaacs" 2366 + } 2367 + }, 2368 + "node_modules/mongodb": { 2369 + "version": "7.1.1", 2370 + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-7.1.1.tgz", 2371 + "integrity": "sha512-067DXiMjcpYQl6bGjWQoTUEE9UoRViTtKFcoqX7z08I+iDZv/emH1g8XEFiO3qiDfXAheT5ozl1VffDTKhIW/w==", 2372 + "license": "Apache-2.0", 2373 + "dependencies": { 2374 + "@mongodb-js/saslprep": "^1.3.0", 2375 + "bson": "^7.1.1", 2376 + "mongodb-connection-string-url": "^7.0.0" 2377 + }, 2378 + "engines": { 2379 + "node": ">=20.19.0" 2380 + }, 2381 + "peerDependencies": { 2382 + "@aws-sdk/credential-providers": "^3.806.0", 2383 + "@mongodb-js/zstd": "^7.0.0", 2384 + "gcp-metadata": "^7.0.1", 2385 + "kerberos": "^7.0.0", 2386 + "mongodb-client-encryption": ">=7.0.0 <7.1.0", 2387 + "snappy": "^7.3.2", 2388 + "socks": "^2.8.6" 2389 + }, 2390 + "peerDependenciesMeta": { 2391 + "@aws-sdk/credential-providers": { 2392 + "optional": true 2393 + }, 2394 + "@mongodb-js/zstd": { 2395 + "optional": true 2396 + }, 2397 + "gcp-metadata": { 2398 + "optional": true 2399 + }, 2400 + "kerberos": { 2401 + "optional": true 2402 + }, 2403 + "mongodb-client-encryption": { 2404 + "optional": true 2405 + }, 2406 + "snappy": { 2407 + "optional": true 2408 + }, 2409 + "socks": { 2410 + "optional": true 2411 + } 2412 + } 2413 + }, 2414 + "node_modules/mongodb-connection-string-url": { 2415 + "version": "7.0.1", 2416 + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-7.0.1.tgz", 2417 + "integrity": "sha512-h0AZ9A7IDVwwHyMxmdMXKy+9oNlF0zFoahHiX3vQ8e3KFcSP3VmsmfvtRSuLPxmyv2vjIDxqty8smTgie/SNRQ==", 2418 + "license": "Apache-2.0", 2419 + "dependencies": { 2420 + "@types/whatwg-url": "^13.0.0", 2421 + "whatwg-url": "^14.1.0" 2422 + }, 2423 + "engines": { 2424 + "node": ">=20.19.0" 2425 + } 2426 + }, 2427 + "node_modules/mongoose": { 2428 + "version": "9.4.1", 2429 + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-9.4.1.tgz", 2430 + "integrity": "sha512-4rFBWa+/wdBQSfvnOPJBpiSG6UCEbhSQh865dEdaH9Y8WfHBUC+I2XT28dp0IBIGrEwmh+gzrgZgea5PbmrHWA==", 2431 + "license": "MIT", 2432 + "dependencies": { 2433 + "kareem": "3.2.0", 2434 + "mongodb": "~7.1", 2435 + "mpath": "0.9.0", 2436 + "mquery": "6.0.0", 2437 + "ms": "2.1.3", 2438 + "sift": "17.1.3" 2439 + }, 2440 + "engines": { 2441 + "node": ">=20.19.0" 2442 + }, 2443 + "funding": { 2444 + "type": "opencollective", 2445 + "url": "https://opencollective.com/mongoose" 2446 + } 2447 + }, 2448 + "node_modules/mongoose/node_modules/ms": { 2449 + "version": "2.1.3", 2450 + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 2451 + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 2452 + "license": "MIT" 2453 + }, 2454 + "node_modules/mpath": { 2455 + "version": "0.9.0", 2456 + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", 2457 + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", 2458 + "license": "MIT", 2459 + "engines": { 2460 + "node": ">=4.0.0" 2461 + } 2462 + }, 2463 + "node_modules/mquery": { 2464 + "version": "6.0.0", 2465 + "resolved": "https://registry.npmjs.org/mquery/-/mquery-6.0.0.tgz", 2466 + "integrity": "sha512-b2KQNsmgtkscfeDgkYMcWGn9vZI9YoXh802VDEwE6qc50zxBFQ0Oo8ROkawbPAsXCY1/Z1yp0MagqsZStPWJjw==", 2467 + "license": "MIT", 2468 + "engines": { 2469 + "node": ">=20.19.0" 2470 + } 2471 + }, 2472 + "node_modules/ms": { 2473 + "version": "2.0.0", 2474 + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 2475 + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", 2476 + "license": "MIT" 2477 + }, 2478 + "node_modules/mz": { 2479 + "version": "2.7.0", 2480 + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", 2481 + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", 2482 + "dev": true, 2483 + "license": "MIT", 2484 + "dependencies": { 2485 + "any-promise": "^1.0.0", 2486 + "object-assign": "^4.0.1", 2487 + "thenify-all": "^1.0.0" 2488 + } 2489 + }, 2490 + "node_modules/nanoid": { 2491 + "version": "3.3.11", 2492 + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", 2493 + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", 2494 + "funding": [ 2495 + { 2496 + "type": "github", 2497 + "url": "https://github.com/sponsors/ai" 2498 + } 2499 + ], 2500 + "license": "MIT", 2501 + "bin": { 2502 + "nanoid": "bin/nanoid.cjs" 2503 + }, 2504 + "engines": { 2505 + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 2506 + } 2507 + }, 2508 + "node_modules/negotiator": { 2509 + "version": "0.6.3", 2510 + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 2511 + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 2512 + "license": "MIT", 2513 + "engines": { 2514 + "node": ">= 0.6" 2515 + } 2516 + }, 2517 + "node_modules/node-releases": { 2518 + "version": "2.0.37", 2519 + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz", 2520 + "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==", 2521 + "dev": true, 2522 + "license": "MIT" 2523 + }, 2524 + "node_modules/nodemon": { 2525 + "version": "3.1.14", 2526 + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", 2527 + "integrity": "sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==", 2528 + "dev": true, 2529 + "license": "MIT", 2530 + "dependencies": { 2531 + "chokidar": "^3.5.2", 2532 + "debug": "^4", 2533 + "ignore-by-default": "^1.0.1", 2534 + "minimatch": "^10.2.1", 2535 + "pstree.remy": "^1.1.8", 2536 + "semver": "^7.5.3", 2537 + "simple-update-notifier": "^2.0.0", 2538 + "supports-color": "^5.5.0", 2539 + "touch": "^3.1.0", 2540 + "undefsafe": "^2.0.5" 2541 + }, 2542 + "bin": { 2543 + "nodemon": "bin/nodemon.js" 2544 + }, 2545 + "engines": { 2546 + "node": ">=10" 2547 + }, 2548 + "funding": { 2549 + "type": "opencollective", 2550 + "url": "https://opencollective.com/nodemon" 2551 + } 2552 + }, 2553 + "node_modules/nodemon/node_modules/debug": { 2554 + "version": "4.4.3", 2555 + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", 2556 + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", 2557 + "dev": true, 2558 + "license": "MIT", 2559 + "dependencies": { 2560 + "ms": "^2.1.3" 2561 + }, 2562 + "engines": { 2563 + "node": ">=6.0" 2564 + }, 2565 + "peerDependenciesMeta": { 2566 + "supports-color": { 2567 + "optional": true 2568 + } 2569 + } 2570 + }, 2571 + "node_modules/nodemon/node_modules/has-flag": { 2572 + "version": "3.0.0", 2573 + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 2574 + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 2575 + "dev": true, 2576 + "license": "MIT", 2577 + "engines": { 2578 + "node": ">=4" 2579 + } 2580 + }, 2581 + "node_modules/nodemon/node_modules/ms": { 2582 + "version": "2.1.3", 2583 + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 2584 + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 2585 + "dev": true, 2586 + "license": "MIT" 2587 + }, 2588 + "node_modules/nodemon/node_modules/supports-color": { 2589 + "version": "5.5.0", 2590 + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 2591 + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 2592 + "dev": true, 2593 + "license": "MIT", 2594 + "dependencies": { 2595 + "has-flag": "^3.0.0" 2596 + }, 2597 + "engines": { 2598 + "node": ">=4" 2599 + } 2600 + }, 2601 + "node_modules/normalize-path": { 2602 + "version": "3.0.0", 2603 + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 2604 + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 2605 + "dev": true, 2606 + "license": "MIT", 2607 + "engines": { 2608 + "node": ">=0.10.0" 2609 + } 2610 + }, 2611 + "node_modules/object-assign": { 2612 + "version": "4.1.1", 2613 + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 2614 + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 2615 + "license": "MIT", 2616 + "engines": { 2617 + "node": ">=0.10.0" 2618 + } 2619 + }, 2620 + "node_modules/object-hash": { 2621 + "version": "3.0.0", 2622 + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", 2623 + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", 2624 + "dev": true, 2625 + "license": "MIT", 2626 + "engines": { 2627 + "node": ">= 6" 2628 + } 2629 + }, 2630 + "node_modules/object-inspect": { 2631 + "version": "1.13.4", 2632 + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", 2633 + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", 2634 + "license": "MIT", 2635 + "engines": { 2636 + "node": ">= 0.4" 2637 + }, 2638 + "funding": { 2639 + "url": "https://github.com/sponsors/ljharb" 2640 + } 2641 + }, 2642 + "node_modules/on-finished": { 2643 + "version": "2.4.1", 2644 + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 2645 + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 2646 + "license": "MIT", 2647 + "dependencies": { 2648 + "ee-first": "1.1.1" 2649 + }, 2650 + "engines": { 2651 + "node": ">= 0.8" 2652 + } 2653 + }, 2654 + "node_modules/parseurl": { 2655 + "version": "1.3.3", 2656 + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 2657 + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 2658 + "license": "MIT", 2659 + "engines": { 2660 + "node": ">= 0.8" 2661 + } 2662 + }, 2663 + "node_modules/path-parse": { 2664 + "version": "1.0.7", 2665 + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 2666 + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 2667 + "dev": true, 2668 + "license": "MIT" 2669 + }, 2670 + "node_modules/path-to-regexp": { 2671 + "version": "0.1.13", 2672 + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", 2673 + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", 2674 + "license": "MIT" 2675 + }, 2676 + "node_modules/picocolors": { 2677 + "version": "1.1.1", 2678 + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 2679 + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 2680 + "license": "ISC" 2681 + }, 2682 + "node_modules/picomatch": { 2683 + "version": "2.3.2", 2684 + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", 2685 + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", 2686 + "dev": true, 2687 + "license": "MIT", 2688 + "engines": { 2689 + "node": ">=8.6" 2690 + }, 2691 + "funding": { 2692 + "url": "https://github.com/sponsors/jonschlinkert" 2693 + } 2694 + }, 2695 + "node_modules/pify": { 2696 + "version": "2.3.0", 2697 + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 2698 + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", 2699 + "dev": true, 2700 + "license": "MIT", 2701 + "engines": { 2702 + "node": ">=0.10.0" 2703 + } 2704 + }, 2705 + "node_modules/pinia": { 2706 + "version": "2.3.1", 2707 + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.3.1.tgz", 2708 + "integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==", 2709 + "license": "MIT", 2710 + "dependencies": { 2711 + "@vue/devtools-api": "^6.6.3", 2712 + "vue-demi": "^0.14.10" 2713 + }, 2714 + "funding": { 2715 + "url": "https://github.com/sponsors/posva" 2716 + }, 2717 + "peerDependencies": { 2718 + "typescript": ">=4.4.4", 2719 + "vue": "^2.7.0 || ^3.5.11" 2720 + }, 2721 + "peerDependenciesMeta": { 2722 + "typescript": { 2723 + "optional": true 2724 + } 2725 + } 2726 + }, 2727 + "node_modules/pirates": { 2728 + "version": "4.0.7", 2729 + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", 2730 + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", 2731 + "dev": true, 2732 + "license": "MIT", 2733 + "engines": { 2734 + "node": ">= 6" 2735 + } 2736 + }, 2737 + "node_modules/postcss": { 2738 + "version": "8.5.9", 2739 + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz", 2740 + "integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==", 2741 + "funding": [ 2742 + { 2743 + "type": "opencollective", 2744 + "url": "https://opencollective.com/postcss/" 2745 + }, 2746 + { 2747 + "type": "tidelift", 2748 + "url": "https://tidelift.com/funding/github/npm/postcss" 2749 + }, 2750 + { 2751 + "type": "github", 2752 + "url": "https://github.com/sponsors/ai" 2753 + } 2754 + ], 2755 + "license": "MIT", 2756 + "peer": true, 2757 + "dependencies": { 2758 + "nanoid": "^3.3.11", 2759 + "picocolors": "^1.1.1", 2760 + "source-map-js": "^1.2.1" 2761 + }, 2762 + "engines": { 2763 + "node": "^10 || ^12 || >=14" 2764 + } 2765 + }, 2766 + "node_modules/postcss-import": { 2767 + "version": "15.1.0", 2768 + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", 2769 + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", 2770 + "dev": true, 2771 + "license": "MIT", 2772 + "dependencies": { 2773 + "postcss-value-parser": "^4.0.0", 2774 + "read-cache": "^1.0.0", 2775 + "resolve": "^1.1.7" 2776 + }, 2777 + "engines": { 2778 + "node": ">=14.0.0" 2779 + }, 2780 + "peerDependencies": { 2781 + "postcss": "^8.0.0" 2782 + } 2783 + }, 2784 + "node_modules/postcss-js": { 2785 + "version": "4.1.0", 2786 + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", 2787 + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", 2788 + "dev": true, 2789 + "funding": [ 2790 + { 2791 + "type": "opencollective", 2792 + "url": "https://opencollective.com/postcss/" 2793 + }, 2794 + { 2795 + "type": "github", 2796 + "url": "https://github.com/sponsors/ai" 2797 + } 2798 + ], 2799 + "license": "MIT", 2800 + "dependencies": { 2801 + "camelcase-css": "^2.0.1" 2802 + }, 2803 + "engines": { 2804 + "node": "^12 || ^14 || >= 16" 2805 + }, 2806 + "peerDependencies": { 2807 + "postcss": "^8.4.21" 2808 + } 2809 + }, 2810 + "node_modules/postcss-load-config": { 2811 + "version": "6.0.1", 2812 + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", 2813 + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", 2814 + "dev": true, 2815 + "funding": [ 2816 + { 2817 + "type": "opencollective", 2818 + "url": "https://opencollective.com/postcss/" 2819 + }, 2820 + { 2821 + "type": "github", 2822 + "url": "https://github.com/sponsors/ai" 2823 + } 2824 + ], 2825 + "license": "MIT", 2826 + "dependencies": { 2827 + "lilconfig": "^3.1.1" 2828 + }, 2829 + "engines": { 2830 + "node": ">= 18" 2831 + }, 2832 + "peerDependencies": { 2833 + "jiti": ">=1.21.0", 2834 + "postcss": ">=8.0.9", 2835 + "tsx": "^4.8.1", 2836 + "yaml": "^2.4.2" 2837 + }, 2838 + "peerDependenciesMeta": { 2839 + "jiti": { 2840 + "optional": true 2841 + }, 2842 + "postcss": { 2843 + "optional": true 2844 + }, 2845 + "tsx": { 2846 + "optional": true 2847 + }, 2848 + "yaml": { 2849 + "optional": true 2850 + } 2851 + } 2852 + }, 2853 + "node_modules/postcss-nested": { 2854 + "version": "6.2.0", 2855 + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", 2856 + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", 2857 + "dev": true, 2858 + "funding": [ 2859 + { 2860 + "type": "opencollective", 2861 + "url": "https://opencollective.com/postcss/" 2862 + }, 2863 + { 2864 + "type": "github", 2865 + "url": "https://github.com/sponsors/ai" 2866 + } 2867 + ], 2868 + "license": "MIT", 2869 + "dependencies": { 2870 + "postcss-selector-parser": "^6.1.1" 2871 + }, 2872 + "engines": { 2873 + "node": ">=12.0" 2874 + }, 2875 + "peerDependencies": { 2876 + "postcss": "^8.2.14" 2877 + } 2878 + }, 2879 + "node_modules/postcss-selector-parser": { 2880 + "version": "6.1.2", 2881 + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", 2882 + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", 2883 + "dev": true, 2884 + "license": "MIT", 2885 + "dependencies": { 2886 + "cssesc": "^3.0.0", 2887 + "util-deprecate": "^1.0.2" 2888 + }, 2889 + "engines": { 2890 + "node": ">=4" 2891 + } 2892 + }, 2893 + "node_modules/postcss-value-parser": { 2894 + "version": "4.2.0", 2895 + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", 2896 + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", 2897 + "dev": true, 2898 + "license": "MIT" 2899 + }, 2900 + "node_modules/proxy-addr": { 2901 + "version": "2.0.7", 2902 + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 2903 + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 2904 + "license": "MIT", 2905 + "dependencies": { 2906 + "forwarded": "0.2.0", 2907 + "ipaddr.js": "1.9.1" 2908 + }, 2909 + "engines": { 2910 + "node": ">= 0.10" 2911 + } 2912 + }, 2913 + "node_modules/pstree.remy": { 2914 + "version": "1.1.8", 2915 + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", 2916 + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", 2917 + "dev": true, 2918 + "license": "MIT" 2919 + }, 2920 + "node_modules/punycode": { 2921 + "version": "2.3.1", 2922 + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", 2923 + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", 2924 + "license": "MIT", 2925 + "engines": { 2926 + "node": ">=6" 2927 + } 2928 + }, 2929 + "node_modules/qs": { 2930 + "version": "6.14.2", 2931 + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", 2932 + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", 2933 + "license": "BSD-3-Clause", 2934 + "dependencies": { 2935 + "side-channel": "^1.1.0" 2936 + }, 2937 + "engines": { 2938 + "node": ">=0.6" 2939 + }, 2940 + "funding": { 2941 + "url": "https://github.com/sponsors/ljharb" 2942 + } 2943 + }, 2944 + "node_modules/queue-microtask": { 2945 + "version": "1.2.3", 2946 + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 2947 + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 2948 + "dev": true, 2949 + "funding": [ 2950 + { 2951 + "type": "github", 2952 + "url": "https://github.com/sponsors/feross" 2953 + }, 2954 + { 2955 + "type": "patreon", 2956 + "url": "https://www.patreon.com/feross" 2957 + }, 2958 + { 2959 + "type": "consulting", 2960 + "url": "https://feross.org/support" 2961 + } 2962 + ], 2963 + "license": "MIT" 2964 + }, 2965 + "node_modules/range-parser": { 2966 + "version": "1.2.1", 2967 + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 2968 + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 2969 + "license": "MIT", 2970 + "engines": { 2971 + "node": ">= 0.6" 2972 + } 2973 + }, 2974 + "node_modules/raw-body": { 2975 + "version": "2.5.3", 2976 + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", 2977 + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", 2978 + "license": "MIT", 2979 + "dependencies": { 2980 + "bytes": "~3.1.2", 2981 + "http-errors": "~2.0.1", 2982 + "iconv-lite": "~0.4.24", 2983 + "unpipe": "~1.0.0" 2984 + }, 2985 + "engines": { 2986 + "node": ">= 0.8" 2987 + } 2988 + }, 2989 + "node_modules/read-cache": { 2990 + "version": "1.0.0", 2991 + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", 2992 + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", 2993 + "dev": true, 2994 + "license": "MIT", 2995 + "dependencies": { 2996 + "pify": "^2.3.0" 2997 + } 2998 + }, 2999 + "node_modules/readdirp": { 3000 + "version": "3.6.0", 3001 + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 3002 + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 3003 + "dev": true, 3004 + "license": "MIT", 3005 + "dependencies": { 3006 + "picomatch": "^2.2.1" 3007 + }, 3008 + "engines": { 3009 + "node": ">=8.10.0" 3010 + } 3011 + }, 3012 + "node_modules/require-directory": { 3013 + "version": "2.1.1", 3014 + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 3015 + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", 3016 + "dev": true, 3017 + "license": "MIT", 3018 + "engines": { 3019 + "node": ">=0.10.0" 3020 + } 3021 + }, 3022 + "node_modules/resolve": { 3023 + "version": "1.22.12", 3024 + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", 3025 + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", 3026 + "dev": true, 3027 + "license": "MIT", 3028 + "dependencies": { 3029 + "es-errors": "^1.3.0", 3030 + "is-core-module": "^2.16.1", 3031 + "path-parse": "^1.0.7", 3032 + "supports-preserve-symlinks-flag": "^1.0.0" 3033 + }, 3034 + "bin": { 3035 + "resolve": "bin/resolve" 3036 + }, 3037 + "engines": { 3038 + "node": ">= 0.4" 3039 + }, 3040 + "funding": { 3041 + "url": "https://github.com/sponsors/ljharb" 3042 + } 3043 + }, 3044 + "node_modules/reusify": { 3045 + "version": "1.1.0", 3046 + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", 3047 + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", 3048 + "dev": true, 3049 + "license": "MIT", 3050 + "engines": { 3051 + "iojs": ">=1.0.0", 3052 + "node": ">=0.10.0" 3053 + } 3054 + }, 3055 + "node_modules/rollup": { 3056 + "version": "4.60.1", 3057 + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", 3058 + "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", 3059 + "dev": true, 3060 + "license": "MIT", 3061 + "dependencies": { 3062 + "@types/estree": "1.0.8" 3063 + }, 3064 + "bin": { 3065 + "rollup": "dist/bin/rollup" 3066 + }, 3067 + "engines": { 3068 + "node": ">=18.0.0", 3069 + "npm": ">=8.0.0" 3070 + }, 3071 + "optionalDependencies": { 3072 + "@rollup/rollup-android-arm-eabi": "4.60.1", 3073 + "@rollup/rollup-android-arm64": "4.60.1", 3074 + "@rollup/rollup-darwin-arm64": "4.60.1", 3075 + "@rollup/rollup-darwin-x64": "4.60.1", 3076 + "@rollup/rollup-freebsd-arm64": "4.60.1", 3077 + "@rollup/rollup-freebsd-x64": "4.60.1", 3078 + "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", 3079 + "@rollup/rollup-linux-arm-musleabihf": "4.60.1", 3080 + "@rollup/rollup-linux-arm64-gnu": "4.60.1", 3081 + "@rollup/rollup-linux-arm64-musl": "4.60.1", 3082 + "@rollup/rollup-linux-loong64-gnu": "4.60.1", 3083 + "@rollup/rollup-linux-loong64-musl": "4.60.1", 3084 + "@rollup/rollup-linux-ppc64-gnu": "4.60.1", 3085 + "@rollup/rollup-linux-ppc64-musl": "4.60.1", 3086 + "@rollup/rollup-linux-riscv64-gnu": "4.60.1", 3087 + "@rollup/rollup-linux-riscv64-musl": "4.60.1", 3088 + "@rollup/rollup-linux-s390x-gnu": "4.60.1", 3089 + "@rollup/rollup-linux-x64-gnu": "4.60.1", 3090 + "@rollup/rollup-linux-x64-musl": "4.60.1", 3091 + "@rollup/rollup-openbsd-x64": "4.60.1", 3092 + "@rollup/rollup-openharmony-arm64": "4.60.1", 3093 + "@rollup/rollup-win32-arm64-msvc": "4.60.1", 3094 + "@rollup/rollup-win32-ia32-msvc": "4.60.1", 3095 + "@rollup/rollup-win32-x64-gnu": "4.60.1", 3096 + "@rollup/rollup-win32-x64-msvc": "4.60.1", 3097 + "fsevents": "~2.3.2" 3098 + } 3099 + }, 3100 + "node_modules/run-parallel": { 3101 + "version": "1.2.0", 3102 + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 3103 + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 3104 + "dev": true, 3105 + "funding": [ 3106 + { 3107 + "type": "github", 3108 + "url": "https://github.com/sponsors/feross" 3109 + }, 3110 + { 3111 + "type": "patreon", 3112 + "url": "https://www.patreon.com/feross" 3113 + }, 3114 + { 3115 + "type": "consulting", 3116 + "url": "https://feross.org/support" 3117 + } 3118 + ], 3119 + "license": "MIT", 3120 + "dependencies": { 3121 + "queue-microtask": "^1.2.2" 3122 + } 3123 + }, 3124 + "node_modules/rxjs": { 3125 + "version": "7.8.2", 3126 + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", 3127 + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", 3128 + "dev": true, 3129 + "license": "Apache-2.0", 3130 + "dependencies": { 3131 + "tslib": "^2.1.0" 3132 + } 3133 + }, 3134 + "node_modules/safe-buffer": { 3135 + "version": "5.2.1", 3136 + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 3137 + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 3138 + "funding": [ 3139 + { 3140 + "type": "github", 3141 + "url": "https://github.com/sponsors/feross" 3142 + }, 3143 + { 3144 + "type": "patreon", 3145 + "url": "https://www.patreon.com/feross" 3146 + }, 3147 + { 3148 + "type": "consulting", 3149 + "url": "https://feross.org/support" 3150 + } 3151 + ], 3152 + "license": "MIT" 3153 + }, 3154 + "node_modules/safer-buffer": { 3155 + "version": "2.1.2", 3156 + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 3157 + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 3158 + "license": "MIT" 3159 + }, 3160 + "node_modules/semver": { 3161 + "version": "7.7.4", 3162 + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", 3163 + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", 3164 + "dev": true, 3165 + "license": "ISC", 3166 + "bin": { 3167 + "semver": "bin/semver.js" 3168 + }, 3169 + "engines": { 3170 + "node": ">=10" 3171 + } 3172 + }, 3173 + "node_modules/send": { 3174 + "version": "0.19.2", 3175 + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", 3176 + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", 3177 + "license": "MIT", 3178 + "dependencies": { 3179 + "debug": "2.6.9", 3180 + "depd": "2.0.0", 3181 + "destroy": "1.2.0", 3182 + "encodeurl": "~2.0.0", 3183 + "escape-html": "~1.0.3", 3184 + "etag": "~1.8.1", 3185 + "fresh": "~0.5.2", 3186 + "http-errors": "~2.0.1", 3187 + "mime": "1.6.0", 3188 + "ms": "2.1.3", 3189 + "on-finished": "~2.4.1", 3190 + "range-parser": "~1.2.1", 3191 + "statuses": "~2.0.2" 3192 + }, 3193 + "engines": { 3194 + "node": ">= 0.8.0" 3195 + } 3196 + }, 3197 + "node_modules/send/node_modules/ms": { 3198 + "version": "2.1.3", 3199 + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 3200 + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 3201 + "license": "MIT" 3202 + }, 3203 + "node_modules/serve-static": { 3204 + "version": "1.16.3", 3205 + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", 3206 + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", 3207 + "license": "MIT", 3208 + "dependencies": { 3209 + "encodeurl": "~2.0.0", 3210 + "escape-html": "~1.0.3", 3211 + "parseurl": "~1.3.3", 3212 + "send": "~0.19.1" 3213 + }, 3214 + "engines": { 3215 + "node": ">= 0.8.0" 3216 + } 3217 + }, 3218 + "node_modules/setprototypeof": { 3219 + "version": "1.2.0", 3220 + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 3221 + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", 3222 + "license": "ISC" 3223 + }, 3224 + "node_modules/shell-quote": { 3225 + "version": "1.8.3", 3226 + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", 3227 + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", 3228 + "dev": true, 3229 + "license": "MIT", 3230 + "engines": { 3231 + "node": ">= 0.4" 3232 + }, 3233 + "funding": { 3234 + "url": "https://github.com/sponsors/ljharb" 3235 + } 3236 + }, 3237 + "node_modules/side-channel": { 3238 + "version": "1.1.0", 3239 + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", 3240 + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", 3241 + "license": "MIT", 3242 + "dependencies": { 3243 + "es-errors": "^1.3.0", 3244 + "object-inspect": "^1.13.3", 3245 + "side-channel-list": "^1.0.0", 3246 + "side-channel-map": "^1.0.1", 3247 + "side-channel-weakmap": "^1.0.2" 3248 + }, 3249 + "engines": { 3250 + "node": ">= 0.4" 3251 + }, 3252 + "funding": { 3253 + "url": "https://github.com/sponsors/ljharb" 3254 + } 3255 + }, 3256 + "node_modules/side-channel-list": { 3257 + "version": "1.0.1", 3258 + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", 3259 + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", 3260 + "license": "MIT", 3261 + "dependencies": { 3262 + "es-errors": "^1.3.0", 3263 + "object-inspect": "^1.13.4" 3264 + }, 3265 + "engines": { 3266 + "node": ">= 0.4" 3267 + }, 3268 + "funding": { 3269 + "url": "https://github.com/sponsors/ljharb" 3270 + } 3271 + }, 3272 + "node_modules/side-channel-map": { 3273 + "version": "1.0.1", 3274 + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", 3275 + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", 3276 + "license": "MIT", 3277 + "dependencies": { 3278 + "call-bound": "^1.0.2", 3279 + "es-errors": "^1.3.0", 3280 + "get-intrinsic": "^1.2.5", 3281 + "object-inspect": "^1.13.3" 3282 + }, 3283 + "engines": { 3284 + "node": ">= 0.4" 3285 + }, 3286 + "funding": { 3287 + "url": "https://github.com/sponsors/ljharb" 3288 + } 3289 + }, 3290 + "node_modules/side-channel-weakmap": { 3291 + "version": "1.0.2", 3292 + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", 3293 + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", 3294 + "license": "MIT", 3295 + "dependencies": { 3296 + "call-bound": "^1.0.2", 3297 + "es-errors": "^1.3.0", 3298 + "get-intrinsic": "^1.2.5", 3299 + "object-inspect": "^1.13.3", 3300 + "side-channel-map": "^1.0.1" 3301 + }, 3302 + "engines": { 3303 + "node": ">= 0.4" 3304 + }, 3305 + "funding": { 3306 + "url": "https://github.com/sponsors/ljharb" 3307 + } 3308 + }, 3309 + "node_modules/sift": { 3310 + "version": "17.1.3", 3311 + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", 3312 + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==", 3313 + "license": "MIT" 3314 + }, 3315 + "node_modules/simple-update-notifier": { 3316 + "version": "2.0.0", 3317 + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", 3318 + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", 3319 + "dev": true, 3320 + "license": "MIT", 3321 + "dependencies": { 3322 + "semver": "^7.5.3" 3323 + }, 3324 + "engines": { 3325 + "node": ">=10" 3326 + } 3327 + }, 3328 + "node_modules/source-map-js": { 3329 + "version": "1.2.1", 3330 + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 3331 + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 3332 + "license": "BSD-3-Clause", 3333 + "engines": { 3334 + "node": ">=0.10.0" 3335 + } 3336 + }, 3337 + "node_modules/sparse-bitfield": { 3338 + "version": "3.0.3", 3339 + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", 3340 + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", 3341 + "license": "MIT", 3342 + "dependencies": { 3343 + "memory-pager": "^1.0.2" 3344 + } 3345 + }, 3346 + "node_modules/statuses": { 3347 + "version": "2.0.2", 3348 + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", 3349 + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", 3350 + "license": "MIT", 3351 + "engines": { 3352 + "node": ">= 0.8" 3353 + } 3354 + }, 3355 + "node_modules/string-width": { 3356 + "version": "4.2.3", 3357 + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 3358 + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 3359 + "dev": true, 3360 + "license": "MIT", 3361 + "dependencies": { 3362 + "emoji-regex": "^8.0.0", 3363 + "is-fullwidth-code-point": "^3.0.0", 3364 + "strip-ansi": "^6.0.1" 3365 + }, 3366 + "engines": { 3367 + "node": ">=8" 3368 + } 3369 + }, 3370 + "node_modules/strip-ansi": { 3371 + "version": "6.0.1", 3372 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 3373 + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 3374 + "dev": true, 3375 + "license": "MIT", 3376 + "dependencies": { 3377 + "ansi-regex": "^5.0.1" 3378 + }, 3379 + "engines": { 3380 + "node": ">=8" 3381 + } 3382 + }, 3383 + "node_modules/sucrase": { 3384 + "version": "3.35.1", 3385 + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", 3386 + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", 3387 + "dev": true, 3388 + "license": "MIT", 3389 + "dependencies": { 3390 + "@jridgewell/gen-mapping": "^0.3.2", 3391 + "commander": "^4.0.0", 3392 + "lines-and-columns": "^1.1.6", 3393 + "mz": "^2.7.0", 3394 + "pirates": "^4.0.1", 3395 + "tinyglobby": "^0.2.11", 3396 + "ts-interface-checker": "^0.1.9" 3397 + }, 3398 + "bin": { 3399 + "sucrase": "bin/sucrase", 3400 + "sucrase-node": "bin/sucrase-node" 3401 + }, 3402 + "engines": { 3403 + "node": ">=16 || 14 >=14.17" 3404 + } 3405 + }, 3406 + "node_modules/supports-color": { 3407 + "version": "8.1.1", 3408 + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", 3409 + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", 3410 + "dev": true, 3411 + "license": "MIT", 3412 + "dependencies": { 3413 + "has-flag": "^4.0.0" 3414 + }, 3415 + "engines": { 3416 + "node": ">=10" 3417 + }, 3418 + "funding": { 3419 + "url": "https://github.com/chalk/supports-color?sponsor=1" 3420 + } 3421 + }, 3422 + "node_modules/supports-preserve-symlinks-flag": { 3423 + "version": "1.0.0", 3424 + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 3425 + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 3426 + "dev": true, 3427 + "license": "MIT", 3428 + "engines": { 3429 + "node": ">= 0.4" 3430 + }, 3431 + "funding": { 3432 + "url": "https://github.com/sponsors/ljharb" 3433 + } 3434 + }, 3435 + "node_modules/tailwindcss": { 3436 + "version": "3.4.19", 3437 + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", 3438 + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", 3439 + "dev": true, 3440 + "license": "MIT", 3441 + "dependencies": { 3442 + "@alloc/quick-lru": "^5.2.0", 3443 + "arg": "^5.0.2", 3444 + "chokidar": "^3.6.0", 3445 + "didyoumean": "^1.2.2", 3446 + "dlv": "^1.1.3", 3447 + "fast-glob": "^3.3.2", 3448 + "glob-parent": "^6.0.2", 3449 + "is-glob": "^4.0.3", 3450 + "jiti": "^1.21.7", 3451 + "lilconfig": "^3.1.3", 3452 + "micromatch": "^4.0.8", 3453 + "normalize-path": "^3.0.0", 3454 + "object-hash": "^3.0.0", 3455 + "picocolors": "^1.1.1", 3456 + "postcss": "^8.4.47", 3457 + "postcss-import": "^15.1.0", 3458 + "postcss-js": "^4.0.1", 3459 + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", 3460 + "postcss-nested": "^6.2.0", 3461 + "postcss-selector-parser": "^6.1.2", 3462 + "resolve": "^1.22.8", 3463 + "sucrase": "^3.35.0" 3464 + }, 3465 + "bin": { 3466 + "tailwind": "lib/cli.js", 3467 + "tailwindcss": "lib/cli.js" 3468 + }, 3469 + "engines": { 3470 + "node": ">=14.0.0" 3471 + } 3472 + }, 3473 + "node_modules/tailwindcss/node_modules/glob-parent": { 3474 + "version": "6.0.2", 3475 + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 3476 + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 3477 + "dev": true, 3478 + "license": "ISC", 3479 + "dependencies": { 3480 + "is-glob": "^4.0.3" 3481 + }, 3482 + "engines": { 3483 + "node": ">=10.13.0" 3484 + } 3485 + }, 3486 + "node_modules/thenify": { 3487 + "version": "3.3.1", 3488 + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", 3489 + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", 3490 + "dev": true, 3491 + "license": "MIT", 3492 + "dependencies": { 3493 + "any-promise": "^1.0.0" 3494 + } 3495 + }, 3496 + "node_modules/thenify-all": { 3497 + "version": "1.6.0", 3498 + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", 3499 + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", 3500 + "dev": true, 3501 + "license": "MIT", 3502 + "dependencies": { 3503 + "thenify": ">= 3.1.0 < 4" 3504 + }, 3505 + "engines": { 3506 + "node": ">=0.8" 3507 + } 3508 + }, 3509 + "node_modules/tinyglobby": { 3510 + "version": "0.2.16", 3511 + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", 3512 + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", 3513 + "dev": true, 3514 + "license": "MIT", 3515 + "dependencies": { 3516 + "fdir": "^6.5.0", 3517 + "picomatch": "^4.0.4" 3518 + }, 3519 + "engines": { 3520 + "node": ">=12.0.0" 3521 + }, 3522 + "funding": { 3523 + "url": "https://github.com/sponsors/SuperchupuDev" 3524 + } 3525 + }, 3526 + "node_modules/tinyglobby/node_modules/fdir": { 3527 + "version": "6.5.0", 3528 + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", 3529 + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", 3530 + "dev": true, 3531 + "license": "MIT", 3532 + "engines": { 3533 + "node": ">=12.0.0" 3534 + }, 3535 + "peerDependencies": { 3536 + "picomatch": "^3 || ^4" 3537 + }, 3538 + "peerDependenciesMeta": { 3539 + "picomatch": { 3540 + "optional": true 3541 + } 3542 + } 3543 + }, 3544 + "node_modules/tinyglobby/node_modules/picomatch": { 3545 + "version": "4.0.4", 3546 + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", 3547 + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", 3548 + "dev": true, 3549 + "license": "MIT", 3550 + "peer": true, 3551 + "engines": { 3552 + "node": ">=12" 3553 + }, 3554 + "funding": { 3555 + "url": "https://github.com/sponsors/jonschlinkert" 3556 + } 3557 + }, 3558 + "node_modules/to-regex-range": { 3559 + "version": "5.0.1", 3560 + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 3561 + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 3562 + "dev": true, 3563 + "license": "MIT", 3564 + "dependencies": { 3565 + "is-number": "^7.0.0" 3566 + }, 3567 + "engines": { 3568 + "node": ">=8.0" 3569 + } 3570 + }, 3571 + "node_modules/toidentifier": { 3572 + "version": "1.0.1", 3573 + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 3574 + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 3575 + "license": "MIT", 3576 + "engines": { 3577 + "node": ">=0.6" 3578 + } 3579 + }, 3580 + "node_modules/touch": { 3581 + "version": "3.1.1", 3582 + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", 3583 + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", 3584 + "dev": true, 3585 + "license": "ISC", 3586 + "bin": { 3587 + "nodetouch": "bin/nodetouch.js" 3588 + } 3589 + }, 3590 + "node_modules/tr46": { 3591 + "version": "5.1.1", 3592 + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", 3593 + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", 3594 + "license": "MIT", 3595 + "dependencies": { 3596 + "punycode": "^2.3.1" 3597 + }, 3598 + "engines": { 3599 + "node": ">=18" 3600 + } 3601 + }, 3602 + "node_modules/tree-kill": { 3603 + "version": "1.2.2", 3604 + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", 3605 + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", 3606 + "dev": true, 3607 + "license": "MIT", 3608 + "bin": { 3609 + "tree-kill": "cli.js" 3610 + } 3611 + }, 3612 + "node_modules/ts-interface-checker": { 3613 + "version": "0.1.13", 3614 + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", 3615 + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", 3616 + "dev": true, 3617 + "license": "Apache-2.0" 3618 + }, 3619 + "node_modules/tslib": { 3620 + "version": "2.8.1", 3621 + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", 3622 + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", 3623 + "dev": true, 3624 + "license": "0BSD" 3625 + }, 3626 + "node_modules/type-is": { 3627 + "version": "1.6.18", 3628 + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 3629 + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 3630 + "license": "MIT", 3631 + "dependencies": { 3632 + "media-typer": "0.3.0", 3633 + "mime-types": "~2.1.24" 3634 + }, 3635 + "engines": { 3636 + "node": ">= 0.6" 3637 + } 3638 + }, 3639 + "node_modules/undefsafe": { 3640 + "version": "2.0.5", 3641 + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", 3642 + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", 3643 + "dev": true, 3644 + "license": "MIT" 3645 + }, 3646 + "node_modules/unpipe": { 3647 + "version": "1.0.0", 3648 + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 3649 + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 3650 + "license": "MIT", 3651 + "engines": { 3652 + "node": ">= 0.8" 3653 + } 3654 + }, 3655 + "node_modules/update-browserslist-db": { 3656 + "version": "1.2.3", 3657 + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", 3658 + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", 3659 + "dev": true, 3660 + "funding": [ 3661 + { 3662 + "type": "opencollective", 3663 + "url": "https://opencollective.com/browserslist" 3664 + }, 3665 + { 3666 + "type": "tidelift", 3667 + "url": "https://tidelift.com/funding/github/npm/browserslist" 3668 + }, 3669 + { 3670 + "type": "github", 3671 + "url": "https://github.com/sponsors/ai" 3672 + } 3673 + ], 3674 + "license": "MIT", 3675 + "dependencies": { 3676 + "escalade": "^3.2.0", 3677 + "picocolors": "^1.1.1" 3678 + }, 3679 + "bin": { 3680 + "update-browserslist-db": "cli.js" 3681 + }, 3682 + "peerDependencies": { 3683 + "browserslist": ">= 4.21.0" 3684 + } 3685 + }, 3686 + "node_modules/util-deprecate": { 3687 + "version": "1.0.2", 3688 + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 3689 + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 3690 + "dev": true, 3691 + "license": "MIT" 3692 + }, 3693 + "node_modules/utils-merge": { 3694 + "version": "1.0.1", 3695 + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 3696 + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 3697 + "license": "MIT", 3698 + "engines": { 3699 + "node": ">= 0.4.0" 3700 + } 3701 + }, 3702 + "node_modules/vary": { 3703 + "version": "1.1.2", 3704 + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 3705 + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 3706 + "license": "MIT", 3707 + "engines": { 3708 + "node": ">= 0.8" 3709 + } 3710 + }, 3711 + "node_modules/vite": { 3712 + "version": "6.4.2", 3713 + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz", 3714 + "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", 3715 + "dev": true, 3716 + "license": "MIT", 3717 + "peer": true, 3718 + "dependencies": { 3719 + "esbuild": "^0.25.0", 3720 + "fdir": "^6.4.4", 3721 + "picomatch": "^4.0.2", 3722 + "postcss": "^8.5.3", 3723 + "rollup": "^4.34.9", 3724 + "tinyglobby": "^0.2.13" 3725 + }, 3726 + "bin": { 3727 + "vite": "bin/vite.js" 3728 + }, 3729 + "engines": { 3730 + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 3731 + }, 3732 + "funding": { 3733 + "url": "https://github.com/vitejs/vite?sponsor=1" 3734 + }, 3735 + "optionalDependencies": { 3736 + "fsevents": "~2.3.3" 3737 + }, 3738 + "peerDependencies": { 3739 + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 3740 + "jiti": ">=1.21.0", 3741 + "less": "*", 3742 + "lightningcss": "^1.21.0", 3743 + "sass": "*", 3744 + "sass-embedded": "*", 3745 + "stylus": "*", 3746 + "sugarss": "*", 3747 + "terser": "^5.16.0", 3748 + "tsx": "^4.8.1", 3749 + "yaml": "^2.4.2" 3750 + }, 3751 + "peerDependenciesMeta": { 3752 + "@types/node": { 3753 + "optional": true 3754 + }, 3755 + "jiti": { 3756 + "optional": true 3757 + }, 3758 + "less": { 3759 + "optional": true 3760 + }, 3761 + "lightningcss": { 3762 + "optional": true 3763 + }, 3764 + "sass": { 3765 + "optional": true 3766 + }, 3767 + "sass-embedded": { 3768 + "optional": true 3769 + }, 3770 + "stylus": { 3771 + "optional": true 3772 + }, 3773 + "sugarss": { 3774 + "optional": true 3775 + }, 3776 + "terser": { 3777 + "optional": true 3778 + }, 3779 + "tsx": { 3780 + "optional": true 3781 + }, 3782 + "yaml": { 3783 + "optional": true 3784 + } 3785 + } 3786 + }, 3787 + "node_modules/vite/node_modules/fdir": { 3788 + "version": "6.5.0", 3789 + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", 3790 + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", 3791 + "dev": true, 3792 + "license": "MIT", 3793 + "engines": { 3794 + "node": ">=12.0.0" 3795 + }, 3796 + "peerDependencies": { 3797 + "picomatch": "^3 || ^4" 3798 + }, 3799 + "peerDependenciesMeta": { 3800 + "picomatch": { 3801 + "optional": true 3802 + } 3803 + } 3804 + }, 3805 + "node_modules/vite/node_modules/picomatch": { 3806 + "version": "4.0.4", 3807 + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", 3808 + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", 3809 + "dev": true, 3810 + "license": "MIT", 3811 + "peer": true, 3812 + "engines": { 3813 + "node": ">=12" 3814 + }, 3815 + "funding": { 3816 + "url": "https://github.com/sponsors/jonschlinkert" 3817 + } 3818 + }, 3819 + "node_modules/vue": { 3820 + "version": "3.5.32", 3821 + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.32.tgz", 3822 + "integrity": "sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==", 3823 + "license": "MIT", 3824 + "peer": true, 3825 + "dependencies": { 3826 + "@vue/compiler-dom": "3.5.32", 3827 + "@vue/compiler-sfc": "3.5.32", 3828 + "@vue/runtime-dom": "3.5.32", 3829 + "@vue/server-renderer": "3.5.32", 3830 + "@vue/shared": "3.5.32" 3831 + }, 3832 + "peerDependencies": { 3833 + "typescript": "*" 3834 + }, 3835 + "peerDependenciesMeta": { 3836 + "typescript": { 3837 + "optional": true 3838 + } 3839 + } 3840 + }, 3841 + "node_modules/vue-demi": { 3842 + "version": "0.14.10", 3843 + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", 3844 + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", 3845 + "hasInstallScript": true, 3846 + "license": "MIT", 3847 + "bin": { 3848 + "vue-demi-fix": "bin/vue-demi-fix.js", 3849 + "vue-demi-switch": "bin/vue-demi-switch.js" 3850 + }, 3851 + "engines": { 3852 + "node": ">=12" 3853 + }, 3854 + "funding": { 3855 + "url": "https://github.com/sponsors/antfu" 3856 + }, 3857 + "peerDependencies": { 3858 + "@vue/composition-api": "^1.0.0-rc.1", 3859 + "vue": "^3.0.0-0 || ^2.6.0" 3860 + }, 3861 + "peerDependenciesMeta": { 3862 + "@vue/composition-api": { 3863 + "optional": true 3864 + } 3865 + } 3866 + }, 3867 + "node_modules/vue-router": { 3868 + "version": "4.6.4", 3869 + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz", 3870 + "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", 3871 + "license": "MIT", 3872 + "dependencies": { 3873 + "@vue/devtools-api": "^6.6.4" 3874 + }, 3875 + "funding": { 3876 + "url": "https://github.com/sponsors/posva" 3877 + }, 3878 + "peerDependencies": { 3879 + "vue": "^3.5.0" 3880 + } 3881 + }, 3882 + "node_modules/webidl-conversions": { 3883 + "version": "7.0.0", 3884 + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", 3885 + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", 3886 + "license": "BSD-2-Clause", 3887 + "engines": { 3888 + "node": ">=12" 3889 + } 3890 + }, 3891 + "node_modules/whatwg-url": { 3892 + "version": "14.2.0", 3893 + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", 3894 + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", 3895 + "license": "MIT", 3896 + "dependencies": { 3897 + "tr46": "^5.1.0", 3898 + "webidl-conversions": "^7.0.0" 3899 + }, 3900 + "engines": { 3901 + "node": ">=18" 3902 + } 3903 + }, 3904 + "node_modules/wrap-ansi": { 3905 + "version": "7.0.0", 3906 + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 3907 + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 3908 + "dev": true, 3909 + "license": "MIT", 3910 + "dependencies": { 3911 + "ansi-styles": "^4.0.0", 3912 + "string-width": "^4.1.0", 3913 + "strip-ansi": "^6.0.0" 3914 + }, 3915 + "engines": { 3916 + "node": ">=10" 3917 + }, 3918 + "funding": { 3919 + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 3920 + } 3921 + }, 3922 + "node_modules/y18n": { 3923 + "version": "5.0.8", 3924 + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 3925 + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 3926 + "dev": true, 3927 + "license": "ISC", 3928 + "engines": { 3929 + "node": ">=10" 3930 + } 3931 + }, 3932 + "node_modules/yargs": { 3933 + "version": "17.7.2", 3934 + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", 3935 + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", 3936 + "dev": true, 3937 + "license": "MIT", 3938 + "dependencies": { 3939 + "cliui": "^8.0.1", 3940 + "escalade": "^3.1.1", 3941 + "get-caller-file": "^2.0.5", 3942 + "require-directory": "^2.1.1", 3943 + "string-width": "^4.2.3", 3944 + "y18n": "^5.0.5", 3945 + "yargs-parser": "^21.1.1" 3946 + }, 3947 + "engines": { 3948 + "node": ">=12" 3949 + } 3950 + }, 3951 + "node_modules/yargs-parser": { 3952 + "version": "21.1.1", 3953 + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", 3954 + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", 3955 + "dev": true, 3956 + "license": "ISC", 3957 + "engines": { 3958 + "node": ">=12" 3959 + } 3960 + } 3961 + } 3962 + }
+31
package.json
··· 1 + { 2 + "name": "refapp", 3 + "version": "1.0.0", 4 + "description": "web management ui for refbot", 5 + "type": "module", 6 + "scripts": { 7 + "dev": "concurrently -n vite,api -c cyan,yellow \"vite\" \"nodemon\"", 8 + "dev:api": "nodemon", 9 + "dev:ui": "vite", 10 + "build": "vite build", 11 + "preview": "vite preview", 12 + "start": "node --env-file=.env api/index.js" 13 + }, 14 + "dependencies": { 15 + "cors": "^2.8.5", 16 + "express": "^4.21.2", 17 + "mongoose": "^9.0.2", 18 + "pinia": "^2.3.1", 19 + "vue": "^3.5.13", 20 + "vue-router": "^4.5.0" 21 + }, 22 + "devDependencies": { 23 + "@vitejs/plugin-vue": "^5.2.1", 24 + "autoprefixer": "^10.4.20", 25 + "concurrently": "^9.1.2", 26 + "nodemon": "^3.1.9", 27 + "postcss": "^8.5.3", 28 + "tailwindcss": "^3.4.17", 29 + "vite": "^6.2.6" 30 + } 31 + }
+6
postcss.config.js
··· 1 + export default { 2 + plugins: { 3 + tailwindcss: {}, 4 + autoprefixer: {}, 5 + }, 6 + }
+12
src/App.vue
··· 1 + <script setup> 2 + import AppNav from './components/AppNav.vue' 3 + </script> 4 + 5 + <template> 6 + <div class="min-h-screen bg-zinc-950 text-zinc-100"> 7 + <AppNav /> 8 + <main class="max-w-7xl mx-auto px-4 py-8"> 9 + <RouterView /> 10 + </main> 11 + </div> 12 + </template>
+21
src/api.js
··· 1 + async function get(path, params = {}) { 2 + const url = new URL('/api' + path, window.location.origin) 3 + for (const [k, v] of Object.entries(params)) { 4 + if (v != null) url.searchParams.set(k, v) 5 + } 6 + const res = await fetch(url) 7 + if (!res.ok) throw new Error(`api error ${res.status}: ${path}`) 8 + return res.json() 9 + } 10 + 11 + async function patch(path, body) { 12 + const res = await fetch('/api' + path, { 13 + method: 'PATCH', 14 + headers: { 'Content-Type': 'application/json' }, 15 + body: JSON.stringify(body), 16 + }) 17 + if (!res.ok) throw new Error(`api error ${res.status}: ${path}`) 18 + return res.json() 19 + } 20 + 21 + export const api = { get, patch }
+39
src/components/AppNav.vue
··· 1 + <script setup> 2 + import { RouterLink, useRoute } from 'vue-router' 3 + 4 + const route = useRoute() 5 + 6 + const links = [ 7 + { to: '/', label: 'Dashboard', exact: true }, 8 + { to: '/matches', label: 'Matches' }, 9 + { to: '/events', label: 'Events' }, 10 + { to: '/players', label: 'Players' }, 11 + ] 12 + 13 + function isActive(link) { 14 + return link.exact ? route.path === link.to : route.path.startsWith(link.to) 15 + } 16 + </script> 17 + 18 + <template> 19 + <nav class="border-b border-zinc-800 bg-zinc-900/80 backdrop-blur sticky top-0 z-50"> 20 + <div class="max-w-7xl mx-auto px-4 h-14 flex items-center gap-8"> 21 + <RouterLink to="/" class="font-mono font-medium text-indigo-400 tracking-tight text-lg shrink-0"> 22 + refapp 23 + </RouterLink> 24 + <div class="flex items-center gap-1"> 25 + <RouterLink 26 + v-for="link in links" 27 + :key="link.to" 28 + :to="link.to" 29 + class="px-3 py-1.5 rounded-md text-sm font-medium transition-colors" 30 + :class="isActive(link) 31 + ? 'text-zinc-100 bg-zinc-800' 32 + : 'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800/50'" 33 + > 34 + {{ link.label }} 35 + </RouterLink> 36 + </div> 37 + </div> 38 + </nav> 39 + </template>
+89
src/components/MatchCard.vue
··· 1 + <script setup> 2 + import { computed } from 'vue' 3 + import { useRouter } from 'vue-router' 4 + import StatusBadge from './StatusBadge.vue' 5 + 6 + const props = defineProps({ 7 + match: { type: Object, required: true }, 8 + }) 9 + 10 + const router = useRouter() 11 + 12 + function getName(player) { 13 + return player?.serverNickname 14 + ?? player?.spinshareUsername 15 + ?? player?.discordDisplayName 16 + ?? player?.discordUsername 17 + ?? player?.displayName 18 + ?? '?' 19 + } 20 + 21 + const p1 = computed(() => props.match.players?.[0]) 22 + const p2 = computed(() => props.match.players?.[1]) 23 + const mapsPlayed = computed(() => props.match.mappool?.filter(c => c.status?.played).length ?? 0) 24 + const totalMaps = computed(() => props.match.mappool?.length ?? 0) 25 + </script> 26 + 27 + <template> 28 + <div 29 + class="bg-zinc-900 border border-zinc-800 rounded-xl p-4 cursor-pointer hover:border-zinc-600 transition-all hover:bg-zinc-900/80 group" 30 + @click="router.push('/matches/' + match._id)" 31 + > 32 + <!-- header row --> 33 + <div class="flex items-start justify-between gap-2 mb-4"> 34 + <div class="min-w-0"> 35 + <div class="text-xs text-zinc-500 font-mono truncate">{{ match.meta?.round ?? 'Unknown Round' }}</div> 36 + <div class="font-medium text-zinc-200 text-sm truncate">{{ match.meta?.name ?? 'Unnamed Match' }}</div> 37 + </div> 38 + <StatusBadge :progressLevel="match.progressLevel" :status="match.status" /> 39 + </div> 40 + 41 + <!-- players + score --> 42 + <div class="flex items-center gap-2"> 43 + <!-- p1 --> 44 + <div class="flex-1 flex flex-col items-center gap-1.5 min-w-0"> 45 + <div class="relative"> 46 + <img 47 + v-if="p1?.spinshareAvatarUrl || p1?.avatarUrl" 48 + :src="p1.spinshareAvatarUrl ?? p1.avatarUrl" 49 + class="w-11 h-11 rounded-full bg-zinc-800 object-cover" 50 + :class="p1?.winner ? 'ring-2 ring-emerald-500' : ''" 51 + onerror="this.style.display='none'" 52 + /> 53 + <div v-else class="w-11 h-11 rounded-full bg-zinc-800 flex items-center justify-center text-zinc-500 text-sm">?</div> 54 + <span v-if="p1?.winner" class="absolute -top-1 -right-1 text-sm">🏆</span> 55 + </div> 56 + <span class="text-xs text-zinc-300 text-center truncate w-full text-center">{{ getName(p1) }}</span> 57 + </div> 58 + 59 + <!-- score --> 60 + <div class="flex items-center gap-2 font-mono shrink-0 px-1"> 61 + <span class="text-3xl font-bold" :class="p1?.winner ? 'text-emerald-400' : 'text-zinc-100'">{{ p1?.points ?? 0 }}</span> 62 + <span class="text-zinc-600 text-lg">–</span> 63 + <span class="text-3xl font-bold" :class="p2?.winner ? 'text-emerald-400' : 'text-zinc-100'">{{ p2?.points ?? 0 }}</span> 64 + </div> 65 + 66 + <!-- p2 --> 67 + <div class="flex-1 flex flex-col items-center gap-1.5 min-w-0"> 68 + <div class="relative"> 69 + <img 70 + v-if="p2?.spinshareAvatarUrl || p2?.avatarUrl" 71 + :src="p2.spinshareAvatarUrl ?? p2.avatarUrl" 72 + class="w-11 h-11 rounded-full bg-zinc-800 object-cover" 73 + :class="p2?.winner ? 'ring-2 ring-emerald-500' : ''" 74 + onerror="this.style.display='none'" 75 + /> 76 + <div v-else class="w-11 h-11 rounded-full bg-zinc-800 flex items-center justify-center text-zinc-500 text-sm">?</div> 77 + <span v-if="p2?.winner" class="absolute -top-1 -right-1 text-sm">🏆</span> 78 + </div> 79 + <span class="text-xs text-zinc-300 text-center truncate w-full text-center">{{ getName(p2) }}</span> 80 + </div> 81 + </div> 82 + 83 + <!-- footer --> 84 + <div class="flex items-center justify-between mt-4 pt-3 border-t border-zinc-800 text-xs text-zinc-500 font-mono"> 85 + <span>bo{{ match.meta?.bestOf ?? '?' }}</span> 86 + <span v-if="totalMaps > 0">{{ mapsPlayed }}/{{ totalMaps }} maps</span> 87 + </div> 88 + </div> 89 + </template>
+35
src/components/StatusBadge.vue
··· 1 + <script setup> 2 + defineProps({ 3 + progressLevel: String, 4 + status: String, 5 + }) 6 + 7 + const levelConfig = { 8 + 'check-in': { label: 'check-in', cls: 'bg-blue-900/50 text-blue-400' }, 9 + 'ban-phase': { label: 'ban phase', cls: 'bg-amber-900/50 text-amber-400' }, 10 + 'ready-check': { label: 'ready', cls: 'bg-amber-900/50 text-amber-400' }, 11 + 'playing': { label: 'playing', cls: 'bg-emerald-900/50 text-emerald-400' }, 12 + 'picking-post-result': { label: 'picking', cls: 'bg-emerald-900/50 text-emerald-400' }, 13 + 'finished': { label: 'finished', cls: 'bg-zinc-800 text-zinc-400' }, 14 + } 15 + 16 + const statusConfig = { 17 + 'completed': { label: 'done', cls: 'bg-zinc-800 text-zinc-400' }, 18 + 'abandoned': { label: 'abandoned', cls: 'bg-red-900/50 text-red-400' }, 19 + 'restarted': { label: 'restarted', cls: 'bg-amber-900/50 text-amber-400' }, 20 + } 21 + </script> 22 + 23 + <template> 24 + <span 25 + class="text-xs px-2 py-0.5 rounded-full font-medium font-mono shrink-0 whitespace-nowrap" 26 + :class="status !== 'in_progress' 27 + ? (statusConfig[status]?.cls ?? 'bg-zinc-800 text-zinc-400') 28 + : (levelConfig[progressLevel]?.cls ?? 'bg-zinc-800 text-zinc-400')" 29 + > 30 + {{ status !== 'in_progress' 31 + ? (statusConfig[status]?.label ?? status) 32 + : (levelConfig[progressLevel]?.label ?? progressLevel) 33 + }} 34 + </span> 35 + </template>
+10
src/main.js
··· 1 + import { createApp } from 'vue' 2 + import { createPinia } from 'pinia' 3 + import router from './router/index.js' 4 + import App from './App.vue' 5 + import './style.css' 6 + 7 + const app = createApp(App) 8 + app.use(createPinia()) 9 + app.use(router) 10 + app.mount('#app')
+15
src/router/index.js
··· 1 + import { createRouter, createWebHistory } from 'vue-router' 2 + import DashboardView from '../views/DashboardView.vue' 3 + 4 + const router = createRouter({ 5 + history: createWebHistory(), 6 + routes: [ 7 + { path: '/', component: DashboardView }, 8 + { path: '/matches', component: () => import('../views/MatchesView.vue') }, 9 + { path: '/matches/:id', component: () => import('../views/MatchDetailView.vue') }, 10 + { path: '/events', component: () => import('../views/EventsView.vue') }, 11 + { path: '/players', component: () => import('../views/PlayersView.vue') }, 12 + ], 13 + }) 14 + 15 + export default router
+3
src/style.css
··· 1 + @tailwind base; 2 + @tailwind components; 3 + @tailwind utilities;
+150
src/views/DashboardView.vue
··· 1 + <script setup> 2 + import { ref, onMounted, onUnmounted } from 'vue' 3 + import { api } from '../api.js' 4 + import MatchCard from '../components/MatchCard.vue' 5 + 6 + const activeEvent = ref(null) 7 + const activeMatches = ref([]) 8 + const recentMatches = ref([]) 9 + const stats = ref({ active: 0, completed: 0, players: 0 }) 10 + const loading = ref(true) 11 + let pollInterval = null 12 + 13 + async function load() { 14 + try { 15 + const [events, active, recent, players] = await Promise.all([ 16 + api.get('/events'), 17 + api.get('/matches', { status: 'in_progress', limit: 20 }), 18 + api.get('/matches', { status: 'completed', limit: 10 }), 19 + api.get('/players', { limit: 1 }), 20 + ]) 21 + activeEvent.value = events.find(e => e.active) ?? null 22 + activeMatches.value = active.matches 23 + recentMatches.value = recent.matches 24 + stats.value = { active: active.total, completed: recent.total, players: players.total } 25 + } 26 + catch (err) { 27 + console.error('dashboard load error:', err) 28 + } 29 + finally { 30 + loading.value = false 31 + } 32 + } 33 + 34 + onMounted(() => { 35 + load() 36 + pollInterval = setInterval(load, 10_000) 37 + }) 38 + onUnmounted(() => clearInterval(pollInterval)) 39 + 40 + function getName(player) { 41 + return player?.serverNickname ?? player?.spinshareUsername ?? player?.discordDisplayName ?? player?.discordUsername ?? player?.displayName ?? '?' 42 + } 43 + 44 + function fmtTime(dateStr) { 45 + if (!dateStr) return '-' 46 + return new Date(dateStr).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) 47 + } 48 + 49 + const statusLabel = s => ({ in_progress: 'live', completed: 'done', abandoned: 'abandoned', restarted: 'restarted' })[s] ?? s 50 + const statusCls = s => ({ 51 + in_progress: 'bg-emerald-900/50 text-emerald-400', 52 + completed: 'bg-zinc-800 text-zinc-400', 53 + abandoned: 'bg-red-900/50 text-red-400', 54 + restarted: 'bg-amber-900/50 text-amber-400', 55 + })[s] ?? 'bg-zinc-800 text-zinc-400' 56 + </script> 57 + 58 + <template> 59 + <div> 60 + <!-- page header --> 61 + <div class="mb-8 flex items-baseline gap-3"> 62 + <h1 class="text-2xl font-semibold">Dashboard</h1> 63 + <span v-if="activeEvent" class="text-sm text-indigo-400 font-mono">{{ activeEvent.name }}</span> 64 + <span v-else-if="!loading" class="text-sm text-zinc-600">no active event</span> 65 + </div> 66 + 67 + <!-- stats strip --> 68 + <div class="grid grid-cols-3 gap-4 mb-10"> 69 + <div class="bg-zinc-900 border border-zinc-800 rounded-xl p-5"> 70 + <div class="text-4xl font-bold text-emerald-400 font-mono">{{ stats.active }}</div> 71 + <div class="text-sm text-zinc-500 mt-1.5">active matches</div> 72 + </div> 73 + <div class="bg-zinc-900 border border-zinc-800 rounded-xl p-5"> 74 + <div class="text-4xl font-bold text-zinc-300 font-mono">{{ stats.completed }}</div> 75 + <div class="text-sm text-zinc-500 mt-1.5">completed matches</div> 76 + </div> 77 + <div class="bg-zinc-900 border border-zinc-800 rounded-xl p-5"> 78 + <div class="text-4xl font-bold text-zinc-300 font-mono">{{ stats.players }}</div> 79 + <div class="text-sm text-zinc-500 mt-1.5">registered players</div> 80 + </div> 81 + </div> 82 + 83 + <!-- active matches --> 84 + <section class="mb-10"> 85 + <div class="flex items-center justify-between mb-4"> 86 + <h2 class="font-semibold text-zinc-200">Active Matches</h2> 87 + <RouterLink to="/matches?status=in_progress" class="text-sm text-indigo-400 hover:text-indigo-300 transition-colors">see all</RouterLink> 88 + </div> 89 + <div v-if="loading" class="text-zinc-600 text-sm">loading...</div> 90 + <div v-else-if="activeMatches.length === 0" class="text-zinc-600 text-sm py-8 text-center border border-dashed border-zinc-800 rounded-xl"> 91 + no active matches right now 92 + </div> 93 + <div v-else class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4"> 94 + <MatchCard v-for="m in activeMatches" :key="m._id" :match="m" /> 95 + </div> 96 + </section> 97 + 98 + <!-- recent matches table --> 99 + <section> 100 + <div class="flex items-center justify-between mb-4"> 101 + <h2 class="font-semibold text-zinc-200">Recent Matches</h2> 102 + <RouterLink to="/matches" class="text-sm text-indigo-400 hover:text-indigo-300 transition-colors">see all</RouterLink> 103 + </div> 104 + <div class="bg-zinc-900 border border-zinc-800 rounded-xl overflow-hidden"> 105 + <table class="w-full text-sm"> 106 + <thead> 107 + <tr class="border-b border-zinc-800"> 108 + <th class="text-left px-4 py-3 text-zinc-500 font-medium">Round</th> 109 + <th class="text-left px-4 py-3 text-zinc-500 font-medium">Players</th> 110 + <th class="text-center px-4 py-3 text-zinc-500 font-medium">Score</th> 111 + <th class="text-left px-4 py-3 text-zinc-500 font-medium">Status</th> 112 + <th class="text-left px-4 py-3 text-zinc-500 font-medium">Time</th> 113 + </tr> 114 + </thead> 115 + <tbody> 116 + <tr v-if="!loading && recentMatches.length === 0"> 117 + <td colspan="5" class="px-4 py-8 text-center text-zinc-600">no completed matches yet</td> 118 + </tr> 119 + <tr 120 + v-for="m in recentMatches" 121 + :key="m._id" 122 + class="border-b border-zinc-800/50 hover:bg-zinc-800/30 transition-colors cursor-pointer" 123 + @click="$router.push('/matches/' + m._id)" 124 + > 125 + <td class="px-4 py-3 text-zinc-400 text-xs font-mono">{{ m.meta?.round ?? '-' }}</td> 126 + <td class="px-4 py-3"> 127 + <div class="flex items-center gap-2 text-sm"> 128 + <img v-if="m.players?.[0]?.spinshareAvatarUrl" :src="m.players[0].spinshareAvatarUrl" class="w-5 h-5 rounded-full bg-zinc-800 shrink-0" onerror="this.style.display='none'" /> 129 + <span :class="m.players?.[0]?.winner ? 'text-emerald-400 font-medium' : 'text-zinc-200'">{{ getName(m.players?.[0]) }}</span> 130 + <span class="text-zinc-600">vs</span> 131 + <img v-if="m.players?.[1]?.spinshareAvatarUrl" :src="m.players[1].spinshareAvatarUrl" class="w-5 h-5 rounded-full bg-zinc-800 shrink-0" onerror="this.style.display='none'" /> 132 + <span :class="m.players?.[1]?.winner ? 'text-emerald-400 font-medium' : 'text-zinc-200'">{{ getName(m.players?.[1]) }}</span> 133 + </div> 134 + </td> 135 + <td class="px-4 py-3 text-center font-mono"> 136 + <span :class="m.players?.[0]?.winner ? 'text-emerald-400 font-bold' : 'text-zinc-300'">{{ m.players?.[0]?.points ?? 0 }}</span> 137 + <span class="text-zinc-600 mx-1">–</span> 138 + <span :class="m.players?.[1]?.winner ? 'text-emerald-400 font-bold' : 'text-zinc-300'">{{ m.players?.[1]?.points ?? 0 }}</span> 139 + </td> 140 + <td class="px-4 py-3"> 141 + <span class="text-xs px-2 py-0.5 rounded-full font-mono" :class="statusCls(m.status)">{{ statusLabel(m.status) }}</span> 142 + </td> 143 + <td class="px-4 py-3 text-zinc-600 font-mono text-xs">{{ fmtTime(m.meta?.startedAt) }}</td> 144 + </tr> 145 + </tbody> 146 + </table> 147 + </div> 148 + </section> 149 + </div> 150 + </template>
+101
src/views/EventsView.vue
··· 1 + <script setup> 2 + import { ref, onMounted } from 'vue' 3 + import { api } from '../api.js' 4 + 5 + const events = ref([]) 6 + const loading = ref(true) 7 + const actionLoading = ref(null) 8 + 9 + async function load() { 10 + try { 11 + events.value = await api.get('/events') 12 + } 13 + finally { 14 + loading.value = false 15 + } 16 + } 17 + 18 + async function activate(id) { 19 + actionLoading.value = id 20 + try { 21 + await api.patch('/events/' + id + '/activate', {}) 22 + await load() 23 + } 24 + finally { 25 + actionLoading.value = null 26 + } 27 + } 28 + 29 + async function deactivate(id) { 30 + actionLoading.value = id 31 + try { 32 + await api.patch('/events/' + id + '/deactivate', {}) 33 + await load() 34 + } 35 + finally { 36 + actionLoading.value = null 37 + } 38 + } 39 + 40 + function fmtDate(dateStr) { 41 + if (!dateStr) return '-' 42 + return new Date(dateStr).toLocaleDateString([], { dateStyle: 'medium' }) 43 + } 44 + 45 + onMounted(load) 46 + </script> 47 + 48 + <template> 49 + <div> 50 + <h1 class="text-2xl font-semibold mb-6">Events</h1> 51 + 52 + <div v-if="loading" class="text-zinc-600 text-sm py-12 text-center">loading...</div> 53 + <div v-else-if="events.length === 0" class="text-zinc-600 text-sm py-16 text-center border border-dashed border-zinc-800 rounded-xl"> 54 + no events found 55 + </div> 56 + 57 + <div v-else class="space-y-3"> 58 + <div 59 + v-for="evt in events" 60 + :key="evt._id" 61 + class="bg-zinc-900 border rounded-xl p-5 flex items-center gap-4 transition-colors" 62 + :class="evt.active ? 'border-indigo-700/60' : 'border-zinc-800'" 63 + > 64 + <!-- left: info --> 65 + <div class="flex-1 min-w-0"> 66 + <div class="flex items-center gap-2 flex-wrap"> 67 + <span class="font-semibold text-zinc-100">{{ evt.name }}</span> 68 + <span v-if="evt.active" class="text-xs bg-indigo-900/60 text-indigo-400 px-2 py-0.5 rounded-full font-mono">active</span> 69 + </div> 70 + <div class="flex items-center flex-wrap gap-x-4 gap-y-1 mt-1.5 text-xs text-zinc-500"> 71 + <span class="font-mono">{{ evt.matchCount ?? 0 }} matches</span> 72 + <span v-if="(evt.activeMatchCount ?? 0) > 0" class="text-emerald-400 font-mono">{{ evt.activeMatchCount }} live</span> 73 + <span class="font-mono">{{ evt.playerCount ?? 0 }} players</span> 74 + <span>created {{ fmtDate(evt.createdAt) }}</span> 75 + <span v-if="evt.tournamentSlug" class="font-mono text-zinc-600">{{ evt.tournamentSlug }}</span> 76 + </div> 77 + </div> 78 + 79 + <!-- right: action --> 80 + <div class="shrink-0"> 81 + <button 82 + v-if="!evt.active" 83 + class="text-sm px-4 py-2 bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-white rounded-lg transition-colors font-medium" 84 + :disabled="actionLoading === evt._id" 85 + @click="activate(evt._id)" 86 + > 87 + {{ actionLoading === evt._id ? '...' : 'set active' }} 88 + </button> 89 + <button 90 + v-else 91 + class="text-sm px-4 py-2 bg-zinc-700 hover:bg-zinc-600 disabled:opacity-50 text-zinc-300 rounded-lg transition-colors font-medium" 92 + :disabled="actionLoading === evt._id" 93 + @click="deactivate(evt._id)" 94 + > 95 + {{ actionLoading === evt._id ? '...' : 'deactivate' }} 96 + </button> 97 + </div> 98 + </div> 99 + </div> 100 + </div> 101 + </template>
+299
src/views/MatchDetailView.vue
··· 1 + <script setup> 2 + import { ref, computed, onMounted, onUnmounted } from 'vue' 3 + import { useRoute, useRouter } from 'vue-router' 4 + import { api } from '../api.js' 5 + import StatusBadge from '../components/StatusBadge.vue' 6 + 7 + const route = useRoute() 8 + const router = useRouter() 9 + const match = ref(null) 10 + const loading = ref(true) 11 + let pollInterval = null 12 + 13 + async function load() { 14 + try { 15 + match.value = await api.get('/matches/' + route.params.id) 16 + } 17 + catch (err) { 18 + console.error('match load error:', err) 19 + } 20 + finally { 21 + loading.value = false 22 + } 23 + } 24 + 25 + onMounted(() => { 26 + load() 27 + // faster poll on the detail view so live updates feel snappy 28 + pollInterval = setInterval(load, 5_000) 29 + }) 30 + onUnmounted(() => clearInterval(pollInterval)) 31 + 32 + const p1 = computed(() => match.value?.players?.[0]) 33 + const p2 = computed(() => match.value?.players?.[1]) 34 + 35 + function getName(player) { 36 + return player?.serverNickname 37 + ?? player?.spinshareUsername 38 + ?? player?.discordDisplayName 39 + ?? player?.discordUsername 40 + ?? player?.displayName 41 + ?? '?' 42 + } 43 + 44 + // format raw score numbers into human-readable strings 45 + function fmtScore(n) { 46 + if (n == null) return '-' 47 + if (n >= 1_000_000) return (n / 1_000_000).toFixed(2) + 'M' 48 + if (n >= 1_000) return (n / 1_000).toFixed(1) + 'K' 49 + return String(n) 50 + } 51 + 52 + function fmtTime(dateStr) { 53 + if (!dateStr) return '-' 54 + return new Date(dateStr).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' }) 55 + } 56 + 57 + function fmtDuration(start, end) { 58 + if (!start) return null 59 + const ms = new Date(end ?? Date.now()) - new Date(start) 60 + const m = Math.floor(ms / 60_000) 61 + const s = Math.floor((ms % 60_000) / 1000) 62 + return `${m}m ${s}s` 63 + } 64 + 65 + const feedIcon = type => ({ 66 + 'match.start': '🏁', 67 + 'match.end': '🏆', 68 + 'match.abandoned': '❌', 69 + 'ban': '🚫', 70 + 'pick': '📌', 71 + 'result': '✅', 72 + 'ready': '✓', 73 + 'tiebreaker': '⚡', 74 + 'tiebreaker-pick': '⚡', 75 + })[type] ?? '•' 76 + 77 + // P1/P2 label for each ban slot in the ban order 78 + const banOrderSlots = computed(() => { 79 + if (!match.value?.banPhase?.banOrder) return [] 80 + return match.value.banPhase.banOrder.map(discordId => { 81 + const p = match.value.players.find(p => p.discordId === discordId) 82 + return p ? (p.slot === 1 ? 'P1' : 'P2') : '?' 83 + }) 84 + }) 85 + 86 + function chartBorderCls(chart) { 87 + if (chart.status?.isBeingPlayed) return 'border-blue-500 ring-1 ring-blue-400/20' 88 + if (chart.status?.banned) return 'border-red-800/50' 89 + if (chart.isTiebreaker && !chart.status?.played) return 'border-violet-600/60' 90 + if (chart.status?.played) return 'border-emerald-700/50' 91 + return 'border-zinc-700/60' 92 + } 93 + </script> 94 + 95 + <template> 96 + <div> 97 + <button 98 + class="flex items-center gap-1.5 text-sm text-zinc-500 hover:text-zinc-300 mb-6 transition-colors" 99 + @click="router.back()" 100 + > 101 + ← back 102 + </button> 103 + 104 + <div v-if="loading" class="text-zinc-600 text-sm py-12 text-center">loading...</div> 105 + <div v-else-if="!match" class="text-zinc-600 text-sm py-12 text-center">match not found</div> 106 + 107 + <div v-else> 108 + <!-- match header --> 109 + <div class="flex items-start justify-between mb-8 gap-4"> 110 + <div> 111 + <h1 class="text-2xl font-semibold">{{ match.meta?.name ?? 'Match' }}</h1> 112 + <div class="flex items-center flex-wrap gap-2 mt-1.5"> 113 + <span class="text-zinc-500 text-sm">{{ match.meta?.round }}</span> 114 + <span v-if="match.meta?.bestOf" class="text-xs bg-zinc-800 text-zinc-400 px-2 py-0.5 rounded font-mono">bo{{ match.meta.bestOf }}</span> 115 + <span v-if="match.meta?.type === 'friendly'" class="text-xs bg-violet-900/40 text-violet-400 px-2 py-0.5 rounded font-mono">friendly</span> 116 + <span v-if="match.meta?.startedAt" class="text-xs text-zinc-600 font-mono"> 117 + {{ fmtDuration(match.meta.startedAt, match.meta.completedAt) }} 118 + </span> 119 + </div> 120 + </div> 121 + <StatusBadge :progressLevel="match.progressLevel" :status="match.status" /> 122 + </div> 123 + 124 + <!-- player panels --> 125 + <div class="grid grid-cols-2 gap-4 mb-6"> 126 + <div 127 + v-for="(player, i) in [p1, p2]" 128 + :key="i" 129 + class="bg-zinc-900 border rounded-xl p-4" 130 + :class="player?.winner ? 'border-emerald-700/60' : 'border-zinc-800'" 131 + > 132 + <div class="flex items-center gap-3 mb-4"> 133 + <div class="relative shrink-0"> 134 + <img 135 + v-if="player?.spinshareAvatarUrl || player?.avatarUrl" 136 + :src="player.spinshareAvatarUrl ?? player.avatarUrl" 137 + class="w-12 h-12 rounded-full bg-zinc-800 object-cover" 138 + onerror="this.style.display='none'" 139 + /> 140 + <div v-else class="w-12 h-12 rounded-full bg-zinc-800 flex items-center justify-center text-zinc-500">?</div> 141 + <span v-if="player?.winner" class="absolute -top-1 -right-1 text-base">🏆</span> 142 + </div> 143 + <div class="min-w-0"> 144 + <div class="font-semibold text-zinc-100 truncate">{{ getName(player) }}</div> 145 + <div v-if="player?.pronouns" class="text-xs text-zinc-500">{{ player.pronouns }}</div> 146 + <div v-if="player?.discordUsername" class="text-xs text-zinc-600 font-mono">@{{ player.discordUsername }}</div> 147 + </div> 148 + </div> 149 + <div class="text-center py-2"> 150 + <div class="text-5xl font-bold font-mono" :class="player?.winner ? 'text-emerald-400' : 'text-zinc-100'"> 151 + {{ player?.points ?? 0 }} 152 + </div> 153 + <div class="text-xs text-zinc-600 mt-1">pts</div> 154 + </div> 155 + <!-- ready state during ready-check --> 156 + <div 157 + v-if="match.progressLevel === 'ready-check'" 158 + class="mt-3 text-center text-xs font-medium" 159 + :class="player?.ready ? 'text-emerald-400' : 'text-zinc-600'" 160 + > 161 + {{ player?.ready ? '✓ ready' : 'waiting...' }} 162 + </div> 163 + </div> 164 + </div> 165 + 166 + <!-- ban phase panel --> 167 + <div 168 + v-if="match.progressLevel === 'ban-phase' && match.banPhase" 169 + class="bg-zinc-900 border border-amber-800/40 rounded-xl p-4 mb-6" 170 + > 171 + <div class="flex items-center justify-between mb-3"> 172 + <h2 class="font-medium text-amber-400 text-sm tracking-wide uppercase text-xs">Ban Phase</h2> 173 + <span class="text-xs text-zinc-500 font-mono">{{ match.banPhase.bansCompleted }}/{{ match.banPhase.totalBans }} bans done</span> 174 + </div> 175 + 176 + <!-- ban order visualization --> 177 + <div class="flex items-center gap-1.5 mb-3 flex-wrap"> 178 + <span 179 + v-for="(slot, i) in banOrderSlots" 180 + :key="i" 181 + class="w-9 h-9 rounded-lg flex items-center justify-center text-xs font-mono font-semibold border transition-all" 182 + :class="{ 183 + 'bg-amber-500 text-zinc-900 border-amber-400 scale-110': i === match.banPhase.bansCompleted, 184 + 'bg-zinc-800 text-zinc-300 border-zinc-700': i > match.banPhase.bansCompleted, 185 + 'bg-zinc-900 text-zinc-700 border-zinc-800/50 line-through': i < match.banPhase.bansCompleted, 186 + }" 187 + >{{ slot }}</span> 188 + </div> 189 + 190 + <div v-if="match.banPhase.currentBannerDiscordId" class="text-sm text-zinc-400"> 191 + banning now: 192 + <span class="text-amber-300 font-semibold ml-1"> 193 + {{ getName(match.players?.find(p => p.discordId === match.banPhase.currentBannerDiscordId)) }} 194 + </span> 195 + </div> 196 + </div> 197 + 198 + <!-- currently picking panel --> 199 + <div 200 + v-if="['picking-post-result', 'check-in'].includes(match.progressLevel) && match.currentPickerDiscordId" 201 + class="bg-zinc-900 border border-emerald-800/40 rounded-xl p-4 mb-6 text-sm text-zinc-400" 202 + > 203 + picking next: 204 + <span class="text-emerald-300 font-semibold ml-1"> 205 + {{ getName(match.players?.find(p => p.discordId === match.currentPickerDiscordId)) }} 206 + </span> 207 + </div> 208 + 209 + <!-- mappool grid --> 210 + <section class="mb-6"> 211 + <h2 class="font-semibold text-zinc-200 mb-3">Mappool</h2> 212 + <div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-3"> 213 + <div 214 + v-for="(chart, i) in match.mappool" 215 + :key="i" 216 + class="relative rounded-xl overflow-hidden border bg-zinc-900 aspect-square" 217 + :class="chartBorderCls(chart)" 218 + > 219 + <!-- album art background --> 220 + <img 221 + v-if="chart.thumbnailUrl || chart.cover" 222 + :src="chart.thumbnailUrl ?? chart.cover" 223 + class="absolute inset-0 w-full h-full object-cover" 224 + onerror="this.style.display='none'" 225 + /> 226 + 227 + <!-- gradient overlay so text is always readable --> 228 + <div class="absolute inset-0 bg-gradient-to-t from-black/95 via-black/50 to-black/10" /> 229 + 230 + <!-- banned overlay --> 231 + <div v-if="chart.status?.banned" class="absolute inset-0 bg-red-950/70 flex items-center justify-center"> 232 + <span class="text-red-400 text-3xl font-bold drop-shadow">✕</span> 233 + </div> 234 + 235 + <!-- currently playing pulse ring --> 236 + <div v-if="chart.status?.isBeingPlayed" class="absolute inset-0 rounded-xl animate-pulse border-2 border-blue-400 pointer-events-none" /> 237 + 238 + <!-- tiebreaker tag --> 239 + <div v-if="chart.isTiebreaker" class="absolute top-2 left-2"> 240 + <span class="text-xs bg-violet-600/90 text-white px-1.5 py-0.5 rounded font-mono backdrop-blur-sm">TB</span> 241 + </div> 242 + 243 + <!-- difficulty badge --> 244 + <div v-if="chart.difficulty != null" class="absolute top-2 right-2"> 245 + <span class="text-xs bg-black/60 text-zinc-300 px-1.5 py-0.5 rounded font-mono backdrop-blur-sm">{{ chart.difficulty }}</span> 246 + </div> 247 + 248 + <!-- info (bottom) --> 249 + <div class="absolute bottom-0 left-0 right-0 p-2.5"> 250 + <div class="text-xs font-semibold text-zinc-100 leading-tight truncate drop-shadow"> 251 + {{ chart.title ?? chart.displayName ?? '?' }} 252 + </div> 253 + <div v-if="chart.charter" class="text-xs text-zinc-400 truncate mt-0.5">{{ chart.charter }}</div> 254 + 255 + <!-- result scores --> 256 + <div v-if="chart.result && chart.status?.played" class="flex items-center gap-1 mt-1.5"> 257 + <span class="text-xs font-mono" :class="chart.result.winnerSlot === 1 ? 'text-emerald-400 font-bold' : 'text-zinc-500'"> 258 + {{ fmtScore(chart.result.score1) }} 259 + <span v-if="chart.result.pfc1" class="text-violet-400 ml-0.5">PFC</span> 260 + <span v-else-if="chart.result.fc1" class="text-yellow-400 ml-0.5">FC</span> 261 + </span> 262 + <span class="text-zinc-700 text-xs">–</span> 263 + <span class="text-xs font-mono" :class="chart.result.winnerSlot === 2 ? 'text-emerald-400 font-bold' : 'text-zinc-500'"> 264 + {{ fmtScore(chart.result.score2) }} 265 + <span v-if="chart.result.pfc2" class="text-violet-400 ml-0.5">PFC</span> 266 + <span v-else-if="chart.result.fc2" class="text-yellow-400 ml-0.5">FC</span> 267 + </span> 268 + </div> 269 + 270 + <!-- status label for special states --> 271 + <div v-if="chart.status?.isBeingPlayed" class="mt-1"> 272 + <span class="text-xs text-blue-400 font-mono animate-pulse">● playing</span> 273 + </div> 274 + </div> 275 + </div> 276 + </div> 277 + </section> 278 + 279 + <!-- match feed --> 280 + <section> 281 + <h2 class="font-semibold text-zinc-200 mb-3">Match Feed</h2> 282 + <div class="bg-zinc-900 border border-zinc-800 rounded-xl overflow-hidden"> 283 + <div v-if="!match.feed?.length" class="px-4 py-8 text-center text-zinc-600 text-sm">no events yet</div> 284 + <div 285 + v-for="(event, i) in [...(match.feed ?? [])].reverse()" 286 + :key="i" 287 + class="flex items-start gap-3 px-4 py-3 border-b border-zinc-800/40 last:border-0 hover:bg-zinc-800/20 transition-colors" 288 + > 289 + <span class="text-base shrink-0 mt-0.5 leading-none">{{ feedIcon(event.type) }}</span> 290 + <div class="flex-1 min-w-0"> 291 + <div class="text-sm text-zinc-300">{{ event.message }}</div> 292 + </div> 293 + <div class="text-xs text-zinc-700 font-mono shrink-0 mt-0.5">{{ fmtTime(event.timestamp) }}</div> 294 + </div> 295 + </div> 296 + </section> 297 + </div> 298 + </div> 299 + </template>
+148
src/views/MatchesView.vue
··· 1 + <script setup> 2 + import { ref, onMounted } from 'vue' 3 + import { useRoute, useRouter } from 'vue-router' 4 + import { api } from '../api.js' 5 + import MatchCard from '../components/MatchCard.vue' 6 + import StatusBadge from '../components/StatusBadge.vue' 7 + 8 + const route = useRoute() 9 + const router = useRouter() 10 + 11 + const matches = ref([]) 12 + const total = ref(0) 13 + const loading = ref(true) 14 + const statusFilter = ref(route.query.status ?? '') 15 + const skip = ref(0) 16 + const LIMIT = 24 17 + 18 + function getName(player) { 19 + return player?.serverNickname ?? player?.spinshareUsername ?? player?.discordDisplayName ?? player?.discordUsername ?? player?.displayName ?? '?' 20 + } 21 + 22 + async function load() { 23 + loading.value = true 24 + try { 25 + const res = await api.get('/matches', { 26 + status: statusFilter.value || undefined, 27 + limit: LIMIT, 28 + skip: skip.value, 29 + }) 30 + matches.value = res.matches 31 + total.value = res.total 32 + } 33 + finally { 34 + loading.value = false 35 + } 36 + } 37 + 38 + function setFilter(val) { 39 + statusFilter.value = val 40 + skip.value = 0 41 + router.replace({ query: val ? { status: val } : {} }) 42 + load() 43 + } 44 + 45 + function fmtTime(dateStr) { 46 + if (!dateStr) return '-' 47 + return new Date(dateStr).toLocaleString([], { dateStyle: 'short', timeStyle: 'short' }) 48 + } 49 + 50 + const filters = [ 51 + { val: '', label: 'All' }, 52 + { val: 'in_progress', label: 'Live' }, 53 + { val: 'completed', label: 'Completed' }, 54 + { val: 'abandoned', label: 'Abandoned' }, 55 + ] 56 + 57 + onMounted(load) 58 + </script> 59 + 60 + <template> 61 + <div> 62 + <div class="flex items-center justify-between mb-6"> 63 + <h1 class="text-2xl font-semibold">Matches</h1> 64 + <span class="text-sm text-zinc-600 font-mono">{{ total }} total</span> 65 + </div> 66 + 67 + <!-- filter tabs --> 68 + <div class="flex gap-2 mb-6"> 69 + <button 70 + v-for="f in filters" 71 + :key="f.val" 72 + class="px-3 py-1.5 rounded-lg text-sm font-medium transition-colors" 73 + :class="statusFilter === f.val 74 + ? 'bg-indigo-600 text-white' 75 + : 'bg-zinc-800 text-zinc-400 hover:text-zinc-200 hover:bg-zinc-700'" 76 + @click="setFilter(f.val)" 77 + >{{ f.label }}</button> 78 + </div> 79 + 80 + <div v-if="loading" class="text-zinc-600 text-sm py-12 text-center">loading...</div> 81 + <div v-else-if="matches.length === 0" class="text-zinc-600 text-sm py-16 text-center border border-dashed border-zinc-800 rounded-xl"> 82 + no matches found 83 + </div> 84 + 85 + <!-- card grid for live matches --> 86 + <div v-else-if="statusFilter === 'in_progress'" class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4"> 87 + <MatchCard v-for="m in matches" :key="m._id" :match="m" /> 88 + </div> 89 + 90 + <!-- table view for everything else --> 91 + <div v-else class="bg-zinc-900 border border-zinc-800 rounded-xl overflow-hidden"> 92 + <table class="w-full text-sm"> 93 + <thead> 94 + <tr class="border-b border-zinc-800"> 95 + <th class="text-left px-4 py-3 text-zinc-500 font-medium">Round</th> 96 + <th class="text-left px-4 py-3 text-zinc-500 font-medium">Players</th> 97 + <th class="text-center px-4 py-3 text-zinc-500 font-medium">Score</th> 98 + <th class="text-left px-4 py-3 text-zinc-500 font-medium">Status</th> 99 + <th class="text-left px-4 py-3 text-zinc-500 font-medium">Started</th> 100 + </tr> 101 + </thead> 102 + <tbody> 103 + <tr 104 + v-for="m in matches" 105 + :key="m._id" 106 + class="border-b border-zinc-800/50 hover:bg-zinc-800/30 transition-colors cursor-pointer" 107 + @click="$router.push('/matches/' + m._id)" 108 + > 109 + <td class="px-4 py-3 text-zinc-400 text-xs font-mono">{{ m.meta?.round ?? '-' }}</td> 110 + <td class="px-4 py-3"> 111 + <div class="flex items-center gap-2"> 112 + <img v-if="m.players?.[0]?.spinshareAvatarUrl" :src="m.players[0].spinshareAvatarUrl" class="w-6 h-6 rounded-full bg-zinc-800 shrink-0" onerror="this.style.display='none'" /> 113 + <span :class="m.players?.[0]?.winner ? 'text-emerald-400 font-medium' : 'text-zinc-200'">{{ getName(m.players?.[0]) }}</span> 114 + <span class="text-zinc-600">vs</span> 115 + <img v-if="m.players?.[1]?.spinshareAvatarUrl" :src="m.players[1].spinshareAvatarUrl" class="w-6 h-6 rounded-full bg-zinc-800 shrink-0" onerror="this.style.display='none'" /> 116 + <span :class="m.players?.[1]?.winner ? 'text-emerald-400 font-medium' : 'text-zinc-200'">{{ getName(m.players?.[1]) }}</span> 117 + </div> 118 + </td> 119 + <td class="px-4 py-3 text-center font-mono"> 120 + <span :class="m.players?.[0]?.winner ? 'text-emerald-400 font-bold' : 'text-zinc-300'">{{ m.players?.[0]?.points ?? 0 }}</span> 121 + <span class="text-zinc-600 mx-1">–</span> 122 + <span :class="m.players?.[1]?.winner ? 'text-emerald-400 font-bold' : 'text-zinc-300'">{{ m.players?.[1]?.points ?? 0 }}</span> 123 + </td> 124 + <td class="px-4 py-3"> 125 + <StatusBadge :progressLevel="m.progressLevel" :status="m.status" /> 126 + </td> 127 + <td class="px-4 py-3 text-zinc-600 font-mono text-xs">{{ fmtTime(m.meta?.startedAt) }}</td> 128 + </tr> 129 + </tbody> 130 + </table> 131 + </div> 132 + 133 + <!-- pagination --> 134 + <div v-if="total > LIMIT" class="flex items-center justify-center gap-3 mt-6"> 135 + <button 136 + class="px-4 py-2 bg-zinc-800 text-zinc-400 rounded-lg text-sm font-medium transition-colors hover:bg-zinc-700 disabled:opacity-30 disabled:cursor-not-allowed" 137 + :disabled="skip === 0" 138 + @click="skip = Math.max(0, skip - LIMIT); load()" 139 + >← prev</button> 140 + <span class="text-zinc-500 text-sm font-mono">{{ Math.floor(skip / LIMIT) + 1 }} / {{ Math.ceil(total / LIMIT) }}</span> 141 + <button 142 + class="px-4 py-2 bg-zinc-800 text-zinc-400 rounded-lg text-sm font-medium transition-colors hover:bg-zinc-700 disabled:opacity-30 disabled:cursor-not-allowed" 143 + :disabled="skip + LIMIT >= total" 144 + @click="skip += LIMIT; load()" 145 + >next →</button> 146 + </div> 147 + </div> 148 + </template>
+104
src/views/PlayersView.vue
··· 1 + <script setup> 2 + import { ref, onMounted } from 'vue' 3 + import { api } from '../api.js' 4 + 5 + const players = ref([]) 6 + const total = ref(0) 7 + const loading = ref(true) 8 + const search = ref('') 9 + const skip = ref(0) 10 + const LIMIT = 60 11 + let searchTimeout = null 12 + 13 + async function load() { 14 + loading.value = true 15 + try { 16 + const res = await api.get('/players', { 17 + search: search.value || undefined, 18 + limit: LIMIT, 19 + skip: skip.value, 20 + }) 21 + players.value = res.players 22 + total.value = res.total 23 + } 24 + finally { 25 + loading.value = false 26 + } 27 + } 28 + 29 + function onSearch() { 30 + clearTimeout(searchTimeout) 31 + skip.value = 0 32 + searchTimeout = setTimeout(load, 280) 33 + } 34 + 35 + function getName(p) { 36 + return p.gamerTag ?? p.spinshareUsername ?? p.discordId ?? '?' 37 + } 38 + 39 + function getPronouns(p) { 40 + return p.spinsharePronouns ?? p.csvPronouns ?? null 41 + } 42 + 43 + onMounted(load) 44 + </script> 45 + 46 + <template> 47 + <div> 48 + <div class="flex items-center justify-between mb-6"> 49 + <h1 class="text-2xl font-semibold">Players</h1> 50 + <span class="text-sm text-zinc-600 font-mono">{{ total }} total</span> 51 + </div> 52 + 53 + <input 54 + v-model="search" 55 + type="text" 56 + placeholder="search by name or spinshare username..." 57 + class="w-full bg-zinc-900 border border-zinc-700 text-zinc-100 rounded-xl px-4 py-2.5 text-sm mb-6 placeholder-zinc-600 focus:outline-none focus:border-indigo-500 transition-colors" 58 + @input="onSearch" 59 + /> 60 + 61 + <div v-if="loading" class="text-zinc-600 text-sm py-12 text-center">loading...</div> 62 + <div v-else-if="players.length === 0" class="text-zinc-600 text-sm py-16 text-center border border-dashed border-zinc-800 rounded-xl"> 63 + no players found 64 + </div> 65 + 66 + <div v-else class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-3"> 67 + <div 68 + v-for="player in players" 69 + :key="player._id" 70 + class="bg-zinc-900 border border-zinc-800 rounded-xl p-3.5 flex items-center gap-3 hover:border-zinc-700 transition-colors" 71 + > 72 + <img 73 + v-if="player.spinshareAvatarUrl" 74 + :src="player.spinshareAvatarUrl" 75 + class="w-10 h-10 rounded-full bg-zinc-800 object-cover shrink-0" 76 + onerror="this.style.display='none'" 77 + /> 78 + <div v-else class="w-10 h-10 rounded-full bg-zinc-800 flex items-center justify-center text-zinc-600 shrink-0 text-sm select-none">?</div> 79 + <div class="min-w-0"> 80 + <div class="font-medium text-zinc-100 text-sm truncate">{{ getName(player) }}</div> 81 + <div v-if="getPronouns(player)" class="text-xs text-zinc-500 mt-0.5">{{ getPronouns(player) }}</div> 82 + <div v-if="player.spinshareUsername && player.spinshareUsername !== player.gamerTag" class="text-xs text-zinc-600 font-mono truncate mt-0.5"> 83 + {{ player.spinshareUsername }} 84 + </div> 85 + </div> 86 + </div> 87 + </div> 88 + 89 + <!-- pagination --> 90 + <div v-if="total > LIMIT" class="flex items-center justify-center gap-3 mt-6"> 91 + <button 92 + class="px-4 py-2 bg-zinc-800 text-zinc-400 rounded-lg text-sm font-medium transition-colors hover:bg-zinc-700 disabled:opacity-30 disabled:cursor-not-allowed" 93 + :disabled="skip === 0" 94 + @click="skip = Math.max(0, skip - LIMIT); load()" 95 + >← prev</button> 96 + <span class="text-zinc-500 text-sm font-mono">{{ Math.floor(skip / LIMIT) + 1 }} / {{ Math.ceil(total / LIMIT) }}</span> 97 + <button 98 + class="px-4 py-2 bg-zinc-800 text-zinc-400 rounded-lg text-sm font-medium transition-colors hover:bg-zinc-700 disabled:opacity-30 disabled:cursor-not-allowed" 99 + :disabled="skip + LIMIT >= total" 100 + @click="skip += LIMIT; load()" 101 + >next →</button> 102 + </div> 103 + </div> 104 + </template>
+13
tailwind.config.js
··· 1 + /** @type {import('tailwindcss').Config} */ 2 + export default { 3 + content: ['./index.html', './src/**/*.{vue,js}'], 4 + theme: { 5 + extend: { 6 + fontFamily: { 7 + sans: ['Inter', 'ui-sans-serif', 'system-ui', 'sans-serif'], 8 + mono: ['JetBrains Mono', 'ui-monospace', 'monospace'], 9 + }, 10 + }, 11 + }, 12 + plugins: [], 13 + }
+20
vite.config.js
··· 1 + import { defineConfig } from 'vite' 2 + import vue from '@vitejs/plugin-vue' 3 + import { fileURLToPath, URL } from 'node:url' 4 + 5 + export default defineConfig({ 6 + plugins: [vue()], 7 + resolve: { 8 + alias: { 9 + '@': fileURLToPath(new URL('./src', import.meta.url)), 10 + }, 11 + }, 12 + server: { 13 + proxy: { 14 + '/api': { 15 + target: 'http://localhost:3001', 16 + changeOrigin: true, 17 + }, 18 + }, 19 + }, 20 + })