postgres -> sqlite, pinia/middleware fix?

other smaller: little type fixes, little changes to ui - more readable category chooser
- result screen with correct, incorrect and chosen answers
little changes to readme
This commit is contained in:
NetMan 2025-12-13 16:07:23 +01:00
parent c99576617b
commit 63121da4b7
25 changed files with 654 additions and 262 deletions

View file

@ -1,2 +1,2 @@
DATABASE_URL="postgres://USERNAME:PASSWORD@HOST:PORT/DATABASE" DATABASE_URL="file:./db/database.db"
CDN_URL="http://DOMAIN.TLD/FOLDER" CDN_URL="http://DOMAIN.TLD/FOLDER"

View file

@ -12,27 +12,29 @@ pnpm install
The [db-prawo-jazdy](https://git.mandarynki.eu/netman/db-prawo-jazdy) project is designed for this one in mind, so use it in conjunction with this - visit it for more details The [db-prawo-jazdy](https://git.mandarynki.eu/netman/db-prawo-jazdy) project is designed for this one in mind, so use it in conjunction with this - visit it for more details
You also need the exam media files from the (Ministry of Infrasture)[https://www.gov.pl/web/infrastruktura/prawo-jazdy]. The newest at the moment of me writing this (19th of April 2025) are the (visualisations for questions from the 18th of January of 2024)[https://www.gov.pl/pliki/mi/wizualizacje_do_pytan_18_01_2024.zip] You also need the exam media files from the (Ministry of Infrasture)[https://www.gov.pl/web/infrastruktura/prawo-jazdy] - the latest files should be there. The newest at the moment of me writing this (13th of Decemver 2025) are the (visualisations for questions from November(?) of 2025)[https://www.gov.pl/pliki/mi/pytania_egzaminacyjne_na_prawo_jazdy_11_2025.zip]
# To-do: # To-do:
- [x] re-forge database structure (good for now) - [x] re-forge database structure (good for now)
- [x] choose category (good for now) - [x] choose category (good for now)
- [x] come up with how to show results appropriately - [x] come up with how to show results appropriately
- [x] db: script for processing, share appropriate files
- [x] better answer click recognition - [x] better answer click recognition
- [x] beautify website (good for now) - [x] beautify website (good for now)
- [ ] <b>fix pinia middleware between pages, MAJOR ISSUE - finishing exam sometimes redirects to homepage instead of results, help appreciated</b> - [x] <b>Fixed?</b> Needs testing, but should be fine question-mark? - <b>fix pinia middleware between pages, MAJOR ISSUE - finishing exam sometimes redirects to homepage instead of results, help appreciated</b>
- [x] (scrapped - lazy loading)
- [ ] exam (& results?) warning leave message on exit and timer end (and definitely on refresh) - [ ] exam (& results?) warning leave message on exit and timer end (and definitely on refresh)
- [ ] question timers - [ ] question timers
- [ ] lazy loading - [ ] i18n - pl, en, de, ua (not all questions are available in ua, api handle)
- [ ] i18n - pl, en, de, ua (not all questions are not available in ua, api handle) - UI i18n
- db: examstore add language field, api handle languages
- [ ] db: (revise) script for processing, (revise and) share appropriate files
## Some info ## Some info
My intention is, to share access to test exams free of charge - all data is free of charge and is already available as public information, either on the gov website, or by writing to the MI My intention is, to share access to test exams free of charge - all data is free of charge and is already available as public information, either on the gov website, or by writing to the MI
This project is an SSR website mimicking an official driver's license exam (for different categories) with a seperate CDN for media, connected using an ORM to a postgres DB This project is a website mimicking an official driver's license exam (for different categories) with a seperate CDN for media, connected using an ORM to a postgres DB
## Development Server ## Development Server

View file

@ -3,3 +3,9 @@
<NuxtPage /> <NuxtPage />
</div> </div>
</template> </template>
<style>
.outline-set-solid {
outline-style: solid;
}
</style>

View file

@ -12,3 +12,33 @@ export default [
'D1', 'D1',
'PT', 'PT',
]; ];
export const opis = [
'motocykle bez ograniczeń mocy',
'⭐ samochody osobowe do 3,5 t',
'pojazdy ciężarowe powyżej 3,5 t',
'autobusy',
'ciągniki rolnicze i pojazdy wolnobieżne',
'motorowery i lekkie czterokołowce',
'motocykle do 125 cm³ i 11 kW',
'motocykle do 35 kW',
'czterokołowce (np. quady)',
'pojazdy od 3,5 t do 7,5 t',
'autobusy do 16 pasażerów',
'tramwaje',
];
export const wiek = [
'(24 lata; lub 20 lat jeśli masz kat. A2 min. 2 lata)',
'(18 lat)',
'(21 lat; lub 18 lat z kwalifikacją wstępną)',
'(24 lata; lub 21 lat z kwalifikacją wstępną)',
'(16 lat)',
'(14 lat)',
'(16 lat)',
'(18 lat)',
'(16 lat)',
'(18 lat)',
'(21 lat; lub 18 lat z kwalifikacją wstępną)',
'(21 lat)',
];

View file

@ -4,6 +4,8 @@ const myModal = useTemplateRef('myModal');
onMounted(() => { onMounted(() => {
myModal.value?.showModal(); myModal.value?.showModal();
}); });
defineEmits(['again']);
</script> </script>
<template> <template>
@ -20,9 +22,9 @@ onMounted(() => {
<div class="*:inline">Wynik: <slot name="resultTrueFalse" /></div> <div class="*:inline">Wynik: <slot name="resultTrueFalse" /></div>
<div class="flex flex-row gap-2"> <div class="flex flex-row gap-2">
<NuxtLink to="/" class="btn btn-soft">Wróć na stronę główną</NuxtLink> <NuxtLink to="/" class="btn btn-soft">Wróć na stronę główną</NuxtLink>
<NuxtLink to="/exam" class="btn btn-outline"> <div class="btn btn-outline" @click="$emit('again')">
Rozpocznij jeszcze raz Rozpocznij jeszcze raz
</NuxtLink> </div>
<button class="btn btn-neutral" @click="myModal?.close()"> <button class="btn btn-neutral" @click="myModal?.close()">
Przejrzyj odpowiedzi Przejrzyj odpowiedzi
</button> </button>

View file

@ -11,6 +11,7 @@ defineProps<{
const emit = defineEmits<{ const emit = defineEmits<{
changeNow: [value: string]; changeNow: [value: string];
changeCount: [num: number]; changeCount: [num: number];
again: [];
}>(); }>();
</script> </script>
@ -81,14 +82,8 @@ const emit = defineEmits<{
<div class="*:inline">Punkty: <slot name="points" /> / 74</div> <div class="*:inline">Punkty: <slot name="points" /> / 74</div>
<div class="*:inline">Wynik: <slot name="resultTrueFalse" /></div> <div class="*:inline">Wynik: <slot name="resultTrueFalse" /></div>
</div> </div>
<NuxtLink to="/exam" class="btn btn-warning btn-xl"> <div class="btn btn-warning btn-xl" @click="$emit('again')">
Rozpocznij jeszcze raz Rozpocznij jeszcze raz
</NuxtLink> </div>
</div> </div>
</template> </template>
<style scoped>
.outline-set-solid {
outline-style: solid;
}
</style>

View file

@ -1,6 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
defineProps<{ defineProps<{
question: AdvancedQuestion | undefined; question: Question;
phase: string;
}>(); }>();
const answer = defineModel<string | null | undefined>(); const answer = defineModel<string | null | undefined>();
@ -16,9 +17,9 @@ const answer = defineModel<string | null | undefined>();
<div class="flex flex-col gap-3"> <div class="flex flex-col gap-3">
<div <div
v-for="[element, value] of Object.entries({ v-for="[element, value] of Object.entries({
A: question?.answer_a, A: (question as AdvancedQuestion)?.answer_a,
B: question?.answer_b, B: (question as AdvancedQuestion)?.answer_b,
C: question?.answer_c, C: (question as AdvancedQuestion)?.answer_c,
})" })"
:key="`btn_answer_${element}_${value}`" :key="`btn_answer_${element}_${value}`"
> >
@ -32,7 +33,13 @@ const answer = defineModel<string | null | undefined>();
/> />
<label :for="`odp_${element}`"> <label :for="`odp_${element}`">
<div <div
:class="answer === element ? ' !btn-secondary' : ''" :class="
phase == 'exam'
? answer === element
? ' !btn-secondary'
: ''
: `${answer === element ? 'outline-set-solid outline-2' : ''} ${element == question?.correct_answer ? 'btn-success' : 'btn-error'}`
"
class="btn btn-primary btn-lg" class="btn btn-primary btn-lg"
> >
{{ element }} {{ element }}

View file

@ -1,6 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
defineProps<{ defineProps<{
question: BasicQuestion | undefined; question: Question;
phase: string;
}>(); }>();
const answer = defineModel<string | null | undefined>(); const answer = defineModel<string | null | undefined>();
@ -26,11 +27,21 @@ const answer = defineModel<string | null | undefined>();
class="btn btn-primary btn-xl" class="btn btn-primary btn-xl"
:aria-label="element" :aria-label="element"
:class=" :class="
answer == null phase == 'exam'
? false ? answer == null
: answer === value.toString() ? false
? '!btn-secondary' : answer === value.toString()
: '' ? '!btn-secondary'
: ''
: `${
answer === value.toString()
? 'outline-set-solid outline-2'
: ''
} ${
question?.correct_answer?.toString() == value.toString()
? ' btn-success'
: ' btn-error'
}`
" "
:checked="answer == null ? false : answer === value.toString()" :checked="answer == null ? false : answer === value.toString()"
/> />

BIN
db/database.db Normal file

Binary file not shown.

36
db/schema.ts Normal file
View file

@ -0,0 +1,36 @@
import { sqliteTable, text, int } from 'drizzle-orm/sqlite-core';
export const tasks = sqliteTable('tasks', {
id: int().notNull(),
correct_answer: text(),
media_url: text(),
weight: int(),
});
export const questions = sqliteTable('questions', {
task_id: int(),
lang: text(),
text: text(),
});
export const tasks_advanced = sqliteTable('tasks_advanced', {
id: int().notNull(),
correct_answer: text(),
media_url: text(),
weight: int(),
});
export const questions_advanced = sqliteTable('questions_advanced', {
task_id: int(),
lang: text(),
text: text(),
answer_a: text(),
answer_b: text(),
answer_c: text(),
});
export const categories_db = sqliteTable('categories', {
name: text(),
task_id: int(),
});

View file

@ -2,9 +2,9 @@ import 'dotenv/config';
import { defineConfig } from 'drizzle-kit'; import { defineConfig } from 'drizzle-kit';
export default defineConfig({ export default defineConfig({
dialect: 'postgresql',
schema: './src/db/schema.ts',
out: './drizzle', out: './drizzle',
schema: './db/schema.ts',
dialect: 'sqlite',
dbCredentials: { dbCredentials: {
url: process.env.DATABASE_URL!, url: process.env.DATABASE_URL!,
}, },

View file

@ -1,9 +1,9 @@
export default defineNuxtRouteMiddleware(async () => { export default defineNuxtRouteMiddleware(async () => {
const examStore = useExamStore(); const examStore = useExamStore();
if (examStore.end) {
if (examStore.category === '') { return '/result';
examStore.resetExam(); }
return navigateTo('/'); if (examStore.category === '') {
return '/anomaly';
} }
examStore.mildReset();
}); });

View file

@ -1,8 +1,6 @@
export default defineNuxtRouteMiddleware(() => { export default defineNuxtRouteMiddleware(async () => {
const examStore = useExamStore(); const examStore = useExamStore();
if (!examStore.end || examStore.category === '') {
if (!examStore.end) { return '/anomaly';
examStore.resetExam();
return navigateTo('/');
} }
}); });

View file

@ -6,10 +6,11 @@ export default defineNuxtConfig({
'@nuxtjs/tailwindcss', '@nuxtjs/tailwindcss',
'@nuxt/fonts', '@nuxt/fonts',
'@pinia/nuxt', '@pinia/nuxt',
'pinia-plugin-persistedstate/nuxt',
'@nuxt/eslint', '@nuxt/eslint',
'@nuxt/image', '@nuxt/image',
], ],
ssr: true, ssr: false,
imports: { imports: {
dirs: ['types/*.ts', 'store/*.ts', 'types/**/*.ts'], dirs: ['types/*.ts', 'store/*.ts', 'types/**/*.ts'],
}, },
@ -46,4 +47,7 @@ export default defineNuxtConfig({
}, },
provider: 'selfhost', provider: 'selfhost',
}, },
pinia: {
storesDirs: ['./store/**'],
},
}); });

View file

@ -14,6 +14,7 @@
"tsc": "nuxi typecheck" "tsc": "nuxi typecheck"
}, },
"dependencies": { "dependencies": {
"@libsql/client": "^0.15.15",
"@nuxt/fonts": "0.11.1", "@nuxt/fonts": "0.11.1",
"@nuxt/image": "1.10.0", "@nuxt/image": "1.10.0",
"@nuxtjs/tailwindcss": "6.13.2", "@nuxtjs/tailwindcss": "6.13.2",
@ -27,8 +28,8 @@
"eslint": "^9.24.0", "eslint": "^9.24.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"nuxt": "~3.16.2", "nuxt": "~3.16.2",
"pg": "^8.14.1",
"pinia": "^3.0.2", "pinia": "^3.0.2",
"pinia-plugin-persistedstate": "^4.7.1",
"ufo": "^1.6.1", "ufo": "^1.6.1",
"vue": "latest", "vue": "latest",
"vue-router": "latest" "vue-router": "latest"
@ -37,7 +38,6 @@
"devDependencies": { "devDependencies": {
"@nuxt/eslint": "1.3.0", "@nuxt/eslint": "1.3.0",
"@types/lodash": "^4.17.16", "@types/lodash": "^4.17.16",
"@types/pg": "^8.11.13",
"eslint-config-prettier": "^10.1.2", "eslint-config-prettier": "^10.1.2",
"prettier": "^3.5.3", "prettier": "^3.5.3",
"tsx": "^4.19.3", "tsx": "^4.19.3",

17
pages/anomaly.vue Normal file
View file

@ -0,0 +1,17 @@
<script setup lang="ts">
const examStore = useExamStore();
const basicStore = useBasicStore();
const advancedStore = useAdvancedStore();
</script>
<template>
<div class="flex flex-col gap-2 items-start m-2">
<h1 class="text-2xl">Nastąpiła anomalia</h1>
<br />
Kategoria: {{ examStore.category != '' ? examStore.category : '""' }} <br />
Koniec: {{ examStore.end }} <br />
Pytania podstawowe: {{ basicStore.basic }} <br />
Pytania specjalistyczne: {{ advancedStore.advanced }} <br />
<NuxtLink to="/" class="btn btn-primary"> Wróć na stronę główną </NuxtLink>
</div>
</template>

View file

@ -1,13 +1,28 @@
<script lang="ts" setup> <script lang="ts" setup>
import { intervalToDuration, addMinutes, addSeconds, isEqual } from 'date-fns'; import {
intervalToDuration,
addMinutes,
addSeconds,
isEqual,
isAfter,
} from 'date-fns';
import { useExamStore } from '~/store/examStore'; import { useExamStore } from '~/store/examStore';
definePageMeta({ middleware: ['exam'] }); definePageMeta({
middleware: 'exam',
});
const examStore = useExamStore();
const basicStore = useBasicStore();
const advancedStore = useAdvancedStore();
// await callOnce(() => examStore.mildReset(), { mode: 'navigation' });
useHead({ useHead({
title: 'Pytanie 1/20', title: 'Pytanie 1/20',
}); });
const now = ref('basic');
const nowTime = ref(new Date()); const nowTime = ref(new Date());
const timeEnd = addMinutes(new Date(), 25); const timeEnd = addMinutes(new Date(), 25);
@ -22,11 +37,11 @@ const timeRemainingTotal = computed(() =>
onMounted(() => { onMounted(() => {
const endInterval = setInterval(() => { const endInterval = setInterval(() => {
nowTime.value = addSeconds(nowTime.value, 1); nowTime.value = addSeconds(nowTime.value, 1);
if (isEqual(nowTime.value, timeEnd)) { if (isEqual(nowTime.value, timeEnd) || isAfter(nowTime.value, timeEnd)) {
clearInterval(endInterval); clearInterval(endInterval);
endExam(); endExam();
} }
}, 1000); }, 999);
watchEffect(() => { watchEffect(() => {
if (now.value === 'basic') if (now.value === 'basic')
@ -36,8 +51,6 @@ onMounted(() => {
}); });
}); });
const examStore = useExamStore();
const { const {
data: dataBasic, data: dataBasic,
error: errorBasic, error: errorBasic,
@ -61,7 +74,6 @@ const {
const countBasic = ref(0); const countBasic = ref(0);
const countAdvanced = ref(-1); const countAdvanced = ref(-1);
const now = ref('basic');
const answer = ref<string>(''); const answer = ref<string>('');
const ending = ref(false); const ending = ref(false);
@ -84,44 +96,46 @@ const result: Ref<ResultEndType> = ref({
advanced: [], advanced: [],
}); });
async function next() { function next() {
if (now.value === 'basic' || now.value === 'advanced') { result.value[now.value as keyof ResultEndType].push({
result.value[now.value].push({ question: question.value,
question: question.value, chosen_answer: answer.value,
chosen_answer: answer.value, correct_answer: question.value?.correct_answer ?? null,
chosen_is_correct: answer.value === question.value?.correct_answer, chosen_is_correct: answer.value == question.value?.correct_answer,
}); });
}
answer.value = ''; answer.value = '';
if (now.value === 'basic') { if (now.value === 'basic') {
if (countBasic.value < 19) { if (countBasic.value + 1 <= 19) {
countBasic.value++; countBasic.value++;
} else { } else {
now.value = 'advanced'; now.value = 'advanced';
countAdvanced.value++; countAdvanced.value++;
} }
} else if (now.value === 'advanced') { } else if (now.value === 'advanced') {
if (countAdvanced.value < 11) { if (countAdvanced.value + 1 <= 11) {
countAdvanced.value++; countAdvanced.value++;
} } else if (countAdvanced.value + 1 >= 12) {
if (countAdvanced.value >= 11) {
ending.value = true; ending.value = true;
} else {
// error?
} }
} }
} }
function endExam() { function endExam() {
loading.value = true; loading.value = true;
while (!ending.value) { while (ending.value == false) next();
next(); examStore.setBasic(result.value.basic);
} examStore.setAdvanced(result.value.advanced);
next();
examStore.setResult(result.value);
examStore.setEnd(true); examStore.setEnd(true);
while (true) { while (true) {
if (examStore.result == result.value && examStore.end) { if (
return navigateTo('/result', { replace: true }); basicStore.basic == result.value.basic &&
advancedStore.advanced == result.value.advanced &&
examStore.end
) {
return navigateTo(`/result`, { replace: true });
} }
} }
} }
@ -145,15 +159,16 @@ const loading = ref(false);
<QuestionBasic <QuestionBasic
v-if="now === 'basic'" v-if="now === 'basic'"
v-model="answer" v-model="answer"
phase="exam"
:question="questionBasic" :question="questionBasic"
/> />
<QuestionAdvanced <QuestionAdvanced
v-else-if="now === 'advanced'" v-else-if="now === 'advanced'"
v-model="answer" v-model="answer"
phase="exam"
:question="questionAdvanced" :question="questionAdvanced"
/> />
</div> </div>
<BarRightExam <BarRightExam
:count-basic="countBasic" :count-basic="countBasic"
:count-advanced="countAdvanced" :count-advanced="countAdvanced"

View file

@ -1,5 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import categories from '~/categories'; import categories from '~/categories';
import { opis } from '~/categories';
import { wiek } from '~/categories';
onMounted(() => { onMounted(() => {
useHead({ useHead({
@ -10,6 +12,9 @@ onMounted(() => {
const loading = ref(false); const loading = ref(false);
const examStore = useExamStore(); const examStore = useExamStore();
const basicStore = useBasicStore();
const advancedStore = useAdvancedStore();
await callOnce(() => examStore.resetExam(), { mode: 'navigation' });
function setAndGo(category: string) { function setAndGo(category: string) {
loading.value = true; loading.value = true;
@ -24,22 +29,24 @@ function setAndGo(category: string) {
<template> <template>
<div> <div>
<div v-if="!loading" class="text-3xl"> <div v-if="!loading" class="text-3xl m-2 flex flex-col gap-2">
<span>Test na prawo jazdy</span> <span>Test na prawo jazdy</span>
<p> <div
Witaj w teście na prawo jazdy, aby rozpocząć, naciśnij jeden z class="flex flex-col flex-wrap gap-2 items-start p-4 bg-slate-100 border-1 border-slate-500 rounded-xl w-fit"
poniższych przycisków: >
<br /> <div
</p> v-for="[index, category] of categories.entries()"
<div class="flex flex-row flex-wrap gap-2">
<button
v-for="category in categories"
:key="`btn-${category}`" :key="`btn-${category}`"
class="btn btn-xl btn-secondary" class="flex flex-row gap-3 items-center"
@click="setAndGo(category)"
> >
{{ category }} <button class="btn btn-xl btn-secondary" @click="setAndGo(category)">
</button> {{ category }}
</button>
<div class="flex flex-col text-sm">
<div>{{ opis[index] }}</div>
<div>{{ wiek[index] }}</div>
</div>
</div>
</div> </div>
</div> </div>
<LoadingScreen v-else /> <LoadingScreen v-else />

View file

@ -5,14 +5,19 @@ definePageMeta({ middleware: ['result'] });
const examStore = useExamStore(); const examStore = useExamStore();
const basicStore = useBasicStore();
const advancedStore = useAdvancedStore();
const loading = ref(false);
const points = ref<number>(0); const points = ref<number>(0);
examStore.result.basic.forEach((answer) => { basicStore.basic.forEach((answer) => {
if (answer.chosen_is_correct) { if (answer.chosen_is_correct) {
points.value += answer.question?.weight ?? 0; points.value += answer.question?.weight ?? 0;
} }
}); });
examStore.result.advanced.forEach((answer) => { advancedStore.advanced.forEach((answer) => {
if (answer.chosen_is_correct) { if (answer.chosen_is_correct) {
points.value += answer.question?.weight ?? 0; points.value += answer.question?.weight ?? 0;
} }
@ -32,17 +37,17 @@ onMounted(() => {
const countBasic = ref(0); const countBasic = ref(0);
const countAdvanced = ref(0); const countAdvanced = ref(0);
const resultQuestionBasic = computed<ResultType<BasicQuestion> | undefined>( const resultQuestionBasic = computed<ResultType | undefined>(() =>
() => examStore.result.basic.at(countBasic.value), basicStore.basic.at(countBasic.value),
);
const resultQuestionAdvanced = computed<ResultType | undefined>(() =>
advancedStore.advanced.at(countAdvanced.value),
); );
const resultQuestionAdvanced = computed<
ResultType<AdvancedQuestion> | undefined
>(() => examStore.result.advanced.at(countAdvanced.value));
const questionBasic = computed<BasicQuestion | undefined>( const questionBasic = computed<Question>(
() => resultQuestionBasic.value?.question, () => resultQuestionBasic.value?.question,
); );
const questionAdvanced = computed<AdvancedQuestion | undefined>( const questionAdvanced = computed<Question>(
() => resultQuestionAdvanced.value?.question, () => resultQuestionAdvanced.value?.question,
); );
@ -81,46 +86,60 @@ function changeCount(num: number) {
countAdvanced.value = num; countAdvanced.value = num;
} }
} }
async function again() {
loading.value = true;
await examStore.mildReset();
return await navigateTo('/exam');
}
</script> </script>
<template> <template>
<div> <div>
<ResultModal> <LoadingScreen v-if="loading" />
<template #title>Egzamin teorytyczny</template> <div v-else>
<template #category>{{ examStore.category }}</template> <ResultModal @again="again">
<template #points>{{ points }}</template> <template #title>Egzamin teorytyczny</template>
<template #resultTrueFalse>{{ resultTrueFalse }}</template> <template #category>{{ examStore.category }}</template>
</ResultModal> <template #points>{{ points }}</template>
<div> <template #resultTrueFalse>{{ resultTrueFalse }} </template>
<div class="grid grid-cols-4 min-h-dvh"> </ResultModal>
<div class="col-span-3 flex flex-col"> <div>
<BarTop :points="question?.weight" :category="examStore.category" /> <div class="grid grid-cols-4 min-h-dvh">
<MediaBox :media-path="question?.media_url" /> <div class="col-span-3 flex flex-col">
<QuestionBasic <BarTop :points="question?.weight" :category="examStore.category" />
v-if="now === 'basic'" <MediaBox :media-path="question?.media_url" />
v-model="answer" <QuestionBasic
:question="questionBasic" v-if="now === 'basic'"
class="select-none z-[-1]" v-model="answer"
/> :question="questionBasic"
<QuestionAdvanced phase="result"
v-else-if="now === 'advanced'" class="select-none z-[-1]"
v-model="answer" />
:question="questionAdvanced" <QuestionAdvanced
class="select-none z-[-1]" v-else-if="now === 'advanced'"
/> v-model="answer"
:question="questionAdvanced"
phase="result"
class="select-none z-[-1]"
/>
</div>
<BarRightResult
:result="{
basic: basicStore.basic,
advanced: advancedStore.advanced,
}"
:count-basic="countBasic"
:count-advanced="countAdvanced"
:now="now"
@change-now="changeNow"
@change-count="changeCount"
@again="again"
>
<template #points>{{ points }}</template>
<template #resultTrueFalse>{{ resultTrueFalse }}</template>
</BarRightResult>
</div> </div>
<BarRightResult
:result="examStore.result"
:count-basic="countBasic"
:count-advanced="countAdvanced"
:now="now"
@change-now="changeNow"
@change-count="changeCount"
>
<template #points>{{ points }}</template>
<template #resultTrueFalse>{{ resultTrueFalse }}</template>
</BarRightResult>
</div> </div>
</div> </div>
</div> </div>

354
pnpm-lock.yaml generated
View file

@ -8,12 +8,15 @@ importers:
.: .:
dependencies: dependencies:
'@libsql/client':
specifier: ^0.15.15
version: 0.15.15
'@nuxt/fonts': '@nuxt/fonts':
specifier: 0.11.1 specifier: 0.11.1
version: 0.11.1(db0@0.3.1(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1)(magicast@0.3.5)(vite@6.2.6(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)) version: 0.11.1(db0@0.3.1(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1)(magicast@0.3.5)(vite@6.2.6(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))
'@nuxt/image': '@nuxt/image':
specifier: 1.10.0 specifier: 1.10.0
version: 1.10.0(db0@0.3.1(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1)(magicast@0.3.5) version: 1.10.0(db0@0.3.1(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1)(magicast@0.3.5)
'@nuxtjs/tailwindcss': '@nuxtjs/tailwindcss':
specifier: 6.13.2 specifier: 6.13.2
version: 6.13.2(magicast@0.3.5) version: 6.13.2(magicast@0.3.5)
@ -24,8 +27,8 @@ importers:
specifier: ^3.0.0 specifier: ^3.0.0
version: 3.0.0 version: 3.0.0
daisyui: daisyui:
specifier: ^5.0.23 specifier: ^5.0.27
version: 5.0.23 version: 5.2.3
date-fns: date-fns:
specifier: ^4.1.0 specifier: ^4.1.0
version: 4.1.0 version: 4.1.0
@ -37,7 +40,7 @@ importers:
version: 0.31.0 version: 0.31.0
drizzle-orm: drizzle-orm:
specifier: ^0.42.0 specifier: ^0.42.0
version: 0.42.0(@types/pg@8.11.13)(pg@8.14.1) version: 0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)
eslint: eslint:
specifier: ^9.24.0 specifier: ^9.24.0
version: 9.24.0(jiti@2.4.2) version: 9.24.0(jiti@2.4.2)
@ -46,13 +49,13 @@ importers:
version: 4.17.21 version: 4.17.21
nuxt: nuxt:
specifier: ~3.16.2 specifier: ~3.16.2
version: 3.16.2(@parcel/watcher@2.5.1)(@types/node@22.14.1)(db0@0.3.1(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)))(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1))(eslint@9.24.0(jiti@2.4.2))(ioredis@5.6.1)(lightningcss@1.29.2)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.40.0)(terser@5.39.0)(tsx@4.19.3)(typescript@5.8.3)(vite@6.2.6(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(yaml@2.7.1) version: 3.16.2(@libsql/client@0.15.15)(@parcel/watcher@2.5.1)(@types/node@22.14.1)(db0@0.3.1(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)))(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1))(eslint@9.24.0(jiti@2.4.2))(ioredis@5.6.1)(lightningcss@1.29.2)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.40.0)(terser@5.39.0)(tsx@4.19.3)(typescript@5.8.3)(vite@6.2.6(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(yaml@2.7.1)
pg:
specifier: ^8.14.1
version: 8.14.1
pinia: pinia:
specifier: ^3.0.2 specifier: ^3.0.2
version: 3.0.2(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3)) version: 3.0.2(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3))
pinia-plugin-persistedstate:
specifier: ^4.7.1
version: 4.7.1(@nuxt/kit@3.16.2(magicast@0.3.5))(@pinia/nuxt@0.11.0(magicast@0.3.5)(pinia@3.0.2(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3))))(pinia@3.0.2(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3)))
ufo: ufo:
specifier: ^1.6.1 specifier: ^1.6.1
version: 1.6.1 version: 1.6.1
@ -69,9 +72,6 @@ importers:
'@types/lodash': '@types/lodash':
specifier: ^4.17.16 specifier: ^4.17.16
version: 4.17.16 version: 4.17.16
'@types/pg':
specifier: ^8.11.13
version: 8.11.13
eslint-config-prettier: eslint-config-prettier:
specifier: ^10.1.2 specifier: ^10.1.2
version: 10.1.2(eslint@9.24.0(jiti@2.4.2)) version: 10.1.2(eslint@9.24.0(jiti@2.4.2))
@ -678,6 +678,67 @@ packages:
'@kwsites/promise-deferred@1.1.1': '@kwsites/promise-deferred@1.1.1':
resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==}
'@libsql/client@0.15.15':
resolution: {integrity: sha512-twC0hQxPNHPKfeOv3sNT6u2pturQjLcI+CnpTM0SjRpocEGgfiZ7DWKXLNnsothjyJmDqEsBQJ5ztq9Wlu470w==}
'@libsql/core@0.15.15':
resolution: {integrity: sha512-C88Z6UKl+OyuKKPwz224riz02ih/zHYI3Ho/LAcVOgjsunIRZoBw7fjRfaH9oPMmSNeQfhGklSG2il1URoOIsA==}
'@libsql/darwin-arm64@0.5.22':
resolution: {integrity: sha512-4B8ZlX3nIDPndfct7GNe0nI3Yw6ibocEicWdC4fvQbSs/jdq/RC2oCsoJxJ4NzXkvktX70C1J4FcmmoBy069UA==}
cpu: [arm64]
os: [darwin]
'@libsql/darwin-x64@0.5.22':
resolution: {integrity: sha512-ny2HYWt6lFSIdNFzUFIJ04uiW6finXfMNJ7wypkAD8Pqdm6nAByO+Fdqu8t7sD0sqJGeUCiOg480icjyQ2/8VA==}
cpu: [x64]
os: [darwin]
'@libsql/hrana-client@0.7.0':
resolution: {integrity: sha512-OF8fFQSkbL7vJY9rfuegK1R7sPgQ6kFMkDamiEccNUvieQ+3urzfDFI616oPl8V7T9zRmnTkSjMOImYCAVRVuw==}
'@libsql/isomorphic-fetch@0.3.1':
resolution: {integrity: sha512-6kK3SUK5Uu56zPq/Las620n5aS9xJq+jMBcNSOmjhNf/MUvdyji4vrMTqD7ptY7/4/CAVEAYDeotUz60LNQHtw==}
engines: {node: '>=18.0.0'}
'@libsql/isomorphic-ws@0.1.5':
resolution: {integrity: sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==}
'@libsql/linux-arm-gnueabihf@0.5.22':
resolution: {integrity: sha512-3Uo3SoDPJe/zBnyZKosziRGtszXaEtv57raWrZIahtQDsjxBVjuzYQinCm9LRCJCUT5t2r5Z5nLDPJi2CwZVoA==}
cpu: [arm]
os: [linux]
'@libsql/linux-arm-musleabihf@0.5.22':
resolution: {integrity: sha512-LCsXh07jvSojTNJptT9CowOzwITznD+YFGGW+1XxUr7fS+7/ydUrpDfsMX7UqTqjm7xG17eq86VkWJgHJfvpNg==}
cpu: [arm]
os: [linux]
'@libsql/linux-arm64-gnu@0.5.22':
resolution: {integrity: sha512-KSdnOMy88c9mpOFKUEzPskSaF3VLflfSUCBwas/pn1/sV3pEhtMF6H8VUCd2rsedwoukeeCSEONqX7LLnQwRMA==}
cpu: [arm64]
os: [linux]
'@libsql/linux-arm64-musl@0.5.22':
resolution: {integrity: sha512-mCHSMAsDTLK5YH//lcV3eFEgiR23Ym0U9oEvgZA0667gqRZg/2px+7LshDvErEKv2XZ8ixzw3p1IrBzLQHGSsw==}
cpu: [arm64]
os: [linux]
'@libsql/linux-x64-gnu@0.5.22':
resolution: {integrity: sha512-kNBHaIkSg78Y4BqAdgjcR2mBilZXs4HYkAmi58J+4GRwDQZh5fIUWbnQvB9f95DkWUIGVeenqLRFY2pcTmlsew==}
cpu: [x64]
os: [linux]
'@libsql/linux-x64-musl@0.5.22':
resolution: {integrity: sha512-UZ4Xdxm4pu3pQXjvfJiyCzZop/9j/eA2JjmhMaAhe3EVLH2g11Fy4fwyUp9sT1QJYR1kpc2JLuybPM0kuXv/Tg==}
cpu: [x64]
os: [linux]
'@libsql/win32-x64-msvc@0.5.22':
resolution: {integrity: sha512-Fj0j8RnBpo43tVZUVoNK6BV/9AtDUM5S7DF3LB4qTYg1LMSZqi3yeCneUTLJD6XomQJlZzbI4mst89yspVSAnA==}
cpu: [x64]
os: [win32]
'@mapbox/node-pre-gyp@2.0.0': '@mapbox/node-pre-gyp@2.0.0':
resolution: {integrity: sha512-llMXd39jtP0HpQLVI37Bf1m2ADlEb35GYSh1SDSLsBhR+5iCxiNGlT31yqbNtVHygHAtMy6dWFERpU2JgufhPg==} resolution: {integrity: sha512-llMXd39jtP0HpQLVI37Bf1m2ADlEb35GYSh1SDSLsBhR+5iCxiNGlT31yqbNtVHygHAtMy6dWFERpU2JgufhPg==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -686,6 +747,9 @@ packages:
'@napi-rs/wasm-runtime@0.2.8': '@napi-rs/wasm-runtime@0.2.8':
resolution: {integrity: sha512-OBlgKdX7gin7OIq4fadsjpg+cp2ZphvAIKucHsNfTdJiqdOmOEwQd/bHi0VwNrcw5xpBJyUw6cK/QilCqy1BSg==} resolution: {integrity: sha512-OBlgKdX7gin7OIq4fadsjpg+cp2ZphvAIKucHsNfTdJiqdOmOEwQd/bHi0VwNrcw5xpBJyUw6cK/QilCqy1BSg==}
'@neon-rs/load@0.0.4':
resolution: {integrity: sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==}
'@netlify/functions@3.0.4': '@netlify/functions@3.0.4':
resolution: {integrity: sha512-Ox8+ABI+nsLK+c4/oC5dpquXuEIjzfTlJrdQKgQijCsDQoje7inXFAtKDLvvaGvuvE+PVpMLwQcIUL6P9Ob1hQ==} resolution: {integrity: sha512-Ox8+ABI+nsLK+c4/oC5dpquXuEIjzfTlJrdQKgQijCsDQoje7inXFAtKDLvvaGvuvE+PVpMLwQcIUL6P9Ob1hQ==}
engines: {node: '>=18.0.0'} engines: {node: '>=18.0.0'}
@ -1209,6 +1273,9 @@ packages:
'@types/resolve@1.20.2': '@types/resolve@1.20.2':
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
'@types/ws@8.18.1':
resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}
'@typescript-eslint/eslint-plugin@8.30.1': '@typescript-eslint/eslint-plugin@8.30.1':
resolution: {integrity: sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==} resolution: {integrity: sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@ -1911,8 +1978,12 @@ packages:
csstype@3.1.3: csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
daisyui@5.0.23: daisyui@5.2.3:
resolution: {integrity: sha512-SIR8yAneeNxvrpaR5kREG1DrPK8XFyfmyvqyZEUTJ2e6tv4Pp56/w+52Vdv34hmSmtAyDldTCEPWx+GvPyp0Yg==} resolution: {integrity: sha512-sldBQUIFCsSPoF4LvoHhIi9GnvBX/3aZD9NoTOvpTSX8sDjO484wQx7yEvRyREMpn4rZMvQSKKskHAHdM8+B4Q==}
data-uri-to-buffer@4.0.1:
resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
engines: {node: '>= 12'}
date-fns@4.1.0: date-fns@4.1.0:
resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==}
@ -2021,6 +2092,10 @@ packages:
engines: {node: '>=0.10'} engines: {node: '>=0.10'}
hasBin: true hasBin: true
detect-libc@2.0.2:
resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==}
engines: {node: '>=8'}
detect-libc@2.0.3: detect-libc@2.0.3:
resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -2423,6 +2498,10 @@ packages:
picomatch: picomatch:
optional: true optional: true
fetch-blob@3.2.0:
resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
engines: {node: ^12.20 || >= 14.13}
file-entry-cache@8.0.0: file-entry-cache@8.0.0:
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
engines: {node: '>=16.0.0'} engines: {node: '>=16.0.0'}
@ -2463,6 +2542,10 @@ packages:
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'} engines: {node: '>=14'}
formdata-polyfill@4.0.10:
resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
engines: {node: '>=12.20.0'}
fraction.js@4.3.7: fraction.js@4.3.7:
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
@ -2819,6 +2902,9 @@ packages:
resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==}
hasBin: true hasBin: true
js-base64@3.7.8:
resolution: {integrity: sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==}
js-tokens@4.0.0: js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@ -2915,6 +3001,10 @@ packages:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
libsql@0.5.22:
resolution: {integrity: sha512-NscWthMQt7fpU8lqd7LXMvT9pi+KhhmTHAJWUB/Lj6MWa0MKFv0F2V4C6WKKpjCVZl0VwcDz4nOI3CyaT1DDiA==}
os: [darwin, linux, win32]
lightningcss-darwin-arm64@1.29.2: lightningcss-darwin-arm64@1.29.2:
resolution: {integrity: sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==} resolution: {integrity: sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
@ -3209,6 +3299,11 @@ packages:
node-addon-api@7.1.1: node-addon-api@7.1.1:
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
node-domexception@1.0.0:
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
engines: {node: '>=10.5.0'}
deprecated: Use your platform's native DOMException instead
node-fetch-native@1.6.6: node-fetch-native@1.6.6:
resolution: {integrity: sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==} resolution: {integrity: sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==}
@ -3221,6 +3316,10 @@ packages:
encoding: encoding:
optional: true optional: true
node-fetch@3.3.2:
resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
node-forge@1.3.1: node-forge@1.3.1:
resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
engines: {node: '>= 6.13.0'} engines: {node: '>= 6.13.0'}
@ -3490,6 +3589,20 @@ packages:
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
pinia-plugin-persistedstate@4.7.1:
resolution: {integrity: sha512-WHOqh2esDlR3eAaknPbqXrkkj0D24h8shrDPqysgCFR6ghqP/fpFfJmMPJp0gETHsvrh9YNNg6dQfo2OEtDnIQ==}
peerDependencies:
'@nuxt/kit': '>=3.0.0'
'@pinia/nuxt': '>=0.10.0'
pinia: '>=3.0.0'
peerDependenciesMeta:
'@nuxt/kit':
optional: true
'@pinia/nuxt':
optional: true
pinia:
optional: true
pinia@3.0.2: pinia@3.0.2:
resolution: {integrity: sha512-sH2JK3wNY809JOeiiURUR0wehJ9/gd9qFN2Y828jCbxEzKEmEt0pzCXwqiSTfuRsK9vQsOflSdnbdBOGrhtn+g==} resolution: {integrity: sha512-sH2JK3wNY809JOeiiURUR0wehJ9/gd9qFN2Y828jCbxEzKEmEt0pzCXwqiSTfuRsK9vQsOflSdnbdBOGrhtn+g==}
peerDependencies: peerDependencies:
@ -3790,6 +3903,9 @@ packages:
resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
engines: {node: '>= 0.6.0'} engines: {node: '>= 0.6.0'}
promise-limit@2.7.0:
resolution: {integrity: sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw==}
prompts@2.4.2: prompts@2.4.2:
resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
@ -4625,6 +4741,10 @@ packages:
typescript: typescript:
optional: true optional: true
web-streams-polyfill@3.3.3:
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
engines: {node: '>= 8'}
webidl-conversions@3.0.1: webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
@ -5273,6 +5393,68 @@ snapshots:
'@kwsites/promise-deferred@1.1.1': {} '@kwsites/promise-deferred@1.1.1': {}
'@libsql/client@0.15.15':
dependencies:
'@libsql/core': 0.15.15
'@libsql/hrana-client': 0.7.0
js-base64: 3.7.8
libsql: 0.5.22
promise-limit: 2.7.0
transitivePeerDependencies:
- bufferutil
- utf-8-validate
'@libsql/core@0.15.15':
dependencies:
js-base64: 3.7.8
'@libsql/darwin-arm64@0.5.22':
optional: true
'@libsql/darwin-x64@0.5.22':
optional: true
'@libsql/hrana-client@0.7.0':
dependencies:
'@libsql/isomorphic-fetch': 0.3.1
'@libsql/isomorphic-ws': 0.1.5
js-base64: 3.7.8
node-fetch: 3.3.2
transitivePeerDependencies:
- bufferutil
- utf-8-validate
'@libsql/isomorphic-fetch@0.3.1': {}
'@libsql/isomorphic-ws@0.1.5':
dependencies:
'@types/ws': 8.18.1
ws: 8.18.1
transitivePeerDependencies:
- bufferutil
- utf-8-validate
'@libsql/linux-arm-gnueabihf@0.5.22':
optional: true
'@libsql/linux-arm-musleabihf@0.5.22':
optional: true
'@libsql/linux-arm64-gnu@0.5.22':
optional: true
'@libsql/linux-arm64-musl@0.5.22':
optional: true
'@libsql/linux-x64-gnu@0.5.22':
optional: true
'@libsql/linux-x64-musl@0.5.22':
optional: true
'@libsql/win32-x64-msvc@0.5.22':
optional: true
'@mapbox/node-pre-gyp@2.0.0': '@mapbox/node-pre-gyp@2.0.0':
dependencies: dependencies:
consola: 3.4.2 consola: 3.4.2
@ -5293,6 +5475,8 @@ snapshots:
'@tybys/wasm-util': 0.9.0 '@tybys/wasm-util': 0.9.0
optional: true optional: true
'@neon-rs/load@0.0.4': {}
'@netlify/functions@3.0.4': '@netlify/functions@3.0.4':
dependencies: dependencies:
'@netlify/serverless-functions-api': 1.36.0 '@netlify/serverless-functions-api': 1.36.0
@ -5480,7 +5664,7 @@ snapshots:
- utf-8-validate - utf-8-validate
- vite - vite
'@nuxt/fonts@0.11.1(db0@0.3.1(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1)(magicast@0.3.5)(vite@6.2.6(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))': '@nuxt/fonts@0.11.1(db0@0.3.1(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1)(magicast@0.3.5)(vite@6.2.6(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))':
dependencies: dependencies:
'@nuxt/devtools-kit': 2.4.0(magicast@0.3.5)(vite@6.2.6(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)) '@nuxt/devtools-kit': 2.4.0(magicast@0.3.5)(vite@6.2.6(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))
'@nuxt/kit': 3.16.2(magicast@0.3.5) '@nuxt/kit': 3.16.2(magicast@0.3.5)
@ -5501,7 +5685,7 @@ snapshots:
ufo: 1.6.1 ufo: 1.6.1
unifont: 0.1.7 unifont: 0.1.7
unplugin: 2.3.2 unplugin: 2.3.2
unstorage: 1.15.0(db0@0.3.1(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1) unstorage: 1.15.0(db0@0.3.1(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1)
transitivePeerDependencies: transitivePeerDependencies:
- '@azure/app-configuration' - '@azure/app-configuration'
- '@azure/cosmos' - '@azure/cosmos'
@ -5525,7 +5709,7 @@ snapshots:
- uploadthing - uploadthing
- vite - vite
'@nuxt/image@1.10.0(db0@0.3.1(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1)(magicast@0.3.5)': '@nuxt/image@1.10.0(db0@0.3.1(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1)(magicast@0.3.5)':
dependencies: dependencies:
'@nuxt/kit': 3.16.2(magicast@0.3.5) '@nuxt/kit': 3.16.2(magicast@0.3.5)
consola: 3.4.2 consola: 3.4.2
@ -5538,7 +5722,7 @@ snapshots:
std-env: 3.9.0 std-env: 3.9.0
ufo: 1.6.1 ufo: 1.6.1
optionalDependencies: optionalDependencies:
ipx: 2.1.0(db0@0.3.1(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1) ipx: 2.1.0(db0@0.3.1(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1)
transitivePeerDependencies: transitivePeerDependencies:
- '@azure/app-configuration' - '@azure/app-configuration'
- '@azure/cosmos' - '@azure/cosmos'
@ -5999,9 +6183,14 @@ snapshots:
'@types/node': 22.14.1 '@types/node': 22.14.1
pg-protocol: 1.8.0 pg-protocol: 1.8.0
pg-types: 4.0.2 pg-types: 4.0.2
optional: true
'@types/resolve@1.20.2': {} '@types/resolve@1.20.2': {}
'@types/ws@8.18.1':
dependencies:
'@types/node': 22.14.1
'@typescript-eslint/eslint-plugin@8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.24.0(jiti@2.4.2))(typescript@5.8.3)': '@typescript-eslint/eslint-plugin@8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.24.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies: dependencies:
'@eslint-community/regexpp': 4.12.1 '@eslint-community/regexpp': 4.12.1
@ -6791,13 +6980,16 @@ snapshots:
csstype@3.1.3: {} csstype@3.1.3: {}
daisyui@5.0.23: {} daisyui@5.2.3: {}
data-uri-to-buffer@4.0.1: {}
date-fns@4.1.0: {} date-fns@4.1.0: {}
db0@0.3.1(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)): db0@0.3.1(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)):
optionalDependencies: optionalDependencies:
drizzle-orm: 0.42.0(@types/pg@8.11.13)(pg@8.14.1) '@libsql/client': 0.15.15
drizzle-orm: 0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)
debug@3.2.7: debug@3.2.7:
dependencies: dependencies:
@ -6848,6 +7040,8 @@ snapshots:
detect-libc@1.0.3: {} detect-libc@1.0.3: {}
detect-libc@2.0.2: {}
detect-libc@2.0.3: {} detect-libc@2.0.3: {}
devalue@5.1.1: {} devalue@5.1.1: {}
@ -6897,8 +7091,9 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1): drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1):
optionalDependencies: optionalDependencies:
'@libsql/client': 0.15.15
'@types/pg': 8.11.13 '@types/pg': 8.11.13
pg: 8.14.1 pg: 8.14.1
@ -7267,6 +7462,11 @@ snapshots:
optionalDependencies: optionalDependencies:
picomatch: 4.0.2 picomatch: 4.0.2
fetch-blob@3.2.0:
dependencies:
node-domexception: 1.0.0
web-streams-polyfill: 3.3.3
file-entry-cache@8.0.0: file-entry-cache@8.0.0:
dependencies: dependencies:
flat-cache: 4.0.1 flat-cache: 4.0.1
@ -7326,6 +7526,10 @@ snapshots:
cross-spawn: 7.0.6 cross-spawn: 7.0.6
signal-exit: 4.1.0 signal-exit: 4.1.0
formdata-polyfill@4.0.10:
dependencies:
fetch-blob: 3.2.0
fraction.js@4.3.7: {} fraction.js@4.3.7: {}
fresh@0.5.2: {} fresh@0.5.2: {}
@ -7585,7 +7789,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
ipx@2.1.0(db0@0.3.1(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1): ipx@2.1.0(db0@0.3.1(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1):
dependencies: dependencies:
'@fastify/accept-negotiator': 1.1.0 '@fastify/accept-negotiator': 1.1.0
citty: 0.1.6 citty: 0.1.6
@ -7601,7 +7805,7 @@ snapshots:
sharp: 0.32.6 sharp: 0.32.6
svgo: 3.3.2 svgo: 3.3.2
ufo: 1.6.1 ufo: 1.6.1
unstorage: 1.15.0(db0@0.3.1(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1) unstorage: 1.15.0(db0@0.3.1(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1)
xss: 1.0.15 xss: 1.0.15
transitivePeerDependencies: transitivePeerDependencies:
- '@azure/app-configuration' - '@azure/app-configuration'
@ -7725,6 +7929,8 @@ snapshots:
jiti@2.4.2: {} jiti@2.4.2: {}
js-base64@3.7.8: {}
js-tokens@4.0.0: {} js-tokens@4.0.0: {}
js-tokens@9.0.1: {} js-tokens@9.0.1: {}
@ -7838,6 +8044,21 @@ snapshots:
prelude-ls: 1.2.1 prelude-ls: 1.2.1
type-check: 0.4.0 type-check: 0.4.0
libsql@0.5.22:
dependencies:
'@neon-rs/load': 0.0.4
detect-libc: 2.0.2
optionalDependencies:
'@libsql/darwin-arm64': 0.5.22
'@libsql/darwin-x64': 0.5.22
'@libsql/linux-arm-gnueabihf': 0.5.22
'@libsql/linux-arm-musleabihf': 0.5.22
'@libsql/linux-arm64-gnu': 0.5.22
'@libsql/linux-arm64-musl': 0.5.22
'@libsql/linux-x64-gnu': 0.5.22
'@libsql/linux-x64-musl': 0.5.22
'@libsql/win32-x64-msvc': 0.5.22
lightningcss-darwin-arm64@1.29.2: lightningcss-darwin-arm64@1.29.2:
optional: true optional: true
@ -8075,7 +8296,7 @@ snapshots:
negotiator@0.6.3: {} negotiator@0.6.3: {}
nitropack@2.11.9(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)): nitropack@2.11.9(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)):
dependencies: dependencies:
'@cloudflare/kv-asset-handler': 0.4.0 '@cloudflare/kv-asset-handler': 0.4.0
'@netlify/functions': 3.0.4 '@netlify/functions': 3.0.4
@ -8097,7 +8318,7 @@ snapshots:
cookie-es: 2.0.0 cookie-es: 2.0.0
croner: 9.0.0 croner: 9.0.0
crossws: 0.3.4 crossws: 0.3.4
db0: 0.3.1(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)) db0: 0.3.1(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1))
defu: 6.1.4 defu: 6.1.4
destr: 2.0.5 destr: 2.0.5
dot-prop: 9.0.0 dot-prop: 9.0.0
@ -8143,7 +8364,7 @@ snapshots:
unenv: 2.0.0-rc.15 unenv: 2.0.0-rc.15
unimport: 5.0.0 unimport: 5.0.0
unplugin-utils: 0.2.4 unplugin-utils: 0.2.4
unstorage: 1.15.0(db0@0.3.1(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1) unstorage: 1.15.0(db0@0.3.1(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1)
untyped: 2.0.0 untyped: 2.0.0
unwasm: 0.3.9 unwasm: 0.3.9
youch: 4.1.0-beta.7 youch: 4.1.0-beta.7
@ -8185,12 +8406,20 @@ snapshots:
node-addon-api@7.1.1: {} node-addon-api@7.1.1: {}
node-domexception@1.0.0: {}
node-fetch-native@1.6.6: {} node-fetch-native@1.6.6: {}
node-fetch@2.7.0: node-fetch@2.7.0:
dependencies: dependencies:
whatwg-url: 5.0.0 whatwg-url: 5.0.0
node-fetch@3.3.2:
dependencies:
data-uri-to-buffer: 4.0.1
fetch-blob: 3.2.0
formdata-polyfill: 4.0.10
node-forge@1.3.1: {} node-forge@1.3.1: {}
node-gyp-build@4.8.4: {} node-gyp-build@4.8.4: {}
@ -8226,7 +8455,7 @@ snapshots:
dependencies: dependencies:
boolbase: 1.0.0 boolbase: 1.0.0
nuxt@3.16.2(@parcel/watcher@2.5.1)(@types/node@22.14.1)(db0@0.3.1(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)))(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1))(eslint@9.24.0(jiti@2.4.2))(ioredis@5.6.1)(lightningcss@1.29.2)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.40.0)(terser@5.39.0)(tsx@4.19.3)(typescript@5.8.3)(vite@6.2.6(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(yaml@2.7.1): nuxt@3.16.2(@libsql/client@0.15.15)(@parcel/watcher@2.5.1)(@types/node@22.14.1)(db0@0.3.1(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)))(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1))(eslint@9.24.0(jiti@2.4.2))(ioredis@5.6.1)(lightningcss@1.29.2)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.40.0)(terser@5.39.0)(tsx@4.19.3)(typescript@5.8.3)(vite@6.2.6(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(yaml@2.7.1):
dependencies: dependencies:
'@nuxt/cli': 3.24.1(magicast@0.3.5) '@nuxt/cli': 3.24.1(magicast@0.3.5)
'@nuxt/devalue': 2.0.2 '@nuxt/devalue': 2.0.2
@ -8263,7 +8492,7 @@ snapshots:
mlly: 1.7.4 mlly: 1.7.4
mocked-exports: 0.1.1 mocked-exports: 0.1.1
nanotar: 0.2.0 nanotar: 0.2.0
nitropack: 2.11.9(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)) nitropack: 2.11.9(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1))
nypm: 0.6.0 nypm: 0.6.0
ofetch: 1.4.1 ofetch: 1.4.1
ohash: 2.0.11 ohash: 2.0.11
@ -8285,7 +8514,7 @@ snapshots:
unimport: 4.2.0 unimport: 4.2.0
unplugin: 2.3.2 unplugin: 2.3.2
unplugin-vue-router: 0.12.0(vue-router@4.5.0(vue@3.5.13(typescript@5.8.3)))(vue@3.5.13(typescript@5.8.3)) unplugin-vue-router: 0.12.0(vue-router@4.5.0(vue@3.5.13(typescript@5.8.3)))(vue@3.5.13(typescript@5.8.3))
unstorage: 1.15.0(db0@0.3.1(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1) unstorage: 1.15.0(db0@0.3.1(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1)
untyped: 2.0.0 untyped: 2.0.0
vue: 3.5.13(typescript@5.8.3) vue: 3.5.13(typescript@5.8.3)
vue-bundle-renderer: 2.1.1 vue-bundle-renderer: 2.1.1
@ -8359,7 +8588,8 @@ snapshots:
object-hash@3.0.0: {} object-hash@3.0.0: {}
obuf@1.1.2: {} obuf@1.1.2:
optional: true
ofetch@1.4.1: ofetch@1.4.1:
dependencies: dependencies:
@ -8511,17 +8741,22 @@ snapshots:
pg-cloudflare@1.1.1: pg-cloudflare@1.1.1:
optional: true optional: true
pg-connection-string@2.7.0: {} pg-connection-string@2.7.0:
optional: true
pg-int8@1.0.1: {} pg-int8@1.0.1:
optional: true
pg-numeric@1.0.2: {} pg-numeric@1.0.2:
optional: true
pg-pool@3.8.0(pg@8.14.1): pg-pool@3.8.0(pg@8.14.1):
dependencies: dependencies:
pg: 8.14.1 pg: 8.14.1
optional: true
pg-protocol@1.8.0: {} pg-protocol@1.8.0:
optional: true
pg-types@2.2.0: pg-types@2.2.0:
dependencies: dependencies:
@ -8530,6 +8765,7 @@ snapshots:
postgres-bytea: 1.0.0 postgres-bytea: 1.0.0
postgres-date: 1.0.7 postgres-date: 1.0.7
postgres-interval: 1.2.0 postgres-interval: 1.2.0
optional: true
pg-types@4.0.2: pg-types@4.0.2:
dependencies: dependencies:
@ -8540,6 +8776,7 @@ snapshots:
postgres-date: 2.1.0 postgres-date: 2.1.0
postgres-interval: 3.0.0 postgres-interval: 3.0.0
postgres-range: 1.1.4 postgres-range: 1.1.4
optional: true
pg@8.14.1: pg@8.14.1:
dependencies: dependencies:
@ -8550,10 +8787,12 @@ snapshots:
pgpass: 1.0.5 pgpass: 1.0.5
optionalDependencies: optionalDependencies:
pg-cloudflare: 1.1.1 pg-cloudflare: 1.1.1
optional: true
pgpass@1.0.5: pgpass@1.0.5:
dependencies: dependencies:
split2: 4.2.0 split2: 4.2.0
optional: true
picocolors@1.1.1: {} picocolors@1.1.1: {}
@ -8563,6 +8802,14 @@ snapshots:
pify@2.3.0: {} pify@2.3.0: {}
pinia-plugin-persistedstate@4.7.1(@nuxt/kit@3.16.2(magicast@0.3.5))(@pinia/nuxt@0.11.0(magicast@0.3.5)(pinia@3.0.2(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3))))(pinia@3.0.2(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3))):
dependencies:
defu: 6.1.4
optionalDependencies:
'@nuxt/kit': 3.16.2(magicast@0.3.5)
'@pinia/nuxt': 0.11.0(magicast@0.3.5)(pinia@3.0.2(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3)))
pinia: 3.0.2(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3))
pinia@3.0.2(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3)): pinia@3.0.2(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3)):
dependencies: dependencies:
'@vue/devtools-api': 7.7.2 '@vue/devtools-api': 7.7.2
@ -8791,27 +9038,36 @@ snapshots:
picocolors: 1.1.1 picocolors: 1.1.1
source-map-js: 1.2.1 source-map-js: 1.2.1
postgres-array@2.0.0: {} postgres-array@2.0.0:
optional: true
postgres-array@3.0.4: {} postgres-array@3.0.4:
optional: true
postgres-bytea@1.0.0: {} postgres-bytea@1.0.0:
optional: true
postgres-bytea@3.0.0: postgres-bytea@3.0.0:
dependencies: dependencies:
obuf: 1.1.2 obuf: 1.1.2
optional: true
postgres-date@1.0.7: {} postgres-date@1.0.7:
optional: true
postgres-date@2.1.0: {} postgres-date@2.1.0:
optional: true
postgres-interval@1.2.0: postgres-interval@1.2.0:
dependencies: dependencies:
xtend: 4.0.2 xtend: 4.0.2
optional: true
postgres-interval@3.0.0: {} postgres-interval@3.0.0:
optional: true
postgres-range@1.1.4: {} postgres-range@1.1.4:
optional: true
prebuild-install@7.1.3: prebuild-install@7.1.3:
dependencies: dependencies:
@ -8839,6 +9095,8 @@ snapshots:
process@0.11.10: {} process@0.11.10: {}
promise-limit@2.7.0: {}
prompts@2.4.2: prompts@2.4.2:
dependencies: dependencies:
kleur: 3.0.3 kleur: 3.0.3
@ -9177,7 +9435,8 @@ snapshots:
speakingurl@14.0.1: {} speakingurl@14.0.1: {}
split2@4.2.0: {} split2@4.2.0:
optional: true
stable-hash@0.0.5: {} stable-hash@0.0.5: {}
@ -9590,7 +9849,7 @@ snapshots:
'@unrs/resolver-binding-win32-ia32-msvc': 1.5.0 '@unrs/resolver-binding-win32-ia32-msvc': 1.5.0
'@unrs/resolver-binding-win32-x64-msvc': 1.5.0 '@unrs/resolver-binding-win32-x64-msvc': 1.5.0
unstorage@1.15.0(db0@0.3.1(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1): unstorage@1.15.0(db0@0.3.1(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1)))(ioredis@5.6.1):
dependencies: dependencies:
anymatch: 3.1.3 anymatch: 3.1.3
chokidar: 4.0.3 chokidar: 4.0.3
@ -9601,7 +9860,7 @@ snapshots:
ofetch: 1.4.1 ofetch: 1.4.1
ufo: 1.6.1 ufo: 1.6.1
optionalDependencies: optionalDependencies:
db0: 0.3.1(drizzle-orm@0.42.0(@types/pg@8.11.13)(pg@8.14.1)) db0: 0.3.1(@libsql/client@0.15.15)(drizzle-orm@0.42.0(@libsql/client@0.15.15)(@types/pg@8.11.13)(pg@8.14.1))
ioredis: 5.6.1 ioredis: 5.6.1
untun@0.1.3: untun@0.1.3:
@ -9788,6 +10047,8 @@ snapshots:
optionalDependencies: optionalDependencies:
typescript: 5.8.3 typescript: 5.8.3
web-streams-polyfill@3.3.3: {}
webidl-conversions@3.0.1: {} webidl-conversions@3.0.1: {}
webpack-virtual-modules@0.6.2: {} webpack-virtual-modules@0.6.2: {}
@ -9831,7 +10092,8 @@ snapshots:
cssfilter: 0.0.10 cssfilter: 0.0.10
optional: true optional: true
xtend@4.0.2: {} xtend@4.0.2:
optional: true
y18n@5.0.8: {} y18n@5.0.8: {}

View file

@ -1,12 +1,8 @@
import 'dotenv/config'; import 'dotenv/config';
import { drizzle } from 'drizzle-orm/node-postgres'; import { drizzle } from 'drizzle-orm/libsql';
import { sql, eq, and } from 'drizzle-orm'; import { sql, eq, and } from 'drizzle-orm';
import arrayShuffle from 'array-shuffle'; import arrayShuffle from 'array-shuffle';
import { import { tasks_advanced, questions_advanced, categories_db } from '~/db/schema';
tasks_advanced,
questions_advanced,
categories_db,
} from '@/src/db/schema';
import type { AdvancedQuestion } from '~/types'; import type { AdvancedQuestion } from '~/types';
import categories from '~/categories'; import categories from '~/categories';

View file

@ -1,8 +1,8 @@
import 'dotenv/config'; import 'dotenv/config';
import { drizzle } from 'drizzle-orm/node-postgres'; import { drizzle } from 'drizzle-orm/libsql';
import { sql, eq, and } from 'drizzle-orm'; import { sql, eq, and } from 'drizzle-orm';
import arrayShuffle from 'array-shuffle'; import arrayShuffle from 'array-shuffle';
import { tasks, questions, categories_db } from '@/src/db/schema'; import { tasks, questions, categories_db } from '~/db/schema';
import type { BasicQuestion } from '~/types'; import type { BasicQuestion } from '~/types';
import categories from '~/categories'; import categories from '~/categories';

View file

@ -1,35 +0,0 @@
import { integer, pgTable, text, smallint, char } from 'drizzle-orm/pg-core';
export const tasks = pgTable('tasks', {
id: integer().notNull(),
correct_answer: text(),
media_url: text(),
weight: smallint(),
});
export const questions = pgTable('questions', {
task_id: integer(),
lang: char({ length: 2 }),
text: text(),
});
export const tasks_advanced = pgTable('tasks_advanced', {
id: integer().notNull(),
correct_answer: char({ length: 1 }),
media_url: text(),
weight: smallint(),
});
export const questions_advanced = pgTable('questions_advanced', {
task_id: integer(),
lang: char({ length: 2 }),
text: text(),
answer_a: text(),
answer_b: text(),
answer_c: text(),
});
export const categories_db = pgTable('categories', {
name: text(),
task_id: integer(),
});

View file

@ -1,43 +1,60 @@
import { defineStore } from 'pinia'; export const useBasicStore = defineStore('basicStore', {
state: () => ({
export const useExamStore = defineStore('exam-store', () => { basic: [] as ResultType[],
const category = ref(''); }),
const end = ref(false); actions: {
const result: Ref<ResultEndType> = ref({ async set(basic: ResultType[]) {
basic: [], this.basic = basic;
advanced: [], },
}); },
function resetExam() { persist: {
category.value = ''; storage: piniaPluginPersistedstate.localStorage(),
mildReset(); },
} });
function mildReset() {
end.value = false; export const useAdvancedStore = defineStore('advancedStore', {
result.value = { state: () => ({
basic: [], advanced: [] as ResultType[],
advanced: [], }),
}; actions: {
} async set(advanced: ResultType[]) {
function setEnd(value: boolean) { this.advanced = advanced;
end.value = value; },
return end.value; },
} persist: {
function setCategory(value: string) { storage: piniaPluginPersistedstate.localStorage(),
category.value = value; },
return category.value; });
}
function setResult(value: ResultEndType) { export const useExamStore = defineStore('examStore', {
result.value = value; state: () => ({
return result.value; category: '',
} end: false,
return { }),
category, actions: {
end, async setCategory(category: string) {
result, this.category = category;
resetExam, },
mildReset, async setEnd(end: boolean) {
setEnd, this.end = end;
setCategory, },
setResult, async setBasic(basic: ResultType[]) {
}; useBasicStore().set(basic);
},
async setAdvanced(advanced: ResultType[]) {
useAdvancedStore().set(advanced);
},
async mildReset() {
this.end = false;
this.setBasic([]);
this.setAdvanced([]);
},
async resetExam() {
this.category = '';
this.mildReset();
},
},
persist: {
storage: piniaPluginPersistedstate.cookies(),
},
}); });

View file

@ -12,13 +12,16 @@ export interface AdvancedQuestion extends BasicQuestion {
answer_c: string | null; answer_c: string | null;
} }
export interface ResultType<T> { export type Question = BasicQuestion | AdvancedQuestion | null | undefined;
question: T | undefined;
export interface ResultType {
question: Question;
chosen_answer: string; chosen_answer: string;
correct_answer: string | null;
chosen_is_correct: boolean | undefined; chosen_is_correct: boolean | undefined;
} }
export interface ResultEndType { export interface ResultEndType {
basic: ResultType<BasicQuestion>[]; basic: ResultType[];
advanced: ResultType<AdvancedQuestion>[]; advanced: ResultType[];
} }