feat: feedback i18n, entrelineas dev-lock, and developer access system

This commit is contained in:
Esteban 2026-05-31 12:16:52 -05:00
parent ce8efe5a8a
commit 2dd21ffe45
19 changed files with 779 additions and 1387 deletions

View File

@ -0,0 +1,71 @@
<script setup lang="ts">
const { $i18n } = useNuxtApp()
const t = $i18n.t
defineProps<{
modelValue: string
}>()
const emit = defineEmits<{
'update:modelValue': [value: string]
}>()
function sanitize(text: string): string {
let clean = text
clean = clean.replace(/<[^>]*>/g, '')
clean = clean.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
clean = clean.replace(/https?:\/\/[^\s]+/gi, '')
clean = clean.replace(/www\.[^\s]+/gi, '')
clean = clean.replace(/javascript\s*:/gi, '')
clean = clean.replace(/\beval\s*\(/gi, '')
clean = clean.replace(/\bon\w+\s*=/gi, '')
clean = clean.replace(/[A-Za-z0-9+/]{50,}={0,2}/g, '')
clean = clean.replace(/'\s*OR\s+\d+\s*=\s*\d+/gi, '')
clean = clean.replace(/'\s*--/g, "'")
clean = clean.replace(/'\s*;\s*DROP\s+TABLE/gi, "'")
clean = clean.replace(/UNION\s+SELECT/gi, '')
clean = clean.replace(/xp_cmdshell/gi, '')
clean = clean.replace(/EXEC\s*\(/gi, '')
clean = clean.replace(/`[^`]*`/g, '')
clean = clean.replace(/\$\(.*?\)/g, '')
clean = clean.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, '')
return clean.slice(0, 500)
}
function onInput(value: string) {
emit('update:modelValue', sanitize(value))
}
</script>
<template>
<UCard class="w-full max-w-xl shadow-sm">
<div class="flex flex-col items-center gap-4 py-4">
<UIcon name="i-lucide-bug" class="size-10 text-carpablue" />
<div class="text-center space-y-1">
<h2 class="text-lg font-semibold text-highlighted">
{{ t('feedback.title') }}
</h2>
<p class="text-sm text-muted leading-relaxed max-w-sm">
{{ t('feedback.description') }}
</p>
</div>
<UTextarea
:model-value="modelValue"
:placeholder="t('feedback.placeholder')"
:rows="6"
:maxlength="500"
autoresize
size="lg"
class="w-full"
@update:model-value="onInput($event)"
/>
<div class="flex items-center justify-between w-full text-xs text-muted">
<span>{{ t('feedback.anonymous_notice') }}</span>
<span>{{ modelValue.length }}/500</span>
</div>
</div>
</UCard>
</template>

View File

@ -0,0 +1,33 @@
const STORAGE_KEY = 'entrelineas_dev_unlocked'
export function useDevMode() {
const config = useRuntimeConfig()
const devKey = config.public.entrelineasDevKey as string
const unlocked = ref(false)
if (import.meta.client) {
unlocked.value = localStorage.getItem(STORAGE_KEY) === 'true'
}
function unlock(key: string): boolean {
if (!devKey) return false
if (key === devKey) {
unlocked.value = true
if (import.meta.client) {
localStorage.setItem(STORAGE_KEY, 'true')
}
return true
}
return false
}
function lock() {
unlocked.value = false
if (import.meta.client) {
localStorage.removeItem(STORAGE_KEY)
}
}
return { unlocked, unlock, lock }
}

View File

@ -0,0 +1,45 @@
let loaded = false
let loading = false
let loadPromise: Promise<void> | null = null
function loadScript(siteKey: string): Promise<void> {
if (loaded) return Promise.resolve()
if (loading && loadPromise) return loadPromise
loading = true
loadPromise = new Promise((resolve, reject) => {
const script = document.createElement('script')
script.src = `https://www.google.com/recaptcha/api.js?render=${siteKey}`
script.async = true
script.defer = true
script.onload = () => {
loaded = true
loading = false
resolve()
}
script.onerror = () => {
loading = false
reject(new Error('Failed to load reCAPTCHA'))
}
document.head.appendChild(script)
})
return loadPromise
}
export function useRecaptcha(siteKey: string) {
async function executeRecaptcha(action: string = 'submit'): Promise<string> {
await loadScript(siteKey)
return new Promise((resolve, reject) => {
window.grecaptcha.ready(() => {
window.grecaptcha
.execute(siteKey, { action })
.then((token: string) => resolve(token))
.catch(reject)
})
})
}
return { executeRecaptcha }
}

View File

@ -64,6 +64,12 @@ const links = computed(() => {
icon: 'i-lucide-settings',
to: '/configuracion',
onSelect: () => { open.value = false }
},
{
label: t('feedback.title'),
icon: 'i-lucide-bug',
to: '/feedback',
onSelect: () => { open.value = false }
}
] satisfies NavigationMenuItem[]
})

View File

@ -16,6 +16,20 @@ interface Release {
}
const releases: Release[] = [
{
version: '0.6',
date: '31 de mayo, 2026',
title: 'Feedback con traducciones, bloqueo de Entrelíneas y acceso desarrollador',
changes: [
{ type: 'nuevo', text: 'Página de Feedback con traducciones completas en 4 idiomas' },
{ type: 'nuevo', text: 'Sistema de bloqueo por clave de desarrollador para secciones en desarrollo' },
{ type: 'nuevo', text: 'Acceso de desarrollador en Configuración con desbloqueo por clave' },
{ type: 'nuevo', text: 'Banner visual mejorado para Entrelíneas cuando está bloqueado' },
{ type: 'mejora', text: 'Traducciones añadidas al componente BugReportInput' },
{ type: 'mejora', text: 'Nombre del tab Feedback ahora usa traducciones' },
{ type: 'mejora', text: 'Textos del banner de Entrelíneas traducidos a 4 idiomas' }
]
},
{
version: '0.5',
date: '30 de mayo, 2026',

View File

@ -25,6 +25,19 @@ const paginationItems = [
description: t('settings.numbered_desc')
}
]
const { unlocked, unlock, lock } = useDevMode()
const devKeyInput = ref('')
const devKeyError = ref('')
function tryUnlock() {
devKeyError.value = ''
if (unlock(devKeyInput.value)) {
devKeyInput.value = ''
} else {
devKeyError.value = t('settings.dev_wrong_key')
}
}
</script>
<template>
@ -69,6 +82,37 @@ const paginationItems = [
</div>
<USwitch v-model="showParagraphNumbers" />
</div>
<USeparator />
<!-- Acceso desarrollador -->
<div>
<p class="text-sm font-semibold text-highlighted mb-1">
{{ t('settings.dev_access_title') }}
</p>
<p class="text-xs text-muted mb-4">{{ t('settings.dev_access_desc') }}</p>
<div v-if="!unlocked" class="flex gap-2">
<UInput
v-model="devKeyInput"
type="password"
:placeholder="t('settings.dev_key_placeholder')"
class="flex-1"
@keyup.enter="tryUnlock"
/>
<UButton @click="tryUnlock">
{{ t('settings.dev_unlock') }}
</UButton>
</div>
<div v-else class="flex items-center gap-2">
<UIcon name="i-lucide-lock-open" class="size-5 text-green-500" />
<span class="text-sm text-green-600 font-medium">{{ t('settings.dev_unlocked') }}</span>
<UButton color="neutral" variant="outline" size="sm" @click="lock">
{{ t('settings.dev_lock') }}
</UButton>
</div>
<p v-if="devKeyError" class="text-xs text-red-500 mt-1">{{ devKeyError }}</p>
</div>
</div>
</div>
</UDashboardPanel>

View File

@ -6,24 +6,18 @@ import { useFavoritesStore } from '~/stores/favorites'
import { useSettingsStore } from '~/stores/settings'
import type { SearchHit } from '~/types'
/* -------------------------------------------------------------------------- */
/* CONFIGURACIÓN — lo único que necesitas tocar */
/* -------------------------------------------------------------------------- */
const COLLECTION = 'entrelineas'
const QUERY_BY = 'text'
const INCLUDE_FIELDS = '*'
const EXTRA_FILTER_BY = ''
const FAVORITES_COLLECTION = 'entrelineas'
/* -------------------------------------------------------------------------- */
/* Estado */
/* -------------------------------------------------------------------------- */
const { $i18n } = useNuxtApp()
const t = $i18n.t
const { locale } = useI18n()
const { unlocked } = useDevMode()
const filterBy = computed(() => {
const localeFilter = `locale:=${locale.value}`
return EXTRA_FILTER_BY ? `${localeFilter} && ${EXTRA_FILTER_BY}` : localeFilter
@ -33,7 +27,6 @@ const REQUEST_TIMEOUT_MS = 15000
const settings = useSettingsStore()
// Restaurar estado desde URL antes de crear los refs
const { query: q0, page: p0, scroll: s0, selectedId: sid0 } = useSearchUrlState()
const query = ref(q0)
@ -96,10 +89,6 @@ const hasMore = computed(() =>
settings.paginationType === 'infinite_scroll' ? hits.value.length < total.value : false
)
/* -------------------------------------------------------------------------- */
/* Búsqueda */
/* -------------------------------------------------------------------------- */
const { documentsApi } = useTypesenseApi()
let searchSeq = 0
@ -199,10 +188,6 @@ watch(debouncedQuery, (q) => {
runSearch(q, 1, false)
})
/* -------------------------------------------------------------------------- */
/* Selección / panel de detalle */
/* -------------------------------------------------------------------------- */
const selected = ref<EntrelineaDoc | null>(null)
const isPanelOpen = computed({
@ -216,23 +201,17 @@ watch(hits, () => {
if (!stillThere) selected.value = null
})
// ID del item seleccionado para sincronizar con la URL
const selectedId = computed(() => selected.value?.id?.toString() ?? null)
// Contenedor scrollable de la lista
const listEl = ref<HTMLElement | null>(null)
// Sincronización con URL
useSearchUrlSync({ query, page: activePage, selectedId, scrollEl: listEl })
// Ciclo de vida
onMounted(async () => {
await runSearch(q0, p0, false)
// Restaurar scroll
restoreScrollPosition(listEl.value, s0)
// Restaurar item seleccionado
if (sid0) {
const found = hits.value.find(h => h.document.id === sid0)
if (found) selected.value = found.document
@ -244,10 +223,6 @@ const isMobile = breakpoints.smaller('lg')
useDetailHistory(isPanelOpen, isMobile)
/* -------------------------------------------------------------------------- */
/* Favoritos */
/* -------------------------------------------------------------------------- */
const favorites = useFavoritesStore()
const toast = useToast()
@ -281,10 +256,6 @@ function toggleFavorite(doc: EntrelineaDoc, ev?: Event) {
})
}
/* -------------------------------------------------------------------------- */
/* Helpers de presentación */
/* -------------------------------------------------------------------------- */
function highlightedFor(hit: TypesenseHit, field: string): string | null {
const fromArr = hit.highlights?.find(h => h.field === field)
if (fromArr?.snippet) return fromArr.snippet
@ -308,12 +279,37 @@ function highlightedFor(hit: TypesenseHit, field: string): string | null {
<template #leading>
<UDashboardSidebarCollapse />
</template>
<template #trailing>
<UBadge :label="total" variant="subtle" />
</template>
</UDashboardNavbar>
<!-- Banner: se muestra cuando NO hay clave de desarrollador -->
<template v-if="!unlocked">
<div class="flex-1 flex items-center justify-center p-8 bg-gradient-to-br from-amber-50 via-white to-amber-100/60">
<div class="flex flex-col items-center gap-6 text-center max-w-sm">
<div class="size-28 rounded-full bg-gradient-to-br from-amber-300 to-amber-500 flex items-center justify-center shadow-lg shadow-amber-200/50 ring-4 ring-white">
<UIcon name="i-lucide-flask-conical" class="size-14 text-white" />
</div>
<div class="space-y-2">
<h2 class="text-2xl font-bold text-highlighted">
{{ t('entrelineas.development_banner') }}
</h2>
<p class="text-sm text-toned leading-relaxed">
{{ t('entrelineas.development_subtitle_line1') }}<br>
{{ t('entrelineas.development_subtitle_line2') }}
</p>
</div>
<div class="flex items-center gap-2 pt-2">
<span class="size-2 rounded-full bg-amber-300 animate-pulse" />
<span class="size-2 rounded-full bg-amber-400 animate-pulse" style="animation-delay: 0.2s" />
<span class="size-2 rounded-full bg-amber-500 animate-pulse" style="animation-delay: 0.4s" />
</div>
</div>
</div>
</template>
<!-- Funcional: se muestra cuando la clave de desarrollador es correcta -->
<template v-else>
<div class="px-4 sm:px-6 py-3 border-b border-default">
<UInput
v-model="query"
@ -375,14 +371,6 @@ function highlightedFor(hit: TypesenseHit, field: string): string | null {
>
<div class="flex items-start justify-between gap-2 mb-1">
<div class="min-w-0 flex-1 flex gap-2">
<!-- <UBadge
v-if="hit.document?.page"
:label="`Página ${hit.document?.page}`"
size="sm"
variant="subtle"
color="error"
class="mb-1 uppercase"
/> -->
<UBadge
v-if="hit.document?.filter"
:label="hit.document?.filter"
@ -419,13 +407,8 @@ function highlightedFor(hit: TypesenseHit, field: string): string | null {
/>
<USeparator class="my-2"/>
<!-- <div class="text-xs text-dimmed">
esta es la página {{ hit.document?.description }}
</div> -->
</div>
<!-- Infinite scroll: cargando más -->
<div
v-if="settings.paginationType === 'infinite_scroll' && hasMore && !loading"
class="p-4 flex justify-center"
@ -449,7 +432,6 @@ function highlightedFor(hit: TypesenseHit, field: string): string | null {
</div>
</div>
<!-- Paginación numerada -->
<div
v-if="settings.paginationType === 'numbered' && totalPages > 1 && !loading"
class="px-4 py-3 border-t border-default flex justify-center shrink-0"
@ -462,9 +444,10 @@ function highlightedFor(hit: TypesenseHit, field: string): string | null {
@update:page="goToPage"
/>
</div>
</template>
</UDashboardPanel>
<!-- Panel de detalle (escritorio) -->
<template v-if="unlocked">
<EntrelineaDetail
v-if="selected && !isMobile"
:document="selected"
@ -481,7 +464,6 @@ function highlightedFor(hit: TypesenseHit, field: string): string | null {
</div>
</div>
<!-- Panel de detalle (móvil) -->
<ClientOnly>
<USlideover v-if="isMobile" v-model:open="isPanelOpen">
<template #content>
@ -495,6 +477,7 @@ function highlightedFor(hit: TypesenseHit, field: string): string | null {
</template>
</USlideover>
</ClientOnly>
</template>
</template>
<style scoped>

196
app/pages/feedback.vue Normal file
View File

@ -0,0 +1,196 @@
<script setup lang="ts">
const { $i18n } = useNuxtApp()
const t = $i18n.t
const message = ref('')
const sending = ref(false)
const sent = ref(false)
const error = ref('')
const cooldown = ref(0)
const honeypot = ref('')
const mountTime = Date.now()
let cooldownTimer: ReturnType<typeof setInterval> | null = null
const {
recaptchaSiteKey: siteKey,
feedbackMaxPerHour: MAX_PER_HOUR,
feedbackMaxPerSession: MAX_PER_SESSION,
feedbackCooldownSec: COOLDOWN_SEC,
feedbackMinSeconds: MIN_SECONDS
} = useRuntimeConfig().public
const RATE_LIMIT_KEY = 'feedback_ratelimit'
const SESSION_LIMIT_KEY = 'feedback_session'
function sanitize(text: string): string {
let clean = text
clean = clean.replace(/<[^>]*>/g, '')
clean = clean.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
clean = clean.replace(/https?:\/\/[^\s]+/gi, '')
clean = clean.replace(/www\.[^\s]+/gi, '')
clean = clean.replace(/javascript\s*:/gi, '')
clean = clean.replace(/\beval\s*\(/gi, '')
clean = clean.replace(/\bon\w+\s*=/gi, '')
clean = clean.replace(/[A-Za-z0-9+/]{50,}={0,2}/g, '')
clean = clean.replace(/'\s*OR\s+\d+\s*=\s*\d+/gi, '')
clean = clean.replace(/'\s*--/g, "'")
clean = clean.replace(/'\s*;\s*DROP\s+TABLE/gi, "'")
clean = clean.replace(/UNION\s+SELECT/gi, '')
clean = clean.replace(/xp_cmdshell/gi, '')
clean = clean.replace(/EXEC\s*\(/gi, '')
clean = clean.replace(/`[^`]*`/g, '')
clean = clean.replace(/\$\(.*?\)/g, '')
clean = clean.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, '')
return clean.slice(0, 500)
}
function getRateLimitCount(): number {
try {
const raw = localStorage.getItem(RATE_LIMIT_KEY)
if (!raw) return 0
const data: { count: number; reset: number } = JSON.parse(raw)
if (Date.now() > data.reset) {
localStorage.removeItem(RATE_LIMIT_KEY)
return 0
}
return data.count
} catch {
return 0
}
}
function incrementRateLimit() {
const raw = localStorage.getItem(RATE_LIMIT_KEY)
const now = Date.now()
let data = { count: 0, reset: now + 3600000 }
if (raw) {
try {
const parsed = JSON.parse(raw)
if (now <= parsed.reset) {
data = parsed
}
} catch { /* usar default */ }
}
data.count++
localStorage.setItem(RATE_LIMIT_KEY, JSON.stringify(data))
}
function getSessionCount(): number {
try {
const raw = sessionStorage.getItem(SESSION_LIMIT_KEY)
return raw ? Number(raw) : 0
} catch {
return 0
}
}
function incrementSession() {
const count = getSessionCount() + 1
sessionStorage.setItem(SESSION_LIMIT_KEY, String(count))
}
function checkBlocked(): string | null {
const elapsed = (Date.now() - mountTime) / 1000
if (elapsed < MIN_SECONDS) return t('feedback.error_cooldown')
const rateCount = getRateLimitCount()
if (rateCount >= MAX_PER_HOUR) return t('feedback.error_rate_limit')
const sessionCount = getSessionCount()
if (sessionCount >= MAX_PER_SESSION) return t('feedback.error_session_limit')
return null
}
function startCooldown() {
cooldown.value = COOLDOWN_SEC
cooldownTimer = setInterval(() => {
cooldown.value--
if (cooldown.value <= 0) {
if (cooldownTimer) clearInterval(cooldownTimer)
cooldown.value = 0
}
}, 1000)
}
const { executeRecaptcha } = useRecaptcha(siteKey)
async function send() {
const body = sanitize(message.value)
if (!body.trim()) return
if (honeypot.value.trim()) return
const blocked = checkBlocked()
if (blocked !== null) {
error.value = blocked
return
}
sending.value = true
error.value = ''
try {
const token = siteKey ? await executeRecaptcha('submit_feedback') : null
await $fetch('/api/feedback', {
method: 'POST',
body: { message: body, recaptchaToken: token }
})
sent.value = true
message.value = ''
incrementRateLimit()
incrementSession()
startCooldown()
} catch (e) {
error.value = t('feedback.error_generic')
} finally {
sending.value = false
}
}
</script>
<template>
<UDashboardPanel id="bugreport-panel" grow>
<UDashboardNavbar :title="t('feedback.title')">
<template #leading>
<UDashboardSidebarCollapse />
</template>
</UDashboardNavbar>
<div class="flex-1 flex items-center justify-center p-6">
<div v-if="sent" class="text-center space-y-3">
<UIcon name="i-lucide-circle-check" class="size-16 text-green-500" />
<p class="text-sm text-muted">{{ t('feedback.success_message') }}</p>
<UButton color="neutral" variant="outline" @click="sent = false">
{{ t('feedback.send_another') }}
</UButton>
</div>
<div v-else class="flex flex-col items-center gap-6 w-full max-w-xl">
<BugReportInput v-model="message" />
<input
v-model="honeypot"
type="text"
tabindex="-1"
autocomplete="off"
class="absolute -left-[9999px] -top-[9999px] opacity-0 pointer-events-none size-0"
aria-hidden="true"
/>
<UButton
:loading="sending"
:disabled="!message.trim() || cooldown > 0"
size="lg"
class="max-w-xl"
@click="send"
>
{{ sending ? t('feedback.sending') : cooldown > 0 ? t('feedback.wait_seconds', { seconds: cooldown }) : t('feedback.send') }}
</UButton>
<p v-if="error" class="text-sm text-red-500">{{ error }}</p>
</div>
</div>
</UDashboardPanel>
</template>

10
app/types/index.d.ts vendored
View File

@ -55,6 +55,16 @@ export interface Member {
avatar: AvatarProps
}
declare global {
interface Window {
grecaptcha: {
ready: (callback: () => void) => void
execute: (siteKey: string, options: { action: string }) => Promise<string>
render: (container: string | HTMLElement, options: Record<string, unknown>) => void
}
}
}
export interface Notification {
id: number
unread?: boolean

View File

@ -46,13 +46,40 @@
"numbered": "Numbered pages",
"numbered_desc": "Navigate between pages with pagination controls.",
"paragraph_numbers_title": "Paragraph numbers",
"paragraph_numbers_desc": "Show the paragraph number next to each paragraph in the document detail."
"paragraph_numbers_desc": "Show the paragraph number next to each paragraph in the document detail.",
"dev_access_title": "Developer access",
"dev_access_desc": "Enter the key to enable sections in development.",
"dev_key_placeholder": "Development key",
"dev_unlock": "Unlock",
"dev_lock": "Lock",
"dev_unlocked": "Unlocked",
"dev_wrong_key": "Wrong key"
},
"downloads": {
"audio": "Audio",
"book": "Book",
"simple": "Simple"
},
"feedback": {
"title": "Report an error",
"description": "If you find an error or have a suggestion to improve the search, write it here. Your feedback helps us improve.",
"placeholder": "Describe the error or suggestion...",
"anonymous_notice": "Anonymous report. Do not include personal information or passwords.",
"success_message": "Message sent successfully. Thank you for your feedback.",
"send_another": "Send another",
"send": "Send report",
"sending": "Sending...",
"wait_seconds": "Wait {seconds}s",
"error_generic": "Could not send the message. Try again.",
"error_cooldown": "Wait a few seconds before sending.",
"error_rate_limit": "You have reached the hourly limit. Try again later.",
"error_session_limit": "You have reached the session limit."
},
"entrelineas": {
"development_banner": "This section is under development",
"development_subtitle_line1": "We're preparing details for this section.",
"development_subtitle_line2": "Come back soon."
},
"ui": {
"copy": "Copy",
"draft": "Draft",

View File

@ -51,13 +51,40 @@
"numbered": "Páginas numeradas",
"numbered_desc": "Navega entre páginas con controles de paginación.",
"paragraph_numbers_title": "Números de párrafo",
"paragraph_numbers_desc": "Muestra el número de párrafo al lado de cada párrafo en el detalle del documento."
"paragraph_numbers_desc": "Muestra el número de párrafo al lado de cada párrafo en el detalle del documento.",
"dev_access_title": "Acceso de desarrollador",
"dev_access_desc": "Ingresa la clave para habilitar secciones en desarrollo.",
"dev_key_placeholder": "Clave de desarrollo",
"dev_unlock": "Desbloquear",
"dev_lock": "Bloquear",
"dev_unlocked": "Desbloqueado",
"dev_wrong_key": "Clave incorrecta"
},
"downloads": {
"audio": "Audio",
"book": "Libro",
"simple": "Sencillo",
},
"feedback": {
"title": "Reportar un error",
"description": "Si encuentras un error o tienes una sugerencia para mejorar el buscador, escríbelo aquí. Tu retroalimentación nos ayuda a mejorar.",
"placeholder": "Describe el error o sugerencia...",
"anonymous_notice": "Reporte anónimo. No incluyas información personal ni contraseñas.",
"success_message": "Mensaje enviado correctamente. Gracias por tu retroalimentación.",
"send_another": "Enviar otro",
"send": "Enviar reporte",
"sending": "Enviando...",
"wait_seconds": "Espera {seconds}s",
"error_generic": "No se pudo enviar el mensaje. Intenta de nuevo.",
"error_cooldown": "Espera unos segundos antes de enviar.",
"error_rate_limit": "Has alcanzado el límite de envíos por hora. Intenta más tarde.",
"error_session_limit": "Has alcanzado el límite de envíos en esta sesión."
},
"entrelineas": {
"development_banner": "Esta sección se encuentra en desarrollo",
"development_subtitle_line1": "Estamos preparando detalles para esta sección.",
"development_subtitle_line2": "Vuelve pronto."
},
"ui": {
"copy": "Copiar",
"draft": "Borrador",

View File

@ -34,13 +34,40 @@
"numbered": "Pages numérotées",
"numbered_desc": "Naviguez entre les pages avec des contrôles de pagination.",
"paragraph_numbers_title": "Numéros de paragraphe",
"paragraph_numbers_desc": "Affiche le numéro de paragraphe à côté de chaque paragraphe dans le détail du document."
"paragraph_numbers_desc": "Affiche le numéro de paragraphe à côté de chaque paragraphe dans le détail du document.",
"dev_access_title": "Accès développeur",
"dev_access_desc": "Entrez la clé pour activer les sections en développement.",
"dev_key_placeholder": "Clé de développement",
"dev_unlock": "Déverrouiller",
"dev_lock": "Verrouiller",
"dev_unlocked": "Déverrouillé",
"dev_wrong_key": "Clé incorrecte"
},
"downloads": {
"audio": "Audio",
"book": "Libre",
"simple": "Simple"
},
"feedback": {
"title": "Rapporter une erreur",
"description": "Si vous trouvez une erreur ou avez une suggestion pour améliorer la recherche, écrivez-la ici. Votre retour nous aide à nous améliorer.",
"placeholder": "Décrivez l'erreur ou la suggestion...",
"anonymous_notice": "Rapport anonyme. N'incluez pas d'informations personnelles ni de mots de passe.",
"success_message": "Message envoyé avec succès. Merci pour votre retour.",
"send_another": "Envoyer un autre",
"send": "Envoyer le rapport",
"sending": "Envoi en cours...",
"wait_seconds": "Attendez {seconds}s",
"error_generic": "Impossible d'envoyer le message. Réessayez.",
"error_cooldown": "Attendez quelques secondes avant d'envoyer.",
"error_rate_limit": "Vous avez atteint la limite horaire. Réessayez plus tard.",
"error_session_limit": "Vous avez atteint la limite de cette session."
},
"entrelineas": {
"development_banner": "Cette section est en cours de développement",
"development_subtitle_line1": "Nous préparons les détails de cette section.",
"development_subtitle_line2": "Revenez bientôt."
},
"ui": {
"copy": "Copie",
"draft": "Brouillon",

View File

@ -44,13 +44,40 @@
"numbered": "Páginas numeradas",
"numbered_desc": "Navegue entre páginas com controles de paginação.",
"paragraph_numbers_title": "Números de parágrafo",
"paragraph_numbers_desc": "Exibe o número do parágrafo ao lado de cada parágrafo no detalhe do documento."
"paragraph_numbers_desc": "Exibe o número do parágrafo ao lado de cada parágrafo no detalhe do documento.",
"dev_access_title": "Acesso de desenvolvedor",
"dev_access_desc": "Insira a chave para ativar seções em desenvolvimento.",
"dev_key_placeholder": "Chave de desenvolvimento",
"dev_unlock": "Desbloquear",
"dev_lock": "Bloquear",
"dev_unlocked": "Desbloqueado",
"dev_wrong_key": "Chave incorreta"
},
"downloads": {
"audio": "Áudio",
"book": "Livro",
"simple": "Simples"
},
"feedback": {
"title": "Reportar um erro",
"description": "Se encontrar um erro ou tem uma sugestão, escreva-la aqui. A sua opinião ira ajudar-nos a melhorar.",
"placeholder": "Descreva o erro ou sugestão",
"anonymous_notice": "Reporte anônimo. Não inclua informações pessoais nem senhas.",
"success_message": "Mensagem enviada corretamente. Obrigado por sua opinião.",
"send_another": "Enviar outro",
"send": "Enviar reporte",
"sending": "Enviando...",
"wait_seconds": "Aguarde {seconds}s",
"error_generic": "Não foi possível enviar a mensagem. Tente novamente.",
"error_cooldown": "Aguarde alguns segundos antes de enviar.",
"error_rate_limit": "Você atingiu o limite horário. Tente novamente mais tarde.",
"error_session_limit": "Você atingiu o limite desta sessão."
},
"entrelineas": {
"development_banner": "Esta seção está em desenvolvimento",
"development_subtitle_line1": "Estamos preparando detalhes para esta seleção.",
"development_subtitle_line2": "Volte logo."
},
"ui": {
"copy": "Cópia",
"draft": "Rascunho"

View File

@ -1,6 +1,6 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
modules: ['@nuxt/eslint', '@nuxt/ui', '@vueuse/nuxt', 'nuxt-meilisearch', '@nuxtjs/i18n', '@pinia/nuxt', '@sfxcode/nuxt-typesense'],
modules: ['@nuxt/eslint', '@nuxt/ui', '@vueuse/nuxt', '@nuxtjs/i18n', '@pinia/nuxt', '@sfxcode/nuxt-typesense'],
app: {
head: {
@ -19,6 +19,19 @@ export default defineNuxtConfig({
colorMode: false
},
runtimeConfig: {
feedbackToken: '',
public: {
feedbackWebhook: '',
recaptchaSiteKey: '',
feedbackMaxPerHour: 5,
feedbackMaxPerSession: 3,
feedbackCooldownSec: 45,
feedbackMinSeconds: 4,
entrelineasDevKey: ''
}
},
routeRules: {
'/api/**': {
cors: true
@ -75,18 +88,9 @@ export default defineNuxtConfig({
},
},
meilisearch: {
hostUrl: 'https://search.carpa.com', // required
searchApiKey: '04be59c1f633e2bb434082fc1a6fcc6ce97e3630e3fcf9e814e1f03a386c03e1', // required
serverSideUsage: true // default: false
},
typesense: {
url: 'https://searchts.carpa.com', // Your Typesense server URL
apiKey: 'ULcypm8VYP2vgQkN57CuUqSFypWaR6ox', // Your Typesense API key
// Habilita los composables auto-importados en cliente
// (useTypesenseDocuments, useTypesenseApi, etc.).
// ⚠️ Solo usa una clave de búsqueda (search-only) aquí: queda expuesta al navegador.
url: process.env.NUXT_PUBLIC_TYPESENSE_URL || 'https://searchts.carpa.com',
apiKey: process.env.NUXT_PUBLIC_TYPESENSE_API_KEY || '',
clientMode: true
}
})

666
package-lock.json generated
View File

@ -23,7 +23,6 @@
"date-fns": "^4.1.0",
"dayjs": "^1.11.20",
"nuxt": "^4.4.2",
"nuxt-meilisearch": "^1.4.17",
"pinia": "^3.0.4",
"scule": "^1.3.0",
"tailwindcss": "^4.2.4",
@ -39,267 +38,6 @@
"vue-tsc": "^3.2.7"
}
},
"node_modules/@ai-sdk/gateway": {
"version": "2.0.86",
"resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-2.0.86.tgz",
"integrity": "sha512-pP9F5G7C5sqZtAwquFB+g50lVS/s4Wf/ll2WSm0ODk0Iix27trVgBDpFK5CBletcQXSDlAvSQQi25nBodYLt3g==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.3",
"@ai-sdk/provider-utils": "3.0.25",
"@vercel/oidc": "3.1.0"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4.1.8"
}
},
"node_modules/@ai-sdk/provider": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-2.0.3.tgz",
"integrity": "sha512-h88OPkavHTiN9tMn2l5awAznGB0lXzjcLhgR1/rvjB2zlLprsNxbM2tt6OJsHUxduLC3klq0/eqaSf6fX5XVww==",
"license": "Apache-2.0",
"dependencies": {
"json-schema": "^0.4.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@ai-sdk/provider-utils": {
"version": "3.0.25",
"resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.25.tgz",
"integrity": "sha512-CvsRu+32Y8a167s+lrIBtsybvgTHp8j9y+6BeTvLeoW3Q+okw/b4CnNUFOLIXsRaKHQKAH+IHNJPYWywfpw0LA==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/provider": "2.0.3",
"@standard-schema/spec": "^1.0.0",
"eventsource-parser": "^3.0.6"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4.1.8"
}
},
"node_modules/@algolia/abtesting": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.18.0.tgz",
"integrity": "sha512-8siuLG+FIns1AjZ/g2SDVwHz9S+ObacDQISEJvS8XsNei1zl3FXqfqQrBpmrG7ACWCyesXHbicMJtvRbg00FEw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@algolia/client-common": "5.52.0",
"@algolia/requester-browser-xhr": "5.52.0",
"@algolia/requester-fetch": "5.52.0",
"@algolia/requester-node-http": "5.52.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-abtesting": {
"version": "5.52.0",
"resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.52.0.tgz",
"integrity": "sha512-wtwPgyPmO7b7sQPVgoK29c1VpfS08DnnJCmxX/oU1pV2DlMRJCzQcLN7JSloYpodyKHwM8+9wOzlAM0co3TDmA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@algolia/client-common": "5.52.0",
"@algolia/requester-browser-xhr": "5.52.0",
"@algolia/requester-fetch": "5.52.0",
"@algolia/requester-node-http": "5.52.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-analytics": {
"version": "5.52.0",
"resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.52.0.tgz",
"integrity": "sha512-9KY36bRl4AH7RjqSeDDOKnjsz4IxQFBEOB8/fWmEbdQe+Isbs5jGzVJu9NEPQ1Tgwxlf8Uf07Swj3jZyMNUZ2g==",
"license": "MIT",
"peer": true,
"dependencies": {
"@algolia/client-common": "5.52.0",
"@algolia/requester-browser-xhr": "5.52.0",
"@algolia/requester-fetch": "5.52.0",
"@algolia/requester-node-http": "5.52.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-common": {
"version": "5.52.0",
"resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.52.0.tgz",
"integrity": "sha512-3a/qM3dzJqqfTx7Yrw7uGQ98I3Q0rDfb4Vkv0wEzko96l7YQMxfBVz/VbLq2N+c59GweYv6Vhp8mPeqnWJSITw==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-insights": {
"version": "5.52.0",
"resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.52.0.tgz",
"integrity": "sha512-Rki7ACbMcvbQW0BuM84x9dkGHY47ABmv4jU6tYssat2k02p3mIUms2YOLUAMeknhmnFsj6lb6ZzOXdMWMyc1sA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@algolia/client-common": "5.52.0",
"@algolia/requester-browser-xhr": "5.52.0",
"@algolia/requester-fetch": "5.52.0",
"@algolia/requester-node-http": "5.52.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-personalization": {
"version": "5.52.0",
"resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.52.0.tgz",
"integrity": "sha512-96s4Uzc3kk+/f4jJXIVVGWP5XlngOGNQ1x6hW9AT59pOixHlOs5tqJg+ZUS/GQ6h/iYP0ceQcmxDQeLyCLTaDQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@algolia/client-common": "5.52.0",
"@algolia/requester-browser-xhr": "5.52.0",
"@algolia/requester-fetch": "5.52.0",
"@algolia/requester-node-http": "5.52.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-query-suggestions": {
"version": "5.52.0",
"resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.52.0.tgz",
"integrity": "sha512-lqeycNpSPe5Qa0OUWpejVvYQjQWV5nQuLT0a4aq7XzRAvCxprV/6Lf841EygdD2nrFnuS58ok7Au1uOtXzpnkg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@algolia/client-common": "5.52.0",
"@algolia/requester-browser-xhr": "5.52.0",
"@algolia/requester-fetch": "5.52.0",
"@algolia/requester-node-http": "5.52.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/client-search": {
"version": "5.52.0",
"resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.52.0.tgz",
"integrity": "sha512-ly1wETVGRo30cx61O7fetESN+ElL9c9K+bD/AVgnT1ar4c6v+/Yqjrhdtu6Fm4D0s4NZP081Isf6tunH1wUXHg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@algolia/client-common": "5.52.0",
"@algolia/requester-browser-xhr": "5.52.0",
"@algolia/requester-fetch": "5.52.0",
"@algolia/requester-node-http": "5.52.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/events": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz",
"integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==",
"license": "MIT"
},
"node_modules/@algolia/ingestion": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.52.0.tgz",
"integrity": "sha512-U4EeTvgmluRjj39ykZSAd5X+a6LD5m7/mcOWDmB7hqm1R6QY0yT8jLxpNVEjYhzgEN5hcDGW6X67EWQY8KiYGQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@algolia/client-common": "5.52.0",
"@algolia/requester-browser-xhr": "5.52.0",
"@algolia/requester-fetch": "5.52.0",
"@algolia/requester-node-http": "5.52.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/monitoring": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.52.0.tgz",
"integrity": "sha512-FCPnDcILfpTE94u7BVlV4DmnSV5wE3+j25EEF+3dYPrVzkVCSoAHs318oWDGxnxsAgiL4HpL12Jc4XHmw9shpA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@algolia/client-common": "5.52.0",
"@algolia/requester-browser-xhr": "5.52.0",
"@algolia/requester-fetch": "5.52.0",
"@algolia/requester-node-http": "5.52.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/recommend": {
"version": "5.52.0",
"resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.52.0.tgz",
"integrity": "sha512-br3DO7n4N8CXwTRbZS0MnB4WQ9YHfNjCwkCEzVR/wek/qNTDQKDb0nROmkFaNZ8ucUqUVKZi074dbwMwRDlK8Q==",
"license": "MIT",
"peer": true,
"dependencies": {
"@algolia/client-common": "5.52.0",
"@algolia/requester-browser-xhr": "5.52.0",
"@algolia/requester-fetch": "5.52.0",
"@algolia/requester-node-http": "5.52.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/requester-browser-xhr": {
"version": "5.52.0",
"resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.52.0.tgz",
"integrity": "sha512-b0T/Ca2c9KyEslKsVrGZvbe1UrrKKSdfXhBZ2pbpKahFUzJfziRZ0urbOm7V65O0tO/jwU+Lo/+bIiiyhzGt8w==",
"license": "MIT",
"peer": true,
"dependencies": {
"@algolia/client-common": "5.52.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/requester-fetch": {
"version": "5.52.0",
"resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.52.0.tgz",
"integrity": "sha512-ozBT8J/mtD4H4IAojw8QPirlcL2gHrI1BGuZ4/ZXXO/rTE1yQ4VIPJj4mTTbwo4FbkS1MoJsD/DsrqLzhnc4/g==",
"license": "MIT",
"peer": true,
"dependencies": {
"@algolia/client-common": "5.52.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@algolia/requester-node-http": {
"version": "5.52.0",
"resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.52.0.tgz",
"integrity": "sha512-gyyWcLD22tnabmoit4iukCXuoRc5HYJuUjPSEa8a0D/f/NlRafpWi52AlAaa4Uu/rsl7saHsJFTNjTptWbu2+A==",
"license": "MIT",
"peer": true,
"dependencies": {
"@algolia/client-common": "5.52.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/@alloc/quick-lru": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
@ -2273,21 +2011,6 @@
"node": ">=6.0.0"
}
},
"node_modules/@meilisearch/instant-meilisearch": {
"version": "0.28.0",
"resolved": "https://registry.npmjs.org/@meilisearch/instant-meilisearch/-/instant-meilisearch-0.28.0.tgz",
"integrity": "sha512-QeY8w0PsoZUwzrKJyrmmi3lGRXDhzPr38t1Ns9iezoA5CD9L3YARjJJKgExybQF6KIReFw1zfJaKbPRA1xTDCA==",
"license": "MIT",
"dependencies": {
"meilisearch": "0.53"
}
},
"node_modules/@meilisearch/instant-meilisearch/node_modules/meilisearch": {
"version": "0.53.0",
"resolved": "https://registry.npmjs.org/meilisearch/-/meilisearch-0.53.0.tgz",
"integrity": "sha512-nG4VXbEOSzUmtbfsgOo+t6yX1ECEgXaT4hC0ap9MBpQGK5xwT+NWYDENYsKWR75cVaWaAqva+ok4zHlgtdXlLw==",
"license": "MIT"
},
"node_modules/@miyaneee/rollup-plugin-json5": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@miyaneee/rollup-plugin-json5/-/rollup-plugin-json5-1.2.0.tgz",
@ -4143,15 +3866,6 @@
"vue": "^3.5.0"
}
},
"node_modules/@opentelemetry/api": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
"integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
"license": "Apache-2.0",
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/@oxc-minify/binding-android-arm-eabi": {
"version": "0.128.0",
"resolved": "https://registry.npmjs.org/@oxc-minify/binding-android-arm-eabi/-/binding-android-arm-eabi-0.128.0.tgz",
@ -7371,12 +7085,6 @@
"integrity": "sha512-QjcRY+adGbYvBFS7cwv5txhVIwX1XXIUswWl+kSQTbI6NjgZydrZkEKX/etzVd7i+bCsCb40Z/xlBY5eoFuvWQ==",
"license": "MIT"
},
"node_modules/@types/dom-speech-recognition": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/@types/dom-speech-recognition/-/dom-speech-recognition-0.0.1.tgz",
"integrity": "sha512-udCxb8DvjcDKfk1WTBzDsxFbLgYxmQGKrE/ricoMqHRNjSlSUCcamVTA5lIQqzY10mY5qCY0QDwBfFEwhfoDPw==",
"license": "MIT"
},
"node_modules/@types/esrecurse": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz",
@ -7395,18 +7103,6 @@
"integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
"license": "MIT"
},
"node_modules/@types/google.maps": {
"version": "3.64.0",
"resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.64.0.tgz",
"integrity": "sha512-dN0H6tB4lgLQLovcbPXFYYOEV41TpyyJghzb5jrzjB96FZmjeOghevVdC+BMGd6YqyCqXaggyEtqRXLRjzCBZA==",
"license": "MIT"
},
"node_modules/@types/hogan.js": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/@types/hogan.js/-/hogan.js-3.0.5.tgz",
"integrity": "sha512-/uRaY3HGPWyLqOyhgvW9Aa43BNnLZrNeQxl2p8wqId4UHMfPKolSB+U7BlZyO1ng7MkLnyEAItsBzCG0SDhqrA==",
"license": "MIT"
},
"node_modules/@types/json-schema": {
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
@ -7451,12 +7147,6 @@
"integrity": "sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==",
"license": "MIT"
},
"node_modules/@types/qs": {
"version": "6.15.0",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.0.tgz",
"integrity": "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==",
"license": "MIT"
},
"node_modules/@types/resolve": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
@ -8219,15 +7909,6 @@
"node": ">=8"
}
},
"node_modules/@vercel/oidc": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.1.0.tgz",
"integrity": "sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==",
"license": "Apache-2.0",
"engines": {
"node": ">= 20"
}
},
"node_modules/@vitejs/plugin-vue": {
"version": "6.0.6",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.6.tgz",
@ -8724,24 +8405,6 @@
"node": ">= 14"
}
},
"node_modules/ai": {
"version": "5.0.183",
"resolved": "https://registry.npmjs.org/ai/-/ai-5.0.183.tgz",
"integrity": "sha512-lmLFkxJ2epeUXi6QXi/9VYs1HF61vikpP8vGnGd3Erdh/syUyfZ/DC1to2AoNwytBNpICN3OGbTpwc7jfPewgg==",
"license": "Apache-2.0",
"dependencies": {
"@ai-sdk/gateway": "2.0.86",
"@ai-sdk/provider": "2.0.3",
"@ai-sdk/provider-utils": "3.0.25",
"@opentelemetry/api": "1.9.0"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"zod": "^3.25.76 || ^4.1.8"
}
},
"node_modules/ajv": {
"version": "6.15.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
@ -8758,44 +8421,6 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/algoliasearch": {
"version": "5.52.0",
"resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.52.0.tgz",
"integrity": "sha512-0ZzY9mjqV7gop/AH8pIBiAS8giXP7WcSiUfoFYIzYAK9QC5c37E4SIVtJVBMwlURc0/uNt2o4RcNRvdHa4CJ5w==",
"license": "MIT",
"peer": true,
"dependencies": {
"@algolia/abtesting": "1.18.0",
"@algolia/client-abtesting": "5.52.0",
"@algolia/client-analytics": "5.52.0",
"@algolia/client-common": "5.52.0",
"@algolia/client-insights": "5.52.0",
"@algolia/client-personalization": "5.52.0",
"@algolia/client-query-suggestions": "5.52.0",
"@algolia/client-search": "5.52.0",
"@algolia/ingestion": "1.52.0",
"@algolia/monitoring": "1.52.0",
"@algolia/recommend": "5.52.0",
"@algolia/requester-browser-xhr": "5.52.0",
"@algolia/requester-fetch": "5.52.0",
"@algolia/requester-node-http": "5.52.0"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/algoliasearch-helper": {
"version": "3.26.0",
"resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.26.0.tgz",
"integrity": "sha512-Rv2x3GXleQ3ygwhkhJubhhYGsICmShLAiqtUuJTUkr9uOCOXyF2E71LVT4XDnVffbknv8XgScP4U0Oxtgm+hIw==",
"license": "MIT",
"dependencies": {
"@algolia/events": "^4.0.1"
},
"peerDependencies": {
"algoliasearch": ">= 3.1 < 6"
}
},
"node_modules/alien-signals": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-3.1.2.tgz",
@ -11795,15 +11420,6 @@
"bare-events": "^2.7.0"
}
},
"node_modules/eventsource-parser": {
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.8.tgz",
"integrity": "sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ==",
"license": "MIT",
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/execa": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
@ -12620,51 +12236,12 @@
"integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==",
"license": "MIT"
},
"node_modules/hogan.js": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz",
"integrity": "sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==",
"dependencies": {
"mkdirp": "0.3.0",
"nopt": "1.0.10"
},
"bin": {
"hulk": "bin/hulk"
}
},
"node_modules/hogan.js/node_modules/abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"license": "ISC"
},
"node_modules/hogan.js/node_modules/nopt": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
"integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
"license": "MIT",
"dependencies": {
"abbrev": "1"
},
"bin": {
"nopt": "bin/nopt.js"
},
"engines": {
"node": "*"
}
},
"node_modules/hookable": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/hookable/-/hookable-6.1.1.tgz",
"integrity": "sha512-U9LYDy1CwhMCnprUfeAZWZGByVbhd54hwepegYTK7Pi5NvqEj63ifz5z+xukznehT7i6NIZRu89Ay1AZmRsLEQ==",
"license": "MIT"
},
"node_modules/htm": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/htm/-/htm-3.1.1.tgz",
"integrity": "sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==",
"license": "Apache-2.0"
},
"node_modules/html-entities": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz",
@ -12850,88 +12427,6 @@
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"license": "ISC"
},
"node_modules/instantsearch-ui-components": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/instantsearch-ui-components/-/instantsearch-ui-components-0.12.0.tgz",
"integrity": "sha512-WcyrNJ5sqeqAWLibztnssSKDhgFEdj4C1prZOHSCONxF+5RSfCsD0oqKiZrTMx3dlAL/Qx7eZxKhD56u5mxJMA==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.27.6",
"ai": "^5.0.18",
"markdown-to-jsx": "^7.7.15",
"zod": "^3.25.76 || ^4",
"zod-to-json-schema": "3.24.6"
}
},
"node_modules/instantsearch-ui-components/node_modules/zod": {
"version": "3.25.76",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
},
"node_modules/instantsearch-ui-components/node_modules/zod-to-json-schema": {
"version": "3.24.6",
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz",
"integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==",
"license": "ISC",
"peerDependencies": {
"zod": "^3.24.1"
}
},
"node_modules/instantsearch.css": {
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/instantsearch.css/-/instantsearch.css-8.6.0.tgz",
"integrity": "sha512-YweaPxsvaITBgKPxEZnuTX0XLfa4JeLBGkhrlcN2glCH1Ipk9XU1M9X+clcAEottTe8K1/q5COePW0Ozr2+0MA==",
"license": "MIT"
},
"node_modules/instantsearch.js": {
"version": "4.81.0",
"resolved": "https://registry.npmjs.org/instantsearch.js/-/instantsearch.js-4.81.0.tgz",
"integrity": "sha512-zyIUSrikpst5eaBMrruGRGmRHOHQciDyJ8UW7i4xhPVNRwxr5Ls/NBez9AdNne+7OvALCOeaTI3t9LoBQakWhw==",
"license": "MIT",
"dependencies": {
"@algolia/events": "^4.0.1",
"@types/dom-speech-recognition": "^0.0.1",
"@types/google.maps": "^3.55.12",
"@types/hogan.js": "^3.0.0",
"@types/qs": "^6.5.3",
"ai": "^5.0.18",
"algoliasearch-helper": "3.26.0",
"hogan.js": "^3.0.2",
"htm": "^3.0.0",
"instantsearch-ui-components": "0.12.0",
"preact": "^10.10.0",
"qs": "^6.5.1 < 6.10",
"react": ">= 0.14.0",
"search-insights": "^2.17.2",
"zod": "^3.25.76 || ^4",
"zod-to-json-schema": "3.24.6"
},
"peerDependencies": {
"algoliasearch": ">= 3.1 < 6"
}
},
"node_modules/instantsearch.js/node_modules/zod": {
"version": "3.25.76",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
},
"node_modules/instantsearch.js/node_modules/zod-to-json-schema": {
"version": "3.24.6",
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz",
"integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==",
"license": "ISC",
"peerDependencies": {
"zod": "^3.24.1"
}
},
"node_modules/internmap": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
@ -13276,12 +12771,6 @@
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
"license": "MIT"
},
"node_modules/json-schema": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
"license": "(AFL-2.1 OR BSD-3-Clause)"
},
"node_modules/json-schema-to-typescript-lite": {
"version": "15.0.0",
"resolved": "https://registry.npmjs.org/json-schema-to-typescript-lite/-/json-schema-to-typescript-lite-15.0.0.tgz",
@ -14022,23 +13511,6 @@
"vt-pbf": "^3.1.3"
}
},
"node_modules/markdown-to-jsx": {
"version": "7.7.17",
"resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.7.17.tgz",
"integrity": "sha512-7mG/1feQ0TX5I7YyMZVDgCC/y2I3CiEhIRQIhyov9nGBP5eoVrOXXHuL5ZP8GRfxVZKRiXWJgwXkb9It+nQZfQ==",
"license": "MIT",
"engines": {
"node": ">= 10"
},
"peerDependencies": {
"react": ">= 0.14.0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
}
}
},
"node_modules/marked": {
"version": "17.0.6",
"resolved": "https://registry.npmjs.org/marked/-/marked-17.0.6.tgz",
@ -14066,12 +13538,6 @@
"integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==",
"license": "CC0-1.0"
},
"node_modules/meilisearch": {
"version": "0.54.0",
"resolved": "https://registry.npmjs.org/meilisearch/-/meilisearch-0.54.0.tgz",
"integrity": "sha512-b1bwJAEfj8C6hgSN88+/LvW3pe3nWC+thBS2seAbPZGakf/vzsLqppgZquiomzCr2GhU7U7H289625qhYe3rbw==",
"license": "MIT"
},
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@ -14209,22 +13675,6 @@
"node": ">= 18"
}
},
"node_modules/mitt": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mitt/-/mitt-2.1.0.tgz",
"integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==",
"license": "MIT"
},
"node_modules/mkdirp": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz",
"integrity": "sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==",
"deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)",
"license": "MIT/X11",
"engines": {
"node": "*"
}
},
"node_modules/mlly": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz",
@ -15204,60 +14654,6 @@
}
}
},
"node_modules/nuxt-meilisearch": {
"version": "1.4.17",
"resolved": "https://registry.npmjs.org/nuxt-meilisearch/-/nuxt-meilisearch-1.4.17.tgz",
"integrity": "sha512-9O0dUIwuu00YAGVqQ0BVp/7kgLf3a6ONeOy6gDYtgj8sw/VI1o5tYIwg9hMjesOD1Jw/2WGL8dORkNRN2Mwedg==",
"license": "MIT",
"dependencies": {
"@meilisearch/instant-meilisearch": "0.28.0",
"@nuxt/kit": "4.2.0",
"instantsearch.css": "8.6.0",
"meilisearch": "0.54.0",
"vue-instantsearch": "4.22.0"
}
},
"node_modules/nuxt-meilisearch/node_modules/@nuxt/kit": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-4.2.0.tgz",
"integrity": "sha512-1yN3LL6RDN5GjkNLPUYCbNRkaYnat6hqejPyfIBBVzrWOrpiQeNMGxQM/IcVdaSuBJXAnu0sUvTKXpXkmPhljg==",
"license": "MIT",
"dependencies": {
"c12": "^3.3.1",
"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",
"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"
},
"engines": {
"node": ">=18.12.0"
}
},
"node_modules/nuxt-meilisearch/node_modules/rc9": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz",
"integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==",
"license": "MIT",
"dependencies": {
"defu": "^6.1.4",
"destr": "^2.0.3"
}
},
"node_modules/nuxt/node_modules/cookie-es": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-2.0.1.tgz",
@ -16362,16 +15758,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/preact": {
"version": "10.29.1",
"resolved": "https://registry.npmjs.org/preact/-/preact-10.29.1.tgz",
"integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/preact"
}
},
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@ -16578,18 +15964,6 @@
"node": ">=6"
}
},
"node_modules/qs": {
"version": "6.9.9",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.9.tgz",
"integrity": "sha512-4mp+ySf3n7scxSqU6LIO9jjYCJWIdbXh3EQ8uvEc1uXiZm8sLI7moRTOvZb66c8zEHelBGEVRkSW6e9JCaayTw==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/quansync": {
"version": "0.2.11",
"resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz",
@ -16657,15 +16031,6 @@
"destr": "^2.0.5"
}
},
"node_modules/react": {
"version": "19.2.5",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.5.tgz",
"integrity": "sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/readable-stream": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz",
@ -17111,12 +16476,6 @@
"integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==",
"license": "MIT"
},
"node_modules/search-insights": {
"version": "2.17.3",
"resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz",
"integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==",
"license": "MIT"
},
"node_modules/semver": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
@ -19187,31 +18546,6 @@
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
"license": "MIT"
},
"node_modules/vue-instantsearch": {
"version": "4.22.0",
"resolved": "https://registry.npmjs.org/vue-instantsearch/-/vue-instantsearch-4.22.0.tgz",
"integrity": "sha512-/BUdzD+NAybC81FGzEeSuCSYobYUVgHEHI7QY0HlTzdxIHOqWlw2y152/80kGKndS0C+Yu5ifGGg+xVIcFc4Dg==",
"license": "MIT",
"dependencies": {
"instantsearch-ui-components": "0.12.0",
"instantsearch.js": "4.81.0",
"mitt": "^2.1.0"
},
"peerDependencies": {
"@vue/server-renderer": "^3.1.2",
"algoliasearch": ">= 3.32.0 < 6",
"vue": "^2.6.0 || >=3.0.0-rc.0",
"vue-server-renderer": "^2.6.11"
},
"peerDependenciesMeta": {
"@vue/server-renderer": {
"optional": true
},
"vue-server-renderer": {
"optional": true
}
}
},
"node_modules/vue-router": {
"version": "5.0.6",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-5.0.6.tgz",

View File

@ -27,7 +27,6 @@
"date-fns": "^4.1.0",
"dayjs": "^1.11.20",
"nuxt": "^4.4.2",
"nuxt-meilisearch": "^1.4.17",
"pinia": "^3.0.4",
"scule": "^1.3.0",
"tailwindcss": "^4.2.4",

View File

@ -22,7 +22,7 @@ importers:
version: 3.12.1
'@nuxt/ui':
specifier: ^4.7.0
version: 4.7.1(@internationalized/date@3.12.1)(@internationalized/number@3.6.6)(@tiptap/extensions@3.23.1(@tiptap/core@3.23.1(@tiptap/pm@3.23.1))(@tiptap/pm@3.23.1))(@tiptap/y-tiptap@3.0.3(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.8)(y-protocols@1.0.7(yjs@13.6.30))(yjs@13.6.30))(axios@1.16.0)(change-case@5.4.4)(db0@0.3.4)(embla-carousel@8.6.0)(ioredis@5.10.1)(magicast@0.5.2)(react@19.2.6)(tailwindcss@4.3.0)(typescript@6.0.3)(vite@7.3.3(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.47.1)(yaml@2.9.0))(vue-router@4.6.4(vue@3.5.34(typescript@6.0.3)))(vue@3.5.34(typescript@6.0.3))(yjs@13.6.30)(zod@4.4.3)
version: 4.7.1(@internationalized/date@3.12.1)(@internationalized/number@3.6.6)(@tiptap/extensions@3.23.1(@tiptap/core@3.23.1(@tiptap/pm@3.23.1))(@tiptap/pm@3.23.1))(@tiptap/y-tiptap@3.0.3(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.8)(y-protocols@1.0.7(yjs@13.6.30))(yjs@13.6.30))(axios@1.16.0)(change-case@5.4.4)(db0@0.3.4)(embla-carousel@8.6.0)(ioredis@5.10.1)(magicast@0.5.2)(tailwindcss@4.3.0)(typescript@6.0.3)(vite@7.3.3(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.47.1)(yaml@2.9.0))(vue-router@4.6.4(vue@3.5.34(typescript@6.0.3)))(vue@3.5.34(typescript@6.0.3))(yjs@13.6.30)(zod@4.4.3)
'@nuxtjs/i18n':
specifier: ^9.5.6
version: 9.5.6(@vue/compiler-dom@3.5.34)(eslint@10.3.0(jiti@2.7.0))(magicast@0.5.2)(rollup@4.60.3)(vue@3.5.34(typescript@6.0.3))
@ -56,9 +56,6 @@ importers:
nuxt:
specifier: ^4.4.2
version: 4.4.5(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@vue/compiler-sfc@3.5.34)(cac@6.7.14)(db0@0.3.4)(eslint@10.3.0(jiti@2.7.0))(ioredis@5.10.1)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(pinia@3.0.4(typescript@6.0.3)(vue@3.5.34(typescript@6.0.3)))(rollup-plugin-visualizer@7.0.1(rollup@4.60.3))(rollup@4.60.3)(srvx@0.11.15)(terser@5.47.1)(typescript@6.0.3)(vite@7.3.3(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.47.1)(yaml@2.9.0))(vue-tsc@3.2.8(typescript@6.0.3))(yaml@2.9.0)
nuxt-meilisearch:
specifier: ^1.4.17
version: 1.4.17(@vue/server-renderer@3.5.34(vue@3.5.34(typescript@6.0.3)))(algoliasearch@5.52.1)(magicast@0.5.2)(react@19.2.6)(vue@3.5.34(typescript@6.0.3))
pinia:
specifier: ^3.0.4
version: 3.0.4(typescript@6.0.3)(vue@3.5.34(typescript@6.0.3))
@ -96,81 +93,6 @@ importers:
packages:
'@ai-sdk/gateway@2.0.88':
resolution: {integrity: sha512-H62l0gxr4K0rdR2WHbvck2wOKMsocAjdZg41Exsj9Qf5/TyAuHzcNt9jKNv5t2vRFXFZaCpbC5uCCxgUC/GiaA==}
engines: {node: '>=18'}
peerDependencies:
zod: ^3.25.76 || ^4.1.8
'@ai-sdk/provider-utils@3.0.25':
resolution: {integrity: sha512-CvsRu+32Y8a167s+lrIBtsybvgTHp8j9y+6BeTvLeoW3Q+okw/b4CnNUFOLIXsRaKHQKAH+IHNJPYWywfpw0LA==}
engines: {node: '>=18'}
peerDependencies:
zod: ^3.25.76 || ^4.1.8
'@ai-sdk/provider@2.0.3':
resolution: {integrity: sha512-h88OPkavHTiN9tMn2l5awAznGB0lXzjcLhgR1/rvjB2zlLprsNxbM2tt6OJsHUxduLC3klq0/eqaSf6fX5XVww==}
engines: {node: '>=18'}
'@algolia/abtesting@1.18.1':
resolution: {integrity: sha512-aehCadlWOGvrT91KUIZpC0MbB8KBW9yUuvTJFd2xesR7le/IsT4nJUnjCCZ4ZqZCeTcPHPV5mo//fZ5oxcSVYw==}
engines: {node: '>= 14.0.0'}
'@algolia/client-abtesting@5.52.1':
resolution: {integrity: sha512-HmXOGBOAOJPounpBzBpuY0zDYeiCpxgHnQmuA7JO6ScukcBdGp3/XM9zJk5pJx/xNGD68mbPGXWpDxGtl6BwDQ==}
engines: {node: '>= 14.0.0'}
'@algolia/client-analytics@5.52.1':
resolution: {integrity: sha512-5oo4+I8iixie9vXhCyNFCzeIr8pqA3FQ//VsLHTDvZAV4ttYOPGvYHGQq5NSalrLx5Jc3dRro/5uDOlnUMcBJg==}
engines: {node: '>= 14.0.0'}
'@algolia/client-common@5.52.1':
resolution: {integrity: sha512-qCDoZfx5MpX7XQzvQ3bC4tSEMkQWQMaF/ABtLuoze03Y/flR563CCSws02qIJ23oX7lxl92LsilZjINVyTdtLw==}
engines: {node: '>= 14.0.0'}
'@algolia/client-insights@5.52.1':
resolution: {integrity: sha512-hnGs0/lsFJ2PWDxNBz7pxreXo/Xz7gxYRcfePBUjsH26ad0kU/sgnVZd9LwWBpsQv65z2jlb5dkyaB9WE9M9FQ==}
engines: {node: '>= 14.0.0'}
'@algolia/client-personalization@5.52.1':
resolution: {integrity: sha512-2VxxNc/uBysyKvGeBdSM5n9eIDKH8kWD7wd9/yqbJAiVwU4Yv6tU1LSJusHKrXV/aCu1KW7t9Gug9QyeEmtn/Q==}
engines: {node: '>= 14.0.0'}
'@algolia/client-query-suggestions@5.52.1':
resolution: {integrity: sha512-O6mPtsw3xEfNOe6gWFpYLeAZAIljNa4Hgna3bq15PwyN7nbjTY0wXJFRbzs/0YVf75Br+SbOQUmjKxXYjDiSiQ==}
engines: {node: '>= 14.0.0'}
'@algolia/client-search@5.52.1':
resolution: {integrity: sha512-gA8oJOV1LnQQkDf91iebNnFInHuW0gRPEgLSOQ7EfipCEjYTHm5swm1DlH9H5RaRw4RrHuzHBegnlzc0MAstcg==}
engines: {node: '>= 14.0.0'}
'@algolia/events@4.0.1':
resolution: {integrity: sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==}
'@algolia/ingestion@1.52.1':
resolution: {integrity: sha512-U9zZfc5xIu9wRxZkt+HceJUAD4VKHKbAyLSloJdEyMRmphXeibfrY9cxqIXBcmPeZzGhn3Imb35Dq8l19PkJhw==}
engines: {node: '>= 14.0.0'}
'@algolia/monitoring@1.52.1':
resolution: {integrity: sha512-a3SGNceHmkQfq77iG8Ka+w1pvwfZa/0lzEIgse30fL0kD+yKnd/dg0dQvSfFPAEt2f21DMcGkDSSeJlO3KdQjQ==}
engines: {node: '>= 14.0.0'}
'@algolia/recommend@5.52.1':
resolution: {integrity: sha512-z98QEguCFDpxb4S/PyrUK1igqF8tPsdbqOUUO6ON91vJ58w+Gwa6ncrI0oNXSFcrkxA5EqPKPQ2A1PBCn08TYQ==}
engines: {node: '>= 14.0.0'}
'@algolia/requester-browser-xhr@5.52.1':
resolution: {integrity: sha512-CI7+/0I11QeZM59Uc8whd2or0kqzFVjpaPn9Qpwll/krHcBAxk24WkAQ6WX+IwDVMfpont4YGbKwAmCre3vE8Q==}
engines: {node: '>= 14.0.0'}
'@algolia/requester-fetch@5.52.1':
resolution: {integrity: sha512-S6bDuw9byfOvm3T71cgdoZgrgnZq6hpdMLkx52Louh57nUAmvGQESz2aojOynQHjbTiV55smvAFbgn0qT4tJrg==}
engines: {node: '>= 14.0.0'}
'@algolia/requester-node-http@5.52.1':
resolution: {integrity: sha512-tqZXM+54rWo4mk5jL5Z/flE11nPmNEdXwFBM5py9DkOmbjeCNemfVd45FyM97XdzfZ0dl9uOJC6PYn1FpkeyQg==}
engines: {node: '>= 14.0.0'}
'@alloc/quick-lru@5.2.0':
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
engines: {node: '>=10'}
@ -1121,9 +1043,6 @@ packages:
resolution: {integrity: sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==}
engines: {node: '>=6.0.0'}
'@meilisearch/instant-meilisearch@0.28.0':
resolution: {integrity: sha512-QeY8w0PsoZUwzrKJyrmmi3lGRXDhzPr38t1Ns9iezoA5CD9L3YARjJJKgExybQF6KIReFw1zfJaKbPRA1xTDCA==}
'@miyaneee/rollup-plugin-json5@1.2.0':
resolution: {integrity: sha512-JjTIaXZp9WzhUHpElrqPnl1AzBi/rvRs065F71+aTmlqvTMVkdbjZ8vfFl4nRlgJy+TPBw69ZK4pwFdmOAt4aA==}
peerDependencies:
@ -1218,10 +1137,6 @@ packages:
resolution: {integrity: sha512-eGo9DjJ9NzKMbJpFU/UTd4c5iOSYuivghKD8W/jVGHs7kew+hdSMvUy401IfQB7EObKPvt/WXEutAIaTg9OsyA==}
engines: {node: '>=18.12.0'}
'@nuxt/kit@4.2.0':
resolution: {integrity: sha512-1yN3LL6RDN5GjkNLPUYCbNRkaYnat6hqejPyfIBBVzrWOrpiQeNMGxQM/IcVdaSuBJXAnu0sUvTKXpXkmPhljg==}
engines: {node: '>=18.12.0'}
'@nuxt/kit@4.4.5':
resolution: {integrity: sha512-J0BpoOomzd3iVZozYlZJ7AwAVliXRgeChZnAkQLfg8d0h/Q+aMK9kkHuhwFULASaRn5idiD4BIhOUz7/uoLbSw==}
engines: {node: '>=18.12.0'}
@ -1316,10 +1231,6 @@ packages:
resolution: {integrity: sha512-PhrQtJT6Di9uoslL5BTrBFqntFlfCaUKlO3T9ORJwmWFdowPqQeFjQ9OjVbKA6TNWr3kQhDqLbIcGlhbuG1USQ==}
engines: {node: '>=18.12.0'}
'@opentelemetry/api@1.9.0':
resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==}
engines: {node: '>=8.0.0'}
'@oxc-minify/binding-android-arm-eabi@0.128.0':
resolution: {integrity: sha512-EwdDhZLRmXxSnfy0v9gdOru7TutM8ItRg1Xv8e2B4boWMnHlFCIH38JfwgQnenbkF8SVTwVJtDCkmwEzN4q3xA==}
engines: {node: ^20.19.0 || >=22.12.0}
@ -2625,9 +2536,6 @@ packages:
'@types/dagre@0.7.54':
resolution: {integrity: sha512-QjcRY+adGbYvBFS7cwv5txhVIwX1XXIUswWl+kSQTbI6NjgZydrZkEKX/etzVd7i+bCsCb40Z/xlBY5eoFuvWQ==}
'@types/dom-speech-recognition@0.0.1':
resolution: {integrity: sha512-udCxb8DvjcDKfk1WTBzDsxFbLgYxmQGKrE/ricoMqHRNjSlSUCcamVTA5lIQqzY10mY5qCY0QDwBfFEwhfoDPw==}
'@types/esrecurse@4.3.1':
resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==}
@ -2640,12 +2548,6 @@ packages:
'@types/geojson@7946.0.16':
resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==}
'@types/google.maps@3.64.0':
resolution: {integrity: sha512-dN0H6tB4lgLQLovcbPXFYYOEV41TpyyJghzb5jrzjB96FZmjeOghevVdC+BMGd6YqyCqXaggyEtqRXLRjzCBZA==}
'@types/hogan.js@3.0.5':
resolution: {integrity: sha512-/uRaY3HGPWyLqOyhgvW9Aa43BNnLZrNeQxl2p8wqId4UHMfPKolSB+U7BlZyO1ng7MkLnyEAItsBzCG0SDhqrA==}
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
@ -2664,9 +2566,6 @@ packages:
'@types/pbf@3.0.5':
resolution: {integrity: sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==}
'@types/qs@6.15.1':
resolution: {integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==}
'@types/resolve@1.20.2':
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
@ -2887,10 +2786,6 @@ packages:
engines: {node: '>=20'}
hasBin: true
'@vercel/oidc@3.1.0':
resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==}
engines: {node: '>= 20'}
'@vitejs/plugin-vue-jsx@5.1.5':
resolution: {integrity: sha512-jIAsvHOEtWpslLOI2MeElGFxH7M8pM83BU/Tor4RLyiwH0FM4nUW3xdvbw20EeU9wc5IspQwMq225K3CMnJEpA==}
engines: {node: ^20.19.0 || >=22.12.0}
@ -3076,9 +2971,6 @@ packages:
peerDependencies:
vue: ^3.5.0
abbrev@1.1.1:
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
abbrev@3.0.1:
resolution: {integrity: sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==}
engines: {node: ^18.17.0 || >=20.5.0}
@ -3106,24 +2998,9 @@ packages:
resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
engines: {node: '>= 14'}
ai@5.0.186:
resolution: {integrity: sha512-0HVwYO9k/x5eSNggqya/75uirBLjkZoL5QdNp9ftjOCl/IXWSzqys/SzsL3ifWBz603a0KbW+EZyYVtmbFJrTQ==}
engines: {node: '>=18'}
peerDependencies:
zod: ^3.25.76 || ^4.1.8
ajv@6.15.0:
resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==}
algoliasearch-helper@3.26.0:
resolution: {integrity: sha512-Rv2x3GXleQ3ygwhkhJubhhYGsICmShLAiqtUuJTUkr9uOCOXyF2E71LVT4XDnVffbknv8XgScP4U0Oxtgm+hIw==}
peerDependencies:
algoliasearch: '>= 3.1 < 6'
algoliasearch@5.52.1:
resolution: {integrity: sha512-fHA8+kXTbjagw3jkLiaS7KKrH8qe2DyOsiUhGlN4cdT77PEsfqXZl7ewDk1hsg+pJnPlnE50XtLxjR91iJOpmg==}
engines: {node: '>= 14.0.0'}
alien-signals@3.1.2:
resolution: {integrity: sha512-d9dYqZTS90WLiU0I5c6DHj/HcKkF8ZyGN3G5x8wSbslulz70KOxaqCT0hQCo9KOyhVqzqGojvNdJXoTumZOtcw==}
@ -4134,10 +4011,6 @@ packages:
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
engines: {node: '>=0.8.x'}
eventsource-parser@3.0.8:
resolution: {integrity: sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ==}
engines: {node: '>=18.0.0'}
execa@8.0.1:
resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
engines: {node: '>=16.17'}
@ -4403,19 +4276,12 @@ packages:
hey-listen@1.0.8:
resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==}
hogan.js@3.0.2:
resolution: {integrity: sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==}
hasBin: true
hookable@5.5.3:
resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
hookable@6.1.1:
resolution: {integrity: sha512-U9LYDy1CwhMCnprUfeAZWZGByVbhd54hwepegYTK7Pi5NvqEj63ifz5z+xukznehT7i6NIZRu89Ay1AZmRsLEQ==}
htm@3.1.1:
resolution: {integrity: sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ==}
html-entities@2.6.0:
resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==}
@ -4484,17 +4350,6 @@ packages:
resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
instantsearch-ui-components@0.12.0:
resolution: {integrity: sha512-WcyrNJ5sqeqAWLibztnssSKDhgFEdj4C1prZOHSCONxF+5RSfCsD0oqKiZrTMx3dlAL/Qx7eZxKhD56u5mxJMA==}
instantsearch.css@8.6.0:
resolution: {integrity: sha512-YweaPxsvaITBgKPxEZnuTX0XLfa4JeLBGkhrlcN2glCH1Ipk9XU1M9X+clcAEottTe8K1/q5COePW0Ozr2+0MA==}
instantsearch.js@4.81.0:
resolution: {integrity: sha512-zyIUSrikpst5eaBMrruGRGmRHOHQciDyJ8UW7i4xhPVNRwxr5Ls/NBez9AdNne+7OvALCOeaTI3t9LoBQakWhw==}
peerDependencies:
algoliasearch: '>= 3.1 < 6'
internmap@1.0.1:
resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==}
@ -4631,9 +4486,6 @@ packages:
json-schema-traverse@0.4.1:
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
json-schema@0.4.0:
resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==}
json-stable-stringify-without-jsonify@1.0.1:
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
@ -4842,15 +4694,6 @@ packages:
maplibre-gl@2.4.0:
resolution: {integrity: sha512-csNFylzntPmHWidczfgCZpvbTSmhaWvLRj9e1ezUDBEPizGgshgm3ea1T5TCNEEBq0roauu7BPuRZjA3wO4KqA==}
markdown-to-jsx@7.7.17:
resolution: {integrity: sha512-7mG/1feQ0TX5I7YyMZVDgCC/y2I3CiEhIRQIhyov9nGBP5eoVrOXXHuL5ZP8GRfxVZKRiXWJgwXkb9It+nQZfQ==}
engines: {node: '>= 10'}
peerDependencies:
react: '>= 0.14.0'
peerDependenciesMeta:
react:
optional: true
marked@17.0.6:
resolution: {integrity: sha512-gB0gkNafnonOw0obSTEGZTT86IuhILt2Wfx0mWH/1Au83kybTayroZ/V6nS25mN7u8ASy+5fMhgB3XPNrOZdmA==}
engines: {node: '>= 20'}
@ -4866,12 +4709,6 @@ packages:
mdn-data@2.27.1:
resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==}
meilisearch@0.53.0:
resolution: {integrity: sha512-nG4VXbEOSzUmtbfsgOo+t6yX1ECEgXaT4hC0ap9MBpQGK5xwT+NWYDENYsKWR75cVaWaAqva+ok4zHlgtdXlLw==}
meilisearch@0.54.0:
resolution: {integrity: sha512-b1bwJAEfj8C6hgSN88+/LvW3pe3nWC+thBS2seAbPZGakf/vzsLqppgZquiomzCr2GhU7U7H289625qhYe3rbw==}
merge-stream@2.0.0:
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
@ -4931,16 +4768,9 @@ packages:
resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==}
engines: {node: '>= 18'}
mitt@2.1.0:
resolution: {integrity: sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==}
mitt@3.0.1:
resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
mkdirp@0.3.0:
resolution: {integrity: sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==}
deprecated: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)
mlly@1.8.2:
resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==}
@ -5027,10 +4857,6 @@ packages:
node-releases@2.0.38:
resolution: {integrity: sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==}
nopt@1.0.10:
resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==}
hasBin: true
nopt@8.1.0:
resolution: {integrity: sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==}
engines: {node: ^18.17.0 || >=20.5.0}
@ -5051,9 +4877,6 @@ packages:
nth-check@2.1.1:
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
nuxt-meilisearch@1.4.17:
resolution: {integrity: sha512-9O0dUIwuu00YAGVqQ0BVp/7kgLf3a6ONeOy6gDYtgj8sw/VI1o5tYIwg9hMjesOD1Jw/2WGL8dORkNRN2Mwedg==}
nuxt@4.4.5:
resolution: {integrity: sha512-MwTf3wyaEIm1U9/T1VKpqg7rGhhrn5Cx2ZS40lwo8GxsiY9xE7UOj5Cg0eAI0fSbJzyXlzdxspytgqWsgL+nIA==}
engines: {node: ^20.19.0 || >=22.12.0}
@ -5431,9 +5254,6 @@ packages:
resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==}
engines: {node: '>=20'}
preact@10.29.1:
resolution: {integrity: sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==}
prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
@ -5499,10 +5319,6 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
qs@6.9.9:
resolution: {integrity: sha512-4mp+ySf3n7scxSqU6LIO9jjYCJWIdbXh3EQ8uvEc1uXiZm8sLI7moRTOvZb66c8zEHelBGEVRkSW6e9JCaayTw==}
engines: {node: '>=0.6'}
quansync@0.2.11:
resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==}
@ -5519,16 +5335,9 @@ packages:
resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
engines: {node: '>= 0.6'}
rc9@2.1.2:
resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==}
rc9@3.0.1:
resolution: {integrity: sha512-gMDyleLWVE+i6Sgtc0QbbY6pEKqYs97NGi6isHQPqYlLemPoO8dxQ3uGi0f4NiP98c+jMW6cG1Kx9dDwfvqARQ==}
react@19.2.6:
resolution: {integrity: sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==}
engines: {node: '>=0.10.0'}
readable-stream@2.3.8:
resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
@ -5667,9 +5476,6 @@ packages:
scule@1.3.0:
resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==}
search-insights@2.17.3:
resolution: {integrity: sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==}
semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
hasBin: true
@ -6342,19 +6148,6 @@ packages:
peerDependencies:
vue: ^3.0.0
vue-instantsearch@4.22.0:
resolution: {integrity: sha512-/BUdzD+NAybC81FGzEeSuCSYobYUVgHEHI7QY0HlTzdxIHOqWlw2y152/80kGKndS0C+Yu5ifGGg+xVIcFc4Dg==}
peerDependencies:
'@vue/server-renderer': ^3.1.2
algoliasearch: '>= 3.32.0 < 6'
vue: ^2.6.0 || >=3.0.0-rc.0
vue-server-renderer: ^2.6.11
peerDependenciesMeta:
'@vue/server-renderer':
optional: true
vue-server-renderer:
optional: true
vue-router@4.6.4:
resolution: {integrity: sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==}
peerDependencies:
@ -6519,120 +6312,11 @@ packages:
resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==}
engines: {node: '>= 14'}
zod-to-json-schema@3.24.6:
resolution: {integrity: sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==}
peerDependencies:
zod: ^3.24.1
zod@4.4.3:
resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==}
snapshots:
'@ai-sdk/gateway@2.0.88(zod@4.4.3)':
dependencies:
'@ai-sdk/provider': 2.0.3
'@ai-sdk/provider-utils': 3.0.25(zod@4.4.3)
'@vercel/oidc': 3.1.0
zod: 4.4.3
'@ai-sdk/provider-utils@3.0.25(zod@4.4.3)':
dependencies:
'@ai-sdk/provider': 2.0.3
'@standard-schema/spec': 1.1.0
eventsource-parser: 3.0.8
zod: 4.4.3
'@ai-sdk/provider@2.0.3':
dependencies:
json-schema: 0.4.0
'@algolia/abtesting@1.18.1':
dependencies:
'@algolia/client-common': 5.52.1
'@algolia/requester-browser-xhr': 5.52.1
'@algolia/requester-fetch': 5.52.1
'@algolia/requester-node-http': 5.52.1
'@algolia/client-abtesting@5.52.1':
dependencies:
'@algolia/client-common': 5.52.1
'@algolia/requester-browser-xhr': 5.52.1
'@algolia/requester-fetch': 5.52.1
'@algolia/requester-node-http': 5.52.1
'@algolia/client-analytics@5.52.1':
dependencies:
'@algolia/client-common': 5.52.1
'@algolia/requester-browser-xhr': 5.52.1
'@algolia/requester-fetch': 5.52.1
'@algolia/requester-node-http': 5.52.1
'@algolia/client-common@5.52.1': {}
'@algolia/client-insights@5.52.1':
dependencies:
'@algolia/client-common': 5.52.1
'@algolia/requester-browser-xhr': 5.52.1
'@algolia/requester-fetch': 5.52.1
'@algolia/requester-node-http': 5.52.1
'@algolia/client-personalization@5.52.1':
dependencies:
'@algolia/client-common': 5.52.1
'@algolia/requester-browser-xhr': 5.52.1
'@algolia/requester-fetch': 5.52.1
'@algolia/requester-node-http': 5.52.1
'@algolia/client-query-suggestions@5.52.1':
dependencies:
'@algolia/client-common': 5.52.1
'@algolia/requester-browser-xhr': 5.52.1
'@algolia/requester-fetch': 5.52.1
'@algolia/requester-node-http': 5.52.1
'@algolia/client-search@5.52.1':
dependencies:
'@algolia/client-common': 5.52.1
'@algolia/requester-browser-xhr': 5.52.1
'@algolia/requester-fetch': 5.52.1
'@algolia/requester-node-http': 5.52.1
'@algolia/events@4.0.1': {}
'@algolia/ingestion@1.52.1':
dependencies:
'@algolia/client-common': 5.52.1
'@algolia/requester-browser-xhr': 5.52.1
'@algolia/requester-fetch': 5.52.1
'@algolia/requester-node-http': 5.52.1
'@algolia/monitoring@1.52.1':
dependencies:
'@algolia/client-common': 5.52.1
'@algolia/requester-browser-xhr': 5.52.1
'@algolia/requester-fetch': 5.52.1
'@algolia/requester-node-http': 5.52.1
'@algolia/recommend@5.52.1':
dependencies:
'@algolia/client-common': 5.52.1
'@algolia/requester-browser-xhr': 5.52.1
'@algolia/requester-fetch': 5.52.1
'@algolia/requester-node-http': 5.52.1
'@algolia/requester-browser-xhr@5.52.1':
dependencies:
'@algolia/client-common': 5.52.1
'@algolia/requester-fetch@5.52.1':
dependencies:
'@algolia/client-common': 5.52.1
'@algolia/requester-node-http@5.52.1':
dependencies:
'@algolia/client-common': 5.52.1
'@alloc/quick-lru@5.2.0': {}
'@antfu/install-pkg@1.1.0':
@ -7457,10 +7141,6 @@ snapshots:
'@mapbox/whoots-js@3.1.0': {}
'@meilisearch/instant-meilisearch@0.28.0':
dependencies:
meilisearch: 0.53.0
'@miyaneee/rollup-plugin-json5@1.2.0(rollup@4.60.3)':
dependencies:
'@rollup/pluginutils': 5.3.0(rollup@4.60.3)
@ -7748,31 +7428,6 @@ snapshots:
transitivePeerDependencies:
- magicast
'@nuxt/kit@4.2.0(magicast@0.5.2)':
dependencies:
c12: 3.3.4(magicast@0.5.2)
consola: 3.4.2
defu: 6.1.7
destr: 2.0.5
errx: 0.1.0
exsolve: 1.0.8
ignore: 7.0.5
jiti: 2.7.0
klona: 2.0.6
mlly: 1.8.2
ohash: 2.0.11
pathe: 2.0.3
pkg-types: 2.3.1
rc9: 2.1.2
scule: 1.3.0
semver: 7.8.0
tinyglobby: 0.2.16
ufo: 1.6.4
unctx: 2.5.0
untyped: 2.0.0
transitivePeerDependencies:
- magicast
'@nuxt/kit@4.4.5(magicast@0.5.2)':
dependencies:
c12: 3.3.4(magicast@0.5.2)
@ -7885,7 +7540,7 @@ snapshots:
rc9: 3.0.1
std-env: 4.1.0
'@nuxt/ui@4.7.1(@internationalized/date@3.12.1)(@internationalized/number@3.6.6)(@tiptap/extensions@3.23.1(@tiptap/core@3.23.1(@tiptap/pm@3.23.1))(@tiptap/pm@3.23.1))(@tiptap/y-tiptap@3.0.3(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.8)(y-protocols@1.0.7(yjs@13.6.30))(yjs@13.6.30))(axios@1.16.0)(change-case@5.4.4)(db0@0.3.4)(embla-carousel@8.6.0)(ioredis@5.10.1)(magicast@0.5.2)(react@19.2.6)(tailwindcss@4.3.0)(typescript@6.0.3)(vite@7.3.3(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.47.1)(yaml@2.9.0))(vue-router@4.6.4(vue@3.5.34(typescript@6.0.3)))(vue@3.5.34(typescript@6.0.3))(yjs@13.6.30)(zod@4.4.3)':
'@nuxt/ui@4.7.1(@internationalized/date@3.12.1)(@internationalized/number@3.6.6)(@tiptap/extensions@3.23.1(@tiptap/core@3.23.1(@tiptap/pm@3.23.1))(@tiptap/pm@3.23.1))(@tiptap/y-tiptap@3.0.3(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.8)(y-protocols@1.0.7(yjs@13.6.30))(yjs@13.6.30))(axios@1.16.0)(change-case@5.4.4)(db0@0.3.4)(embla-carousel@8.6.0)(ioredis@5.10.1)(magicast@0.5.2)(tailwindcss@4.3.0)(typescript@6.0.3)(vite@7.3.3(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.47.1)(yaml@2.9.0))(vue-router@4.6.4(vue@3.5.34(typescript@6.0.3)))(vue@3.5.34(typescript@6.0.3))(yjs@13.6.30)(zod@4.4.3)':
dependencies:
'@floating-ui/dom': 1.7.6
'@iconify/vue': 5.0.1(vue@3.5.34(typescript@6.0.3))
@ -7935,7 +7590,7 @@ snapshots:
knitwork: 1.3.0
magic-string: 0.30.21
mlly: 1.8.2
motion-v: 2.2.1(@vueuse/core@14.3.0(vue@3.5.34(typescript@6.0.3)))(react@19.2.6)(vue@3.5.34(typescript@6.0.3))
motion-v: 2.2.1(@vueuse/core@14.3.0(vue@3.5.34(typescript@6.0.3)))(vue@3.5.34(typescript@6.0.3))
ohash: 2.0.11
pathe: 2.0.3
reka-ui: 2.9.6(vue@3.5.34(typescript@6.0.3))
@ -8103,8 +7758,6 @@ snapshots:
- supports-color
- vue
'@opentelemetry/api@1.9.0': {}
'@oxc-minify/binding-android-arm-eabi@0.128.0':
optional: true
@ -9080,8 +8733,6 @@ snapshots:
'@types/dagre@0.7.54': {}
'@types/dom-speech-recognition@0.0.1': {}
'@types/esrecurse@4.3.1': {}
'@types/estree@1.0.8': {}
@ -9090,10 +8741,6 @@ snapshots:
'@types/geojson@7946.0.16': {}
'@types/google.maps@3.64.0': {}
'@types/hogan.js@3.0.5': {}
'@types/json-schema@7.0.15': {}
'@types/leaflet@1.7.6':
@ -9112,8 +8759,6 @@ snapshots:
'@types/pbf@3.0.5': {}
'@types/qs@6.15.1': {}
'@types/resolve@1.20.2': {}
'@types/supercluster@5.0.3':
@ -9445,8 +9090,6 @@ snapshots:
- rollup
- supports-color
'@vercel/oidc@3.1.0': {}
'@vitejs/plugin-vue-jsx@5.1.5(vite@7.3.3(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.47.1)(yaml@2.9.0))(vue@3.5.34(typescript@6.0.3))':
dependencies:
'@babel/core': 7.29.0
@ -9683,8 +9326,6 @@ snapshots:
dependencies:
vue: 3.5.34(typescript@6.0.3)
abbrev@1.1.1: {}
abbrev@3.0.1: {}
abort-controller@3.0.0:
@ -9703,14 +9344,6 @@ snapshots:
agent-base@7.1.4: {}
ai@5.0.186(zod@4.4.3):
dependencies:
'@ai-sdk/gateway': 2.0.88(zod@4.4.3)
'@ai-sdk/provider': 2.0.3
'@ai-sdk/provider-utils': 3.0.25(zod@4.4.3)
'@opentelemetry/api': 1.9.0
zod: 4.4.3
ajv@6.15.0:
dependencies:
fast-deep-equal: 3.1.3
@ -9718,28 +9351,6 @@ snapshots:
json-schema-traverse: 0.4.1
uri-js: 4.4.1
algoliasearch-helper@3.26.0(algoliasearch@5.52.1):
dependencies:
'@algolia/events': 4.0.1
algoliasearch: 5.52.1
algoliasearch@5.52.1:
dependencies:
'@algolia/abtesting': 1.18.1
'@algolia/client-abtesting': 5.52.1
'@algolia/client-analytics': 5.52.1
'@algolia/client-common': 5.52.1
'@algolia/client-insights': 5.52.1
'@algolia/client-personalization': 5.52.1
'@algolia/client-query-suggestions': 5.52.1
'@algolia/client-search': 5.52.1
'@algolia/ingestion': 1.52.1
'@algolia/monitoring': 1.52.1
'@algolia/recommend': 5.52.1
'@algolia/requester-browser-xhr': 5.52.1
'@algolia/requester-fetch': 5.52.1
'@algolia/requester-node-http': 5.52.1
alien-signals@3.1.2: {}
ansi-regex@5.0.1: {}
@ -10833,8 +10444,6 @@ snapshots:
events@3.3.0: {}
eventsource-parser@3.0.8: {}
execa@8.0.1:
dependencies:
cross-spawn: 7.0.6
@ -10985,13 +10594,11 @@ snapshots:
fraction.js@5.3.4: {}
framer-motion@12.38.0(react@19.2.6):
framer-motion@12.38.0:
dependencies:
motion-dom: 12.38.0
motion-utils: 12.36.0
tslib: 2.8.1
optionalDependencies:
react: 19.2.6
fresh@2.0.0: {}
@ -11124,17 +10731,10 @@ snapshots:
hey-listen@1.0.8: {}
hogan.js@3.0.2:
dependencies:
mkdirp: 0.3.0
nopt: 1.0.10
hookable@5.5.3: {}
hookable@6.1.1: {}
htm@3.1.1: {}
html-entities@2.6.0: {}
http-errors@2.0.1:
@ -11195,38 +10795,6 @@ snapshots:
ini@4.1.1: {}
instantsearch-ui-components@0.12.0(react@19.2.6):
dependencies:
'@babel/runtime': 7.29.2
ai: 5.0.186(zod@4.4.3)
markdown-to-jsx: 7.7.17(react@19.2.6)
zod: 4.4.3
zod-to-json-schema: 3.24.6(zod@4.4.3)
transitivePeerDependencies:
- react
instantsearch.css@8.6.0: {}
instantsearch.js@4.81.0(algoliasearch@5.52.1):
dependencies:
'@algolia/events': 4.0.1
'@types/dom-speech-recognition': 0.0.1
'@types/google.maps': 3.64.0
'@types/hogan.js': 3.0.5
'@types/qs': 6.15.1
ai: 5.0.186(zod@4.4.3)
algoliasearch: 5.52.1
algoliasearch-helper: 3.26.0(algoliasearch@5.52.1)
hogan.js: 3.0.2
htm: 3.1.1
instantsearch-ui-components: 0.12.0(react@19.2.6)
preact: 10.29.1
qs: 6.9.9
react: 19.2.6
search-insights: 2.17.3
zod: 4.4.3
zod-to-json-schema: 3.24.6(zod@4.4.3)
internmap@1.0.1: {}
internmap@2.0.3: {}
@ -11337,8 +10905,6 @@ snapshots:
json-schema-traverse@0.4.1: {}
json-schema@0.4.0: {}
json-stable-stringify-without-jsonify@1.0.1: {}
json5@2.2.3: {}
@ -11555,10 +11121,6 @@ snapshots:
tinyqueue: 2.0.3
vt-pbf: 3.1.3
markdown-to-jsx@7.7.17(react@19.2.6):
optionalDependencies:
react: 19.2.6
marked@17.0.6: {}
math-intrinsics@1.1.0: {}
@ -11567,10 +11129,6 @@ snapshots:
mdn-data@2.27.1: {}
meilisearch@0.53.0: {}
meilisearch@0.54.0: {}
merge-stream@2.0.0: {}
merge2@1.4.1: {}
@ -11616,12 +11174,8 @@ snapshots:
dependencies:
minipass: 7.1.3
mitt@2.1.0: {}
mitt@3.0.1: {}
mkdirp@0.3.0: {}
mlly@1.8.2:
dependencies:
acorn: 8.16.0
@ -11637,10 +11191,10 @@ snapshots:
motion-utils@12.36.0: {}
motion-v@2.2.1(@vueuse/core@14.3.0(vue@3.5.34(typescript@6.0.3)))(react@19.2.6)(vue@3.5.34(typescript@6.0.3)):
motion-v@2.2.1(@vueuse/core@14.3.0(vue@3.5.34(typescript@6.0.3)))(vue@3.5.34(typescript@6.0.3)):
dependencies:
'@vueuse/core': 14.3.0(vue@3.5.34(typescript@6.0.3))
framer-motion: 12.38.0(react@19.2.6)
framer-motion: 12.38.0
hey-listen: 1.0.8
motion-dom: 12.38.0
motion-utils: 12.36.0
@ -11787,10 +11341,6 @@ snapshots:
node-releases@2.0.38: {}
nopt@1.0.10:
dependencies:
abbrev: 1.1.1
nopt@8.1.0:
dependencies:
abbrev: 3.0.1
@ -11810,21 +11360,6 @@ snapshots:
dependencies:
boolbase: 1.0.0
nuxt-meilisearch@1.4.17(@vue/server-renderer@3.5.34(vue@3.5.34(typescript@6.0.3)))(algoliasearch@5.52.1)(magicast@0.5.2)(react@19.2.6)(vue@3.5.34(typescript@6.0.3)):
dependencies:
'@meilisearch/instant-meilisearch': 0.28.0
'@nuxt/kit': 4.2.0(magicast@0.5.2)
instantsearch.css: 8.6.0
meilisearch: 0.54.0
vue-instantsearch: 4.22.0(@vue/server-renderer@3.5.34(vue@3.5.34(typescript@6.0.3)))(algoliasearch@5.52.1)(react@19.2.6)(vue@3.5.34(typescript@6.0.3))
transitivePeerDependencies:
- '@vue/server-renderer'
- algoliasearch
- magicast
- react
- vue
- vue-server-renderer
nuxt@4.4.5(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0))(@parcel/watcher@2.5.6)(@vue/compiler-sfc@3.5.34)(cac@6.7.14)(db0@0.3.4)(eslint@10.3.0(jiti@2.7.0))(ioredis@5.10.1)(lightningcss@1.32.0)(magicast@0.5.2)(optionator@0.9.4)(pinia@3.0.4(typescript@6.0.3)(vue@3.5.34(typescript@6.0.3)))(rollup-plugin-visualizer@7.0.1(rollup@4.60.3))(rollup@4.60.3)(srvx@0.11.15)(terser@5.47.1)(typescript@6.0.3)(vite@7.3.3(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.47.1)(yaml@2.9.0))(vue-tsc@3.2.8(typescript@6.0.3))(yaml@2.9.0):
dependencies:
'@dxup/nuxt': 0.4.1(magicast@0.5.2)(typescript@6.0.3)
@ -12375,8 +11910,6 @@ snapshots:
powershell-utils@0.1.0: {}
preact@10.29.1: {}
prelude-ls@1.2.1: {}
pretty-bytes@7.1.0: {}
@ -12466,8 +11999,6 @@ snapshots:
punycode@2.3.1: {}
qs@6.9.9: {}
quansync@0.2.11: {}
queue-microtask@1.2.3: {}
@ -12478,18 +12009,11 @@ snapshots:
range-parser@1.2.1: {}
rc9@2.1.2:
dependencies:
defu: 6.1.7
destr: 2.0.5
rc9@3.0.1:
dependencies:
defu: 6.1.7
destr: 2.0.5
react@19.2.6: {}
readable-stream@2.3.8:
dependencies:
core-util-is: 1.0.3
@ -12648,8 +12172,6 @@ snapshots:
scule@1.3.0: {}
search-insights@2.17.3: {}
semver@6.3.1: {}
semver@7.8.0: {}
@ -13331,18 +12853,6 @@ snapshots:
'@vue/devtools-api': 6.6.4
vue: 3.5.34(typescript@6.0.3)
vue-instantsearch@4.22.0(@vue/server-renderer@3.5.34(vue@3.5.34(typescript@6.0.3)))(algoliasearch@5.52.1)(react@19.2.6)(vue@3.5.34(typescript@6.0.3)):
dependencies:
algoliasearch: 5.52.1
instantsearch-ui-components: 0.12.0(react@19.2.6)
instantsearch.js: 4.81.0(algoliasearch@5.52.1)
mitt: 2.1.0
vue: 3.5.34(typescript@6.0.3)
optionalDependencies:
'@vue/server-renderer': 3.5.34(vue@3.5.34(typescript@6.0.3))
transitivePeerDependencies:
- react
vue-router@4.6.4(vue@3.5.34(typescript@6.0.3)):
dependencies:
'@vue/devtools-api': 6.6.4
@ -13504,8 +13014,4 @@ snapshots:
compress-commons: 6.0.2
readable-stream: 4.7.0
zod-to-json-schema@3.24.6(zod@4.4.3):
dependencies:
zod: 4.4.3
zod@4.4.3: {}

6
pnpm-workspace.yaml Normal file
View File

@ -0,0 +1,6 @@
allowBuilds:
'@parcel/watcher': true
esbuild: true
maplibre-gl: true
unrs-resolver: true
vue-demi: true

View File

@ -0,0 +1,33 @@
import { defineEventHandler, readBody, createError } from 'h3'
export default defineEventHandler(async (event) => {
const { message, recaptchaToken } = await readBody(event)
if (!message?.trim()) {
throw createError({ statusCode: 400, message: 'Mensaje vacío' })
}
const config = useRuntimeConfig(event)
const webhookUrl = config.public.feedbackWebhook
const feedbackToken = config.feedbackToken
if (!webhookUrl) {
throw createError({ statusCode: 500, message: 'Webhook no configurado' })
}
const headers: Record<string, string> = {}
if (feedbackToken) {
headers['X-Feedback-Token'] = feedbackToken
}
try {
const res = await $fetch(webhookUrl, {
method: 'POST',
headers,
body: { message, recaptchaToken }
})
return { ok: true, data: res }
} catch (e) {
throw createError({ statusCode: 502, message: 'Error al reenviar el feedback' })
}
})