diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts index 85729ef..7f5d9d4 100644 --- a/apps/api/src/index.ts +++ b/apps/api/src/index.ts @@ -1,4 +1,5 @@ import { Hono } from 'hono'; +import { cors } from 'hono/cors'; import { manifestRoute } from './routes/manifest.ts'; import { healthRoute } from './routes/health.ts'; @@ -8,6 +9,23 @@ import { reviewsRouter } from './routes/reviews.ts'; const app = new Hono(); +app.use( + '*', + cors({ + origin: (origin) => { + if (!origin) return origin; + // Dev: localhost-Ports erlaubt. Prod: explizite Whitelist. + if (/^https?:\/\/localhost(:\d+)?$/.test(origin)) return origin; + if (/^https?:\/\/127\.0\.0\.1(:\d+)?$/.test(origin)) return origin; + if (origin === 'https://cardecky.mana.how') return origin; + return null; + }, + allowHeaders: ['Content-Type', 'X-User-Id', 'Authorization', 'X-Service-Key'], + allowMethods: ['GET', 'POST', 'PATCH', 'DELETE', 'OPTIONS'], + credentials: true, + }) +); + app.route('/', healthRoute); app.route('/.well-known/mana-app.json', manifestRoute); app.route('/api/v1/decks', decksRouter()); diff --git a/apps/web/package.json b/apps/web/package.json index fe3766e..a41dbfa 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -15,14 +15,19 @@ "clean": "rm -rf .svelte-kit build .turbo" }, "dependencies": { - "@cards/domain": "workspace:*" + "@cards/domain": "workspace:*", + "dompurify": "^3.4.2", + "marked": "^18.0.3" }, "devDependencies": { "@sveltejs/adapter-node": "^5.2.0", "@sveltejs/kit": "^2.8.0", "@sveltejs/vite-plugin-svelte": "^4.0.0", + "@tailwindcss/vite": "^4.2.4", + "@types/dompurify": "^3.2.0", "svelte": "^5.0.0", "svelte-check": "^4.0.0", + "tailwindcss": "^4.2.4", "vite": "^5.4.0", "vitest": "^2.1.0" } diff --git a/apps/web/src/app.css b/apps/web/src/app.css new file mode 100644 index 0000000..e81a46b --- /dev/null +++ b/apps/web/src/app.css @@ -0,0 +1,41 @@ +@import 'tailwindcss'; + +@theme { + --color-bg: oklch(0.99 0.005 240); + --color-fg: oklch(0.20 0.02 240); + --color-muted: oklch(0.55 0.02 240); + --color-border: oklch(0.92 0.01 240); + --color-card: oklch(1 0 0); + --color-primary: oklch(0.55 0.15 250); + --color-primary-fg: oklch(1 0 0); + --color-success: oklch(0.6 0.15 145); + --color-warning: oklch(0.75 0.15 75); + --color-danger: oklch(0.55 0.18 25); + + --font-sans: + ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; +} + +@layer base { + html { + background-color: var(--color-bg); + color: var(--color-fg); + font-family: var(--font-sans); + } + body { + min-height: 100dvh; + } +} + +@media (prefers-color-scheme: dark) { + @theme { + --color-bg: oklch(0.18 0.02 240); + --color-fg: oklch(0.95 0.01 240); + --color-muted: oklch(0.65 0.02 240); + --color-border: oklch(0.30 0.02 240); + --color-card: oklch(0.22 0.02 240); + --color-primary: oklch(0.70 0.18 250); + --color-primary-fg: oklch(0.18 0.02 240); + } +} diff --git a/apps/web/src/lib/api/cards.ts b/apps/web/src/lib/api/cards.ts new file mode 100644 index 0000000..984ce0f --- /dev/null +++ b/apps/web/src/lib/api/cards.ts @@ -0,0 +1,23 @@ +import type { Card, CardCreate, CardUpdate } from '@cards/domain'; +import { api } from './client.ts'; + +export function listCards(deckId?: string) { + const qs = deckId ? `?deck_id=${encodeURIComponent(deckId)}` : ''; + return api<{ cards: Card[]; total: number }>(`/api/v1/cards${qs}`); +} + +export function getCard(id: string) { + return api(`/api/v1/cards/${id}`); +} + +export function createCard(input: CardCreate) { + return api('/api/v1/cards', { method: 'POST', body: input }); +} + +export function updateCard(id: string, patch: CardUpdate) { + return api(`/api/v1/cards/${id}`, { method: 'PATCH', body: patch }); +} + +export function deleteCard(id: string) { + return api<{ deleted: string }>(`/api/v1/cards/${id}`, { method: 'DELETE' }); +} diff --git a/apps/web/src/lib/api/client.ts b/apps/web/src/lib/api/client.ts new file mode 100644 index 0000000..eca6b67 --- /dev/null +++ b/apps/web/src/lib/api/client.ts @@ -0,0 +1,55 @@ +/** + * Cards-API-Client. Dünner Fetch-Wrapper, der `X-User-Id`-Header aus + * dem Dev-Auth-Stub setzt. Phase 2 ersetzt das durch ein Bearer-Token + * aus @mana/shared-auth. + */ + +import { devUser } from '$lib/auth/dev-stub.svelte.ts'; + +export const API_BASE = (() => { + if (typeof window !== 'undefined') { + return import.meta.env.PUBLIC_CARDS_API_URL ?? 'http://localhost:3081'; + } + return process.env.CARDS_API_URL ?? 'http://localhost:3081'; +})(); + +export class ApiError extends Error { + constructor( + readonly status: number, + readonly body: unknown, + message?: string + ) { + super(message ?? `cards-api ${status}`); + } +} + +type RequestOptions = { + method?: 'GET' | 'POST' | 'PATCH' | 'DELETE'; + body?: unknown; + signal?: AbortSignal; +}; + +export async function api(path: string, opts: RequestOptions = {}): Promise { + const headers: Record = { + 'Content-Type': 'application/json', + }; + if (devUser.id) { + headers['X-User-Id'] = devUser.id; + } + const res = await fetch(`${API_BASE}${path}`, { + method: opts.method ?? 'GET', + headers, + body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined, + signal: opts.signal, + }); + if (!res.ok) { + let body: unknown = null; + try { + body = await res.json(); + } catch { + body = await res.text(); + } + throw new ApiError(res.status, body); + } + return (await res.json()) as T; +} diff --git a/apps/web/src/lib/api/decks.ts b/apps/web/src/lib/api/decks.ts new file mode 100644 index 0000000..f692850 --- /dev/null +++ b/apps/web/src/lib/api/decks.ts @@ -0,0 +1,22 @@ +import type { Deck, DeckCreate, DeckUpdate } from '@cards/domain'; +import { api } from './client.ts'; + +export function listDecks() { + return api<{ decks: Deck[]; total: number }>('/api/v1/decks'); +} + +export function getDeck(id: string) { + return api(`/api/v1/decks/${id}`); +} + +export function createDeck(input: DeckCreate) { + return api('/api/v1/decks', { method: 'POST', body: input }); +} + +export function updateDeck(id: string, patch: DeckUpdate) { + return api(`/api/v1/decks/${id}`, { method: 'PATCH', body: patch }); +} + +export function deleteDeck(id: string) { + return api<{ deleted: string }>(`/api/v1/decks/${id}`, { method: 'DELETE' }); +} diff --git a/apps/web/src/lib/api/reviews.ts b/apps/web/src/lib/api/reviews.ts new file mode 100644 index 0000000..1321417 --- /dev/null +++ b/apps/web/src/lib/api/reviews.ts @@ -0,0 +1,23 @@ +import type { Card, Rating, Review } from '@cards/domain'; +import { api } from './client.ts'; + +export type DueReview = Review & { + card?: Pick; +}; + +export function listDueReviews(opts: { deckId?: string; limit?: number } = {}) { + const params = new URLSearchParams(); + if (opts.deckId) params.set('deck_id', opts.deckId); + if (opts.limit) params.set('limit', String(opts.limit)); + const qs = params.toString(); + return api<{ reviews: DueReview[]; total: number }>( + `/api/v1/reviews/due${qs ? `?${qs}` : ''}` + ); +} + +export function gradeReview(cardId: string, subIndex: number, rating: Rating) { + return api(`/api/v1/reviews/${cardId}/${subIndex}/grade`, { + method: 'POST', + body: { rating }, + }); +} diff --git a/apps/web/src/lib/auth/dev-stub.svelte.ts b/apps/web/src/lib/auth/dev-stub.svelte.ts new file mode 100644 index 0000000..abbb7c2 --- /dev/null +++ b/apps/web/src/lib/auth/dev-stub.svelte.ts @@ -0,0 +1,35 @@ +/** + * Dev-Auth-Stub. Phase 2 ersetzt diesen Layer durch echtes JWT- + * Handling via @mana/shared-auth gegen mana-auth. + * + * Für jetzt: User-ID lebt in sessionStorage und wird als + * `X-User-Id`-Header an cards-api geschickt. + */ + +class DevUser { + id = $state(null); + + constructor() { + if (typeof window !== 'undefined') { + this.id = sessionStorage.getItem('cards.dev.userId'); + } + } + + set(userId: string) { + const trimmed = userId.trim(); + if (!trimmed) return; + this.id = trimmed; + if (typeof window !== 'undefined') { + sessionStorage.setItem('cards.dev.userId', trimmed); + } + } + + clear() { + this.id = null; + if (typeof window !== 'undefined') { + sessionStorage.removeItem('cards.dev.userId'); + } + } +} + +export const devUser = new DevUser(); diff --git a/apps/web/src/lib/components/Header.svelte b/apps/web/src/lib/components/Header.svelte new file mode 100644 index 0000000..5aca0f5 --- /dev/null +++ b/apps/web/src/lib/components/Header.svelte @@ -0,0 +1,53 @@ + + +
+
+ + + C + + Cards + + + + +
+ {#if devUser.id} + {devUser.id} + + + {:else} + + {/if} +
+
+
diff --git a/apps/web/src/lib/components/ToastStack.svelte b/apps/web/src/lib/components/ToastStack.svelte new file mode 100644 index 0000000..d1abb28 --- /dev/null +++ b/apps/web/src/lib/components/ToastStack.svelte @@ -0,0 +1,25 @@ + + +{#if toasts.items.length > 0} +
+ {#each toasts.items as t (t.id)} +
+ {t.message} + +
+ {/each} +
+{/if} diff --git a/apps/web/src/lib/markdown.ts b/apps/web/src/lib/markdown.ts new file mode 100644 index 0000000..ff28f1f --- /dev/null +++ b/apps/web/src/lib/markdown.ts @@ -0,0 +1,22 @@ +import DOMPurify from 'dompurify'; +import { marked } from 'marked'; + +marked.setOptions({ + gfm: true, + breaks: true, +}); + +/** + * Markdown → HTML, sanitized via DOMPurify. + * Sicher gegen Stored-XSS aus User-Card-Inhalten. + * + * SSR-Hinweis: marked + DOMPurify müssen nur im Browser laufen + * (DOMPurify erwartet `window`). Aufrufer sind Card-Editor und + * Study-View, beide sind client-only. + */ +export function renderMarkdown(source: string): string { + if (!source) return ''; + const html = marked.parse(source, { async: false }) as string; + if (typeof window === 'undefined') return html; // SSR-Fallback (selten Pfad) + return DOMPurify.sanitize(html); +} diff --git a/apps/web/src/lib/stores/toasts.svelte.ts b/apps/web/src/lib/stores/toasts.svelte.ts new file mode 100644 index 0000000..a1e7bcf --- /dev/null +++ b/apps/web/src/lib/stores/toasts.svelte.ts @@ -0,0 +1,44 @@ +/** + * Toast-Notifications. Svelte-5-Runes-Pattern: ein Modul-State, + * dessen Mutationen reaktiv von Components beobachtet werden. + */ + +export type ToastKind = 'info' | 'success' | 'warning' | 'error'; + +export type Toast = { + id: string; + kind: ToastKind; + message: string; + expires_at: number; +}; + +class ToastStore { + items = $state([]); + private nextId = 1; + + push(kind: ToastKind, message: string, durationMs = 4000) { + const id = `t-${this.nextId++}`; + const t: Toast = { id, kind, message, expires_at: Date.now() + durationMs }; + this.items.push(t); + setTimeout(() => this.dismiss(id), durationMs); + } + + dismiss(id: string) { + this.items = this.items.filter((t) => t.id !== id); + } + + info(msg: string) { + this.push('info', msg); + } + success(msg: string) { + this.push('success', msg); + } + warning(msg: string) { + this.push('warning', msg); + } + error(msg: string) { + this.push('error', msg); + } +} + +export const toasts = new ToastStore(); diff --git a/apps/web/src/routes/+layout.svelte b/apps/web/src/routes/+layout.svelte index aa9bcde..1f72c6a 100644 --- a/apps/web/src/routes/+layout.svelte +++ b/apps/web/src/routes/+layout.svelte @@ -1,20 +1,15 @@ -
+
+ +
{@render children?.()}
- + diff --git a/apps/web/src/routes/+page.svelte b/apps/web/src/routes/+page.svelte index f718c14..eb4a266 100644 --- a/apps/web/src/routes/+page.svelte +++ b/apps/web/src/routes/+page.svelte @@ -1,16 +1,51 @@ -

Cards

-

- Karteikarten-App des Vereins mana e.V. - — Phase 0, Repo-Skelett. -

-

- Plan: - CARDS_GREENFIELD.md - -

+
+

Cards

+

+ Karteikarten-App des Vereins mana e.V. +

+ + {#if !devUser.id} +
+

Phase 0 — Dev-Login

+

+ Bevor mana-auth-Föderation steht (Phase 2), schaltet ein Dev-Stub den Login frei. + Trag eine User-ID ein (z.B. u-test-1). +

+
{ + e.preventDefault(); + const fd = new FormData(e.currentTarget as HTMLFormElement); + const id = String(fd.get('user_id') ?? '').trim(); + if (id) { + devUser.set(id); + goto('/decks'); + } + }} + > + + +
+
+ {/if} +
diff --git a/apps/web/src/routes/cards/new/+page.svelte b/apps/web/src/routes/cards/new/+page.svelte new file mode 100644 index 0000000..478a1e0 --- /dev/null +++ b/apps/web/src/routes/cards/new/+page.svelte @@ -0,0 +1,153 @@ + + +← Zurück +

Neue Karte

+ +
+
+ + + +
+ +
+
+ + {#if front.trim()} +
+
Vorschau
+
{@html frontHtml}
+
+ {/if} +
+ +
+ + {#if back.trim()} +
+
Vorschau
+
{@html backHtml}
+
+ {/if} +
+
+ +
+ + Abbrechen +
+
diff --git a/apps/web/src/routes/decks/+page.svelte b/apps/web/src/routes/decks/+page.svelte new file mode 100644 index 0000000..35004a5 --- /dev/null +++ b/apps/web/src/routes/decks/+page.svelte @@ -0,0 +1,105 @@ + + +
+

Decks

+ Neues Deck +
+ +{#if loading} +

Lade…

+{:else if error} +

Fehler: {error}

+{:else if decks.length === 0} +
+

Noch keine Decks.

+ Erstes Deck anlegen → +
+{:else} + +{/if} diff --git a/apps/web/src/routes/decks/[id]/+page.svelte b/apps/web/src/routes/decks/[id]/+page.svelte new file mode 100644 index 0000000..2ba9a8f --- /dev/null +++ b/apps/web/src/routes/decks/[id]/+page.svelte @@ -0,0 +1,146 @@ + + +{#if loading} +

Lade…

+{:else if error} +

Fehler: {error}

+{:else if deck} + ← Decks + +
+
+ {#if deck.color} + + {/if} +

{deck.name}

+
+
+ + + Karte + + {#if dueCount > 0} + + Lernen ({dueCount} fällig) + + {:else} + + {/if} +
+
+ + {#if deck.description} +

{deck.description}

+ {/if} + +
+ {cards.length} Karte{cards.length === 1 ? '' : 'n'} · {dueCount} fällig +
+ + {#if cards.length === 0} +
+

Noch keine Karten in diesem Deck.

+ Erste Karte anlegen → +
+ {:else} +
    + {#each cards as card (card.id)} +
  • +
    +
    + {card.type} +
    +

    + {card.fields.front ?? '(leer)'} + → {card.fields.back ?? '(leer)'} +

    +
    + +
  • + {/each} +
+ {/if} +{/if} diff --git a/apps/web/src/routes/decks/new/+page.svelte b/apps/web/src/routes/decks/new/+page.svelte new file mode 100644 index 0000000..13b88f8 --- /dev/null +++ b/apps/web/src/routes/decks/new/+page.svelte @@ -0,0 +1,81 @@ + + +
+ ← Zurück +

Neues Deck

+ +
+ + + + + + +
+ + Abbrechen +
+
+
diff --git a/apps/web/src/routes/study/+page.svelte b/apps/web/src/routes/study/+page.svelte new file mode 100644 index 0000000..eec479f --- /dev/null +++ b/apps/web/src/routes/study/+page.svelte @@ -0,0 +1,70 @@ + + +

Lernen

+ +{#if loading} +

Lade…

+{:else} +
    + {#each items as it (it.deck.id)} +
  • +
    + {#if it.deck.color} + + {/if} + {it.deck.name} + + {it.due} fällig + +
    + {#if it.due > 0} + + Starten + + {:else} + + {/if} +
  • + {/each} +
+{/if} diff --git a/apps/web/src/routes/study/[deckId]/+page.svelte b/apps/web/src/routes/study/[deckId]/+page.svelte new file mode 100644 index 0000000..aafdb49 --- /dev/null +++ b/apps/web/src/routes/study/[deckId]/+page.svelte @@ -0,0 +1,220 @@ + + +
+ ← Lernen +

{deckName}

+

+ {#if !loading && !isDone} + {queueIndex + 1} / {queue.length} + {/if} +

+ + {#if loading} +

Lade Sitzung…

+ {:else if queue.length === 0} +
+

Keine Karten fällig in diesem Deck. 🎉

+ + Zurück zum Deck → + +
+ {:else if isDone} +
+

Sitzung abgeschlossen

+

+ {stats.reviewed} Reviews erledigt · {stats.again}× nochmal +

+ +
+ {:else} +
+
{@html promptHtml}
+ + {#if revealed} +
+
{@html answerHtml}
+ {/if} +
+ + {#if !revealed} +
+ +
+ {:else} +
+ + + + +
+ {/if} + +

+ Hotkeys: Space/Enter = aufdecken & gut · 14 = bewerten +

+ {/if} +
diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts index 42d7f26..59aad41 100644 --- a/apps/web/vite.config.ts +++ b/apps/web/vite.config.ts @@ -1,8 +1,9 @@ import { sveltekit } from '@sveltejs/kit/vite'; +import tailwindcss from '@tailwindcss/vite'; import { defineConfig } from 'vite'; export default defineConfig({ - plugins: [sveltekit()], + plugins: [tailwindcss(), sveltekit()], server: { port: Number(process.env.CARDS_WEB_PORT ?? 3082), host: true, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3d0d683..7ace017 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,35 +53,50 @@ importers: version: 0.30.6 vitest: specifier: ^2.1.0 - version: 2.1.9(@types/node@22.19.18) + version: 2.1.9(@types/node@22.19.18)(lightningcss@1.32.0) apps/web: dependencies: '@cards/domain': specifier: workspace:* version: link:../../packages/cards-domain + dompurify: + specifier: ^3.4.2 + version: 3.4.2 + marked: + specifier: ^18.0.3 + version: 18.0.3 devDependencies: '@sveltejs/adapter-node': specifier: ^5.2.0 - version: 5.5.4(@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)))(svelte@5.55.5)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.18))) + version: 5.5.4(@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)))(svelte@5.55.5)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0))) '@sveltejs/kit': specifier: ^2.8.0 - version: 2.59.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)))(svelte@5.55.5)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.18)) + version: 2.59.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)))(svelte@5.55.5)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)) '@sveltejs/vite-plugin-svelte': specifier: ^4.0.0 - version: 4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)) + version: 4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)) + '@tailwindcss/vite': + specifier: ^4.2.4 + version: 4.2.4(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)) + '@types/dompurify': + specifier: ^3.2.0 + version: 3.2.0 svelte: specifier: ^5.0.0 version: 5.55.5 svelte-check: specifier: ^4.0.0 version: 4.4.8(picomatch@4.0.4)(svelte@5.55.5)(typescript@5.9.3) + tailwindcss: + specifier: ^4.2.4 + version: 4.2.4 vite: specifier: ^5.4.0 - version: 5.4.21(@types/node@22.19.18) + version: 5.4.21(@types/node@22.19.18)(lightningcss@1.32.0) vitest: specifier: ^2.1.0 - version: 2.1.9(@types/node@22.19.18) + version: 2.1.9(@types/node@22.19.18)(lightningcss@1.32.0) packages/cards-domain: dependencies: @@ -94,7 +109,7 @@ importers: devDependencies: vitest: specifier: ^2.1.0 - version: 2.1.9(@types/node@22.19.18) + version: 2.1.9(@types/node@22.19.18)(lightningcss@1.32.0) packages: @@ -744,6 +759,96 @@ packages: svelte: ^5.0.0-next.96 || ^5.0.0 vite: ^5.0.0 + '@tailwindcss/node@4.2.4': + resolution: {integrity: sha512-Ai7+yQPxz3ddrDQzFfBKdHEVBg0w3Zl83jnjuwxnZOsnH9pGn93QHQtpU0p/8rYWxvbFZHneni6p1BSLK4DkGA==} + + '@tailwindcss/oxide-android-arm64@4.2.4': + resolution: {integrity: sha512-e7MOr1SAn9U8KlZzPi1ZXGZHeC5anY36qjNwmZv9pOJ8E4Q6jmD1vyEHkQFmNOIN7twGPEMXRHmitN4zCMN03g==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.2.4': + resolution: {integrity: sha512-tSC/Kbqpz/5/o/C2sG7QvOxAKqyd10bq+ypZNf+9Fi2TvbVbv1zNpcEptcsU7DPROaSbVgUXmrzKhurFvo5eDg==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.2.4': + resolution: {integrity: sha512-yPyUXn3yO/ufR6+Kzv0t4fCg2qNr90jxXc5QqBpjlPNd0NqyDXcmQb/6weunH/MEDXW5dhyEi+agTDiqa3WsGg==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.2.4': + resolution: {integrity: sha512-BoMIB4vMQtZsXdGLVc2z+P9DbETkiopogfWZKbWwM8b/1Vinbs4YcUwo+kM/KeLkX3Ygrf4/PsRndKaYhS8Eiw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.4': + resolution: {integrity: sha512-7pIHBLTHYRAlS7V22JNuTh33yLH4VElwKtB3bwchK/UaKUPpQ0lPQiOWcbm4V3WP2I6fNIJ23vABIvoy2izdwA==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.2.4': + resolution: {integrity: sha512-+E4wxJ0ZGOzSH325reXTWB48l42i93kQqMvDyz5gqfRzRZ7faNhnmvlV4EPGJU3QJM/3Ab5jhJ5pCRUsKn6OQw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.2.4': + resolution: {integrity: sha512-bBADEGAbo4ASnppIziaQJelekCxdMaxisrk+fB7Thit72IBnALp9K6ffA2G4ruj90G9XRS2VQ6q2bCKbfFV82g==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.2.4': + resolution: {integrity: sha512-7Mx25E4WTfnht0TVRTyC00j3i0M+EeFe7wguMDTlX4mRxafznw0CA8WJkFjWYH5BlgELd1kSjuU2JiPnNZbJDA==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.2.4': + resolution: {integrity: sha512-2wwJRF7nyhOR0hhHoChc04xngV3iS+akccHTGtz965FwF0up4b2lOdo6kI1EbDaEXKgvcrFBYcYQQ/rrnWFVfA==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.2.4': + resolution: {integrity: sha512-FQsqApeor8Fo6gUEklzmaa9994orJZZDBAlQpK2Mq+DslRKFJeD6AjHpBQ0kZFQohVr8o85PPh8eOy86VlSCmw==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.2.4': + resolution: {integrity: sha512-L9BXqxC4ToVgwMFqj3pmZRqyHEztulpUJzCxUtLjobMCzTPsGt1Fa9enKbOpY2iIyVtaHNeNvAK8ERP/64sqGQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.2.4': + resolution: {integrity: sha512-ESlKG0EpVJQwRjXDDa9rLvhEAh0mhP1sF7sap9dNZT0yyl9SAG6T7gdP09EH0vIv0UNTlo6jPWyujD6559fZvw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.2.4': + resolution: {integrity: sha512-9El/iI069DKDSXwTvB9J4BwdO5JhRrOweGaK25taBAvBXyXqJAX+Jqdvs8r8gKpsI/1m0LeJLyQYTf/WLrBT1Q==} + engines: {node: '>= 20'} + + '@tailwindcss/vite@4.2.4': + resolution: {integrity: sha512-pCvohwOCspk3ZFn6eJzrrX3g4n2JY73H6MmYC87XfGPyTty4YsCjYTMArRZm/zOI8dIt3+EcrLHAFPe5A4bgtw==} + peerDependencies: + vite: ^5.2.0 || ^6 || ^7 || ^8 + '@turbo/darwin-64@2.9.10': resolution: {integrity: sha512-5BVJnes8/zMPydF8ktfBBWqCCpUeWVxwZ6avYHRqLzk2PuTAsLz0TlaKdDe1nk1cz3/o0c+7CEf6zqNXdB2N7Q==} cpu: [x64] @@ -780,6 +885,10 @@ packages: '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + '@types/dompurify@3.2.0': + resolution: {integrity: sha512-Fgg31wv9QbLDA0SpTOXO3MaxySc4DKGLi8sna4/Utjo4r3ZRPdCt4UQee8BWr+Q5z21yifghREPJGYaEOEIACg==} + deprecated: This is a stub types definition. dompurify provides its own type definitions, so you do not need this installed. + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} @@ -891,9 +1000,16 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + devalue@5.8.0: resolution: {integrity: sha512-2zA9pFEsnp7vWBZbXF5JAgAq0fsUIt/1XPbRiAmRV3lp/2C3upzH+sADiyy66aFCihoLEsrQHxNM5w1gIDfsBg==} + dompurify@3.4.2: + resolution: {integrity: sha512-lHeS9SA/IKeIFFyYciHBr2n0v1VMPlSj843HdLOwjb2OxNwdq9Xykxqhk+FE42MzAdHvInbAolSE4mhahPpjXA==} + drizzle-kit@0.30.6: resolution: {integrity: sha512-U4wWit0fyZuGuP7iNmRleQyK2V8wCuv57vf5l3MnG4z4fzNTjY/U13M8owyQ5RavqvqxBifWORaR3wIUzlN64g==} hasBin: true @@ -990,6 +1106,10 @@ packages: sqlite3: optional: true + enhanced-resolve@5.21.2: + resolution: {integrity: sha512-xe9vQb5kReirPUxgQrXA3ihgbCqssmTiM7cOZ+Gzu+VeGWgpV98lLZvp0dl4yriyAePcewxGUs9UpKD8PET9KQ==} + engines: {node: '>=10.13.0'} + env-paths@3.0.0: resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1067,6 +1187,9 @@ packages: get-tsconfig@4.14.0: resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==} + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + hasown@2.0.3: resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==} engines: {node: '>= 0.4'} @@ -1092,10 +1215,84 @@ packages: resolution: {integrity: sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==} engines: {node: '>=18'} + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + kleur@4.1.5: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + locate-character@3.0.0: resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} @@ -1105,6 +1302,11 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + marked@18.0.3: + resolution: {integrity: sha512-7VT90JOkDeaRWpfjOReRGPEKn0ecdARBkDGL+tT1wZY0efPPqkUxLUSmzy/C7TIylQYJC9STISEsCHrqb/7VIA==} + engines: {node: '>= 20'} + hasBin: true + mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -1230,6 +1432,13 @@ packages: resolution: {integrity: sha512-2uCs/LZ9us+AktdzYJM8OcxQ8qnPS1kpaO7syGT/MgO+6Qr1Ybl+TqPq+97u7PHqmmMlye5ZkoyXONy5mjjAbw==} engines: {node: '>=18'} + tailwindcss@4.2.4: + resolution: {integrity: sha512-HhKppgO81FQof5m6TEnuBWCZGgfRAWbaeOaGT00KOy/Pf/j6oUihdvBpA7ltCeAvZpFhW3j0PTclkxsd4IXYDA==} + + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -1716,19 +1925,19 @@ snapshots: dependencies: acorn: 8.16.0 - '@sveltejs/adapter-node@5.5.4(@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)))(svelte@5.55.5)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.18)))': + '@sveltejs/adapter-node@5.5.4(@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)))(svelte@5.55.5)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)))': dependencies: '@rollup/plugin-commonjs': 29.0.2(rollup@4.60.3) '@rollup/plugin-json': 6.1.0(rollup@4.60.3) '@rollup/plugin-node-resolve': 16.0.3(rollup@4.60.3) - '@sveltejs/kit': 2.59.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)))(svelte@5.55.5)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.18)) + '@sveltejs/kit': 2.59.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)))(svelte@5.55.5)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)) rollup: 4.60.3 - '@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)))(svelte@5.55.5)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.18))': + '@sveltejs/kit@2.59.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)))(svelte@5.55.5)(typescript@5.9.3)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0))': dependencies: '@standard-schema/spec': 1.1.0 '@sveltejs/acorn-typescript': 1.0.9(acorn@8.16.0) - '@sveltejs/vite-plugin-svelte': 4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)) + '@sveltejs/vite-plugin-svelte': 4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)) '@types/cookie': 0.6.0 acorn: 8.16.0 cookie: 0.6.0 @@ -1740,32 +1949,100 @@ snapshots: set-cookie-parser: 3.1.0 sirv: 3.0.2 svelte: 5.55.5 - vite: 5.4.21(@types/node@22.19.18) + vite: 5.4.21(@types/node@22.19.18)(lightningcss@1.32.0) optionalDependencies: typescript: 5.9.3 - '@sveltejs/vite-plugin-svelte-inspector@3.0.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)))(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18))': + '@sveltejs/vite-plugin-svelte-inspector@3.0.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)))(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)) + '@sveltejs/vite-plugin-svelte': 4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)) debug: 4.4.3 svelte: 5.55.5 - vite: 5.4.21(@types/node@22.19.18) + vite: 5.4.21(@types/node@22.19.18)(lightningcss@1.32.0) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18))': + '@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 3.0.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)))(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)) + '@sveltejs/vite-plugin-svelte-inspector': 3.0.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)))(svelte@5.55.5)(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)) debug: 4.4.3 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.21 svelte: 5.55.5 - vite: 5.4.21(@types/node@22.19.18) - vitefu: 1.1.3(vite@5.4.21(@types/node@22.19.18)) + vite: 5.4.21(@types/node@22.19.18)(lightningcss@1.32.0) + vitefu: 1.1.3(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)) transitivePeerDependencies: - supports-color + '@tailwindcss/node@4.2.4': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.21.2 + jiti: 2.7.0 + lightningcss: 1.32.0 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.2.4 + + '@tailwindcss/oxide-android-arm64@4.2.4': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.2.4': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.2.4': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.2.4': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.4': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.2.4': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.2.4': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.2.4': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.2.4': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.2.4': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.2.4': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.2.4': + optional: true + + '@tailwindcss/oxide@4.2.4': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.2.4 + '@tailwindcss/oxide-darwin-arm64': 4.2.4 + '@tailwindcss/oxide-darwin-x64': 4.2.4 + '@tailwindcss/oxide-freebsd-x64': 4.2.4 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.4 + '@tailwindcss/oxide-linux-arm64-gnu': 4.2.4 + '@tailwindcss/oxide-linux-arm64-musl': 4.2.4 + '@tailwindcss/oxide-linux-x64-gnu': 4.2.4 + '@tailwindcss/oxide-linux-x64-musl': 4.2.4 + '@tailwindcss/oxide-wasm32-wasi': 4.2.4 + '@tailwindcss/oxide-win32-arm64-msvc': 4.2.4 + '@tailwindcss/oxide-win32-x64-msvc': 4.2.4 + + '@tailwindcss/vite@4.2.4(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0))': + dependencies: + '@tailwindcss/node': 4.2.4 + '@tailwindcss/oxide': 4.2.4 + tailwindcss: 4.2.4 + vite: 5.4.21(@types/node@22.19.18)(lightningcss@1.32.0) + '@turbo/darwin-64@2.9.10': optional: true @@ -1790,6 +2067,10 @@ snapshots: '@types/cookie@0.6.0': {} + '@types/dompurify@3.2.0': + dependencies: + dompurify: 3.4.2 + '@types/estree@1.0.8': {} '@types/estree@1.0.9': {} @@ -1809,13 +2090,13 @@ snapshots: chai: 5.3.3 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.9(vite@5.4.21(@types/node@22.19.18))': + '@vitest/mocker@2.1.9(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0))': dependencies: '@vitest/spy': 2.1.9 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 5.4.21(@types/node@22.19.18) + vite: 5.4.21(@types/node@22.19.18)(lightningcss@1.32.0) '@vitest/pretty-format@2.1.9': dependencies: @@ -1886,8 +2167,14 @@ snapshots: deepmerge@4.3.1: {} + detect-libc@2.1.2: {} + devalue@5.8.0: {} + dompurify@3.4.2: + optionalDependencies: + '@types/trusted-types': 2.0.7 + drizzle-kit@0.30.6: dependencies: '@drizzle-team/brocli': 0.10.2 @@ -1903,6 +2190,11 @@ snapshots: bun-types: 1.3.13 postgres: 3.4.9 + enhanced-resolve@5.21.2: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + env-paths@3.0.0: {} es-errors@1.3.0: {} @@ -2031,6 +2323,8 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 + graceful-fs@4.2.11: {} + hasown@2.0.3: dependencies: function-bind: 1.1.2 @@ -2053,8 +2347,59 @@ snapshots: isexe@3.1.5: {} + jiti@2.7.0: {} + kleur@4.1.5: {} + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + locate-character@3.0.0: {} loupe@3.2.1: {} @@ -2063,6 +2408,8 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + marked@18.0.3: {} + mri@1.2.0: {} mrmime@2.0.1: {} @@ -2204,6 +2551,10 @@ snapshots: transitivePeerDependencies: - '@typescript-eslint/types' + tailwindcss@4.2.4: {} + + tapable@2.3.3: {} + tinybench@2.9.0: {} tinyexec@0.3.2: {} @@ -2231,13 +2582,13 @@ snapshots: undici-types@6.21.0: {} - vite-node@2.1.9(@types/node@22.19.18): + vite-node@2.1.9(@types/node@22.19.18)(lightningcss@1.32.0): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 1.1.2 - vite: 5.4.21(@types/node@22.19.18) + vite: 5.4.21(@types/node@22.19.18)(lightningcss@1.32.0) transitivePeerDependencies: - '@types/node' - less @@ -2249,7 +2600,7 @@ snapshots: - supports-color - terser - vite@5.4.21(@types/node@22.19.18): + vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0): dependencies: esbuild: 0.21.5 postcss: 8.5.14 @@ -2257,15 +2608,16 @@ snapshots: optionalDependencies: '@types/node': 22.19.18 fsevents: 2.3.3 + lightningcss: 1.32.0 - vitefu@1.1.3(vite@5.4.21(@types/node@22.19.18)): + vitefu@1.1.3(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)): optionalDependencies: - vite: 5.4.21(@types/node@22.19.18) + vite: 5.4.21(@types/node@22.19.18)(lightningcss@1.32.0) - vitest@2.1.9(@types/node@22.19.18): + vitest@2.1.9(@types/node@22.19.18)(lightningcss@1.32.0): dependencies: '@vitest/expect': 2.1.9 - '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@22.19.18)) + '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@22.19.18)(lightningcss@1.32.0)) '@vitest/pretty-format': 2.1.9 '@vitest/runner': 2.1.9 '@vitest/snapshot': 2.1.9 @@ -2281,8 +2633,8 @@ snapshots: tinyexec: 0.3.2 tinypool: 1.1.1 tinyrainbow: 1.2.0 - vite: 5.4.21(@types/node@22.19.18) - vite-node: 2.1.9(@types/node@22.19.18) + vite: 5.4.21(@types/node@22.19.18)(lightningcss@1.32.0) + vite-node: 2.1.9(@types/node@22.19.18)(lightningcss@1.32.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.19.18