├── .npmrc ├── .env.example ├── .prettierignore ├── src ├── routes │ ├── login │ │ ├── +page.svelte │ │ ├── +page.server.ts │ │ └── google │ │ │ ├── +server.ts │ │ │ └── callback │ │ │ └── +server.ts │ ├── +layout.svelte │ ├── +page.svelte │ └── +page.server.ts ├── lib │ └── server │ │ ├── oauth.ts │ │ ├── db.ts │ │ ├── user.ts │ │ ├── rate-limit.ts │ │ └── session.ts ├── app.html ├── app.d.ts └── hooks.server.ts ├── vite.config.ts ├── .prettierrc ├── .gitignore ├── setup.sql ├── README.md ├── LICENSE ├── tsconfig.json ├── svelte.config.js ├── package.json └── pnpm-lock.yaml /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | GOOGLE_CLIENT_ID="" 2 | GOOGLE_CLIENT_SECRET="" -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Package Managers 2 | package-lock.json 3 | pnpm-lock.yaml 4 | yarn.lock 5 | -------------------------------------------------------------------------------- /src/routes/login/+page.svelte: -------------------------------------------------------------------------------- 1 |

Sign in

2 | Sign in with Google 3 | -------------------------------------------------------------------------------- /src/routes/+layout.svelte: -------------------------------------------------------------------------------- 1 | 2 | Google OAuth example in SvelteKit 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from "@sveltejs/kit/vite"; 2 | import { defineConfig } from "vite"; 3 | 4 | export default defineConfig({ 5 | plugins: [sveltekit()] 6 | }); 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "trailingComma": "none", 4 | "printWidth": 120, 5 | "plugins": ["prettier-plugin-svelte"], 6 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] 7 | } 8 | -------------------------------------------------------------------------------- /src/lib/server/oauth.ts: -------------------------------------------------------------------------------- 1 | import { Google } from "arctic"; 2 | import { GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET } from "$env/static/private"; 3 | 4 | export const google = new Google(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, "http://localhost:5173/login/google/callback"); 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | # Output 4 | .output 5 | .vercel 6 | /.svelte-kit 7 | /build 8 | 9 | # OS 10 | .DS_Store 11 | Thumbs.db 12 | 13 | # Env 14 | .env 15 | .env.* 16 | !.env.example 17 | !.env.test 18 | 19 | # Vite 20 | vite.config.js.timestamp-* 21 | vite.config.ts.timestamp-* 22 | 23 | sqlite.db -------------------------------------------------------------------------------- /src/routes/login/+page.server.ts: -------------------------------------------------------------------------------- 1 | import { redirect } from "@sveltejs/kit"; 2 | 3 | import type { RequestEvent } from "./$types"; 4 | 5 | export async function load(event: RequestEvent) { 6 | if (event.locals.session !== null && event.locals.user !== null) { 7 | return redirect(302, "/"); 8 | } 9 | return {}; 10 | } 11 | -------------------------------------------------------------------------------- /src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 |

Hi, {data.user.name}!

10 | profile 11 |

Email: {data.user.email}

12 |
13 | 14 |
15 | -------------------------------------------------------------------------------- /setup.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE user ( 2 | id INTEGER NOT NULL PRIMARY KEY, 3 | google_id TEXT NOT NULL UNIQUE, 4 | email TEXT NOT NULL UNIQUE, 5 | name TEXT NOT NULL, 6 | picture TEXT NOT NULL 7 | ); 8 | 9 | CREATE INDEX google_id_index ON user(google_id); 10 | 11 | CREATE TABLE session ( 12 | id TEXT NOT NULL PRIMARY KEY, 13 | user_id INTEGER NOT NULL REFERENCES user(id), 14 | expires_at INTEGER NOT NULL 15 | ); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Google OAuth example in SvelteKit 2 | 3 | Uses SQLite. Rate limiting is implemented using JavaScript `Map`. 4 | 5 | ## Initialize project 6 | 7 | Register an OAuth client on the Google API Console. Paste the client ID and secret to a `.env` file. 8 | 9 | ```bash 10 | GOOGLE_CLIENT_ID="" 11 | GOOGLE_CLIENT_SECRET=" 12 | ``` 13 | 14 | Create `sqlite.db` and run `setup.sql`. 15 | 16 | ``` 17 | sqlite3 sqlite.db 18 | ``` 19 | 20 | Run the application: 21 | 22 | ``` 23 | pnpm dev 24 | ``` 25 | -------------------------------------------------------------------------------- /src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | // for information about these interfaces 3 | import type { User } from "$lib/server/user"; 4 | import type { Session } from "$lib/server/session"; 5 | 6 | declare global { 7 | namespace App { 8 | // interface Error {} 9 | interface Locals { 10 | user: User | null; 11 | session: Session | null; 12 | } 13 | // interface PageData {} 14 | // interface PageState {} 15 | // interface Platform {} 16 | } 17 | } 18 | 19 | export {}; 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 pilcrowOnPaper and contributors 2 | 3 | Permission to use, copy, modify, and/or distribute this software for 4 | any purpose with or without fee is hereby granted. 5 | 6 | THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL 7 | WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 8 | OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE 9 | FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY 10 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 11 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 12 | OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true, 12 | "moduleResolution": "bundler" 13 | } 14 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 15 | // except $lib which is handled by https://kit.svelte.dev/docs/configuration#files 16 | // 17 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 18 | // from the referenced tsconfig.json - TypeScript does not merge them in 19 | } 20 | -------------------------------------------------------------------------------- /svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from "@sveltejs/adapter-auto"; 2 | import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | // Consult https://kit.svelte.dev/docs/integrations#preprocessors 7 | // for more information about preprocessors 8 | preprocess: vitePreprocess(), 9 | 10 | kit: { 11 | // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. 12 | // If your environment is not supported, or you settled on a specific environment, switch out the adapter. 13 | // See https://kit.svelte.dev/docs/adapters for more information about adapters. 14 | adapter: adapter() 15 | } 16 | }; 17 | 18 | export default config; 19 | -------------------------------------------------------------------------------- /src/routes/+page.server.ts: -------------------------------------------------------------------------------- 1 | import { fail, redirect } from "@sveltejs/kit"; 2 | import { deleteSessionTokenCookie, invalidateSession } from "$lib/server/session"; 3 | 4 | import type { Actions, RequestEvent } from "./$types"; 5 | 6 | export async function load(event: RequestEvent) { 7 | if (event.locals.session === null || event.locals.user === null) { 8 | return redirect(302, "/login"); 9 | } 10 | return { 11 | user: event.locals.user 12 | }; 13 | } 14 | 15 | export const actions: Actions = { 16 | default: action 17 | }; 18 | 19 | async function action(event: RequestEvent) { 20 | if (event.locals.session === null) { 21 | return fail(401); 22 | } 23 | invalidateSession(event.locals.session.id); 24 | deleteSessionTokenCookie(event); 25 | return redirect(302, "/login"); 26 | } 27 | -------------------------------------------------------------------------------- /src/lib/server/db.ts: -------------------------------------------------------------------------------- 1 | import sqlite3 from "better-sqlite3"; 2 | import { SyncDatabase } from "@pilcrowjs/db-query"; 3 | 4 | import type { SyncAdapter } from "@pilcrowjs/db-query"; 5 | 6 | const sqlite = sqlite3("sqlite.db"); 7 | 8 | const adapter: SyncAdapter = { 9 | query: (statement: string, params: unknown[]): unknown[][] => { 10 | const result = sqlite 11 | .prepare(statement) 12 | .raw() 13 | .all(...params); 14 | return result as unknown[][]; 15 | }, 16 | execute: (statement: string, params: unknown[]): sqlite3.RunResult => { 17 | const result = sqlite.prepare(statement).run(...params); 18 | return result; 19 | } 20 | }; 21 | 22 | class Database extends SyncDatabase { 23 | public inTransaction(): boolean { 24 | return sqlite.inTransaction; 25 | } 26 | } 27 | 28 | export const db = new Database(adapter); 29 | -------------------------------------------------------------------------------- /src/routes/login/google/+server.ts: -------------------------------------------------------------------------------- 1 | import { google } from "$lib/server/oauth"; 2 | import { generateCodeVerifier, generateState } from "arctic"; 3 | 4 | import type { RequestEvent } from "./$types"; 5 | 6 | export function GET(event: RequestEvent): Response { 7 | const state = generateState(); 8 | const codeVerifier = generateCodeVerifier(); 9 | const url = google.createAuthorizationURL(state, codeVerifier, ["openid", "profile", "email"]); 10 | 11 | event.cookies.set("google_oauth_state", state, { 12 | httpOnly: true, 13 | maxAge: 60 * 10, 14 | secure: import.meta.env.PROD, 15 | path: "/", 16 | sameSite: "lax" 17 | }); 18 | event.cookies.set("google_code_verifier", codeVerifier, { 19 | httpOnly: true, 20 | maxAge: 60 * 10, 21 | secure: import.meta.env.PROD, 22 | path: "/", 23 | sameSite: "lax" 24 | }); 25 | 26 | return new Response(null, { 27 | status: 302, 28 | headers: { 29 | Location: url.toString() 30 | } 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /src/lib/server/user.ts: -------------------------------------------------------------------------------- 1 | import { db } from "./db"; 2 | 3 | export function createUser(googleId: string, email: string, name: string, picture: string): User { 4 | const row = db.queryOne("INSERT INTO user (google_id, email, name, picture) VALUES (?, ?, ?, ?) RETURNING user.id", [ 5 | googleId, 6 | email, 7 | name, 8 | picture 9 | ]); 10 | if (row === null) { 11 | throw new Error("Unexpected error"); 12 | } 13 | const user: User = { 14 | id: row.number(0), 15 | googleId, 16 | email, 17 | name, 18 | picture 19 | }; 20 | return user; 21 | } 22 | 23 | export function getUserFromGoogleId(googleId: string): User | null { 24 | const row = db.queryOne("SELECT id, google_id, email, name, picture FROM user WHERE google_id = ?", [googleId]); 25 | if (row === null) { 26 | return null; 27 | } 28 | const user: User = { 29 | id: row.number(0), 30 | googleId: row.string(1), 31 | email: row.string(2), 32 | name: row.string(3), 33 | picture: row.string(4) 34 | }; 35 | return user; 36 | } 37 | 38 | export interface User { 39 | id: number; 40 | email: string; 41 | googleId: string; 42 | name: string; 43 | picture: string; 44 | } 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-sveltekit-google-oauth", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite dev", 7 | "build": "vite build", 8 | "preview": "vite preview", 9 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 10 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 11 | "lint": "prettier --check .", 12 | "format": "prettier --write ." 13 | }, 14 | "devDependencies": { 15 | "@sveltejs/adapter-auto": "^3.0.0", 16 | "@sveltejs/kit": "^2.0.0", 17 | "@sveltejs/vite-plugin-svelte": "^3.0.0", 18 | "@types/better-sqlite3": "^7.6.11", 19 | "prettier": "^3.1.1", 20 | "prettier-plugin-svelte": "^3.1.2", 21 | "svelte": "^4.2.7", 22 | "svelte-check": "^4.0.0", 23 | "typescript": "^5.0.0", 24 | "vite": "^5.0.3" 25 | }, 26 | "type": "module", 27 | "dependencies": { 28 | "@oslojs/binary": "^1.0.0", 29 | "@oslojs/crypto": "^1.0.1", 30 | "@oslojs/encoding": "^1.1.0", 31 | "@pilcrowjs/db-query": "^0.0.2", 32 | "@pilcrowjs/object-parser": "^0.0.4", 33 | "arctic": "2.0.0-next.9", 34 | "better-sqlite3": "^11.3.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/hooks.server.ts: -------------------------------------------------------------------------------- 1 | import { TokenBucket } from "$lib/server/rate-limit"; 2 | import { validateSessionToken, setSessionTokenCookie, deleteSessionTokenCookie } from "$lib/server/session"; 3 | import { sequence } from "@sveltejs/kit/hooks"; 4 | 5 | import type { Handle } from "@sveltejs/kit"; 6 | 7 | const bucket = new TokenBucket(100, 1); 8 | 9 | const rateLimitHandle: Handle = async ({ event, resolve }) => { 10 | // Note: Assumes X-Forwarded-For will always be defined. 11 | const clientIP = event.request.headers.get("X-Forwarded-For"); 12 | if (clientIP === null) { 13 | return resolve(event); 14 | } 15 | let cost: number; 16 | if (event.request.method === "GET" || event.request.method === "OPTIONS") { 17 | cost = 1; 18 | } else { 19 | cost = 3; 20 | } 21 | if (!bucket.consume(clientIP, cost)) { 22 | return new Response("Too many requests", { 23 | status: 429 24 | }); 25 | } 26 | return resolve(event); 27 | }; 28 | 29 | const authHandle: Handle = async ({ event, resolve }) => { 30 | const token = event.cookies.get("session") ?? null; 31 | if (token === null) { 32 | event.locals.user = null; 33 | event.locals.session = null; 34 | return resolve(event); 35 | } 36 | 37 | const { session, user } = validateSessionToken(token); 38 | if (session !== null) { 39 | setSessionTokenCookie(event, token, session.expiresAt); 40 | } else { 41 | deleteSessionTokenCookie(event); 42 | } 43 | 44 | event.locals.session = session; 45 | event.locals.user = user; 46 | return resolve(event); 47 | }; 48 | 49 | export const handle = sequence(rateLimitHandle, authHandle); 50 | -------------------------------------------------------------------------------- /src/lib/server/rate-limit.ts: -------------------------------------------------------------------------------- 1 | export class TokenBucket<_Key> { 2 | public max: number; 3 | public refillIntervalSeconds: number; 4 | 5 | constructor(max: number, refillIntervalSeconds: number) { 6 | this.max = max; 7 | this.refillIntervalSeconds = refillIntervalSeconds; 8 | } 9 | 10 | private storage = new Map<_Key, Bucket>(); 11 | 12 | public check(key: _Key, cost: number): boolean { 13 | const bucket = this.storage.get(key) ?? null; 14 | if (bucket === null) { 15 | return true; 16 | } 17 | const now = Date.now(); 18 | const refill = Math.floor((now - bucket.refilledAt) / (this.refillIntervalSeconds * 1000)); 19 | if (refill > 0) { 20 | return Math.min(bucket.count + refill, this.max) >= cost; 21 | } 22 | return bucket.count >= cost; 23 | } 24 | 25 | public consume(key: _Key, cost: number): boolean { 26 | let bucket = this.storage.get(key) ?? null; 27 | const now = Date.now(); 28 | if (bucket === null) { 29 | bucket = { 30 | count: this.max - cost, 31 | refilledAt: now 32 | }; 33 | this.storage.set(key, bucket); 34 | return true; 35 | } 36 | const refill = Math.floor((now - bucket.refilledAt) / (this.refillIntervalSeconds * 1000)); 37 | if (refill > 0) { 38 | bucket.count = Math.min(bucket.count + refill, this.max); 39 | bucket.refilledAt = now; 40 | } 41 | if (bucket.count < cost) { 42 | this.storage.set(key, bucket); 43 | return false; 44 | } 45 | bucket.count -= cost; 46 | this.storage.set(key, bucket); 47 | return true; 48 | } 49 | } 50 | interface Bucket { 51 | count: number; 52 | refilledAt: number; 53 | } 54 | -------------------------------------------------------------------------------- /src/routes/login/google/callback/+server.ts: -------------------------------------------------------------------------------- 1 | import { google } from "$lib/server/oauth"; 2 | import { ObjectParser } from "@pilcrowjs/object-parser"; 3 | import { createUser, getUserFromGoogleId } from "$lib/server/user"; 4 | import { createSession, generateSessionToken, setSessionTokenCookie } from "$lib/server/session"; 5 | import { decodeIdToken } from "arctic"; 6 | 7 | import type { RequestEvent } from "./$types"; 8 | import type { OAuth2Tokens } from "arctic"; 9 | 10 | export async function GET(event: RequestEvent): Promise { 11 | const storedState = event.cookies.get("google_oauth_state") ?? null; 12 | const codeVerifier = event.cookies.get("google_code_verifier") ?? null; 13 | const code = event.url.searchParams.get("code"); 14 | const state = event.url.searchParams.get("state"); 15 | 16 | if (storedState === null || codeVerifier === null || code === null || state === null) { 17 | return new Response("Please restart the process.", { 18 | status: 400 19 | }); 20 | } 21 | if (storedState !== state) { 22 | return new Response("Please restart the process.", { 23 | status: 400 24 | }); 25 | } 26 | 27 | let tokens: OAuth2Tokens; 28 | try { 29 | tokens = await google.validateAuthorizationCode(code, codeVerifier); 30 | } catch (e) { 31 | return new Response("Please restart the process.", { 32 | status: 400 33 | }); 34 | } 35 | 36 | const claims = decodeIdToken(tokens.idToken()); 37 | const claimsParser = new ObjectParser(claims); 38 | 39 | const googleId = claimsParser.getString("sub"); 40 | const name = claimsParser.getString("name"); 41 | const picture = claimsParser.getString("picture"); 42 | const email = claimsParser.getString("email"); 43 | 44 | const existingUser = getUserFromGoogleId(googleId); 45 | if (existingUser !== null) { 46 | const sessionToken = generateSessionToken(); 47 | const session = createSession(sessionToken, existingUser.id); 48 | setSessionTokenCookie(event, sessionToken, session.expiresAt); 49 | return new Response(null, { 50 | status: 302, 51 | headers: { 52 | Location: "/" 53 | } 54 | }); 55 | } 56 | 57 | const user = createUser(googleId, email, name, picture); 58 | const sessionToken = generateSessionToken(); 59 | const session = createSession(sessionToken, user.id); 60 | setSessionTokenCookie(event, sessionToken, session.expiresAt); 61 | return new Response(null, { 62 | status: 302, 63 | headers: { 64 | Location: "/" 65 | } 66 | }); 67 | } 68 | -------------------------------------------------------------------------------- /src/lib/server/session.ts: -------------------------------------------------------------------------------- 1 | import { db } from "./db"; 2 | import { encodeBase32, encodeHexLowerCase } from "@oslojs/encoding"; 3 | import { sha256 } from "@oslojs/crypto/sha2"; 4 | 5 | import type { User } from "./user"; 6 | import type { RequestEvent } from "@sveltejs/kit"; 7 | 8 | export function validateSessionToken(token: string): SessionValidationResult { 9 | const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token))); 10 | const row = db.queryOne( 11 | ` 12 | SELECT session.id, session.user_id, session.expires_at, user.id, user.google_id, user.email, user.name, user.picture FROM session 13 | INNER JOIN user ON session.user_id = user.id 14 | WHERE session.id = ? 15 | `, 16 | [sessionId] 17 | ); 18 | 19 | if (row === null) { 20 | return { session: null, user: null }; 21 | } 22 | const session: Session = { 23 | id: row.string(0), 24 | userId: row.number(1), 25 | expiresAt: new Date(row.number(2) * 1000) 26 | }; 27 | const user: User = { 28 | id: row.number(3), 29 | googleId: row.string(4), 30 | email: row.string(5), 31 | name: row.string(6), 32 | picture: row.string(7) 33 | }; 34 | if (Date.now() >= session.expiresAt.getTime()) { 35 | db.execute("DELETE FROM session WHERE id = ?", [session.id]); 36 | return { session: null, user: null }; 37 | } 38 | if (Date.now() >= session.expiresAt.getTime() - 1000 * 60 * 60 * 24 * 15) { 39 | session.expiresAt = new Date(Date.now() + 1000 * 60 * 60 * 24 * 30); 40 | db.execute("UPDATE session SET expires_at = ? WHERE session.id = ?", [ 41 | Math.floor(session.expiresAt.getTime() / 1000), 42 | session.id 43 | ]); 44 | } 45 | return { session, user }; 46 | } 47 | 48 | export function invalidateSession(sessionId: string): void { 49 | db.execute("DELETE FROM session WHERE id = ?", [sessionId]); 50 | } 51 | 52 | export function invalidateUserSessions(userId: number): void { 53 | db.execute("DELETE FROM session WHERE user_id = ?", [userId]); 54 | } 55 | 56 | export function setSessionTokenCookie(event: RequestEvent, token: string, expiresAt: Date): void { 57 | event.cookies.set("session", token, { 58 | httpOnly: true, 59 | path: "/", 60 | secure: import.meta.env.PROD, 61 | sameSite: "lax", 62 | expires: expiresAt 63 | }); 64 | } 65 | 66 | export function deleteSessionTokenCookie(event: RequestEvent): void { 67 | event.cookies.set("session", "", { 68 | httpOnly: true, 69 | path: "/", 70 | secure: import.meta.env.PROD, 71 | sameSite: "lax", 72 | maxAge: 0 73 | }); 74 | } 75 | 76 | export function generateSessionToken(): string { 77 | const tokenBytes = new Uint8Array(20); 78 | crypto.getRandomValues(tokenBytes); 79 | const token = encodeBase32(tokenBytes).toLowerCase(); 80 | return token; 81 | } 82 | 83 | export function createSession(token: string, userId: number): Session { 84 | const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token))); 85 | const session: Session = { 86 | id: sessionId, 87 | userId, 88 | expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 30) 89 | }; 90 | db.execute("INSERT INTO session (id, user_id, expires_at) VALUES (?, ?, ?)", [ 91 | session.id, 92 | session.userId, 93 | Math.floor(session.expiresAt.getTime() / 1000) 94 | ]); 95 | return session; 96 | } 97 | 98 | export interface Session { 99 | id: string; 100 | expiresAt: Date; 101 | userId: number; 102 | } 103 | 104 | type SessionValidationResult = { session: Session; user: User } | { session: null; user: null }; 105 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | '@oslojs/binary': 12 | specifier: ^1.0.0 13 | version: 1.0.0 14 | '@oslojs/crypto': 15 | specifier: ^1.0.1 16 | version: 1.0.1 17 | '@oslojs/encoding': 18 | specifier: ^1.1.0 19 | version: 1.1.0 20 | '@pilcrowjs/db-query': 21 | specifier: ^0.0.2 22 | version: 0.0.2 23 | '@pilcrowjs/object-parser': 24 | specifier: ^0.0.4 25 | version: 0.0.4 26 | arctic: 27 | specifier: 2.0.0-next.9 28 | version: 2.0.0-next.9 29 | better-sqlite3: 30 | specifier: ^11.3.0 31 | version: 11.3.0 32 | devDependencies: 33 | '@sveltejs/adapter-auto': 34 | specifier: ^3.0.0 35 | version: 3.2.5(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4)))(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4))) 36 | '@sveltejs/kit': 37 | specifier: ^2.0.0 38 | version: 2.6.1(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4)))(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4)) 39 | '@sveltejs/vite-plugin-svelte': 40 | specifier: ^3.0.0 41 | version: 3.1.2(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4)) 42 | '@types/better-sqlite3': 43 | specifier: ^7.6.11 44 | version: 7.6.11 45 | prettier: 46 | specifier: ^3.1.1 47 | version: 3.3.3 48 | prettier-plugin-svelte: 49 | specifier: ^3.1.2 50 | version: 3.2.7(prettier@3.3.3)(svelte@4.2.19) 51 | svelte: 52 | specifier: ^4.2.7 53 | version: 4.2.19 54 | svelte-check: 55 | specifier: ^4.0.0 56 | version: 4.0.4(svelte@4.2.19)(typescript@5.6.2) 57 | typescript: 58 | specifier: ^5.0.0 59 | version: 5.6.2 60 | vite: 61 | specifier: ^5.0.3 62 | version: 5.4.8(@types/node@22.7.4) 63 | 64 | packages: 65 | 66 | '@ampproject/remapping@2.3.0': 67 | resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} 68 | engines: {node: '>=6.0.0'} 69 | 70 | '@esbuild/aix-ppc64@0.21.5': 71 | resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} 72 | engines: {node: '>=12'} 73 | cpu: [ppc64] 74 | os: [aix] 75 | 76 | '@esbuild/android-arm64@0.21.5': 77 | resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} 78 | engines: {node: '>=12'} 79 | cpu: [arm64] 80 | os: [android] 81 | 82 | '@esbuild/android-arm@0.21.5': 83 | resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} 84 | engines: {node: '>=12'} 85 | cpu: [arm] 86 | os: [android] 87 | 88 | '@esbuild/android-x64@0.21.5': 89 | resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} 90 | engines: {node: '>=12'} 91 | cpu: [x64] 92 | os: [android] 93 | 94 | '@esbuild/darwin-arm64@0.21.5': 95 | resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} 96 | engines: {node: '>=12'} 97 | cpu: [arm64] 98 | os: [darwin] 99 | 100 | '@esbuild/darwin-x64@0.21.5': 101 | resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} 102 | engines: {node: '>=12'} 103 | cpu: [x64] 104 | os: [darwin] 105 | 106 | '@esbuild/freebsd-arm64@0.21.5': 107 | resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} 108 | engines: {node: '>=12'} 109 | cpu: [arm64] 110 | os: [freebsd] 111 | 112 | '@esbuild/freebsd-x64@0.21.5': 113 | resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} 114 | engines: {node: '>=12'} 115 | cpu: [x64] 116 | os: [freebsd] 117 | 118 | '@esbuild/linux-arm64@0.21.5': 119 | resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} 120 | engines: {node: '>=12'} 121 | cpu: [arm64] 122 | os: [linux] 123 | 124 | '@esbuild/linux-arm@0.21.5': 125 | resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} 126 | engines: {node: '>=12'} 127 | cpu: [arm] 128 | os: [linux] 129 | 130 | '@esbuild/linux-ia32@0.21.5': 131 | resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} 132 | engines: {node: '>=12'} 133 | cpu: [ia32] 134 | os: [linux] 135 | 136 | '@esbuild/linux-loong64@0.21.5': 137 | resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} 138 | engines: {node: '>=12'} 139 | cpu: [loong64] 140 | os: [linux] 141 | 142 | '@esbuild/linux-mips64el@0.21.5': 143 | resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} 144 | engines: {node: '>=12'} 145 | cpu: [mips64el] 146 | os: [linux] 147 | 148 | '@esbuild/linux-ppc64@0.21.5': 149 | resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} 150 | engines: {node: '>=12'} 151 | cpu: [ppc64] 152 | os: [linux] 153 | 154 | '@esbuild/linux-riscv64@0.21.5': 155 | resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} 156 | engines: {node: '>=12'} 157 | cpu: [riscv64] 158 | os: [linux] 159 | 160 | '@esbuild/linux-s390x@0.21.5': 161 | resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} 162 | engines: {node: '>=12'} 163 | cpu: [s390x] 164 | os: [linux] 165 | 166 | '@esbuild/linux-x64@0.21.5': 167 | resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} 168 | engines: {node: '>=12'} 169 | cpu: [x64] 170 | os: [linux] 171 | 172 | '@esbuild/netbsd-x64@0.21.5': 173 | resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} 174 | engines: {node: '>=12'} 175 | cpu: [x64] 176 | os: [netbsd] 177 | 178 | '@esbuild/openbsd-x64@0.21.5': 179 | resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} 180 | engines: {node: '>=12'} 181 | cpu: [x64] 182 | os: [openbsd] 183 | 184 | '@esbuild/sunos-x64@0.21.5': 185 | resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} 186 | engines: {node: '>=12'} 187 | cpu: [x64] 188 | os: [sunos] 189 | 190 | '@esbuild/win32-arm64@0.21.5': 191 | resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} 192 | engines: {node: '>=12'} 193 | cpu: [arm64] 194 | os: [win32] 195 | 196 | '@esbuild/win32-ia32@0.21.5': 197 | resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} 198 | engines: {node: '>=12'} 199 | cpu: [ia32] 200 | os: [win32] 201 | 202 | '@esbuild/win32-x64@0.21.5': 203 | resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} 204 | engines: {node: '>=12'} 205 | cpu: [x64] 206 | os: [win32] 207 | 208 | '@jridgewell/gen-mapping@0.3.5': 209 | resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} 210 | engines: {node: '>=6.0.0'} 211 | 212 | '@jridgewell/resolve-uri@3.1.2': 213 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 214 | engines: {node: '>=6.0.0'} 215 | 216 | '@jridgewell/set-array@1.2.1': 217 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} 218 | engines: {node: '>=6.0.0'} 219 | 220 | '@jridgewell/sourcemap-codec@1.5.0': 221 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 222 | 223 | '@jridgewell/trace-mapping@0.3.25': 224 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 225 | 226 | '@oslojs/asn1@0.2.2': 227 | resolution: {integrity: sha512-/c7DTaOdmk3Xb482b4CFnPdWLo5e2WQuozhc89KVb91kohA+VvVNTd9IPyLsZpDUf9u3iwP4HcuMEXBcYmGFnQ==} 228 | 229 | '@oslojs/asn1@1.0.0': 230 | resolution: {integrity: sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA==} 231 | 232 | '@oslojs/binary@0.2.3': 233 | resolution: {integrity: sha512-pBJvvl5wpBBmkbP8cMZvPXzxPd7WN+NDBHPEg2N6WTDSnYCCPmqghIz6W+Cw16hhAju9wgmOeHryjHFbNezr1w==} 234 | 235 | '@oslojs/binary@1.0.0': 236 | resolution: {integrity: sha512-9RCU6OwXU6p67H4NODbuxv2S3eenuQ4/WFLrsq+K/k682xrznH5EVWA7N4VFk9VYVcbFtKqur5YQQZc0ySGhsQ==} 237 | 238 | '@oslojs/crypto@0.6.0': 239 | resolution: {integrity: sha512-MAwQt2BwW/oLvYaX1SuVHBqBXV+3CsF7ied23LDqeVeesFTPxLLIqW6pbQ6SMUPnGEJXQx4OTfm2BYSLLvp5Hg==} 240 | 241 | '@oslojs/crypto@1.0.1': 242 | resolution: {integrity: sha512-7n08G8nWjAr/Yu3vu9zzrd0L9XnrJfpMioQcvCMxBIiF5orECHe5/3J0jmXRVvgfqMm/+4oxlQ+Sq39COYLcNQ==} 243 | 244 | '@oslojs/encoding@0.4.1': 245 | resolution: {integrity: sha512-hkjo6MuIK/kQR5CrGNdAPZhS01ZCXuWDRJ187zh6qqF2+yMHZpD9fAYpX8q2bOO6Ryhl3XpCT6kUX76N8hhm4Q==} 246 | 247 | '@oslojs/encoding@1.1.0': 248 | resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} 249 | 250 | '@oslojs/jwt@0.1.0': 251 | resolution: {integrity: sha512-g6JHWeCl9OkHLeoaaKUZoQUfCzhn2U5hYnyoT7/Uh/HY0AGpf0odmFViW6AhPKaOOVXKITvoOArEhec1vEd6GA==} 252 | 253 | '@pilcrowjs/db-query@0.0.2': 254 | resolution: {integrity: sha512-d1iARoIxeUL2cTGhJe4JPhp/n1sXtgnM1mL7elrfsKjdwwjWTDyPDtVcGQy6W7RvrtZ40Wh0pdeYdBnboQjewg==} 255 | 256 | '@pilcrowjs/object-parser@0.0.4': 257 | resolution: {integrity: sha512-mBy3FMv2lvl/sZX/q03wvl3Km8FWg7kbrqQ/qMxK49uZcBssD76Js5k+o7VuCDJI8SNvsrbIX8y6vclx7bWeSg==} 258 | 259 | '@polka/url@1.0.0-next.28': 260 | resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} 261 | 262 | '@rollup/rollup-android-arm-eabi@4.24.0': 263 | resolution: {integrity: sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==} 264 | cpu: [arm] 265 | os: [android] 266 | 267 | '@rollup/rollup-android-arm64@4.24.0': 268 | resolution: {integrity: sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==} 269 | cpu: [arm64] 270 | os: [android] 271 | 272 | '@rollup/rollup-darwin-arm64@4.24.0': 273 | resolution: {integrity: sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==} 274 | cpu: [arm64] 275 | os: [darwin] 276 | 277 | '@rollup/rollup-darwin-x64@4.24.0': 278 | resolution: {integrity: sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==} 279 | cpu: [x64] 280 | os: [darwin] 281 | 282 | '@rollup/rollup-linux-arm-gnueabihf@4.24.0': 283 | resolution: {integrity: sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==} 284 | cpu: [arm] 285 | os: [linux] 286 | 287 | '@rollup/rollup-linux-arm-musleabihf@4.24.0': 288 | resolution: {integrity: sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==} 289 | cpu: [arm] 290 | os: [linux] 291 | 292 | '@rollup/rollup-linux-arm64-gnu@4.24.0': 293 | resolution: {integrity: sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==} 294 | cpu: [arm64] 295 | os: [linux] 296 | 297 | '@rollup/rollup-linux-arm64-musl@4.24.0': 298 | resolution: {integrity: sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==} 299 | cpu: [arm64] 300 | os: [linux] 301 | 302 | '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': 303 | resolution: {integrity: sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==} 304 | cpu: [ppc64] 305 | os: [linux] 306 | 307 | '@rollup/rollup-linux-riscv64-gnu@4.24.0': 308 | resolution: {integrity: sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==} 309 | cpu: [riscv64] 310 | os: [linux] 311 | 312 | '@rollup/rollup-linux-s390x-gnu@4.24.0': 313 | resolution: {integrity: sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==} 314 | cpu: [s390x] 315 | os: [linux] 316 | 317 | '@rollup/rollup-linux-x64-gnu@4.24.0': 318 | resolution: {integrity: sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==} 319 | cpu: [x64] 320 | os: [linux] 321 | 322 | '@rollup/rollup-linux-x64-musl@4.24.0': 323 | resolution: {integrity: sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==} 324 | cpu: [x64] 325 | os: [linux] 326 | 327 | '@rollup/rollup-win32-arm64-msvc@4.24.0': 328 | resolution: {integrity: sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==} 329 | cpu: [arm64] 330 | os: [win32] 331 | 332 | '@rollup/rollup-win32-ia32-msvc@4.24.0': 333 | resolution: {integrity: sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==} 334 | cpu: [ia32] 335 | os: [win32] 336 | 337 | '@rollup/rollup-win32-x64-msvc@4.24.0': 338 | resolution: {integrity: sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==} 339 | cpu: [x64] 340 | os: [win32] 341 | 342 | '@sveltejs/adapter-auto@3.2.5': 343 | resolution: {integrity: sha512-27LR+uKccZ62lgq4N/hvyU2G+hTP9fxWEAfnZcl70HnyfAjMSsGk1z/SjAPXNCD1mVJIE7IFu3TQ8cQ/UH3c0A==} 344 | peerDependencies: 345 | '@sveltejs/kit': ^2.0.0 346 | 347 | '@sveltejs/kit@2.6.1': 348 | resolution: {integrity: sha512-QFlch3GPGZYidYhdRAub0fONw8UTguPICFHUSPxNkA/jdlU1p6C6yqq19J1QWdxIHS2El/ycDCGrHb3EAiMNqg==} 349 | engines: {node: '>=18.13'} 350 | hasBin: true 351 | peerDependencies: 352 | '@sveltejs/vite-plugin-svelte': ^3.0.0 || ^4.0.0-next.1 353 | svelte: ^4.0.0 || ^5.0.0-next.0 354 | vite: ^5.0.3 355 | 356 | '@sveltejs/vite-plugin-svelte-inspector@2.1.0': 357 | resolution: {integrity: sha512-9QX28IymvBlSCqsCll5t0kQVxipsfhFFL+L2t3nTWfXnddYwxBuAEtTtlaVQpRz9c37BhJjltSeY4AJSC03SSg==} 358 | engines: {node: ^18.0.0 || >=20} 359 | peerDependencies: 360 | '@sveltejs/vite-plugin-svelte': ^3.0.0 361 | svelte: ^4.0.0 || ^5.0.0-next.0 362 | vite: ^5.0.0 363 | 364 | '@sveltejs/vite-plugin-svelte@3.1.2': 365 | resolution: {integrity: sha512-Txsm1tJvtiYeLUVRNqxZGKR/mI+CzuIQuc2gn+YCs9rMTowpNZ2Nqt53JdL8KF9bLhAf2ruR/dr9eZCwdTriRA==} 366 | engines: {node: ^18.0.0 || >=20} 367 | peerDependencies: 368 | svelte: ^4.0.0 || ^5.0.0-next.0 369 | vite: ^5.0.0 370 | 371 | '@types/better-sqlite3@7.6.11': 372 | resolution: {integrity: sha512-i8KcD3PgGtGBLl3+mMYA8PdKkButvPyARxA7IQAd6qeslht13qxb1zzO8dRCtE7U3IoJS782zDBAeoKiM695kg==} 373 | 374 | '@types/cookie@0.6.0': 375 | resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} 376 | 377 | '@types/estree@1.0.6': 378 | resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} 379 | 380 | '@types/node@22.7.4': 381 | resolution: {integrity: sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==} 382 | 383 | acorn@8.12.1: 384 | resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} 385 | engines: {node: '>=0.4.0'} 386 | hasBin: true 387 | 388 | arctic@2.0.0-next.9: 389 | resolution: {integrity: sha512-VUi47ekY8oWEa+NE4AcEl5fwZF5lMn0/PCQUsPieLP8wFVXVFR+vxDKESkMQg+d8Ffd7LBLXWW/DTIgvD8zRtw==} 390 | 391 | aria-query@5.3.2: 392 | resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} 393 | engines: {node: '>= 0.4'} 394 | 395 | axobject-query@4.1.0: 396 | resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} 397 | engines: {node: '>= 0.4'} 398 | 399 | base64-js@1.5.1: 400 | resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} 401 | 402 | better-sqlite3@11.3.0: 403 | resolution: {integrity: sha512-iHt9j8NPYF3oKCNOO5ZI4JwThjt3Z6J6XrcwG85VNMVzv1ByqrHWv5VILEbCMFWDsoHhXvQ7oC8vgRXFAKgl9w==} 404 | 405 | bindings@1.5.0: 406 | resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} 407 | 408 | bl@4.1.0: 409 | resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} 410 | 411 | buffer@5.7.1: 412 | resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} 413 | 414 | chokidar@4.0.1: 415 | resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} 416 | engines: {node: '>= 14.16.0'} 417 | 418 | chownr@1.1.4: 419 | resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} 420 | 421 | code-red@1.0.4: 422 | resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==} 423 | 424 | cookie@0.6.0: 425 | resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} 426 | engines: {node: '>= 0.6'} 427 | 428 | css-tree@2.3.1: 429 | resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} 430 | engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} 431 | 432 | debug@4.3.7: 433 | resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} 434 | engines: {node: '>=6.0'} 435 | peerDependencies: 436 | supports-color: '*' 437 | peerDependenciesMeta: 438 | supports-color: 439 | optional: true 440 | 441 | decompress-response@6.0.0: 442 | resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} 443 | engines: {node: '>=10'} 444 | 445 | deep-extend@0.6.0: 446 | resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} 447 | engines: {node: '>=4.0.0'} 448 | 449 | deepmerge@4.3.1: 450 | resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} 451 | engines: {node: '>=0.10.0'} 452 | 453 | detect-libc@2.0.3: 454 | resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} 455 | engines: {node: '>=8'} 456 | 457 | devalue@5.1.1: 458 | resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==} 459 | 460 | end-of-stream@1.4.4: 461 | resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} 462 | 463 | esbuild@0.21.5: 464 | resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} 465 | engines: {node: '>=12'} 466 | hasBin: true 467 | 468 | esm-env@1.0.0: 469 | resolution: {integrity: sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==} 470 | 471 | estree-walker@3.0.3: 472 | resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} 473 | 474 | expand-template@2.0.3: 475 | resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} 476 | engines: {node: '>=6'} 477 | 478 | fdir@6.4.0: 479 | resolution: {integrity: sha512-3oB133prH1o4j/L5lLW7uOCF1PlD+/It2L0eL/iAqWMB91RBbqTewABqxhj0ibBd90EEmWZq7ntIWzVaWcXTGQ==} 480 | peerDependencies: 481 | picomatch: ^3 || ^4 482 | peerDependenciesMeta: 483 | picomatch: 484 | optional: true 485 | 486 | file-uri-to-path@1.0.0: 487 | resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} 488 | 489 | fs-constants@1.0.0: 490 | resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} 491 | 492 | fsevents@2.3.3: 493 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 494 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 495 | os: [darwin] 496 | 497 | github-from-package@0.0.0: 498 | resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} 499 | 500 | globalyzer@0.1.0: 501 | resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} 502 | 503 | globrex@0.1.2: 504 | resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} 505 | 506 | ieee754@1.2.1: 507 | resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} 508 | 509 | import-meta-resolve@4.1.0: 510 | resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} 511 | 512 | inherits@2.0.4: 513 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 514 | 515 | ini@1.3.8: 516 | resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} 517 | 518 | is-reference@3.0.2: 519 | resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} 520 | 521 | kleur@4.1.5: 522 | resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} 523 | engines: {node: '>=6'} 524 | 525 | locate-character@3.0.0: 526 | resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} 527 | 528 | magic-string@0.30.11: 529 | resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} 530 | 531 | mdn-data@2.0.30: 532 | resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} 533 | 534 | mimic-response@3.1.0: 535 | resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} 536 | engines: {node: '>=10'} 537 | 538 | minimist@1.2.8: 539 | resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} 540 | 541 | mkdirp-classic@0.5.3: 542 | resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} 543 | 544 | mri@1.2.0: 545 | resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} 546 | engines: {node: '>=4'} 547 | 548 | mrmime@2.0.0: 549 | resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} 550 | engines: {node: '>=10'} 551 | 552 | ms@2.1.3: 553 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 554 | 555 | nanoid@3.3.7: 556 | resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} 557 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 558 | hasBin: true 559 | 560 | napi-build-utils@1.0.2: 561 | resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} 562 | 563 | node-abi@3.68.0: 564 | resolution: {integrity: sha512-7vbj10trelExNjFSBm5kTvZXXa7pZyKWx9RCKIyqe6I9Ev3IzGpQoqBP3a+cOdxY+pWj6VkP28n/2wWysBHD/A==} 565 | engines: {node: '>=10'} 566 | 567 | once@1.4.0: 568 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 569 | 570 | periscopic@3.1.0: 571 | resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} 572 | 573 | picocolors@1.1.0: 574 | resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} 575 | 576 | postcss@8.4.47: 577 | resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} 578 | engines: {node: ^10 || ^12 || >=14} 579 | 580 | prebuild-install@7.1.2: 581 | resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==} 582 | engines: {node: '>=10'} 583 | hasBin: true 584 | 585 | prettier-plugin-svelte@3.2.7: 586 | resolution: {integrity: sha512-/Dswx/ea0lV34If1eDcG3nulQ63YNr5KPDfMsjbdtpSWOxKKJ7nAc2qlVuYwEvCr4raIuredNoR7K4JCkmTGaQ==} 587 | peerDependencies: 588 | prettier: ^3.0.0 589 | svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0 590 | 591 | prettier@3.3.3: 592 | resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} 593 | engines: {node: '>=14'} 594 | hasBin: true 595 | 596 | pump@3.0.2: 597 | resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} 598 | 599 | rc@1.2.8: 600 | resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} 601 | hasBin: true 602 | 603 | readable-stream@3.6.2: 604 | resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} 605 | engines: {node: '>= 6'} 606 | 607 | readdirp@4.0.2: 608 | resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} 609 | engines: {node: '>= 14.16.0'} 610 | 611 | rollup@4.24.0: 612 | resolution: {integrity: sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==} 613 | engines: {node: '>=18.0.0', npm: '>=8.0.0'} 614 | hasBin: true 615 | 616 | sade@1.8.1: 617 | resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} 618 | engines: {node: '>=6'} 619 | 620 | safe-buffer@5.2.1: 621 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 622 | 623 | semver@7.6.3: 624 | resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} 625 | engines: {node: '>=10'} 626 | hasBin: true 627 | 628 | set-cookie-parser@2.7.0: 629 | resolution: {integrity: sha512-lXLOiqpkUumhRdFF3k1osNXCy9akgx/dyPZ5p8qAg9seJzXr5ZrlqZuWIMuY6ejOsVLE6flJ5/h3lsn57fQ/PQ==} 630 | 631 | simple-concat@1.0.1: 632 | resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} 633 | 634 | simple-get@4.0.1: 635 | resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} 636 | 637 | sirv@2.0.4: 638 | resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} 639 | engines: {node: '>= 10'} 640 | 641 | source-map-js@1.2.1: 642 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 643 | engines: {node: '>=0.10.0'} 644 | 645 | string_decoder@1.3.0: 646 | resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} 647 | 648 | strip-json-comments@2.0.1: 649 | resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} 650 | engines: {node: '>=0.10.0'} 651 | 652 | svelte-check@4.0.4: 653 | resolution: {integrity: sha512-AcHWIPuZb1mh/jKoIrww0ebBPpAvwWd1bfXCnwC2dx4OkydNMaiG//+Xnry91RJMHFH7CiE+6Y2p332DRIaOXQ==} 654 | engines: {node: '>= 18.0.0'} 655 | hasBin: true 656 | peerDependencies: 657 | svelte: ^4.0.0 || ^5.0.0-next.0 658 | typescript: '>=5.0.0' 659 | 660 | svelte-hmr@0.16.0: 661 | resolution: {integrity: sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==} 662 | engines: {node: ^12.20 || ^14.13.1 || >= 16} 663 | peerDependencies: 664 | svelte: ^3.19.0 || ^4.0.0 665 | 666 | svelte@4.2.19: 667 | resolution: {integrity: sha512-IY1rnGr6izd10B0A8LqsBfmlT5OILVuZ7XsI0vdGPEvuonFV7NYEUK4dAkm9Zg2q0Um92kYjTpS1CAP3Nh/KWw==} 668 | engines: {node: '>=16'} 669 | 670 | tar-fs@2.1.1: 671 | resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} 672 | 673 | tar-stream@2.2.0: 674 | resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} 675 | engines: {node: '>=6'} 676 | 677 | tiny-glob@0.2.9: 678 | resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} 679 | 680 | totalist@3.0.1: 681 | resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} 682 | engines: {node: '>=6'} 683 | 684 | tunnel-agent@0.6.0: 685 | resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} 686 | 687 | typescript@5.6.2: 688 | resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} 689 | engines: {node: '>=14.17'} 690 | hasBin: true 691 | 692 | undici-types@6.19.8: 693 | resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} 694 | 695 | util-deprecate@1.0.2: 696 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} 697 | 698 | vite@5.4.8: 699 | resolution: {integrity: sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==} 700 | engines: {node: ^18.0.0 || >=20.0.0} 701 | hasBin: true 702 | peerDependencies: 703 | '@types/node': ^18.0.0 || >=20.0.0 704 | less: '*' 705 | lightningcss: ^1.21.0 706 | sass: '*' 707 | sass-embedded: '*' 708 | stylus: '*' 709 | sugarss: '*' 710 | terser: ^5.4.0 711 | peerDependenciesMeta: 712 | '@types/node': 713 | optional: true 714 | less: 715 | optional: true 716 | lightningcss: 717 | optional: true 718 | sass: 719 | optional: true 720 | sass-embedded: 721 | optional: true 722 | stylus: 723 | optional: true 724 | sugarss: 725 | optional: true 726 | terser: 727 | optional: true 728 | 729 | vitefu@0.2.5: 730 | resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} 731 | peerDependencies: 732 | vite: ^3.0.0 || ^4.0.0 || ^5.0.0 733 | peerDependenciesMeta: 734 | vite: 735 | optional: true 736 | 737 | wrappy@1.0.2: 738 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 739 | 740 | snapshots: 741 | 742 | '@ampproject/remapping@2.3.0': 743 | dependencies: 744 | '@jridgewell/gen-mapping': 0.3.5 745 | '@jridgewell/trace-mapping': 0.3.25 746 | 747 | '@esbuild/aix-ppc64@0.21.5': 748 | optional: true 749 | 750 | '@esbuild/android-arm64@0.21.5': 751 | optional: true 752 | 753 | '@esbuild/android-arm@0.21.5': 754 | optional: true 755 | 756 | '@esbuild/android-x64@0.21.5': 757 | optional: true 758 | 759 | '@esbuild/darwin-arm64@0.21.5': 760 | optional: true 761 | 762 | '@esbuild/darwin-x64@0.21.5': 763 | optional: true 764 | 765 | '@esbuild/freebsd-arm64@0.21.5': 766 | optional: true 767 | 768 | '@esbuild/freebsd-x64@0.21.5': 769 | optional: true 770 | 771 | '@esbuild/linux-arm64@0.21.5': 772 | optional: true 773 | 774 | '@esbuild/linux-arm@0.21.5': 775 | optional: true 776 | 777 | '@esbuild/linux-ia32@0.21.5': 778 | optional: true 779 | 780 | '@esbuild/linux-loong64@0.21.5': 781 | optional: true 782 | 783 | '@esbuild/linux-mips64el@0.21.5': 784 | optional: true 785 | 786 | '@esbuild/linux-ppc64@0.21.5': 787 | optional: true 788 | 789 | '@esbuild/linux-riscv64@0.21.5': 790 | optional: true 791 | 792 | '@esbuild/linux-s390x@0.21.5': 793 | optional: true 794 | 795 | '@esbuild/linux-x64@0.21.5': 796 | optional: true 797 | 798 | '@esbuild/netbsd-x64@0.21.5': 799 | optional: true 800 | 801 | '@esbuild/openbsd-x64@0.21.5': 802 | optional: true 803 | 804 | '@esbuild/sunos-x64@0.21.5': 805 | optional: true 806 | 807 | '@esbuild/win32-arm64@0.21.5': 808 | optional: true 809 | 810 | '@esbuild/win32-ia32@0.21.5': 811 | optional: true 812 | 813 | '@esbuild/win32-x64@0.21.5': 814 | optional: true 815 | 816 | '@jridgewell/gen-mapping@0.3.5': 817 | dependencies: 818 | '@jridgewell/set-array': 1.2.1 819 | '@jridgewell/sourcemap-codec': 1.5.0 820 | '@jridgewell/trace-mapping': 0.3.25 821 | 822 | '@jridgewell/resolve-uri@3.1.2': {} 823 | 824 | '@jridgewell/set-array@1.2.1': {} 825 | 826 | '@jridgewell/sourcemap-codec@1.5.0': {} 827 | 828 | '@jridgewell/trace-mapping@0.3.25': 829 | dependencies: 830 | '@jridgewell/resolve-uri': 3.1.2 831 | '@jridgewell/sourcemap-codec': 1.5.0 832 | 833 | '@oslojs/asn1@0.2.2': 834 | dependencies: 835 | '@oslojs/binary': 0.2.3 836 | 837 | '@oslojs/asn1@1.0.0': 838 | dependencies: 839 | '@oslojs/binary': 1.0.0 840 | 841 | '@oslojs/binary@0.2.3': {} 842 | 843 | '@oslojs/binary@1.0.0': {} 844 | 845 | '@oslojs/crypto@0.6.0': 846 | dependencies: 847 | '@oslojs/asn1': 0.2.2 848 | '@oslojs/binary': 0.2.3 849 | 850 | '@oslojs/crypto@1.0.1': 851 | dependencies: 852 | '@oslojs/asn1': 1.0.0 853 | '@oslojs/binary': 1.0.0 854 | 855 | '@oslojs/encoding@0.4.1': {} 856 | 857 | '@oslojs/encoding@1.1.0': {} 858 | 859 | '@oslojs/jwt@0.1.0': 860 | dependencies: 861 | '@oslojs/encoding': 0.4.1 862 | 863 | '@pilcrowjs/db-query@0.0.2': {} 864 | 865 | '@pilcrowjs/object-parser@0.0.4': {} 866 | 867 | '@polka/url@1.0.0-next.28': {} 868 | 869 | '@rollup/rollup-android-arm-eabi@4.24.0': 870 | optional: true 871 | 872 | '@rollup/rollup-android-arm64@4.24.0': 873 | optional: true 874 | 875 | '@rollup/rollup-darwin-arm64@4.24.0': 876 | optional: true 877 | 878 | '@rollup/rollup-darwin-x64@4.24.0': 879 | optional: true 880 | 881 | '@rollup/rollup-linux-arm-gnueabihf@4.24.0': 882 | optional: true 883 | 884 | '@rollup/rollup-linux-arm-musleabihf@4.24.0': 885 | optional: true 886 | 887 | '@rollup/rollup-linux-arm64-gnu@4.24.0': 888 | optional: true 889 | 890 | '@rollup/rollup-linux-arm64-musl@4.24.0': 891 | optional: true 892 | 893 | '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': 894 | optional: true 895 | 896 | '@rollup/rollup-linux-riscv64-gnu@4.24.0': 897 | optional: true 898 | 899 | '@rollup/rollup-linux-s390x-gnu@4.24.0': 900 | optional: true 901 | 902 | '@rollup/rollup-linux-x64-gnu@4.24.0': 903 | optional: true 904 | 905 | '@rollup/rollup-linux-x64-musl@4.24.0': 906 | optional: true 907 | 908 | '@rollup/rollup-win32-arm64-msvc@4.24.0': 909 | optional: true 910 | 911 | '@rollup/rollup-win32-ia32-msvc@4.24.0': 912 | optional: true 913 | 914 | '@rollup/rollup-win32-x64-msvc@4.24.0': 915 | optional: true 916 | 917 | '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4)))(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4)))': 918 | dependencies: 919 | '@sveltejs/kit': 2.6.1(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4)))(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4)) 920 | import-meta-resolve: 4.1.0 921 | 922 | '@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4)))(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4))': 923 | dependencies: 924 | '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4)) 925 | '@types/cookie': 0.6.0 926 | cookie: 0.6.0 927 | devalue: 5.1.1 928 | esm-env: 1.0.0 929 | import-meta-resolve: 4.1.0 930 | kleur: 4.1.5 931 | magic-string: 0.30.11 932 | mrmime: 2.0.0 933 | sade: 1.8.1 934 | set-cookie-parser: 2.7.0 935 | sirv: 2.0.4 936 | svelte: 4.2.19 937 | tiny-glob: 0.2.9 938 | vite: 5.4.8(@types/node@22.7.4) 939 | 940 | '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4)))(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4))': 941 | dependencies: 942 | '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4)) 943 | debug: 4.3.7 944 | svelte: 4.2.19 945 | vite: 5.4.8(@types/node@22.7.4) 946 | transitivePeerDependencies: 947 | - supports-color 948 | 949 | '@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4))': 950 | dependencies: 951 | '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4)))(svelte@4.2.19)(vite@5.4.8(@types/node@22.7.4)) 952 | debug: 4.3.7 953 | deepmerge: 4.3.1 954 | kleur: 4.1.5 955 | magic-string: 0.30.11 956 | svelte: 4.2.19 957 | svelte-hmr: 0.16.0(svelte@4.2.19) 958 | vite: 5.4.8(@types/node@22.7.4) 959 | vitefu: 0.2.5(vite@5.4.8(@types/node@22.7.4)) 960 | transitivePeerDependencies: 961 | - supports-color 962 | 963 | '@types/better-sqlite3@7.6.11': 964 | dependencies: 965 | '@types/node': 22.7.4 966 | 967 | '@types/cookie@0.6.0': {} 968 | 969 | '@types/estree@1.0.6': {} 970 | 971 | '@types/node@22.7.4': 972 | dependencies: 973 | undici-types: 6.19.8 974 | 975 | acorn@8.12.1: {} 976 | 977 | arctic@2.0.0-next.9: 978 | dependencies: 979 | '@oslojs/crypto': 0.6.0 980 | '@oslojs/encoding': 0.4.1 981 | '@oslojs/jwt': 0.1.0 982 | 983 | aria-query@5.3.2: {} 984 | 985 | axobject-query@4.1.0: {} 986 | 987 | base64-js@1.5.1: {} 988 | 989 | better-sqlite3@11.3.0: 990 | dependencies: 991 | bindings: 1.5.0 992 | prebuild-install: 7.1.2 993 | 994 | bindings@1.5.0: 995 | dependencies: 996 | file-uri-to-path: 1.0.0 997 | 998 | bl@4.1.0: 999 | dependencies: 1000 | buffer: 5.7.1 1001 | inherits: 2.0.4 1002 | readable-stream: 3.6.2 1003 | 1004 | buffer@5.7.1: 1005 | dependencies: 1006 | base64-js: 1.5.1 1007 | ieee754: 1.2.1 1008 | 1009 | chokidar@4.0.1: 1010 | dependencies: 1011 | readdirp: 4.0.2 1012 | 1013 | chownr@1.1.4: {} 1014 | 1015 | code-red@1.0.4: 1016 | dependencies: 1017 | '@jridgewell/sourcemap-codec': 1.5.0 1018 | '@types/estree': 1.0.6 1019 | acorn: 8.12.1 1020 | estree-walker: 3.0.3 1021 | periscopic: 3.1.0 1022 | 1023 | cookie@0.6.0: {} 1024 | 1025 | css-tree@2.3.1: 1026 | dependencies: 1027 | mdn-data: 2.0.30 1028 | source-map-js: 1.2.1 1029 | 1030 | debug@4.3.7: 1031 | dependencies: 1032 | ms: 2.1.3 1033 | 1034 | decompress-response@6.0.0: 1035 | dependencies: 1036 | mimic-response: 3.1.0 1037 | 1038 | deep-extend@0.6.0: {} 1039 | 1040 | deepmerge@4.3.1: {} 1041 | 1042 | detect-libc@2.0.3: {} 1043 | 1044 | devalue@5.1.1: {} 1045 | 1046 | end-of-stream@1.4.4: 1047 | dependencies: 1048 | once: 1.4.0 1049 | 1050 | esbuild@0.21.5: 1051 | optionalDependencies: 1052 | '@esbuild/aix-ppc64': 0.21.5 1053 | '@esbuild/android-arm': 0.21.5 1054 | '@esbuild/android-arm64': 0.21.5 1055 | '@esbuild/android-x64': 0.21.5 1056 | '@esbuild/darwin-arm64': 0.21.5 1057 | '@esbuild/darwin-x64': 0.21.5 1058 | '@esbuild/freebsd-arm64': 0.21.5 1059 | '@esbuild/freebsd-x64': 0.21.5 1060 | '@esbuild/linux-arm': 0.21.5 1061 | '@esbuild/linux-arm64': 0.21.5 1062 | '@esbuild/linux-ia32': 0.21.5 1063 | '@esbuild/linux-loong64': 0.21.5 1064 | '@esbuild/linux-mips64el': 0.21.5 1065 | '@esbuild/linux-ppc64': 0.21.5 1066 | '@esbuild/linux-riscv64': 0.21.5 1067 | '@esbuild/linux-s390x': 0.21.5 1068 | '@esbuild/linux-x64': 0.21.5 1069 | '@esbuild/netbsd-x64': 0.21.5 1070 | '@esbuild/openbsd-x64': 0.21.5 1071 | '@esbuild/sunos-x64': 0.21.5 1072 | '@esbuild/win32-arm64': 0.21.5 1073 | '@esbuild/win32-ia32': 0.21.5 1074 | '@esbuild/win32-x64': 0.21.5 1075 | 1076 | esm-env@1.0.0: {} 1077 | 1078 | estree-walker@3.0.3: 1079 | dependencies: 1080 | '@types/estree': 1.0.6 1081 | 1082 | expand-template@2.0.3: {} 1083 | 1084 | fdir@6.4.0: {} 1085 | 1086 | file-uri-to-path@1.0.0: {} 1087 | 1088 | fs-constants@1.0.0: {} 1089 | 1090 | fsevents@2.3.3: 1091 | optional: true 1092 | 1093 | github-from-package@0.0.0: {} 1094 | 1095 | globalyzer@0.1.0: {} 1096 | 1097 | globrex@0.1.2: {} 1098 | 1099 | ieee754@1.2.1: {} 1100 | 1101 | import-meta-resolve@4.1.0: {} 1102 | 1103 | inherits@2.0.4: {} 1104 | 1105 | ini@1.3.8: {} 1106 | 1107 | is-reference@3.0.2: 1108 | dependencies: 1109 | '@types/estree': 1.0.6 1110 | 1111 | kleur@4.1.5: {} 1112 | 1113 | locate-character@3.0.0: {} 1114 | 1115 | magic-string@0.30.11: 1116 | dependencies: 1117 | '@jridgewell/sourcemap-codec': 1.5.0 1118 | 1119 | mdn-data@2.0.30: {} 1120 | 1121 | mimic-response@3.1.0: {} 1122 | 1123 | minimist@1.2.8: {} 1124 | 1125 | mkdirp-classic@0.5.3: {} 1126 | 1127 | mri@1.2.0: {} 1128 | 1129 | mrmime@2.0.0: {} 1130 | 1131 | ms@2.1.3: {} 1132 | 1133 | nanoid@3.3.7: {} 1134 | 1135 | napi-build-utils@1.0.2: {} 1136 | 1137 | node-abi@3.68.0: 1138 | dependencies: 1139 | semver: 7.6.3 1140 | 1141 | once@1.4.0: 1142 | dependencies: 1143 | wrappy: 1.0.2 1144 | 1145 | periscopic@3.1.0: 1146 | dependencies: 1147 | '@types/estree': 1.0.6 1148 | estree-walker: 3.0.3 1149 | is-reference: 3.0.2 1150 | 1151 | picocolors@1.1.0: {} 1152 | 1153 | postcss@8.4.47: 1154 | dependencies: 1155 | nanoid: 3.3.7 1156 | picocolors: 1.1.0 1157 | source-map-js: 1.2.1 1158 | 1159 | prebuild-install@7.1.2: 1160 | dependencies: 1161 | detect-libc: 2.0.3 1162 | expand-template: 2.0.3 1163 | github-from-package: 0.0.0 1164 | minimist: 1.2.8 1165 | mkdirp-classic: 0.5.3 1166 | napi-build-utils: 1.0.2 1167 | node-abi: 3.68.0 1168 | pump: 3.0.2 1169 | rc: 1.2.8 1170 | simple-get: 4.0.1 1171 | tar-fs: 2.1.1 1172 | tunnel-agent: 0.6.0 1173 | 1174 | prettier-plugin-svelte@3.2.7(prettier@3.3.3)(svelte@4.2.19): 1175 | dependencies: 1176 | prettier: 3.3.3 1177 | svelte: 4.2.19 1178 | 1179 | prettier@3.3.3: {} 1180 | 1181 | pump@3.0.2: 1182 | dependencies: 1183 | end-of-stream: 1.4.4 1184 | once: 1.4.0 1185 | 1186 | rc@1.2.8: 1187 | dependencies: 1188 | deep-extend: 0.6.0 1189 | ini: 1.3.8 1190 | minimist: 1.2.8 1191 | strip-json-comments: 2.0.1 1192 | 1193 | readable-stream@3.6.2: 1194 | dependencies: 1195 | inherits: 2.0.4 1196 | string_decoder: 1.3.0 1197 | util-deprecate: 1.0.2 1198 | 1199 | readdirp@4.0.2: {} 1200 | 1201 | rollup@4.24.0: 1202 | dependencies: 1203 | '@types/estree': 1.0.6 1204 | optionalDependencies: 1205 | '@rollup/rollup-android-arm-eabi': 4.24.0 1206 | '@rollup/rollup-android-arm64': 4.24.0 1207 | '@rollup/rollup-darwin-arm64': 4.24.0 1208 | '@rollup/rollup-darwin-x64': 4.24.0 1209 | '@rollup/rollup-linux-arm-gnueabihf': 4.24.0 1210 | '@rollup/rollup-linux-arm-musleabihf': 4.24.0 1211 | '@rollup/rollup-linux-arm64-gnu': 4.24.0 1212 | '@rollup/rollup-linux-arm64-musl': 4.24.0 1213 | '@rollup/rollup-linux-powerpc64le-gnu': 4.24.0 1214 | '@rollup/rollup-linux-riscv64-gnu': 4.24.0 1215 | '@rollup/rollup-linux-s390x-gnu': 4.24.0 1216 | '@rollup/rollup-linux-x64-gnu': 4.24.0 1217 | '@rollup/rollup-linux-x64-musl': 4.24.0 1218 | '@rollup/rollup-win32-arm64-msvc': 4.24.0 1219 | '@rollup/rollup-win32-ia32-msvc': 4.24.0 1220 | '@rollup/rollup-win32-x64-msvc': 4.24.0 1221 | fsevents: 2.3.3 1222 | 1223 | sade@1.8.1: 1224 | dependencies: 1225 | mri: 1.2.0 1226 | 1227 | safe-buffer@5.2.1: {} 1228 | 1229 | semver@7.6.3: {} 1230 | 1231 | set-cookie-parser@2.7.0: {} 1232 | 1233 | simple-concat@1.0.1: {} 1234 | 1235 | simple-get@4.0.1: 1236 | dependencies: 1237 | decompress-response: 6.0.0 1238 | once: 1.4.0 1239 | simple-concat: 1.0.1 1240 | 1241 | sirv@2.0.4: 1242 | dependencies: 1243 | '@polka/url': 1.0.0-next.28 1244 | mrmime: 2.0.0 1245 | totalist: 3.0.1 1246 | 1247 | source-map-js@1.2.1: {} 1248 | 1249 | string_decoder@1.3.0: 1250 | dependencies: 1251 | safe-buffer: 5.2.1 1252 | 1253 | strip-json-comments@2.0.1: {} 1254 | 1255 | svelte-check@4.0.4(svelte@4.2.19)(typescript@5.6.2): 1256 | dependencies: 1257 | '@jridgewell/trace-mapping': 0.3.25 1258 | chokidar: 4.0.1 1259 | fdir: 6.4.0 1260 | picocolors: 1.1.0 1261 | sade: 1.8.1 1262 | svelte: 4.2.19 1263 | typescript: 5.6.2 1264 | transitivePeerDependencies: 1265 | - picomatch 1266 | 1267 | svelte-hmr@0.16.0(svelte@4.2.19): 1268 | dependencies: 1269 | svelte: 4.2.19 1270 | 1271 | svelte@4.2.19: 1272 | dependencies: 1273 | '@ampproject/remapping': 2.3.0 1274 | '@jridgewell/sourcemap-codec': 1.5.0 1275 | '@jridgewell/trace-mapping': 0.3.25 1276 | '@types/estree': 1.0.6 1277 | acorn: 8.12.1 1278 | aria-query: 5.3.2 1279 | axobject-query: 4.1.0 1280 | code-red: 1.0.4 1281 | css-tree: 2.3.1 1282 | estree-walker: 3.0.3 1283 | is-reference: 3.0.2 1284 | locate-character: 3.0.0 1285 | magic-string: 0.30.11 1286 | periscopic: 3.1.0 1287 | 1288 | tar-fs@2.1.1: 1289 | dependencies: 1290 | chownr: 1.1.4 1291 | mkdirp-classic: 0.5.3 1292 | pump: 3.0.2 1293 | tar-stream: 2.2.0 1294 | 1295 | tar-stream@2.2.0: 1296 | dependencies: 1297 | bl: 4.1.0 1298 | end-of-stream: 1.4.4 1299 | fs-constants: 1.0.0 1300 | inherits: 2.0.4 1301 | readable-stream: 3.6.2 1302 | 1303 | tiny-glob@0.2.9: 1304 | dependencies: 1305 | globalyzer: 0.1.0 1306 | globrex: 0.1.2 1307 | 1308 | totalist@3.0.1: {} 1309 | 1310 | tunnel-agent@0.6.0: 1311 | dependencies: 1312 | safe-buffer: 5.2.1 1313 | 1314 | typescript@5.6.2: {} 1315 | 1316 | undici-types@6.19.8: {} 1317 | 1318 | util-deprecate@1.0.2: {} 1319 | 1320 | vite@5.4.8(@types/node@22.7.4): 1321 | dependencies: 1322 | esbuild: 0.21.5 1323 | postcss: 8.4.47 1324 | rollup: 4.24.0 1325 | optionalDependencies: 1326 | '@types/node': 22.7.4 1327 | fsevents: 2.3.3 1328 | 1329 | vitefu@0.2.5(vite@5.4.8(@types/node@22.7.4)): 1330 | optionalDependencies: 1331 | vite: 5.4.8(@types/node@22.7.4) 1332 | 1333 | wrappy@1.0.2: {} 1334 | --------------------------------------------------------------------------------