mirror of
https://github.com/ArthurDanjou/artchat.git
synced 2026-01-14 11:54:03 +01:00
refactor: update ESLint configuration and remove unused dependencies
- Replaced Nuxt ESLint configuration with Antfu's ESLint config. - Removed 'nuxt-visitors' module from Nuxt configuration. - Added linting scripts to package.json for easier code quality checks. - Introduced a new API endpoint for fetching weather data from OpenWeather. - Enhanced chat types with new enums and properties for better state management. - Added OpenWeather response types for improved type safety. - Updated social links in types/index.ts to include an email contact.
This commit is contained in:
15
.env.example
15
.env.example
@@ -1,15 +0,0 @@
|
||||
NUXT_DISCORD_ID=
|
||||
NUXT_DISCORD_TOKEN=
|
||||
NUXT_DISCORD_USER_ID=
|
||||
|
||||
NUXT_HUB_ENV=
|
||||
NUXT_HUB_PROJECT_KEY=
|
||||
|
||||
NUXT_PUBLIC_I18N_BASE_URL=
|
||||
NUXT_PUBLIC_SITE_URL=
|
||||
|
||||
NUXT_WAKATIME_CODING=
|
||||
NUXT_WAKATIME_EDITORS=
|
||||
NUXT_WAKATIME_LANGUAGES=
|
||||
NUXT_WAKATIME_OS=
|
||||
NUXT_WAKATIME_USER_ID=
|
||||
@@ -8,7 +8,6 @@ useHead({
|
||||
<UApp>
|
||||
<NuxtLoadingIndicator color="#808080" />
|
||||
<AppBackground />
|
||||
<AppVisitors />
|
||||
<UContainer class="z-50 relative">
|
||||
<NuxtPage class="mt-12" />
|
||||
</UContainer>
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1
|
||||
class="text-3xl font-bold tracking-tight text-zinc-800 dark:text-zinc-100"
|
||||
>
|
||||
{{ title }}
|
||||
</h1>
|
||||
<p class="mt-4 text-base">
|
||||
{{ description }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,20 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
const { visitors } = useVisitors()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ClientOnly>
|
||||
<UBadge
|
||||
color="green"
|
||||
variant="outline"
|
||||
class="fixed z-50 bottom-4 right-4 rounded-full px-1.5 py-0.5 bg-white ring ring-green-400 dark:bg-neutral-950 dark:ring-green-600"
|
||||
>
|
||||
<div class="flex items-center gap-1">
|
||||
<p class="text-neutral-500">
|
||||
{{ visitors }}
|
||||
</p>
|
||||
<div class="w-3 h-3 bg-green-200/70 dark:bg-green-800/70 rounded-full border-2 border-green-400 dark:border-green-600" />
|
||||
</div>
|
||||
</UBadge>
|
||||
</ClientOnly>
|
||||
</template>
|
||||
@@ -1,108 +1,60 @@
|
||||
<script lang="ts" setup>
|
||||
import type { CommandPaletteItem } from '@nuxt/ui'
|
||||
import { ChatState } from '~~/types'
|
||||
|
||||
const searchTerm = ref('')
|
||||
const open = ref(false)
|
||||
const openMessageModal = ref(false)
|
||||
const openClearModal = ref(false)
|
||||
|
||||
const { t } = useI18n({ useScope: 'local' })
|
||||
|
||||
const messages = computed(() => {
|
||||
return [
|
||||
{
|
||||
label: t('chat.theme.label'),
|
||||
kbds: ['T'],
|
||||
icon: 'i-ph-lightbulb-filament-duotone',
|
||||
prompt: t('chat.theme.prompt'),
|
||||
},
|
||||
{
|
||||
label: t('chat.language.label'),
|
||||
kbds: ['L'],
|
||||
icon: 'i-ph-translate-duotone',
|
||||
prompt: t('chat.language.prompt'),
|
||||
},
|
||||
{
|
||||
label: t('chat.activity.label'),
|
||||
icon: 'i-ph-activity',
|
||||
prompt: t('chat.activity.prompt'),
|
||||
},
|
||||
{
|
||||
label: t('chat.about.label'),
|
||||
icon: 'i-ph-person-arms-spread-duotone',
|
||||
prompt: t('chat.about.prompt'),
|
||||
},
|
||||
{
|
||||
label: t('chat.projects.label'),
|
||||
icon: 'i-ph-code-duotone',
|
||||
prompt: t('chat.projects.prompt'),
|
||||
},
|
||||
{
|
||||
label: t('chat.writings.label'),
|
||||
icon: 'i-ph-books-duotone',
|
||||
prompt: t('chat.writings.prompt'),
|
||||
},
|
||||
{
|
||||
label: t('chat.experiences.label'),
|
||||
icon: 'i-ph-briefcase-duotone',
|
||||
prompt: t('chat.experiences.prompt'),
|
||||
},
|
||||
{
|
||||
label: t('chat.skills.label'),
|
||||
icon: 'i-ph-rocket-duotone',
|
||||
prompt: t('chat.skills.prompt'),
|
||||
},
|
||||
{
|
||||
label: t('chat.stack.label'),
|
||||
icon: 'i-ph-stack-duotone',
|
||||
prompt: t('chat.stack.prompt'),
|
||||
},
|
||||
{
|
||||
label: t('chat.status.label'),
|
||||
icon: 'i-ph-warning-duotone',
|
||||
prompt: t('chat.status.prompt'),
|
||||
},
|
||||
{
|
||||
label: t('chat.resume.label'),
|
||||
icon: 'i-ph-address-book-duotone',
|
||||
prompt: t('chat.resume.prompt'),
|
||||
},
|
||||
{
|
||||
label: t('chat.contact.label'),
|
||||
icon: 'i-ph-envelope-duotone',
|
||||
prompt: t('chat.contact.prompt'),
|
||||
},
|
||||
{
|
||||
label: t('chat.hobbies.label'),
|
||||
icon: 'i-ph-heart-duotone',
|
||||
prompt: t('chat.hobbies.prompt'),
|
||||
},
|
||||
{
|
||||
label: t('chat.credits.label'),
|
||||
icon: 'i-ph-star-duotone',
|
||||
prompt: t('chat.credits.prompt'),
|
||||
},
|
||||
]
|
||||
})
|
||||
const { messages, submitMessage } = useChat(t)
|
||||
|
||||
function onSelect(event: any) {
|
||||
const { clearMessages, messages: storeMessages } = useChatStore()
|
||||
const loading = computed(() => storeMessages.some(msg => msg.state === ChatState.LOADING))
|
||||
function handleDelete() {
|
||||
clearMessages()
|
||||
openClearModal.value = false
|
||||
}
|
||||
|
||||
function onSelect(item: CommandPaletteItem) {
|
||||
searchTerm.value = ''
|
||||
open.value = false
|
||||
// send Message
|
||||
openMessageModal.value = false
|
||||
submitMessage(item.type, item.prompt, item.fetchStates ?? [])
|
||||
}
|
||||
defineShortcuts({
|
||||
meta_enter: () => {
|
||||
open.value = !open.value
|
||||
openMessageModal.value = !openMessageModal.value
|
||||
},
|
||||
meta_d: () => {
|
||||
openClearModal.value = !openClearModal.value
|
||||
},
|
||||
})
|
||||
|
||||
const modalUi = {
|
||||
content: 'bg-default-30 dark:bg-default/70 backdrop-blur-xl border border-accented/70 max-w-2xl h-100 flex flex-col shadow-raycast',
|
||||
}
|
||||
|
||||
const commandPaletteUi = {
|
||||
root: 'flex flex-col h-full',
|
||||
label: 'text-muted font-medium',
|
||||
item: 'data-highlighted:not-data-disabled:before:bg-muted',
|
||||
content: 'flex-1 overflow-y-auto',
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav class="fixed bottom-0 left-1/2 z-50 -translate-x-1/2 pb-4">
|
||||
<nav class="fixed bottom-0 left-1/2 z-50 -translate-x-1/2 pb-8">
|
||||
<UFieldGroup>
|
||||
<UModal v-model:open="open">
|
||||
<UModal v-model:open="openMessageModal" :ui="modalUi">
|
||||
<UButton
|
||||
:label="t('buttons.new')"
|
||||
:label="loading ? t('cmd.sending') : t('cmd.send')"
|
||||
variant="solid"
|
||||
color="neutral"
|
||||
size="xl"
|
||||
icon="i-ph-paper-plane-tilt-duotone"
|
||||
class="rounded-full"
|
||||
:disabled="loading"
|
||||
>
|
||||
<template #trailing>
|
||||
<UKbd value="meta" />
|
||||
@@ -112,13 +64,26 @@ defineShortcuts({
|
||||
|
||||
<template #content>
|
||||
<UCommandPalette
|
||||
v-model:search-term="searchTerm"
|
||||
close
|
||||
:placeholder="t('buttons.new')"
|
||||
:groups="[{ id: 'messages', items: messages }]"
|
||||
:ui="commandPaletteUi"
|
||||
:groups="messages"
|
||||
@update:model-value="onSelect"
|
||||
@update:open="open = $event"
|
||||
@update:open="openMessageModal = $event"
|
||||
>
|
||||
<template #item="{ item }">
|
||||
<div class="relative flex items-center justify-between w-full p-1">
|
||||
<div class="absolute inset-0 -m-1" />
|
||||
<div class="flex items-center gap-2.5">
|
||||
<div class="flex items-center gap-2.5">
|
||||
<UIcon :name="item.icon!" size="20" />
|
||||
<span>{{ item.label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="text-muted text-xs font-medium">
|
||||
{{ item.prompt }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<UIcon name="i-simple-icons-nuxtdotjs" class="size-5 text-dimmed ml-1" />
|
||||
@@ -134,13 +99,33 @@ defineShortcuts({
|
||||
</UCommandPalette>
|
||||
</template>
|
||||
</UModal>
|
||||
<UButton
|
||||
:label="t('buttons.clear')"
|
||||
variant="solid"
|
||||
color="error"
|
||||
leading-icon="i-ph-trash-duotone"
|
||||
size="xl"
|
||||
/>
|
||||
<UModal
|
||||
v-model:open="openClearModal"
|
||||
:title="t('clear.title')"
|
||||
:description="t('clear.description')"
|
||||
>
|
||||
<UButton
|
||||
:label="t('clear.button')"
|
||||
variant="solid"
|
||||
color="error"
|
||||
leading-icon="i-ph-trash-duotone"
|
||||
size="xl"
|
||||
class="rounded-full"
|
||||
:disabled="storeMessages.length === 0"
|
||||
>
|
||||
<template #trailing>
|
||||
<UKbd value="meta" />
|
||||
<UKbd value="D" />
|
||||
</template>
|
||||
</UButton>
|
||||
|
||||
<template #footer="{ close }">
|
||||
<UFieldGroup>
|
||||
<UButton :label="t('clear.cancel')" color="neutral" variant="outline" @click="close" />
|
||||
<UButton :label="t('clear.submit')" color="error" @click.prevent="handleDelete()" />
|
||||
</UFieldGroup>
|
||||
</template>
|
||||
</UModal>
|
||||
</UFieldGroup>
|
||||
</nav>
|
||||
</template>
|
||||
@@ -148,60 +133,261 @@ defineShortcuts({
|
||||
<i18n lang="json">
|
||||
{
|
||||
"en": {
|
||||
"buttons": {
|
||||
"new": "Send new message",
|
||||
"clear": "Clear conversation"
|
||||
"clear": {
|
||||
"button": "Clear",
|
||||
"cancel": "Cancel",
|
||||
"submit": "Delete",
|
||||
"title": "Are you sure you want to delete this conversation?",
|
||||
"description": "This action cannot be undone."
|
||||
},
|
||||
"cmd": {
|
||||
"send": "Send message"
|
||||
"send": "Send message",
|
||||
"sending": "Sending..."
|
||||
},
|
||||
"chat": {
|
||||
"theme": {
|
||||
"label": "Switch Theme",
|
||||
"prompt": ""
|
||||
},
|
||||
"language": {
|
||||
"label": "Change Language",
|
||||
"prompt": ""
|
||||
}
|
||||
"action": "Components",
|
||||
"arthur": "More about Arthur",
|
||||
"interface": "Change the interface",
|
||||
"theme": {
|
||||
"label": "Change theme",
|
||||
"prompt": "How can I change the theme?"
|
||||
},
|
||||
"stats": {
|
||||
"label": "View statistics",
|
||||
"prompt": "How can I view the statistics concerning Arthur?"
|
||||
},
|
||||
"weather": {
|
||||
"label": "View weather",
|
||||
"prompt": "How can I view the weather conditions near Arthur?"
|
||||
},
|
||||
"location": {
|
||||
"label": "View location",
|
||||
"prompt": "How can I view the location of Arthur?"
|
||||
},
|
||||
"language": {
|
||||
"label": "Change language",
|
||||
"prompt": "How can I change the chat language?"
|
||||
},
|
||||
"activity": {
|
||||
"label": "Activity",
|
||||
"prompt": "What are you currently doing?"
|
||||
},
|
||||
"about": {
|
||||
"label": "About Arthur",
|
||||
"prompt": "I want you to tell me about yourself."
|
||||
},
|
||||
"projects": {
|
||||
"label": "Projects",
|
||||
"prompt": "Tell me about your projects."
|
||||
},
|
||||
"writings": {
|
||||
"label": "Writings",
|
||||
"prompt": "What are your latest articles?"
|
||||
},
|
||||
"experiences": {
|
||||
"label": "Experiences",
|
||||
"prompt": "What experiences do you have in your career?"
|
||||
},
|
||||
"skills": {
|
||||
"label": "Skills",
|
||||
"prompt": "What are your skills?"
|
||||
},
|
||||
"stack": {
|
||||
"label": "Tech Stack",
|
||||
"prompt": "What tech stack are you currently using?"
|
||||
},
|
||||
"status": {
|
||||
"label": "Homelab status",
|
||||
"prompt": "I saw you have a homelab, is it currently working?"
|
||||
},
|
||||
"resume": {
|
||||
"label": "Resume",
|
||||
"prompt": "Can you send me your resume?"
|
||||
},
|
||||
"contact": {
|
||||
"label": "Contact",
|
||||
"prompt": "How can I contact you?"
|
||||
},
|
||||
"hobbies": {
|
||||
"label": "Hobbies and passions",
|
||||
"prompt": "What are your hobbies? Your passions? Your interests?"
|
||||
},
|
||||
"credits": {
|
||||
"label": "Credits",
|
||||
"prompt": "How is this chat made?"
|
||||
}
|
||||
}
|
||||
},
|
||||
"fr": {
|
||||
"buttons": {
|
||||
"new": "Envoyer un nouveau message",
|
||||
"clear": "Effacer la conversation"
|
||||
"clear": {
|
||||
"button": "Effacer",
|
||||
"cancel": "Annuler",
|
||||
"submit": "Supprimer",
|
||||
"title": "Êtes-vous sûr de vouloir supprimer cette conversation ?",
|
||||
"description": "Cette action ne peut pas être annulée."
|
||||
},
|
||||
"cmd": {
|
||||
"send": "Envoyer le message"
|
||||
"send": "Envoyer le message",
|
||||
"sending": "Envoi..."
|
||||
},
|
||||
"chat": {
|
||||
"action": "Composants",
|
||||
"arthur": "En savoir plus sur Arthur",
|
||||
"interface": "Changer l'interface",
|
||||
"theme": {
|
||||
"label": "Changer de thème",
|
||||
"prompt": ""
|
||||
"prompt": "Comment puis-je changer le thème ?"
|
||||
},
|
||||
"stats": {
|
||||
"label": "Voir les statistiques",
|
||||
"prompt": "Comment puis-je voir les statistiques concernant Arthur ?"
|
||||
},
|
||||
"weather": {
|
||||
"label": "Voir la météo",
|
||||
"prompt": "Comment puis-je voir les conditions météorologiques près d'Arthur ?"
|
||||
},
|
||||
"location": {
|
||||
"label": "Voir la localisation",
|
||||
"prompt": "Comment puis-je voir la localisation d'Arthur ?"
|
||||
},
|
||||
"language": {
|
||||
"label": "Changer de langue",
|
||||
"prompt": ""
|
||||
"prompt": "Comment puis-je changer la langue du chat ?"
|
||||
},
|
||||
"activity": {
|
||||
"label": "Activité",
|
||||
"prompt": "Que fais-tu actuellement ?"
|
||||
},
|
||||
"about": {
|
||||
"label": "A propos d'Arthur",
|
||||
"prompt": "Je veux que tu me parles de toi."
|
||||
},
|
||||
"projects": {
|
||||
"label": "Projets",
|
||||
"prompt": "Je veux que tu me parles de tes projets."
|
||||
},
|
||||
"writings": {
|
||||
"label": "Écrits",
|
||||
"prompt": "Quels sont tes derniers articles ?"
|
||||
},
|
||||
"experiences": {
|
||||
"label": "Expériences",
|
||||
"prompt": "Quelles expériences as-tu lors de ta carrière ?"
|
||||
},
|
||||
"skills": {
|
||||
"label": "Compétences",
|
||||
"prompt": "Quelles sont tes compétences ?"
|
||||
},
|
||||
"stack": {
|
||||
"label": "Tech Stack",
|
||||
"prompt": "Quelle est stack technique utilises-tu en ce moment ?"
|
||||
},
|
||||
"status": {
|
||||
"label": "Statut du homelab",
|
||||
"prompt": "J'ai vu que tu avais un homelab, est-il actuellement fonctionnel ?"
|
||||
},
|
||||
"resume": {
|
||||
"label": "CV",
|
||||
"prompt": "Peux-tu m'envoyer ton CV ?"
|
||||
},
|
||||
"contact": {
|
||||
"label": "Contact",
|
||||
"prompt": "Comment puis-je te contacter ?"
|
||||
},
|
||||
"hobbies": {
|
||||
"label": "Loisirs et passions",
|
||||
"prompt": "Quels sont tes loisirs ? Tes passions ? Tes intérêts ?"
|
||||
},
|
||||
"credits": {
|
||||
"label": "Crédits",
|
||||
"prompt": "Comment est réalisé ce chat ?"
|
||||
}
|
||||
}
|
||||
},
|
||||
"es": {
|
||||
"buttons": {
|
||||
"new": "Enviar un nuevo mensaje",
|
||||
"clear": "Borrar conversación"
|
||||
"clear": {
|
||||
"button": "Borrar",
|
||||
"cancel": "Cancelar",
|
||||
"submit": "Eliminar",
|
||||
"title": "¿Estás seguro de que deseas eliminar esta conversación?",
|
||||
"description": "Esta acción no se puede deshacer."
|
||||
},
|
||||
"cmd": {
|
||||
"send": "Enviar el mensaje"
|
||||
"send": "Enviar el mensaje",
|
||||
"sending": "Enviando..."
|
||||
},
|
||||
"chat": {
|
||||
"theme": {
|
||||
"label": "Cambiar tema",
|
||||
"prompt": ""
|
||||
},
|
||||
"language": {
|
||||
"label": "Cambiar idioma",
|
||||
"prompt": ""
|
||||
}
|
||||
"action": "Componentes",
|
||||
"arthur": "Más sobre Arthur",
|
||||
"interface": "Cambiar la interfaz",
|
||||
"theme": {
|
||||
"label": "Cambiar tema",
|
||||
"prompt": "¿Cómo puedo cambiar el tema?"
|
||||
},
|
||||
"stats": {
|
||||
"label": "Ver estadísticas",
|
||||
"prompt": "¿Cómo puedo ver las estadísticas sobre Arthur?"
|
||||
},
|
||||
"weather": {
|
||||
"label": "Ver el clima",
|
||||
"prompt": "¿Cómo puedo ver las condiciones climáticas cerca de Arthur?"
|
||||
},
|
||||
"location": {
|
||||
"label": "Ver ubicación",
|
||||
"prompt": "¿Cómo puedo ver la ubicación de Arthur?"
|
||||
},
|
||||
"language": {
|
||||
"label": "Cambiar idioma",
|
||||
"prompt": "¿Cómo puedo cambiar el idioma del chat?"
|
||||
},
|
||||
"activity": {
|
||||
"label": "Actividad",
|
||||
"prompt": "¿Qué estás haciendo actualmente?"
|
||||
},
|
||||
"about": {
|
||||
"label": "Sobre Arthur",
|
||||
"prompt": "Quiero que me hables de ti."
|
||||
},
|
||||
"projects": {
|
||||
"label": "Proyectos",
|
||||
"prompt": "Háblame de tus proyectos."
|
||||
},
|
||||
"writings": {
|
||||
"label": "Escritos",
|
||||
"prompt": "¿Cuáles son tus últimos artículos?"
|
||||
},
|
||||
"experiences": {
|
||||
"label": "Experiencias",
|
||||
"prompt": "¿Qué experiencias tienes en tu carrera?"
|
||||
},
|
||||
"skills": {
|
||||
"label": "Habilidades",
|
||||
"prompt": "¿Cuáles son tus habilidades?"
|
||||
},
|
||||
"stack": {
|
||||
"label": "Stack tecnológico",
|
||||
"prompt": "¿Qué stack tecnológico estás usando actualmente?"
|
||||
},
|
||||
"status": {
|
||||
"label": "Estado del homelab",
|
||||
"prompt": "Vi que tienes un homelab, ¿está funcionando actualmente?"
|
||||
},
|
||||
"resume": {
|
||||
"label": "CV",
|
||||
"prompt": "¿Puedes enviarme tu CV?"
|
||||
},
|
||||
"contact": {
|
||||
"label": "Contacto",
|
||||
"prompt": "¿Cómo puedo contactarte?"
|
||||
},
|
||||
"hobbies": {
|
||||
"label": "Pasatiempos y pasiones",
|
||||
"prompt": "¿Cuáles son tus pasatiempos? ¿Tus pasiones? ¿Tus intereses?"
|
||||
},
|
||||
"credits": {
|
||||
"label": "Créditos",
|
||||
"prompt": "¿Cómo se ha hecho este chat?"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,60 @@
|
||||
<script lang="ts" setup>
|
||||
import type { ChatFetchState } from '~~/types'
|
||||
import { ChatState } from '~~/types'
|
||||
|
||||
const props = defineProps<{ messageId: number, fetchStates: ChatFetchState[] }>()
|
||||
|
||||
const currentState = ref<ChatFetchState | undefined>(props.fetchStates[0] ?? undefined)
|
||||
|
||||
const { setLoadingState } = useChatStore()
|
||||
|
||||
onMounted(() => {
|
||||
let index = 0
|
||||
function nextState() {
|
||||
index++
|
||||
if (index < props.fetchStates.length) {
|
||||
const delay = Math.random() * 3000 + 500
|
||||
setTimeout(() => {
|
||||
currentState.value = props.fetchStates[index]
|
||||
nextState()
|
||||
}, delay)
|
||||
}
|
||||
else {
|
||||
setLoadingState(props.messageId, ChatState.SENT)
|
||||
}
|
||||
}
|
||||
if (props.fetchStates.length > 1) {
|
||||
nextState()
|
||||
}
|
||||
else {
|
||||
// If only one state, call setLoadingState immediately
|
||||
setLoadingState(props.messageId, ChatState.SENT)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<UIcon name="i-ph-spinner-duotone" class="animate-spin" />
|
||||
<span
|
||||
class="relative inline-block overflow-hidden animate-shine italic bg-[linear-gradient(110deg,#bfbfbf,35%,#000,50%,#bfbfbf,75%,#bfbfbf)] dark:bg-[linear-gradient(110deg,#404040,35%,#fff,50%,#404040,75%,#404040)] bg-[length:200%_100%] bg-clip-text text-transparent"
|
||||
>
|
||||
<slot>{{ currentState }}</slot>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
<style scoped>
|
||||
.animate-shine {
|
||||
animation: shine 2s linear infinite;
|
||||
}
|
||||
|
||||
</style>
|
||||
@keyframes shine {
|
||||
0% {
|
||||
background-position: -200% center;
|
||||
}
|
||||
100% {
|
||||
background-position: 200% center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<script lang="ts" setup>
|
||||
const props = withDefaults(defineProps<{
|
||||
user?: 'user' | 'arthur'
|
||||
}>(), {
|
||||
user: 'user',
|
||||
})
|
||||
import type { ChatMessage } from '~~/types'
|
||||
import { ChatSender, ChatState, ChatType } from '~~/types'
|
||||
|
||||
const isArthur = computed(() => props.user === 'arthur')
|
||||
const props = defineProps<{
|
||||
message: ChatMessage
|
||||
}>()
|
||||
|
||||
const isArthur = computed(() => props.message.sender === ChatSender.ARTHUR)
|
||||
|
||||
const { locale, locales } = useI18n({
|
||||
useScope: 'local',
|
||||
@@ -15,22 +16,69 @@ const formatted = computed(() => useDateFormat(useNow(), 'D MMMM YYYY, HH:mm', {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="group flex flex-col gap-4">
|
||||
<div v-if="!isArthur" class="group flex flex-col gap-4">
|
||||
<div class="flex flex-col-reverse gap-4 md:flex-row-reverse items-end">
|
||||
<UCard
|
||||
variant="solid"
|
||||
class="rounded-xl mt-1 bg-sky-300 md:max-w-3/4"
|
||||
:ui="{ body: 'sm:p-2', header: 'sm:p-2', footer: 'sm:p-2' }"
|
||||
>
|
||||
<div class="text-justify">
|
||||
{{ message.content }}
|
||||
</div>
|
||||
</UCard>
|
||||
</div>
|
||||
<div class="opacity-0 group-hover:opacity-80 duration-500 flex text-sm italic justify-end">
|
||||
{{ formatted }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="flex flex-col-reverse gap-4 items-start md:flex-row-reverse">
|
||||
<UCard
|
||||
:variant="isArthur ? 'soft' : 'solid'"
|
||||
class="rounded-xl p-2 mt-1"
|
||||
:class="isArthur ? 'w-full bg-transparent !p-0' : 'bg-sky-300 md:max-w-3/4'"
|
||||
:ui="{ body: isArthur ? 'p-0 sm:p-0' : 'sm:p-2', header: isArthur ? 'p-0 sm:p-0' : 'sm:p-2', footer: isArthur ? 'p-0 sm:p-0' : 'sm:p-2' }"
|
||||
v-if="message.state === ChatState.LOADING && message.fetchStates && message.fetchStates.length > 0"
|
||||
variant="soft"
|
||||
class="mt-1 w-full bg-transparent"
|
||||
:ui="{ body: 'p-0 sm:p-0', header: 'p-0 sm:p-0', footer: 'p-0 sm:p-0' }"
|
||||
>
|
||||
<slot />
|
||||
<ChatLoading :fetch-states="message.fetchStates" :message-id="message.id" />
|
||||
</UCard>
|
||||
<div v-if="isArthur" class="flex items-center gap-2">
|
||||
<UCard
|
||||
v-else
|
||||
variant="soft"
|
||||
class="mt-1 w-full bg-transparent"
|
||||
:ui="{ body: 'p-0 sm:p-0', header: 'p-0 sm:p-0', footer: 'p-0 sm:p-0' }"
|
||||
>
|
||||
<div v-if="message.type === ChatType.INIT">
|
||||
{{ message.content }}
|
||||
</div>
|
||||
<div v-else-if="message.type === ChatType.THEME">
|
||||
<ToolTheme />
|
||||
</div>
|
||||
<div v-else-if="message.type === ChatType.LANGUAGE">
|
||||
<ToolLanguage />
|
||||
</div>
|
||||
<div v-else-if="message.type === ChatType.STATS">
|
||||
<ToolStats />
|
||||
</div>
|
||||
<div v-else-if="message.type === ChatType.ACTIVITY">
|
||||
<ToolActivity />
|
||||
</div>
|
||||
<div v-else-if="message.type === ChatType.CONTACT">
|
||||
<ToolContact />
|
||||
</div>
|
||||
<div v-else-if="message.type === ChatType.WEATHER">
|
||||
<ToolWeather />
|
||||
</div>
|
||||
<div v-else>
|
||||
{{ message }}
|
||||
</div>
|
||||
</UCard>
|
||||
<div class="flex items-center gap-2">
|
||||
<UAvatar src="/arthur.webp" size="lg" />
|
||||
<span class="md:hidden">Arthur DANJOU</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="opacity-0 group-hover:opacity-100 duration-500 flex" :class="isArthur ? 'justify-start ml-12' : 'justify-end'">
|
||||
<div class="opacity-0 group-hover:opacity-80 duration-500 flex text-sm italic justify-start ml-12">
|
||||
{{ formatted }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
34
app/components/chat/Typing.vue
Normal file
34
app/components/chat/Typing.vue
Normal file
@@ -0,0 +1,34 @@
|
||||
<script setup lang="ts">
|
||||
const children = ref<HTMLElement[]>([])
|
||||
const shown = ref<HTMLElement[]>([])
|
||||
|
||||
const container = ref<HTMLElement | null>(null)
|
||||
|
||||
onMounted(async () => {
|
||||
if (!container.value)
|
||||
return
|
||||
|
||||
children.value = Array.from(container.value.children) as HTMLElement[]
|
||||
|
||||
for (const child of children.value) {
|
||||
shown.value.push(child)
|
||||
await new Promise(resolve => setTimeout(resolve, 400))
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div ref="container" class="hidden">
|
||||
<slot />
|
||||
</div>
|
||||
<div>
|
||||
<component
|
||||
:is="el.tagName.toLowerCase()"
|
||||
v-for="(el, index) in shown"
|
||||
:key="index"
|
||||
v-html="el.innerHTML"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
43
app/components/tool/Contact.vue
Normal file
43
app/components/tool/Contact.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<script lang="ts" setup>
|
||||
import { socials } from '~~/types'
|
||||
|
||||
const { t } = useI18n({ useScope: 'local' })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section>
|
||||
<div>
|
||||
<p class="prose dark:prose-invert">
|
||||
{{ t('contact') }}
|
||||
</p>
|
||||
<div class="flex gap-2 flex-wrap my-2">
|
||||
<UButton
|
||||
v-for="social in socials"
|
||||
:key="social.label"
|
||||
:icon="social.icon"
|
||||
:label="social.label"
|
||||
variant="subtle"
|
||||
color="neutral"
|
||||
target="_blank"
|
||||
class=""
|
||||
:href="social.to"
|
||||
:aria-label="social.label"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<i18n lang="json">
|
||||
{
|
||||
"en": {
|
||||
"contact": "There are different ways to contact me. Here is a list:"
|
||||
},
|
||||
"fr": {
|
||||
"contact": "Il existe différents façons de me contacter. Voici une liste :"
|
||||
},
|
||||
"es": {
|
||||
"contact": "Existen diferentes formas de contactarme. Aquí hay una lista:"
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
@@ -1,13 +1,98 @@
|
||||
<script lang="ts" setup>
|
||||
<script setup lang="ts">
|
||||
import type { Weather } from '~~/types'
|
||||
|
||||
const { t } = useI18n({ useScope: 'local' })
|
||||
|
||||
const { data: weather } = await useAsyncData<Weather>('weather', () =>
|
||||
$fetch('/api/weather'))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<!-- TODO: Implement weather component -->
|
||||
</div>
|
||||
<UCard v-if="weather" variant="outline" class="md:max-w-2/3">
|
||||
<template #header>
|
||||
<div class="flex gap-4 items-center">
|
||||
<UIcon name="i-ph-cloud-duotone" size="24" />
|
||||
<h3 class="text-lg font-semibold">
|
||||
{{ t('weather') }}
|
||||
</h3>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #default>
|
||||
<h3 class="text-2xl font-bold">
|
||||
{{ weather.location }}
|
||||
</h3>
|
||||
<div class="flex items-end gap-2">
|
||||
<span class="text-5xl font-bold">{{ weather.temperature }}°C</span>
|
||||
<span class="capitalize text-lg">{{ weather.description }}</span>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-3 gap-2 mt-4">
|
||||
<div class="bg-zinc-200 dark:bg-zinc-800 rounded-md p-2 text-center">
|
||||
<p class="text-sm text-zinc-800 dark:text-zinc-400">
|
||||
{{ t('high') }}
|
||||
</p>
|
||||
<p class="font-semibold">
|
||||
{{ weather.temp_max }}°C
|
||||
</p>
|
||||
</div>
|
||||
<div class="bg-zinc-200 dark:bg-zinc-800 rounded-md p-2 text-center">
|
||||
<p class="text-sm text-zinc-800 dark:text-zinc-400">
|
||||
{{ t('low') }}
|
||||
</p>
|
||||
<p class="font-semibold">
|
||||
{{ weather.temp_min }}°C
|
||||
</p>
|
||||
</div>
|
||||
<div class="bg-zinc-200 dark:bg-zinc-800 rounded-md p-2 text-center">
|
||||
<p class="text-sm text-zinc-800 dark:text-zinc-400">
|
||||
{{ t('humidity') }}
|
||||
</p>
|
||||
<p class="font-semibold">
|
||||
{{ weather.humidity }}%
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<div class="flex items-center justify-between">
|
||||
<p class="text-sm text-zinc-600 dark:text-zinc-400">
|
||||
{{ t('wind') }}: {{ weather.wind }} km/h
|
||||
</p>
|
||||
<p class="text-sm text-zinc-600 dark:text-zinc-400">
|
||||
{{ t('powered_by') }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</UCard>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
<i18n lang="json">
|
||||
{
|
||||
"en": {
|
||||
"weather": "Weather",
|
||||
"powered_by": "Powered by OpenWeatherMap",
|
||||
"low": "Low",
|
||||
"high": "High",
|
||||
"humidity": "Humidity",
|
||||
"wind": "Wind"
|
||||
},
|
||||
"fr": {
|
||||
"weather": "Météo",
|
||||
"powered_by": "Alimenté par OpenWeatherMap",
|
||||
"low": "Bas",
|
||||
"high": "Haut",
|
||||
"humidity": "Humidité",
|
||||
"wind": "Vent"
|
||||
},
|
||||
"es": {
|
||||
"weather": "Tiempo",
|
||||
"powered_by": "Impulsado por OpenWeatherMap",
|
||||
"low": "Bajo",
|
||||
"high": "Alto",
|
||||
"humidity": "Humedad",
|
||||
"wind": "Viento"
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
|
||||
161
app/composables/chat.ts
Normal file
161
app/composables/chat.ts
Normal file
@@ -0,0 +1,161 @@
|
||||
import { ChatFetchState, ChatSender, ChatType } from '~~/types/chat'
|
||||
|
||||
export function useChat(t: any) {
|
||||
const messages = computed(() => {
|
||||
return [
|
||||
{
|
||||
id: 'interface',
|
||||
label: t('chat.interface'),
|
||||
items: [
|
||||
{
|
||||
label: t('chat.theme.label'),
|
||||
icon: 'i-ph-lightbulb-filament-duotone',
|
||||
prompt: t('chat.theme.prompt'),
|
||||
type: ChatType.THEME,
|
||||
fetchStates: [ChatFetchState.THINKING, ChatFetchState.GENERATING],
|
||||
},
|
||||
{
|
||||
label: t('chat.language.label'),
|
||||
icon: 'i-ph-translate-duotone',
|
||||
prompt: t('chat.language.prompt'),
|
||||
type: ChatType.LANGUAGE,
|
||||
fetchStates: [ChatFetchState.THINKING, ChatFetchState.GENERATING],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'actions',
|
||||
label: t('chat.actions'),
|
||||
items: [
|
||||
{
|
||||
label: t('chat.location.label'),
|
||||
icon: 'i-ph-map-pin-area-duotone',
|
||||
prompt: t('chat.location.prompt'),
|
||||
type: ChatType.LOCATION,
|
||||
fetchStates: [ChatFetchState.FETCHING, ChatFetchState.GENERATING],
|
||||
},
|
||||
{
|
||||
label: t('chat.stats.label'),
|
||||
icon: 'i-ph-projector-screen-chart-duotone',
|
||||
prompt: t('chat.stats.prompt'),
|
||||
type: ChatType.STATS,
|
||||
fetchStates: [ChatFetchState.FETCHING, ChatFetchState.GENERATING],
|
||||
},
|
||||
{
|
||||
label: t('chat.weather.label'),
|
||||
icon: 'i-ph-cloud-rain-duotone',
|
||||
prompt: t('chat.weather.prompt'),
|
||||
type: ChatType.WEATHER,
|
||||
fetchStates: [ChatFetchState.FETCHING, ChatFetchState.GENERATING],
|
||||
},
|
||||
{
|
||||
label: t('chat.activity.label'),
|
||||
icon: 'i-ph-activity',
|
||||
prompt: t('chat.activity.prompt'),
|
||||
type: ChatType.ACTIVITY,
|
||||
fetchStates: [ChatFetchState.FETCHING, ChatFetchState.GENERATING],
|
||||
},
|
||||
{
|
||||
label: t('chat.status.label'),
|
||||
icon: 'i-ph-warning-duotone',
|
||||
prompt: t('chat.status.prompt'),
|
||||
type: ChatType.STATUS,
|
||||
fetchStates: [ChatFetchState.FETCHING, ChatFetchState.GENERATING],
|
||||
},
|
||||
].sort((a, b) => a.label.localeCompare(b.label)),
|
||||
},
|
||||
{
|
||||
id: 'arthur',
|
||||
label: t('chat.arthur'),
|
||||
items: [
|
||||
{
|
||||
label: t('chat.credits.label'),
|
||||
icon: 'i-ph-star-duotone',
|
||||
prompt: t('chat.credits.prompt'),
|
||||
type: ChatType.CREDITS,
|
||||
},
|
||||
{
|
||||
label: t('chat.about.label'),
|
||||
icon: 'i-ph-person-arms-spread-duotone',
|
||||
prompt: t('chat.about.prompt'),
|
||||
type: ChatType.ABOUT,
|
||||
},
|
||||
{
|
||||
label: t('chat.projects.label'),
|
||||
icon: 'i-ph-code-duotone',
|
||||
prompt: t('chat.projects.prompt'),
|
||||
type: ChatType.PROJECTS,
|
||||
fetchStates: [ChatFetchState.FETCHING, ChatFetchState.GENERATING],
|
||||
},
|
||||
{
|
||||
label: t('chat.writings.label'),
|
||||
icon: 'i-ph-books-duotone',
|
||||
prompt: t('chat.writings.prompt'),
|
||||
type: ChatType.WRITINGS,
|
||||
fetchStates: [ChatFetchState.FETCHING, ChatFetchState.GENERATING],
|
||||
},
|
||||
{
|
||||
label: t('chat.experiences.label'),
|
||||
icon: 'i-ph-briefcase-duotone',
|
||||
prompt: t('chat.experiences.prompt'),
|
||||
type: ChatType.EXPERIENCES,
|
||||
},
|
||||
{
|
||||
label: t('chat.skills.label'),
|
||||
icon: 'i-ph-rocket-duotone',
|
||||
prompt: t('chat.skills.prompt'),
|
||||
type: ChatType.SKILLS,
|
||||
},
|
||||
{
|
||||
label: t('chat.stack.label'),
|
||||
icon: 'i-ph-stack-duotone',
|
||||
prompt: t('chat.stack.prompt'),
|
||||
type: ChatType.STACK,
|
||||
},
|
||||
{
|
||||
label: t('chat.resume.label'),
|
||||
icon: 'i-ph-address-book-duotone',
|
||||
prompt: t('chat.resume.prompt'),
|
||||
type: ChatType.RESUME,
|
||||
},
|
||||
{
|
||||
label: t('chat.contact.label'),
|
||||
icon: 'i-ph-envelope-duotone',
|
||||
prompt: t('chat.contact.prompt'),
|
||||
type: ChatType.CONTACT,
|
||||
},
|
||||
{
|
||||
label: t('chat.hobbies.label'),
|
||||
icon: 'i-ph-heart-duotone',
|
||||
prompt: t('chat.hobbies.prompt'),
|
||||
type: ChatType.HOBBIES,
|
||||
},
|
||||
|
||||
].sort((a, b) => a.label.localeCompare(b.label)),
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
const { addMessage } = useChatStore()
|
||||
|
||||
async function submitMessage(type: ChatType, prompt: string, fetchStates: ChatFetchState[]) {
|
||||
addMessage(
|
||||
type,
|
||||
prompt,
|
||||
ChatSender.USER,
|
||||
[],
|
||||
)
|
||||
await new Promise(resolve => setTimeout(resolve, 700))
|
||||
addMessage(
|
||||
type,
|
||||
'',
|
||||
ChatSender.ARTHUR,
|
||||
fetchStates,
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
messages,
|
||||
submitMessage,
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,86 @@
|
||||
<script lang="ts" setup>
|
||||
import { nextTick, watch } from 'vue'
|
||||
import { ChatSender, ChatState, ChatType } from '~~/types'
|
||||
|
||||
useSeoMeta({
|
||||
title: 'Arthur Danjou - AI enjoyer and Maths student',
|
||||
description: 'Developer enjoying Artificial Intelligence and Machine Learning. Mathematics Student at Paris Dauphine-PSL University specialised in Statistics',
|
||||
})
|
||||
|
||||
const { messages } = useChatStore()
|
||||
const { t } = useI18n({ useScope: 'local' })
|
||||
|
||||
const scrollParents = ref<HTMLElement | null>(null)
|
||||
const lastMessage = computed(() => messages[messages.length - 1])
|
||||
|
||||
watch(
|
||||
() => lastMessage.value?.state,
|
||||
async () => {
|
||||
await nextTick()
|
||||
const container = scrollParents.value
|
||||
if (container) {
|
||||
const lastChild = container.lastElementChild
|
||||
if (lastChild) {
|
||||
lastChild.scrollIntoView({ behavior: 'smooth' })
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<main class="!max-w-none">
|
||||
<AppVisitors />
|
||||
<ChatCommandPalette />
|
||||
<div class="space-y-8">
|
||||
<ChatMessageContainer>
|
||||
Hello Arthur, tell me about you!
|
||||
</ChatMessageContainer>
|
||||
<ChatMessageContainer user="arthur">
|
||||
I am an AI enjoyer and a Maths student.
|
||||
</ChatMessageContainer>
|
||||
<ChatMessageContainer>
|
||||
I want to switch the theme
|
||||
</ChatMessageContainer>
|
||||
<ChatMessageContainer user="arthur">
|
||||
<ToolTheme />
|
||||
</ChatMessageContainer>
|
||||
<ChatMessageContainer>
|
||||
I want to change the language of the chat
|
||||
</ChatMessageContainer>
|
||||
<ChatMessageContainer user="arthur">
|
||||
<ToolLanguage />
|
||||
</ChatMessageContainer>
|
||||
<ChatMessageContainer>
|
||||
Show me the stats of Arthur
|
||||
</ChatMessageContainer>
|
||||
<ChatMessageContainer user="arthur">
|
||||
<ToolStats />
|
||||
</ChatMessageContainer>
|
||||
<ChatMessageContainer>
|
||||
What is Arthur doing?
|
||||
</ChatMessageContainer>
|
||||
<ChatMessageContainer user="arthur">
|
||||
<ToolActivity />
|
||||
</ChatMessageContainer>
|
||||
<div ref="scrollParents" class="space-y-8 max-h-[calc(100vh-10rem)] overflow-y-auto">
|
||||
<ChatMessageContainer
|
||||
:message="{
|
||||
content: t('init'),
|
||||
id: 0,
|
||||
sender: ChatSender.ARTHUR,
|
||||
state: ChatState.SENT,
|
||||
type: ChatType.INIT,
|
||||
}"
|
||||
/>
|
||||
<ChatMessageContainer
|
||||
:message="{
|
||||
id: 0,
|
||||
content: t('question'),
|
||||
sender: ChatSender.USER,
|
||||
state: ChatState.SENT,
|
||||
type: ChatType.INIT,
|
||||
}"
|
||||
/>
|
||||
<ChatMessageContainer
|
||||
:message="{
|
||||
content: t('about'),
|
||||
id: 0,
|
||||
sender: ChatSender.ARTHUR,
|
||||
state: ChatState.SENT,
|
||||
type: ChatType.INIT,
|
||||
}"
|
||||
/>
|
||||
<ChatMessageContainer v-for="message in messages" :key="message.id" :message="message" />
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<i18n lang="json">
|
||||
{
|
||||
"en": {
|
||||
"init": "Hey, welcome to ArtChat. I'm an AI assistant that knows everything about Arthur Danjou. Ask me anything and I'll answer as if I were him!",
|
||||
"question": "Awesome! Tell me a bit more about you.",
|
||||
"about": "I'm a student in Mathematics and Statistics at Université Paris-Dauphine in France. With a deep understanding of emerging technologies, I'm at the heart of a rapidly expanding field. My background in mathematics gives me an edge in understanding the concepts and theories behind these technologies and designing them effectively."
|
||||
},
|
||||
"fr": {
|
||||
|
||||
"init": "Salut, bienvenue sur ArtChat. Je suis un assistant IA connaissant tout sur Arthur Danjou. Pose moi des questions et j'y répondrai comme si j'étais lui.",
|
||||
"question": "Génial ! Parle moi un peu plus de toi.",
|
||||
"about": "Je suis étudiant en Mathématiques et en Statistiques à l'Université Paris-Dauphine en France. Avec une compréhension approfondie des technologies émergentes, je suis au cœur d'un domaine en pleine expansion. Mon parcours en mathématiques me donne un avantage pour comprendre les concepts et les théories derrière ces technologies et pour les concevoir efficacement."
|
||||
},
|
||||
"es": {
|
||||
"init": "Hola, bienvenido a ArtChat. Soy un asistente de IA que sabe todo sobre Arthur Danjou. Hazme preguntas y responderé como si fuera él.",
|
||||
"question": "¡Genial! Háblame un poco más sobre ti.",
|
||||
"about": "Soy estudiante de Matemáticas y Estadísticas en la Universidad Paris-Dauphine en Francia. Con una comprensión profunda de las tecnologías emergentes, estoy en el corazón de un campo en rápida expansión. Mi formación en matemáticas me da una ventaja para comprender los conceptos y teorías detrás de estas tecnologías y para diseñarlas de manera efectiva."
|
||||
}
|
||||
}
|
||||
</i18n>
|
||||
|
||||
@@ -1,17 +1,50 @@
|
||||
import type { ChatMessage } from '~~/types'
|
||||
import type { ChatMessage, ChatType } from '~~/types'
|
||||
import { ChatFetchState, ChatSender, ChatState } from '~~/types'
|
||||
|
||||
export const useChatStore = defineStore('chat', () => {
|
||||
const messages = ref<ChatMessage[]>([])
|
||||
let id = 0
|
||||
|
||||
function addMessage(message: ChatMessage) {
|
||||
messages.value.push({ ...message, id: id++ })
|
||||
const canSend = computed(() => {
|
||||
return !messages.value.some(msg => msg.state === ChatState.LOADING)
|
||||
})
|
||||
|
||||
function addMessage(type: ChatType, content: string, sender: ChatSender, fetchStates: ChatFetchState[]) {
|
||||
if (sender === ChatSender.ARTHUR) {
|
||||
const message: ChatMessage = {
|
||||
id: id++,
|
||||
type,
|
||||
content: null,
|
||||
sender,
|
||||
state: ChatState.LOADING,
|
||||
fetchStates: [...fetchStates, ChatFetchState.DONE],
|
||||
}
|
||||
|
||||
messages.value.push(message)
|
||||
}
|
||||
else {
|
||||
messages.value.push({
|
||||
id: id++,
|
||||
type,
|
||||
content,
|
||||
sender,
|
||||
state: ChatState.SENT,
|
||||
fetchStates: [ChatFetchState.DONE],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function clearMessages() {
|
||||
messages.value = []
|
||||
messages.value.splice(0, messages.value.length)
|
||||
id = 0
|
||||
}
|
||||
|
||||
return { messages, addMessage, clearMessages }
|
||||
function setLoadingState(messageId: number, loadingState: ChatState) {
|
||||
const message = messages.value.find(msg => msg.id === messageId)
|
||||
if (message) {
|
||||
message.state = loadingState
|
||||
}
|
||||
}
|
||||
|
||||
return { messages, addMessage, clearMessages, canSend, setLoadingState }
|
||||
})
|
||||
|
||||
83
bun.lock
83
bun.lock
@@ -4,6 +4,7 @@
|
||||
"": {
|
||||
"name": "nuxt-app",
|
||||
"dependencies": {
|
||||
"@antfu/eslint-config": "^5.2.1",
|
||||
"@iconify-json/devicon": "^1.2.43",
|
||||
"@iconify-json/logos": "^1.2.9",
|
||||
"@iconify-json/lucide": "^1.2.66",
|
||||
@@ -47,6 +48,8 @@
|
||||
|
||||
"@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="],
|
||||
|
||||
"@antfu/eslint-config": ["@antfu/eslint-config@5.2.1", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@clack/prompts": "^0.11.0", "@eslint-community/eslint-plugin-eslint-comments": "^4.5.0", "@eslint/markdown": "^7.1.0", "@stylistic/eslint-plugin": "^5.2.3", "@typescript-eslint/eslint-plugin": "^8.39.0", "@typescript-eslint/parser": "^8.39.0", "@vitest/eslint-plugin": "^1.3.4", "ansis": "^4.1.0", "cac": "^6.7.14", "eslint-config-flat-gitignore": "^2.1.0", "eslint-flat-config-utils": "^2.1.1", "eslint-merge-processors": "^2.0.0", "eslint-plugin-antfu": "^3.1.1", "eslint-plugin-command": "^3.3.1", "eslint-plugin-import-lite": "^0.3.0", "eslint-plugin-jsdoc": "^52.0.4", "eslint-plugin-jsonc": "^2.20.1", "eslint-plugin-n": "^17.21.3", "eslint-plugin-no-only-tests": "^3.3.0", "eslint-plugin-perfectionist": "^4.15.0", "eslint-plugin-pnpm": "^1.1.0", "eslint-plugin-regexp": "^2.10.0", "eslint-plugin-toml": "^0.12.0", "eslint-plugin-unicorn": "^60.0.0", "eslint-plugin-unused-imports": "^4.1.4", "eslint-plugin-vue": "^10.4.0", "eslint-plugin-yml": "^1.18.0", "eslint-processor-vue-blocks": "^2.0.0", "globals": "^16.3.0", "jsonc-eslint-parser": "^2.4.0", "local-pkg": "^1.1.1", "parse-gitignore": "^2.0.0", "toml-eslint-parser": "^0.10.0", "vue-eslint-parser": "^10.2.0", "yaml-eslint-parser": "^1.3.0" }, "peerDependencies": { "@eslint-react/eslint-plugin": "^1.38.4", "@next/eslint-plugin-next": "^15.4.0-canary.115", "@prettier/plugin-xml": "^3.4.1", "@unocss/eslint-plugin": ">=0.50.0", "astro-eslint-parser": "^1.0.2", "eslint": "^9.10.0", "eslint-plugin-astro": "^1.2.0", "eslint-plugin-format": ">=0.1.0", "eslint-plugin-jsx-a11y": ">=6.10.2", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.19", "eslint-plugin-solid": "^0.14.3", "eslint-plugin-svelte": ">=2.35.1", "eslint-plugin-vuejs-accessibility": "^2.4.1", "prettier-plugin-astro": "^0.14.0", "prettier-plugin-slidev": "^1.0.5", "svelte-eslint-parser": ">=0.37.0" }, "optionalPeers": ["@eslint-react/eslint-plugin", "@next/eslint-plugin-next", "@prettier/plugin-xml", "@unocss/eslint-plugin", "astro-eslint-parser", "eslint-plugin-astro", "eslint-plugin-format", "eslint-plugin-jsx-a11y", "eslint-plugin-react-hooks", "eslint-plugin-react-refresh", "eslint-plugin-solid", "eslint-plugin-svelte", "eslint-plugin-vuejs-accessibility", "prettier-plugin-astro", "prettier-plugin-slidev", "svelte-eslint-parser"], "bin": { "eslint-config": "bin/index.js" } }, "sha512-EG/5kwDci1PFKSwAPMEMHDA/VYJFn0TAqwXLdnmE7zuFcaug3EGih7UOWmapMfL59Hqq6jbomaUHN31aVnL8NA=="],
|
||||
|
||||
"@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="],
|
||||
|
||||
"@antfu/utils": ["@antfu/utils@9.2.0", "", {}, "sha512-Oq1d9BGZakE/FyoEtcNeSwM7MpDO2vUBi11RWBZXf75zPsbUVWmUs03EqkRFrcgbXyKTas0BdZWC1wcuSoqSAw=="],
|
||||
@@ -121,7 +124,7 @@
|
||||
|
||||
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
||||
|
||||
"@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.53.0", "", { "dependencies": { "@types/estree": "^1.0.8", "@typescript-eslint/types": "^8.39.1", "comment-parser": "1.4.1", "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.8.0" } }, "sha512-Wyed8Wfn3vMNVwrZrgLMxmqwmlcCE1/RfUAOHFzMJb3QLH03mi9Yv1iOCZjif0yx5EZUeJ+17VD1MHPka9IQjQ=="],
|
||||
"@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.50.2", "", { "dependencies": { "@types/estree": "^1.0.6", "@typescript-eslint/types": "^8.11.0", "comment-parser": "1.4.1", "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.1.0" } }, "sha512-YAdE/IJSpwbOTiaURNCKECdAwqrJuFiZhylmesBcIRawtYKnBR2wxPhoIewMg+Yu+QuYvHfJNReWpoxGBKOChA=="],
|
||||
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.9", "", { "os": "aix", "cpu": "ppc64" }, "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA=="],
|
||||
|
||||
@@ -175,6 +178,8 @@
|
||||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.9", "", { "os": "win32", "cpu": "x64" }, "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ=="],
|
||||
|
||||
"@eslint-community/eslint-plugin-eslint-comments": ["@eslint-community/eslint-plugin-eslint-comments@4.5.0", "", { "dependencies": { "escape-string-regexp": "^4.0.0", "ignore": "^5.2.4" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-MAhuTKlr4y/CE3WYX26raZjy+I/kS2PLKSzvfmDCGrBLTFHOYwqROZdr4XwPgXwX3K9rjzMr4pSmUWGnzsUyMg=="],
|
||||
|
||||
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="],
|
||||
|
||||
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="],
|
||||
@@ -193,6 +198,8 @@
|
||||
|
||||
"@eslint/js": ["@eslint/js@9.34.0", "", {}, "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw=="],
|
||||
|
||||
"@eslint/markdown": ["@eslint/markdown@7.2.0", "", { "dependencies": { "@eslint/core": "^0.15.2", "@eslint/plugin-kit": "^0.3.5", "github-slugger": "^2.0.0", "mdast-util-from-markdown": "^2.0.2", "mdast-util-frontmatter": "^2.0.1", "mdast-util-gfm": "^3.1.0", "micromark-extension-frontmatter": "^2.0.0", "micromark-extension-gfm": "^3.0.0", "micromark-util-normalize-identifier": "^2.0.1" } }, "sha512-cmDloByulvKzofM0tIkSGWwxMcrKOLsXZC+EM0FLkRIrxKzW+2RkZAt9TAh37EtQRmx1M4vjBEmlC6R0wiGkog=="],
|
||||
|
||||
"@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="],
|
||||
|
||||
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.5", "", { "dependencies": { "@eslint/core": "^0.15.2", "levn": "^0.4.1" } }, "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w=="],
|
||||
@@ -461,6 +468,8 @@
|
||||
|
||||
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
|
||||
|
||||
"@pkgr/core": ["@pkgr/core@0.2.9", "", {}, "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA=="],
|
||||
|
||||
"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
|
||||
|
||||
"@poppinss/colors": ["@poppinss/colors@4.1.5", "", { "dependencies": { "kleur": "^4.1.5" } }, "sha512-FvdDqtcRCtz6hThExcFOgW0cWX+xwSMWcRuQe5ZEb2m7cVQOAVZOIMt+/v9RxGiD9/OY16qJBXK4CVKWAPalBw=="],
|
||||
@@ -701,6 +710,8 @@
|
||||
|
||||
"@vitejs/plugin-vue-jsx": ["@vitejs/plugin-vue-jsx@5.1.1", "", { "dependencies": { "@babel/core": "^7.28.3", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/plugin-transform-typescript": "^7.28.0", "@rolldown/pluginutils": "^1.0.0-beta.34", "@vue/babel-plugin-jsx": "^1.5.0" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", "vue": "^3.0.0" } }, "sha512-uQkfxzlF8SGHJJVH966lFTdjM/lGcwJGzwAHpVqAPDD/QcsqoUGa+q31ox1BrUfi+FLP2ChVp7uLXE3DkHyDdQ=="],
|
||||
|
||||
"@vitest/eslint-plugin": ["@vitest/eslint-plugin@1.3.6", "", { "dependencies": { "@typescript-eslint/scope-manager": "^8.41.0", "@typescript-eslint/utils": "^8.24.1" }, "peerDependencies": { "eslint": ">= 8.57.0", "typescript": ">= 5.0.0", "vitest": "*" }, "optionalPeers": ["typescript", "vitest"] }, "sha512-sa/QAljHbUP+sMdPjK8e/6nS2+QB/bh1aDKEkAKMqsKVzBXqz4LRYfT7UVGIP8LMIrskGTxqAbHuiL+FOYWzHg=="],
|
||||
|
||||
"@volar/language-core": ["@volar/language-core@2.4.23", "", { "dependencies": { "@volar/source-map": "2.4.23" } }, "sha512-hEEd5ET/oSmBC6pi1j6NaNYRWoAiDhINbT8rmwtINugR39loROSlufGdYMF9TaKGfz+ViGs1Idi3mAhnuPcoGQ=="],
|
||||
|
||||
"@volar/source-map": ["@volar/source-map@2.4.23", "", {}, "sha512-Z1Uc8IB57Lm6k7q6KIDu/p+JWtf3xsXJqAX/5r18hYOTpJyBn0KXUR8oTJ4WFYOcDzWC9n3IflGgHowx6U6z9Q=="],
|
||||
@@ -1043,6 +1054,8 @@
|
||||
|
||||
"emoticon": ["emoticon@4.1.0", "", {}, "sha512-VWZfnxqwNcc51hIy/sbOdEem6D+cVtpPzEEtVAFdaas30+1dgkyaOQ4sQ6Bp0tOMqWO1v+HQfYaoodOkdhK6SQ=="],
|
||||
|
||||
"empathic": ["empathic@2.0.0", "", {}, "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA=="],
|
||||
|
||||
"encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
|
||||
|
||||
"engine.io-client": ["engine.io-client@6.6.3", "", { "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", "ws": "~8.17.1", "xmlhttprequest-ssl": "~2.1.1" } }, "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w=="],
|
||||
@@ -1071,26 +1084,52 @@
|
||||
|
||||
"eslint": ["eslint@9.34.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.34.0", "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg=="],
|
||||
|
||||
"eslint-compat-utils": ["eslint-compat-utils@0.6.5", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-vAUHYzue4YAa2hNACjB8HvUQj5yehAZgiClyFVVom9cP8z5NSFq3PwB/TtJslN2zAMgRX6FCFCjYBbQh71g5RQ=="],
|
||||
|
||||
"eslint-config-flat-gitignore": ["eslint-config-flat-gitignore@2.1.0", "", { "dependencies": { "@eslint/compat": "^1.2.5" }, "peerDependencies": { "eslint": "^9.5.0" } }, "sha512-cJzNJ7L+psWp5mXM7jBX+fjHtBvvh06RBlcweMhKD8jWqQw0G78hOW5tpVALGHGFPsBV+ot2H+pdDGJy6CV8pA=="],
|
||||
|
||||
"eslint-flat-config-utils": ["eslint-flat-config-utils@2.1.1", "", { "dependencies": { "pathe": "^2.0.3" } }, "sha512-K8eaPkBemHkfbYsZH7z4lZ/tt6gNSsVh535Wh9W9gQBS2WjvfUbbVr2NZR3L1yiRCLuOEimYfPxCxODczD4Opg=="],
|
||||
|
||||
"eslint-import-context": ["eslint-import-context@0.1.9", "", { "dependencies": { "get-tsconfig": "^4.10.1", "stable-hash-x": "^0.2.0" }, "peerDependencies": { "unrs-resolver": "^1.0.0" }, "optionalPeers": ["unrs-resolver"] }, "sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg=="],
|
||||
|
||||
"eslint-json-compat-utils": ["eslint-json-compat-utils@0.2.1", "", { "dependencies": { "esquery": "^1.6.0" }, "peerDependencies": { "eslint": "*", "jsonc-eslint-parser": "^2.4.0" } }, "sha512-YzEodbDyW8DX8bImKhAcCeu/L31Dd/70Bidx2Qex9OFUtgzXLqtfWL4Hr5fM/aCCB8QUZLuJur0S9k6UfgFkfg=="],
|
||||
|
||||
"eslint-merge-processors": ["eslint-merge-processors@2.0.0", "", { "peerDependencies": { "eslint": "*" } }, "sha512-sUuhSf3IrJdGooquEUB5TNpGNpBoQccbnaLHsb1XkBLUPPqCNivCpY05ZcpCOiV9uHwO2yxXEWVczVclzMxYlA=="],
|
||||
|
||||
"eslint-plugin-antfu": ["eslint-plugin-antfu@3.1.1", "", { "peerDependencies": { "eslint": "*" } }, "sha512-7Q+NhwLfHJFvopI2HBZbSxWXngTwBLKxW1AGXLr2lEGxcEIK/AsDs8pn8fvIizl5aZjBbVbVK5ujmMpBe4Tvdg=="],
|
||||
|
||||
"eslint-plugin-command": ["eslint-plugin-command@3.3.1", "", { "dependencies": { "@es-joy/jsdoccomment": "^0.50.2" }, "peerDependencies": { "eslint": "*" } }, "sha512-fBVTXQ2y48TVLT0+4A6PFINp7GcdIailHAXbvPBixE7x+YpYnNQhFZxTdvnb+aWk+COgNebQKen/7m4dmgyWAw=="],
|
||||
|
||||
"eslint-plugin-es-x": ["eslint-plugin-es-x@7.8.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.1.2", "@eslint-community/regexpp": "^4.11.0", "eslint-compat-utils": "^0.5.1" }, "peerDependencies": { "eslint": ">=8" } }, "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ=="],
|
||||
|
||||
"eslint-plugin-import-lite": ["eslint-plugin-import-lite@0.3.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/types": "^8.34.0" }, "peerDependencies": { "eslint": ">=9.0.0", "typescript": ">=4.5" }, "optionalPeers": ["typescript"] }, "sha512-dkNBAL6jcoCsXZsQ/Tt2yXmMDoNt5NaBh/U7yvccjiK8cai6Ay+MK77bMykmqQA2bTF6lngaLCDij6MTO3KkvA=="],
|
||||
|
||||
"eslint-plugin-import-x": ["eslint-plugin-import-x@4.16.1", "", { "dependencies": { "@typescript-eslint/types": "^8.35.0", "comment-parser": "^1.4.1", "debug": "^4.4.1", "eslint-import-context": "^0.1.9", "is-glob": "^4.0.3", "minimatch": "^9.0.3 || ^10.0.1", "semver": "^7.7.2", "stable-hash-x": "^0.2.0", "unrs-resolver": "^1.9.2" }, "peerDependencies": { "@typescript-eslint/utils": "^8.0.0", "eslint": "^8.57.0 || ^9.0.0", "eslint-import-resolver-node": "*" }, "optionalPeers": ["@typescript-eslint/utils", "eslint-import-resolver-node"] }, "sha512-vPZZsiOKaBAIATpFE2uMI4w5IRwdv/FpQ+qZZMR4E+PeOcM4OeoEbqxRMnywdxP19TyB/3h6QBB0EWon7letSQ=="],
|
||||
|
||||
"eslint-plugin-jsdoc": ["eslint-plugin-jsdoc@54.2.0", "", { "dependencies": { "@es-joy/jsdoccomment": "~0.53.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.4.1", "escape-string-regexp": "^4.0.0", "espree": "^10.4.0", "esquery": "^1.6.0", "parse-imports-exports": "^0.2.4", "semver": "^7.7.2", "spdx-expression-parse": "^4.0.0" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-3hDYfmkcKxlxkco5xfPFtGNiSdrYl6IePVMHS+DrGzwlpABuMiY7IeRMyFsp2K4ZnMuUX+nqTGMGOHq/oSXn6A=="],
|
||||
"eslint-plugin-jsdoc": ["eslint-plugin-jsdoc@52.0.4", "", { "dependencies": { "@es-joy/jsdoccomment": "~0.52.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.4.1", "escape-string-regexp": "^4.0.0", "espree": "^10.4.0", "esquery": "^1.6.0", "parse-imports-exports": "^0.2.4", "semver": "^7.7.2", "spdx-expression-parse": "^4.0.0" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-be5OzGlLExvcK13Il3noU7/v7WmAQGenTmCaBKf1pwVtPOb6X+PGFVnJad0QhMj4KKf45XjE4hbsBxv25q1fTg=="],
|
||||
|
||||
"eslint-plugin-jsonc": ["eslint-plugin-jsonc@2.20.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.5.1", "eslint-compat-utils": "^0.6.4", "eslint-json-compat-utils": "^0.2.1", "espree": "^9.6.1 || ^10.3.0", "graphemer": "^1.4.0", "jsonc-eslint-parser": "^2.4.0", "natural-compare": "^1.4.0", "synckit": "^0.6.2 || ^0.7.3 || ^0.11.5" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-gUzIwQHXx7ZPypUoadcyRi4WbHW2TPixDr0kqQ4miuJBU0emJmyGTlnaT3Og9X2a8R1CDayN9BFSq5weGWbTng=="],
|
||||
|
||||
"eslint-plugin-n": ["eslint-plugin-n@17.21.3", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.5.0", "enhanced-resolve": "^5.17.1", "eslint-plugin-es-x": "^7.8.0", "get-tsconfig": "^4.8.1", "globals": "^15.11.0", "globrex": "^0.1.2", "ignore": "^5.3.2", "semver": "^7.6.3", "ts-declaration-location": "^1.0.6" }, "peerDependencies": { "eslint": ">=8.23.0" } }, "sha512-MtxYjDZhMQgsWRm/4xYLL0i2EhusWT7itDxlJ80l1NND2AL2Vi5Mvneqv/ikG9+zpran0VsVRXTEHrpLmUZRNw=="],
|
||||
|
||||
"eslint-plugin-no-only-tests": ["eslint-plugin-no-only-tests@3.3.0", "", {}, "sha512-brcKcxGnISN2CcVhXJ/kEQlNa0MEfGRtwKtWA16SkqXHKitaKIMrfemJKLKX1YqDU5C/5JY3PvZXd5jEW04e0Q=="],
|
||||
|
||||
"eslint-plugin-perfectionist": ["eslint-plugin-perfectionist@4.15.0", "", { "dependencies": { "@typescript-eslint/types": "^8.34.1", "@typescript-eslint/utils": "^8.34.1", "natural-orderby": "^5.0.0" }, "peerDependencies": { "eslint": ">=8.45.0" } }, "sha512-pC7PgoXyDnEXe14xvRUhBII8A3zRgggKqJFx2a82fjrItDs1BSI7zdZnQtM2yQvcyod6/ujmzb7ejKPx8lZTnw=="],
|
||||
|
||||
"eslint-plugin-pnpm": ["eslint-plugin-pnpm@1.1.1", "", { "dependencies": { "empathic": "^2.0.0", "jsonc-eslint-parser": "^2.4.0", "pathe": "^2.0.3", "pnpm-workspace-yaml": "1.1.1", "tinyglobby": "^0.2.14", "yaml-eslint-parser": "^1.3.0" }, "peerDependencies": { "eslint": "^9.0.0" } }, "sha512-gNo+swrLCgvT8L6JX6hVmxuKeuStGK2l8IwVjDxmYIn+wP4SW/d0ORLKyUiYamsp+UxknQo3f2M1irrTpqahCw=="],
|
||||
|
||||
"eslint-plugin-regexp": ["eslint-plugin-regexp@2.10.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "comment-parser": "^1.4.0", "jsdoc-type-pratt-parser": "^4.0.0", "refa": "^0.12.1", "regexp-ast-analysis": "^0.7.1", "scslre": "^0.3.0" }, "peerDependencies": { "eslint": ">=8.44.0" } }, "sha512-ovzQT8ESVn5oOe5a7gIDPD5v9bCSjIFJu57sVPDqgPRXicQzOnYfFN21WoQBQF18vrhT5o7UMKFwJQVVjyJ0ng=="],
|
||||
|
||||
"eslint-plugin-toml": ["eslint-plugin-toml@0.12.0", "", { "dependencies": { "debug": "^4.1.1", "eslint-compat-utils": "^0.6.0", "lodash": "^4.17.19", "toml-eslint-parser": "^0.10.0" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-+/wVObA9DVhwZB1nG83D2OAQRrcQZXy+drqUnFJKymqnmbnbfg/UPmEMCKrJNcEboUGxUjYrJlgy+/Y930mURQ=="],
|
||||
|
||||
"eslint-plugin-unicorn": ["eslint-plugin-unicorn@60.0.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "@eslint-community/eslint-utils": "^4.7.0", "@eslint/plugin-kit": "^0.3.3", "change-case": "^5.4.4", "ci-info": "^4.3.0", "clean-regexp": "^1.0.0", "core-js-compat": "^3.44.0", "esquery": "^1.6.0", "find-up-simple": "^1.0.1", "globals": "^16.3.0", "indent-string": "^5.0.0", "is-builtin-module": "^5.0.0", "jsesc": "^3.1.0", "pluralize": "^8.0.0", "regexp-tree": "^0.1.27", "regjsparser": "^0.12.0", "semver": "^7.7.2", "strip-indent": "^4.0.0" }, "peerDependencies": { "eslint": ">=9.29.0" } }, "sha512-QUzTefvP8stfSXsqKQ+vBQSEsXIlAiCduS/V1Em+FKgL9c21U/IIm20/e3MFy1jyCf14tHAhqC1sX8OTy6VUCg=="],
|
||||
|
||||
"eslint-plugin-unused-imports": ["eslint-plugin-unused-imports@4.2.0", "", { "peerDependencies": { "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", "eslint": "^9.0.0 || ^8.0.0" }, "optionalPeers": ["@typescript-eslint/eslint-plugin"] }, "sha512-hLbJ2/wnjKq4kGA9AUaExVFIbNzyxYdVo49QZmKCnhk5pc9wcYRbfgLHvWJ8tnsdcseGhoUAddm9gn/lt+d74w=="],
|
||||
|
||||
"eslint-plugin-vue": ["eslint-plugin-vue@10.4.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", "postcss-selector-parser": "^6.0.15", "semver": "^7.6.3", "xml-name-validator": "^4.0.0" }, "peerDependencies": { "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", "eslint": "^8.57.0 || ^9.0.0", "vue-eslint-parser": "^10.0.0" }, "optionalPeers": ["@typescript-eslint/parser"] }, "sha512-K6tP0dW8FJVZLQxa2S7LcE1lLw3X8VvB3t887Q6CLrFVxHYBXGANbXvwNzYIu6Ughx1bSJ5BDT0YB3ybPT39lw=="],
|
||||
|
||||
"eslint-plugin-yml": ["eslint-plugin-yml@1.18.0", "", { "dependencies": { "debug": "^4.3.2", "escape-string-regexp": "4.0.0", "eslint-compat-utils": "^0.6.0", "natural-compare": "^1.4.0", "yaml-eslint-parser": "^1.2.1" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-9NtbhHRN2NJa/s3uHchO3qVVZw0vyOIvWlXWGaKCr/6l3Go62wsvJK5byiI6ZoYztDsow4GnS69BZD3GnqH3hA=="],
|
||||
|
||||
"eslint-processor-vue-blocks": ["eslint-processor-vue-blocks@2.0.0", "", { "peerDependencies": { "@vue/compiler-sfc": "^3.3.0", "eslint": ">=9.0.0" } }, "sha512-u4W0CJwGoWY3bjXAuFpc/b6eK3NQEI8MoeW7ritKj3G3z/WtHrKjkqf+wk8mPEy5rlMGS+k6AZYOw2XBoN/02Q=="],
|
||||
|
||||
"eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
|
||||
@@ -1141,6 +1180,8 @@
|
||||
|
||||
"fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
|
||||
|
||||
"fault": ["fault@2.0.1", "", { "dependencies": { "format": "^0.2.0" } }, "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ=="],
|
||||
|
||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||
|
||||
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
|
||||
@@ -1165,6 +1206,8 @@
|
||||
|
||||
"foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
|
||||
|
||||
"format": ["format@0.2.2", "", {}, "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww=="],
|
||||
|
||||
"fraction.js": ["fraction.js@4.3.7", "", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="],
|
||||
|
||||
"framer-motion": ["framer-motion@12.23.12", "", { "dependencies": { "motion-dom": "^12.23.12", "motion-utils": "^12.23.6", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-6e78rdVtnBvlEVgu6eFEAgG9v3wLnYEboM8I5O5EXvfKC8gxGQB8wXJdhkMy10iVcn05jl6CNw7/HTsTCfwcWg=="],
|
||||
@@ -1205,6 +1248,8 @@
|
||||
|
||||
"globby": ["globby@14.1.0", "", { "dependencies": { "@sindresorhus/merge-streams": "^2.1.0", "fast-glob": "^3.3.3", "ignore": "^7.0.3", "path-type": "^6.0.0", "slash": "^5.1.0", "unicorn-magic": "^0.3.0" } }, "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA=="],
|
||||
|
||||
"globrex": ["globrex@0.1.2", "", {}, "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="],
|
||||
|
||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||
|
||||
"graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="],
|
||||
@@ -1467,6 +1512,8 @@
|
||||
|
||||
"mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA=="],
|
||||
|
||||
"mdast-util-frontmatter": ["mdast-util-frontmatter@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "escape-string-regexp": "^5.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-extension-frontmatter": "^2.0.0" } }, "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA=="],
|
||||
|
||||
"mdast-util-gfm": ["mdast-util-gfm@3.1.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-gfm-autolink-literal": "^2.0.0", "mdast-util-gfm-footnote": "^2.0.0", "mdast-util-gfm-strikethrough": "^2.0.0", "mdast-util-gfm-table": "^2.0.0", "mdast-util-gfm-task-list-item": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ=="],
|
||||
|
||||
"mdast-util-gfm-autolink-literal": ["mdast-util-gfm-autolink-literal@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-find-and-replace": "^3.0.0", "micromark-util-character": "^2.0.0" } }, "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ=="],
|
||||
@@ -1499,6 +1546,8 @@
|
||||
|
||||
"micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="],
|
||||
|
||||
"micromark-extension-frontmatter": ["micromark-extension-frontmatter@2.0.0", "", { "dependencies": { "fault": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg=="],
|
||||
|
||||
"micromark-extension-gfm": ["micromark-extension-gfm@3.0.0", "", { "dependencies": { "micromark-extension-gfm-autolink-literal": "^2.0.0", "micromark-extension-gfm-footnote": "^2.0.0", "micromark-extension-gfm-strikethrough": "^2.0.0", "micromark-extension-gfm-table": "^2.0.0", "micromark-extension-gfm-tagfilter": "^2.0.0", "micromark-extension-gfm-task-list-item": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w=="],
|
||||
|
||||
"micromark-extension-gfm-autolink-literal": ["micromark-extension-gfm-autolink-literal@2.1.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw=="],
|
||||
@@ -1603,6 +1652,8 @@
|
||||
|
||||
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
||||
|
||||
"natural-orderby": ["natural-orderby@5.0.0", "", {}, "sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg=="],
|
||||
|
||||
"nitropack": ["nitropack@2.12.5", "", { "dependencies": { "@cloudflare/kv-asset-handler": "^0.4.0", "@rollup/plugin-alias": "^5.1.1", "@rollup/plugin-commonjs": "^28.0.6", "@rollup/plugin-inject": "^5.0.5", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.1", "@rollup/plugin-replace": "^6.0.2", "@rollup/plugin-terser": "^0.4.4", "@vercel/nft": "^0.30.1", "archiver": "^7.0.1", "c12": "^3.2.0", "chokidar": "^4.0.3", "citty": "^0.1.6", "compatx": "^0.2.0", "confbox": "^0.2.2", "consola": "^3.4.2", "cookie-es": "^2.0.0", "croner": "^9.1.0", "crossws": "^0.3.5", "db0": "^0.3.2", "defu": "^6.1.4", "destr": "^2.0.5", "dot-prop": "^9.0.0", "esbuild": "^0.25.9", "escape-string-regexp": "^5.0.0", "etag": "^1.8.1", "exsolve": "^1.0.7", "globby": "^14.1.0", "gzip-size": "^7.0.0", "h3": "^1.15.4", "hookable": "^5.5.3", "httpxy": "^0.1.7", "ioredis": "^5.7.0", "jiti": "^2.5.1", "klona": "^2.0.6", "knitwork": "^1.2.0", "listhen": "^1.9.0", "magic-string": "^0.30.18", "magicast": "^0.3.5", "mime": "^4.0.7", "mlly": "^1.8.0", "node-fetch-native": "^1.6.7", "node-mock-http": "^1.0.2", "ofetch": "^1.4.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^2.0.0", "pkg-types": "^2.3.0", "pretty-bytes": "^7.0.1", "radix3": "^1.1.2", "rollup": "^4.50.0", "rollup-plugin-visualizer": "^6.0.3", "scule": "^1.3.0", "semver": "^7.7.2", "serve-placeholder": "^2.0.2", "serve-static": "^2.2.0", "source-map": "^0.7.6", "std-env": "^3.9.0", "ufo": "^1.6.1", "ultrahtml": "^1.6.0", "uncrypto": "^0.1.3", "unctx": "^2.4.1", "unenv": "2.0.0-rc.20", "unimport": "^5.2.0", "unplugin-utils": "^0.3.0", "unstorage": "^1.17.0", "untyped": "^2.0.0", "unwasm": "^0.3.11", "youch": "4.1.0-beta.8", "youch-core": "^0.3.3" }, "peerDependencies": { "xml2js": "^0.6.2" }, "optionalPeers": ["xml2js"], "bin": { "nitro": "dist/cli/index.mjs", "nitropack": "dist/cli/index.mjs" } }, "sha512-KDTFhATOzqWHXFZkNlAH9J989Wibpl6s38eaYZj/Km2GbcUBLdcDxL4x7vd9pHWhD1Yk1u5oLh8+MsqJeQ7GMA=="],
|
||||
|
||||
"node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],
|
||||
@@ -1679,6 +1730,8 @@
|
||||
|
||||
"parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="],
|
||||
|
||||
"parse-gitignore": ["parse-gitignore@2.0.0", "", {}, "sha512-RmVuCHWsfu0QPNW+mraxh/xjQVw/lhUCUru8Zni3Ctq3AoMhpDTq0OVdKS6iesd6Kqb7viCV3isAL43dciOSog=="],
|
||||
|
||||
"parse-imports-exports": ["parse-imports-exports@0.2.4", "", { "dependencies": { "parse-statements": "1.0.11" } }, "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ=="],
|
||||
|
||||
"parse-path": ["parse-path@7.1.0", "", { "dependencies": { "protocols": "^2.0.0" } }, "sha512-EuCycjZtfPcjWk7KTksnJ5xPMvWGA/6i4zrLYhRG0hGvC3GPU/jGUj3Cy+ZR0v30duV3e23R95T1lE2+lsndSw=="],
|
||||
@@ -1717,6 +1770,8 @@
|
||||
|
||||
"pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="],
|
||||
|
||||
"pnpm-workspace-yaml": ["pnpm-workspace-yaml@1.1.1", "", { "dependencies": { "yaml": "^2.8.1" } }, "sha512-nGBB7h3Ped3g9dBrR6d3YNwXCKYsEg8K9J3GMmSrwGEXq3RHeGW44/B4MZW51p4FRMnyxJzTY5feSBbUjRhIHQ=="],
|
||||
|
||||
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
||||
|
||||
"postcss-calc": ["postcss-calc@10.1.1", "", { "dependencies": { "postcss-selector-parser": "^7.0.0", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.38" } }, "sha512-NYEsLHh8DgG/PRH2+G9BTuUdtf9ViS+vdoQ0YA5OQdGsfN4ztiwtDWNtBl9EKeqNMFnIu8IKZ0cLxEQ5r5KVMw=="],
|
||||
@@ -1993,6 +2048,8 @@
|
||||
|
||||
"swrv": ["swrv@1.1.0", "", { "peerDependencies": { "vue": ">=3.2.26 < 4" } }, "sha512-pjllRDr2s0iTwiE5Isvip51dZGR7GjLH1gCSVyE8bQnbAx6xackXsFdojau+1O5u98yHF5V73HQGOFxKUXO9gQ=="],
|
||||
|
||||
"synckit": ["synckit@0.11.11", "", { "dependencies": { "@pkgr/core": "^0.2.9" } }, "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw=="],
|
||||
|
||||
"system-architecture": ["system-architecture@0.1.0", "", {}, "sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA=="],
|
||||
|
||||
"tailwind-merge": ["tailwind-merge@3.3.1", "", {}, "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g=="],
|
||||
@@ -2023,6 +2080,8 @@
|
||||
|
||||
"toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
|
||||
|
||||
"toml-eslint-parser": ["toml-eslint-parser@0.10.0", "", { "dependencies": { "eslint-visitor-keys": "^3.0.0" } }, "sha512-khrZo4buq4qVmsGzS5yQjKe/WsFvV8fGfOjDQN0q4iy9FjRfPWRgTFrU8u1R2iu/SfWLhY9WnCi4Jhdrcbtg+g=="],
|
||||
|
||||
"tosource": ["tosource@2.0.0-alpha.3", "", {}, "sha512-KAB2lrSS48y91MzFPFuDg4hLbvDiyTjOVgaK7Erw+5AmZXNq4sFRVn8r6yxSLuNs15PaokrDRpS61ERY9uZOug=="],
|
||||
|
||||
"totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
|
||||
@@ -2037,6 +2096,8 @@
|
||||
|
||||
"ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="],
|
||||
|
||||
"ts-declaration-location": ["ts-declaration-location@1.0.7", "", { "dependencies": { "picomatch": "^4.0.2" }, "peerDependencies": { "typescript": ">=4.0.0" } }, "sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA=="],
|
||||
|
||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
|
||||
@@ -2227,6 +2288,8 @@
|
||||
|
||||
"@cloudflare/kv-asset-handler/mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="],
|
||||
|
||||
"@es-joy/jsdoccomment/jsdoc-type-pratt-parser": ["jsdoc-type-pratt-parser@4.1.0", "", {}, "sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg=="],
|
||||
|
||||
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||
|
||||
"@eslint/config-array/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
||||
@@ -2261,6 +2324,8 @@
|
||||
|
||||
"@nuxt/eslint/@nuxt/kit": ["@nuxt/kit@4.0.3", "", { "dependencies": { "c12": "^3.2.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.5.1", "klona": "^2.0.6", "mlly": "^1.7.4", "ohash": "^2.0.11", "pathe": "^2.0.3", "pkg-types": "^2.2.0", "scule": "^1.3.0", "semver": "^7.7.2", "std-env": "^3.9.0", "tinyglobby": "^0.2.14", "ufo": "^1.6.1", "unctx": "^2.4.1", "unimport": "^5.2.0", "untyped": "^2.0.0" } }, "sha512-9+lwvP4n8KhO91azoebO0o39smESGzEV4HU6nef9HIFyt04YwlVMY37Pk63GgZn0WhWVjyPWcQWs0rUdZUYcPw=="],
|
||||
|
||||
"@nuxt/eslint-config/eslint-plugin-jsdoc": ["eslint-plugin-jsdoc@54.2.0", "", { "dependencies": { "@es-joy/jsdoccomment": "~0.53.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.4.1", "escape-string-regexp": "^4.0.0", "espree": "^10.4.0", "esquery": "^1.6.0", "parse-imports-exports": "^0.2.4", "semver": "^7.7.2", "spdx-expression-parse": "^4.0.0" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-3hDYfmkcKxlxkco5xfPFtGNiSdrYl6IePVMHS+DrGzwlpABuMiY7IeRMyFsp2K4ZnMuUX+nqTGMGOHq/oSXn6A=="],
|
||||
|
||||
"@nuxt/icon/@nuxt/kit": ["@nuxt/kit@4.0.3", "", { "dependencies": { "c12": "^3.2.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.5.1", "klona": "^2.0.6", "mlly": "^1.7.4", "ohash": "^2.0.11", "pathe": "^2.0.3", "pkg-types": "^2.2.0", "scule": "^1.3.0", "semver": "^7.7.2", "std-env": "^3.9.0", "tinyglobby": "^0.2.14", "ufo": "^1.6.1", "unctx": "^2.4.1", "unimport": "^5.2.0", "untyped": "^2.0.0" } }, "sha512-9+lwvP4n8KhO91azoebO0o39smESGzEV4HU6nef9HIFyt04YwlVMY37Pk63GgZn0WhWVjyPWcQWs0rUdZUYcPw=="],
|
||||
|
||||
"@nuxt/kit/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
||||
@@ -2351,6 +2416,12 @@
|
||||
|
||||
"eslint/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
||||
|
||||
"eslint-plugin-es-x/eslint-compat-utils": ["eslint-compat-utils@0.5.1", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q=="],
|
||||
|
||||
"eslint-plugin-jsdoc/@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.52.0", "", { "dependencies": { "@types/estree": "^1.0.8", "@typescript-eslint/types": "^8.34.1", "comment-parser": "1.4.1", "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.1.0" } }, "sha512-BXuN7BII+8AyNtn57euU2Yxo9yA/KUDNzrpXyi3pfqKmBhhysR6ZWOebFh3vyPoqA3/j1SOvGgucElMGwlXing=="],
|
||||
|
||||
"eslint-plugin-n/globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="],
|
||||
|
||||
"eslint-plugin-vue/postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="],
|
||||
|
||||
"fast-glob/@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
|
||||
@@ -2383,6 +2454,8 @@
|
||||
|
||||
"mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
|
||||
|
||||
"mdast-util-frontmatter/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
|
||||
|
||||
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"mlly/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
|
||||
@@ -2457,6 +2530,8 @@
|
||||
|
||||
"terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
|
||||
|
||||
"toml-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||
|
||||
"unimport/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
|
||||
|
||||
"unplugin-auto-import/unplugin-utils": ["unplugin-utils@0.3.0", "", { "dependencies": { "pathe": "^2.0.3", "picomatch": "^4.0.3" } }, "sha512-JLoggz+PvLVMJo+jZt97hdIIIZ2yTzGgft9e9q8iMrC4ewufl62ekeW7mixBghonn2gVb/ICjyvlmOCUBnJLQg=="],
|
||||
@@ -2489,6 +2564,8 @@
|
||||
|
||||
"@nuxt/devtools/which/isexe": ["isexe@3.1.1", "", {}, "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="],
|
||||
|
||||
"@nuxt/eslint-config/eslint-plugin-jsdoc/@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.53.0", "", { "dependencies": { "@types/estree": "^1.0.8", "@typescript-eslint/types": "^8.39.1", "comment-parser": "1.4.1", "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.8.0" } }, "sha512-Wyed8Wfn3vMNVwrZrgLMxmqwmlcCE1/RfUAOHFzMJb3QLH03mi9Yv1iOCZjif0yx5EZUeJ+17VD1MHPka9IQjQ=="],
|
||||
|
||||
"@nuxt/eslint/@nuxt/kit/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
||||
|
||||
"@nuxt/icon/@nuxt/kit/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
||||
@@ -2509,6 +2586,8 @@
|
||||
|
||||
"csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="],
|
||||
|
||||
"eslint-plugin-jsdoc/@es-joy/jsdoccomment/jsdoc-type-pratt-parser": ["jsdoc-type-pratt-parser@4.1.0", "", {}, "sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg=="],
|
||||
|
||||
"eslint/find-up/locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
||||
|
||||
"eslint/find-up/path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// @ts-check
|
||||
import withNuxt from './.nuxt/eslint.config.mjs'
|
||||
import antfu from '@antfu/eslint-config'
|
||||
|
||||
export default withNuxt(
|
||||
export default antfu(
|
||||
// Your custom configs here
|
||||
)
|
||||
)
|
||||
@@ -23,13 +23,11 @@ export default defineNuxtConfig({
|
||||
'@vueuse/nuxt',
|
||||
'@nuxtjs/google-fonts',
|
||||
'@nuxt/image',
|
||||
'nuxt-visitors',
|
||||
'motion-v/nuxt',
|
||||
'@pinia/nuxt',
|
||||
'@nuxtjs/i18n',
|
||||
],
|
||||
|
||||
|
||||
// Nuxt Content
|
||||
content: {
|
||||
preview: {
|
||||
@@ -124,16 +122,13 @@ export default defineNuxtConfig({
|
||||
languages: '',
|
||||
os: '',
|
||||
},
|
||||
openWeather: {
|
||||
apiKey: '',
|
||||
},
|
||||
public: {
|
||||
i18n: {
|
||||
baseUrl: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Nuxt Visitors
|
||||
visitors: {
|
||||
// Set to true to enable tracking of visitor locations
|
||||
locations: true,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
@@ -7,9 +7,12 @@
|
||||
"dev": "nuxt dev",
|
||||
"generate": "nuxt generate",
|
||||
"preview": "nuxt preview",
|
||||
"postinstall": "nuxt prepare"
|
||||
"postinstall": "nuxt prepare",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint --fix ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@antfu/eslint-config": "^5.2.1",
|
||||
"@iconify-json/devicon": "^1.2.43",
|
||||
"@iconify-json/logos": "^1.2.9",
|
||||
"@iconify-json/lucide": "^1.2.66",
|
||||
|
||||
26
server/api/weather/index.get.ts
Normal file
26
server/api/weather/index.get.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import type { OpenWeatherResponse } from '~~/types'
|
||||
|
||||
export default defineCachedEventHandler(async (event) => {
|
||||
const { openWeather } = useRuntimeConfig(event)
|
||||
const response = await $fetch<OpenWeatherResponse>(`https://api.openweathermap.org/data/2.5/weather`, {
|
||||
params: {
|
||||
q: 'Paris,FR',
|
||||
units: 'metric',
|
||||
lang: 'en',
|
||||
appid: openWeather.apiKey,
|
||||
},
|
||||
})
|
||||
const weather = {
|
||||
location: response.name,
|
||||
temperature: Math.round(response.main.temp),
|
||||
temp_min: Math.round(response.main.temp_min),
|
||||
temp_max: Math.round(response.main.temp_max),
|
||||
humidity: response.main.humidity,
|
||||
wind: response.wind.speed,
|
||||
description: response.weather[0].description,
|
||||
}
|
||||
|
||||
return weather
|
||||
}, {
|
||||
maxAge: 12 * 60 * 60, // 12 hours
|
||||
})
|
||||
@@ -16,11 +16,31 @@ export enum ChatType {
|
||||
STATS = 'stats',
|
||||
ACTIVITY = 'activity',
|
||||
RESUME = 'resume',
|
||||
INIT = 'init',
|
||||
}
|
||||
|
||||
export enum ChatState {
|
||||
SENT = 'sent',
|
||||
LOADING = 'loading',
|
||||
}
|
||||
|
||||
export enum ChatSender {
|
||||
USER = 'user',
|
||||
ARTHUR = 'arthur',
|
||||
}
|
||||
|
||||
export enum ChatFetchState {
|
||||
THINKING = 'Thinking...',
|
||||
FETCHING = 'Fetching the data...',
|
||||
GENERATING = 'Generating the component...',
|
||||
DONE = 'Done!',
|
||||
}
|
||||
|
||||
export interface ChatMessage {
|
||||
id: number
|
||||
content: string
|
||||
sender: string
|
||||
content: string | null
|
||||
sender: ChatSender
|
||||
type: ChatType
|
||||
state: ChatState
|
||||
fetchStates?: ChatFetchState[]
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from './chat'
|
||||
export * from './lanyard'
|
||||
export * from './openweather'
|
||||
export * from './time'
|
||||
export * from './wakatime'
|
||||
|
||||
@@ -31,4 +32,5 @@ export const socials = [
|
||||
{ icon: 'i-ph:github-logo-duotone', label: 'GitHub', to: 'https://github.com/ArthurDanjou' },
|
||||
{ icon: 'i-ph:linkedin-logo-duotone', label: 'LinkedIn', to: 'https://www.linkedin.com/in/arthurdanjou/' },
|
||||
{ icon: 'i-ph:discord-logo-duotone', label: 'Discord', to: 'https://discordapp.com/users/179635349100691456' },
|
||||
{ icon: 'i-ph-envelope-duotone', label: 'Email', to: 'mailto:arthur.danjou@example.com' },
|
||||
] as const
|
||||
|
||||
25
types/openweather.ts
Normal file
25
types/openweather.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
export interface OpenWeatherResponse {
|
||||
name: string
|
||||
main: {
|
||||
temp: number
|
||||
temp_min: number
|
||||
temp_max: number
|
||||
humidity: number
|
||||
}
|
||||
wind: {
|
||||
speed: number
|
||||
}
|
||||
weather: {
|
||||
description: string
|
||||
}[]
|
||||
};
|
||||
|
||||
export interface Weather {
|
||||
location: string
|
||||
temperature: number
|
||||
temp_min: number
|
||||
temp_max: number
|
||||
humidity: number
|
||||
wind: number
|
||||
description: string
|
||||
};
|
||||
Reference in New Issue
Block a user