Finished API integration

This commit is contained in:
2025-10-30 21:24:32 +03:30
parent 305170f185
commit 03d13d432a
11 changed files with 636 additions and 339 deletions

View File

@@ -0,0 +1,110 @@
<script setup lang="ts">
import { ref } from "vue";
const props = defineProps<{
name: string;
totalTrackers: number;
magnetUrl: string;
}>();
const copied = ref(false);
function copyMagnet() {
navigator.clipboard.writeText(decodeURIComponent(props.magnetUrl));
copied.value = true;
setTimeout(() => (copied.value = false), 2000);
}
</script>
<template>
<div class="w-full max-w-2xl mx-auto ">
<div class="rounded-2xl border bg-base-100 shadow-lg p-6 space-y-4">
<!-- Title and trackers -->
<div class="flex items-center justify-between">
<h2 class="text-lg font-semibold wrap-break-word flex-1">
{{ name }}
</h2>
<span class="badge badge-outline whitespace-nowrap ml-3">
{{ totalTrackers }} trackers
</span>
</div>
<!-- Magnet link with copy -->
<div class="form-control">
<label class="label">
<span class="label-text font-medium">Maxed Out Magnet Link</span>
</label>
<div class="flex items-center gap-2">
<input
type="url"
:value="decodeURIComponent(props.magnetUrl)"
readonly
class="input input-bordered w-full font-medium text-xs"
/>
<button
v-auto-animate
class="btn btn-square btn-primary text-accent"
@click="copyMagnet"
:title="copied ? 'Copied!' : 'Copy magnet link'"
>
<!-- Default copy icon -->
<svg v-if="!copied" xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round"
d="M15.666 3.888A2.25 2.25 0 0 0 13.5
2.25h-3c-1.03 0-1.9.693-2.166
1.638m7.332 0c.055.194.084.4.084.612v0a.75.75
0 0 1-.75.75H9a.75.75 0 0
1-.75-.75v0c0-.212.03-.418.084-.612m7.332
0c.646.049 1.288.11 1.927.184 1.1.128
1.907 1.077 1.907 2.185V19.5a2.25
2.25 0 0 1-2.25 2.25H6.75A2.25
2.25 0 0 1 4.5 19.5V6.257c0-1.108.806-2.057
1.907-2.185a48.208 48.208 0 0 1
1.927-.184" />
</svg>
<!-- Success icon -->
<svg v-else xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round"
d="M11.35 3.836c-.065.21-.1.433-.1.664
0 .414.336.75.75.75h4.5a.75.75
0 0 0 .75-.75 2.25 2.25 0 0
0-.1-.664m-5.8 0A2.251 2.251
0 0 1 13.5 2.25H15c1.012 0
1.867.668 2.15 1.586m-5.8
0c-.376.023-.75.05-1.124.08C9.095
4.01 8.25 4.973 8.25 6.108V8.25m8.9-4.414c.376.023.75.05
1.124.08 1.131.094 1.976 1.057
1.976 2.192V16.5A2.25 2.25
0 0 1 18 18.75h-2.25m-7.5-10.5H4.875c-.621
0-1.125.504-1.125 1.125v11.25c0
.621.504 1.125 1.125 1.125h9.75c.621
0 1.125-.504 1.125-1.125V18.75m-7.5-10.5h6.375c.621
0 1.125.504 1.125 1.125v9.375m-8.25-3
1.5 1.5 3-3.75" />
</svg>
</button>
</div>
</div>
<!-- Info alert -->
<div class="alert alert-soft mt-2">
<svg xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 24 24"
class="stroke-current shrink-0 w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21
12a9 9 0 11-18 0 9 9 0 0118
0z"/>
</svg>
<span>
This magnet link has been enriched with additional trackers for better availability.
</span>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,87 @@
<script setup lang="ts">
import { ref } from "vue";
const emit = defineEmits(["submit"]);
const magnetUrl = ref("");
const error = ref("");
function isMagnetLink(url: string): boolean {
const magnetRegex =
/^magnet:\?xt=urn:btih:(?:[A-F0-9]{40}|[A-Z2-7]{32})(?:&[a-z0-9]+=[^&]*)*$/i;
return magnetRegex.test(url.trim());
}
function handleSubmit() {
if (!isMagnetLink(magnetUrl.value)) {
error.value = "Invalid magnet URL";
return;
}
error.value = "";
emit("submit", magnetUrl.value);
}
</script>
<template>
<div class="w-full">
<div
class="flex items-center w-full rounded-2xl shadow-lg px-4 py-2 transition-all duration-500 focus-within:ring-2"
:class="
error
? 'border-2 border-red-500 bg-base-200'
: 'border border-primary bg-base-100 focus-within:ring-primary'
"
>
<!-- Left icon -->
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="size-5 mr-3 transition-colors duration-500"
:class="error ? 'text-red-500' : 'text-gray-400'"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244"
/>
</svg>
<!-- Input -->
<input
v-model="magnetUrl"
type="text"
placeholder="Enter magnet URL"
class="flex-1 bg-transparent outline-none text-base"
/>
<!-- Right circular button -->
<button
class="ml-3 w-10 h-10 flex items-center justify-center rounded-full bg-primary text-accent hover:scale-110 transition-transform duration-300 shadow-md"
@click="handleSubmit"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="size-5"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M9.813 15.904 9 18.75l-.813-2.846a4.5 4.5 0 0 0-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 0 0 3.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 0 0 3.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 0 0-3.09 3.09ZM18.259 8.715 18 9.75l-.259-1.035a3.375 3.375 0 0 0-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 0 0 2.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 0 0 2.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 0 0-2.456 2.456ZM16.894 20.567 16.5 21.75l-.394-1.183a2.25 2.25 0 0 0-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 0 0 1.423-1.423l.394-1.183.394 1.183a2.25 2.25 0 0 0 1.423 1.423l1.183.394-1.183.394a2.25 2.25 0 0 0-1.423 1.423Z"
/>
</svg>
</button>
</div>
<!-- Error text -->
<p v-motion-fade v-if="error" class="mt-2 text-sm text-red-500">
{{ error }}
</p>
</div>
</template>

View File

@@ -1,201 +1,104 @@
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { useMotion } from '@vueuse/motion'
import MagnetCard from "~/components/MagnetCard.vue";
import { ref } from "vue";
const magnetInput = ref('')
const isLoading = ref(false)
// Light bar particles
interface Particle {
id: number;
x: number;
y: number;
opacity: number;
speed: number;
size: number;
symbol: string;
interface MaxedMagnetResponse {
totalTrackers: number;
name?: string;
id: string;
maxedMagnet: string;
}
const particles = ref<Particle[]>([])
const maxedMagnet = ref<MaxedMagnetResponse | null>(null);
const error = ref<string | null>(null);
const loading = ref(false);
onMounted(() => {
if (process.client) {
initializeParticles()
}
})
async function getMaxedMagnetUrl(magnet: string) {
error.value = null; // Clear any previous error
loading.value = true; // Set loading to true
const symbols = ['✦', '✧', '★', '●', '◈', '◇', '◈']
try {
const response = await fetch("/api/magnet", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ magnet }),
});
const initializeParticles = () => {
if (typeof window === 'undefined') return
const particleCount = 20
particles.value = []
for (let i = 0; i < particleCount; i++) {
particles.value.push({
id: i,
x: Math.random() * window.innerWidth,
y: Math.random() * 60, // Start from top area where light bar is
opacity: Math.random() * 0.4 + 0.2,
speed: Math.random() * 0.8 + 0.2,
size: Math.random() * 8 + 4,
symbol: symbols[Math.floor(Math.random() * symbols.length)]
})
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
error.value =
errorData.message || `HTTP error! status: ${response.status}`;
console.error("API error:", error.value);
return;
}
// Start animation
animateParticles()
maxedMagnet.value = await response.json();
} catch (err) {
error.value =
err instanceof Error ? err.message : "An unknown error occurred";
console.error("Network error:", err);
} finally {
loading.value = false; // Reset loading state
}
let animationFrameId: number
const animateParticles = () => {
particles.value.forEach(particle => {
// Move particles down
particle.y += particle.speed
// Reset particles that go off screen
if (particle.y > window.innerHeight) {
particle.y = Math.random() * 20
particle.x = Math.random() * window.innerWidth
}
})
// Continue animation
animationFrameId = requestAnimationFrame(animateParticles)
}
const addTrackers = async () => {
if (!magnetInput.value.trim()) return
isLoading.value = true
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 1500))
isLoading.value = false
// Here you would implement the actual tracker addition logic
console.log('Adding trackers to:', magnetInput.value)
}
// Clean up animation on component unmount
onUnmounted(() => {
if (animationFrameId) {
cancelAnimationFrame(animationFrameId)
}
})
</script>
<template>
<div class="min-h-screen bg-black text-white overflow-hidden relative">
<!-- Single expanding radial gradient for seamless light -->
<div
v-motion
:initial="{ width: '0px', height: '0px', top: '-20%', left: '50%', transform: 'translateX(-50%)' }"
:visibleOnce="{
width: '200vw',
height: '200vh',
transition: { duration: 3000, ease: 'cubic-bezier(0.3, 0.7, 0.4, 1.0)' }
}"
class="absolute z-0 opacity-40"
:style="{
background: 'radial-gradient(circle at 50% 20%, rgba(59, 130, 246, 0.5), rgba(139, 92, 246, 0.25) 20%, transparent 50%)',
'background-size': '100% 100%',
'background-repeat': 'no-repeat'
}"
></div>
<!-- Additional bright center glow -->
<div
v-motion
:initial="{ opacity: 0 }"
:visibleOnce="{ opacity: 0.5, transition: { duration: 500, delay: 300 } }"
class="absolute top-[-10%] left-1/2 transform -translate-x-1/2 w-80 h-80 rounded-full bg-blue-400 blur-3xl z-0"
></div>
<!-- Falling particles -->
<div class="absolute inset-0 z-0">
<div
v-for="particle in particles"
:key="particle.id"
class="absolute text-blue-300/60 text-lg font-bold select-none pointer-events-none"
:style="{
left: particle.x + 'px',
top: particle.y + 'px',
opacity: particle.opacity,
fontSize: particle.size + 'px',
transform: 'translate(-50%, -50%)'
}"
>
{{ particle.symbol }}
</div>
</div>
<!-- Content -->
<div class="relative z-10 min-h-screen flex flex-col items-center justify-center p-6">
<!-- Title with subtle fade in -->
<div
v-motion
:initial="{ opacity: 0 }"
:visibleOnce="{ opacity: 1, transition: { duration: 1000 } }"
class="text-center mb-10"
>
<h1 class="text-4xl md:text-6xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-purple-500 mb-4 tracking-tight">
TorrentMax
</h1>
<p class="text-gray-400 max-w-md mx-auto">
Maximize your torrents with premium tracker integration
<div class="flex flex-col min-h-screen bg-base-300">
<div class="grow flex items-start justify-center pt-40 px-4">
<div class="w-full max-w-2xl space-y-6">
<div class="hero">
<div class="hero-content text-center">
<div class="max-w-md">
<h1 class="text-5xl font-bold drop-shadow-xl">TorrentMax</h1>
<p class="py-6">
Paste a magnet link below and TorrentMax will enrich it with
additional trackers
</p>
</div>
</div>
</div>
<SearchBar @submit="getMaxedMagnetUrl" />
<!-- Input and Button -->
<!-- Loading indicator -->
<div
v-motion
:initial="{ opacity: 0 }"
:visibleOnce="{ opacity: 1, transition: { duration: 1000, delay: 300 } }"
class="w-full max-w-2xl flex flex-col sm:flex-row gap-4"
v-motion-fade
v-if="loading"
class="flex justify-center items-center p-8"
>
<textarea
v-model="magnetInput"
placeholder="Enter magnet link or .torrent file content..."
class="flex-grow px-6 py-4 rounded-xl bg-gray-800/50 backdrop-blur-sm border border-gray-700 focus:border-blue-400 focus:ring-2 focus:ring-blue-500/30 text-white placeholder-gray-500 min-h-[60px] max-h-[120px] resize-none shadow-inner focus:shadow-blue-500/10 focus:shadow-lg transition-all duration-300"
rows="1"
></textarea>
<button
@click="addTrackers"
:disabled="isLoading"
class="px-8 py-4 bg-gradient-to-r from-blue-600 to-purple-600 rounded-xl font-medium text-white shadow-lg shadow-blue-500/20 hover:shadow-blue-500/40 hover:from-blue-500 hover:to-purple-600 transition-all duration-500 disabled:opacity-50 flex items-center justify-center whitespace-nowrap"
>
<span v-if="!isLoading" class="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" />
</svg>
Max It Out
</span>
<span v-else class="flex items-center">
<svg class="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Processing...
</span>
</button>
<span class="loading loading-infinity loading-lg"></span>
</div>
<div class="mt-10 text-center text-sm text-gray-600">
<p>Your torrents will be enhanced with premium trackers for maximum performance</p>
<!-- Error message display -->
<div v-if="error && !loading" class="max-w-2xl mx-auto p-4">
<div class="alert alert-error">
<svg
xmlns="http://www.w3.org/2000/svg"
class="stroke-current shrink-0 h-6 w-6"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<span>{{ error }}</span>
</div>
</div>
<MagnetCard
v-motion-fade
v-if="maxedMagnet && !loading"
:name="maxedMagnet.name || 'Unknown Torrent'"
:total-trackers="maxedMagnet.totalTrackers"
:magnet-url="maxedMagnet.maxedMagnet"
/>
</div>
</div>
</div>
</template>
<style scoped>
/* Simple fade in animation */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.fade-in {
animation: fadeIn 1s ease-in-out;
}
</style>

View File

@@ -1,2 +1,4 @@
@import "tailwindcss";
@plugin "daisyui";
@plugin "daisyui" {
themes: lemonade --default, abyss --prefersdark;
}

View File

@@ -4,7 +4,7 @@ import tailwindcss from "@tailwindcss/vite";
export default defineNuxtConfig({
compatibilityDate: '2025-07-15',
devtools: { enabled: true },
modules: ['@nuxt/eslint','@vueuse/motion/nuxt'],
modules: ['@nuxt/eslint','@vueuse/motion/nuxt','@formkit/auto-animate/nuxt'],
vite: {
plugins: [tailwindcss()],
},

View File

@@ -10,6 +10,7 @@
"postinstall": "nuxt prepare"
},
"dependencies": {
"@formkit/auto-animate": "^0.9.0",
"@nuxt/eslint": "1.10.0",
"@tailwindcss/vite": "^4.1.16",
"@vueuse/motion": "^3.0.3",
@@ -19,5 +20,8 @@
"tailwindcss": "^4.1.16",
"vue": "^3.5.22",
"vue-router": "^4.6.3"
},
"devDependencies": {
"typescript": "^5.9.3"
}
}

328
pnpm-lock.yaml generated
View File

@@ -8,15 +8,18 @@ importers:
.:
dependencies:
'@formkit/auto-animate':
specifier: ^0.9.0
version: 0.9.0
'@nuxt/eslint':
specifier: 1.10.0
version: 1.10.0(@typescript-eslint/utils@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.22)(eslint@9.38.0(jiti@2.6.1))(magicast@0.5.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))
version: 1.10.0(@typescript-eslint/utils@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.22)(eslint@9.38.0(jiti@2.6.1))(magicast@0.3.5)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))
'@tailwindcss/vite':
specifier: ^4.1.16
version: 4.1.16(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))
'@vueuse/motion':
specifier: ^3.0.3
version: 3.0.3(magicast@0.5.0)(vue@3.5.22(typescript@5.9.3))
version: 3.0.3(magicast@0.3.5)(vue@3.5.22(typescript@5.9.3))
daisyui:
specifier: ^5.3.10
version: 5.3.10
@@ -25,7 +28,7 @@ importers:
version: 9.38.0(jiti@2.6.1)
nuxt:
specifier: ^4.2.0
version: 4.2.0(@parcel/watcher@2.5.1)(@vue/compiler-sfc@3.5.22)(db0@0.3.4)(eslint@9.38.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1)
version: 4.2.0(@parcel/watcher@2.5.1)(@vue/compiler-sfc@3.5.22)(db0@0.3.4)(eslint@9.38.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1)
tailwindcss:
specifier: ^4.1.16
version: 4.1.16
@@ -35,6 +38,10 @@ importers:
vue-router:
specifier: ^4.6.3
version: 4.6.3(vue@3.5.22(typescript@5.9.3))
devDependencies:
typescript:
specifier: ^5.9.3
version: 5.9.3
packages:
@@ -363,8 +370,8 @@ packages:
resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
'@eslint/compat@1.4.0':
resolution: {integrity: sha512-DEzm5dKeDBPm3r08Ixli/0cmxr8LkRdwxMRUIJBlSCpAwSrvFEJpVBzV+66JhDxiaqKxnRzCXhtiMiczF7Hglg==}
'@eslint/compat@1.4.1':
resolution: {integrity: sha512-cfO82V9zxxGBxcQDr1lfaYB7wykTa0b00mGa36FrJl7iTFd0Z2cHfEYuxcBRP/iNijCsWsEkA+jzT8hGYmv33w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.40 || 9
@@ -376,8 +383,8 @@ packages:
resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/config-helpers@0.4.1':
resolution: {integrity: sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==}
'@eslint/config-helpers@0.4.2':
resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/config-inspector@1.3.0':
@@ -390,6 +397,10 @@ packages:
resolution: {integrity: sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/core@0.17.0':
resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/eslintrc@3.3.1':
resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -402,10 +413,13 @@ packages:
resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/plugin-kit@0.4.0':
resolution: {integrity: sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==}
'@eslint/plugin-kit@0.4.1':
resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@formkit/auto-animate@0.9.0':
resolution: {integrity: sha512-VhP4zEAacXS3dfTpJpJ88QdLqMTcabMg0jwpOSxZ/VzfQVfl3GkZSCZThhGC5uhq/TxPHPzW0dzr4H9Bb1OgKA==}
'@humanfs/core@0.19.1':
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
engines: {node: '>=18.18.0'}
@@ -425,6 +439,14 @@ packages:
'@ioredis/commands@1.4.0':
resolution: {integrity: sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ==}
'@isaacs/balanced-match@4.0.1':
resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
engines: {node: 20 || >=22}
'@isaacs/brace-expansion@5.0.0':
resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==}
engines: {node: 20 || >=22}
'@isaacs/cliui@8.0.2':
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'}
@@ -1006,8 +1028,8 @@ packages:
rollup:
optional: true
'@rollup/plugin-replace@6.0.2':
resolution: {integrity: sha512-7QaYCf8bqF04dOy7w/eHmJeNExxTYwvKAmlSAH/EaWWUzbT0h5sbF6bktFoX/0F/0qwng5/dWFMyf3gzaM8DsQ==}
'@rollup/plugin-replace@6.0.3':
resolution: {integrity: sha512-J4RZarRvQAm5IF0/LwUUg+obsm+xZhYnbMXmXROyoSE1ATJe3oXSb9L5MMppdxP2ylNSjv6zFBwKYjcKMucVfA==}
engines: {node: '>=14.0.0'}
peerDependencies:
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
@@ -1669,8 +1691,8 @@ packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
baseline-browser-mapping@2.8.20:
resolution: {integrity: sha512-JMWsdF+O8Orq3EMukbUN1QfbLK9mX2CkUmQBcW2T0s8OmdAUL5LLM/6wFwSrqXzlXB13yhyK9gTKS1rIizOduQ==}
baseline-browser-mapping@2.8.21:
resolution: {integrity: sha512-JU0h5APyQNsHOlAM7HnQnPToSDQoEBZqzu/YBlqDnEeymPnZDREeXJA3KBMQee+dKteAxZ2AtvQEvVYdZf241Q==}
hasBin: true
bindings@1.5.0:
@@ -1898,8 +1920,8 @@ packages:
engines: {node: '>=4'}
hasBin: true
cssnano-preset-default@7.0.9:
resolution: {integrity: sha512-tCD6AAFgYBOVpMBX41KjbvRh9c2uUjLXRyV7KHSIrwHiq5Z9o0TFfUCoM3TwVrRsRteN3sVXGNvjVNxYzkpTsA==}
cssnano-preset-default@7.0.10:
resolution: {integrity: sha512-6ZBjW0Lf1K1Z+0OKUAUpEN62tSXmYChXWi2NAA0afxEVsj9a+MbcB1l5qel6BHJHmULai2fCGRthCeKSFbScpA==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
@@ -1910,8 +1932,8 @@ packages:
peerDependencies:
postcss: ^8.4.32
cssnano@7.1.1:
resolution: {integrity: sha512-fm4D8ti0dQmFPeF8DXSAA//btEmqCOgAc/9Oa3C1LW94h5usNrJEfrON7b4FkPZgnDEn6OUs5NdxiJZmAtGOpQ==}
cssnano@7.1.2:
resolution: {integrity: sha512-HYOPBsNvoiFeR1eghKD5C3ASm64v9YVyJB4Ivnl2gqKoQYvjjN/G0rztvKQq8OxocUtC6sjqY8jwYngIB4AByA==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
@@ -2144,8 +2166,8 @@ packages:
eslint-import-resolver-node:
optional: true
eslint-plugin-jsdoc@61.1.10:
resolution: {integrity: sha512-ACsczYGax1Iu9zRBiG176I66cgL2nRt1TbMgE9TAzxoGKfBD9PjhA//K/JKk3uBk25RsYHj3TqMaAiy913IpEA==}
eslint-plugin-jsdoc@61.1.11:
resolution: {integrity: sha512-c+NQQOFd+ZTjFt0pfFMB8OTumExg0vf8mlJsOtLj6qTDGewtLh7bhwoDgBg6rIiTziYc8N4u4dYmSdAIn0yTEQ==}
engines: {node: '>=20.11.0'}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
@@ -2829,8 +2851,8 @@ packages:
magicast@0.3.5:
resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==}
magicast@0.5.0:
resolution: {integrity: sha512-D0cxqnb8DpO66P4LkD9ME6a4AhRK6A+xprXksD5vtsJN6G4zbzdI10vDaWCIyj3eLwjNZrQxUYB20FDhKrMEKQ==}
magicast@0.5.1:
resolution: {integrity: sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==}
mdn-data@2.0.28:
resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==}
@@ -2871,6 +2893,10 @@ packages:
resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
engines: {node: '>=12'}
minimatch@10.1.1:
resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==}
engines: {node: 20 || >=22}
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
@@ -2966,8 +2992,8 @@ packages:
node-mock-http@1.0.3:
resolution: {integrity: sha512-jN8dK25fsfnMrVsEhluUTPkBFY+6ybu7jSB1n+ri/vOGjJxU8J9CZhpSGkHXSkFjtUhbmoncG/YG9ta5Ludqog==}
node-releases@2.0.26:
resolution: {integrity: sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA==}
node-releases@2.0.27:
resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
nopt@8.1.0:
resolution: {integrity: sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==}
@@ -3180,20 +3206,20 @@ packages:
peerDependencies:
postcss: ^8.4.38
postcss-colormin@7.0.4:
resolution: {integrity: sha512-ziQuVzQZBROpKpfeDwmrG+Vvlr0YWmY/ZAk99XD+mGEBuEojoFekL41NCsdhyNUtZI7DPOoIWIR7vQQK9xwluw==}
postcss-colormin@7.0.5:
resolution: {integrity: sha512-ekIBP/nwzRWhEMmIxHHbXHcMdzd1HIUzBECaj5KEdLz9DVP2HzT065sEhvOx1dkLjYW7jyD0CngThx6bpFi2fA==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-convert-values@7.0.7:
resolution: {integrity: sha512-HR9DZLN04Xbe6xugRH6lS4ZQH2zm/bFh/ZyRkpedZozhvh+awAfbA0P36InO4fZfDhvYfNJeNvlTf1sjwGbw/A==}
postcss-convert-values@7.0.8:
resolution: {integrity: sha512-+XNKuPfkHTCEo499VzLMYn94TiL3r9YqRE3Ty+jP7UX4qjewUONey1t7CG21lrlTLN07GtGM8MqFVp86D4uKJg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-discard-comments@7.0.4:
resolution: {integrity: sha512-6tCUoql/ipWwKtVP/xYiFf1U9QgJ0PUvxN7pTcsQ8Ns3Fnwq1pU5D5s1MhT/XySeLq6GXNvn37U46Ded0TckWg==}
postcss-discard-comments@7.0.5:
resolution: {integrity: sha512-IR2Eja8WfYgN5n32vEGSctVQ1+JARfu4UH8M7bgGh1bC+xI/obsPJXaBpQF7MAByvgwZinhpHpdrmXtvVVlKcQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
@@ -3222,8 +3248,8 @@ packages:
peerDependencies:
postcss: ^8.4.32
postcss-merge-rules@7.0.6:
resolution: {integrity: sha512-2jIPT4Tzs8K87tvgCpSukRQ2jjd+hH6Bb8rEEOUDmmhOeTcqDg5fEFK8uKIu+Pvc3//sm3Uu6FRqfyv7YF7+BQ==}
postcss-merge-rules@7.0.7:
resolution: {integrity: sha512-njWJrd/Ms6XViwowaaCc+/vqhPG3SmXn725AGrnl+BgTuRPEacjiLEaGq16J6XirMJbtKkTwnt67SS+e2WGoew==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
@@ -3240,8 +3266,8 @@ packages:
peerDependencies:
postcss: ^8.4.32
postcss-minify-params@7.0.4:
resolution: {integrity: sha512-3OqqUddfH8c2e7M35W6zIwv7jssM/3miF9cbCSb1iJiWvtguQjlxZGIHK9JRmc8XAKmE2PFGtHSM7g/VcW97sw==}
postcss-minify-params@7.0.5:
resolution: {integrity: sha512-FGK9ky02h6Ighn3UihsyeAH5XmLEE2MSGH5Tc4tXMFtEDx7B+zTG6hD/+/cT+fbF7PbYojsmmWjyTwFwW1JKQQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
@@ -3288,8 +3314,8 @@ packages:
peerDependencies:
postcss: ^8.4.32
postcss-normalize-unicode@7.0.4:
resolution: {integrity: sha512-LvIURTi1sQoZqj8mEIE8R15yvM+OhbR1avynMtI9bUzj5gGKR/gfZFd8O7VMj0QgJaIFzxDwxGl/ASMYAkqO8g==}
postcss-normalize-unicode@7.0.5:
resolution: {integrity: sha512-X6BBwiRxVaFHrb2WyBMddIeB5HBjJcAaUHyhLrM2FsxSq5TFqcHSsK7Zu1otag+o0ZphQGJewGH1tAyrD0zX1Q==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
@@ -3312,8 +3338,8 @@ packages:
peerDependencies:
postcss: ^8.4.32
postcss-reduce-initial@7.0.4:
resolution: {integrity: sha512-rdIC9IlMBn7zJo6puim58Xd++0HdbvHeHaPgXsimMfG1ijC5A9ULvNLSE0rUKVJOvNMcwewW4Ga21ngyJjY/+Q==}
postcss-reduce-initial@7.0.5:
resolution: {integrity: sha512-RHagHLidG8hTZcnr4FpyMB2jtgd/OcyAazjMhoy5qmWJOx1uxKh4ntk0Pb46ajKM0rkf32lRH4C8c9qQiPR6IA==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
@@ -3556,8 +3582,8 @@ packages:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
engines: {node: '>=14'}
simple-git@3.28.0:
resolution: {integrity: sha512-Rs/vQRwsn1ILH1oBUy8NucJlXmnnLeLCfcvbSehkPzbv3wwoFWIdtfd6Ndo6ZPhlPsCZ60CPI4rxurnwAa+a2w==}
simple-git@3.29.0:
resolution: {integrity: sha512-PEBgFYc8plTys6/XuxinxAJ+6CbXVh+xxsBTOEXw/uYBd3sYlGGoyB12nX5rRPGsFrdnnZWb81qluSl7a83HtA==}
sirv@3.0.2:
resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==}
@@ -3674,8 +3700,8 @@ packages:
style-value-types@5.1.2:
resolution: {integrity: sha512-Vs9fNreYF9j6W2VvuDTP7kepALi7sk0xtk2Tu8Yxi9UoajJdEVpNpCov0HsLTqXvNGKX+Uv09pkozVITi1jf3Q==}
stylehacks@7.0.6:
resolution: {integrity: sha512-iitguKivmsueOmTO0wmxURXBP8uqOO+zikLGZ7Mm9e/94R4w5T999Js2taS/KBOnQ/wdC3jN3vNSrkGDrlnqQg==}
stylehacks@7.0.7:
resolution: {integrity: sha512-bJkD0JkEtbRrMFtwgpJyBbFIwfDDONQ1Ov3sDLZQP8HuJ73kBOyx66H4bOcAbVWmnfLdvQ0AJwXxOMkpujcO6g==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
@@ -3719,8 +3745,8 @@ packages:
tar-stream@3.1.7:
resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==}
tar@7.5.1:
resolution: {integrity: sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==}
tar@7.5.2:
resolution: {integrity: sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==}
engines: {node: '>=18'}
terser@5.44.0:
@@ -3804,8 +3830,8 @@ packages:
resolution: {integrity: sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==}
engines: {node: '>=20.18.1'}
unenv@2.0.0-rc.23:
resolution: {integrity: sha512-NeOb/HbW2OwOzYaV21MewVQYfzlSwG0kVUB74RyV0gEIP44M5DsYTK9e7jDcekB/3YU+pfNWniZj+r4M/aejyQ==}
unenv@2.0.0-rc.24:
resolution: {integrity: sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==}
unhead@2.0.19:
resolution: {integrity: sha512-gEEjkV11Aj+rBnY6wnRfsFtF2RxKOLaPN4i+Gx3UhBxnszvV6ApSNZbGk7WKyy/lErQ6ekPN63qdFL7sa1leow==}
@@ -3830,8 +3856,8 @@ packages:
resolution: {integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==}
engines: {node: '>=20.19.0'}
unplugin-vue-router@0.16.0:
resolution: {integrity: sha512-yFmUQoN07KABkbxMSaNvfjnflwSi3nkSVKi7v6FTwXlzXyRDSx63vQ8Se4ho0T9Ao9I8U5FJB12fzmrGxFB0CA==}
unplugin-vue-router@0.16.1:
resolution: {integrity: sha512-7A7gUVzLIYMBrBPKk8l4lZoZXDOrO8+etw6/RTrqG3OzpLUUZEXJFUW7+OyMIpQK93sEbdkR2z9ZNNl/r32FMw==}
peerDependencies:
'@vue/compiler-sfc': ^3.5.17
vue-router: ^4.6.0
@@ -4361,10 +4387,10 @@ snapshots:
dependencies:
mime: 3.0.0
'@dxup/nuxt@0.2.0(magicast@0.5.0)':
'@dxup/nuxt@0.2.0(magicast@0.3.5)':
dependencies:
'@dxup/unimport': 0.1.0
'@nuxt/kit': 4.2.0(magicast@0.5.0)
'@nuxt/kit': 4.2.0(magicast@0.3.5)
chokidar: 4.0.3
pathe: 2.0.3
tinyglobby: 0.2.15
@@ -4484,9 +4510,9 @@ snapshots:
'@eslint-community/regexpp@4.12.2': {}
'@eslint/compat@1.4.0(eslint@9.38.0(jiti@2.6.1))':
'@eslint/compat@1.4.1(eslint@9.38.0(jiti@2.6.1))':
dependencies:
'@eslint/core': 0.16.0
'@eslint/core': 0.17.0
optionalDependencies:
eslint: 9.38.0(jiti@2.6.1)
@@ -4498,9 +4524,9 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@eslint/config-helpers@0.4.1':
'@eslint/config-helpers@0.4.2':
dependencies:
'@eslint/core': 0.16.0
'@eslint/core': 0.17.0
'@eslint/config-inspector@1.3.0(eslint@9.38.0(jiti@2.6.1))':
dependencies:
@@ -4529,6 +4555,10 @@ snapshots:
dependencies:
'@types/json-schema': 7.0.15
'@eslint/core@0.17.0':
dependencies:
'@types/json-schema': 7.0.15
'@eslint/eslintrc@3.3.1':
dependencies:
ajv: 6.12.6
@@ -4547,11 +4577,13 @@ snapshots:
'@eslint/object-schema@2.1.7': {}
'@eslint/plugin-kit@0.4.0':
'@eslint/plugin-kit@0.4.1':
dependencies:
'@eslint/core': 0.16.0
'@eslint/core': 0.17.0
levn: 0.4.1
'@formkit/auto-animate@0.9.0': {}
'@humanfs/core@0.19.1': {}
'@humanfs/node@0.16.7':
@@ -4565,6 +4597,12 @@ snapshots:
'@ioredis/commands@1.4.0': {}
'@isaacs/balanced-match@4.0.1': {}
'@isaacs/brace-expansion@5.0.0':
dependencies:
'@isaacs/balanced-match': 4.0.1
'@isaacs/cliui@8.0.2':
dependencies:
string-width: 5.1.2
@@ -4618,7 +4656,7 @@ snapshots:
node-fetch: 2.7.0
nopt: 8.1.0
semver: 7.7.3
tar: 7.5.1
tar: 7.5.2
transitivePeerDependencies:
- encoding
- supports-color
@@ -4661,9 +4699,9 @@ snapshots:
'@nodelib/fs.scandir': 4.0.1
fastq: 1.19.1
'@nuxt/cli@3.29.3(magicast@0.5.0)':
'@nuxt/cli@3.29.3(magicast@0.3.5)':
dependencies:
c12: 3.3.1(magicast@0.5.0)
c12: 3.3.1(magicast@0.3.5)
citty: 0.1.6
clipboardy: 5.0.0
confbox: 0.2.2
@@ -4703,9 +4741,9 @@ snapshots:
transitivePeerDependencies:
- magicast
'@nuxt/devtools-kit@3.0.0(magicast@0.5.0)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))':
'@nuxt/devtools-kit@3.0.0(magicast@0.3.5)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))':
dependencies:
'@nuxt/kit': 4.2.0(magicast@0.5.0)
'@nuxt/kit': 4.2.0(magicast@0.3.5)
execa: 8.0.1
vite: 7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1)
transitivePeerDependencies:
@@ -4748,7 +4786,7 @@ snapshots:
perfect-debounce: 1.0.0
pkg-types: 2.3.0
semver: 7.7.3
simple-git: 3.28.0
simple-git: 3.29.0
sirv: 3.0.2
structured-clone-es: 1.0.0
tinyglobby: 0.2.15
@@ -4778,7 +4816,7 @@ snapshots:
eslint-merge-processors: 2.0.0(eslint@9.38.0(jiti@2.6.1))
eslint-plugin-import-lite: 0.3.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))
eslint-plugin-jsdoc: 61.1.10(eslint@9.38.0(jiti@2.6.1))
eslint-plugin-jsdoc: 61.1.11(eslint@9.38.0(jiti@2.6.1))
eslint-plugin-regexp: 2.10.0(eslint@9.38.0(jiti@2.6.1))
eslint-plugin-unicorn: 62.0.0(eslint@9.38.0(jiti@2.6.1))
eslint-plugin-vue: 10.5.1(@stylistic/eslint-plugin@5.5.0(eslint@9.38.0(jiti@2.6.1)))(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.38.0(jiti@2.6.1)))
@@ -4803,13 +4841,13 @@ snapshots:
- supports-color
- typescript
'@nuxt/eslint@1.10.0(@typescript-eslint/utils@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.22)(eslint@9.38.0(jiti@2.6.1))(magicast@0.5.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))':
'@nuxt/eslint@1.10.0(@typescript-eslint/utils@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.22)(eslint@9.38.0(jiti@2.6.1))(magicast@0.3.5)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))':
dependencies:
'@eslint/config-inspector': 1.3.0(eslint@9.38.0(jiti@2.6.1))
'@nuxt/devtools-kit': 3.0.0(magicast@0.5.0)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))
'@nuxt/devtools-kit': 3.0.0(magicast@0.3.5)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))
'@nuxt/eslint-config': 1.10.0(@typescript-eslint/utils@8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.22)(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
'@nuxt/eslint-plugin': 1.10.0(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)
'@nuxt/kit': 4.2.0(magicast@0.5.0)
'@nuxt/kit': 4.2.0(magicast@0.3.5)
chokidar: 4.0.3
eslint: 9.38.0(jiti@2.6.1)
eslint-flat-config-utils: 2.1.4
@@ -4857,35 +4895,9 @@ snapshots:
transitivePeerDependencies:
- magicast
'@nuxt/kit@3.20.0(magicast@0.5.0)':
'@nuxt/kit@4.2.0(magicast@0.3.5)':
dependencies:
c12: 3.3.1(magicast@0.5.0)
consola: 3.4.2
defu: 6.1.4
destr: 2.0.5
errx: 0.1.0
exsolve: 1.0.7
ignore: 7.0.5
jiti: 2.6.1
klona: 2.0.6
knitwork: 1.2.0
mlly: 1.8.0
ohash: 2.0.11
pathe: 2.0.3
pkg-types: 2.3.0
rc9: 2.1.2
scule: 1.3.0
semver: 7.7.3
tinyglobby: 0.2.15
ufo: 1.6.1
unctx: 2.4.1
untyped: 2.0.0
transitivePeerDependencies:
- magicast
'@nuxt/kit@4.2.0(magicast@0.5.0)':
dependencies:
c12: 3.3.1(magicast@0.5.0)
c12: 3.3.1(magicast@0.3.5)
consola: 3.4.2
defu: 6.1.4
destr: 2.0.5
@@ -4908,10 +4920,10 @@ snapshots:
transitivePeerDependencies:
- magicast
'@nuxt/nitro-server@4.2.0(db0@0.3.4)(ioredis@5.8.2)(magicast@0.5.0)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@vue/compiler-sfc@3.5.22)(db0@0.3.4)(eslint@9.38.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1))(typescript@5.9.3)':
'@nuxt/nitro-server@4.2.0(db0@0.3.4)(ioredis@5.8.2)(magicast@0.3.5)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@vue/compiler-sfc@3.5.22)(db0@0.3.4)(eslint@9.38.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1))(typescript@5.9.3)':
dependencies:
'@nuxt/devalue': 2.0.2
'@nuxt/kit': 4.2.0(magicast@0.5.0)
'@nuxt/kit': 4.2.0(magicast@0.3.5)
'@unhead/vue': 2.0.19(vue@3.5.22(typescript@5.9.3))
'@vue/shared': 3.5.22
consola: 3.4.2
@@ -4926,7 +4938,7 @@ snapshots:
klona: 2.0.6
mocked-exports: 0.1.1
nitropack: 2.12.9
nuxt: 4.2.0(@parcel/watcher@2.5.1)(@vue/compiler-sfc@3.5.22)(db0@0.3.4)(eslint@9.38.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1)
nuxt: 4.2.0(@parcel/watcher@2.5.1)(@vue/compiler-sfc@3.5.22)(db0@0.3.4)(eslint@9.38.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1)
pathe: 2.0.3
pkg-types: 2.3.0
radix3: 1.1.2
@@ -4980,9 +4992,9 @@ snapshots:
pkg-types: 2.3.0
std-env: 3.10.0
'@nuxt/telemetry@2.6.6(magicast@0.5.0)':
'@nuxt/telemetry@2.6.6(magicast@0.3.5)':
dependencies:
'@nuxt/kit': 3.20.0(magicast@0.5.0)
'@nuxt/kit': 3.20.0(magicast@0.3.5)
citty: 0.1.6
consola: 3.4.2
destr: 2.0.5
@@ -4997,15 +5009,15 @@ snapshots:
transitivePeerDependencies:
- magicast
'@nuxt/vite-builder@4.2.0(eslint@9.38.0(jiti@2.6.1))(lightningcss@1.30.2)(magicast@0.5.0)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@vue/compiler-sfc@3.5.22)(db0@0.3.4)(eslint@9.38.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1))(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vue@3.5.22(typescript@5.9.3))(yaml@2.8.1)':
'@nuxt/vite-builder@4.2.0(eslint@9.38.0(jiti@2.6.1))(lightningcss@1.30.2)(magicast@0.3.5)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@vue/compiler-sfc@3.5.22)(db0@0.3.4)(eslint@9.38.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1))(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vue@3.5.22(typescript@5.9.3))(yaml@2.8.1)':
dependencies:
'@nuxt/kit': 4.2.0(magicast@0.5.0)
'@rollup/plugin-replace': 6.0.2(rollup@4.52.5)
'@nuxt/kit': 4.2.0(magicast@0.3.5)
'@rollup/plugin-replace': 6.0.3(rollup@4.52.5)
'@vitejs/plugin-vue': 6.0.1(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3))
'@vitejs/plugin-vue-jsx': 5.1.1(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3))
autoprefixer: 10.4.21(postcss@8.5.6)
consola: 3.4.2
cssnano: 7.1.1(postcss@8.5.6)
cssnano: 7.1.2(postcss@8.5.6)
defu: 6.1.4
esbuild: 0.25.11
escape-string-regexp: 5.0.0
@@ -5017,7 +5029,7 @@ snapshots:
magic-string: 0.30.21
mlly: 1.8.0
mocked-exports: 0.1.1
nuxt: 4.2.0(@parcel/watcher@2.5.1)(@vue/compiler-sfc@3.5.22)(db0@0.3.4)(eslint@9.38.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1)
nuxt: 4.2.0(@parcel/watcher@2.5.1)(@vue/compiler-sfc@3.5.22)(db0@0.3.4)(eslint@9.38.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1)
pathe: 2.0.3
pkg-types: 2.3.0
postcss: 8.5.6
@@ -5025,7 +5037,7 @@ snapshots:
seroval: 1.3.2
std-env: 3.10.0
ufo: 1.6.1
unenv: 2.0.0-rc.23
unenv: 2.0.0-rc.24
vite: 7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1)
vite-node: 3.2.4(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1)
vite-plugin-checker: 0.11.0(eslint@9.38.0(jiti@2.6.1))(optionator@0.9.4)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))
@@ -5325,7 +5337,7 @@ snapshots:
optionalDependencies:
rollup: 4.52.5
'@rollup/plugin-replace@6.0.2(rollup@4.52.5)':
'@rollup/plugin-replace@6.0.3(rollup@4.52.5)':
dependencies:
'@rollup/pluginutils': 5.3.0(rollup@4.52.5)
magic-string: 0.30.21
@@ -5862,7 +5874,7 @@ snapshots:
'@vueuse/metadata@13.9.0': {}
'@vueuse/motion@3.0.3(magicast@0.5.0)(vue@3.5.22(typescript@5.9.3))':
'@vueuse/motion@3.0.3(magicast@0.3.5)(vue@3.5.22(typescript@5.9.3))':
dependencies:
'@vueuse/core': 13.9.0(vue@3.5.22(typescript@5.9.3))
'@vueuse/shared': 13.9.0(vue@3.5.22(typescript@5.9.3))
@@ -5872,7 +5884,7 @@ snapshots:
style-value-types: 5.1.2
vue: 3.5.22(typescript@5.9.3)
optionalDependencies:
'@nuxt/kit': 3.20.0(magicast@0.5.0)
'@nuxt/kit': 3.20.0(magicast@0.3.5)
transitivePeerDependencies:
- magicast
@@ -5983,7 +5995,7 @@ snapshots:
base64-js@1.5.1: {}
baseline-browser-mapping@2.8.20: {}
baseline-browser-mapping@2.8.21: {}
bindings@1.5.0:
dependencies:
@@ -6008,10 +6020,10 @@ snapshots:
browserslist@4.27.0:
dependencies:
baseline-browser-mapping: 2.8.20
baseline-browser-mapping: 2.8.21
caniuse-lite: 1.0.30001751
electron-to-chromium: 1.5.243
node-releases: 2.0.26
node-releases: 2.0.27
update-browserslist-db: 1.1.4(browserslist@4.27.0)
buffer-crc32@1.0.0: {}
@@ -6051,7 +6063,7 @@ snapshots:
optionalDependencies:
magicast: 0.3.5
c12@3.3.1(magicast@0.5.0):
c12@3.3.1(magicast@0.5.1):
dependencies:
chokidar: 4.0.3
confbox: 0.2.2
@@ -6066,7 +6078,7 @@ snapshots:
pkg-types: 2.3.0
rc9: 2.1.2
optionalDependencies:
magicast: 0.5.0
magicast: 0.5.1
cac@6.7.14: {}
@@ -6222,24 +6234,24 @@ snapshots:
cssesc@3.0.0: {}
cssnano-preset-default@7.0.9(postcss@8.5.6):
cssnano-preset-default@7.0.10(postcss@8.5.6):
dependencies:
browserslist: 4.27.0
css-declaration-sorter: 7.3.0(postcss@8.5.6)
cssnano-utils: 5.0.1(postcss@8.5.6)
postcss: 8.5.6
postcss-calc: 10.1.1(postcss@8.5.6)
postcss-colormin: 7.0.4(postcss@8.5.6)
postcss-convert-values: 7.0.7(postcss@8.5.6)
postcss-discard-comments: 7.0.4(postcss@8.5.6)
postcss-colormin: 7.0.5(postcss@8.5.6)
postcss-convert-values: 7.0.8(postcss@8.5.6)
postcss-discard-comments: 7.0.5(postcss@8.5.6)
postcss-discard-duplicates: 7.0.2(postcss@8.5.6)
postcss-discard-empty: 7.0.1(postcss@8.5.6)
postcss-discard-overridden: 7.0.1(postcss@8.5.6)
postcss-merge-longhand: 7.0.5(postcss@8.5.6)
postcss-merge-rules: 7.0.6(postcss@8.5.6)
postcss-merge-rules: 7.0.7(postcss@8.5.6)
postcss-minify-font-values: 7.0.1(postcss@8.5.6)
postcss-minify-gradients: 7.0.1(postcss@8.5.6)
postcss-minify-params: 7.0.4(postcss@8.5.6)
postcss-minify-params: 7.0.5(postcss@8.5.6)
postcss-minify-selectors: 7.0.5(postcss@8.5.6)
postcss-normalize-charset: 7.0.1(postcss@8.5.6)
postcss-normalize-display-values: 7.0.1(postcss@8.5.6)
@@ -6247,11 +6259,11 @@ snapshots:
postcss-normalize-repeat-style: 7.0.1(postcss@8.5.6)
postcss-normalize-string: 7.0.1(postcss@8.5.6)
postcss-normalize-timing-functions: 7.0.1(postcss@8.5.6)
postcss-normalize-unicode: 7.0.4(postcss@8.5.6)
postcss-normalize-unicode: 7.0.5(postcss@8.5.6)
postcss-normalize-url: 7.0.1(postcss@8.5.6)
postcss-normalize-whitespace: 7.0.1(postcss@8.5.6)
postcss-ordered-values: 7.0.2(postcss@8.5.6)
postcss-reduce-initial: 7.0.4(postcss@8.5.6)
postcss-reduce-initial: 7.0.5(postcss@8.5.6)
postcss-reduce-transforms: 7.0.1(postcss@8.5.6)
postcss-svgo: 7.1.0(postcss@8.5.6)
postcss-unique-selectors: 7.0.4(postcss@8.5.6)
@@ -6260,9 +6272,9 @@ snapshots:
dependencies:
postcss: 8.5.6
cssnano@7.1.1(postcss@8.5.6):
cssnano@7.1.2(postcss@8.5.6):
dependencies:
cssnano-preset-default: 7.0.9(postcss@8.5.6)
cssnano-preset-default: 7.0.10(postcss@8.5.6)
lilconfig: 3.1.3
postcss: 8.5.6
@@ -6405,7 +6417,7 @@ snapshots:
eslint-config-flat-gitignore@2.1.0(eslint@9.38.0(jiti@2.6.1)):
dependencies:
'@eslint/compat': 1.4.0(eslint@9.38.0(jiti@2.6.1))
'@eslint/compat': 1.4.1(eslint@9.38.0(jiti@2.6.1))
eslint: 9.38.0(jiti@2.6.1)
eslint-flat-config-utils@2.1.4:
@@ -6439,7 +6451,7 @@ snapshots:
eslint: 9.38.0(jiti@2.6.1)
eslint-import-context: 0.1.9(unrs-resolver@1.11.1)
is-glob: 4.0.3
minimatch: 9.0.5
minimatch: 10.1.1
semver: 7.7.3
stable-hash-x: 0.2.0
unrs-resolver: 1.11.1
@@ -6448,7 +6460,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-plugin-jsdoc@61.1.10(eslint@9.38.0(jiti@2.6.1)):
eslint-plugin-jsdoc@61.1.11(eslint@9.38.0(jiti@2.6.1)):
dependencies:
'@es-joy/jsdoccomment': 0.76.0
'@es-joy/resolve.exports': 1.2.0
@@ -6483,7 +6495,7 @@ snapshots:
dependencies:
'@babel/helper-validator-identifier': 7.28.5
'@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1))
'@eslint/plugin-kit': 0.4.0
'@eslint/plugin-kit': 0.4.1
change-case: 5.4.4
ci-info: 4.3.1
clean-regexp: 1.0.0
@@ -6540,11 +6552,11 @@ snapshots:
'@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1))
'@eslint-community/regexpp': 4.12.2
'@eslint/config-array': 0.21.1
'@eslint/config-helpers': 0.4.1
'@eslint/config-helpers': 0.4.2
'@eslint/core': 0.16.0
'@eslint/eslintrc': 3.3.1
'@eslint/js': 9.38.0
'@eslint/plugin-kit': 0.4.0
'@eslint/plugin-kit': 0.4.1
'@humanfs/node': 0.16.7
'@humanwhocodes/module-importer': 1.0.1
'@humanwhocodes/retry': 0.4.3
@@ -7165,7 +7177,7 @@ snapshots:
'@babel/types': 7.28.5
source-map-js: 1.2.1
magicast@0.5.0:
magicast@0.5.1:
dependencies:
'@babel/parser': 7.28.5
'@babel/types': 7.28.5
@@ -7196,6 +7208,10 @@ snapshots:
mimic-fn@4.0.0: {}
minimatch@10.1.1:
dependencies:
'@isaacs/brace-expansion': 5.0.0
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.12
@@ -7249,11 +7265,11 @@ snapshots:
'@rollup/plugin-inject': 5.0.5(rollup@4.52.5)
'@rollup/plugin-json': 6.1.0(rollup@4.52.5)
'@rollup/plugin-node-resolve': 16.0.3(rollup@4.52.5)
'@rollup/plugin-replace': 6.0.2(rollup@4.52.5)
'@rollup/plugin-replace': 6.0.3(rollup@4.52.5)
'@rollup/plugin-terser': 0.4.4(rollup@4.52.5)
'@vercel/nft': 0.30.3(rollup@4.52.5)
archiver: 7.0.1
c12: 3.3.1(magicast@0.5.0)
c12: 3.3.1(magicast@0.5.1)
chokidar: 4.0.3
citty: 0.1.6
compatx: 0.2.0
@@ -7281,7 +7297,7 @@ snapshots:
knitwork: 1.2.0
listhen: 1.9.0
magic-string: 0.30.21
magicast: 0.5.0
magicast: 0.5.1
mime: 4.1.0
mlly: 1.8.0
node-fetch-native: 1.6.7
@@ -7305,7 +7321,7 @@ snapshots:
ultrahtml: 1.6.0
uncrypto: 0.1.3
unctx: 2.4.1
unenv: 2.0.0-rc.23
unenv: 2.0.0-rc.24
unimport: 5.5.0
unplugin-utils: 0.3.1
unstorage: 1.17.1(db0@0.3.4)(ioredis@5.8.2)
@@ -7357,7 +7373,7 @@ snapshots:
node-mock-http@1.0.3: {}
node-releases@2.0.26: {}
node-releases@2.0.27: {}
nopt@8.1.0:
dependencies:
@@ -7380,19 +7396,19 @@ snapshots:
dependencies:
boolbase: 1.0.0
nuxt@4.2.0(@parcel/watcher@2.5.1)(@vue/compiler-sfc@3.5.22)(db0@0.3.4)(eslint@9.38.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1):
nuxt@4.2.0(@parcel/watcher@2.5.1)(@vue/compiler-sfc@3.5.22)(db0@0.3.4)(eslint@9.38.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1):
dependencies:
'@dxup/nuxt': 0.2.0(magicast@0.5.0)
'@nuxt/cli': 3.29.3(magicast@0.5.0)
'@dxup/nuxt': 0.2.0(magicast@0.3.5)
'@nuxt/cli': 3.29.3(magicast@0.3.5)
'@nuxt/devtools': 2.7.0(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3))
'@nuxt/kit': 4.2.0(magicast@0.5.0)
'@nuxt/nitro-server': 4.2.0(db0@0.3.4)(ioredis@5.8.2)(magicast@0.5.0)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@vue/compiler-sfc@3.5.22)(db0@0.3.4)(eslint@9.38.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1))(typescript@5.9.3)
'@nuxt/kit': 4.2.0(magicast@0.3.5)
'@nuxt/nitro-server': 4.2.0(db0@0.3.4)(ioredis@5.8.2)(magicast@0.3.5)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@vue/compiler-sfc@3.5.22)(db0@0.3.4)(eslint@9.38.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1))(typescript@5.9.3)
'@nuxt/schema': 4.2.0
'@nuxt/telemetry': 2.6.6(magicast@0.5.0)
'@nuxt/vite-builder': 4.2.0(eslint@9.38.0(jiti@2.6.1))(lightningcss@1.30.2)(magicast@0.5.0)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@vue/compiler-sfc@3.5.22)(db0@0.3.4)(eslint@9.38.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.5.0)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1))(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vue@3.5.22(typescript@5.9.3))(yaml@2.8.1)
'@nuxt/telemetry': 2.6.6(magicast@0.3.5)
'@nuxt/vite-builder': 4.2.0(eslint@9.38.0(jiti@2.6.1))(lightningcss@1.30.2)(magicast@0.3.5)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@vue/compiler-sfc@3.5.22)(db0@0.3.4)(eslint@9.38.0(jiti@2.6.1))(ioredis@5.8.2)(lightningcss@1.30.2)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vite@7.1.12(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.1))(yaml@2.8.1))(optionator@0.9.4)(rollup@4.52.5)(terser@5.44.0)(typescript@5.9.3)(vue@3.5.22(typescript@5.9.3))(yaml@2.8.1)
'@unhead/vue': 2.0.19(vue@3.5.22(typescript@5.9.3))
'@vue/shared': 3.5.22
c12: 3.3.1(magicast@0.5.0)
c12: 3.3.1(magicast@0.3.5)
chokidar: 4.0.3
compatx: 0.2.0
consola: 3.4.2
@@ -7435,7 +7451,7 @@ snapshots:
unctx: 2.4.1
unimport: 5.5.0
unplugin: 2.3.10
unplugin-vue-router: 0.16.0(@vue/compiler-sfc@3.5.22)(typescript@5.9.3)(vue-router@4.6.3(vue@3.5.22(typescript@5.9.3)))(vue@3.5.22(typescript@5.9.3))
unplugin-vue-router: 0.16.1(@vue/compiler-sfc@3.5.22)(typescript@5.9.3)(vue-router@4.6.3(vue@3.5.22(typescript@5.9.3)))(vue@3.5.22(typescript@5.9.3))
untyped: 2.0.0
vue: 3.5.22(typescript@5.9.3)
vue-router: 4.6.3(vue@3.5.22(typescript@5.9.3))
@@ -7713,7 +7729,7 @@ snapshots:
postcss-selector-parser: 7.1.0
postcss-value-parser: 4.2.0
postcss-colormin@7.0.4(postcss@8.5.6):
postcss-colormin@7.0.5(postcss@8.5.6):
dependencies:
browserslist: 4.27.0
caniuse-api: 3.0.0
@@ -7721,13 +7737,13 @@ snapshots:
postcss: 8.5.6
postcss-value-parser: 4.2.0
postcss-convert-values@7.0.7(postcss@8.5.6):
postcss-convert-values@7.0.8(postcss@8.5.6):
dependencies:
browserslist: 4.27.0
postcss: 8.5.6
postcss-value-parser: 4.2.0
postcss-discard-comments@7.0.4(postcss@8.5.6):
postcss-discard-comments@7.0.5(postcss@8.5.6):
dependencies:
postcss: 8.5.6
postcss-selector-parser: 7.1.0
@@ -7748,9 +7764,9 @@ snapshots:
dependencies:
postcss: 8.5.6
postcss-value-parser: 4.2.0
stylehacks: 7.0.6(postcss@8.5.6)
stylehacks: 7.0.7(postcss@8.5.6)
postcss-merge-rules@7.0.6(postcss@8.5.6):
postcss-merge-rules@7.0.7(postcss@8.5.6):
dependencies:
browserslist: 4.27.0
caniuse-api: 3.0.0
@@ -7770,7 +7786,7 @@ snapshots:
postcss: 8.5.6
postcss-value-parser: 4.2.0
postcss-minify-params@7.0.4(postcss@8.5.6):
postcss-minify-params@7.0.5(postcss@8.5.6):
dependencies:
browserslist: 4.27.0
cssnano-utils: 5.0.1(postcss@8.5.6)
@@ -7812,7 +7828,7 @@ snapshots:
postcss: 8.5.6
postcss-value-parser: 4.2.0
postcss-normalize-unicode@7.0.4(postcss@8.5.6):
postcss-normalize-unicode@7.0.5(postcss@8.5.6):
dependencies:
browserslist: 4.27.0
postcss: 8.5.6
@@ -7834,7 +7850,7 @@ snapshots:
postcss: 8.5.6
postcss-value-parser: 4.2.0
postcss-reduce-initial@7.0.4(postcss@8.5.6):
postcss-reduce-initial@7.0.5(postcss@8.5.6):
dependencies:
browserslist: 4.27.0
caniuse-api: 3.0.0
@@ -8085,7 +8101,7 @@ snapshots:
signal-exit@4.1.0: {}
simple-git@3.28.0:
simple-git@3.29.0:
dependencies:
'@kwsites/file-exists': 1.1.1
'@kwsites/promise-deferred': 1.1.1
@@ -8195,7 +8211,7 @@ snapshots:
hey-listen: 1.0.8
tslib: 2.4.0
stylehacks@7.0.6(postcss@8.5.6):
stylehacks@7.0.7(postcss@8.5.6):
dependencies:
browserslist: 4.27.0
postcss: 8.5.6
@@ -8240,7 +8256,7 @@ snapshots:
- bare-abort-controller
- react-native-b4a
tar@7.5.1:
tar@7.5.2:
dependencies:
'@isaacs/fs-minipass': 4.0.1
chownr: 3.0.0
@@ -8321,7 +8337,7 @@ snapshots:
undici@7.16.0: {}
unenv@2.0.0-rc.23:
unenv@2.0.0-rc.24:
dependencies:
pathe: 2.0.3
@@ -8360,7 +8376,7 @@ snapshots:
pathe: 2.0.3
picomatch: 4.0.3
unplugin-vue-router@0.16.0(@vue/compiler-sfc@3.5.22)(typescript@5.9.3)(vue-router@4.6.3(vue@3.5.22(typescript@5.9.3)))(vue@3.5.22(typescript@5.9.3)):
unplugin-vue-router@0.16.1(@vue/compiler-sfc@3.5.22)(typescript@5.9.3)(vue-router@4.6.3(vue@3.5.22(typescript@5.9.3)))(vue@3.5.22(typescript@5.9.3)):
dependencies:
'@babel/generator': 7.28.5
'@vue-macros/common': 3.1.1(vue@3.5.22(typescript@5.9.3))

32
server/api/magnet.ts Normal file
View File

@@ -0,0 +1,32 @@
import { getMagnetUrl, parseMagnet } from "~~/server/utils/magnetParser";
import { addTrackers, getTrackers } from "~~/server/utils/trackerHelper";
export default defineEventHandler(async (event) => {
const body = await readBody<{ magnet?: string }>(event);
const magnetUrl = body?.magnet;
if (!magnetUrl) {
throw createError({
statusCode: 400,
statusMessage: "Missing magnet URL",
});
}
try {
const maxedMagnet = addTrackers(
parseMagnet(magnetUrl),
await getTrackers()
);
return {
totalTrackers: maxedMagnet.tr?.length,
name: maxedMagnet.dn,
id: maxedMagnet.xt.slice(9),
maxedMagnet: getMagnetUrl(maxedMagnet),
};
} catch (error: any) {
throw createError({
statusCode: 400,
statusMessage: error.message || "Invalid magnet URL",
});
}
});

View File

@@ -0,0 +1,68 @@
import type { MagnetUrl } from "../../shared/types/magnet";
export function parseMagnet(magnetUrl: string): MagnetUrl {
if (!magnetUrl.startsWith("magnet:?")) {
throw new Error('Invalid magnet URL: Must start with "magnet:?"');
}
const params = new URLSearchParams(magnetUrl.substring(8)); // Remove 'magnet:?' prefix
const xt = params.get("xt");
if (!xt) {
throw new Error("Invalid magnet URL: Missing required xt parameter");
}
// Validate xt format (btih hash)
const btihRegex = /^urn:btih:([a-fA-F0-9]{40}|[A-Z2-7]{32})$/;
if (!btihRegex.test(xt)) {
throw new Error("Invalid magnet URL: Invalid xt parameter format");
}
const magnet: MagnetUrl = {
xt,
};
const dn = params.get("dn");
if (dn) {
magnet.dn = decodeURIComponent(dn);
}
const tr = params.getAll("tr");
if (tr.length > 0) {
magnet.tr = tr.map(decodeURIComponent);
}
const as = params.getAll("as");
if (as.length > 0) {
magnet.as = as.map(decodeURIComponent);
}
const xs = params.getAll("xs");
if (xs.length > 0) {
magnet.xs = xs.map(decodeURIComponent);
}
const kt = params.get("kt");
if (kt) {
magnet.kt = decodeURIComponent(kt);
}
const mt = params.get("mt");
if (mt) {
magnet.mt = decodeURIComponent(mt);
}
return magnet;
}
export function getMagnetUrl(magnet: MagnetUrl): string {
const params = new URLSearchParams();
Object.entries(magnet).forEach(([key, value]) => {
if (Array.isArray(value)) {
value.forEach((v) => params.append(`${key}`, v));
} else {
params.append(`${key}`, value);
}
});
return `magnet:?${params.toString()}`;
}

View File

@@ -0,0 +1,54 @@
import type { MagnetUrl } from "../../shared/types/magnet";
let cachedTrackers: string[] | null = null;
let lastFetched = 0;
const CACHE_TTL = 1000 * 60 * 10; // 10 minutes
export async function getTrackers(): Promise<string[]> {
const now = Date.now();
if (cachedTrackers && now - lastFetched < CACHE_TTL) {
return cachedTrackers;
}
const TRACKER_URLS = [
"https://raw.githubusercontent.com/XIU2/TrackersListCollection/refs/heads/master/all.txt",
"https://raw.githubusercontent.com/ngosang/trackerslist/refs/heads/master/trackers_all.txt",
];
for (const url of TRACKER_URLS) {
try {
const response = await fetch(url);
if (response.ok) {
const text = await response.text();
const trackers = text
.split("\n")
.map((line) => line.trim())
.filter((line) => line !== "");
// update cache
cachedTrackers = trackers;
lastFetched = now;
return trackers;
}
} catch (err) {
console.error(err);
}
}
// fallback: return cached even if stale, or empty
return cachedTrackers ?? [];
}
export function addTrackers(magnet: MagnetUrl, trackers: string[]): MagnetUrl {
if (trackers.length > 0) {
// avoid duplicates
const existing = new Set(magnet.tr ?? []);
for (const tracker of trackers) {
if (!existing.has(tracker)) {
magnet.tr?.push(tracker);
}
}
}
return magnet;
}

21
shared/types/magnet.ts Normal file
View File

@@ -0,0 +1,21 @@
export type MagnetUrl = {
/**
* A magnet link is a string that contains all the information needed to download a torrent file.
* It consists of several parameters that are separated by ampersands (&).
* The parameters are:
* - xt (exact topic): The hash of the torrent file.
* - dn (display name): The name of the torrent file.
* - tr (tracker URL): The URL of the tracker.
* - as (acceptable source): The URL of the acceptable source.
* - xs (exact source): The URL of the exact source.
* - kt (keyword topic): The keyword topic.
* - mt (magnet topic): The magnet topic.
*/
xt: string;
dn?: string;
tr?: string[];
as?: string[];
xs?: string[];
kt?: string;
mt?: string;
}