From b6804e9ee22fd548508fc08a7862cd808d3903b5 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Tue, 13 Jan 2026 15:48:16 -0500 Subject: [PATCH 01/85] install better-auth package --- bun.lock | 27 +++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 28 insertions(+) diff --git a/bun.lock b/bun.lock index 7455016..4c07319 100644 --- a/bun.lock +++ b/bun.lock @@ -33,6 +33,7 @@ "@tanstack/table-core": "^8.21.3", "add": "^2.0.6", "arctic": "^3.7.0", + "better-auth": "^1.4.12", "bits-ui": "^2.14.4", "bun": "^1.3.5", "clsx": "^2.1.1", @@ -94,6 +95,14 @@ "@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="], + "@better-auth/core": ["@better-auth/core@1.4.12", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "zod": "^4.1.12" }, "peerDependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "better-call": "1.1.7", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" } }, "sha512-VfqZwMAEl9rnGx092BIZ2Q5z8rt7jjN2OAbvPqehufSKZGmh8JsdtZRBMl/CHQir9bwi2Ev0UF4+7TQp+DXEMg=="], + + "@better-auth/telemetry": ["@better-auth/telemetry@1.4.12", "", { "dependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21" }, "peerDependencies": { "@better-auth/core": "1.4.12" } }, "sha512-4q504Og42PzkUbZjXDt+FyeYaS0WZmAlEOC3nbBCZDObTVCRUnGgJW52B2maJ7BCVvAQgBGLEeQmQzU5+63J0A=="], + + "@better-auth/utils": ["@better-auth/utils@0.3.0", "", {}, "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw=="], + + "@better-fetch/fetch": ["@better-fetch/fetch@1.1.21", "", {}, "sha512-/ImESw0sskqlVR94jB+5+Pxjf+xBwDZF/N5+y2/q4EqD7IARUTSpPfIo8uf39SYpCxyOCtbyYpUrZ3F/k0zT4A=="], + "@colors/colors": ["@colors/colors@1.6.0", "", {}, "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA=="], "@dabh/diagnostics": ["@dabh/diagnostics@2.0.8", "", { "dependencies": { "@so-ric/colorspace": "^1.1.6", "enabled": "2.0.x", "kuler": "^2.0.0" } }, "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q=="], @@ -226,6 +235,8 @@ "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], + "@noble/ciphers": ["@noble/ciphers@2.1.1", "", {}, "sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw=="], + "@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], @@ -606,6 +617,10 @@ "before-after-hook": ["before-after-hook@3.0.2", "", {}, "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A=="], + "better-auth": ["better-auth@1.4.12", "", { "dependencies": { "@better-auth/core": "1.4.12", "@better-auth/telemetry": "1.4.12", "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "@noble/ciphers": "^2.0.0", "@noble/hashes": "^2.0.0", "better-call": "1.1.7", "defu": "^6.1.4", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1", "zod": "^4.1.12" }, "peerDependencies": { "@lynx-js/react": "*", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "@sveltejs/kit": "^2.0.0", "@tanstack/react-start": "^1.0.0", "better-sqlite3": "^12.0.0", "drizzle-kit": ">=0.31.4", "drizzle-orm": ">=0.41.0", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", "pg": "^8.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0", "vue": "^3.0.0" }, "optionalPeers": ["@lynx-js/react", "@prisma/client", "@sveltejs/kit", "@tanstack/react-start", "better-sqlite3", "drizzle-kit", "drizzle-orm", "mongodb", "mysql2", "next", "pg", "prisma", "react", "react-dom", "solid-js", "svelte", "vitest", "vue"] }, "sha512-FsFMnWgk+AGrxsIGbpWLCibgYcbm6uNhPHln3ohXFDXSRa0gk39Beuh54Q+x6ml2qYodF0snxf/tPtDpBI/JiA=="], + + "better-call": ["better-call@1.1.7", "", { "dependencies": { "@better-auth/utils": "^0.3.0", "@better-fetch/fetch": "^1.1.4", "rou3": "^0.7.10", "set-cookie-parser": "^2.7.1" }, "peerDependencies": { "zod": "^4.0.0" }, "optionalPeers": ["zod"] }, "sha512-6gaJe1bBIEgVebQu/7q9saahVzvBsGaByEnE8aDVncZEDiJO7sdNB28ot9I6iXSbR25egGmmZ6aIURXyQHRraQ=="], + "bits-ui": ["bits-ui@2.15.4", "", { "dependencies": { "@floating-ui/core": "^1.7.1", "@floating-ui/dom": "^1.7.1", "esm-env": "^1.1.2", "runed": "^0.35.1", "svelte-toolbelt": "^0.10.6", "tabbable": "^6.2.0" }, "peerDependencies": { "@internationalized/date": "^3.8.1", "svelte": "^5.33.0" } }, "sha512-7H9YUfp03KOk1LVDh8wPYSRPxlZgG/GRWLNSA8QC73/8Z8ytun+DWJhIuibyFyz7A0cP/RANVcB4iDrbY8q+Og=="], "bottleneck": ["bottleneck@2.19.5", "", {}, "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="], @@ -668,6 +683,8 @@ "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], + "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], + "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], @@ -816,6 +833,8 @@ "joi": ["joi@17.13.3", "", { "dependencies": { "@hapi/hoek": "^9.3.0", "@hapi/topo": "^5.1.0", "@sideway/address": "^4.1.5", "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } }, "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA=="], + "jose": ["jose@6.1.3", "", {}, "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ=="], + "joycon": ["joycon@3.1.1", "", {}, "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw=="], "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], @@ -836,6 +855,8 @@ "kuler": ["kuler@2.0.0", "", {}, "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="], + "kysely": ["kysely@0.28.9", "", {}, "sha512-3BeXMoiOhpOwu62CiVpO6lxfq4eS6KMYfQdMsN/2kUCRNuF2YiEr7u0HLHaQU+O4Xu8YXE3bHVkwaQ85i72EuA=="], + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], "libphonenumber-js": ["libphonenumber-js@1.12.34", "", {}, "sha512-v/Ip8k8eYdp7bINpzqDh46V/PaQ8sK+qi97nMQgjZzFlb166YFqlR/HVI+MzsI9JqcyyVWCOipmmretiaSyQyw=="], @@ -902,6 +923,8 @@ "nanoid": ["nanoid@5.1.6", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg=="], + "nanostores": ["nanostores@1.1.0", "", {}, "sha512-yJBmDJr18xy47dbNVlHcgdPrulSn1nhSE6Ns9vTG+Nx9VPT6iV1MD6aQFp/t52zpf82FhLLTXAXr30NuCnxvwA=="], + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], "node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="], @@ -1006,6 +1029,8 @@ "rollup": ["rollup@4.55.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.55.1", "@rollup/rollup-android-arm64": "4.55.1", "@rollup/rollup-darwin-arm64": "4.55.1", "@rollup/rollup-darwin-x64": "4.55.1", "@rollup/rollup-freebsd-arm64": "4.55.1", "@rollup/rollup-freebsd-x64": "4.55.1", "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", "@rollup/rollup-linux-arm-musleabihf": "4.55.1", "@rollup/rollup-linux-arm64-gnu": "4.55.1", "@rollup/rollup-linux-arm64-musl": "4.55.1", "@rollup/rollup-linux-loong64-gnu": "4.55.1", "@rollup/rollup-linux-loong64-musl": "4.55.1", "@rollup/rollup-linux-ppc64-gnu": "4.55.1", "@rollup/rollup-linux-ppc64-musl": "4.55.1", "@rollup/rollup-linux-riscv64-gnu": "4.55.1", "@rollup/rollup-linux-riscv64-musl": "4.55.1", "@rollup/rollup-linux-s390x-gnu": "4.55.1", "@rollup/rollup-linux-x64-gnu": "4.55.1", "@rollup/rollup-linux-x64-musl": "4.55.1", "@rollup/rollup-openbsd-x64": "4.55.1", "@rollup/rollup-openharmony-arm64": "4.55.1", "@rollup/rollup-win32-arm64-msvc": "4.55.1", "@rollup/rollup-win32-ia32-msvc": "4.55.1", "@rollup/rollup-win32-x64-gnu": "4.55.1", "@rollup/rollup-win32-x64-msvc": "4.55.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A=="], + "rou3": ["rou3@0.7.12", "", {}, "sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg=="], + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], "runed": ["runed@0.37.1", "", { "dependencies": { "dequal": "^2.0.3", "esm-env": "^1.0.0", "lz-string": "^1.5.0" }, "peerDependencies": { "@sveltejs/kit": "^2.21.0", "svelte": "^5.7.0", "zod": "^4.1.0" }, "optionalPeers": ["@sveltejs/kit", "zod"] }, "sha512-MeFY73xBW8IueWBm012nNFIGy19WUGPLtknavyUPMpnyt350M47PhGSGrGoSLbidwn+Zlt/O0cp8/OZE3LASWA=="], @@ -1202,6 +1227,8 @@ "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "better-auth/@noble/hashes": ["@noble/hashes@2.0.1", "", {}, "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw=="], + "bits-ui/runed": ["runed@0.35.1", "", { "dependencies": { "dequal": "^2.0.3", "esm-env": "^1.0.0", "lz-string": "^1.5.0" }, "peerDependencies": { "@sveltejs/kit": "^2.21.0", "svelte": "^5.7.0" }, "optionalPeers": ["@sveltejs/kit"] }, "sha512-2F4Q/FZzbeJTFdIS/PuOoPRSm92sA2LhzTnv6FXhCoENb3huf5+fDuNOg1LNvGOouy3u/225qxmuJvcV3IZK5Q=="], "color/color-convert": ["color-convert@3.1.3", "", { "dependencies": { "color-name": "^2.0.0" } }, "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg=="], diff --git a/package.json b/package.json index 17cedd8..f44272a 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,7 @@ "@tanstack/table-core": "^8.21.3", "add": "^2.0.6", "arctic": "^3.7.0", + "better-auth": "^1.4.12", "bits-ui": "^2.14.4", "bun": "^1.3.5", "clsx": "^2.1.1", From 9123bfc2c6b6f0374cc9f1efe30757587b46d076 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Tue, 13 Jan 2026 20:01:02 -0500 Subject: [PATCH 02/85] basic betterAuth server/client setup --- src/lib/auth/client.ts | 9 +++++++++ src/lib/auth/server.ts | 23 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/lib/auth/client.ts create mode 100644 src/lib/auth/server.ts diff --git a/src/lib/auth/client.ts b/src/lib/auth/client.ts new file mode 100644 index 0000000..c863ef6 --- /dev/null +++ b/src/lib/auth/client.ts @@ -0,0 +1,9 @@ +import { createAuthClient } from 'better-auth/svelte'; +import { inferAdditionalFields } from 'better-auth/client/plugins'; +import type { auth } from './server'; + +const authClient = createAuthClient({ + plugins: [inferAdditionalFields()] +}); + +export const { signIn, signUp, useSession } = authClient; diff --git a/src/lib/auth/server.ts b/src/lib/auth/server.ts new file mode 100644 index 0000000..ca39491 --- /dev/null +++ b/src/lib/auth/server.ts @@ -0,0 +1,23 @@ +import { serverEnv } from '$lib/env/server'; +import { db } from '$lib/server/db'; +import { betterAuth } from 'better-auth'; +import { drizzleAdapter } from 'better-auth/adapters/drizzle'; + +export const auth = betterAuth({ + database: drizzleAdapter(db, { + provider: 'pg' + }), + socialProviders: { + github: { + clientId: serverEnv.GITHUB_APP_CLIENT_ID, + clientSecret: serverEnv.GITHUB_APP_CLIENT_SECRET, + disableImplicitSignUp: true, + disableSignUp: true + } + }, + experimental: { joins: true } +}); + +export type AuthData = typeof auth.$Infer.Session; +export type User = AuthData['user']; +export type Session = AuthData['session']; From 7d0ffd59e9beec4153e8a7023ff69e116b43e0b0 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Tue, 13 Jan 2026 20:01:27 -0500 Subject: [PATCH 03/85] better auth handler function --- src/app.d.ts | 4 ++-- src/hooks.server.ts | 30 ++++++++++++------------------ 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/app.d.ts b/src/app.d.ts index 1c8a9fc..9a8468a 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -3,8 +3,8 @@ declare global { namespace App { interface Locals { - user: import('$lib/server/auth').SessionValidationResult['user']; - session: import('$lib/server/auth').SessionValidationResult['session']; + user: import('$lib/auth/server').User; + session: import('$lib/auth/server').Session; } } } diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 33a84cf..8949225 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -1,25 +1,19 @@ +import { auth } from '$lib/auth/server'; // path to your auth file +import { svelteKitHandler } from 'better-auth/svelte-kit'; +import { building } from '$app/environment'; import type { Handle } from '@sveltejs/kit'; -import * as auth from '$lib/server/auth.js'; -const handleAuth: Handle = async ({ event, resolve }) => { - const sessionToken = event.cookies.get(auth.sessionCookieName); - if (!sessionToken) { - event.locals.user = null; - event.locals.session = null; - return resolve(event); - } +export const handle: Handle = async ({ event, resolve }) => { + // Fetch current session from Better Auth + const session = await auth.api.getSession({ + headers: event.request.headers + }); - const { session, user } = await auth.validateSessionToken(sessionToken); + // Make session and user available on server if (session) { - auth.setSessionTokenCookie(event, sessionToken, session.expiresAt); - } else { - auth.deleteSessionTokenCookie(event); + event.locals.session = session.session; + event.locals.user = session.user; } - event.locals.user = user; - event.locals.session = session; - - return resolve(event); + return svelteKitHandler({ event, resolve, auth, building }); }; - -export const handle: Handle = handleAuth; From 09cc1539248efbe29b5982935eeb832d0d0caf75 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Tue, 13 Jan 2026 20:01:47 -0500 Subject: [PATCH 04/85] auth database schema with generation command --- package.json | 1 + src/lib/server/db/auth.ts | 93 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 src/lib/server/db/auth.ts diff --git a/package.json b/package.json index f44272a..f92196c 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "db:studio": "drizzle-kit studio", "db:gen": "drizzle-kit generate", "db:drop": "drizzle-kit drop", + "auth:db": "bunx @better-auth/cli@latest generate --config src/lib/auth/server.ts --output src/lib/server/db/auth.ts", "sv": "sv", "ui": "shadcn-svelte", "clean": "rm -rf .svelte-kit build" diff --git a/src/lib/server/db/auth.ts b/src/lib/server/db/auth.ts new file mode 100644 index 0000000..413a524 --- /dev/null +++ b/src/lib/server/db/auth.ts @@ -0,0 +1,93 @@ +import { relations } from "drizzle-orm"; +import { pgTable, text, timestamp, boolean, index } from "drizzle-orm/pg-core"; + +export const user = pgTable("user", { + id: text("id").primaryKey(), + name: text("name").notNull(), + email: text("email").notNull().unique(), + emailVerified: boolean("email_verified").default(false).notNull(), + image: text("image"), + createdAt: timestamp("created_at").defaultNow().notNull(), + updatedAt: timestamp("updated_at") + .defaultNow() + .$onUpdate(() => /* @__PURE__ */ new Date()) + .notNull(), +}); + +export const session = pgTable( + "session", + { + id: text("id").primaryKey(), + expiresAt: timestamp("expires_at").notNull(), + token: text("token").notNull().unique(), + createdAt: timestamp("created_at").defaultNow().notNull(), + updatedAt: timestamp("updated_at") + .$onUpdate(() => /* @__PURE__ */ new Date()) + .notNull(), + ipAddress: text("ip_address"), + userAgent: text("user_agent"), + userId: text("user_id") + .notNull() + .references(() => user.id, { onDelete: "cascade" }), + }, + (table) => [index("session_userId_idx").on(table.userId)], +); + +export const account = pgTable( + "account", + { + id: text("id").primaryKey(), + accountId: text("account_id").notNull(), + providerId: text("provider_id").notNull(), + userId: text("user_id") + .notNull() + .references(() => user.id, { onDelete: "cascade" }), + accessToken: text("access_token"), + refreshToken: text("refresh_token"), + idToken: text("id_token"), + accessTokenExpiresAt: timestamp("access_token_expires_at"), + refreshTokenExpiresAt: timestamp("refresh_token_expires_at"), + scope: text("scope"), + password: text("password"), + createdAt: timestamp("created_at").defaultNow().notNull(), + updatedAt: timestamp("updated_at") + .$onUpdate(() => /* @__PURE__ */ new Date()) + .notNull(), + }, + (table) => [index("account_userId_idx").on(table.userId)], +); + +export const verification = pgTable( + "verification", + { + id: text("id").primaryKey(), + identifier: text("identifier").notNull(), + value: text("value").notNull(), + expiresAt: timestamp("expires_at").notNull(), + createdAt: timestamp("created_at").defaultNow().notNull(), + updatedAt: timestamp("updated_at") + .defaultNow() + .$onUpdate(() => /* @__PURE__ */ new Date()) + .notNull(), + }, + (table) => [index("verification_identifier_idx").on(table.identifier)], +); + +export const userRelations = relations(user, ({ many }) => ({ + sessions: many(session), + accounts: many(account), +})); + +export const sessionRelations = relations(session, ({ one }) => ({ + user: one(user, { + fields: [session.userId], + references: [user.id], + }), +})); + +export const accountRelations = relations(account, ({ one }) => ({ + user: one(user, { + fields: [account.userId], + references: [user.id], + }), +})); From 26c13734bb5412d11fe16744c66d86ac0858b86b Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 12:32:40 -0500 Subject: [PATCH 05/85] react email --- bun.lock | 727 ++++++++++++++++++++++++++-- package.json | 10 + src/lib/email/emails/magic-link.tsx | 85 ++++ src/lib/email/index.tsx | 15 + src/lib/env/server.ts | 4 +- tsconfig.json | 31 +- 6 files changed, 840 insertions(+), 32 deletions(-) create mode 100644 src/lib/email/emails/magic-link.tsx create mode 100644 src/lib/email/index.tsx diff --git a/bun.lock b/bun.lock index 4c07319..6407764 100644 --- a/bun.lock +++ b/bun.lock @@ -5,6 +5,7 @@ "": { "name": "hackhelp", "dependencies": { + "@better-auth/passkey": "^1.4.12", "@faker-js/faker": "^9.9.0", "@fontsource-variable/inter": "^5.2.8", "@fontsource-variable/inter-tight": "^5.2.7", @@ -19,6 +20,7 @@ "@oslojs/crypto": "^1.0.1", "@oslojs/encoding": "^1.1.0", "@paralleldrive/cuid2": "^2.3.1", + "@react-email/components": "^1.0.4", "@sveltejs/adapter-auto": "^7.0.0", "@sveltejs/adapter-node": "^5.4.0", "@sveltejs/kit": "^2.49.2", @@ -45,6 +47,7 @@ "lucide-svelte": "^0.562.0", "mode-watcher": "^1.1.0", "nanoid": "^5.1.6", + "nodemailer": "^7.0.12", "octokit": "^4.1.4", "pino": "^10.1.0", "pino-pretty": "^13.1.3", @@ -66,9 +69,12 @@ }, "devDependencies": { "@eslint/compat": "^2.0.1", + "@react-email/preview-server": "5.2.3", "@sveltejs/vite-plugin-svelte": "^6.2.1", "@tailwindcss/vite": "^4.1.18", "@types/node": "^22.19.3", + "@types/nodemailer": "^7.0.5", + "@types/react": "^19.2.8", "eslint": "^9.39.2", "eslint-config-prettier": "^10.1.8", "eslint-plugin-svelte": "^3.13.1", @@ -76,6 +82,7 @@ "prettier": "^3.7.4", "prettier-plugin-svelte": "^3.4.1", "prettier-plugin-tailwindcss": "^0.7.2", + "react-email": "^5.2.3", "shadcn-svelte": "1.1.0", "sv": "^0.11.2", "svelte-check": "^4.3.5", @@ -93,10 +100,94 @@ "@ark/util": ["@ark/util@0.56.0", "", {}, "sha512-BghfRC8b9pNs3vBoDJhcta0/c1J1rsoS1+HgVUreMFPdhz/CRAKReAu57YEllNaSy98rWAdY1gE+gFup7OXpgA=="], + "@aws-crypto/sha256-browser": ["@aws-crypto/sha256-browser@5.2.0", "", { "dependencies": { "@aws-crypto/sha256-js": "^5.2.0", "@aws-crypto/supports-web-crypto": "^5.2.0", "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw=="], + + "@aws-crypto/sha256-js": ["@aws-crypto/sha256-js@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA=="], + + "@aws-crypto/supports-web-crypto": ["@aws-crypto/supports-web-crypto@5.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg=="], + + "@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="], + + "@aws-sdk/client-sesv2": ["@aws-sdk/client-sesv2@3.968.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.968.0", "@aws-sdk/credential-provider-node": "3.968.0", "@aws-sdk/middleware-host-header": "3.968.0", "@aws-sdk/middleware-logger": "3.968.0", "@aws-sdk/middleware-recursion-detection": "3.968.0", "@aws-sdk/middleware-user-agent": "3.968.0", "@aws-sdk/region-config-resolver": "3.968.0", "@aws-sdk/signature-v4-multi-region": "3.968.0", "@aws-sdk/types": "3.968.0", "@aws-sdk/util-endpoints": "3.968.0", "@aws-sdk/util-user-agent-browser": "3.968.0", "@aws-sdk/util-user-agent-node": "3.968.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.3", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.4", "@smithy/middleware-retry": "^4.4.20", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.5", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.19", "@smithy/util-defaults-mode-node": "^4.2.22", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-vuzF/4Ovzv2UW2iVVMNSu3yIIczzdUKBkkiXTvYYRmOL4Kjtq7RLu8A8O6jy+/mJoWW1CTyZH9pTc4MCQzjLIA=="], + + "@aws-sdk/client-sso": ["@aws-sdk/client-sso@3.968.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.968.0", "@aws-sdk/middleware-host-header": "3.968.0", "@aws-sdk/middleware-logger": "3.968.0", "@aws-sdk/middleware-recursion-detection": "3.968.0", "@aws-sdk/middleware-user-agent": "3.968.0", "@aws-sdk/region-config-resolver": "3.968.0", "@aws-sdk/types": "3.968.0", "@aws-sdk/util-endpoints": "3.968.0", "@aws-sdk/util-user-agent-browser": "3.968.0", "@aws-sdk/util-user-agent-node": "3.968.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.3", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.4", "@smithy/middleware-retry": "^4.4.20", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.5", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.19", "@smithy/util-defaults-mode-node": "^4.2.22", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-y+k23MvMzpn1WpeQ9sdEXg1Bbw7dfi0ZH2uwyBv78F/kz0mZOI+RJ1KJg8DgSD8XvdxB8gX5GQ8rzo0LnDothA=="], + + "@aws-sdk/core": ["@aws-sdk/core@3.968.0", "", { "dependencies": { "@aws-sdk/types": "3.968.0", "@aws-sdk/xml-builder": "3.968.0", "@smithy/core": "^3.20.3", "@smithy/node-config-provider": "^4.3.7", "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/signature-v4": "^5.3.7", "@smithy/smithy-client": "^4.10.5", "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-u4lIpvGqMMHZN523/RxW70xNoVXHBXucIWZsxFKc373E6TWYEb16ddFhXTELioS5TU93qkd/6yDQZzI6AAhbkw=="], + + "@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.968.0", "", { "dependencies": { "@aws-sdk/core": "3.968.0", "@aws-sdk/types": "3.968.0", "@smithy/property-provider": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-G+zgXEniQxBHFtHo+0yImkYutvJZLvWqvkPUP8/cG+IaYg54OY7L/GPIAZJh0U3m0Uepao98NbL15zjM+uplqQ=="], + + "@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.968.0", "", { "dependencies": { "@aws-sdk/core": "3.968.0", "@aws-sdk/types": "3.968.0", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/node-http-handler": "^4.4.7", "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.5", "@smithy/types": "^4.11.0", "@smithy/util-stream": "^4.5.8", "tslib": "^2.6.2" } }, "sha512-79teHBx/EtsNRR3Bq8fQdmMHtUcYwvohm9EwXXFt2Jd3BEOBH872IjIlfKdAvdkM+jW1QeeWOZBAxXGPir7GcQ=="], + + "@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.968.0", "", { "dependencies": { "@aws-sdk/core": "3.968.0", "@aws-sdk/credential-provider-env": "3.968.0", "@aws-sdk/credential-provider-http": "3.968.0", "@aws-sdk/credential-provider-login": "3.968.0", "@aws-sdk/credential-provider-process": "3.968.0", "@aws-sdk/credential-provider-sso": "3.968.0", "@aws-sdk/credential-provider-web-identity": "3.968.0", "@aws-sdk/nested-clients": "3.968.0", "@aws-sdk/types": "3.968.0", "@smithy/credential-provider-imds": "^4.2.7", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-9J9pcweoEN8yG7Qliux1zl9J3DT8X6OLcDN2RVXdTd5xzWBaYlupnUiJzoP6lvXdMnEmlDZaV7IMtoBdG7MY6g=="], + + "@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.968.0", "", { "dependencies": { "@aws-sdk/core": "3.968.0", "@aws-sdk/nested-clients": "3.968.0", "@aws-sdk/types": "3.968.0", "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-YxBaR0IMuHPOVTG+73Ve0QfllweN+EdwBRnHFhUGnahMGAcTmcaRdotqwqWfiws+9ud44IFKjxXR3t8jaGpFnQ=="], + + "@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.968.0", "", { "dependencies": { "@aws-sdk/credential-provider-env": "3.968.0", "@aws-sdk/credential-provider-http": "3.968.0", "@aws-sdk/credential-provider-ini": "3.968.0", "@aws-sdk/credential-provider-process": "3.968.0", "@aws-sdk/credential-provider-sso": "3.968.0", "@aws-sdk/credential-provider-web-identity": "3.968.0", "@aws-sdk/types": "3.968.0", "@smithy/credential-provider-imds": "^4.2.7", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-wei6v0c9vDEam8pM5eWe9bt+5ixg8nL0q+DFPzI6iwdLUqmJsPoAzWPEyMkgp03iE02SS2fMqPWpmRjz/NVyUw=="], + + "@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.968.0", "", { "dependencies": { "@aws-sdk/core": "3.968.0", "@aws-sdk/types": "3.968.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-my9M/ijRyEACoyeEWiC2sTVM3+eck5IWPGTPQrlYMKivy4LLlZchohtIopuqTom+JZzLZD508j1s9aDvl7BA0w=="], + + "@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.968.0", "", { "dependencies": { "@aws-sdk/client-sso": "3.968.0", "@aws-sdk/core": "3.968.0", "@aws-sdk/token-providers": "3.968.0", "@aws-sdk/types": "3.968.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-XPYPcxfWIt5jBbofoP2xhAHlFYos0dzwbHsoE18Cera/XnaCEbsUpdROo30t0Kjdbv0EWMYLMPDi9G+vPRDnhQ=="], + + "@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.968.0", "", { "dependencies": { "@aws-sdk/core": "3.968.0", "@aws-sdk/nested-clients": "3.968.0", "@aws-sdk/types": "3.968.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-9HNAP6mx2jsBW4moWnRg5ycyZ0C1EbtMIegIHa93ga13B/8VZF9Y0iDnwW73yQYzCEt9UrDiFeRck/ChZup3rA=="], + + "@aws-sdk/middleware-host-header": ["@aws-sdk/middleware-host-header@3.968.0", "", { "dependencies": { "@aws-sdk/types": "3.968.0", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-ujlNT215VtE/2D2jEhFVcTuPPB36HJyLBM0ytnni/WPIjzq89iJrKR1tEhxpk8uct6A5NSQ6w9Y7g2Rw1rkSoQ=="], + + "@aws-sdk/middleware-logger": ["@aws-sdk/middleware-logger@3.968.0", "", { "dependencies": { "@aws-sdk/types": "3.968.0", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-zvhhEPZgvaRDxzf27m2WmgaXoN7upFt/gvG7ofBN5zCBlkh3JtFamMh5KWYVQwMhc4eQBK3NjH0oIUKZSVztag=="], + + "@aws-sdk/middleware-recursion-detection": ["@aws-sdk/middleware-recursion-detection@3.968.0", "", { "dependencies": { "@aws-sdk/types": "3.968.0", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-KygPiwpSAPGobgodK/oLb7OLiwK29pNJeNtP+GZ9pxpceDRqhN0Ub8Eo84dBbWq+jbzAqBYHzy+B1VsbQ/hLWA=="], + + "@aws-sdk/middleware-sdk-s3": ["@aws-sdk/middleware-sdk-s3@3.968.0", "", { "dependencies": { "@aws-sdk/core": "3.968.0", "@aws-sdk/types": "3.968.0", "@aws-sdk/util-arn-parser": "3.968.0", "@smithy/core": "^3.20.3", "@smithy/node-config-provider": "^4.3.7", "@smithy/protocol-http": "^5.3.7", "@smithy/signature-v4": "^5.3.7", "@smithy/smithy-client": "^4.10.5", "@smithy/types": "^4.11.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-stream": "^4.5.8", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-fh2mQ/uwJ1Sth1q2dWAbeyky/SBPaqe1fjxvsNeEY6dtfi8PjW85zHpz1JoAhCKTRkrEdXYAqkqUwsUydLucyQ=="], + + "@aws-sdk/middleware-user-agent": ["@aws-sdk/middleware-user-agent@3.968.0", "", { "dependencies": { "@aws-sdk/core": "3.968.0", "@aws-sdk/types": "3.968.0", "@aws-sdk/util-endpoints": "3.968.0", "@smithy/core": "^3.20.3", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-4h5/B8FyxMjLxtXd5jbM2R69aO57qQiHoAJQTtkpuxmM7vhvjSxEQtMM9L1kuMXoMVNE7xM4886h0+gbmmxplg=="], + + "@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.968.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.968.0", "@aws-sdk/middleware-host-header": "3.968.0", "@aws-sdk/middleware-logger": "3.968.0", "@aws-sdk/middleware-recursion-detection": "3.968.0", "@aws-sdk/middleware-user-agent": "3.968.0", "@aws-sdk/region-config-resolver": "3.968.0", "@aws-sdk/types": "3.968.0", "@aws-sdk/util-endpoints": "3.968.0", "@aws-sdk/util-user-agent-browser": "3.968.0", "@aws-sdk/util-user-agent-node": "3.968.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.3", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.4", "@smithy/middleware-retry": "^4.4.20", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.5", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.19", "@smithy/util-defaults-mode-node": "^4.2.22", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-LLppm+8MzD3afD2IA/tYDp5AoVPOybK7MHQz5DVB4HsZ+fHvwYlvau2ZUK8nKwJSk5c1kWcxCZkyuJQjFu37ng=="], + + "@aws-sdk/region-config-resolver": ["@aws-sdk/region-config-resolver@3.968.0", "", { "dependencies": { "@aws-sdk/types": "3.968.0", "@smithy/config-resolver": "^4.4.5", "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-BzrCpxEsAHbi+yDGtgXJ+/5AvLPjfhcT6DlL+Fc4g13J5Z0VwiO95Wem+Q4KK7WDZH7/sZ/1WFvfitjLTKZbEw=="], + + "@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.968.0", "", { "dependencies": { "@aws-sdk/middleware-sdk-s3": "3.968.0", "@aws-sdk/types": "3.968.0", "@smithy/protocol-http": "^5.3.7", "@smithy/signature-v4": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-kRBA1KK3LTHnfYJLPsESNF2WhQN6DyGc9MiM6qG8AdJwMPQkanF5hwtckV1ToO2KB5v1q+1PuvBvy6Npd2IV+w=="], + + "@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.968.0", "", { "dependencies": { "@aws-sdk/core": "3.968.0", "@aws-sdk/nested-clients": "3.968.0", "@aws-sdk/types": "3.968.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-lXUZqB2qTFmZYNXPnVT0suSHGiuQAPrL2DhmhbjqOdR7+GKDHL5KbeKFvPisy7Y4neliJqT4Q1VPWa0nqYaiZg=="], + + "@aws-sdk/types": ["@aws-sdk/types@3.968.0", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-Wuumj/1cuiuXTMdHmvH88zbEl+5Pw++fOFQuMCF4yP0R+9k1lwX8rVst+oy99xaxtdluJZXrsccoZoA67ST1Ow=="], + + "@aws-sdk/util-arn-parser": ["@aws-sdk/util-arn-parser@3.968.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-gqqvYcitIIM2K4lrDX9de9YvOfXBcVdxfT/iLnvHJd4YHvSXlt+gs+AsL4FfPCxG4IG9A+FyulP9Sb1MEA75vw=="], + + "@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.968.0", "", { "dependencies": { "@aws-sdk/types": "3.968.0", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-endpoints": "^3.2.7", "tslib": "^2.6.2" } }, "sha512-9IdilgylS0crFSeI59vtr8qhDYMYYOvnvkl1dLp59+EmLH1IdXz7+4cR5oh5PkoqD7DRzc5Uzm2GnZhK6I0oVQ=="], + + "@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.965.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-qKgO7wAYsXzhwCHhdbaKFyxd83Fgs8/1Ka+jjSPrv2Ll7mB55Wbwlo0kkfMLh993/yEc8aoDIAc1Fz9h4Spi4Q=="], + + "@aws-sdk/util-user-agent-browser": ["@aws-sdk/util-user-agent-browser@3.968.0", "", { "dependencies": { "@aws-sdk/types": "3.968.0", "@smithy/types": "^4.11.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-nRxjs8Jpq8ZHFsa/0uiww2f4+40D6Dt6bQmepAJHIE/D+atwPINDKsfamCjFnxrjKU3WBWpGYEf/QDO0XZsFMw=="], + + "@aws-sdk/util-user-agent-node": ["@aws-sdk/util-user-agent-node@3.968.0", "", { "dependencies": { "@aws-sdk/middleware-user-agent": "3.968.0", "@aws-sdk/types": "3.968.0", "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "peerDependencies": { "aws-crt": ">=1.0.0" }, "optionalPeers": ["aws-crt"] }, "sha512-oaIkPGraGhZgkDmxVhTIlakaUNWKO9aMN+uB6I+eS26MWi/lpMK66HTZeXEnaTrmt5/kl99YC0N37zScz58Tdg=="], + + "@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.968.0", "", { "dependencies": { "@smithy/types": "^4.11.0", "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" } }, "sha512-bZQKn41ebPh/uW9uWUE5oLuaBr44Gt78dkw2amu5zcwo1J/d8s6FdzZcRDmz0rHE2NHJWYkdQYeVQo7jhMziqA=="], + + "@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.3", "", {}, "sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw=="], + + "@babel/code-frame": ["@babel/code-frame@7.28.6", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q=="], + + "@babel/generator": ["@babel/generator@7.28.6", "", { "dependencies": { "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw=="], + + "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], + + "@babel/parser": ["@babel/parser@7.28.6", "", { "dependencies": { "@babel/types": "^7.28.6" }, "bin": "./bin/babel-parser.js" }, "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ=="], + "@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="], + "@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="], + + "@babel/traverse": ["@babel/traverse@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.6", "@babel/template": "^7.28.6", "@babel/types": "^7.28.6", "debug": "^4.3.1" } }, "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg=="], + + "@babel/types": ["@babel/types@7.28.6", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg=="], + "@better-auth/core": ["@better-auth/core@1.4.12", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "zod": "^4.1.12" }, "peerDependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "better-call": "1.1.7", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" } }, "sha512-VfqZwMAEl9rnGx092BIZ2Q5z8rt7jjN2OAbvPqehufSKZGmh8JsdtZRBMl/CHQir9bwi2Ev0UF4+7TQp+DXEMg=="], + "@better-auth/passkey": ["@better-auth/passkey@1.4.12", "", { "dependencies": { "@simplewebauthn/browser": "^13.1.2", "@simplewebauthn/server": "^13.1.2", "zod": "^4.1.12" }, "peerDependencies": { "@better-auth/core": "1.4.12", "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "better-auth": "1.4.12", "better-call": "1.1.7", "nanostores": "^1.0.1" } }, "sha512-1ZDkwhHSrxAU1Kn13z98QrzzGFTyMHaGKbPIzP4HAmDDhDIwLFgo2kViYzZHgWGwPM1gXYCQLfFv/NoFEdrEaA=="], + "@better-auth/telemetry": ["@better-auth/telemetry@1.4.12", "", { "dependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21" }, "peerDependencies": { "@better-auth/core": "1.4.12" } }, "sha512-4q504Og42PzkUbZjXDt+FyeYaS0WZmAlEOC3nbBCZDObTVCRUnGgJW52B2maJ7BCVvAQgBGLEeQmQzU5+63J0A=="], "@better-auth/utils": ["@better-auth/utils@0.3.0", "", {}, "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw=="], @@ -119,57 +210,57 @@ "@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="], - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="], + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], - "@esbuild/android-arm": ["@esbuild/android-arm@0.27.2", "", { "os": "android", "cpu": "arm" }, "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA=="], + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.2", "", { "os": "android", "cpu": "arm64" }, "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA=="], + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], - "@esbuild/android-x64": ["@esbuild/android-x64@0.27.2", "", { "os": "android", "cpu": "x64" }, "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A=="], + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg=="], + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA=="], + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g=="], + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA=="], + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.2", "", { "os": "linux", "cpu": "arm" }, "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw=="], + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw=="], + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w=="], + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg=="], + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw=="], + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ=="], + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA=="], + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w=="], + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA=="], + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw=="], + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.2", "", { "os": "none", "cpu": "x64" }, "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA=="], + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA=="], + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg=="], + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], - "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag=="], + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg=="], + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg=="], + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ=="], + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.2", "", { "os": "win32", "cpu": "x64" }, "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ=="], + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="], @@ -213,6 +304,8 @@ "@hapi/topo": ["@hapi/topo@5.1.0", "", { "dependencies": { "@hapi/hoek": "^9.0.0" } }, "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg=="], + "@hexagon/base64": ["@hexagon/base64@1.1.28", "", {}, "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw=="], + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], "@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="], @@ -221,8 +314,64 @@ "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], + "@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="], + + "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="], + + "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="], + + "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="], + + "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="], + + "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="], + + "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="], + + "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA=="], + + "@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.2.4", "", { "os": "linux", "cpu": "none" }, "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA=="], + + "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ=="], + + "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="], + + "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="], + + "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="], + + "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="], + + "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="], + + "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.4" }, "os": "linux", "cpu": "ppc64" }, "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA=="], + + "@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.2.4" }, "os": "linux", "cpu": "none" }, "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw=="], + + "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.4" }, "os": "linux", "cpu": "s390x" }, "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg=="], + + "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="], + + "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="], + + "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="], + + "@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.5", "", { "dependencies": { "@emnapi/runtime": "^1.7.0" }, "cpu": "none" }, "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw=="], + + "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="], + + "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg=="], + + "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="], + "@internationalized/date": ["@internationalized/date@3.10.1", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-oJrXtQiAXLvT9clCf1K4kxp3eKsQhIaZqxEyowkBcsvZDdZkbWrVmnGknxs5flTD0VGsxrxKgBCZty1EzoiMzA=="], + "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="], + + "@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="], + + "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], @@ -233,8 +382,28 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], + "@levischuck/tiny-cbor": ["@levischuck/tiny-cbor@0.2.11", "", {}, "sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow=="], + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], + "@next/env": ["@next/env@16.0.10", "", {}, "sha512-8tuaQkyDVgeONQ1MeT9Mkk8pQmZapMKFh5B+OrFUlG3rVmYTXcXlBetBgTurKXGaIZvkoqRT9JL5K3phXcgang=="], + + "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.0.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4XgdKtdVsaflErz+B5XeG0T5PeXKDdruDf3CRpnhN+8UebNa5N2H58+3GDgpn/9GBurrQ1uWW768FfscwYkJRg=="], + + "@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.0.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-spbEObMvRKkQ3CkYVOME+ocPDFo5UqHb8EMTS78/0mQ+O1nqE8toHJVioZo4TvebATxgA8XMTHHrScPrn68OGw=="], + + "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.0.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-uQtWE3X0iGB8apTIskOMi2w/MKONrPOUCi5yLO+v3O8Mb5c7K4Q5KD1jvTpTF5gJKa3VH/ijKjKUq9O9UhwOYw=="], + + "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.0.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-llA+hiDTrYvyWI21Z0L1GiXwjQaanPVQQwru5peOgtooeJ8qx3tlqRV2P7uH2pKQaUfHxI/WVarvI5oYgGxaTw=="], + + "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.0.10", "", { "os": "linux", "cpu": "x64" }, "sha512-AK2q5H0+a9nsXbeZ3FZdMtbtu9jxW4R/NgzZ6+lrTm3d6Zb7jYrWcgjcpM1k8uuqlSy4xIyPR2YiuUr+wXsavA=="], + + "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.0.10", "", { "os": "linux", "cpu": "x64" }, "sha512-1TDG9PDKivNw5550S111gsO4RGennLVl9cipPhtkXIFVwo31YZ73nEbLjNC8qG3SgTz/QZyYyaFYMeY4BKZR/g=="], + + "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.0.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-aEZIS4Hh32xdJQbHz121pyuVZniSNoqDVx1yIr2hy+ZwJGipeqnMZBJHyMxv2tiuAXGx6/xpTcQJ6btIiBjgmg=="], + + "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.0.10", "", { "os": "win32", "cpu": "x64" }, "sha512-E+njfCoFLb01RAFEnGZn6ERoOqhK1Gl3Lfz1Kjnj0Ulfu7oJbuMyvBKNj/bw8XZnenHDASlygTjZICQW+rYW1Q=="], + "@noble/ciphers": ["@noble/ciphers@2.1.1", "", {}, "sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw=="], "@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], @@ -361,6 +530,30 @@ "@paralleldrive/cuid2": ["@paralleldrive/cuid2@2.3.1", "", { "dependencies": { "@noble/hashes": "^1.1.5" } }, "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw=="], + "@peculiar/asn1-android": ["@peculiar/asn1-android@2.6.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-cBRCKtYPF7vJGN76/yG8VbxRcHLPF3HnkoHhKOZeHpoVtbMYfY9ROKtH3DtYUY9m8uI1Mh47PRhHf2hSK3xcSQ=="], + + "@peculiar/asn1-cms": ["@peculiar/asn1-cms@2.6.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "@peculiar/asn1-x509-attr": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-2uZqP+ggSncESeUF/9Su8rWqGclEfEiz1SyU02WX5fUONFfkjzS2Z/F1Li0ofSmf4JqYXIOdCAZqIXAIBAT1OA=="], + + "@peculiar/asn1-csr": ["@peculiar/asn1-csr@2.6.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-BeWIu5VpTIhfRysfEp73SGbwjjoLL/JWXhJ/9mo4vXnz3tRGm+NGm3KNcRzQ9VMVqwYS2RHlolz21svzRXIHPQ=="], + + "@peculiar/asn1-ecc": ["@peculiar/asn1-ecc@2.6.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-FF3LMGq6SfAOwUG2sKpPXblibn6XnEIKa+SryvUl5Pik+WR9rmRA3OCiwz8R3lVXnYnyRkSZsSLdml8H3UiOcw=="], + + "@peculiar/asn1-pfx": ["@peculiar/asn1-pfx@2.6.0", "", { "dependencies": { "@peculiar/asn1-cms": "^2.6.0", "@peculiar/asn1-pkcs8": "^2.6.0", "@peculiar/asn1-rsa": "^2.6.0", "@peculiar/asn1-schema": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-rtUvtf+tyKGgokHHmZzeUojRZJYPxoD/jaN1+VAB4kKR7tXrnDCA/RAWXAIhMJJC+7W27IIRGe9djvxKgsldCQ=="], + + "@peculiar/asn1-pkcs8": ["@peculiar/asn1-pkcs8@2.6.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-KyQ4D8G/NrS7Fw3XCJrngxmjwO/3htnA0lL9gDICvEQ+GJ+EPFqldcJQTwPIdvx98Tua+WjkdKHSC0/Km7T+lA=="], + + "@peculiar/asn1-pkcs9": ["@peculiar/asn1-pkcs9@2.6.0", "", { "dependencies": { "@peculiar/asn1-cms": "^2.6.0", "@peculiar/asn1-pfx": "^2.6.0", "@peculiar/asn1-pkcs8": "^2.6.0", "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "@peculiar/asn1-x509-attr": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-b78OQ6OciW0aqZxdzliXGYHASeCvvw5caqidbpQRYW2mBtXIX2WhofNXTEe7NyxTb0P6J62kAAWLwn0HuMF1Fw=="], + + "@peculiar/asn1-rsa": ["@peculiar/asn1-rsa@2.6.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-Nu4C19tsrTsCp9fDrH+sdcOKoVfdfoQQ7S3VqjJU6vedR7tY3RLkQ5oguOIB3zFW33USDUuYZnPEQYySlgha4w=="], + + "@peculiar/asn1-schema": ["@peculiar/asn1-schema@2.6.0", "", { "dependencies": { "asn1js": "^3.0.6", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "sha512-xNLYLBFTBKkCzEZIw842BxytQQATQv+lDTCEMZ8C196iJcJJMBUZxrhSTxLaohMyKK8QlzRNTRkUmanucnDSqg=="], + + "@peculiar/asn1-x509": ["@peculiar/asn1-x509@2.6.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "asn1js": "^3.0.6", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "sha512-uzYbPEpoQiBoTq0/+jZtpM6Gq6zADBx+JNFP3yqRgziWBxQ/Dt/HcuvRfm9zJTPdRcBqPNdaRHTVwpyiq6iNMA=="], + + "@peculiar/asn1-x509-attr": ["@peculiar/asn1-x509-attr@2.6.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-MuIAXFX3/dc8gmoZBkwJWxUWOSvG4MMDntXhrOZpJVMkYX+MYc/rUAU2uJOved9iJEoiUx7//3D8oG83a78UJA=="], + + "@peculiar/x509": ["@peculiar/x509@1.14.3", "", { "dependencies": { "@peculiar/asn1-cms": "^2.6.0", "@peculiar/asn1-csr": "^2.6.0", "@peculiar/asn1-ecc": "^2.6.0", "@peculiar/asn1-pkcs9": "^2.6.0", "@peculiar/asn1-rsa": "^2.6.0", "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "pvtsutils": "^1.3.6", "reflect-metadata": "^0.2.2", "tslib": "^2.8.1", "tsyringe": "^4.10.0" } }, "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA=="], + "@petamoriken/float16": ["@petamoriken/float16@3.9.3", "", {}, "sha512-8awtpHXCx/bNpFt4mt2xdkgtgVvKqty8VbjHI/WWWQuEw+KLzFot3f4+LkQY9YmOtq7A5GdOnqoIC8Pdygjk2g=="], "@pinojs/redact": ["@pinojs/redact@0.4.0", "", {}, "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg=="], @@ -373,6 +566,50 @@ "@posthog/types": ["@posthog/types@1.318.1", "", {}, "sha512-FYjHp4wlYvt4xc7MM+zIjfYICY/+lvjby/nOib29psTuUMT3nJXwqWz65QBox6XldaJdeId5F+UW6IOtJ1Q9iA=="], + "@react-email/body": ["@react-email/body@0.2.1", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-ljDiQiJDu/Fq//vSIIP0z5Nuvt4+DX1RqGasstChDGJB/14ogd4VdNS9aacoede/ZjGy3o3Qb+cxyS+XgM6SwQ=="], + + "@react-email/button": ["@react-email/button@0.2.1", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-qXyj7RZLE7POy9BMKSoqQ00tOXThjOZSUnI2Yu9i29IHngPlmrNayIWBoVKtElES7OWwypUcpiajwi1mUWx6/A=="], + + "@react-email/code-block": ["@react-email/code-block@0.2.1", "", { "dependencies": { "prismjs": "^1.30.0" }, "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-M3B7JpVH4ytgn83/ujRR1k1DQHvTeABiDM61OvAbjLRPhC/5KLHU5KkzIbbuGIrjWwxAbL1kSQzU8MhLEtSxyw=="], + + "@react-email/code-inline": ["@react-email/code-inline@0.0.6", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-jfhebvv3dVsp3OdPgKXnk8+e2pBiDVZejDOBFzBa/IblrAJ9cQDkN6rBD5IyEg8hTOxwbw3iaI/yZFmDmIguIA=="], + + "@react-email/column": ["@react-email/column@0.0.14", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-f+W+Bk2AjNO77zynE33rHuQhyqVICx4RYtGX9NKsGUg0wWjdGP0qAuIkhx9Rnmk4/hFMo1fUrtYNqca9fwJdHg=="], + + "@react-email/components": ["@react-email/components@1.0.4", "", { "dependencies": { "@react-email/body": "0.2.1", "@react-email/button": "0.2.1", "@react-email/code-block": "0.2.1", "@react-email/code-inline": "0.0.6", "@react-email/column": "0.0.14", "@react-email/container": "0.0.16", "@react-email/font": "0.0.10", "@react-email/head": "0.0.13", "@react-email/heading": "0.0.16", "@react-email/hr": "0.0.12", "@react-email/html": "0.0.12", "@react-email/img": "0.0.12", "@react-email/link": "0.0.13", "@react-email/markdown": "0.0.18", "@react-email/preview": "0.0.14", "@react-email/render": "2.0.2", "@react-email/row": "0.0.13", "@react-email/section": "0.0.17", "@react-email/tailwind": "2.0.3", "@react-email/text": "0.1.6" }, "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-XpSs/mN0APMD9E3TYZnj8N6kRXqb6WBl9WrE+IHyB4PdgLNqXe7uZ5+5oZkKSE8Tskzw/K2vDJUqSZ2v+sRjUA=="], + + "@react-email/container": ["@react-email/container@0.0.16", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-QWBB56RkkU0AJ9h+qy33gfT5iuZknPC7Un/IjZv9B0QmMIK+WWacc0cH6y2SV5Cv/b99hU94fjEMOOO4enpkbQ=="], + + "@react-email/font": ["@react-email/font@0.0.10", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-0urVSgCmQIfx5r7Xc586miBnQUVnGp3OTYUm8m5pwtQRdTRO5XrTtEfNJ3JhYhSOruV0nD8fd+dXtKXobum6tA=="], + + "@react-email/head": ["@react-email/head@0.0.13", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-AJg6le/08Gz4tm+6MtKXqtNNyKHzmooOCdmtqmWxD7FxoAdU1eVcizhtQ0gcnVaY6ethEyE/hnEzQxt1zu5Kog=="], + + "@react-email/heading": ["@react-email/heading@0.0.16", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-jmsKnQm1ykpBzw4hCYHwBkt5pW2jScXffPeEH5ZRF5tZeF5b1pvlFTO9han7C0pCkZYo1kEvWiRtx69yfCIwuw=="], + + "@react-email/hr": ["@react-email/hr@0.0.12", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-TwmOmBDibavUQpXBxpmZYi2Iks/yeZOzFYh+di9EltMSnEabH8dMZXrl+pxNXzCgZ2XE8HY7VmUL65Lenfu5PA=="], + + "@react-email/html": ["@react-email/html@0.0.12", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-KTShZesan+UsreU7PDUV90afrZwU5TLwYlALuCSU0OT+/U8lULNNbAUekg+tGwCnOfIKYtpDPKkAMRdYlqUznw=="], + + "@react-email/img": ["@react-email/img@0.0.12", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-sRCpEARNVTf3FQhZOC+JTvu5r6ubiYWkT0ucYXg8ctkyi4G8QG+jgYPiNUqVeTLA2STOfmPM/nrk1nb84y6CPQ=="], + + "@react-email/link": ["@react-email/link@0.0.13", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-lkWc/NjOcefRZMkQoSDDbuKBEBDES9aXnFEOuPH845wD3TxPwh+QTf0fStuzjoRLUZWpHnio4z7qGGRYusn/sw=="], + + "@react-email/markdown": ["@react-email/markdown@0.0.18", "", { "dependencies": { "marked": "^15.0.12" }, "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-gSuYK5fsMbGk87jDebqQ6fa2fKcWlkf2Dkva8kMONqLgGCq8/0d+ZQYMEJsdidIeBo3kmsnHZPrwdFB4HgjUXg=="], + + "@react-email/preview": ["@react-email/preview@0.0.14", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-aYK8q0IPkBXyMsbpMXgxazwHxYJxTrXrV95GFuu2HbEiIToMwSyUgb8HDFYwPqqfV03/jbwqlsXmFxsOd+VNaw=="], + + "@react-email/preview-server": ["@react-email/preview-server@5.2.3", "", { "dependencies": { "next": "16.0.10" } }, "sha512-1kVIyCGBaHd++N0LAuuIFohS33TvGA/nx3yLlWPBKLW5Wjit9X1MNisoH45tG3bOmx84YZvbtXI++0hPkKL/tQ=="], + + "@react-email/render": ["@react-email/render@2.0.2", "", { "dependencies": { "html-to-text": "^9.0.5", "prettier": "^3.5.3" }, "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-AGuNo86TP9Y2JBUwFcT+z0frPDML4WLIFlnCi7laCPYJA+43kdim0y+qRNPxRxZkJiUz1JMPnE2M5HaNYhWwIg=="], + + "@react-email/row": ["@react-email/row@0.0.13", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-bYnOac40vIKCId7IkwuLAAsa3fKfSfqCvv6epJKmPE0JBuu5qI4FHFCl9o9dVpIIS08s/ub+Y/txoMt0dYziGw=="], + + "@react-email/section": ["@react-email/section@0.0.17", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-qNl65ye3W0Rd5udhdORzTV9ezjb+GFqQQSae03NDzXtmJq6sqVXNWNiVolAjvJNypim+zGXmv6J9TcV5aNtE/w=="], + + "@react-email/tailwind": ["@react-email/tailwind@2.0.3", "", { "dependencies": { "tailwindcss": "^4.1.18" }, "peerDependencies": { "@react-email/body": "0.2.1", "@react-email/button": "0.2.1", "@react-email/code-block": "0.2.1", "@react-email/code-inline": "0.0.6", "@react-email/container": "0.0.16", "@react-email/heading": "0.0.16", "@react-email/hr": "0.0.12", "@react-email/img": "0.0.12", "@react-email/link": "0.0.13", "@react-email/preview": "0.0.14", "@react-email/text": "0.1.6", "react": "^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@react-email/body", "@react-email/button", "@react-email/code-block", "@react-email/code-inline", "@react-email/container", "@react-email/heading", "@react-email/hr", "@react-email/img", "@react-email/link", "@react-email/preview"] }, "sha512-URXb/T2WS4RlNGM5QwekYnivuiVUcU87H0y5sqLl6/Oi3bMmgL0Bmw/W9GeJylC+876Vw+E6NkE0uRiUFIQwGg=="], + + "@react-email/text": ["@react-email/text@0.1.6", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-TYqkioRS45wTR5il3dYk/SbUjjEdhSwh9BtRNB99qNH1pXAwA45H7rAuxehiu8iJQJH0IyIr+6n62gBz9ezmsw=="], + "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-beta.9-commit.d91dfb5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Mp0/gqiPdepHjjVm7e0yL1acWvI0rJVVFQEADSezvAjon9sjQ7CEg9JnXICD4B1YrPmN9qV/e7cQZCp87tTV4w=="], "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-beta.9-commit.d91dfb5", "", { "os": "darwin", "cpu": "x64" }, "sha512-40re4rMNrsi57oavRzIOpRGmg3QRlW6Ea8Q3znaqgOuJuKVrrm2bIQInTfkZJG7a4/5YMX7T951d0+toGLTdCA=="], @@ -457,14 +694,102 @@ "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.55.1", "", { "os": "win32", "cpu": "x64" }, "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw=="], + "@selderee/plugin-htmlparser2": ["@selderee/plugin-htmlparser2@0.11.0", "", { "dependencies": { "domhandler": "^5.0.3", "selderee": "^0.11.0" } }, "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ=="], + "@sideway/address": ["@sideway/address@4.1.5", "", { "dependencies": { "@hapi/hoek": "^9.0.0" } }, "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q=="], "@sideway/formula": ["@sideway/formula@3.0.1", "", {}, "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg=="], "@sideway/pinpoint": ["@sideway/pinpoint@2.0.0", "", {}, "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ=="], + "@simplewebauthn/browser": ["@simplewebauthn/browser@13.2.2", "", {}, "sha512-FNW1oLQpTJyqG5kkDg5ZsotvWgmBaC6jCHR7Ej0qUNep36Wl9tj2eZu7J5rP+uhXgHaLk+QQ3lqcw2vS5MX1IA=="], + + "@simplewebauthn/server": ["@simplewebauthn/server@13.2.2", "", { "dependencies": { "@hexagon/base64": "^1.1.27", "@levischuck/tiny-cbor": "^0.2.2", "@peculiar/asn1-android": "^2.3.10", "@peculiar/asn1-ecc": "^2.3.8", "@peculiar/asn1-rsa": "^2.3.8", "@peculiar/asn1-schema": "^2.3.8", "@peculiar/asn1-x509": "^2.3.8", "@peculiar/x509": "^1.13.0" } }, "sha512-HcWLW28yTMGXpwE9VLx9J+N2KEUaELadLrkPEEI9tpI5la70xNEVEsu/C+m3u7uoq4FulLqZQhgBCzR9IZhFpA=="], + + "@smithy/abort-controller": ["@smithy/abort-controller@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw=="], + + "@smithy/config-resolver": ["@smithy/config-resolver@4.4.6", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ=="], + + "@smithy/core": ["@smithy/core@3.20.5", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.9", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-stream": "^4.5.10", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-0Tz77Td8ynHaowXfOdrD0F1IH4tgWGUhwmLwmpFyTbr+U9WHXNNp9u/k2VjBXGnSe7BwjBERRpXsokGTXzNjhA=="], + + "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.8", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-FNT0xHS1c/CPN8upqbMFP83+ul5YgdisfCfkZ86Jh2NSmnqw/AJ6x5pEogVCTVvSm7j9MopRU89bmDelxuDMYw=="], + + "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.3.9", "", { "dependencies": { "@smithy/protocol-http": "^5.3.8", "@smithy/querystring-builder": "^4.2.8", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" } }, "sha512-I4UhmcTYXBrct03rwzQX1Y/iqQlzVQaPxWjCjula++5EmWq9YGBrx6bbGqluGc1f0XEfhSkiY4jhLgbsJUMKRA=="], + + "@smithy/hash-node": ["@smithy/hash-node@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-7ZIlPbmaDGxVoxErDZnuFG18WekhbA/g2/i97wGj+wUBeS6pcUeAym8u4BXh/75RXWhgIJhyC11hBzig6MljwA=="], + + "@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-N9iozRybwAQ2dn9Fot9kI6/w9vos2oTXLhtK7ovGqwZjlOcxu6XhPlpLpC+INsxktqHinn5gS2DXDjDF2kG5sQ=="], + + "@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], + + "@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.2.8", "", { "dependencies": { "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A=="], + + "@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.4.6", "", { "dependencies": { "@smithy/core": "^3.20.5", "@smithy/middleware-serde": "^4.2.9", "@smithy/node-config-provider": "^4.3.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-middleware": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-dpq3bHqbEOBqGBjRVHVFP3eUSPpX0BYtg1D5d5Irgk6orGGAuZfY22rC4sErhg+ZfY/Y0kPqm1XpAmDZg7DeuA=="], + + "@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.22", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/service-error-classification": "^4.2.8", "@smithy/smithy-client": "^4.10.7", "@smithy/types": "^4.12.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-vwWDMaObSMjw6WCC/3Ae9G7uul5Sk95jr07CDk1gkIMpaDic0phPS1MpVAZ6+YkF7PAzRlpsDjxPwRlh/S11FQ=="], + + "@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.9", "", { "dependencies": { "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ=="], + + "@smithy/middleware-stack": ["@smithy/middleware-stack@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-w6LCfOviTYQjBctOKSwy6A8FIkQy7ICvglrZFl6Bw4FmcQ1Z420fUtIhxaUZZshRe0VCq4kvDiPiXrPZAe8oRA=="], + + "@smithy/node-config-provider": ["@smithy/node-config-provider@4.3.8", "", { "dependencies": { "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-aFP1ai4lrbVlWjfpAfRSL8KFcnJQYfTl5QxLJXY32vghJrDuFyPZ6LtUL+JEGYiFRG1PfPLHLoxj107ulncLIg=="], + + "@smithy/node-http-handler": ["@smithy/node-http-handler@4.4.8", "", { "dependencies": { "@smithy/abort-controller": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/querystring-builder": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-q9u+MSbJVIJ1QmJ4+1u+cERXkrhuILCBDsJUBAW1MPE6sFonbCNaegFuwW9ll8kh5UdyY3jOkoOGlc7BesoLpg=="], + + "@smithy/property-provider": ["@smithy/property-provider@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-EtCTbyIveCKeOXDSWSdze3k612yCPq1YbXsbqX3UHhkOSW8zKsM9NOJG5gTIya0vbY2DIaieG8pKo1rITHYL0w=="], + + "@smithy/protocol-http": ["@smithy/protocol-http@5.3.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-QNINVDhxpZ5QnP3aviNHQFlRogQZDfYlCkQT+7tJnErPQbDhysondEjhikuANxgMsZrkGeiAxXy4jguEGsDrWQ=="], + + "@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-Xr83r31+DrE8CP3MqPgMJl+pQlLLmOfiEUnoyAlGzzJIrEsbKsPy1hqH0qySaQm4oWrCBlUqRt+idEgunKB+iw=="], + + "@smithy/querystring-parser": ["@smithy/querystring-parser@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-vUurovluVy50CUlazOiXkPq40KGvGWSdmusa3130MwrR1UNnNgKAlj58wlOe61XSHRpUfIIh6cE0zZ8mzKaDPA=="], + + "@smithy/service-error-classification": ["@smithy/service-error-classification@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0" } }, "sha512-mZ5xddodpJhEt3RkCjbmUQuXUOaPNTkbMGR0bcS8FE0bJDLMZlhmpgrvPNCYglVw5rsYTpSnv19womw9WWXKQQ=="], + + "@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.4.3", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DfQjxXQnzC5UbCUPeC3Ie8u+rIWZTvuDPAGU/BxzrOGhRvgUanaP68kDZA+jaT3ZI+djOf+4dERGlm9mWfFDrg=="], + + "@smithy/signature-v4": ["@smithy/signature-v4@5.3.8", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg=="], + + "@smithy/smithy-client": ["@smithy/smithy-client@4.10.7", "", { "dependencies": { "@smithy/core": "^3.20.5", "@smithy/middleware-endpoint": "^4.4.6", "@smithy/middleware-stack": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-stream": "^4.5.10", "tslib": "^2.6.2" } }, "sha512-Uznt0I9z3os3Z+8pbXrOSCTXCA6vrjyN7Ub+8l2pRDum44vLv8qw0qGVkJN0/tZBZotaEFHrDPKUoPNueTr5Vg=="], + + "@smithy/types": ["@smithy/types@4.12.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw=="], + + "@smithy/url-parser": ["@smithy/url-parser@4.2.8", "", { "dependencies": { "@smithy/querystring-parser": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-NQho9U68TGMEU639YkXnVMV3GEFFULmmaWdlu1E9qzyIePOHsoSnagTGSDv1Zi8DCNN6btxOSdgmy5E/hsZwhA=="], + + "@smithy/util-base64": ["@smithy/util-base64@4.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ=="], + + "@smithy/util-body-length-browser": ["@smithy/util-body-length-browser@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg=="], + + "@smithy/util-body-length-node": ["@smithy/util-body-length-node@4.2.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA=="], + + "@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="], + + "@smithy/util-config-provider": ["@smithy/util-config-provider@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q=="], + + "@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.21", "", { "dependencies": { "@smithy/property-provider": "^4.2.8", "@smithy/smithy-client": "^4.10.7", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DtmVJarzqtjghtGjCw/PFJolcJkP7GkZgy+hWTAN3YLXNH+IC82uMoMhFoC3ZtIz5mOgCm5+hOGi1wfhVYgrxw=="], + + "@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.24", "", { "dependencies": { "@smithy/config-resolver": "^4.4.6", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/smithy-client": "^4.10.7", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-JelBDKPAVswVY666rezBvY6b0nF/v9TXjUbNwDNAyme7qqKYEX687wJv0uze8lBIZVbg30wlWnlYfVSjjpKYFA=="], + + "@smithy/util-endpoints": ["@smithy/util-endpoints@3.2.8", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-8JaVTn3pBDkhZgHQ8R0epwWt+BqPSLCjdjXXusK1onwJlRuN69fbvSK66aIKKO7SwVFM6x2J2ox5X8pOaWcUEw=="], + + "@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="], + + "@smithy/util-middleware": ["@smithy/util-middleware@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-PMqfeJxLcNPMDgvPbbLl/2Vpin+luxqTGPpW3NAQVLbRrFRzTa4rNAASYeIGjRV9Ytuhzny39SpyU04EQreF+A=="], + + "@smithy/util-retry": ["@smithy/util-retry@4.2.8", "", { "dependencies": { "@smithy/service-error-classification": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-CfJqwvoRY0kTGe5AkQokpURNCT1u/MkRzMTASWMPPo2hNSnKtF1D45dQl3DE2LKLr4m+PW9mCeBMJr5mCAVThg=="], + + "@smithy/util-stream": ["@smithy/util-stream@4.5.10", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.9", "@smithy/node-http-handler": "^4.4.8", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-jbqemy51UFSZSp2y0ZmRfckmrzuKww95zT9BYMmuJ8v3altGcqjwoV1tzpOwuHaKrwQrCjIzOib499ymr2f98g=="], + + "@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="], + + "@smithy/util-utf8": ["@smithy/util-utf8@4.2.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw=="], + + "@smithy/uuid": ["@smithy/uuid@1.1.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw=="], + "@so-ric/colorspace": ["@so-ric/colorspace@1.1.6", "", { "dependencies": { "color": "^5.0.2", "text-hex": "1.0.x" } }, "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw=="], + "@socket.io/component-emitter": ["@socket.io/component-emitter@3.1.2", "", {}, "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA=="], + "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], "@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.8", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-esgN+54+q0NjB0Y/4BomT9samII7jGwNy/2a3wNZbT2A2RpmXsXwUt24LvLhx6jUq2gVk4cWEvcRO6MFQbOfNA=="], @@ -479,7 +804,7 @@ "@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@5.0.2", "", { "dependencies": { "obug": "^2.1.0" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-TZzRTcEtZffICSAoZGkPSl6Etsj2torOVrx6Uw0KpXxrec9Gg6jFWQ60Q3+LmNGfZSxHRCZL7vXVZIWmuV50Ig=="], - "@swc/helpers": ["@swc/helpers@0.5.18", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ=="], + "@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="], "@t3-oss/env-core": ["@t3-oss/env-core@0.12.0", "", { "peerDependencies": { "typescript": ">=5.0.0", "valibot": "^1.0.0-beta.7 || ^1.0.0", "zod": "^3.24.0" }, "optionalPeers": ["typescript", "valibot", "zod"] }, "sha512-lOPj8d9nJJTt81mMuN9GMk8x5veOt7q9m11OSnCBJhwp1QrL/qR+M8Y467ULBSm9SunosryWNbmQQbgoiMgcdw=="], @@ -541,12 +866,18 @@ "@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="], + "@types/cors": ["@types/cors@2.8.19", "", { "dependencies": { "@types/node": "*" } }, "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg=="], + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], "@types/node": ["@types/node@22.19.5", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-HfF8+mYcHPcPypui3w3mvzuIErlNOh2OAG+BCeBZCEwyiD5ls2SiCwEyT47OELtf7M3nHxBdu0FsmzdKxkN52Q=="], + "@types/nodemailer": ["@types/nodemailer@7.0.5", "", { "dependencies": { "@aws-sdk/client-sesv2": "^3.839.0", "@types/node": "*" } }, "sha512-7WtR4MFJUNN2UFy0NIowBRJswj5KXjXDhlZY43Hmots5eGu5q/dTeFd/I6GgJA/qj3RqO6dDy4SvfcV3fOVeIA=="], + + "@types/react": ["@types/react@19.2.8", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg=="], + "@types/resolve": ["@types/resolve@1.20.2", "", {}, "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="], "@types/triple-beam": ["@types/triple-beam@1.3.5", "", {}, "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw=="], @@ -585,6 +916,8 @@ "@vinejs/vine": ["@vinejs/vine@3.0.1", "", { "dependencies": { "@poppinss/macroable": "^1.0.4", "@types/validator": "^13.12.2", "@vinejs/compiler": "^3.0.0", "camelcase": "^8.0.0", "dayjs": "^1.11.13", "dlv": "^1.1.3", "normalize-url": "^8.0.1", "validator": "^13.12.0" } }, "sha512-ZtvYkYpZOYdvbws3uaOAvTFuvFXoQGAtmzeiXu+XSMGxi5GVsODpoI9Xu9TplEMuD/5fmAtBbKb9cQHkWkLXDQ=="], + "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], + "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], @@ -593,6 +926,10 @@ "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="], + + "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "ansis": ["ansis@4.2.0", "", {}, "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig=="], @@ -607,14 +944,20 @@ "arktype": ["arktype@2.1.29", "", { "dependencies": { "@ark/schema": "0.56.0", "@ark/util": "0.56.0", "arkregex": "0.0.5" } }, "sha512-jyfKk4xIOzvYNayqnD8ZJQqOwcrTOUbIU4293yrzAjA3O1dWh61j71ArMQ6tS/u4pD7vabSPe7nG3RCyoXW6RQ=="], + "asn1js": ["asn1js@3.0.7", "", { "dependencies": { "pvtsutils": "^1.3.6", "pvutils": "^1.1.3", "tslib": "^2.8.1" } }, "sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ=="], + "async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="], "atomic-sleep": ["atomic-sleep@1.0.0", "", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="], + "atomically": ["atomically@2.1.0", "", { "dependencies": { "stubborn-fs": "^2.0.0", "when-exit": "^2.1.4" } }, "sha512-+gDffFXRW6sl/HCwbta7zK4uNqbPjv4YJEAdz7Vu+FLQHe77eZ4bvbJGi4hE0QPeJlMYMA3piXEr1UL3dAwx7Q=="], + "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "base64id": ["base64id@2.0.0", "", {}, "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="], + "before-after-hook": ["before-after-hook@3.0.2", "", {}, "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A=="], "better-auth": ["better-auth@1.4.12", "", { "dependencies": { "@better-auth/core": "1.4.12", "@better-auth/telemetry": "1.4.12", "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "@noble/ciphers": "^2.0.0", "@noble/hashes": "^2.0.0", "better-call": "1.1.7", "defu": "^6.1.4", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1", "zod": "^4.1.12" }, "peerDependencies": { "@lynx-js/react": "*", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "@sveltejs/kit": "^2.0.0", "@tanstack/react-start": "^1.0.0", "better-sqlite3": "^12.0.0", "drizzle-kit": ">=0.31.4", "drizzle-orm": ">=0.41.0", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", "pg": "^8.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0", "vue": "^3.0.0" }, "optionalPeers": ["@lynx-js/react", "@prisma/client", "@sveltejs/kit", "@tanstack/react-start", "better-sqlite3", "drizzle-kit", "drizzle-orm", "mongodb", "mysql2", "next", "pg", "prisma", "react", "react-dom", "solid-js", "svelte", "vitest", "vue"] }, "sha512-FsFMnWgk+AGrxsIGbpWLCibgYcbm6uNhPHln3ohXFDXSRa0gk39Beuh54Q+x6ml2qYodF0snxf/tPtDpBI/JiA=="], @@ -625,6 +968,8 @@ "bottleneck": ["bottleneck@2.19.5", "", {}, "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="], + "bowser": ["bowser@2.13.1", "", {}, "sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw=="], + "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], @@ -637,12 +982,22 @@ "camelcase": ["camelcase@8.0.0", "", {}, "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA=="], + "caniuse-lite": ["caniuse-lite@1.0.30001764", "", {}, "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g=="], + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], + "citty": ["citty@0.1.6", "", { "dependencies": { "consola": "^3.2.3" } }, "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ=="], + "class-validator": ["class-validator@0.14.3", "", { "dependencies": { "@types/validator": "^13.15.3", "libphonenumber-js": "^1.11.1", "validator": "^13.15.20" } }, "sha512-rXXekcjofVN1LTOSw+u4u9WXVEUvNBVjORW154q/IdmYWy1nMbOU9aNtZB0t8m+FJQ9q91jlr2f9CwwUFdFMRA=="], + "cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="], + + "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="], + + "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="], + "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], "color": ["color@5.0.3", "", { "dependencies": { "color-convert": "^3.1.3", "color-string": "^2.1.3" } }, "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA=="], @@ -655,28 +1010,42 @@ "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], - "commander": ["commander@14.0.2", "", {}, "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ=="], + "commander": ["commander@13.1.0", "", {}, "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw=="], "commondir": ["commondir@1.0.1", "", {}, "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="], "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + "conf": ["conf@15.0.2", "", { "dependencies": { "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "atomically": "^2.0.3", "debounce-fn": "^6.0.0", "dot-prop": "^10.0.0", "env-paths": "^3.0.0", "json-schema-typed": "^8.0.1", "semver": "^7.7.2", "uint8array-extras": "^1.5.0" } }, "sha512-JBSrutapCafTrddF9dH3lc7+T2tBycGF4uPkI4Js+g4vLLEhG6RZcFi3aJd5zntdf5tQxAejJt8dihkoQ/eSJw=="], + + "confbox": ["confbox@0.2.2", "", {}, "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="], + + "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], + "cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="], "copy-anything": ["copy-anything@4.0.5", "", { "dependencies": { "is-what": "^5.2.0" } }, "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA=="], "core-js": ["core-js@3.47.0", "", {}, "sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg=="], + "cors": ["cors@2.8.5", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g=="], + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], + "date-fns": ["date-fns@4.1.0", "", {}, "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg=="], "dateformat": ["dateformat@4.6.3", "", {}, "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA=="], "dayjs": ["dayjs@1.11.19", "", {}, "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw=="], + "debounce": ["debounce@2.2.0", "", {}, "sha512-Xks6RUDLZFdz8LIdR6q0MTH44k7FikOmnh5xkSjMig6ch45afc8sjTjRQf3P6ax8dMgcQrYO/AR2RGWURrruqw=="], + + "debounce-fn": ["debounce-fn@6.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-rBMW+F2TXryBwB54Q0d8drNEI+TfoS9JpNTAoVpukbWEhjXQq4rySFYLaqXMFXwdv61Zb2OHtj5bviSoimqxRQ=="], + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], @@ -693,23 +1062,43 @@ "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], + "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], + + "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], + + "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], + "dompurify": ["dompurify@3.3.1", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q=="], + "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], + + "dot-prop": ["dot-prop@10.1.0", "", { "dependencies": { "type-fest": "^5.0.0" } }, "sha512-MVUtAugQMOff5RnBy2d9N31iG0lNwg1qAoAOn7pOK5wf94WIaE3My2p3uwTQuvS2AcqchkcR3bHByjaM0mmi7Q=="], + "drizzle-kit": ["drizzle-kit@0.30.6", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.19.7", "esbuild-register": "^3.5.0", "gel": "^2.0.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-U4wWit0fyZuGuP7iNmRleQyK2V8wCuv57vf5l3MnG4z4fzNTjY/U13M8owyQ5RavqvqxBifWORaR3wIUzlN64g=="], "drizzle-orm": ["drizzle-orm@0.39.3", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-EZ8ZpYvDIvKU9C56JYLOmUskazhad+uXZCTCRN4OnRMsL+xAJ05dv1eCpAG5xzhsm1hqiuC5kAZUCS924u2DTw=="], + "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], + "effect": ["effect@3.19.14", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-3vwdq0zlvQOxXzXNKRIPKTqZNMyGCdaFUBfMPqpsyzZDre67kgC1EEHDV4EoQTovJ4w5fmJW756f86kkuz7WFA=="], + "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], + "enabled": ["enabled@2.0.0", "", {}, "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="], "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], + "engine.io": ["engine.io@6.6.5", "", { "dependencies": { "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.4.1", "engine.io-parser": "~5.2.1", "ws": "~8.18.3" } }, "sha512-2RZdgEbXmp5+dVbRm0P7HQUImZpICccJy7rN7Tv+SFa55pH+lxnuw6/K1ZxxBfHoYpSkHLAO92oa8O4SwFXA2A=="], + + "engine.io-parser": ["engine.io-parser@5.2.3", "", {}, "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q=="], + "enhanced-resolve": ["enhanced-resolve@5.18.4", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q=="], + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + "env-paths": ["env-paths@3.0.0", "", {}, "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A=="], - "esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="], + "esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], "esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="], @@ -743,6 +1132,8 @@ "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + "exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="], + "fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "^6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="], "fast-content-type-parse": ["fast-content-type-parse@2.0.1", "", {}, "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q=="], @@ -759,6 +1150,10 @@ "fast-safe-stringify": ["fast-safe-stringify@2.1.1", "", {}, "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="], + "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], + + "fast-xml-parser": ["fast-xml-parser@5.2.5", "", { "dependencies": { "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ=="], + "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], @@ -779,6 +1174,8 @@ "fn.name": ["fn.name@1.1.0", "", {}, "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="], + "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], + "formsnap": ["formsnap@2.0.1", "", { "dependencies": { "svelte-toolbelt": "^0.5.0" }, "peerDependencies": { "svelte": "^5.0.0", "sveltekit-superforms": "^2.19.0" } }, "sha512-iJSe4YKd/W6WhLwKDVJU9FQeaJRpEFuolhju7ZXlRpUVyDdqFdMP8AUBICgnVvQPyP41IPAlBa/v0Eo35iE6wQ=="], "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], @@ -787,8 +1184,12 @@ "gel": ["gel@2.2.0", "", { "dependencies": { "@petamoriken/float16": "^3.8.7", "debug": "^4.3.4", "env-paths": "^3.0.0", "semver": "^7.6.2", "shell-quote": "^1.8.1", "which": "^4.0.0" }, "bin": { "gel": "dist/cli.mjs" } }, "sha512-q0ma7z2swmoamHQusey8ayo8+ilVdzDt4WTxSPzq/yRqvucWRfymRVMvNgmSC0XK7eNjjEZEcplxpgaNojKdmQ=="], + "get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="], + "get-tsconfig": ["get-tsconfig@4.13.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ=="], + "glob": ["glob@11.1.0", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw=="], + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], "globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="], @@ -801,6 +1202,10 @@ "help-me": ["help-me@5.0.0", "", {}, "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg=="], + "html-to-text": ["html-to-text@9.0.5", "", { "dependencies": { "@selderee/plugin-htmlparser2": "^0.11.0", "deepmerge": "^4.3.1", "dom-serializer": "^2.0.0", "htmlparser2": "^8.0.2", "selderee": "^0.11.0" } }, "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg=="], + + "htmlparser2": ["htmlparser2@8.0.2", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1", "entities": "^4.4.0" } }, "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA=="], + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], @@ -815,8 +1220,12 @@ "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + "is-interactive": ["is-interactive@2.0.0", "", {}, "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="], + "is-module": ["is-module@1.0.0", "", {}, "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="], "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], @@ -825,10 +1234,14 @@ "is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], + "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="], + "is-what": ["is-what@5.5.0", "", {}, "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw=="], "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + "jackspeak": ["jackspeak@4.1.1", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" } }, "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ=="], + "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], "joi": ["joi@17.13.3", "", { "dependencies": { "@hapi/hoek": "^9.3.0", "@hapi/topo": "^5.1.0", "@sideway/address": "^4.1.5", "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } }, "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA=="], @@ -837,16 +1250,24 @@ "joycon": ["joycon@3.1.1", "", {}, "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw=="], + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], + "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], "json-schema-to-ts": ["json-schema-to-ts@3.1.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "ts-algebra": "^2.0.0" } }, "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g=="], "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + "json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="], + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], @@ -857,6 +1278,8 @@ "kysely": ["kysely@0.28.9", "", {}, "sha512-3BeXMoiOhpOwu62CiVpO6lxfq4eS6KMYfQdMsN/2kUCRNuF2YiEr7u0HLHaQU+O4Xu8YXE3bHVkwaQ85i72EuA=="], + "leac": ["leac@0.6.0", "", {}, "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg=="], + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], "libphonenumber-js": ["libphonenumber-js@1.12.34", "", {}, "sha512-v/Ip8k8eYdp7bINpzqDh46V/PaQ8sK+qi97nMQgjZzFlb166YFqlR/HVI+MzsI9JqcyyVWCOipmmretiaSyQyw=="], @@ -893,26 +1316,40 @@ "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + "log-symbols": ["log-symbols@7.0.1", "", { "dependencies": { "is-unicode-supported": "^2.0.0", "yoctocolors": "^2.1.1" } }, "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg=="], + "logform": ["logform@2.7.0", "", { "dependencies": { "@colors/colors": "1.6.0", "@types/triple-beam": "^1.3.2", "fecha": "^4.2.0", "ms": "^2.1.1", "safe-stable-stringify": "^2.3.1", "triple-beam": "^1.3.0" } }, "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ=="], + "lru-cache": ["lru-cache@11.2.4", "", {}, "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg=="], + "lucide-svelte": ["lucide-svelte@0.562.0", "", { "peerDependencies": { "svelte": "^3 || ^4 || ^5.0.0-next.42" } }, "sha512-kSJDH/55lf0mun/o4nqWBXOcq0fWYzPeIjbTD97ywoeumAB9kWxtM06gC7oynqjtK3XhAljWSz5RafIzPEYIQA=="], "lz-string": ["lz-string@1.5.0", "", { "bin": { "lz-string": "bin/bin.js" } }, "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ=="], "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + "marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="], + "memoize-weak": ["memoize-weak@1.0.2", "", {}, "sha512-gj39xkrjEw7nCn4nJ1M5ms6+MyMlyiGmttzsqAUsAKn6bYKwuTHh/AO3cKPF8IBrTIYTxb0wWXFs3E//Y8VoWQ=="], "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], + + "mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], + + "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="], + "mini-svg-data-uri": ["mini-svg-data-uri@1.4.4", "", { "bin": { "mini-svg-data-uri": "cli.js" } }, "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg=="], "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + "mode-watcher": ["mode-watcher@1.1.0", "", { "dependencies": { "runed": "^0.25.0", "svelte-toolbelt": "^0.7.1" }, "peerDependencies": { "svelte": "^5.27.0" } }, "sha512-mUT9RRGPDYenk59qJauN1rhsIMKBmWA3xMF+uRwE8MW/tjhaDSCCARqkSuDTq8vr4/2KcAxIGVjACxTjdk5C3g=="], "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], @@ -927,10 +1364,22 @@ "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], + + "next": ["next@16.0.10", "", { "dependencies": { "@next/env": "16.0.10", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.0.10", "@next/swc-darwin-x64": "16.0.10", "@next/swc-linux-arm64-gnu": "16.0.10", "@next/swc-linux-arm64-musl": "16.0.10", "@next/swc-linux-x64-gnu": "16.0.10", "@next/swc-linux-x64-musl": "16.0.10", "@next/swc-win32-arm64-msvc": "16.0.10", "@next/swc-win32-x64-msvc": "16.0.10", "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-RtWh5PUgI+vxlV3HdR+IfWA1UUHu0+Ram/JBO4vWB54cVPentCD0e+lxyAYEsDTqGGMg7qpjhKh6dc6aW7W/sA=="], + "node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="], + "nodemailer": ["nodemailer@7.0.12", "", {}, "sha512-H+rnK5bX2Pi/6ms3sN4/jRQvYSMltV6vqup/0SFOrxYYY/qoNvhXPlYq3e+Pm9RFJRwrMGbMIwi81M4dxpomhA=="], + + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + "normalize-url": ["normalize-url@8.1.1", "", {}, "sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ=="], + "nypm": ["nypm@0.6.2", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.2", "pathe": "^2.0.3", "pkg-types": "^2.3.0", "tinyexec": "^1.0.1" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g=="], + + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + "obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="], "octokit": ["octokit@4.1.4", "", { "dependencies": { "@octokit/app": "^15.1.6", "@octokit/core": "^6.1.5", "@octokit/oauth-app": "^7.1.6", "@octokit/plugin-paginate-graphql": "^5.2.4", "@octokit/plugin-paginate-rest": "^12.0.0", "@octokit/plugin-rest-endpoint-methods": "^14.0.0", "@octokit/plugin-retry": "^7.2.1", "@octokit/plugin-throttling": "^10.0.0", "@octokit/request-error": "^6.1.8", "@octokit/types": "^14.0.0", "@octokit/webhooks": "^13.8.3" } }, "sha512-cRvxRte6FU3vAHRC9+PMSY3D+mRAs2Rd9emMoqp70UGRvJRM3sbAoim2IXRZNNsf8wVfn4sGxVBHRAP+JBVX/g=="], @@ -941,22 +1390,36 @@ "one-time": ["one-time@1.0.0", "", { "dependencies": { "fn.name": "1.x.x" } }, "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g=="], + "onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], + "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="], "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + "ora": ["ora@8.2.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="], + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + "parseley": ["parseley@0.12.1", "", { "dependencies": { "leac": "^0.6.0", "peberminta": "^0.9.0" } }, "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw=="], + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], + "path-scurry": ["path-scurry@2.0.1", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA=="], + + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "peberminta": ["peberminta@0.9.0", "", {}, "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ=="], + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], @@ -969,6 +1432,8 @@ "pino-std-serializers": ["pino-std-serializers@7.0.0", "", {}, "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA=="], + "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="], + "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], "postcss-load-config": ["postcss-load-config@3.1.4", "", { "dependencies": { "lilconfig": "^2.0.5", "yaml": "^1.10.2" }, "peerDependencies": { "postcss": ">=8.0.9", "ts-node": ">=9.0.0" }, "optionalPeers": ["postcss", "ts-node"] }, "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg=="], @@ -993,8 +1458,12 @@ "prettier-plugin-tailwindcss": ["prettier-plugin-tailwindcss@0.7.2", "", { "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-hermes": "*", "@prettier/plugin-oxc": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", "@zackad/prettier-plugin-twig": "*", "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", "prettier-plugin-jsdoc": "*", "prettier-plugin-marko": "*", "prettier-plugin-multiline-arrays": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", "prettier-plugin-sort-imports": "*", "prettier-plugin-svelte": "*" }, "optionalPeers": ["@ianvs/prettier-plugin-sort-imports", "@prettier/plugin-hermes", "@prettier/plugin-oxc", "@prettier/plugin-pug", "@shopify/prettier-plugin-liquid", "@trivago/prettier-plugin-sort-imports", "@zackad/prettier-plugin-twig", "prettier-plugin-astro", "prettier-plugin-css-order", "prettier-plugin-jsdoc", "prettier-plugin-marko", "prettier-plugin-multiline-arrays", "prettier-plugin-organize-attributes", "prettier-plugin-organize-imports", "prettier-plugin-sort-imports", "prettier-plugin-svelte"] }, "sha512-LkphyK3Fw+q2HdMOoiEHWf93fNtYJwfamoKPl7UwtjFQdei/iIBoX11G6j706FzN3ymX9mPVi97qIY8328vdnA=="], + "prismjs": ["prismjs@1.30.0", "", {}, "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw=="], + "process-warning": ["process-warning@5.0.0", "", {}, "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA=="], + "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="], + "property-expr": ["property-expr@2.0.6", "", {}, "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA=="], "pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="], @@ -1003,6 +1472,10 @@ "pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="], + "pvtsutils": ["pvtsutils@1.3.6", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg=="], + + "pvutils": ["pvutils@1.1.5", "", {}, "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA=="], + "query-selector-shadow-dom": ["query-selector-shadow-dom@1.0.1", "", {}, "sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw=="], "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], @@ -1011,18 +1484,30 @@ "radash": ["radash@12.1.1", "", {}, "sha512-h36JMxKRqrAxVD8201FrCpyeNuUY9Y5zZwujr20fFO77tpUtGa6EZzfKw/3WaiBX95fq7+MpsuMLNdSnORAwSA=="], + "react": ["react@19.2.3", "", {}, "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA=="], + + "react-dom": ["react-dom@19.2.3", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.3" } }, "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg=="], + + "react-email": ["react-email@5.2.3", "", { "dependencies": { "@babel/parser": "^7.27.0", "@babel/traverse": "^7.27.0", "chokidar": "^4.0.3", "commander": "^13.0.0", "conf": "^15.0.2", "debounce": "^2.0.0", "esbuild": "^0.25.0", "glob": "^11.0.0", "jiti": "2.4.2", "log-symbols": "^7.0.0", "mime-types": "^3.0.0", "normalize-path": "^3.0.0", "nypm": "0.6.2", "ora": "^8.0.0", "prompts": "2.4.2", "socket.io": "^4.8.1", "tsconfig-paths": "4.2.0" }, "bin": { "email": "dist/index.js" } }, "sha512-EJZLLsdaFD7DYHQKMotpm5tiUp5Fp/FFB6x8VlZA5z20itiJsQ5zBaTTPBDE0KhJXvAUhBbKjC1BheCEchVoOg=="], + "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], "real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="], + "reflect-metadata": ["reflect-metadata@0.2.2", "", {}, "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q=="], + + "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + "resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], + "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], "rolldown": ["rolldown@1.0.0-beta.9-commit.d91dfb5", "", { "dependencies": { "@oxc-project/runtime": "0.71.0", "@oxc-project/types": "0.71.0", "@rolldown/pluginutils": "1.0.0-beta.9-commit.d91dfb5", "ansis": "^4.0.0" }, "optionalDependencies": { "@rolldown/binding-darwin-arm64": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-darwin-x64": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-freebsd-x64": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-linux-x64-musl": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-wasm32-wasi": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.9-commit.d91dfb5", "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.9-commit.d91dfb5" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-FHkj6gGEiEgmAXQchglofvUUdwj2Oiw603Rs+zgFAnn9Cb7T7z3fiaEc0DbN3ja4wYkW6sF2rzMEtC1V4BGx/g=="], @@ -1041,22 +1526,38 @@ "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="], + "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], + "secure-json-parse": ["secure-json-parse@4.1.0", "", {}, "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA=="], + "selderee": ["selderee@0.11.0", "", { "dependencies": { "parseley": "^0.12.0" } }, "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA=="], + "semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], "set-cookie-parser": ["set-cookie-parser@2.7.2", "", {}, "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw=="], "shadcn-svelte": ["shadcn-svelte@1.1.0", "", { "dependencies": { "commander": "^14.0.0", "node-fetch-native": "^1.6.4", "postcss": "^8.5.5" }, "bin": { "shadcn-svelte": "dist/index.js" } }, "sha512-mTo4E6xzEGuS5q7JzL3ecX0zAd86PQaXIGvHW2f04Ap1cclE110YUU81RBIBGf2FvpZS6J5zOE2DHvzI3opg9A=="], + "sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="], + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], "shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="], + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + "sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="], + "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], + + "socket.io": ["socket.io@4.8.3", "", { "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.4.1", "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" } }, "sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A=="], + + "socket.io-adapter": ["socket.io-adapter@2.5.6", "", { "dependencies": { "debug": "~4.4.1", "ws": "~8.18.3" } }, "sha512-DkkO/dz7MGln0dHn5bmN3pPy+JmywNICWrJqVWiVOyvXjWQFIv9c2h24JrQLLFJ2aQVQf/Cvl1vblnd4r2apLQ=="], + + "socket.io-parser": ["socket.io-parser@4.2.5", "", { "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.4.1" } }, "sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ=="], + "sonic-boom": ["sonic-boom@4.2.0", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww=="], "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], @@ -1069,12 +1570,32 @@ "stack-trace": ["stack-trace@0.0.10", "", {}, "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg=="], + "stdin-discarder": ["stdin-discarder@0.2.2", "", {}, "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ=="], + + "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], + + "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], + "strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], + + "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], + "strip-json-comments": ["strip-json-comments@5.0.3", "", {}, "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw=="], + "strnum": ["strnum@2.1.2", "", {}, "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ=="], + + "stubborn-fs": ["stubborn-fs@2.0.0", "", { "dependencies": { "stubborn-utils": "^1.0.1" } }, "sha512-Y0AvSwDw8y+nlSNFXMm2g6L51rBGdAQT20J3YSOqxC53Lo3bjWRtr2BKcfYoAf352WYpsZSTURrA0tqhfgudPA=="], + + "stubborn-utils": ["stubborn-utils@1.0.2", "", {}, "sha512-zOh9jPYI+xrNOyisSelgym4tolKTJCQd5GBhK0+0xJvcYDcwlOoxF/rnFKQ2KRZknXSG9jWAp66fwP6AxN9STg=="], + "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="], + "styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="], + "superjson": ["superjson@2.2.6", "", { "dependencies": { "copy-anything": "^4" } }, "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA=="], "superstruct": ["superstruct@2.0.2", "", {}, "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A=="], @@ -1121,6 +1642,8 @@ "tiny-case": ["tiny-case@1.0.3", "", {}, "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q=="], + "tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="], + "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], @@ -1139,8 +1662,12 @@ "ts-deepmerge": ["ts-deepmerge@7.0.3", "", {}, "sha512-Du/ZW2RfwV/D4cmA5rXafYjBQVuvu4qGiEEla4EmEHVHgRdx68Gftx7i66jn2bzHPwSVZY36Ae6OuDn9el4ZKA=="], + "tsconfig-paths": ["tsconfig-paths@4.2.0", "", { "dependencies": { "json5": "^2.2.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg=="], + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "tsyringe": ["tsyringe@4.10.0", "", { "dependencies": { "tslib": "^1.9.3" } }, "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw=="], + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], "type-fest": ["type-fest@5.3.1", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-VCn+LMHbd4t6sF3wfU/+HKT63C9OoyrSIf4b+vtWHpt2U7/4InZG467YDNMFMR70DdHjAdpPWmw2lzRdg0Xqqg=="], @@ -1151,6 +1678,8 @@ "typescript-eslint": ["typescript-eslint@8.52.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.52.0", "@typescript-eslint/parser": "8.52.0", "@typescript-eslint/typescript-estree": "8.52.0", "@typescript-eslint/utils": "8.52.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-atlQQJ2YkO4pfTVQmQ+wvYQwexPDOIgo+RaVcD7gHgzy/IQA+XTyuxNM9M9TVXvttkF7koBHmcwisKdOAf2EcA=="], + "uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="], + "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], "universal-github-app-jwt": ["universal-github-app-jwt@2.2.2", "", {}, "sha512-dcmbeSrOdTnsjGjUfAlqNDJrhxXizjAz94ija9Qw8YkZ1uu0d+GoZzyH+Jb9tIIqvGsadUfwg+22k5aDqqwzbw=="], @@ -1165,12 +1694,16 @@ "validator": ["validator@13.15.26", "", {}, "sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA=="], + "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], + "vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="], "vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="], "web-vitals": ["web-vitals@4.2.4", "", {}, "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw=="], + "when-exit": ["when-exit@2.1.5", "", {}, "sha512-VGkKJ564kzt6Ms1dbgPP/yuIoQCrsFAnRbptpC5wOEsDaNsbCB2bnfnaA8i/vRs5tjUSEOtIuvl9/MyVsvQZCg=="], + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], "winston": ["winston@3.19.0", "", { "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.8", "async": "^3.2.3", "is-stream": "^2.0.0", "logform": "^2.7.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", "winston-transport": "^4.9.0" } }, "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA=="], @@ -1179,12 +1712,20 @@ "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + "wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + + "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], + "ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="], + "yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="], "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="], + "yup": ["yup@1.7.1", "", { "dependencies": { "property-expr": "^2.0.5", "tiny-case": "^1.0.3", "toposort": "^2.0.2", "type-fest": "^2.19.0" } }, "sha512-GKHFX2nXul2/4Dtfxhozv701jLQHdf6J34YDh2cEkpqoo8le5Mg6/LrdseVLrFarmFygZTlfIhHx/QKfb/QWXw=="], "zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="], @@ -1193,6 +1734,10 @@ "zod-v3-to-json-schema": ["zod-v3-to-json-schema@4.0.0", "", { "peerDependencies": { "zod": "^3.25 || ^4.0.14" } }, "sha512-KixLrhX/uPmRFnDgsZrzrk4x5SSJA+PmaE5adbfID9+3KPJcdxqRobaHU397EfWBqfQircrjKqvEqZ/mW5QH6w=="], + "@aws-crypto/sha256-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], + + "@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], + "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], @@ -1205,6 +1750,10 @@ "@eslint/plugin-kit/@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="], + "@internationalized/date/@swc/helpers": ["@swc/helpers@0.5.18", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ=="], + + "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + "@oslojs/jwt/@oslojs/encoding": ["@oslojs/encoding@0.4.1", "", {}, "sha512-hkjo6MuIK/kQR5CrGNdAPZhS01ZCXuWDRJ187zh6qqF2+yMHZpD9fAYpX8q2bOO6Ryhl3XpCT6kUX76N8hhm4Q=="], "@rollup/plugin-commonjs/is-reference": ["is-reference@1.2.1", "", { "dependencies": { "@types/estree": "*" } }, "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ=="], @@ -1227,6 +1776,10 @@ "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + + "ajv-formats/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], + "better-auth/@noble/hashes": ["@noble/hashes@2.0.1", "", {}, "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw=="], "bits-ui/runed": ["runed@0.35.1", "", { "dependencies": { "dequal": "^2.0.3", "esm-env": "^1.0.0", "lz-string": "^1.5.0" }, "peerDependencies": { "@sveltejs/kit": "^2.21.0", "svelte": "^5.7.0" }, "optionalPeers": ["@sveltejs/kit"] }, "sha512-2F4Q/FZzbeJTFdIS/PuOoPRSm92sA2LhzTnv6FXhCoENb3huf5+fDuNOg1LNvGOouy3u/225qxmuJvcV3IZK5Q=="], @@ -1235,8 +1788,12 @@ "color-string/color-name": ["color-name@2.1.0", "", {}, "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg=="], + "conf/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], + "drizzle-kit/esbuild": ["esbuild@0.19.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.19.12", "@esbuild/android-arm": "0.19.12", "@esbuild/android-arm64": "0.19.12", "@esbuild/android-x64": "0.19.12", "@esbuild/darwin-arm64": "0.19.12", "@esbuild/darwin-x64": "0.19.12", "@esbuild/freebsd-arm64": "0.19.12", "@esbuild/freebsd-x64": "0.19.12", "@esbuild/linux-arm": "0.19.12", "@esbuild/linux-arm64": "0.19.12", "@esbuild/linux-ia32": "0.19.12", "@esbuild/linux-loong64": "0.19.12", "@esbuild/linux-mips64el": "0.19.12", "@esbuild/linux-ppc64": "0.19.12", "@esbuild/linux-riscv64": "0.19.12", "@esbuild/linux-s390x": "0.19.12", "@esbuild/linux-x64": "0.19.12", "@esbuild/netbsd-x64": "0.19.12", "@esbuild/openbsd-x64": "0.19.12", "@esbuild/sunos-x64": "0.19.12", "@esbuild/win32-arm64": "0.19.12", "@esbuild/win32-ia32": "0.19.12", "@esbuild/win32-x64": "0.19.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg=="], + "engine.io/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], + "eslint/@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="], "eslint-plugin-svelte/globals": ["globals@16.5.0", "", {}, "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ=="], @@ -1247,14 +1804,34 @@ "gel/which": ["which@4.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg=="], + "glob/minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "mode-watcher/runed": ["runed@0.25.0", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-7+ma4AG9FT2sWQEA0Egf6mb7PBT2vHyuHail1ie8ropfSjvZGtEAx8YTmUjv/APCsdRRxEVvArNjALk9zFSOrg=="], "mode-watcher/svelte-toolbelt": ["svelte-toolbelt@0.7.1", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.23.2", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-HcBOcR17Vx9bjaOceUvxkY3nGmbBmCBBbuWLLEWO6jtmWH8f/QoWmbyUfQZrpDINH39en1b8mptfPQT9VKQ1xQ=="], + "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], + + "ora/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + + "ora/log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="], + "postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + "prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], + + "react-email/jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="], + + "shadcn-svelte/commander": ["commander@14.0.2", "", {}, "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ=="], + + "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "svelte-eslint-parser/postcss-selector-parser": ["postcss-selector-parser@7.1.1", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg=="], "svelte-sonner/runed": ["runed@0.28.0", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-k2xx7RuO9hWcdd9f+8JoBeqWtYrm5CALfgpkg2YDB80ds/QE4w0qqu34A7fqiAwiBBSBQOid7TLxwxVC27ymWQ=="], @@ -1263,8 +1840,24 @@ "tailwind-variants/tailwind-merge": ["tailwind-merge@2.5.4", "", {}, "sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q=="], + "tsyringe/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], + + "vite/esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="], + + "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + + "wrap-ansi/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "yup/type-fest": ["type-fest@2.19.0", "", {}, "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA=="], + "@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], + + "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], + "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="], @@ -1309,10 +1902,18 @@ "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="], + "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "ajv-formats/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + "color/color-convert/color-name": ["color-name@2.1.0", "", {}, "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg=="], + "conf/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + "drizzle-kit/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.19.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA=="], "drizzle-kit/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.19.12", "", { "os": "android", "cpu": "arm" }, "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w=="], @@ -1362,5 +1963,73 @@ "gel/which/isexe": ["isexe@3.1.1", "", {}, "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="], "mode-watcher/svelte-toolbelt/runed": ["runed@0.23.4", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-9q8oUiBYeXIDLWNK5DfCWlkL0EW3oGbk845VdKlPeia28l751VpfesaB/+7pI6rnbx1I6rqoZ2fZxptOJLxILA=="], + + "next/postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + + "ora/log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], + + "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="], + + "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.2", "", { "os": "android", "cpu": "arm" }, "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA=="], + + "vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.2", "", { "os": "android", "cpu": "arm64" }, "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA=="], + + "vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.2", "", { "os": "android", "cpu": "x64" }, "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A=="], + + "vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg=="], + + "vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA=="], + + "vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g=="], + + "vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA=="], + + "vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.2", "", { "os": "linux", "cpu": "arm" }, "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw=="], + + "vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw=="], + + "vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w=="], + + "vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg=="], + + "vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw=="], + + "vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ=="], + + "vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA=="], + + "vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w=="], + + "vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA=="], + + "vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw=="], + + "vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.2", "", { "os": "none", "cpu": "x64" }, "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA=="], + + "vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA=="], + + "vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg=="], + + "vite/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag=="], + + "vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg=="], + + "vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg=="], + + "vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ=="], + + "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.2", "", { "os": "win32", "cpu": "x64" }, "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ=="], + + "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "wrap-ansi/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], + + "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], } } diff --git a/package.json b/package.json index f92196c..d3c3bdd 100644 --- a/package.json +++ b/package.json @@ -20,15 +20,21 @@ "db:gen": "drizzle-kit generate", "db:drop": "drizzle-kit drop", "auth:db": "bunx @better-auth/cli@latest generate --config src/lib/auth/server.ts --output src/lib/server/db/auth.ts", + "email:build": "email build -d src/lib/email/emails", + "email:dev": "email dev -d src/lib/email/emails", + "email:export": "email export -d src/lib/email/emails", "sv": "sv", "ui": "shadcn-svelte", "clean": "rm -rf .svelte-kit build" }, "devDependencies": { "@eslint/compat": "^2.0.1", + "@react-email/preview-server": "5.2.3", "@sveltejs/vite-plugin-svelte": "^6.2.1", "@tailwindcss/vite": "^4.1.18", "@types/node": "^22.19.3", + "@types/nodemailer": "^7.0.5", + "@types/react": "^19.2.8", "eslint": "^9.39.2", "eslint-config-prettier": "^10.1.8", "eslint-plugin-svelte": "^3.13.1", @@ -36,6 +42,7 @@ "prettier": "^3.7.4", "prettier-plugin-svelte": "^3.4.1", "prettier-plugin-tailwindcss": "^0.7.2", + "react-email": "^5.2.3", "shadcn-svelte": "1.1.0", "sv": "^0.11.2", "svelte-check": "^4.3.5", @@ -44,6 +51,7 @@ "vite": "^7.3.0" }, "dependencies": { + "@better-auth/passkey": "^1.4.12", "@faker-js/faker": "^9.9.0", "@fontsource-variable/inter": "^5.2.8", "@fontsource-variable/inter-tight": "^5.2.7", @@ -58,6 +66,7 @@ "@oslojs/crypto": "^1.0.1", "@oslojs/encoding": "^1.1.0", "@paralleldrive/cuid2": "^2.3.1", + "@react-email/components": "^1.0.4", "@sveltejs/adapter-auto": "^7.0.0", "@sveltejs/adapter-node": "^5.4.0", "@sveltejs/kit": "^2.49.2", @@ -84,6 +93,7 @@ "lucide-svelte": "^0.562.0", "mode-watcher": "^1.1.0", "nanoid": "^5.1.6", + "nodemailer": "^7.0.12", "octokit": "^4.1.4", "pino": "^10.1.0", "pino-pretty": "^13.1.3", diff --git a/src/lib/email/emails/magic-link.tsx b/src/lib/email/emails/magic-link.tsx new file mode 100644 index 0000000..e108618 --- /dev/null +++ b/src/lib/email/emails/magic-link.tsx @@ -0,0 +1,85 @@ +import { + Body, + Button, + Column, + Container, + Head, + Heading, + Hr, + Html, + Img, + Link, + Preview, + Row, + Section, + Tailwind, + Text +} from '@react-email/components'; + +export type MagicLinkEmailProps = { + username: string; + magicLink: string; + fromIp: string; +}; + +export const MagicLinkEmail = ({ username, magicLink, fromIp }: MagicLinkEmailProps) => { + const previewText = `HackHelp Login Link`; + + return ( + + + + + {previewText} + +
+ HackHelp +
+ + HackHelp Login Link + + Hello {username}, + + You have requested a login link for HackHelp. Here it is, fresh off the presses! + +
+ +
+ + or copy and paste this URL into your browser:{' '} + + {magicLink} + + +
+ + This invitation was intended for {username}. This + invite was sent from {fromIp}. If you were not + expecting this login request, you can ignore this email. If you are concerned about + your account's safety, please contact the hackathon organizers. + +
+ +
+ + ); +}; + +MagicLinkEmail.PreviewProps = { + username: 'henrikvtcodes', + magicLink: 'https://hackhelp.unicycl.ing/auth/login/magic', + fromIp: '132.198.201.10' +} as MagicLinkEmailProps; + +export default MagicLinkEmail; diff --git a/src/lib/email/index.tsx b/src/lib/email/index.tsx new file mode 100644 index 0000000..3280757 --- /dev/null +++ b/src/lib/email/index.tsx @@ -0,0 +1,15 @@ +import { render } from '@react-email/components'; +import nodemailer from 'nodemailer'; +import { MagicLinkEmail, type MagicLinkEmailProps } from './emails/magic-link'; +import { serverEnv } from '$lib/env/server'; + +const transporter = nodemailer.createTransport(serverEnv.SMTP_URL); + +export async function sendMagicLinkEmail(to: string, emailProps: MagicLinkEmailProps) { + return await transporter.sendMail({ + from: serverEnv.SMTP_FROM, + to, + subject: 'Your HackHelp Login Link', + html: await render() + }); +} diff --git a/src/lib/env/server.ts b/src/lib/env/server.ts index 6e520c0..fc93943 100644 --- a/src/lib/env/server.ts +++ b/src/lib/env/server.ts @@ -13,7 +13,9 @@ export const serverEnv = createEnv({ GITHUB_APP_CLIENT_ID: z.string().nonempty(), GITHUB_APP_CLIENT_SECRET: z.string().nonempty(), GITHUB_WEBHOOK_SECRET: z.base64().nonempty(), - WHITELIST_ENDPOINT_TOKEN: z.base64().nonempty() + WHITELIST_ENDPOINT_TOKEN: z.base64().nonempty(), + SMTP_URL: z.string(), + SMTP_FROM: z.email() }, client: { PUBLIC_GITHUB_ORGNAME: z.string().nonempty(), diff --git a/tsconfig.json b/tsconfig.json index 0b2d886..ff7eea0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,8 +9,35 @@ "skipLibCheck": true, "sourceMap": true, "strict": true, - "moduleResolution": "bundler" - } + "moduleResolution": "bundler", + "jsx": "react-jsx" + }, + "include": [ + ".svelte-kit/ambient.d.ts", + ".svelte-kit/non-ambient.d.ts", + ".svelte-kit/types/**/$types.d.ts", + "vite.config.js", + "vite.config.ts", + "src/**/*.js", + "src/**/*.ts", + "src/**/*.svelte", + "tests/**/*.js", + "tests/**/*.ts", + "tests/**/*.svelte", + + "src/**/*.tsx" + ], + "exclude": [ + "node_modules", + "src/service-worker.js", + "src/service-worker/**/*.js", + "src/service-worker.ts", + "src/service-worker/**/*.ts", + "src/service-worker.d.ts", + "src/service-worker/**/*.d.ts", + + ".react-email" + ] // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files // From f681e0abb7fe13d5b1fa6e73ff462dadbb5a221c Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 12:32:50 -0500 Subject: [PATCH 06/85] organize some env stuff --- .env.example | 22 ++++++++++++++++------ src/lib/env/server.ts | 13 +++++++------ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/.env.example b/.env.example index a11984b..f56916d 100644 --- a/.env.example +++ b/.env.example @@ -1,18 +1,28 @@ -# Local DB Connect String -# Based on the docker compose database template +# --- Postgres Database Connection URL --- +# The provided example corresponds to the docker compose database DATABASE_URL=postgres://cscrew:database@localhost:32700/hackhelp -# Organization to test on + +# --- GitHub App Configuration +# Organization for HackHelp to integrate with. It is a single tenant app and is not designed to work across multiple orgs at once. PUBLIC_GITHUB_ORGNAME=UVMHacks2026 GITHUB_APP_ID= -GITHUB_APP_INSTALL_ID= +# Client ID for OAuth GITHUB_APP_CLIENT_ID= +# Client Secret for OAuth GITHUB_APP_CLIENT_SECRET= +# App Private Key GITHUB_APP_PRIVATE_KEY= - +# Signing webhooks GITHUB_WEBHOOK_SECRET= -PUBLIC_SHOW_CHALLENGES= +# --- SMTP Connection URL for sending emails --- +# This example URL applies to servers that use STARTTLS on port 587. ?pool=true enables connection pooling. +SMTP_URL="smtp://user:pass@smtp.example.com:587/?pool=true" +# Email account to send from +SMTP_FROM="user@example.com" +# --- Miscellaneous --- +PUBLIC_SHOW_CHALLENGES= WHITELIST_ENDPOINT_TOKEN= \ No newline at end of file diff --git a/src/lib/env/server.ts b/src/lib/env/server.ts index fc93943..4da2bee 100644 --- a/src/lib/env/server.ts +++ b/src/lib/env/server.ts @@ -1,6 +1,6 @@ -import { building } from '$app/environment'; -import { env as privateEnv } from '$env/dynamic/private'; -import { env as publicEnv } from '$env/dynamic/public'; +// import { building } from '$app/environment'; +// import { env as privateEnv } from '$env/dynamic/private'; +// import { env as publicEnv } from '$env/dynamic/public'; import { createEnv } from '@t3-oss/env-core'; import { z } from 'zod'; @@ -22,7 +22,8 @@ export const serverEnv = createEnv({ PUBLIC_SHOW_CHALLENGES: z.coerce.boolean().default(true) }, clientPrefix: 'PUBLIC_', - runtimeEnv: { ...privateEnv, ...publicEnv }, - emptyStringAsUndefined: true, - skipValidation: building + // runtimeEnv: { ...privateEnv, ...publicEnv }, + runtimeEnv: import.meta.env, + emptyStringAsUndefined: true + // skipValidation: building }); From f810f1e0c74b6f905c4c71e90ada50dea3268408 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 13:00:00 -0500 Subject: [PATCH 07/85] more email stuff --- src/lib/email/emails/email-otp.tsx | 79 +++++++++++++++++++++++++++++ src/lib/email/emails/magic-link.tsx | 17 +++---- src/lib/email/index.tsx | 16 ++++++ 3 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 src/lib/email/emails/email-otp.tsx diff --git a/src/lib/email/emails/email-otp.tsx b/src/lib/email/emails/email-otp.tsx new file mode 100644 index 0000000..37024a0 --- /dev/null +++ b/src/lib/email/emails/email-otp.tsx @@ -0,0 +1,79 @@ +import { + Body, + Container, + Head, + Heading, + Hr, + Html, + Img, + Preview, + Section, + Tailwind, + Text, + CodeInline +} from '@react-email/components'; + +export type OTPEmailProps = { + type: 'email-verification' | 'sign-in' | 'forget-password'; + username?: string; + otp: string; + fromIp?: string; +}; + +export const OTPEmail = ({ username, type = 'email-verification', otp, fromIp }: OTPEmailProps) => { + let title = + type === 'email-verification' + ? 'Email Verification Code' + : type === 'sign-in' + ? 'Sign-in Code' + : 'Password Reset Code'; + + return ( + + + + + {`${title} | HackHelp`} + +
+ HackHelp +
+ + HackHelp {title} + + {/* Hello {username}, */} + Hello!{' '} + + You have requested a {title.toLowerCase()} for HackHelp. Here it is, fresh off the + presses! + +
+ {otp} +
+
+ + {/* This email was intended for {username}. This + invite was sent from {fromIp}. */} + If you were not expecting this, you can ignore this email. If you are concerned about + your account's safety, please contact the hackathon organizers. + +
+ +
+ + ); +}; + +OTPEmail.PreviewProps = { + username: 'henrikvtcodes', + otp: 'ab1245', + fromIp: '132.198.201.10' +} as OTPEmailProps; + +export default OTPEmail; diff --git a/src/lib/email/emails/magic-link.tsx b/src/lib/email/emails/magic-link.tsx index e108618..8662d9e 100644 --- a/src/lib/email/emails/magic-link.tsx +++ b/src/lib/email/emails/magic-link.tsx @@ -1,7 +1,6 @@ import { Body, Button, - Column, Container, Head, Heading, @@ -10,16 +9,15 @@ import { Img, Link, Preview, - Row, Section, Tailwind, Text } from '@react-email/components'; export type MagicLinkEmailProps = { - username: string; + username?: string; magicLink: string; - fromIp: string; + fromIp?: string; }; export const MagicLinkEmail = ({ username, magicLink, fromIp }: MagicLinkEmailProps) => { @@ -44,7 +42,8 @@ export const MagicLinkEmail = ({ username, magicLink, fromIp }: MagicLinkEmailPr HackHelp Login Link - Hello {username}, + {/* Hello {username}, */} + Hello! You have requested a login link for HackHelp. Here it is, fresh off the presses! @@ -64,10 +63,10 @@ export const MagicLinkEmail = ({ username, magicLink, fromIp }: MagicLinkEmailPr
- This invitation was intended for {username}. This - invite was sent from {fromIp}. If you were not - expecting this login request, you can ignore this email. If you are concerned about - your account's safety, please contact the hackathon organizers. + {/* This invitation was intended for {username}. This + invite was sent from {fromIp}. */} + If you were not expecting this login request, you can ignore this email. If you are + concerned about your account's safety, please contact the hackathon organizers. diff --git a/src/lib/email/index.tsx b/src/lib/email/index.tsx index 3280757..41145b8 100644 --- a/src/lib/email/index.tsx +++ b/src/lib/email/index.tsx @@ -2,6 +2,7 @@ import { render } from '@react-email/components'; import nodemailer from 'nodemailer'; import { MagicLinkEmail, type MagicLinkEmailProps } from './emails/magic-link'; import { serverEnv } from '$lib/env/server'; +import { OTPEmail, type OTPEmailProps } from './emails/email-otp'; const transporter = nodemailer.createTransport(serverEnv.SMTP_URL); @@ -13,3 +14,18 @@ export async function sendMagicLinkEmail(to: string, emailProps: MagicLinkEmailP html: await render() }); } + +export async function sendEmailOtp(to: string, emailProps: OTPEmailProps) { + let title = + emailProps.type === 'email-verification' + ? 'Email Verification Code' + : emailProps.type === 'sign-in' + ? 'Sign-in Code' + : 'Password Reset Code'; + return await transporter.sendMail({ + from: serverEnv.SMTP_FROM, + to, + subject: `${title} | HackHelp`, + html: await render() + }); +} From bf16e1a9351aa19f7bb13388f6c481ba68441de7 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 13:00:28 -0500 Subject: [PATCH 08/85] plugins with email stuff --- src/lib/auth/server.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/lib/auth/server.ts b/src/lib/auth/server.ts index ca39491..99bfc3a 100644 --- a/src/lib/auth/server.ts +++ b/src/lib/auth/server.ts @@ -2,6 +2,9 @@ import { serverEnv } from '$lib/env/server'; import { db } from '$lib/server/db'; import { betterAuth } from 'better-auth'; import { drizzleAdapter } from 'better-auth/adapters/drizzle'; +import { passkey } from '@better-auth/passkey'; +import { emailOTP, magicLink } from 'better-auth/plugins'; +import { sendEmailOtp, sendMagicLinkEmail } from '$lib/email'; export const auth = betterAuth({ database: drizzleAdapter(db, { @@ -15,6 +18,25 @@ export const auth = betterAuth({ disableSignUp: true } }, + plugins: [ + passkey(), + emailOTP({ + async sendVerificationOTP({ email, otp, type }) { + if (type === 'forget-password') { + throw new Error('Passwords not enabled'); + } else { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + await sendEmailOtp(email, { type, otp }); + } + } + }), + magicLink({ + sendMagicLink: async ({ email, url }) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + await sendMagicLinkEmail(email, { magicLink: url }); + } + }) + ], experimental: { joins: true } }); From 9eedd001f3115c3c9df3a07ad857f464c147a499 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 14:32:52 -0500 Subject: [PATCH 09/85] rich permissions --- src/lib/auth/permissions.ts | 63 +++++++++++++++++++++++++++++++++++++ src/lib/auth/server.ts | 9 ++++-- 2 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 src/lib/auth/permissions.ts diff --git a/src/lib/auth/permissions.ts b/src/lib/auth/permissions.ts new file mode 100644 index 0000000..3cf3667 --- /dev/null +++ b/src/lib/auth/permissions.ts @@ -0,0 +1,63 @@ +import { createAccessControl } from 'better-auth/plugins/access'; +import { defaultStatements, adminAc } from 'better-auth/plugins/admin/access'; + +const statements = { + configuration: ['view', 'update', 'delete'], // System configuration; key value table in postgres + /** + * These are more administrator-like permissions + * If you have one of these, the action applies to all instances of that object in the system. + * i.e. as an administrator, I can view/list all teams, delete any team + */ + anyTeam: ['list', 'view', 'create', 'update', 'delete'], + anyTicket: ['list', 'view', 'update', 'delete'], + anyProfile: ['list', 'view', 'update', 'delete'], + anyScore: ['create', 'view', 'update', 'delete'], + /** + * Individual user permissions; what a user can do to resources they own/are a part of. + * i.e. can a user create a team, update their profile + */ + team: ['create', 'join', 'delete'], + teamChallenge: ['update'], + teamMembers: ['invite', 'remove'], + profile: ['create', 'update', 'delete'], + score: ['view'], + /** + * Sections of the app that a user can view + */ + mentor: ['view'], + judging: ['view'] +} as const; + +export const ac = createAccessControl({ ...defaultStatements, ...statements }); + +const admin = ac.newRole({ + ...adminAc.statements, + // ...ac.statements, + configuration: ['view', 'update', 'delete'], + team: ['create', 'join', 'delete'], + mentor: ['view'], + judging: ['view'] +}); + +const verifiedUser = ac.newRole({ + profile: ['create'] +}); + +const mentor = ac.newRole({ + mentor: ['view'], + anyTeam: ['list', 'view'], + anyTicket: ['list', 'view', 'update'] +}); + +const judge = ac.newRole({ + judging: ['view'], + anyTeam: ['list', 'view'], + anyScore: ['create', 'view', 'update', 'delete'] +}); + +export const roles = { + admin, + verifiedUser, + mentor, + judge +} as const; diff --git a/src/lib/auth/server.ts b/src/lib/auth/server.ts index 99bfc3a..531f9e4 100644 --- a/src/lib/auth/server.ts +++ b/src/lib/auth/server.ts @@ -3,8 +3,9 @@ import { db } from '$lib/server/db'; import { betterAuth } from 'better-auth'; import { drizzleAdapter } from 'better-auth/adapters/drizzle'; import { passkey } from '@better-auth/passkey'; -import { emailOTP, magicLink } from 'better-auth/plugins'; +import { emailOTP, magicLink, admin } from 'better-auth/plugins'; import { sendEmailOtp, sendMagicLinkEmail } from '$lib/email'; +import { ac, roles } from './permissions'; export const auth = betterAuth({ database: drizzleAdapter(db, { @@ -25,16 +26,18 @@ export const auth = betterAuth({ if (type === 'forget-password') { throw new Error('Passwords not enabled'); } else { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call await sendEmailOtp(email, { type, otp }); } } }), magicLink({ sendMagicLink: async ({ email, url }) => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call await sendMagicLinkEmail(email, { magicLink: url }); } + }), + admin({ + ac, + roles }) ], experimental: { joins: true } From 3d72ab0807b84df75d380dbcfbfdfaefd3499587 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 14:33:18 -0500 Subject: [PATCH 10/85] auth client plugins --- src/lib/auth/client.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/lib/auth/client.ts b/src/lib/auth/client.ts index c863ef6..9e9d525 100644 --- a/src/lib/auth/client.ts +++ b/src/lib/auth/client.ts @@ -1,9 +1,21 @@ import { createAuthClient } from 'better-auth/svelte'; import { inferAdditionalFields } from 'better-auth/client/plugins'; import type { auth } from './server'; +import { adminClient, emailOTPClient, magicLinkClient } from 'better-auth/client/plugins'; +import { passkeyClient } from '@better-auth/passkey/client'; +import { ac, roles } from './permissions'; const authClient = createAuthClient({ - plugins: [inferAdditionalFields()] + plugins: [ + inferAdditionalFields(), + passkeyClient(), + emailOTPClient(), + magicLinkClient(), + adminClient({ + ac, + roles + }) + ] }); export const { signIn, signUp, useSession } = authClient; From 749239dc4988ad3e91ebb71b29fcede43c087836 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 14:33:48 -0500 Subject: [PATCH 11/85] rework how database client is exported --- src/lib/orpc/server/context.ts | 3 +-- src/lib/server/db/index.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lib/orpc/server/context.ts b/src/lib/orpc/server/context.ts index 4bda0f9..938e399 100644 --- a/src/lib/orpc/server/context.ts +++ b/src/lib/orpc/server/context.ts @@ -1,5 +1,5 @@ import type { Session, User } from '$lib/server/db/schema'; -import { db, schema } from '$lib/server/db'; +import db from '$lib/server/db'; import { githubApp } from '$lib/github'; import type { Cookies } from '@sveltejs/kit'; import { logger } from '$lib/logger'; @@ -17,7 +17,6 @@ export function createOrpcContext(opts: ContextGeneratorParams) { req: opts.request, ...opts.locals, db, - dbSchema: schema, githubApp, cookies: opts.cookies, logger: logger.child({ requestId: opts.request.headers.get('x-railway-request-id') }) diff --git a/src/lib/server/db/index.ts b/src/lib/server/db/index.ts index b62332d..8763e82 100644 --- a/src/lib/server/db/index.ts +++ b/src/lib/server/db/index.ts @@ -7,4 +7,4 @@ import * as schema from '$lib/server/db/schema'; const queryClient = postgres(serverEnv.DATABASE_URL); export const db = drizzle({ client: queryClient, schema }); -export { schema }; +export default { client: db, schema }; From 7dfcf0eb18525bc2a180165197143e488bc3e818 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 14:46:27 -0500 Subject: [PATCH 12/85] fix auth types --- src/app.d.ts | 4 ++-- src/hooks.server.ts | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/app.d.ts b/src/app.d.ts index 9a8468a..1f8033a 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -3,8 +3,8 @@ declare global { namespace App { interface Locals { - user: import('$lib/auth/server').User; - session: import('$lib/auth/server').Session; + user: import('$lib/auth/server').User | null; + session: import('$lib/auth/server').Session | null; } } } diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 8949225..a10d765 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -13,6 +13,9 @@ export const handle: Handle = async ({ event, resolve }) => { if (session) { event.locals.session = session.session; event.locals.user = session.user; + } else { + event.locals.session = null; + event.locals.user = null; } return svelteKitHandler({ event, resolve, auth, building }); From 16ecc8e8f8bc111c81621cefc5d2bd79e3d25857 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 14:46:39 -0500 Subject: [PATCH 13/85] no more old auth --- src/lib/server/auth.ts | 92 ------------------------------------------ 1 file changed, 92 deletions(-) delete mode 100644 src/lib/server/auth.ts diff --git a/src/lib/server/auth.ts b/src/lib/server/auth.ts deleted file mode 100644 index 9c38754..0000000 --- a/src/lib/server/auth.ts +++ /dev/null @@ -1,92 +0,0 @@ -import type { RequestEvent } from '@sveltejs/kit'; -import { eq } from 'drizzle-orm'; -import { sha256 } from '@oslojs/crypto/sha2'; -import { encodeBase64url, encodeHexLowerCase } from '@oslojs/encoding'; -import { db } from '$lib/server/db'; -import * as table from '$lib/server/db/schema'; -import { GitHub as GitHubOAuth } from 'arctic'; -import { serverEnv } from '$lib/env/server'; -import { dev } from '$app/environment'; - -const DAY_IN_MS = 1000 * 60 * 60 * 24; - -export const sessionCookieName = 'auth-session'; - -export const githubOAuth = new GitHubOAuth( - serverEnv.GITHUB_APP_CLIENT_ID, - serverEnv.GITHUB_APP_CLIENT_SECRET, - dev - ? 'http://localhost:5173/auth/login/github/callback' - : 'https://hackhelp.unicycl.ing/auth/login/github/callback' -); - -export function generateSessionToken() { - const bytes = crypto.getRandomValues(new Uint8Array(18)); - const token = encodeBase64url(bytes); - return token; -} - -export async function createSession(token: string, userId: string) { - const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token))); - const session: table.Session = { - id: sessionId, - userId, - expiresAt: new Date(Date.now() + DAY_IN_MS * 30) - }; - await db.insert(table.session).values(session); - return session; -} - -export async function validateSessionToken(token: string) { - const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token))); - const [result] = await db - .select({ - // Adjust user table here to tweak returned data - user: table.user, - session: table.session - }) - .from(table.session) - .innerJoin(table.user, eq(table.session.userId, table.user.id)) - .where(eq(table.session.id, sessionId)); - - if (!result) { - return { session: null, user: null }; - } - const { session, user } = result; - - const sessionExpired = Date.now() >= session.expiresAt.getTime(); - if (sessionExpired) { - await db.delete(table.session).where(eq(table.session.id, session.id)); - return { session: null, user: null }; - } - - const renewSession = Date.now() >= session.expiresAt.getTime() - DAY_IN_MS * 15; - if (renewSession) { - session.expiresAt = new Date(Date.now() + DAY_IN_MS * 30); - await db - .update(table.session) - .set({ expiresAt: session.expiresAt }) - .where(eq(table.session.id, session.id)); - } - - return { session, user }; -} - -export type SessionValidationResult = Awaited>; - -export async function invalidateSession(sessionId: string) { - await db.delete(table.session).where(eq(table.session.id, sessionId)); -} - -export function setSessionTokenCookie(event: RequestEvent, token: string, expiresAt: Date) { - event.cookies.set(sessionCookieName, token, { - expires: expiresAt, - path: '/' - }); -} - -export function deleteSessionTokenCookie(event: RequestEvent) { - event.cookies.delete(sessionCookieName, { - path: '/' - }); -} From a8b98d78627104559afc443910c0414456874013 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 15:07:41 -0500 Subject: [PATCH 14/85] more old stuff --- src/routes/api/whitelist/+server.ts | 52 ----- src/routes/auth/login/github/+server.ts | 16 -- .../auth/login/github/callback/+server.ts | 217 ------------------ 3 files changed, 285 deletions(-) delete mode 100644 src/routes/api/whitelist/+server.ts delete mode 100644 src/routes/auth/login/github/+server.ts delete mode 100644 src/routes/auth/login/github/callback/+server.ts diff --git a/src/routes/api/whitelist/+server.ts b/src/routes/api/whitelist/+server.ts deleted file mode 100644 index c2aa3f6..0000000 --- a/src/routes/api/whitelist/+server.ts +++ /dev/null @@ -1,52 +0,0 @@ -import type { RequestEvent } from './$types'; -import { z } from 'zod'; -import { batchWhitelistSchema } from '$lib/schemas'; -import { db, schema } from '$lib/server/db'; -import { serverEnv } from '$lib/env/server'; -import { fail } from '@sveltejs/kit'; - -const whitelistBodySchema = z.object({ - authToken: z.string().nonempty(), - users: z.array(batchWhitelistSchema) -}); - -export async function POST(event: RequestEvent) { - let bodyValidated: z.infer; - try { - bodyValidated = await whitelistBodySchema.parseAsync(await event.request.json()); - } catch (e) { - console.log((e as Error).message); - return fail(400, { message: 'Invalid request body' }); - } - if (bodyValidated.authToken !== serverEnv.WHITELIST_ENDPOINT_TOKEN) { - return fail(401, { message: 'Not authorized' }); - } - - const { users } = bodyValidated; - - for (const user of users) { - await db - .insert(schema.profile) - .values({ - givenName: `${user.firstName} ${user.lastName}`, - email: user.email, - username: user.githubUsername, - isWhitelisted: true, - isBanned: false, - role: 'competitor' - }) - .onConflictDoUpdate({ - target: schema.profile.username, - set: { - username: user.githubUsername.toLowerCase(), - givenName: `${user.firstName} ${user.lastName}`, - email: user.email, - isWhitelisted: true, - isBanned: false, - role: 'competitor' - } - }); - } - - return Response.json({ message: 'Whitelist updated' }); -} diff --git a/src/routes/auth/login/github/+server.ts b/src/routes/auth/login/github/+server.ts deleted file mode 100644 index bf7fc6b..0000000 --- a/src/routes/auth/login/github/+server.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { RequestEvent } from './$types'; -import { appRouter } from '$lib/orpc/server/router'; -import { createOrpcContext } from '$lib/orpc/server/context'; - -export async function GET(event: RequestEvent) { - const { url } = await appRouter.auth.getOAuthUrlMutation.callable({ - context: createOrpcContext(event) - })(); - - return new Response(null, { - status: 302, - headers: { - Location: url - } - }); -} diff --git a/src/routes/auth/login/github/callback/+server.ts b/src/routes/auth/login/github/callback/+server.ts deleted file mode 100644 index d9279f9..0000000 --- a/src/routes/auth/login/github/callback/+server.ts +++ /dev/null @@ -1,217 +0,0 @@ -import { generateSessionToken, createSession, setSessionTokenCookie } from '$lib/server/auth'; -import { githubOAuth } from '$lib/server/auth'; - -import type { RequestEvent } from './$types'; -import type { OAuth2Tokens } from 'arctic'; -import { db, schema } from '$lib/server/db'; -import { eq } from 'drizzle-orm'; -import { octokit } from '$lib/github'; -import { logger } from '$lib/logger'; -import { nanoid } from 'nanoid'; -import { authenticatedUserOrgStatus } from '$lib/orpc/server/router/account'; - -export async function GET(event: RequestEvent): Promise { - const reqId = event.request.headers.get('x-railway-request-id') ?? nanoid(); - const apiLogger = logger.child({ - route: '/auth/login/github/callback', - method: 'GET', - reqId - }); - - const code = event.url.searchParams.get('code'); - const state = event.url.searchParams.get('state'); - const storedState = event.cookies.get('github_oauth_state') ?? null; - - apiLogger.info('Github OAuth callback', { code }); - - // --------- Validate State --------- - if (code === null || state === null || storedState === null) { - apiLogger.warn('Invalid state, 400 error', { error: 400, code }); - return Response.json( - { - status: 400, - message: 'Invalid state' - }, - { status: 400 } - ); - } - if (state !== storedState) { - apiLogger.warn('States do not match, 400 error', { error: 400, code }); - return Response.json( - { - status: 400, - message: 'Incorrect state' - }, - { status: 400 } - ); - } - - // --------- Validate Authorization Code --------- - let tokens: OAuth2Tokens; - try { - tokens = await githubOAuth.validateAuthorizationCode(code); - } catch (e: unknown) { - const err = e as Error; - // Invalid code or client credentials - apiLogger.warn('Could not validate OAuth Authorization Code', { error: 400, code }); - return Response.json( - { - status: 400, - message: 'Authorization code error', - error: err.message - }, - { status: 400 } - ); - } - - // --------- Get Github User Info --------- - let githubUserResponse: { data: { login: string; name: string | null; id: number } }; - - try { - const res = await octokit.rest.users.getAuthenticated({ - headers: { - Authorization: `Bearer ${tokens.accessToken()}` - } - }); - githubUserResponse = res; - } catch (e: unknown) { - const err = e as Error; - apiLogger.warn('Could not get authenticated user', { error: 400, code, ghError: err }); - return Response.json( - { - status: 400, - message: 'Could not get authenticated user', - error: err.message - }, - { status: 400 } - ); - } - - const { isInOrg: userInOrg, isAdmin: userIsAdmin } = await authenticatedUserOrgStatus( - githubUserResponse.data.login, - tokens.accessToken() - ); - - apiLogger.info('USER FOUND', { user: githubUserResponse.data.login, admin: userIsAdmin }); - - // --------- Check Whitelist and Ban Status --------- - apiLogger.info('Checking competitor list', { user: githubUserResponse.data.login }); - const [competitor] = await db - .select({ - username: schema.profile.username, - isWhitelisted: schema.profile.isWhitelisted, - isBanned: schema.profile.isBanned - }) - .from(schema.profile) - .where(eq(schema.profile.username, githubUserResponse.data.login.toLowerCase())); - - if (competitor) { - apiLogger.info('Competitor Found', { competitor }); - if (competitor.isBanned) { - apiLogger.warn('User is banned', { user: githubUserResponse.data.login }); - return Response.json( - { - message: 'you are banned' - }, - { - status: 403 - } - ); - } - } else { - apiLogger.info('User not found in competitors, inserting', { - user: githubUserResponse.data.login - }); - await db.insert(schema.profile).values({ - username: githubUserResponse.data.login.toLowerCase(), - role: userIsAdmin ? 'admin' : 'competitor', - // Admins should be automatically whitelisted - isWhitelisted: Boolean(userIsAdmin) - }); - } - - // --------- Check if user already exists --------- - const [existingUser] = await db - .select({ id: schema.user.id }) - .from(schema.user) - .where(eq(schema.user.githubId, githubUserResponse.data.id)); - - apiLogger.info('USER AUTH INFO', { - username: githubUserResponse.data.login, - exists: Boolean(existingUser), - knownStatus: competitor ?? 'no' - }); - - if (existingUser) { - apiLogger.info('User already exists', { user: githubUserResponse.data.login }); - // Create and set session token - const sessionToken = generateSessionToken(); - const session = await createSession(sessionToken, existingUser.id); - setSessionTokenCookie(event, sessionToken, session.expiresAt); - - // Update fullName, adminStatus - await db - .update(schema.user) - .set({ - fullName: githubUserResponse.data.name, - isOrgAdmin: Boolean(userIsAdmin), - isOrgMember: userInOrg - }) - .where(eq(schema.user.id, existingUser.id)); - - await db - .update(schema.profile) - .set({ - linkedUserId: existingUser.id, - isWhitelisted: userIsAdmin ? true : competitor?.isWhitelisted - }) - .where(eq(schema.profile.username, githubUserResponse.data.login.toLowerCase())); - - apiLogger.info('Known User Logged In', { - username: githubUserResponse.data.login, - admin: userIsAdmin - }); - - return new Response(null, { - status: 302, - headers: { - Location: userIsAdmin ? '/admin' : '/home' - } - }); - } - - apiLogger.info('Creating new user', { user: githubUserResponse.data.login }); - - const [user] = await db - .insert(schema.user) - .values({ - username: githubUserResponse.data.login, - githubId: githubUserResponse.data.id, - fullName: githubUserResponse.data.name, - isOrgAdmin: Boolean(userIsAdmin), - isOrgMember: userInOrg - }) - .returning(); - - apiLogger.info('New User Created', { - username: githubUserResponse.data.login, - admin: userIsAdmin - }); - - // Link competitor to user - await db - .update(schema.profile) - .set({ linkedUserId: user.id }) - .where(eq(schema.profile.username, githubUserResponse.data.login.toLowerCase())); - - const sessionToken = generateSessionToken(); - const session = await createSession(sessionToken, user.id); - setSessionTokenCookie(event, sessionToken, session.expiresAt); - - return new Response(null, { - status: 302, - headers: { - Location: userIsAdmin ? '/admin' : '/home' - } - }); -} From aef9207b33504924c6fa0be29ed7555da48a6481 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 15:08:09 -0500 Subject: [PATCH 15/85] increase db connection pool --- src/lib/server/db/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/server/db/index.ts b/src/lib/server/db/index.ts index 8763e82..c3a9cee 100644 --- a/src/lib/server/db/index.ts +++ b/src/lib/server/db/index.ts @@ -4,7 +4,8 @@ import postgres from 'postgres'; import * as schema from '$lib/server/db/schema'; -const queryClient = postgres(serverEnv.DATABASE_URL); +// postgres.js has built in connection pooling +const queryClient = postgres(serverEnv.DATABASE_URL, { max: 20 }); export const db = drizzle({ client: queryClient, schema }); export default { client: db, schema }; From 7e7f3f8322a778d6d0db9dc9bd38289a20ba213a Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 15:08:23 -0500 Subject: [PATCH 16/85] auth:db migrate script --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d3c3bdd..c746663 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "db:studio": "drizzle-kit studio", "db:gen": "drizzle-kit generate", "db:drop": "drizzle-kit drop", - "auth:db": "bunx @better-auth/cli@latest generate --config src/lib/auth/server.ts --output src/lib/server/db/auth.ts", + "auth:db": "bunx @better-auth/cli generate --config src/lib/auth/server.ts --output src/lib/server/db/auth.ts", "email:build": "email build -d src/lib/email/emails", "email:dev": "email dev -d src/lib/email/emails", "email:export": "email export -d src/lib/email/emails", From 12aab097aa6f1c9d9e828e4a82a7b6ac61138a7c Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 15:40:04 -0500 Subject: [PATCH 17/85] document how to generate the auth schema --- src/lib/auth/README.md | 28 ++++++++++++++++++++++++++++ src/lib/env/server.ts | 12 ++++++------ 2 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 src/lib/auth/README.md diff --git a/src/lib/auth/README.md b/src/lib/auth/README.md new file mode 100644 index 0000000..5ef49be --- /dev/null +++ b/src/lib/auth/README.md @@ -0,0 +1,28 @@ +# Authentication + +## Generating the database schema + +SvelteKit has it's own magic for environment variables, but it doesn't work with stuff outside of sveltekit. Thus, some temporary modifications are required to automatically generate the database schema. + +1. In the `createEnv` function call, comment out the lines `runtimeEnv: { ...privateEnv, ...publicEnv },` & `skipValidation: building,`. Uncomment the line that says `runtimeEnv: import.meta.env,` +2. Comment out these imports at the top of the file: + +```ts +import { building } from '$app/environment'; +import { env as privateEnv } from '$env/dynamic/private'; +import { env as publicEnv } from '$env/dynamic/public'; +``` + +so that it becomes + +```ts +// import { building } from '$app/environment'; +// import { env as privateEnv } from '$env/dynamic/private'; +// import { env as publicEnv } from '$env/dynamic/public'; +``` + +3. In the root of the project, run `bun auth:db` + +4. After this is complete, un-comment the imports shown above, then comment out the `runtimeEnv: import.meta.env,` and un-comment the `runtimeEnv: { ...privateEnv, ...publicEnv },` & `skipValidation: building,`. + +The comment/un-comment changes above should not be committed - these changes are only temporary and should be reverted before commits are made. diff --git a/src/lib/env/server.ts b/src/lib/env/server.ts index 4da2bee..c1542be 100644 --- a/src/lib/env/server.ts +++ b/src/lib/env/server.ts @@ -1,6 +1,6 @@ -// import { building } from '$app/environment'; -// import { env as privateEnv } from '$env/dynamic/private'; -// import { env as publicEnv } from '$env/dynamic/public'; +import { building } from '$app/environment'; +import { env as privateEnv } from '$env/dynamic/private'; +import { env as publicEnv } from '$env/dynamic/public'; import { createEnv } from '@t3-oss/env-core'; import { z } from 'zod'; @@ -22,8 +22,8 @@ export const serverEnv = createEnv({ PUBLIC_SHOW_CHALLENGES: z.coerce.boolean().default(true) }, clientPrefix: 'PUBLIC_', - // runtimeEnv: { ...privateEnv, ...publicEnv }, - runtimeEnv: import.meta.env, + runtimeEnv: { ...privateEnv, ...publicEnv }, + // runtimeEnv: import.meta.env, + skipValidation: building, emptyStringAsUndefined: true - // skipValidation: building }); From 665b0d97f5ea34bd10dbe659c6af746483fd3764 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 15:41:33 -0500 Subject: [PATCH 18/85] remove unused/outdated environment variables --- src/lib/env/client.ts | 3 +-- src/lib/env/server.ts | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/lib/env/client.ts b/src/lib/env/client.ts index 2056de6..521a26d 100644 --- a/src/lib/env/client.ts +++ b/src/lib/env/client.ts @@ -5,8 +5,7 @@ import { z } from 'zod'; export const clientEnv = createEnv({ client: { - PUBLIC_GITHUB_ORGNAME: z.string().nonempty(), - PUBLIC_SHOW_CHALLENGES: z.coerce.boolean().default(true) + PUBLIC_GITHUB_ORGNAME: z.string().nonempty() }, clientPrefix: 'PUBLIC_', runtimeEnv, diff --git a/src/lib/env/server.ts b/src/lib/env/server.ts index c1542be..9bd4d52 100644 --- a/src/lib/env/server.ts +++ b/src/lib/env/server.ts @@ -13,13 +13,11 @@ export const serverEnv = createEnv({ GITHUB_APP_CLIENT_ID: z.string().nonempty(), GITHUB_APP_CLIENT_SECRET: z.string().nonempty(), GITHUB_WEBHOOK_SECRET: z.base64().nonempty(), - WHITELIST_ENDPOINT_TOKEN: z.base64().nonempty(), SMTP_URL: z.string(), SMTP_FROM: z.email() }, client: { - PUBLIC_GITHUB_ORGNAME: z.string().nonempty(), - PUBLIC_SHOW_CHALLENGES: z.coerce.boolean().default(true) + PUBLIC_GITHUB_ORGNAME: z.string().nonempty() }, clientPrefix: 'PUBLIC_', runtimeEnv: { ...privateEnv, ...publicEnv }, From 45bd1494ea4b2f064e5838a8c88457e639bb9e8c Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 21:37:09 -0500 Subject: [PATCH 19/85] error page --- src/routes/auth/error/+page.svelte | 68 ++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/routes/auth/error/+page.svelte diff --git a/src/routes/auth/error/+page.svelte b/src/routes/auth/error/+page.svelte new file mode 100644 index 0000000..a61d5db --- /dev/null +++ b/src/routes/auth/error/+page.svelte @@ -0,0 +1,68 @@ + + +
+ + + Oh No! An Error Occurred :( + + + +
+
+
+ +
+
+

{errorMessage}

+

+ Please try again, and if this error continues, contact the hackathon organizers. +

+
+
+
+
+ + + + +
+ + + + +
From eca16a0ce2c7636b432a568d835a8ce39e4b7d96 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 21:38:27 -0500 Subject: [PATCH 20/85] basic auth ui --- src/routes/(auth)/+layout.server.ts | 7 + src/routes/{auth => (auth)}/+layout.svelte | 4 +- src/routes/(auth)/error-box.svelte | 39 ++++++ src/routes/(auth)/login/+page.svelte | 141 +++++++++++++++++++++ src/routes/(auth)/sign-up/+page.svelte | 107 ++++++++++++++++ src/routes/auth/login/+page.server.ts | 15 --- src/routes/auth/login/+page.svelte | 17 --- src/routes/auth/logout/+server.ts | 11 -- 8 files changed, 296 insertions(+), 45 deletions(-) create mode 100644 src/routes/(auth)/+layout.server.ts rename src/routes/{auth => (auth)}/+layout.svelte (77%) create mode 100644 src/routes/(auth)/error-box.svelte create mode 100644 src/routes/(auth)/login/+page.svelte create mode 100644 src/routes/(auth)/sign-up/+page.svelte delete mode 100644 src/routes/auth/login/+page.server.ts delete mode 100644 src/routes/auth/login/+page.svelte delete mode 100644 src/routes/auth/logout/+server.ts diff --git a/src/routes/(auth)/+layout.server.ts b/src/routes/(auth)/+layout.server.ts new file mode 100644 index 0000000..5a4acff --- /dev/null +++ b/src/routes/(auth)/+layout.server.ts @@ -0,0 +1,7 @@ +import { redirect, type ServerLoadEvent } from '@sveltejs/kit'; + +export const load = (event: ServerLoadEvent) => { + if (event.locals.user) { + return redirect(302, '/account'); + } +}; diff --git a/src/routes/auth/+layout.svelte b/src/routes/(auth)/+layout.svelte similarity index 77% rename from src/routes/auth/+layout.svelte rename to src/routes/(auth)/+layout.svelte index 3a4fc28..e0edcef 100644 --- a/src/routes/auth/+layout.svelte +++ b/src/routes/(auth)/+layout.svelte @@ -5,8 +5,8 @@ let { children } = $props(); -
- {@render children()} +
+ {@render children()} diff --git a/src/routes/(auth)/error-box.svelte b/src/routes/(auth)/error-box.svelte new file mode 100644 index 0000000..14463a4 --- /dev/null +++ b/src/routes/(auth)/error-box.svelte @@ -0,0 +1,39 @@ + + +
+
+
+ +
+
+

{error.status} {error.statusText}

+ {#if error.message} +

+ {error.message} +

+ {/if} +
+
+
diff --git a/src/routes/(auth)/login/+page.svelte b/src/routes/(auth)/login/+page.svelte new file mode 100644 index 0000000..4e0b82f --- /dev/null +++ b/src/routes/(auth)/login/+page.svelte @@ -0,0 +1,141 @@ + + + + Login | HackHelp + + +HackHelp Sign In + If you're a UVM student or faculty member, use NetID sign in. + + +
+ + +
+ +
+ +
+ or +
+
+
+ + + +
+ + {#if signInError} + + {/if} +
+ + + + If you have not signed up for the hackathon,
please go
+ Last year's accounts were wiped. +
+
diff --git a/src/routes/(auth)/sign-up/+page.svelte b/src/routes/(auth)/sign-up/+page.svelte new file mode 100644 index 0000000..401bc41 --- /dev/null +++ b/src/routes/(auth)/sign-up/+page.svelte @@ -0,0 +1,107 @@ + + + + Signup | HackHelp + + +HackHelp Sign Up + + If you're a UVM student or faculty member, use NetID sign up to automatically verify your + account. + + + +
+ +
+ +
+ +
+ or +
+
+
+ + + +
+ + {#if signUpError} + + {/if} +
+ + + + If you have an account, please go + + diff --git a/src/routes/auth/login/+page.server.ts b/src/routes/auth/login/+page.server.ts deleted file mode 100644 index 116c536..0000000 --- a/src/routes/auth/login/+page.server.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { redirect, type ServerLoadEvent } from '@sveltejs/kit'; - -export const load = (event: ServerLoadEvent) => { - if (event.locals.user) { - if (!event.locals.user.isOrgMember) { - return redirect(302, '/account'); - } - - if (event.locals.user.isOrgAdmin) { - return redirect(302, '/admin'); - } - - return redirect(302, '/home'); - } -}; diff --git a/src/routes/auth/login/+page.svelte b/src/routes/auth/login/+page.svelte deleted file mode 100644 index 2b18539..0000000 --- a/src/routes/auth/login/+page.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - -HackHelp Sign InSign in with GitHub - diff --git a/src/routes/auth/logout/+server.ts b/src/routes/auth/logout/+server.ts deleted file mode 100644 index 64494ee..0000000 --- a/src/routes/auth/logout/+server.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { type RequestEvent, fail, redirect } from '@sveltejs/kit'; -import { invalidateSession, deleteSessionTokenCookie } from '$lib/server/auth'; - -export async function POST(event: RequestEvent) { - if (event.locals.session === null) { - return fail(401); - } - await invalidateSession(event.locals.session.id); - deleteSessionTokenCookie(event); - return redirect(302, '/auth/login'); -} From bc72f068a78c98413ab2872fad399786663930be Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 21:38:37 -0500 Subject: [PATCH 21/85] remove default mono font --- src/app.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.html b/src/app.html index 0db9428..534b47b 100644 --- a/src/app.html +++ b/src/app.html @@ -7,6 +7,6 @@ %sveltekit.head% -
%sveltekit.body%
+
%sveltekit.body%
From 1ed34075cc0ab9ad3c81d80f61444315c6a836bb Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 21:46:53 -0500 Subject: [PATCH 22/85] add uvm netid auth --- .env.example | 6 ++++++ src/lib/auth/server.ts | 15 +++++++++++++-- src/lib/env/server.ts | 5 ++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/.env.example b/.env.example index f56916d..0279d70 100644 --- a/.env.example +++ b/.env.example @@ -17,6 +17,12 @@ GITHUB_APP_PRIVATE_KEY= # Signing webhooks GITHUB_WEBHOOK_SECRET= +# --- UVM NetID OIDC Configuration --- +# Allows UVM faculty and students to sign in with their NetIDs via Microsoft Entra +UVM_NETID_OIDC_CLIENT_ID= +UVM_NETID_OIDC_CLIENT_SECRET= +UVM_NETID_OIDC_DISCOVERY_URL= + # --- SMTP Connection URL for sending emails --- # This example URL applies to servers that use STARTTLS on port 587. ?pool=true enables connection pooling. SMTP_URL="smtp://user:pass@smtp.example.com:587/?pool=true" diff --git a/src/lib/auth/server.ts b/src/lib/auth/server.ts index 531f9e4..eac36f6 100644 --- a/src/lib/auth/server.ts +++ b/src/lib/auth/server.ts @@ -3,7 +3,7 @@ import { db } from '$lib/server/db'; import { betterAuth } from 'better-auth'; import { drizzleAdapter } from 'better-auth/adapters/drizzle'; import { passkey } from '@better-auth/passkey'; -import { emailOTP, magicLink, admin } from 'better-auth/plugins'; +import { emailOTP, magicLink, admin, genericOAuth, lastLoginMethod } from 'better-auth/plugins'; import { sendEmailOtp, sendMagicLinkEmail } from '$lib/email'; import { ac, roles } from './permissions'; @@ -38,7 +38,18 @@ export const auth = betterAuth({ admin({ ac, roles - }) + }), + genericOAuth({ + config: [ + { + providerId: 'uvm-netid', + clientId: serverEnv.UVM_NETID_OIDC_CLIENT_ID, + clientSecret: serverEnv.UVM_NETID_OIDC_CLIENT_SECRET, + discoveryUrl: serverEnv.UVM_NETID_OIDC_DISCOVERY_URL + } + ] + }), + lastLoginMethod() ], experimental: { joins: true } }); diff --git a/src/lib/env/server.ts b/src/lib/env/server.ts index 9bd4d52..2768b0c 100644 --- a/src/lib/env/server.ts +++ b/src/lib/env/server.ts @@ -14,7 +14,10 @@ export const serverEnv = createEnv({ GITHUB_APP_CLIENT_SECRET: z.string().nonempty(), GITHUB_WEBHOOK_SECRET: z.base64().nonempty(), SMTP_URL: z.string(), - SMTP_FROM: z.email() + SMTP_FROM: z.email(), + UVM_NETID_OIDC_CLIENT_ID: z.string(), + UVM_NETID_OIDC_CLIENT_SECRET: z.string(), + UVM_NETID_OIDC_DISCOVERY_URL: z.string() }, client: { PUBLIC_GITHUB_ORGNAME: z.string().nonempty() From bd95c3025987c3ab27172cbb4e83e4d53ba9adcd Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 21:46:57 -0500 Subject: [PATCH 23/85] more badge options --- src/lib/components/ui/badge/badge.svelte | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lib/components/ui/badge/badge.svelte b/src/lib/components/ui/badge/badge.svelte index 1f23724..304dbc2 100644 --- a/src/lib/components/ui/badge/badge.svelte +++ b/src/lib/components/ui/badge/badge.svelte @@ -7,7 +7,12 @@ default: 'bg-primary text-primary-foreground border-transparent shadow', secondary: 'bg-secondary text-secondary-foreground border-transparent', destructive: 'bg-destructive text-destructive-foreground border-transparent shadow', - outline: 'text-foreground' + outline: 'text-foreground', + blue: "bg-blue-50 text-blue-700 inset-ring-blue-700/10 dark:bg-blue-400/10 dark:text-blue-400 dark:inset-ring-blue-400/30", + green: "bg-green-50 text-green-700 inset-ring-green-700/10 dark:bg-green-400/10 dark:text-green-400 dark:inset-ring-green-400/30", + yellow: "bg-yellow-50 text-yellow-700 inset-ring-yellow-700/10 dark:bg-yellow-400/10 dark:text-yellow-400 dark:inset-ring-yellow-400/30" + + }, hoverEffects: { true: 'hover:cursor-pointer', From 84e59d3b583aa100d3fcb47441ced223a149fdb0 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 21:47:11 -0500 Subject: [PATCH 24/85] better auth client stuff --- src/lib/auth/client.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/lib/auth/client.ts b/src/lib/auth/client.ts index 9e9d525..e73139e 100644 --- a/src/lib/auth/client.ts +++ b/src/lib/auth/client.ts @@ -1,16 +1,24 @@ import { createAuthClient } from 'better-auth/svelte'; import { inferAdditionalFields } from 'better-auth/client/plugins'; import type { auth } from './server'; -import { adminClient, emailOTPClient, magicLinkClient } from 'better-auth/client/plugins'; +import { + adminClient, + emailOTPClient, + magicLinkClient, + genericOAuthClient, + lastLoginMethodClient +} from 'better-auth/client/plugins'; import { passkeyClient } from '@better-auth/passkey/client'; import { ac, roles } from './permissions'; -const authClient = createAuthClient({ +const __authClient = createAuthClient({ plugins: [ inferAdditionalFields(), passkeyClient(), emailOTPClient(), magicLinkClient(), + genericOAuthClient(), + lastLoginMethodClient(), adminClient({ ac, roles @@ -18,4 +26,4 @@ const authClient = createAuthClient({ ] }); -export const { signIn, signUp, useSession } = authClient; +export const { signIn, signUp, signOut, useSession, ...authClient } = __authClient; From 8b32c7d208f5d0858953b745158a0d3df8c23c0a Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 22:04:35 -0500 Subject: [PATCH 25/85] migrations --- drizzle/0000_silky_the_hood.sql | 75 +++++ drizzle/0001_elite_omega_red.sql | 5 + drizzle/meta/0000_snapshot.json | 523 +++++++++++++++++++++++++++++ drizzle/meta/0001_snapshot.json | 554 +++++++++++++++++++++++++++++++ drizzle/meta/_journal.json | 17 +- src/lib/auth/server.ts | 8 +- src/lib/server/db/auth.ts | 45 ++- 7 files changed, 1221 insertions(+), 6 deletions(-) create mode 100644 drizzle/0000_silky_the_hood.sql create mode 100644 drizzle/0001_elite_omega_red.sql create mode 100644 drizzle/meta/0000_snapshot.json create mode 100644 drizzle/meta/0001_snapshot.json diff --git a/drizzle/0000_silky_the_hood.sql b/drizzle/0000_silky_the_hood.sql new file mode 100644 index 0000000..60d55e1 --- /dev/null +++ b/drizzle/0000_silky_the_hood.sql @@ -0,0 +1,75 @@ +CREATE TABLE "configuration" ( + "key" text PRIMARY KEY NOT NULL, + "value" json +); +--> statement-breakpoint +CREATE TABLE "account" ( + "id" text PRIMARY KEY NOT NULL, + "account_id" text NOT NULL, + "provider_id" text NOT NULL, + "user_id" text NOT NULL, + "access_token" text, + "refresh_token" text, + "id_token" text, + "access_token_expires_at" timestamp, + "refresh_token_expires_at" timestamp, + "scope" text, + "password" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp NOT NULL +); +--> statement-breakpoint +CREATE TABLE "passkey" ( + "id" text PRIMARY KEY NOT NULL, + "name" text, + "public_key" text NOT NULL, + "user_id" text NOT NULL, + "credential_id" text NOT NULL, + "counter" integer NOT NULL, + "device_type" text NOT NULL, + "backed_up" boolean NOT NULL, + "transports" text, + "created_at" timestamp, + "aaguid" text +); +--> statement-breakpoint +CREATE TABLE "session" ( + "id" text PRIMARY KEY NOT NULL, + "expires_at" timestamp NOT NULL, + "token" text NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp NOT NULL, + "ip_address" text, + "user_agent" text, + "user_id" text NOT NULL, + CONSTRAINT "session_token_unique" UNIQUE("token") +); +--> statement-breakpoint +CREATE TABLE "user" ( + "id" text PRIMARY KEY NOT NULL, + "name" text NOT NULL, + "email" text NOT NULL, + "email_verified" boolean DEFAULT false NOT NULL, + "image" text, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL, + CONSTRAINT "user_email_unique" UNIQUE("email") +); +--> statement-breakpoint +CREATE TABLE "verification" ( + "id" text PRIMARY KEY NOT NULL, + "identifier" text NOT NULL, + "value" text NOT NULL, + "expires_at" timestamp NOT NULL, + "created_at" timestamp DEFAULT now() NOT NULL, + "updated_at" timestamp DEFAULT now() NOT NULL +); +--> statement-breakpoint +ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "passkey" ADD CONSTRAINT "passkey_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "session" ADD CONSTRAINT "session_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +CREATE INDEX "account_userId_idx" ON "account" USING btree ("user_id");--> statement-breakpoint +CREATE INDEX "passkey_userId_idx" ON "passkey" USING btree ("user_id");--> statement-breakpoint +CREATE INDEX "passkey_credentialID_idx" ON "passkey" USING btree ("credential_id");--> statement-breakpoint +CREATE INDEX "session_userId_idx" ON "session" USING btree ("user_id");--> statement-breakpoint +CREATE INDEX "verification_identifier_idx" ON "verification" USING btree ("identifier"); \ No newline at end of file diff --git a/drizzle/0001_elite_omega_red.sql b/drizzle/0001_elite_omega_red.sql new file mode 100644 index 0000000..d8b78c0 --- /dev/null +++ b/drizzle/0001_elite_omega_red.sql @@ -0,0 +1,5 @@ +ALTER TABLE "session" ADD COLUMN "impersonated_by" text;--> statement-breakpoint +ALTER TABLE "user" ADD COLUMN "role" text;--> statement-breakpoint +ALTER TABLE "user" ADD COLUMN "banned" boolean DEFAULT false;--> statement-breakpoint +ALTER TABLE "user" ADD COLUMN "ban_reason" text;--> statement-breakpoint +ALTER TABLE "user" ADD COLUMN "ban_expires" timestamp; \ No newline at end of file diff --git a/drizzle/meta/0000_snapshot.json b/drizzle/meta/0000_snapshot.json new file mode 100644 index 0000000..6708831 --- /dev/null +++ b/drizzle/meta/0000_snapshot.json @@ -0,0 +1,523 @@ +{ + "id": "ba0c9efb-7a19-425f-bd3e-65d7f991ce31", + "prevId": "00000000-0000-0000-0000-000000000000", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.configuration": { + "name": "configuration", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "value": { + "name": "value", + "type": "json", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "account_userId_idx": { + "name": "account_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.passkey": { + "name": "passkey", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "credential_id": { + "name": "credential_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "counter": { + "name": "counter", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "device_type": { + "name": "device_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "backed_up": { + "name": "backed_up", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "transports": { + "name": "transports", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "aaguid": { + "name": "aaguid", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "passkey_userId_idx": { + "name": "passkey_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "passkey_credentialID_idx": { + "name": "passkey_credentialID_idx", + "columns": [ + { + "expression": "credential_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "passkey_user_id_user_id_fk": { + "name": "passkey_user_id_user_id_fk", + "tableFrom": "passkey", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "session_userId_idx": { + "name": "session_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "verification_identifier_idx": { + "name": "verification_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/0001_snapshot.json b/drizzle/meta/0001_snapshot.json new file mode 100644 index 0000000..bf11993 --- /dev/null +++ b/drizzle/meta/0001_snapshot.json @@ -0,0 +1,554 @@ +{ + "id": "a3f56e93-4f6f-468d-a5fd-ef5ea6a718c7", + "prevId": "ba0c9efb-7a19-425f-bd3e-65d7f991ce31", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.configuration": { + "name": "configuration", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "value": { + "name": "value", + "type": "json", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "account_userId_idx": { + "name": "account_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.passkey": { + "name": "passkey", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "credential_id": { + "name": "credential_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "counter": { + "name": "counter", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "device_type": { + "name": "device_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "backed_up": { + "name": "backed_up", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "transports": { + "name": "transports", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "aaguid": { + "name": "aaguid", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "passkey_userId_idx": { + "name": "passkey_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "passkey_credentialID_idx": { + "name": "passkey_credentialID_idx", + "columns": [ + { + "expression": "credential_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "passkey_user_id_user_id_fk": { + "name": "passkey_user_id_user_id_fk", + "tableFrom": "passkey", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "impersonated_by": { + "name": "impersonated_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "session_userId_idx": { + "name": "session_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "banned": { + "name": "banned", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "ban_reason": { + "name": "ban_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ban_expires": { + "name": "ban_expires", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "verification_identifier_idx": { + "name": "verification_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index eaa8fcf..5dad831 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -1,5 +1,20 @@ { "version": "7", "dialect": "postgresql", - "entries": [] + "entries": [ + { + "idx": 0, + "version": "7", + "when": 1768612097561, + "tag": "0000_silky_the_hood", + "breakpoints": true + }, + { + "idx": 1, + "version": "7", + "when": 1768618886883, + "tag": "0001_elite_omega_red", + "breakpoints": true + } + ] } \ No newline at end of file diff --git a/src/lib/auth/server.ts b/src/lib/auth/server.ts index eac36f6..73a08ed 100644 --- a/src/lib/auth/server.ts +++ b/src/lib/auth/server.ts @@ -35,10 +35,6 @@ export const auth = betterAuth({ await sendMagicLinkEmail(email, { magicLink: url }); } }), - admin({ - ac, - roles - }), genericOAuth({ config: [ { @@ -49,6 +45,10 @@ export const auth = betterAuth({ } ] }), + admin({ + ac, + roles + }), lastLoginMethod() ], experimental: { joins: true } diff --git a/src/lib/server/db/auth.ts b/src/lib/server/db/auth.ts index 413a524..dd3028e 100644 --- a/src/lib/server/db/auth.ts +++ b/src/lib/server/db/auth.ts @@ -1,5 +1,12 @@ import { relations } from "drizzle-orm"; -import { pgTable, text, timestamp, boolean, index } from "drizzle-orm/pg-core"; +import { + pgTable, + text, + timestamp, + boolean, + integer, + index, +} from "drizzle-orm/pg-core"; export const user = pgTable("user", { id: text("id").primaryKey(), @@ -12,6 +19,10 @@ export const user = pgTable("user", { .defaultNow() .$onUpdate(() => /* @__PURE__ */ new Date()) .notNull(), + role: text("role"), + banned: boolean("banned").default(false), + banReason: text("ban_reason"), + banExpires: timestamp("ban_expires"), }); export const session = pgTable( @@ -29,6 +40,7 @@ export const session = pgTable( userId: text("user_id") .notNull() .references(() => user.id, { onDelete: "cascade" }), + impersonatedBy: text("impersonated_by"), }, (table) => [index("session_userId_idx").on(table.userId)], ); @@ -73,9 +85,33 @@ export const verification = pgTable( (table) => [index("verification_identifier_idx").on(table.identifier)], ); +export const passkey = pgTable( + "passkey", + { + id: text("id").primaryKey(), + name: text("name"), + publicKey: text("public_key").notNull(), + userId: text("user_id") + .notNull() + .references(() => user.id, { onDelete: "cascade" }), + credentialID: text("credential_id").notNull(), + counter: integer("counter").notNull(), + deviceType: text("device_type").notNull(), + backedUp: boolean("backed_up").notNull(), + transports: text("transports"), + createdAt: timestamp("created_at"), + aaguid: text("aaguid"), + }, + (table) => [ + index("passkey_userId_idx").on(table.userId), + index("passkey_credentialID_idx").on(table.credentialID), + ], +); + export const userRelations = relations(user, ({ many }) => ({ sessions: many(session), accounts: many(account), + passkeys: many(passkey), })); export const sessionRelations = relations(session, ({ one }) => ({ @@ -91,3 +127,10 @@ export const accountRelations = relations(account, ({ one }) => ({ references: [user.id], }), })); + +export const passkeyRelations = relations(passkey, ({ one }) => ({ + user: one(user, { + fields: [passkey.userId], + references: [user.id], + }), +})); From a7b50462355e1efa54151609b0bb078cd6ead8a8 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 22:05:36 -0500 Subject: [PATCH 26/85] fix signin --- src/routes/+page.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index c3af812..0d94a37 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -4,5 +4,5 @@

HackHelp

- +
From f5608a9efe802c9ef1fb0525970059aafa11a4a5 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 22:05:49 -0500 Subject: [PATCH 27/85] error box component --- src/routes/(auth)/error-box.svelte | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/routes/(auth)/error-box.svelte b/src/routes/(auth)/error-box.svelte index 14463a4..8a297ff 100644 --- a/src/routes/(auth)/error-box.svelte +++ b/src/routes/(auth)/error-box.svelte @@ -1,4 +1,6 @@
@@ -28,10 +36,13 @@
-

{error.status} {error.statusText}

+

+ {error.status} + {statusText} +

{#if error.message}

- {error.message} + {capitalize(error.message)}

{/if}
From c62ab61fd3470d4d8fdd5a368df760e5cd37d4db Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 22:10:49 -0500 Subject: [PATCH 28/85] utility pkg --- bun.lock | 3 +++ package.json | 1 + 2 files changed, 4 insertions(+) diff --git a/bun.lock b/bun.lock index 6407764..2881aad 100644 --- a/bun.lock +++ b/bun.lock @@ -42,6 +42,7 @@ "date-fns": "^4.1.0", "drizzle-kit": "^0.30.6", "drizzle-orm": "^0.39.3", + "es-toolkit": "^1.44.0", "formsnap": "2.0.1", "globals": "^15.15.0", "lucide-svelte": "^0.562.0", @@ -1098,6 +1099,8 @@ "env-paths": ["env-paths@3.0.0", "", {}, "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A=="], + "es-toolkit": ["es-toolkit@1.44.0", "", {}, "sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg=="], + "esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], "esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="], diff --git a/package.json b/package.json index c746663..3944866 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "date-fns": "^4.1.0", "drizzle-kit": "^0.30.6", "drizzle-orm": "^0.39.3", + "es-toolkit": "^1.44.0", "formsnap": "2.0.1", "globals": "^15.15.0", "lucide-svelte": "^0.562.0", From 3c1732b9a6503713fa7ea13a16b682201ed1905d Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 22:44:17 -0500 Subject: [PATCH 29/85] add confirmation for email send --- src/routes/(auth)/login/+layout.svelte | 13 +++++++++++++ src/routes/(auth)/login/+page.svelte | 10 ++-------- src/routes/(auth)/login/email-sent/+page.svelte | 14 ++++++++++++++ src/routes/(auth)/sign-up/+layout.svelte | 16 ++++++++++++++++ src/routes/(auth)/sign-up/+page.svelte | 11 +---------- .../(auth)/sign-up/email-sent/+page.svelte | 14 ++++++++++++++ 6 files changed, 60 insertions(+), 18 deletions(-) create mode 100644 src/routes/(auth)/login/+layout.svelte create mode 100644 src/routes/(auth)/login/email-sent/+page.svelte create mode 100644 src/routes/(auth)/sign-up/+layout.svelte create mode 100644 src/routes/(auth)/sign-up/email-sent/+page.svelte diff --git a/src/routes/(auth)/login/+layout.svelte b/src/routes/(auth)/login/+layout.svelte new file mode 100644 index 0000000..e66397d --- /dev/null +++ b/src/routes/(auth)/login/+layout.svelte @@ -0,0 +1,13 @@ + + +HackHelp Sign In + If you're a UVM student or faculty member, use NetID sign in. + + +{@render children()} diff --git a/src/routes/(auth)/login/+page.svelte b/src/routes/(auth)/login/+page.svelte index 4e0b82f..1b5ec9c 100644 --- a/src/routes/(auth)/login/+page.svelte +++ b/src/routes/(auth)/login/+page.svelte @@ -4,11 +4,8 @@ import { signIn } from '$lib/auth/client'; import Badge from '$lib/components/ui/badge/badge.svelte'; import Button from '$lib/components/ui/button/button.svelte'; - import { CardDescription } from '$lib/components/ui/card'; + import { CardDescription, CardFooter } from '$lib/components/ui/card'; import CardContent from '$lib/components/ui/card/card-content.svelte'; - import CardFooter from '$lib/components/ui/card/card-footer.svelte'; - import CardHeader from '$lib/components/ui/card/card-header.svelte'; - import CardTitle from '$lib/components/ui/card/card-title.svelte'; import Input from '$lib/components/ui/input/input.svelte'; import Label from '$lib/components/ui/label/label.svelte'; import { posthogHandler } from '$lib/utils'; @@ -70,6 +67,7 @@ newUserCallbackURL: '/welcome' }); if (error) signInError = error; + await goto(resolve('/(auth)/login/email-sent')); loading = false; } @@ -78,10 +76,6 @@ Login | HackHelp -HackHelp Sign In - If you're a UVM student or faculty member, use NetID sign in. -
Email me a sign up link diff --git a/src/routes/(auth)/sign-up/email-sent/+page.svelte b/src/routes/(auth)/sign-up/email-sent/+page.svelte new file mode 100644 index 0000000..64ca3f4 --- /dev/null +++ b/src/routes/(auth)/sign-up/email-sent/+page.svelte @@ -0,0 +1,14 @@ + + + + +

Email Sent!

+

+ Check your email for a message from {clientEnv.PUBLIC_SMTP_FROM} +

+
From 2e598b6233e81637a22abd7409cb26d881d58dab Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 22:44:26 -0500 Subject: [PATCH 30/85] move posthog reset --- src/routes/(auth)/+layout.svelte | 4 ++++ src/routes/(auth)/login/+page.svelte | 4 ---- src/routes/(auth)/sign-up/+page.svelte | 7 +++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/routes/(auth)/+layout.svelte b/src/routes/(auth)/+layout.svelte index e0edcef..2411800 100644 --- a/src/routes/(auth)/+layout.svelte +++ b/src/routes/(auth)/+layout.svelte @@ -1,8 +1,12 @@
diff --git a/src/routes/(auth)/login/+page.svelte b/src/routes/(auth)/login/+page.svelte index 1b5ec9c..0f44426 100644 --- a/src/routes/(auth)/login/+page.svelte +++ b/src/routes/(auth)/login/+page.svelte @@ -8,13 +8,9 @@ import CardContent from '$lib/components/ui/card/card-content.svelte'; import Input from '$lib/components/ui/input/input.svelte'; import Label from '$lib/components/ui/label/label.svelte'; - import { posthogHandler } from '$lib/utils'; import ArrowRight from 'lucide-svelte/icons/arrow-right'; import ErrorBox from '../error-box.svelte'; - // Always reset on the sign in page to ensure we don't track the wrong user - posthogHandler((posthog) => posthog.reset()); - let emailText = $state(''); let loading = $state(false); let signInError = $state<{ diff --git a/src/routes/(auth)/sign-up/+page.svelte b/src/routes/(auth)/sign-up/+page.svelte index fb47e88..78614df 100644 --- a/src/routes/(auth)/sign-up/+page.svelte +++ b/src/routes/(auth)/sign-up/+page.svelte @@ -6,12 +6,10 @@ import CardFooter from '$lib/components/ui/card/card-footer.svelte'; import Input from '$lib/components/ui/input/input.svelte'; import Label from '$lib/components/ui/label/label.svelte'; - import { posthogHandler } from '$lib/utils'; import ArrowRight from 'lucide-svelte/icons/arrow-right'; import ErrorBox from '../error-box.svelte'; - - // Always reset on the sign in page to ensure we don't track the wrong user - posthogHandler((posthog) => posthog.reset()); + import { goto } from '$app/navigation'; + import { resolve } from '$app/paths'; let emailText = $state(''); let loading = $state(false); @@ -44,6 +42,7 @@ newUserCallbackURL: '/welcome' }); if (error) signUpError = error; + await goto(resolve('/(auth)/sign-up/email-sent')); loading = false; } From f9bec061ef6e890ad617e4f54bbfb6e736e1d551 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 22:44:50 -0500 Subject: [PATCH 31/85] make smtp from address a public env var --- .env.example | 2 +- src/lib/email/index.tsx | 4 ++-- src/lib/env/client.ts | 3 ++- src/lib/env/server.ts | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.env.example b/.env.example index 0279d70..31f24e3 100644 --- a/.env.example +++ b/.env.example @@ -27,7 +27,7 @@ UVM_NETID_OIDC_DISCOVERY_URL= # This example URL applies to servers that use STARTTLS on port 587. ?pool=true enables connection pooling. SMTP_URL="smtp://user:pass@smtp.example.com:587/?pool=true" # Email account to send from -SMTP_FROM="user@example.com" +PUBLIC_SMTP_FROM="user@example.com" # --- Miscellaneous --- PUBLIC_SHOW_CHALLENGES= diff --git a/src/lib/email/index.tsx b/src/lib/email/index.tsx index 41145b8..aa95445 100644 --- a/src/lib/email/index.tsx +++ b/src/lib/email/index.tsx @@ -8,7 +8,7 @@ const transporter = nodemailer.createTransport(serverEnv.SMTP_URL); export async function sendMagicLinkEmail(to: string, emailProps: MagicLinkEmailProps) { return await transporter.sendMail({ - from: serverEnv.SMTP_FROM, + from: serverEnv.PUBLIC_SMTP_FROM, to, subject: 'Your HackHelp Login Link', html: await render() @@ -23,7 +23,7 @@ export async function sendEmailOtp(to: string, emailProps: OTPEmailProps) { ? 'Sign-in Code' : 'Password Reset Code'; return await transporter.sendMail({ - from: serverEnv.SMTP_FROM, + from: serverEnv.PUBLIC_SMTP_FROM, to, subject: `${title} | HackHelp`, html: await render() diff --git a/src/lib/env/client.ts b/src/lib/env/client.ts index 521a26d..f072560 100644 --- a/src/lib/env/client.ts +++ b/src/lib/env/client.ts @@ -5,7 +5,8 @@ import { z } from 'zod'; export const clientEnv = createEnv({ client: { - PUBLIC_GITHUB_ORGNAME: z.string().nonempty() + PUBLIC_GITHUB_ORGNAME: z.string().nonempty(), + PUBLIC_SMTP_FROM: z.email() }, clientPrefix: 'PUBLIC_', runtimeEnv, diff --git a/src/lib/env/server.ts b/src/lib/env/server.ts index 2768b0c..55cc8c0 100644 --- a/src/lib/env/server.ts +++ b/src/lib/env/server.ts @@ -14,13 +14,13 @@ export const serverEnv = createEnv({ GITHUB_APP_CLIENT_SECRET: z.string().nonempty(), GITHUB_WEBHOOK_SECRET: z.base64().nonempty(), SMTP_URL: z.string(), - SMTP_FROM: z.email(), UVM_NETID_OIDC_CLIENT_ID: z.string(), UVM_NETID_OIDC_CLIENT_SECRET: z.string(), UVM_NETID_OIDC_DISCOVERY_URL: z.string() }, client: { - PUBLIC_GITHUB_ORGNAME: z.string().nonempty() + PUBLIC_GITHUB_ORGNAME: z.string().nonempty(), + PUBLIC_SMTP_FROM: z.email() }, clientPrefix: 'PUBLIC_', runtimeEnv: { ...privateEnv, ...publicEnv }, From a6b058386bc9fa6340a15d0d3f0e376a2ada1a2d Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 16 Jan 2026 23:12:37 -0500 Subject: [PATCH 32/85] move account page --- src/routes/{ => (account)}/account/+page.server.ts | 0 src/routes/{ => (account)}/account/+page.svelte | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/routes/{ => (account)}/account/+page.server.ts (100%) rename src/routes/{ => (account)}/account/+page.svelte (99%) diff --git a/src/routes/account/+page.server.ts b/src/routes/(account)/account/+page.server.ts similarity index 100% rename from src/routes/account/+page.server.ts rename to src/routes/(account)/account/+page.server.ts diff --git a/src/routes/account/+page.svelte b/src/routes/(account)/account/+page.svelte similarity index 99% rename from src/routes/account/+page.svelte rename to src/routes/(account)/account/+page.svelte index 3a71e9c..bc35a0a 100644 --- a/src/routes/account/+page.svelte +++ b/src/routes/(account)/account/+page.svelte @@ -12,7 +12,7 @@ import { Badge } from '$lib/components/ui/badge'; import CardContent from '$lib/components/ui/card/card-content.svelte'; - import type { PageProps } from './$types'; + import type { PageProps } from '../../account/$types'; import { goto } from '$app/navigation'; import { clientEnv } from '$lib/env/client'; From d9c63801e8e3f467bb67ad9ce21752b178245f12 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 12:35:33 -0500 Subject: [PATCH 33/85] better typing for auth api context stuff --- src/app.d.ts | 13 +++++++++++-- src/hooks.server.ts | 12 ++++++++---- src/lib/orpc/server/context.ts | 12 ++++++++++-- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/app.d.ts b/src/app.d.ts index 1f8033a..f4e055c 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -3,10 +3,19 @@ declare global { namespace App { interface Locals { - user: import('$lib/auth/server').User | null; - session: import('$lib/auth/server').Session | null; + auth: AuthLocals; } } } +type AuthLocals = + | { + user: import('$lib/auth/server').User; + session: import('$lib/auth/server').Session; + } + | { + user: null; + session: null; + }; + export {}; diff --git a/src/hooks.server.ts b/src/hooks.server.ts index a10d765..015f93e 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -11,11 +11,15 @@ export const handle: Handle = async ({ event, resolve }) => { // Make session and user available on server if (session) { - event.locals.session = session.session; - event.locals.user = session.user; + event.locals.auth = { + session: session.session, + user: session.user + }; } else { - event.locals.session = null; - event.locals.user = null; + event.locals.auth = { + session: null, + user: null + }; } return svelteKitHandler({ event, resolve, auth, building }); diff --git a/src/lib/orpc/server/context.ts b/src/lib/orpc/server/context.ts index 938e399..6e29163 100644 --- a/src/lib/orpc/server/context.ts +++ b/src/lib/orpc/server/context.ts @@ -1,12 +1,20 @@ -import type { Session, User } from '$lib/server/db/schema'; import db from '$lib/server/db'; import { githubApp } from '$lib/github'; import type { Cookies } from '@sveltejs/kit'; import { logger } from '$lib/logger'; +import type { User, Session } from '$lib/auth/server'; export type ContextGeneratorParams = { request: Request; - locals: { user: User | null; session: Session | null }; + locals: + | { + user: User; + session: Session; + } + | { + user: null; + session: null; + }; cookies: Cookies; }; From f3bb774dfd4a886844c969dc486b657cc0ce8967 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 12:36:36 -0500 Subject: [PATCH 34/85] custom useSession hook with tanstack query for caching --- src/lib/auth/client.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/lib/auth/client.ts b/src/lib/auth/client.ts index e73139e..a52698c 100644 --- a/src/lib/auth/client.ts +++ b/src/lib/auth/client.ts @@ -1,6 +1,6 @@ import { createAuthClient } from 'better-auth/svelte'; import { inferAdditionalFields } from 'better-auth/client/plugins'; -import type { auth } from './server'; +import type { auth, AuthData } from './server'; import { adminClient, emailOTPClient, @@ -10,6 +10,7 @@ import { } from 'better-auth/client/plugins'; import { passkeyClient } from '@better-auth/passkey/client'; import { ac, roles } from './permissions'; +import { createQuery } from '@tanstack/svelte-query'; const __authClient = createAuthClient({ plugins: [ @@ -26,4 +27,12 @@ const __authClient = createAuthClient({ ] }); -export const { signIn, signUp, signOut, useSession, ...authClient } = __authClient; +export const { signIn, signUp, signOut, ...authClient } = __authClient; + +export function useSession(initialData?: AuthData) { + return createQuery(() => ({ + queryKey: ['user'], + queryFn: () => authClient.getSession().then((s) => s.data), + initialData + })); +} From 26d645a30d306a60862164d9c42d427991977a2f Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 14:13:22 -0500 Subject: [PATCH 35/85] rename auth client file to fix reactivity --- src/lib/auth/{client.ts => client.svelte.ts} | 11 ++++++----- src/routes/(auth)/login/+page.svelte | 2 +- src/routes/(auth)/sign-up/+page.svelte | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) rename src/lib/auth/{client.ts => client.svelte.ts} (76%) diff --git a/src/lib/auth/client.ts b/src/lib/auth/client.svelte.ts similarity index 76% rename from src/lib/auth/client.ts rename to src/lib/auth/client.svelte.ts index a52698c..5b0d64c 100644 --- a/src/lib/auth/client.ts +++ b/src/lib/auth/client.svelte.ts @@ -10,11 +10,11 @@ import { } from 'better-auth/client/plugins'; import { passkeyClient } from '@better-auth/passkey/client'; import { ac, roles } from './permissions'; -import { createQuery } from '@tanstack/svelte-query'; +import { createMutation, createQuery } from '@tanstack/svelte-query'; const __authClient = createAuthClient({ plugins: [ - inferAdditionalFields(), + // inferAdditionalFields(), passkeyClient(), emailOTPClient(), magicLinkClient(), @@ -31,8 +31,9 @@ export const { signIn, signUp, signOut, ...authClient } = __authClient; export function useSession(initialData?: AuthData) { return createQuery(() => ({ - queryKey: ['user'], - queryFn: () => authClient.getSession().then((s) => s.data), - initialData + queryKey: ['auth', 'user'], + queryFn: () => __authClient.getSession().then((r) => r.data), + initialData: initialData })); } + diff --git a/src/routes/(auth)/login/+page.svelte b/src/routes/(auth)/login/+page.svelte index 0f44426..a19ff32 100644 --- a/src/routes/(auth)/login/+page.svelte +++ b/src/routes/(auth)/login/+page.svelte @@ -1,7 +1,7 @@ + + Account Home | HackHelp + +

Account

-
+ Profile - +
-

{accountWithStatus.data.user.fullName}

- {#if accountWithStatus.data.user.isOrgAdmin} +

{session?.user.name}

+ {#if isAdmin} Administrator {/if}
- {accountWithStatus.data.user.username} + > -->
+ + Participant Status -
+ + -
+
diff --git a/src/routes/(account)/account/security.svelte b/src/routes/(account)/account/security.svelte new file mode 100644 index 0000000..a78652c --- /dev/null +++ b/src/routes/(account)/account/security.svelte @@ -0,0 +1,132 @@ + + + + + + + Account + Passkeys + + + + + Account + + Make changes to your account here. Click save when you're done. + + + + + + + + + + + + Passkeys + Add passkeys as an additional login method. + + + + + + Name + Actions + + + {#if !passkeyQuery.data && passkeyQuery.status !== 'success'} + {#if passkeyQuery.status === 'pending'} + Loading passkeys... + + {:else if passkeyQuery.status === 'error'} + Cannot load passkeys + {/if} + {:else} + + {#each passkeyQuery.data as passkey (passkey.id)} + + {passkey.name} + + + {/each} + {#if passkeyQuery.data && passkeyQuery.data.length === 0} + No passkeys registered + {/if} + + {/if} + + + + + + + + + From fe2dca6a8aabfab59d83711e72d5a0ece0ed1529 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 15:02:09 -0500 Subject: [PATCH 37/85] add better-auth username plugin --- drizzle/0002_violet_norman_osborn.sql | 3 + drizzle/meta/0002_snapshot.json | 573 ++++++++++++++++++++++++++ drizzle/meta/_journal.json | 7 + src/lib/auth/client.svelte.ts | 4 +- src/lib/auth/server.ts | 10 +- src/lib/server/db/auth.ts | 2 + 6 files changed, 597 insertions(+), 2 deletions(-) create mode 100644 drizzle/0002_violet_norman_osborn.sql create mode 100644 drizzle/meta/0002_snapshot.json diff --git a/drizzle/0002_violet_norman_osborn.sql b/drizzle/0002_violet_norman_osborn.sql new file mode 100644 index 0000000..122ae10 --- /dev/null +++ b/drizzle/0002_violet_norman_osborn.sql @@ -0,0 +1,3 @@ +ALTER TABLE "user" ADD COLUMN "username" text;--> statement-breakpoint +ALTER TABLE "user" ADD COLUMN "display_username" text;--> statement-breakpoint +ALTER TABLE "user" ADD CONSTRAINT "user_username_unique" UNIQUE("username"); \ No newline at end of file diff --git a/drizzle/meta/0002_snapshot.json b/drizzle/meta/0002_snapshot.json new file mode 100644 index 0000000..4519e39 --- /dev/null +++ b/drizzle/meta/0002_snapshot.json @@ -0,0 +1,573 @@ +{ + "id": "15c39188-f224-4fe3-99dd-21d159bb7e3e", + "prevId": "a3f56e93-4f6f-468d-a5fd-ef5ea6a718c7", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.configuration": { + "name": "configuration", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "value": { + "name": "value", + "type": "json", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "account_userId_idx": { + "name": "account_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.passkey": { + "name": "passkey", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "credential_id": { + "name": "credential_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "counter": { + "name": "counter", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "device_type": { + "name": "device_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "backed_up": { + "name": "backed_up", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "transports": { + "name": "transports", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "aaguid": { + "name": "aaguid", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "passkey_userId_idx": { + "name": "passkey_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "passkey_credentialID_idx": { + "name": "passkey_credentialID_idx", + "columns": [ + { + "expression": "credential_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "passkey_user_id_user_id_fk": { + "name": "passkey_user_id_user_id_fk", + "tableFrom": "passkey", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "impersonated_by": { + "name": "impersonated_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "session_userId_idx": { + "name": "session_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "display_username": { + "name": "display_username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "banned": { + "name": "banned", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "ban_reason": { + "name": "ban_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ban_expires": { + "name": "ban_expires", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + }, + "user_username_unique": { + "name": "user_username_unique", + "nullsNotDistinct": false, + "columns": [ + "username" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "verification_identifier_idx": { + "name": "verification_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index 5dad831..c1c16cc 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -15,6 +15,13 @@ "when": 1768618886883, "tag": "0001_elite_omega_red", "breakpoints": true + }, + { + "idx": 2, + "version": "7", + "when": 1768852803939, + "tag": "0002_violet_norman_osborn", + "breakpoints": true } ] } \ No newline at end of file diff --git a/src/lib/auth/client.svelte.ts b/src/lib/auth/client.svelte.ts index f8c7021..fd43ccc 100644 --- a/src/lib/auth/client.svelte.ts +++ b/src/lib/auth/client.svelte.ts @@ -6,7 +6,8 @@ import { emailOTPClient, magicLinkClient, genericOAuthClient, - lastLoginMethodClient + lastLoginMethodClient, + usernameClient } from 'better-auth/client/plugins'; import { passkeyClient } from '@better-auth/passkey/client'; import { ac, roles } from './permissions'; @@ -15,6 +16,7 @@ import { createQuery } from '@tanstack/svelte-query'; const __authClient = createAuthClient({ plugins: [ // inferAdditionalFields(), + usernameClient(), passkeyClient(), emailOTPClient(), magicLinkClient(), diff --git a/src/lib/auth/server.ts b/src/lib/auth/server.ts index 73a08ed..1ae1659 100644 --- a/src/lib/auth/server.ts +++ b/src/lib/auth/server.ts @@ -3,7 +3,14 @@ import { db } from '$lib/server/db'; import { betterAuth } from 'better-auth'; import { drizzleAdapter } from 'better-auth/adapters/drizzle'; import { passkey } from '@better-auth/passkey'; -import { emailOTP, magicLink, admin, genericOAuth, lastLoginMethod } from 'better-auth/plugins'; +import { + emailOTP, + magicLink, + admin, + genericOAuth, + lastLoginMethod, + username +} from 'better-auth/plugins'; import { sendEmailOtp, sendMagicLinkEmail } from '$lib/email'; import { ac, roles } from './permissions'; @@ -20,6 +27,7 @@ export const auth = betterAuth({ } }, plugins: [ + username(), passkey(), emailOTP({ async sendVerificationOTP({ email, otp, type }) { diff --git a/src/lib/server/db/auth.ts b/src/lib/server/db/auth.ts index dd3028e..7813aeb 100644 --- a/src/lib/server/db/auth.ts +++ b/src/lib/server/db/auth.ts @@ -19,6 +19,8 @@ export const user = pgTable("user", { .defaultNow() .$onUpdate(() => /* @__PURE__ */ new Date()) .notNull(), + username: text("username").unique(), + displayUsername: text("display_username"), role: text("role"), banned: boolean("banned").default(false), banReason: text("ban_reason"), From f06dfa2962cec4336342ec45939668dcb1fc4447 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 15:03:19 -0500 Subject: [PATCH 38/85] don't destructure auth client stuff bc that breaks svelte reactivity --- src/lib/auth/client.svelte.ts | 8 ++++---- src/routes/(auth)/login/+page.svelte | 8 ++++---- src/routes/(auth)/sign-up/+page.svelte | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/lib/auth/client.svelte.ts b/src/lib/auth/client.svelte.ts index fd43ccc..f4373f9 100644 --- a/src/lib/auth/client.svelte.ts +++ b/src/lib/auth/client.svelte.ts @@ -13,9 +13,9 @@ import { passkeyClient } from '@better-auth/passkey/client'; import { ac, roles } from './permissions'; import { createQuery } from '@tanstack/svelte-query'; -const __authClient = createAuthClient({ +export const authClient = createAuthClient({ plugins: [ - // inferAdditionalFields(), + inferAdditionalFields(), usernameClient(), passkeyClient(), emailOTPClient(), @@ -29,12 +29,12 @@ const __authClient = createAuthClient({ ] }); -export const { signIn, signUp, signOut, ...authClient } = __authClient; +// export const { signIn, signUp, signOut, ...authClient } = __authClient; export function useSession(initialData?: AuthData) { return createQuery(() => ({ queryKey: ['auth', 'user'], - queryFn: () => __authClient.getSession().then((r) => r.data), + queryFn: () => authClient.getSession().then((r) => r.data), initialData: initialData })); } diff --git a/src/routes/(auth)/login/+page.svelte b/src/routes/(auth)/login/+page.svelte index a19ff32..9638217 100644 --- a/src/routes/(auth)/login/+page.svelte +++ b/src/routes/(auth)/login/+page.svelte @@ -1,7 +1,7 @@ @@ -60,7 +52,7 @@
-

{session?.user.name}

+

{session?.user.name || 'Undefined'}

{#if isAdmin} Administrator { - await signOut(); + await authClient.signOut(); posthogHandler((posthog) => posthog.reset()); await goto(resolve('/(auth)/login')); }}>Sign Out - - - Participant Status - - - + + + Account + Passkeys + + + + + Account + + Make changes to your account here. Click save when you're done. + + + + + + + + + + + + - - -
diff --git a/src/routes/(account)/account/_cards/passkeys-card.svelte b/src/routes/(account)/account/_cards/passkeys-card.svelte new file mode 100644 index 0000000..fada254 --- /dev/null +++ b/src/routes/(account)/account/_cards/passkeys-card.svelte @@ -0,0 +1,110 @@ + + + + + + + Passkeys + Add passkeys as an additional login method. + + + + + + Name + Actions + + + {#if !passkeyQuery.data && passkeyQuery.status !== 'success'} + {#if passkeyQuery.status === 'pending'} + Loading passkeys... + + {:else if passkeyQuery.status === 'error'} + Cannot load passkeys + + {/if} + {:else} + + {#each passkeyQuery.data as passkey (passkey.id)} + + {passkey.name} + + + {/each} + {#if passkeyQuery.data && passkeyQuery.data.length === 0} + No passkeys registered + {/if} + + {/if} + + + + + + + diff --git a/src/routes/(account)/account/security.svelte b/src/routes/(account)/account/security.svelte deleted file mode 100644 index a78652c..0000000 --- a/src/routes/(account)/account/security.svelte +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - Account - Passkeys - - - - - Account - - Make changes to your account here. Click save when you're done. - - - - - - - - - - - - Passkeys - Add passkeys as an additional login method. - - - - - - Name - Actions - - - {#if !passkeyQuery.data && passkeyQuery.status !== 'success'} - {#if passkeyQuery.status === 'pending'} - Loading passkeys... - - {:else if passkeyQuery.status === 'error'} - Cannot load passkeys - {/if} - {:else} - - {#each passkeyQuery.data as passkey (passkey.id)} - - {passkey.name} - - - {/each} - {#if passkeyQuery.data && passkeyQuery.data.length === 0} - No passkeys registered - {/if} - - {/if} - - - - - - - - - From 5b4603ff600a7d2a8a949a62b4bb1aefba09feb5 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 15:36:44 -0500 Subject: [PATCH 41/85] custom profile mapping for UVM Entra OIDC --- src/lib/auth/server.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/lib/auth/server.ts b/src/lib/auth/server.ts index 1ae1659..f7d0a6e 100644 --- a/src/lib/auth/server.ts +++ b/src/lib/auth/server.ts @@ -14,6 +14,13 @@ import { import { sendEmailOtp, sendMagicLinkEmail } from '$lib/email'; import { ac, roles } from './permissions'; +type UVMEntraProfile = { + id: string; + email: string; + name: string; + preferred_username: string; +}; + export const auth = betterAuth({ database: drizzleAdapter(db, { provider: 'pg' @@ -49,7 +56,16 @@ export const auth = betterAuth({ providerId: 'uvm-netid', clientId: serverEnv.UVM_NETID_OIDC_CLIENT_ID, clientSecret: serverEnv.UVM_NETID_OIDC_CLIENT_SECRET, - discoveryUrl: serverEnv.UVM_NETID_OIDC_DISCOVERY_URL + discoveryUrl: serverEnv.UVM_NETID_OIDC_DISCOVERY_URL, + overrideUserInfo: true, + mapProfileToUser: (profile) => { + const uvmProfile = profile as UVMEntraProfile; + return { + name: uvmProfile.name, + username: uvmProfile.preferred_username.split('@')[0], + email: uvmProfile.email + }; + } } ] }), From f4b0d69edd3183ee737a3b372f7406c2b44075de Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 15:37:15 -0500 Subject: [PATCH 42/85] update some packages --- bun.lock | 193 ++++++++++++++++++++++++++++++++++----------------- package.json | 11 ++- 2 files changed, 133 insertions(+), 71 deletions(-) diff --git a/bun.lock b/bun.lock index 2881aad..ae446ee 100644 --- a/bun.lock +++ b/bun.lock @@ -15,8 +15,7 @@ "@orpc/client": "^1.13.2", "@orpc/experimental-pino": "^1.13.2", "@orpc/server": "^1.13.2", - "@orpc/svelte-query": "^1.13.2", - "@orpc/tanstack-query": "^1.13.2", + "@orpc/tanstack-query": "^1.13.4", "@oslojs/crypto": "^1.0.1", "@oslojs/encoding": "^1.1.0", "@paralleldrive/cuid2": "^2.3.1", @@ -28,10 +27,10 @@ "@tailwindcss/container-queries": "^0.1.1", "@tailwindcss/forms": "^0.5.11", "@tailwindcss/typography": "^0.5.19", - "@tanstack/query-async-storage-persister": "^5.90.18", - "@tanstack/svelte-query": "^6.0.14", + "@tanstack/query-async-storage-persister": "^5.90.21", + "@tanstack/svelte-query": "^6.0.17", "@tanstack/svelte-query-devtools": "^6.0.3", - "@tanstack/svelte-query-persist-client": "^6.0.16", + "@tanstack/svelte-query-persist-client": "^6.0.19", "@tanstack/table-core": "^8.21.3", "add": "^2.0.6", "arctic": "^3.7.0", @@ -56,7 +55,7 @@ "posthog-js": "^1.312.0", "runed": "^0.37.1", "superjson": "^2.2.6", - "svelte": "^5.46.1", + "svelte": "^5.47.0", "svelte-adapter-bun": "^1.0.1", "svelte-octicons": "^18.20.0", "svelte-sonner": "^1.0.7", @@ -185,11 +184,11 @@ "@babel/types": ["@babel/types@7.28.6", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg=="], - "@better-auth/core": ["@better-auth/core@1.4.12", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "zod": "^4.1.12" }, "peerDependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "better-call": "1.1.7", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" } }, "sha512-VfqZwMAEl9rnGx092BIZ2Q5z8rt7jjN2OAbvPqehufSKZGmh8JsdtZRBMl/CHQir9bwi2Ev0UF4+7TQp+DXEMg=="], + "@better-auth/core": ["@better-auth/core@1.4.15", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "zod": "^4.1.12" }, "peerDependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "better-call": "1.1.8", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" } }, "sha512-uAvq8YA7SaS7v+TrvH/Kwt7LAJihzUqB3FX8VweDsqu3gn5t51M+Bve+V1vVWR9qBAtC6cN68V6b+scxZxDY4A=="], - "@better-auth/passkey": ["@better-auth/passkey@1.4.12", "", { "dependencies": { "@simplewebauthn/browser": "^13.1.2", "@simplewebauthn/server": "^13.1.2", "zod": "^4.1.12" }, "peerDependencies": { "@better-auth/core": "1.4.12", "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "better-auth": "1.4.12", "better-call": "1.1.7", "nanostores": "^1.0.1" } }, "sha512-1ZDkwhHSrxAU1Kn13z98QrzzGFTyMHaGKbPIzP4HAmDDhDIwLFgo2kViYzZHgWGwPM1gXYCQLfFv/NoFEdrEaA=="], + "@better-auth/passkey": ["@better-auth/passkey@1.4.15", "", { "dependencies": { "@simplewebauthn/browser": "^13.1.2", "@simplewebauthn/server": "^13.1.2", "zod": "^4.1.12" }, "peerDependencies": { "@better-auth/core": "1.4.15", "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "better-auth": "1.4.15", "better-call": "1.1.8", "nanostores": "^1.0.1" } }, "sha512-r9x2TFlFvB6nc6wtBBtgiLS3CF1KCKuqGWCTxwO5OQZKe2/OeImTC8crEhpD48mZZLR7WgxxUNF/bpgrWfYciw=="], - "@better-auth/telemetry": ["@better-auth/telemetry@1.4.12", "", { "dependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21" }, "peerDependencies": { "@better-auth/core": "1.4.12" } }, "sha512-4q504Og42PzkUbZjXDt+FyeYaS0WZmAlEOC3nbBCZDObTVCRUnGgJW52B2maJ7BCVvAQgBGLEeQmQzU5+63J0A=="], + "@better-auth/telemetry": ["@better-auth/telemetry@1.4.15", "", { "dependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21" }, "peerDependencies": { "@better-auth/core": "1.4.15" } }, "sha512-7NW/2PS4RN85rv+ozpAezP/kSLPZeWkxqcA6RA/CFXqWp2YR2e5q5E6Hym1qBgVBkoAQa3lWFdX3b+jEs+vvrQ=="], "@better-auth/utils": ["@better-auth/utils@0.3.0", "", {}, "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw=="], @@ -465,33 +464,53 @@ "@octokit/webhooks-methods": ["@octokit/webhooks-methods@5.1.1", "", {}, "sha512-NGlEHZDseJTCj8TMMFehzwa9g7On4KJMPVHDSrHxCQumL6uSQR8wIkP/qesv52fXqV1BPf4pTxwtS31ldAt9Xg=="], - "@orpc/client": ["@orpc/client@1.13.2", "", { "dependencies": { "@orpc/shared": "1.13.2", "@orpc/standard-server": "1.13.2", "@orpc/standard-server-fetch": "1.13.2", "@orpc/standard-server-peer": "1.13.2" } }, "sha512-xlT72B4EFVCEGPev5edEfN5uqu4fnxZyOoCq9UWUAyj0gNDTCF2Z5mfmA4mdBgwV90k+lIcGLMnUI25baedqpw=="], + "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], - "@orpc/contract": ["@orpc/contract@1.13.2", "", { "dependencies": { "@orpc/client": "1.13.2", "@orpc/shared": "1.13.2", "@standard-schema/spec": "^1.1.0", "openapi-types": "^12.1.3" } }, "sha512-td5ExzLPQ2y2zE9itgqod5gmC3WvCFIlkyJSNFRCRhff04PzokE9/hjqGhW5zsNgKuv4rcPYOrkh0e/YiyFndQ=="], + "@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.208.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-CjruKY9V6NMssL/T1kAFgzosF1v9o6oeN+aX5JB/C/xPNtmgIJqcXHG7fA82Ou1zCpWGl4lROQUKwUNE1pMCyg=="], - "@orpc/experimental-pino": ["@orpc/experimental-pino@1.13.2", "", { "dependencies": { "@orpc/client": "1.13.2", "@orpc/server": "1.13.2", "@orpc/shared": "1.13.2" }, "peerDependencies": { "pino": ">=10.1.0" } }, "sha512-BVwiUk6VD5Odi1DIvP2TMx/ay6K0uf+GH2mx6DAMbQ2j146Gr65He5wV+pqRf8Lns5/hke/jkngSICP/WTX8AA=="], + "@opentelemetry/core": ["@opentelemetry/core@2.2.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw=="], - "@orpc/interop": ["@orpc/interop@1.13.2", "", {}, "sha512-N6AHeREWsXBm0KPShIwwwuPEwGR+slWgyLchXfQYE0HLEQmf2wSZYhoawgaaETl5EoPc6Z7/LUaTqPCE380CzQ=="], + "@opentelemetry/exporter-logs-otlp-http": ["@opentelemetry/exporter-logs-otlp-http@0.208.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.208.0", "@opentelemetry/core": "2.2.0", "@opentelemetry/otlp-exporter-base": "0.208.0", "@opentelemetry/otlp-transformer": "0.208.0", "@opentelemetry/sdk-logs": "0.208.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-jOv40Bs9jy9bZVLo/i8FwUiuCvbjWDI+ZW13wimJm4LjnlwJxGgB+N/VWOZUTpM+ah/awXeQqKdNlpLf2EjvYg=="], - "@orpc/server": ["@orpc/server@1.13.2", "", { "dependencies": { "@orpc/client": "1.13.2", "@orpc/contract": "1.13.2", "@orpc/interop": "1.13.2", "@orpc/shared": "1.13.2", "@orpc/standard-server": "1.13.2", "@orpc/standard-server-aws-lambda": "1.13.2", "@orpc/standard-server-fastify": "1.13.2", "@orpc/standard-server-fetch": "1.13.2", "@orpc/standard-server-node": "1.13.2", "@orpc/standard-server-peer": "1.13.2", "cookie": "^1.1.1" }, "peerDependencies": { "crossws": ">=0.3.4", "ws": ">=8.18.1" }, "optionalPeers": ["crossws", "ws"] }, "sha512-sHGMT5eQ9eFSfXeRr6F3wkVRm76fUJzDurtCIZe5koStS20e5YZOkg7FH5kZb57c0d/EqvqPAbdHD8WRVl4qLQ=="], + "@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.208.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/otlp-transformer": "0.208.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-gMd39gIfVb2OgxldxUtOwGJYSH8P1kVFFlJLuut32L6KgUC4gl1dMhn+YC2mGn0bDOiQYSk/uHOdSjuKp58vvA=="], - "@orpc/shared": ["@orpc/shared@1.13.2", "", { "dependencies": { "radash": "^12.1.1", "type-fest": "^5.3.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0" }, "optionalPeers": ["@opentelemetry/api"] }, "sha512-1icIwoMxtXSTwGFJE2u/Hu4XhZQS81bk0hvRcG7jHATATTMLcNAFR+sv3AG56WTH6yF3C1A96VpYzvCYRUseFA=="], + "@opentelemetry/otlp-transformer": ["@opentelemetry/otlp-transformer@0.208.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.208.0", "@opentelemetry/core": "2.2.0", "@opentelemetry/resources": "2.2.0", "@opentelemetry/sdk-logs": "0.208.0", "@opentelemetry/sdk-metrics": "2.2.0", "@opentelemetry/sdk-trace-base": "2.2.0", "protobufjs": "^7.3.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-DCFPY8C6lAQHUNkzcNT9R+qYExvsk6C5Bto2pbNxgicpcSWbe2WHShLxkOxIdNcBiYPdVHv/e7vH7K6TI+C+fQ=="], - "@orpc/standard-server": ["@orpc/standard-server@1.13.2", "", { "dependencies": { "@orpc/shared": "1.13.2" } }, "sha512-qjxKOvCg2mYBQMPdjEqQEDI+F/v6qm9zKMeFsfxnWKvPhDrPSEk8x40vdXlLbbpW6TCXpQikpycfdvq5H4Nb+Q=="], + "@opentelemetry/resources": ["@opentelemetry/resources@2.4.0", "", { "dependencies": { "@opentelemetry/core": "2.4.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-RWvGLj2lMDZd7M/5tjkI/2VHMpXebLgPKvBUd9LRasEWR2xAynDwEYZuLvY9P2NGG73HF07jbbgWX2C9oavcQg=="], - "@orpc/standard-server-aws-lambda": ["@orpc/standard-server-aws-lambda@1.13.2", "", { "dependencies": { "@orpc/shared": "1.13.2", "@orpc/standard-server": "1.13.2", "@orpc/standard-server-fetch": "1.13.2", "@orpc/standard-server-node": "1.13.2" } }, "sha512-Gkw72+b5eZKjsSJ5zT4vsnEbHww8An1hkkai4jmLvADtujQQMccjhWNTC7MKGBe1/M818plnfbhqmLx+2rU0IA=="], + "@opentelemetry/sdk-logs": ["@opentelemetry/sdk-logs@0.208.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.208.0", "@opentelemetry/core": "2.2.0", "@opentelemetry/resources": "2.2.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.4.0 <1.10.0" } }, "sha512-QlAyL1jRpOeaqx7/leG1vJMp84g0xKP6gJmfELBpnI4O/9xPX+Hu5m1POk9Kl+veNkyth5t19hRlN6tNY1sjbA=="], - "@orpc/standard-server-fastify": ["@orpc/standard-server-fastify@1.13.2", "", { "dependencies": { "@orpc/shared": "1.13.2", "@orpc/standard-server": "1.13.2", "@orpc/standard-server-node": "1.13.2" }, "peerDependencies": { "fastify": ">=5.6.1" }, "optionalPeers": ["fastify"] }, "sha512-N8GHu9GHDm7wQePdTfWxWaJQPGXyjsirHTjJZEBbUDR0R64C8b2JCt+eK1iq9DK3Oc5kYNJUWZQhwlZUCWCClg=="], + "@opentelemetry/sdk-metrics": ["@opentelemetry/sdk-metrics@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/resources": "2.2.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <1.10.0" } }, "sha512-G5KYP6+VJMZzpGipQw7Giif48h6SGQ2PFKEYCybeXJsOCB4fp8azqMAAzE5lnnHK3ZVwYQrgmFbsUJO/zOnwGw=="], - "@orpc/standard-server-fetch": ["@orpc/standard-server-fetch@1.13.2", "", { "dependencies": { "@orpc/shared": "1.13.2", "@orpc/standard-server": "1.13.2" } }, "sha512-JanRDFk78kB8/P5NljV1nx3zcpBsTC9sCAhBcE3ezY1u3Kvt7teRhPxRXcoD0TEBdQjEUeXcqX+zEh4Op2E8nw=="], + "@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/resources": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw=="], - "@orpc/standard-server-node": ["@orpc/standard-server-node@1.13.2", "", { "dependencies": { "@orpc/shared": "1.13.2", "@orpc/standard-server": "1.13.2", "@orpc/standard-server-fetch": "1.13.2" } }, "sha512-asWTGGQEcBKkpz6qEsn0Gfdsj0eZ4zDp/P89jJFuYEREwqsWMrZSiyEQNcCU0Q6UoLai+Wvil575L58i3Adgmg=="], + "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.39.0", "", {}, "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg=="], - "@orpc/standard-server-peer": ["@orpc/standard-server-peer@1.13.2", "", { "dependencies": { "@orpc/shared": "1.13.2", "@orpc/standard-server": "1.13.2" } }, "sha512-LMxaMSmp98jnm0jiHpqPgH5qHXeOvah7pmysrcLaqMfwH+GwRS6S+/ls2hAy9aIba4LrTZyIpTgSohHD/Ed73g=="], + "@orpc/client": ["@orpc/client@1.13.4", "", { "dependencies": { "@orpc/shared": "1.13.4", "@orpc/standard-server": "1.13.4", "@orpc/standard-server-fetch": "1.13.4", "@orpc/standard-server-peer": "1.13.4" } }, "sha512-s13GPMeoooJc5Th2EaYT5HMFtWG8S03DUVytYfJv8pIhP87RYKl94w52A36denH6r/B4LaAgBeC9nTAOslK+Og=="], - "@orpc/svelte-query": ["@orpc/svelte-query@1.13.2", "", { "dependencies": { "@orpc/shared": "1.13.2", "@orpc/tanstack-query": "1.13.2" }, "peerDependencies": { "@orpc/client": "1.13.2", "@tanstack/svelte-query": ">=5.80.2", "svelte": ">=4.2.0" } }, "sha512-NUhgFZAsL06pwSbkFaPhlhdI44qXanvivIZftzHHTmCoRMsKFGtNHJv+dkUAtCBJ9j/SE6PXWWxSNjavaCYrrg=="], + "@orpc/contract": ["@orpc/contract@1.13.4", "", { "dependencies": { "@orpc/client": "1.13.4", "@orpc/shared": "1.13.4", "@standard-schema/spec": "^1.1.0", "openapi-types": "^12.1.3" } }, "sha512-TIxyaF67uOlihCRcasjHZxguZpbqfNK7aMrDLnhoufmQBE4OKvguNzmrOFHgsuM0OXoopX0Nuhun1ccaxKP10A=="], - "@orpc/tanstack-query": ["@orpc/tanstack-query@1.13.2", "", { "dependencies": { "@orpc/shared": "1.13.2" }, "peerDependencies": { "@orpc/client": "1.13.2", "@tanstack/query-core": ">=5.80.2" } }, "sha512-a/BzZP4YZiqPCBoWzr1miHPHDpqGhH8BKPf1RyB9i61s554Utic3MQqKO0PHa61TT0OxEXuZTowVgdwk1zsQFA=="], + "@orpc/experimental-pino": ["@orpc/experimental-pino@1.13.4", "", { "dependencies": { "@orpc/client": "1.13.4", "@orpc/server": "1.13.4", "@orpc/shared": "1.13.4" }, "peerDependencies": { "pino": ">=10.1.0" } }, "sha512-p1TfmgTkij6Jdb3T8oGwbmFDe3weM86oIg8MoOdhzZL0nJ/YA4LOMKOgIkygwh8joSacygbVo65dkDTOzLaY4w=="], + + "@orpc/interop": ["@orpc/interop@1.13.4", "", {}, "sha512-h8HWMSTSUYTtfN9ytGJD/MLMgWaUJOg8Z1Bq7fycnj74DVib0NLGIItoCquJkSzgZ7Otc+s1l0/2NPOViTyl9Q=="], + + "@orpc/server": ["@orpc/server@1.13.4", "", { "dependencies": { "@orpc/client": "1.13.4", "@orpc/contract": "1.13.4", "@orpc/interop": "1.13.4", "@orpc/shared": "1.13.4", "@orpc/standard-server": "1.13.4", "@orpc/standard-server-aws-lambda": "1.13.4", "@orpc/standard-server-fastify": "1.13.4", "@orpc/standard-server-fetch": "1.13.4", "@orpc/standard-server-node": "1.13.4", "@orpc/standard-server-peer": "1.13.4", "cookie": "^1.1.1" }, "peerDependencies": { "crossws": ">=0.3.4", "ws": ">=8.18.1" }, "optionalPeers": ["crossws", "ws"] }, "sha512-noGqSP53KpH+2UvCpIoOCMPn5LY5UIB674ijzSZ2LYHT0EUNGpOgYd5Rab09VUAaG2NejwJc9VvWztFW3Op08w=="], + + "@orpc/shared": ["@orpc/shared@1.13.4", "", { "dependencies": { "radash": "^12.1.1", "type-fest": "^5.3.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0" }, "optionalPeers": ["@opentelemetry/api"] }, "sha512-TYt9rLG/BUkNQBeQ6C1tEiHS/Seb8OojHgj9GlvqyjHJhMZx5qjsIyTW6RqLPZJ4U2vgK6x4Her36+tlFCKJug=="], + + "@orpc/standard-server": ["@orpc/standard-server@1.13.4", "", { "dependencies": { "@orpc/shared": "1.13.4" } }, "sha512-ZOzgfVp6XUg+wVYw+gqesfRfGPtQbnBIrIiSnFMtZF+6ncmFJeF2Shc4RI2Guqc0Qz25juy8Ogo4tX3YqysOcg=="], + + "@orpc/standard-server-aws-lambda": ["@orpc/standard-server-aws-lambda@1.13.4", "", { "dependencies": { "@orpc/shared": "1.13.4", "@orpc/standard-server": "1.13.4", "@orpc/standard-server-fetch": "1.13.4", "@orpc/standard-server-node": "1.13.4" } }, "sha512-iTJK6DiwLufVZtflLAxx5GCNQLo3NhNuQQgVtFavpx5xgCTuRb1dKNjHAoVCkF2lyqUFxv4AON2ZOSvuCCCzpw=="], + + "@orpc/standard-server-fastify": ["@orpc/standard-server-fastify@1.13.4", "", { "dependencies": { "@orpc/shared": "1.13.4", "@orpc/standard-server": "1.13.4", "@orpc/standard-server-node": "1.13.4" }, "peerDependencies": { "fastify": ">=5.6.1" }, "optionalPeers": ["fastify"] }, "sha512-+E40iAD2IY/Vgg7FAE9aM2kQOL73LwJikkMiiD8G08kAEp1By9N7W5ejxXYiRcTVRF0j9vgvNSwhf4aSJmxp8g=="], + + "@orpc/standard-server-fetch": ["@orpc/standard-server-fetch@1.13.4", "", { "dependencies": { "@orpc/shared": "1.13.4", "@orpc/standard-server": "1.13.4" } }, "sha512-/zmKwnuxfAXbppJpgr1CMnQX3ptPlYcDzLz1TaVzz9VG/Xg58Ov3YhabS2Oi1utLVhy5t4kaCppUducAvoKN+A=="], + + "@orpc/standard-server-node": ["@orpc/standard-server-node@1.13.4", "", { "dependencies": { "@orpc/shared": "1.13.4", "@orpc/standard-server": "1.13.4", "@orpc/standard-server-fetch": "1.13.4" } }, "sha512-4sVTsoI1xBmKEqmcxPRGKqf/Egbtr83Lg8yLiUrt5YdjOAYENiahWyU51itL21VPdAdMFDoDdUC9aCpikyQCaw=="], + + "@orpc/standard-server-peer": ["@orpc/standard-server-peer@1.13.4", "", { "dependencies": { "@orpc/shared": "1.13.4", "@orpc/standard-server": "1.13.4" } }, "sha512-UfqnTLqevjCKUk4cmImOG8cQUwANpV1dp9e9u2O1ki6BRBsg/zlXFg6G2N6wP0zr9ayIiO1d2qJdH55yl/1BNw=="], + + "@orpc/tanstack-query": ["@orpc/tanstack-query@1.13.4", "", { "dependencies": { "@orpc/shared": "1.13.4" }, "peerDependencies": { "@orpc/client": "1.13.4", "@tanstack/query-core": ">=5.80.2" } }, "sha512-gCL/kh3kf6OUGKfXxSoOZpcX1jNYzxGfo/PkLQKX7ui4xiTbfWw3sCDF30sNS4I7yAOnBwDwJ3N2xzfkTftOBg=="], "@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="], @@ -503,27 +522,27 @@ "@oslojs/jwt": ["@oslojs/jwt@0.2.0", "", { "dependencies": { "@oslojs/encoding": "0.4.1" } }, "sha512-bLE7BtHrURedCn4Mco3ma9L4Y1GR2SMBuIvjWr7rmQ4/W/4Jy70TIAgZ+0nIlk0xHz1vNP8x8DCns45Sb2XRbg=="], - "@oven/bun-darwin-aarch64": ["@oven/bun-darwin-aarch64@1.3.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-8GvNtMo0NINM7Emk9cNAviCG3teEgr3BUX9be0+GD029zIagx2Sf54jMui1Eu1IpFm7nWHODuLEefGOQNaJ0gQ=="], + "@oven/bun-darwin-aarch64": ["@oven/bun-darwin-aarch64@1.3.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-27rypIapNkYboOSylkf1tD9UW9Ado2I+P1NBL46Qz29KmOjTL6WuJ7mHDC5O66CYxlOkF5r93NPDAC3lFHYBXw=="], - "@oven/bun-darwin-x64": ["@oven/bun-darwin-x64@1.3.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-r33eHQOHAwkuiBJIwmkXIyqONQOQMnd1GMTpDzaxx9vf9+svby80LZO9Hcm1ns6KT/TBRFyODC/0loA7FAaffg=="], + "@oven/bun-darwin-x64": ["@oven/bun-darwin-x64@1.3.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-I82xGzPkBxzBKgbl8DsA0RfMQCWTWjNmLjIEkW1ECiv3qK02kHGQ5FGUr/29L/SuvnGsULW4tBTRNZiMzL37nA=="], - "@oven/bun-darwin-x64-baseline": ["@oven/bun-darwin-x64-baseline@1.3.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-p5q3rJk48qhLuLBOFehVc+kqCE03YrswTc6NCxbwsxiwfySXwcAvpF2KWKF/ZZObvvR8hCCvqe1F81b2p5r2dg=="], + "@oven/bun-darwin-x64-baseline": ["@oven/bun-darwin-x64-baseline@1.3.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-nqtr+pTsHqusYpG2OZc6s+AmpWDB/FmBvstrK0y5zkti4OqnCuu7Ev2xNjS7uyb47NrAFF40pWqkpaio5XEd7w=="], - "@oven/bun-linux-aarch64": ["@oven/bun-linux-aarch64@1.3.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-zkcHPI23QxJ1TdqafhgkXt1NOEN8o5C460sVeNnrhfJ43LwZgtfcvcQE39x/pBedu67fatY8CU0iY00nOh46ZQ=="], + "@oven/bun-linux-aarch64": ["@oven/bun-linux-aarch64@1.3.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-YaQEAYjBanoOOtpqk/c5GGcfZIyxIIkQ2m1TbHjedRmJNwxzWBhGinSARFkrRIc3F8pRIGAopXKvJ/2rjN1LzQ=="], - "@oven/bun-linux-aarch64-musl": ["@oven/bun-linux-aarch64-musl@1.3.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-HKBeUlJdNduRkzJKZ5DXM+pPqntfC50/Hu2X65jVX0Y7hu/6IC8RaUTqpr8FtCZqqmc9wDK0OTL+Mbi9UQIKYQ=="], + "@oven/bun-linux-aarch64-musl": ["@oven/bun-linux-aarch64-musl@1.3.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-FR+iJt17rfFgYgpxL3M67AUwujOgjw52ZJzB9vElI5jQXNjTyOKf8eH4meSk4vjlYF3h/AjKYd6pmN0OIUlVKQ=="], - "@oven/bun-linux-x64": ["@oven/bun-linux-x64@1.3.5", "", { "os": "linux", "cpu": "x64" }, "sha512-n7zhKTSDZS0yOYg5Rq8easZu5Y/o47sv0c7yGr2ciFdcie9uYV55fZ7QMqhWMGK33ezCSikh5EDkUMCIvfWpjA=="], + "@oven/bun-linux-x64": ["@oven/bun-linux-x64@1.3.6", "", { "os": "linux", "cpu": "x64" }, "sha512-egfngj0dfJ868cf30E7B+ye9KUWSebYxOG4l9YP5eWeMXCtenpenx0zdKtAn9qxJgEJym5AN6trtlk+J6x8Lig=="], - "@oven/bun-linux-x64-baseline": ["@oven/bun-linux-x64-baseline@1.3.5", "", { "os": "linux", "cpu": "x64" }, "sha512-FeCQyBU62DMuB0nn01vPnf3McXrKOsrK9p7sHaBFYycw0mmoU8kCq/WkBkGMnLuvQljJSyen8QBTx+fXdNupWg=="], + "@oven/bun-linux-x64-baseline": ["@oven/bun-linux-x64-baseline@1.3.6", "", { "os": "linux", "cpu": "x64" }, "sha512-jRmnX18ak8WzqLrex3siw0PoVKyIeI5AiCv4wJLgSs7VKfOqrPycfHIWfIX2jdn7ngqbHFPzI09VBKANZ4Pckg=="], - "@oven/bun-linux-x64-musl": ["@oven/bun-linux-x64-musl@1.3.5", "", { "os": "linux", "cpu": "x64" }, "sha512-XkCCHkByYn8BIDvoxnny898znju4xnW2kvFE8FT5+0Y62cWdcBGMZ9RdsEUTeRz16k8hHtJpaSfLcEmNTFIwRQ=="], + "@oven/bun-linux-x64-musl": ["@oven/bun-linux-x64-musl@1.3.6", "", { "os": "linux", "cpu": "x64" }, "sha512-YeXcJ9K6vJAt1zSkeA21J6pTe7PgDMLTHKGI3nQBiMYnYf7Ob3K+b/ChSCznrJG7No5PCPiQPg4zTgA+BOTmSA=="], - "@oven/bun-linux-x64-musl-baseline": ["@oven/bun-linux-x64-musl-baseline@1.3.5", "", { "os": "linux", "cpu": "x64" }, "sha512-TJiYC7KCr0XxFTsxgwQOeE7dncrEL/RSyL0EzSL3xRkrxJMWBCvCSjQn7LV1i6T7hFst0+3KoN3VWvD5BinqHA=="], + "@oven/bun-linux-x64-musl-baseline": ["@oven/bun-linux-x64-musl-baseline@1.3.6", "", { "os": "linux", "cpu": "x64" }, "sha512-7FjVnxnRTp/AgWqSQRT/Vt9TYmvnZ+4M+d9QOKh/Lf++wIFXFGSeAgD6bV1X/yr2UPVmZDk+xdhr2XkU7l2v3w=="], - "@oven/bun-windows-x64": ["@oven/bun-windows-x64@1.3.5", "", { "os": "win32", "cpu": "x64" }, "sha512-T3xkODItb/0ftQPFsZDc7EAX2D6A4TEazQ2YZyofZToO8Q7y8YT8ooWdhd0BQiTCd66uEvgE1DCZetynwg2IoA=="], + "@oven/bun-windows-x64": ["@oven/bun-windows-x64@1.3.6", "", { "os": "win32", "cpu": "x64" }, "sha512-Sr1KwUcbB0SEpnSPO22tNJppku2khjFluEst+mTGhxHzAGQTQncNeJxDnt3F15n+p9Q+mlcorxehd68n1siikQ=="], - "@oven/bun-windows-x64-baseline": ["@oven/bun-windows-x64-baseline@1.3.5", "", { "os": "win32", "cpu": "x64" }, "sha512-rtVQB9/1XK8FWJgFtsOthbPifRMYypgJwxu+pK3NHx8WvFKmq7HcPDqNr8xLzGULjQEO7eAo2aOZfONOwYz+5g=="], + "@oven/bun-windows-x64-baseline": ["@oven/bun-windows-x64-baseline@1.3.6", "", { "os": "win32", "cpu": "x64" }, "sha512-PFUa7JL4lGoyyppeS4zqfuoXXih+gSE0XxhDMrCPVEUev0yhGNd/tbWBvcdpYnUth80owENoGjc8s5Knopv9wA=="], "@oxc-project/runtime": ["@oxc-project/runtime@0.71.0", "", {}, "sha512-QwoF5WUXIGFQ+hSxWEib4U/aeLoiDN9JlP18MnBgx9LLPRDfn1iICtcow7Jgey6HLH4XFceWXQD5WBJ39dyJcw=="], @@ -563,9 +582,29 @@ "@poppinss/macroable": ["@poppinss/macroable@1.1.0", "", {}, "sha512-y/YKzZDuG8XrpXpM7Z1RdQpiIc0MAKyva24Ux1PB4aI7RiSI/79K8JVDcdyubriTm7vJ1LhFs8CrZpmPnx/8Pw=="], - "@posthog/core": ["@posthog/core@1.9.1", "", { "dependencies": { "cross-spawn": "^7.0.6" } }, "sha512-kRb1ch2dhQjsAapZmu6V66551IF2LnCbc1rnrQqnR7ArooVyJN9KOPXre16AJ3ObJz2eTfuP7x25BMyS2Y5Exw=="], + "@posthog/core": ["@posthog/core@1.10.0", "", { "dependencies": { "cross-spawn": "^7.0.6" } }, "sha512-Xk3JQ+cdychsvftrV3G9ZrN9W329lbyFW0pGJXFGKFQf8qr4upw2SgNg9BVorjSrfhoXZRnJGt/uNF4nGFBL5A=="], + + "@posthog/types": ["@posthog/types@1.330.0", "", {}, "sha512-J4t35UA+1GxFf2qAYG9wqiJGpjU4hCvMfEUOd6s2SkaFgzAmbZ98GOEPtDfs/uXIxFE1Mj3pB+D6CWnLf4i9ug=="], + + "@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="], + + "@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="], + + "@protobufjs/codegen": ["@protobufjs/codegen@2.0.4", "", {}, "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="], + + "@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.0", "", {}, "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="], + + "@protobufjs/fetch": ["@protobufjs/fetch@1.1.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" } }, "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ=="], - "@posthog/types": ["@posthog/types@1.318.1", "", {}, "sha512-FYjHp4wlYvt4xc7MM+zIjfYICY/+lvjby/nOib29psTuUMT3nJXwqWz65QBox6XldaJdeId5F+UW6IOtJ1Q9iA=="], + "@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="], + + "@protobufjs/inquire": ["@protobufjs/inquire@1.1.0", "", {}, "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="], + + "@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="], + + "@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="], + + "@protobufjs/utf8": ["@protobufjs/utf8@1.1.0", "", {}, "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="], "@react-email/body": ["@react-email/body@0.2.1", "", { "peerDependencies": { "react": "^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-ljDiQiJDu/Fq//vSIIP0z5Nuvt4+DX1RqGasstChDGJB/14ogd4VdNS9aacoede/ZjGy3o3Qb+cxyS+XgM6SwQ=="], @@ -797,9 +836,9 @@ "@sveltejs/adapter-auto": ["@sveltejs/adapter-auto@7.0.0", "", { "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-ImDWaErTOCkRS4Gt+5gZuymKFBobnhChXUZ9lhUZLahUgvA4OOvRzi3sahzYgbxGj5nkA6OV0GAW378+dl/gyw=="], - "@sveltejs/adapter-node": ["@sveltejs/adapter-node@5.4.0", "", { "dependencies": { "@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.0", "rollup": "^4.9.5" }, "peerDependencies": { "@sveltejs/kit": "^2.4.0" } }, "sha512-NMsrwGVPEn+J73zH83Uhss/hYYZN6zT3u31R3IHAn3MiKC3h8fjmIAhLfTSOeNHr5wPYfjjMg8E+1gyFgyrEcQ=="], + "@sveltejs/adapter-node": ["@sveltejs/adapter-node@5.5.1", "", { "dependencies": { "@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.0", "rollup": "^4.9.5" }, "peerDependencies": { "@sveltejs/kit": "^2.4.0" } }, "sha512-VpZdPNRPQuZRtgfAMETPWWKpZx9JwXmUUsgz/+eSpw/Oh7+2O1uZHlsQTuyfxydJHPrRzjfu/ItcJjY4oscCiQ=="], - "@sveltejs/kit": ["@sveltejs/kit@2.49.4", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.3.2", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": "^5.3.3", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["@opentelemetry/api", "typescript"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-JFtOqDoU0DI/+QSG8qnq5bKcehVb3tCHhOG4amsSYth5/KgO4EkJvi42xSAiyKmXAAULW1/Zdb6lkgGEgSxdZg=="], + "@sveltejs/kit": ["@sveltejs/kit@2.50.0", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.6.2", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": "^5.3.3", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["@opentelemetry/api", "typescript"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-Hj8sR8O27p2zshFEIJzsvfhLzxga/hWw6tRLnBjMYw70m1aS9BSYCqAUtzDBjRREtX1EvLMYgaC0mYE3Hz4KWA=="], "@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@6.2.4", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "deepmerge": "^4.3.1", "magic-string": "^0.30.21", "obug": "^2.1.0", "vitefu": "^1.1.1" }, "peerDependencies": { "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-ou/d51QSdTyN26D7h6dSpusAKaZkAiGM55/AKYi+9AGZw7q85hElbjK3kEyzXHhLSnRISHOYzVge6x0jRZ7DXA=="], @@ -845,19 +884,19 @@ "@tailwindcss/vite": ["@tailwindcss/vite@4.1.18", "", { "dependencies": { "@tailwindcss/node": "4.1.18", "@tailwindcss/oxide": "4.1.18", "tailwindcss": "4.1.18" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA=="], - "@tanstack/query-async-storage-persister": ["@tanstack/query-async-storage-persister@5.90.18", "", { "dependencies": { "@tanstack/query-core": "5.90.16", "@tanstack/query-persist-client-core": "5.91.15" } }, "sha512-vCZHpodK3N7MQuRGi79YB/+steiAJnCWD78VbVl79+ysoFHsbD85UX+x40uTicXxml5E2kmxn7Yb4Kbwh6TpLQ=="], + "@tanstack/query-async-storage-persister": ["@tanstack/query-async-storage-persister@5.90.21", "", { "dependencies": { "@tanstack/query-core": "5.90.19", "@tanstack/query-persist-client-core": "5.91.18" } }, "sha512-edpZzybucsMxGiWOMy24io+5l4Lciw4bgv/N2EXQnSp0exS1siTOQbCAQET8jwStCEnaoEiS8ljChnfmnd2pkw=="], - "@tanstack/query-core": ["@tanstack/query-core@5.90.16", "", {}, "sha512-MvtWckSVufs/ja463/K4PyJeqT+HMlJWtw6PrCpywznd2NSgO3m4KwO9RqbFqGg6iDE8vVMFWMeQI4Io3eEYww=="], + "@tanstack/query-core": ["@tanstack/query-core@5.90.19", "", {}, "sha512-GLW5sjPVIvH491VV1ufddnfldyVB+teCnpPIvweEfkpRx7CfUmUGhoh9cdcUKBh/KwVxk22aNEDxeTsvmyB/WA=="], "@tanstack/query-devtools": ["@tanstack/query-devtools@5.92.0", "", {}, "sha512-N8D27KH1vEpVacvZgJL27xC6yPFUy0Zkezn5gnB3L3gRCxlDeSuiya7fKge8Y91uMTnC8aSxBQhcK6ocY7alpQ=="], - "@tanstack/query-persist-client-core": ["@tanstack/query-persist-client-core@5.91.15", "", { "dependencies": { "@tanstack/query-core": "5.90.16" } }, "sha512-vnPSfQVo41EKJN8v20nkhWNZPyB1dMJIy5icOvCGzcCJzsmRefYY1owtr63ICOcjOiPPTuNEfPsdjdBhkzYnmA=="], + "@tanstack/query-persist-client-core": ["@tanstack/query-persist-client-core@5.91.18", "", { "dependencies": { "@tanstack/query-core": "5.90.19" } }, "sha512-1FNvccVTFZph07dtA/4p5PRAVKfqVLPPxA8BXUoYjPOZP6T4qY1asItVkUFtUr6kBu48i0DBnEEZQLmK82BIFw=="], - "@tanstack/svelte-query": ["@tanstack/svelte-query@6.0.14", "", { "dependencies": { "@tanstack/query-core": "5.90.16" }, "peerDependencies": { "svelte": "^5.25.0" } }, "sha512-gKuHxbyGP2pCQgE/Px9FtlyFmHTt0OV5xTrKrk7PMKGkv3LPWTTwDb7xlMDe1V7U2K5ci+jq1j3HsuTPqIZxjA=="], + "@tanstack/svelte-query": ["@tanstack/svelte-query@6.0.17", "", { "dependencies": { "@tanstack/query-core": "5.90.19" }, "peerDependencies": { "svelte": "^5.25.0" } }, "sha512-SFFsW99Z5DCI9rIowJrPBGEJgl5i+Lzimzoup+P1LhHUIrSyJ4R7KcroFlIxTHz0XaYTAqpNjhXuUUvOqjdTHQ=="], "@tanstack/svelte-query-devtools": ["@tanstack/svelte-query-devtools@6.0.3", "", { "dependencies": { "@tanstack/query-devtools": "5.92.0", "esm-env": "^1.2.1" }, "peerDependencies": { "@tanstack/svelte-query": "^6.0.12", "svelte": "^5.25.0" } }, "sha512-AHc/vPiUWeMFXKvtrlZot7wIlsIm4z5vd0wDeQUKwE5XTfZODu0no1A4UCLzVnY2WpbBpakIEUMH+PmSMwYXKg=="], - "@tanstack/svelte-query-persist-client": ["@tanstack/svelte-query-persist-client@6.0.16", "", { "dependencies": { "@tanstack/query-persist-client-core": "5.91.15" }, "peerDependencies": { "@tanstack/svelte-query": "^6.0.14", "svelte": "^5.25.0" } }, "sha512-z3vVjJbeYci8I/ahtC+d2rS2rdG9wHZr3pr5dHvVtAGtgeDMsoSEYBPeY2t5ykdQAvs0OAEw0zqvVeGjUDrckA=="], + "@tanstack/svelte-query-persist-client": ["@tanstack/svelte-query-persist-client@6.0.19", "", { "dependencies": { "@tanstack/query-persist-client-core": "5.91.18" }, "peerDependencies": { "@tanstack/svelte-query": "^6.0.17", "svelte": "^5.25.0" } }, "sha512-XPhc+JZ+6QWkE97Q9rSbDOy2Fu3cX7KwNe/2tK9TsM5IAtyChBwblUKIc9ZRuUKkn30SA27gzslX3MkTaD/eVQ=="], "@tanstack/table-core": ["@tanstack/table-core@8.21.3", "", {}, "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg=="], @@ -873,7 +912,7 @@ "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], - "@types/node": ["@types/node@22.19.5", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-HfF8+mYcHPcPypui3w3mvzuIErlNOh2OAG+BCeBZCEwyiD5ls2SiCwEyT47OELtf7M3nHxBdu0FsmzdKxkN52Q=="], + "@types/node": ["@types/node@22.19.7", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw=="], "@types/nodemailer": ["@types/nodemailer@7.0.5", "", { "dependencies": { "@aws-sdk/client-sesv2": "^3.839.0", "@types/node": "*" } }, "sha512-7WtR4MFJUNN2UFy0NIowBRJswj5KXjXDhlZY43Hmots5eGu5q/dTeFd/I6GgJA/qj3RqO6dDy4SvfcV3fOVeIA=="], @@ -891,25 +930,25 @@ "@typeschema/core": ["@typeschema/core@0.14.0", "", { "peerDependencies": { "@types/json-schema": "^7.0.15" }, "optionalPeers": ["@types/json-schema"] }, "sha512-Ia6PtZHcL3KqsAWXjMi5xIyZ7XMH4aSnOQes8mfMLx+wGFGtGRNlwe6Y7cYvX+WfNK67OL0/HSe9t8QDygV0/w=="], - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.52.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.52.0", "@typescript-eslint/type-utils": "8.52.0", "@typescript-eslint/utils": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.52.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-okqtOgqu2qmZJ5iN4TWlgfF171dZmx2FzdOv2K/ixL2LZWDStL8+JgQerI2sa8eAEfoydG9+0V96m7V+P8yE1Q=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.53.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.53.1", "@typescript-eslint/type-utils": "8.53.1", "@typescript-eslint/utils": "8.53.1", "@typescript-eslint/visitor-keys": "8.53.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.53.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag=="], - "@typescript-eslint/parser": ["@typescript-eslint/parser@8.52.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.52.0", "@typescript-eslint/types": "8.52.0", "@typescript-eslint/typescript-estree": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg=="], + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.53.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.53.1", "@typescript-eslint/types": "8.53.1", "@typescript-eslint/typescript-estree": "8.53.1", "@typescript-eslint/visitor-keys": "8.53.1", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg=="], - "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.52.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.52.0", "@typescript-eslint/types": "^8.52.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw=="], + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.53.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.53.1", "@typescript-eslint/types": "^8.53.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog=="], - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0" } }, "sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA=="], + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.53.1", "", { "dependencies": { "@typescript-eslint/types": "8.53.1", "@typescript-eslint/visitor-keys": "8.53.1" } }, "sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ=="], - "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.52.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg=="], + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.53.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA=="], - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "@typescript-eslint/typescript-estree": "8.52.0", "@typescript-eslint/utils": "8.52.0", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-JD3wKBRWglYRQkAtsyGz1AewDu3mTc7NtRjR/ceTyGoPqmdS5oCdx/oZMWD5Zuqmo6/MpsYs0wp6axNt88/2EQ=="], + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.53.1", "", { "dependencies": { "@typescript-eslint/types": "8.53.1", "@typescript-eslint/typescript-estree": "8.53.1", "@typescript-eslint/utils": "8.53.1", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w=="], - "@typescript-eslint/types": ["@typescript-eslint/types@8.52.0", "", {}, "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg=="], + "@typescript-eslint/types": ["@typescript-eslint/types@8.53.1", "", {}, "sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A=="], - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.52.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.52.0", "@typescript-eslint/tsconfig-utils": "8.52.0", "@typescript-eslint/types": "8.52.0", "@typescript-eslint/visitor-keys": "8.52.0", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ=="], + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.53.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.53.1", "@typescript-eslint/tsconfig-utils": "8.53.1", "@typescript-eslint/types": "8.53.1", "@typescript-eslint/visitor-keys": "8.53.1", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg=="], - "@typescript-eslint/utils": ["@typescript-eslint/utils@8.52.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.52.0", "@typescript-eslint/types": "8.52.0", "@typescript-eslint/typescript-estree": "8.52.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ=="], + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.53.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.53.1", "@typescript-eslint/types": "8.53.1", "@typescript-eslint/typescript-estree": "8.53.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg=="], - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.52.0", "", { "dependencies": { "@typescript-eslint/types": "8.52.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ=="], + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.53.1", "", { "dependencies": { "@typescript-eslint/types": "8.53.1", "eslint-visitor-keys": "^4.2.1" } }, "sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg=="], "@valibot/to-json-schema": ["@valibot/to-json-schema@1.5.0", "", { "peerDependencies": { "valibot": "^1.2.0" } }, "sha512-GE7DmSr1C2UCWPiV0upRH6mv0cCPsqYGs819fb6srCS1tWhyXrkGGe+zxUiwzn/L1BOfADH4sNjY/YHCuP8phQ=="], @@ -961,9 +1000,9 @@ "before-after-hook": ["before-after-hook@3.0.2", "", {}, "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A=="], - "better-auth": ["better-auth@1.4.12", "", { "dependencies": { "@better-auth/core": "1.4.12", "@better-auth/telemetry": "1.4.12", "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "@noble/ciphers": "^2.0.0", "@noble/hashes": "^2.0.0", "better-call": "1.1.7", "defu": "^6.1.4", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1", "zod": "^4.1.12" }, "peerDependencies": { "@lynx-js/react": "*", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "@sveltejs/kit": "^2.0.0", "@tanstack/react-start": "^1.0.0", "better-sqlite3": "^12.0.0", "drizzle-kit": ">=0.31.4", "drizzle-orm": ">=0.41.0", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", "pg": "^8.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0", "vue": "^3.0.0" }, "optionalPeers": ["@lynx-js/react", "@prisma/client", "@sveltejs/kit", "@tanstack/react-start", "better-sqlite3", "drizzle-kit", "drizzle-orm", "mongodb", "mysql2", "next", "pg", "prisma", "react", "react-dom", "solid-js", "svelte", "vitest", "vue"] }, "sha512-FsFMnWgk+AGrxsIGbpWLCibgYcbm6uNhPHln3ohXFDXSRa0gk39Beuh54Q+x6ml2qYodF0snxf/tPtDpBI/JiA=="], + "better-auth": ["better-auth@1.4.15", "", { "dependencies": { "@better-auth/core": "1.4.15", "@better-auth/telemetry": "1.4.15", "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "@noble/ciphers": "^2.0.0", "@noble/hashes": "^2.0.0", "better-call": "1.1.8", "defu": "^6.1.4", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1", "zod": "^4.1.12" }, "peerDependencies": { "@lynx-js/react": "*", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "@sveltejs/kit": "^2.0.0", "@tanstack/react-start": "^1.0.0", "@tanstack/solid-start": "^1.0.0", "better-sqlite3": "^12.0.0", "drizzle-kit": ">=0.31.4", "drizzle-orm": ">=0.41.0", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", "pg": "^8.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0", "vue": "^3.0.0" }, "optionalPeers": ["@lynx-js/react", "@prisma/client", "@sveltejs/kit", "@tanstack/react-start", "@tanstack/solid-start", "better-sqlite3", "drizzle-kit", "drizzle-orm", "mongodb", "mysql2", "next", "pg", "prisma", "react", "react-dom", "solid-js", "svelte", "vitest", "vue"] }, "sha512-XZr4GnFPbjvf8wip8AAjTrpGNn3Sba600zT+DgsR3NNCMWCt9aD8+nuRah6BHwHWnVP1nfnby07tPmti72SRBw=="], - "better-call": ["better-call@1.1.7", "", { "dependencies": { "@better-auth/utils": "^0.3.0", "@better-fetch/fetch": "^1.1.4", "rou3": "^0.7.10", "set-cookie-parser": "^2.7.1" }, "peerDependencies": { "zod": "^4.0.0" }, "optionalPeers": ["zod"] }, "sha512-6gaJe1bBIEgVebQu/7q9saahVzvBsGaByEnE8aDVncZEDiJO7sdNB28ot9I6iXSbR25egGmmZ6aIURXyQHRraQ=="], + "better-call": ["better-call@1.1.8", "", { "dependencies": { "@better-auth/utils": "^0.3.0", "@better-fetch/fetch": "^1.1.4", "rou3": "^0.7.10", "set-cookie-parser": "^2.7.1" }, "peerDependencies": { "zod": "^4.0.0" }, "optionalPeers": ["zod"] }, "sha512-XMQ2rs6FNXasGNfMjzbyroSwKwYbZ/T3IxruSS6U2MJRsSYh3wYtG3o6H00ZlKZ/C/UPOAD97tqgQJNsxyeTXw=="], "bits-ui": ["bits-ui@2.15.4", "", { "dependencies": { "@floating-ui/core": "^1.7.1", "@floating-ui/dom": "^1.7.1", "esm-env": "^1.1.2", "runed": "^0.35.1", "svelte-toolbelt": "^0.10.6", "tabbable": "^6.2.0" }, "peerDependencies": { "@internationalized/date": "^3.8.1", "svelte": "^5.33.0" } }, "sha512-7H9YUfp03KOk1LVDh8wPYSRPxlZgG/GRWLNSA8QC73/8Z8ytun+DWJhIuibyFyz7A0cP/RANVcB4iDrbY8q+Og=="], @@ -977,7 +1016,7 @@ "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], - "bun": ["bun@1.3.5", "", { "optionalDependencies": { "@oven/bun-darwin-aarch64": "1.3.5", "@oven/bun-darwin-x64": "1.3.5", "@oven/bun-darwin-x64-baseline": "1.3.5", "@oven/bun-linux-aarch64": "1.3.5", "@oven/bun-linux-aarch64-musl": "1.3.5", "@oven/bun-linux-x64": "1.3.5", "@oven/bun-linux-x64-baseline": "1.3.5", "@oven/bun-linux-x64-musl": "1.3.5", "@oven/bun-linux-x64-musl-baseline": "1.3.5", "@oven/bun-windows-x64": "1.3.5", "@oven/bun-windows-x64-baseline": "1.3.5" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ], "bin": { "bun": "bin/bun.exe", "bunx": "bin/bunx.exe" } }, "sha512-c1YHIGUfgvYPJmLug5QiLzNWlX2Dg7X/67JWu1Va+AmMXNXzC/KQn2lgQ7rD+n1u1UqDpJMowVGGxTNpbPydNw=="], + "bun": ["bun@1.3.6", "", { "optionalDependencies": { "@oven/bun-darwin-aarch64": "1.3.6", "@oven/bun-darwin-x64": "1.3.6", "@oven/bun-darwin-x64-baseline": "1.3.6", "@oven/bun-linux-aarch64": "1.3.6", "@oven/bun-linux-aarch64-musl": "1.3.6", "@oven/bun-linux-x64": "1.3.6", "@oven/bun-linux-x64-baseline": "1.3.6", "@oven/bun-linux-x64-musl": "1.3.6", "@oven/bun-linux-x64-musl-baseline": "1.3.6", "@oven/bun-windows-x64": "1.3.6", "@oven/bun-windows-x64-baseline": "1.3.6" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ], "bin": { "bun": "bin/bun.exe", "bunx": "bin/bunx.exe" } }, "sha512-Tn98GlZVN2WM7+lg/uGn5DzUao37Yc0PUz7yzYHdeF5hd+SmHQGbCUIKE4Sspdgtxn49LunK3mDNBC2Qn6GJjw=="], "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], @@ -1059,7 +1098,7 @@ "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - "devalue": ["devalue@5.6.1", "", {}, "sha512-jDwizj+IlEZBunHcOuuFVBnIMPAEHvTsJj0BcIp94xYguLRVBcXO853px/MyIJvbVzWdsGvrRweIUWJw8hBP7A=="], + "devalue": ["devalue@5.6.2", "", {}, "sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg=="], "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], @@ -1323,6 +1362,8 @@ "logform": ["logform@2.7.0", "", { "dependencies": { "@colors/colors": "1.6.0", "@types/triple-beam": "^1.3.2", "fecha": "^4.2.0", "ms": "^2.1.1", "safe-stable-stringify": "^2.3.1", "triple-beam": "^1.3.0" } }, "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ=="], + "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], + "lru-cache": ["lru-cache@11.2.4", "", {}, "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg=="], "lucide-svelte": ["lucide-svelte@0.562.0", "", { "peerDependencies": { "svelte": "^3 || ^4 || ^5.0.0-next.42" } }, "sha512-kSJDH/55lf0mun/o4nqWBXOcq0fWYzPeIjbTD97ywoeumAB9kWxtM06gC7oynqjtK3XhAljWSz5RafIzPEYIQA=="], @@ -1427,7 +1468,7 @@ "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], - "pino": ["pino@10.1.1", "", { "dependencies": { "@pinojs/redact": "^0.4.0", "atomic-sleep": "^1.0.0", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^3.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^4.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-3qqVfpJtRQUCAOs4rTOEwLH6mwJJ/CSAlbis8fKOiMzTtXh0HN/VLsn3UWVTJ7U8DsWmxeNon2IpGb+wORXH4g=="], + "pino": ["pino@10.2.1", "", { "dependencies": { "@pinojs/redact": "^0.4.0", "atomic-sleep": "^1.0.0", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^3.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^4.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-Tjyv76gdUe2460dEhtcnA4fU/+HhGq2Kr7OWlo2R/Xxbmn/ZNKWavNWTD2k97IE+s755iVU7WcaOEIl+H3cq8w=="], "pino-abstract-transport": ["pino-abstract-transport@3.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg=="], @@ -1449,13 +1490,13 @@ "postgres": ["postgres@3.4.8", "", {}, "sha512-d+JFcLM17njZaOLkv6SCev7uoLaBtfK86vMUXhW1Z4glPWh4jozno9APvW/XKFJ3CCxVoC7OL38BqRydtu5nGg=="], - "posthog-js": ["posthog-js@1.318.1", "", { "dependencies": { "@posthog/core": "1.9.1", "@posthog/types": "1.318.1", "core-js": "^3.38.1", "dompurify": "^3.3.1", "fflate": "^0.4.8", "preact": "^10.19.3", "query-selector-shadow-dom": "^1.0.1", "web-vitals": "^4.2.4" } }, "sha512-8zG02pcTYILB8At/9P2B2MJjuGq+DY3BeE01I4IPi6bnWNh3hka6+ZQhn9GfgtCQs7Ygk6qMaOxpUFvsDGQaQQ=="], + "posthog-js": ["posthog-js@1.330.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/api-logs": "^0.208.0", "@opentelemetry/exporter-logs-otlp-http": "^0.208.0", "@opentelemetry/resources": "^2.2.0", "@opentelemetry/sdk-logs": "^0.208.0", "@posthog/core": "1.10.0", "@posthog/types": "1.330.0", "core-js": "^3.38.1", "dompurify": "^3.3.1", "fflate": "^0.4.8", "preact": "^10.28.0", "query-selector-shadow-dom": "^1.0.1", "web-vitals": "^4.2.4" } }, "sha512-Sj3xPMtT7Xlfa55LUzzi5aA39BZjn8PcpyP7N4pdW7sqkcppACZYSxPpwUXquRDR3oLbE806/scDl3osOrwLbw=="], "preact": ["preact@10.28.2", "", {}, "sha512-lbteaWGzGHdlIuiJ0l2Jq454m6kcpI1zNje6d8MlGAFlYvP2GO4ibnat7P74Esfz4sPTdM6UxtTwh/d3pwM9JA=="], "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], - "prettier": ["prettier@3.7.4", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA=="], + "prettier": ["prettier@3.8.0", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA=="], "prettier-plugin-svelte": ["prettier-plugin-svelte@3.4.1", "", { "peerDependencies": { "prettier": "^3.0.0", "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" } }, "sha512-xL49LCloMoZRvSwa6IEdN2GV6cq2IqpYGstYtMT+5wmml1/dClEoI0MZR78MiVPpu6BdQFfN0/y73yO6+br5Pg=="], @@ -1469,6 +1510,8 @@ "property-expr": ["property-expr@2.0.6", "", {}, "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA=="], + "protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="], + "pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="], "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], @@ -1491,7 +1534,7 @@ "react-dom": ["react-dom@19.2.3", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.3" } }, "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg=="], - "react-email": ["react-email@5.2.3", "", { "dependencies": { "@babel/parser": "^7.27.0", "@babel/traverse": "^7.27.0", "chokidar": "^4.0.3", "commander": "^13.0.0", "conf": "^15.0.2", "debounce": "^2.0.0", "esbuild": "^0.25.0", "glob": "^11.0.0", "jiti": "2.4.2", "log-symbols": "^7.0.0", "mime-types": "^3.0.0", "normalize-path": "^3.0.0", "nypm": "0.6.2", "ora": "^8.0.0", "prompts": "2.4.2", "socket.io": "^4.8.1", "tsconfig-paths": "4.2.0" }, "bin": { "email": "dist/index.js" } }, "sha512-EJZLLsdaFD7DYHQKMotpm5tiUp5Fp/FFB6x8VlZA5z20itiJsQ5zBaTTPBDE0KhJXvAUhBbKjC1BheCEchVoOg=="], + "react-email": ["react-email@5.2.5", "", { "dependencies": { "@babel/parser": "^7.27.0", "@babel/traverse": "^7.27.0", "chokidar": "^4.0.3", "commander": "^13.0.0", "conf": "^15.0.2", "debounce": "^2.0.0", "esbuild": "^0.25.0", "glob": "^11.0.0", "jiti": "2.4.2", "log-symbols": "^7.0.0", "mime-types": "^3.0.0", "normalize-path": "^3.0.0", "nypm": "0.6.2", "ora": "^8.0.0", "prompts": "2.4.2", "socket.io": "^4.8.1", "tsconfig-paths": "4.2.0" }, "bin": { "email": "dist/index.js" } }, "sha512-YaCp5n/0czviN4lFndsYongiI0IJOMFtFoRVIPJc9+WPJejJEvzJO94r31p3Cz9swDuV0RhEhH1W0lJFAXntHA=="], "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], @@ -1609,7 +1652,7 @@ "sv": ["sv@0.11.2", "", { "bin": { "sv": "dist/bin.mjs" } }, "sha512-WqvLSwSTE2DmHRl4DSTBpkcCp+Y5YOcHKvixneAe7x85ofN6t8YaXv3aA0l4rANfFyu8VADGSYcpelK30ukIjQ=="], - "svelte": ["svelte@5.46.1", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "devalue": "^5.5.0", "esm-env": "^1.2.1", "esrap": "^2.2.1", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-ynjfCHD3nP2el70kN5Pmg37sSi0EjOm9FgHYQdC4giWG/hzO3AatzXXJJgP305uIhGQxSufJLuYWtkY8uK/8RA=="], + "svelte": ["svelte@5.47.0", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "devalue": "^5.6.2", "esm-env": "^1.2.1", "esrap": "^2.2.1", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-LRhAvzhvb4lHLNAcAMJZ2ifUSOif8OuItF4khbssrIeitj01GjpumeeauSnCeAGnSI+X6P2R3Z7S4c5STv4iQQ=="], "svelte-adapter-bun": ["svelte-adapter-bun@1.0.1", "", { "dependencies": { "rolldown": "^1.0.0-beta.38" }, "peerDependencies": { "@sveltejs/kit": "^2.4.0", "typescript": "^5" } }, "sha512-tNOvfm8BGgG+rmEA7hkmqtq07v7zoo4skLQc+hIoQ79J+1fkEMpJEA2RzCIe3aPc8JdrsMJkv3mpiZPMsgahjA=="], @@ -1617,7 +1660,7 @@ "svelte-eslint-parser": ["svelte-eslint-parser@1.4.1", "", { "dependencies": { "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.0.0", "espree": "^10.0.0", "postcss": "^8.4.49", "postcss-scss": "^4.0.9", "postcss-selector-parser": "^7.0.0" }, "peerDependencies": { "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["svelte"] }, "sha512-1eqkfQ93goAhjAXxZiu1SaKI9+0/sxp4JIWQwUpsz7ybehRE5L8dNuz7Iry7K22R47p5/+s9EM+38nHV2OlgXA=="], - "svelte-octicons": ["svelte-octicons@18.20.0", "", {}, "sha512-AHov1ZGI0ShEG1bDolp5h8QNaXn+zruFJDL5wlS2arXvpLKIyzqv3UHUx8cDJhXMQol3gDY0HQJA6vD3X7Klqg=="], + "svelte-octicons": ["svelte-octicons@18.20.1", "", {}, "sha512-MScj3daTXySSY8gvUudtaLVbLCWwdHibr2co3UDX+XjeouRDH3aOLGP8PYMnYfe2pRVBEIn9XmdNZ8r6urUVAQ=="], "svelte-sonner": ["svelte-sonner@1.0.7", "", { "dependencies": { "runed": "^0.28.0" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-1EUFYmd7q/xfs2qCHwJzGPh9n5VJ3X6QjBN10fof2vxgy8fYE7kVfZ7uGnd7i6fQaWIr5KvXcwYXE/cmTEjk5A=="], @@ -1679,7 +1722,7 @@ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], - "typescript-eslint": ["typescript-eslint@8.52.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.52.0", "@typescript-eslint/parser": "8.52.0", "@typescript-eslint/typescript-estree": "8.52.0", "@typescript-eslint/utils": "8.52.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-atlQQJ2YkO4pfTVQmQ+wvYQwexPDOIgo+RaVcD7gHgzy/IQA+XTyuxNM9M9TVXvttkF7koBHmcwisKdOAf2EcA=="], + "typescript-eslint": ["typescript-eslint@8.53.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.53.1", "@typescript-eslint/parser": "8.53.1", "@typescript-eslint/typescript-estree": "8.53.1", "@typescript-eslint/utils": "8.53.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-gB+EVQfP5RDElh9ittfXlhZJdjSU4jUSTyE2+ia8CYyNvet4ElfaLlAIqDvQV9JPknKx0jQH1racTYe/4LaLSg=="], "uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="], @@ -1757,8 +1800,20 @@ "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + "@opentelemetry/otlp-transformer/@opentelemetry/resources": ["@opentelemetry/resources@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A=="], + + "@opentelemetry/resources/@opentelemetry/core": ["@opentelemetry/core@2.4.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-KtcyFHssTn5ZgDu6SXmUznS80OFs/wN7y6MyFRRcKU6TOw8hNcGxKvt8hsdaLJfhzUszNSjURetq5Qpkad14Gw=="], + + "@opentelemetry/sdk-logs/@opentelemetry/resources": ["@opentelemetry/resources@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A=="], + + "@opentelemetry/sdk-metrics/@opentelemetry/resources": ["@opentelemetry/resources@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A=="], + + "@opentelemetry/sdk-trace-base/@opentelemetry/resources": ["@opentelemetry/resources@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A=="], + "@oslojs/jwt/@oslojs/encoding": ["@oslojs/encoding@0.4.1", "", {}, "sha512-hkjo6MuIK/kQR5CrGNdAPZhS01ZCXuWDRJ187zh6qqF2+yMHZpD9fAYpX8q2bOO6Ryhl3XpCT6kUX76N8hhm4Q=="], + "@react-email/render/prettier": ["prettier@3.7.4", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA=="], + "@rollup/plugin-commonjs/is-reference": ["is-reference@1.2.1", "", { "dependencies": { "@types/estree": "*" } }, "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ=="], "@sveltejs/kit/cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="], @@ -1775,6 +1830,10 @@ "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "@types/cors/@types/node": ["@types/node@22.19.5", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-HfF8+mYcHPcPypui3w3mvzuIErlNOh2OAG+BCeBZCEwyiD5ls2SiCwEyT47OELtf7M3nHxBdu0FsmzdKxkN52Q=="], + + "@types/nodemailer/@types/node": ["@types/node@22.19.5", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-HfF8+mYcHPcPypui3w3mvzuIErlNOh2OAG+BCeBZCEwyiD5ls2SiCwEyT47OELtf7M3nHxBdu0FsmzdKxkN52Q=="], + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], @@ -1795,6 +1854,8 @@ "drizzle-kit/esbuild": ["esbuild@0.19.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.19.12", "@esbuild/android-arm": "0.19.12", "@esbuild/android-arm64": "0.19.12", "@esbuild/android-x64": "0.19.12", "@esbuild/darwin-arm64": "0.19.12", "@esbuild/darwin-x64": "0.19.12", "@esbuild/freebsd-arm64": "0.19.12", "@esbuild/freebsd-x64": "0.19.12", "@esbuild/linux-arm": "0.19.12", "@esbuild/linux-arm64": "0.19.12", "@esbuild/linux-ia32": "0.19.12", "@esbuild/linux-loong64": "0.19.12", "@esbuild/linux-mips64el": "0.19.12", "@esbuild/linux-ppc64": "0.19.12", "@esbuild/linux-riscv64": "0.19.12", "@esbuild/linux-s390x": "0.19.12", "@esbuild/linux-x64": "0.19.12", "@esbuild/netbsd-x64": "0.19.12", "@esbuild/openbsd-x64": "0.19.12", "@esbuild/sunos-x64": "0.19.12", "@esbuild/win32-arm64": "0.19.12", "@esbuild/win32-ia32": "0.19.12", "@esbuild/win32-x64": "0.19.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg=="], + "engine.io/@types/node": ["@types/node@22.19.5", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-HfF8+mYcHPcPypui3w3mvzuIErlNOh2OAG+BCeBZCEwyiD5ls2SiCwEyT47OELtf7M3nHxBdu0FsmzdKxkN52Q=="], + "engine.io/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], "eslint/@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="], @@ -1841,6 +1902,8 @@ "svelte-toolbelt/runed": ["runed@0.35.1", "", { "dependencies": { "dequal": "^2.0.3", "esm-env": "^1.0.0", "lz-string": "^1.5.0" }, "peerDependencies": { "@sveltejs/kit": "^2.21.0", "svelte": "^5.7.0" }, "optionalPeers": ["@sveltejs/kit"] }, "sha512-2F4Q/FZzbeJTFdIS/PuOoPRSm92sA2LhzTnv6FXhCoENb3huf5+fDuNOg1LNvGOouy3u/225qxmuJvcV3IZK5Q=="], + "sveltekit-superforms/devalue": ["devalue@5.6.1", "", {}, "sha512-jDwizj+IlEZBunHcOuuFVBnIMPAEHvTsJj0BcIp94xYguLRVBcXO853px/MyIJvbVzWdsGvrRweIUWJw8hBP7A=="], + "tailwind-variants/tailwind-merge": ["tailwind-merge@2.5.4", "", {}, "sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q=="], "tsyringe/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], diff --git a/package.json b/package.json index 3944866..5a5fc80 100644 --- a/package.json +++ b/package.json @@ -61,8 +61,7 @@ "@orpc/client": "^1.13.2", "@orpc/experimental-pino": "^1.13.2", "@orpc/server": "^1.13.2", - "@orpc/svelte-query": "^1.13.2", - "@orpc/tanstack-query": "^1.13.2", + "@orpc/tanstack-query": "^1.13.4", "@oslojs/crypto": "^1.0.1", "@oslojs/encoding": "^1.1.0", "@paralleldrive/cuid2": "^2.3.1", @@ -74,10 +73,10 @@ "@tailwindcss/container-queries": "^0.1.1", "@tailwindcss/forms": "^0.5.11", "@tailwindcss/typography": "^0.5.19", - "@tanstack/query-async-storage-persister": "^5.90.18", - "@tanstack/svelte-query": "^6.0.14", + "@tanstack/query-async-storage-persister": "^5.90.21", + "@tanstack/svelte-query": "^6.0.17", "@tanstack/svelte-query-devtools": "^6.0.3", - "@tanstack/svelte-query-persist-client": "^6.0.16", + "@tanstack/svelte-query-persist-client": "^6.0.19", "@tanstack/table-core": "^8.21.3", "add": "^2.0.6", "arctic": "^3.7.0", @@ -102,7 +101,7 @@ "posthog-js": "^1.312.0", "runed": "^0.37.1", "superjson": "^2.2.6", - "svelte": "^5.46.1", + "svelte": "^5.47.0", "svelte-adapter-bun": "^1.0.1", "svelte-octicons": "^18.20.0", "svelte-sonner": "^1.0.7", From 793efb0fe8b0fbf376c64491168551e340077225 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 15:37:32 -0500 Subject: [PATCH 43/85] move user data preload to route group --- .../(account)/{account/+page.server.ts => +layout.server.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/routes/(account)/{account/+page.server.ts => +layout.server.ts} (100%) diff --git a/src/routes/(account)/account/+page.server.ts b/src/routes/(account)/+layout.server.ts similarity index 100% rename from src/routes/(account)/account/+page.server.ts rename to src/routes/(account)/+layout.server.ts From f2bebc6a97d6a4daee8d33ac1f1821a9ed2a4503 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 19:03:01 -0500 Subject: [PATCH 44/85] semicursed permissions checker function --- src/lib/auth/permissions.test.ts | 41 ++++++++++++++++++++++++++++++++ src/lib/auth/permissions.ts | 31 ++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 src/lib/auth/permissions.test.ts diff --git a/src/lib/auth/permissions.test.ts b/src/lib/auth/permissions.test.ts new file mode 100644 index 0000000..62c3b58 --- /dev/null +++ b/src/lib/auth/permissions.test.ts @@ -0,0 +1,41 @@ +import { expect, test } from 'bun:test'; +import { ac, checkRolePermission } from './permissions'; + +test('admin permissions', () => { + expect( + checkRolePermission({ + role: 'admin', + // @ts-expect-error Technically the types are not correct but this helps make sure stuff stays in sync + permissions: ac.statements + }) + ).toBe(true); + + expect( + checkRolePermission({ + roles: 'verifiedUser,admin', + permissions: { + configuration: ['view'] + } + }) + ).toBe(true); +}); + +test('verifiedUser permissions', () => { + expect( + checkRolePermission({ + roles: 'verifiedUser', + permissions: { + configuration: ['view'] + } + }) + ).toBe(false); + + expect( + checkRolePermission({ + roles: 'verifiedUser', + permissions: { + profile: ['create', 'update'] + } + }) + ).toBe(true); +}); diff --git a/src/lib/auth/permissions.ts b/src/lib/auth/permissions.ts index 3cf3667..f9277b7 100644 --- a/src/lib/auth/permissions.ts +++ b/src/lib/auth/permissions.ts @@ -1,4 +1,4 @@ -import { createAccessControl } from 'better-auth/plugins/access'; +import { createAccessControl, type AuthorizeResponse } from 'better-auth/plugins/access'; import { defaultStatements, adminAc } from 'better-auth/plugins/admin/access'; const statements = { @@ -40,7 +40,7 @@ const admin = ac.newRole({ }); const verifiedUser = ac.newRole({ - profile: ['create'] + profile: ['create', 'update'] }); const mentor = ac.newRole({ @@ -61,3 +61,30 @@ export const roles = { mentor, judge } as const; + +type PermissionsCheckInput = { + // permissions: { [key in keyof TStatements]: SubArray }; + permissions: Parameters['authorize']>[0]; +} & ({ role: keyof typeof roles; roles?: never } | { roles: string; role?: never }); + +export function checkRolePermission(options: PermissionsCheckInput) { + const _roles = ( + options.roles ? options.roles.split(',') : [options.role] + ) as (keyof typeof roles)[]; + + if (_roles.length === 0) return false; + + if (_roles.includes('admin')) return true; + + for (const role of _roles) { + const _role = roles[role]; + // @ts-expect-error It's weird + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + const result = _role?.authorize(options.permissions) as AuthorizeResponse; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (result?.success) { + return true; + } + } + return false; +} From b35ece1f8761b68cd26d12f30c069e5c0ed67d5d Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 19:29:13 -0500 Subject: [PATCH 45/85] fix some weird auth + orpc bug --- src/app.d.ts | 4 +--- src/lib/orpc/server/context.ts | 14 +++----------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/app.d.ts b/src/app.d.ts index f4e055c..6f49ceb 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -8,7 +8,7 @@ declare global { } } -type AuthLocals = +export type AuthLocals = | { user: import('$lib/auth/server').User; session: import('$lib/auth/server').Session; @@ -17,5 +17,3 @@ type AuthLocals = user: null; session: null; }; - -export {}; diff --git a/src/lib/orpc/server/context.ts b/src/lib/orpc/server/context.ts index 6e29163..02cbfc1 100644 --- a/src/lib/orpc/server/context.ts +++ b/src/lib/orpc/server/context.ts @@ -2,19 +2,11 @@ import db from '$lib/server/db'; import { githubApp } from '$lib/github'; import type { Cookies } from '@sveltejs/kit'; import { logger } from '$lib/logger'; -import type { User, Session } from '$lib/auth/server'; +import type { AuthLocals } from '../../../app'; export type ContextGeneratorParams = { request: Request; - locals: - | { - user: User; - session: Session; - } - | { - user: null; - session: null; - }; + locals: { auth: AuthLocals }; cookies: Cookies; }; @@ -23,7 +15,7 @@ export type Context = Awaited>; export function createOrpcContext(opts: ContextGeneratorParams) { return { req: opts.request, - ...opts.locals, + ...opts.locals.auth, db, githubApp, cookies: opts.cookies, From 82c01d2c45a8ee227e4430b32ab672041cdd9c23 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 19:30:21 -0500 Subject: [PATCH 46/85] fixup auth in orpc middleware --- src/lib/orpc/server/shared.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib/orpc/server/shared.ts b/src/lib/orpc/server/shared.ts index 0a19942..921b0fb 100644 --- a/src/lib/orpc/server/shared.ts +++ b/src/lib/orpc/server/shared.ts @@ -4,8 +4,8 @@ import type { Context } from './context'; export const o = os.$context(); const enforceUserIsAuthed = o.middleware(({ context, next }) => { - if (!context.user || !context.session) { - throw new ORPCError('UNAUTHORIZED'); + if (!context.user) { + throw new ORPCError('UNAUTHORIZED', { cause: 'You are not logged in' }); } return next({ context: { @@ -19,12 +19,12 @@ const enforceUserIsAuthed = o.middleware(({ context, next }) => { export const protectedProcedure = o.use(enforceUserIsAuthed); const enforceUserIsAdmin = o.middleware(({ context, next }) => { - if (!context.user || !context.session) { - throw new ORPCError('UNAUTHORIZED'); + if (!context.user) { + throw new ORPCError('UNAUTHORIZED', { cause: 'You are not logged in' }); } - if (!context.user.isOrgAdmin) { - throw new ORPCError('FORBIDDEN'); + if (!context.user.role?.split(',').includes('admin')) { + throw new ORPCError('FORBIDDEN', { cause: 'You are not an administrator' }); } return next({ From 59a398b397774256dcbbedb7d2bb6694ffeb5bf2 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 19:30:40 -0500 Subject: [PATCH 47/85] fix auth check in layout server load fn --- src/routes/(auth)/+layout.server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/(auth)/+layout.server.ts b/src/routes/(auth)/+layout.server.ts index 5a4acff..48d5370 100644 --- a/src/routes/(auth)/+layout.server.ts +++ b/src/routes/(auth)/+layout.server.ts @@ -1,7 +1,7 @@ import { redirect, type ServerLoadEvent } from '@sveltejs/kit'; export const load = (event: ServerLoadEvent) => { - if (event.locals.user) { + if (event.locals.auth.user) { return redirect(302, '/account'); } }; From 95605c543b17e27dfe1a8b3481e59203444dbbed Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 19:31:03 -0500 Subject: [PATCH 48/85] fix orpc url thing --- src/lib/orpc/client/index.svelte.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/orpc/client/index.svelte.ts b/src/lib/orpc/client/index.svelte.ts index 47c769b..5695fc7 100644 --- a/src/lib/orpc/client/index.svelte.ts +++ b/src/lib/orpc/client/index.svelte.ts @@ -8,7 +8,7 @@ import { browser, dev } from '$app/environment'; const ORPC_PATH = '/api/rpc' as const; const ORPC_URL = browser - ? ORPC_PATH + ? `${window.location.origin}${ORPC_PATH}` : dev ? `http://localhost:5173${ORPC_PATH}` : `https://hackhelp.unicycl.ing${ORPC_PATH}`; From a1d3128c45050b645d9cab1a4fe95e074ab815c6 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 19:54:45 -0500 Subject: [PATCH 49/85] more permissions utilities and tests --- src/lib/auth/permissions.test.ts | 24 +++++++++++++++++++++++- src/lib/auth/permissions.ts | 15 +++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/lib/auth/permissions.test.ts b/src/lib/auth/permissions.test.ts index 62c3b58..7933e0a 100644 --- a/src/lib/auth/permissions.test.ts +++ b/src/lib/auth/permissions.test.ts @@ -1,5 +1,5 @@ import { expect, test } from 'bun:test'; -import { ac, checkRolePermission } from './permissions'; +import { ac, addRole, checkRolePermission, removeRole } from './permissions'; test('admin permissions', () => { expect( @@ -39,3 +39,25 @@ test('verifiedUser permissions', () => { }) ).toBe(true); }); + +const addRoleCases = [ + ['judge,verifiedUser', 'admin', 'judge,verifiedUser,admin'], + ['mentor,judge', 'judge', 'mentor,judge'], + ['', 'admin', 'admin'] +]; + +const removeRoleCases = [ + ['admin,judge,verifiedUser', 'admin', 'judge,verifiedUser'], + ['mentor,judge', 'admin', 'mentor,judge'], + ['', 'admin', ''] +]; + +test.each(addRoleCases)('Add role %p + %p == %p', (oldRoles, toAdd, newRoles) => { + // @ts-expect-error Cannot narrow properly + expect(addRole(oldRoles, toAdd)).toBe(newRoles); +}); + +test.each(removeRoleCases)('Add role %p + %p == %p', (oldRoles, toRm, newRoles) => { + // @ts-expect-error Cannot narrow properly + expect(removeRole(oldRoles, toRm)).toBe(newRoles); +}); diff --git a/src/lib/auth/permissions.ts b/src/lib/auth/permissions.ts index f9277b7..5180bf6 100644 --- a/src/lib/auth/permissions.ts +++ b/src/lib/auth/permissions.ts @@ -88,3 +88,18 @@ export function checkRolePermission(options: PermissionsCheckInput) { } return false; } + +export function addRole(existingRole: string, roleToAdd: keyof typeof roles) { + const _roles = existingRole.length === 0 ? [] : existingRole.split(','); + if (_roles.includes(roleToAdd)) return existingRole; + _roles.push(roleToAdd); + return _roles.join(','); +} + +export function removeRole(existingRole: string, roleToRemove: keyof typeof roles) { + let _roles = existingRole.length === 0 ? [] : existingRole.split(','); + if (_roles.includes(roleToRemove)) { + _roles = _roles.filter((r) => r !== roleToRemove); + } + return _roles.join(','); +} From 0e90dddc8fe35c861e4f9261b54695095e9b5ace Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 20:06:12 -0500 Subject: [PATCH 50/85] update role utility function impl --- src/lib/auth/permissions.test.ts | 8 ++++++-- src/lib/auth/permissions.ts | 12 +++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/lib/auth/permissions.test.ts b/src/lib/auth/permissions.test.ts index 7933e0a..6f121eb 100644 --- a/src/lib/auth/permissions.test.ts +++ b/src/lib/auth/permissions.test.ts @@ -54,10 +54,14 @@ const removeRoleCases = [ test.each(addRoleCases)('Add role %p + %p == %p', (oldRoles, toAdd, newRoles) => { // @ts-expect-error Cannot narrow properly - expect(addRole(oldRoles, toAdd)).toBe(newRoles); + const r = addRole(oldRoles, toAdd).join(','); + expect(r).toBe(newRoles); + expect(r).toContain(toAdd); }); test.each(removeRoleCases)('Add role %p + %p == %p', (oldRoles, toRm, newRoles) => { // @ts-expect-error Cannot narrow properly - expect(removeRole(oldRoles, toRm)).toBe(newRoles); + const r = removeRole(oldRoles, toRm).join(','); + expect(r).toBe(newRoles); + expect(r).not.toContain(toRm); }); diff --git a/src/lib/auth/permissions.ts b/src/lib/auth/permissions.ts index 5180bf6..a4080a1 100644 --- a/src/lib/auth/permissions.ts +++ b/src/lib/auth/permissions.ts @@ -62,6 +62,8 @@ export const roles = { judge } as const; +type Role = keyof typeof roles; + type PermissionsCheckInput = { // permissions: { [key in keyof TStatements]: SubArray }; permissions: Parameters['authorize']>[0]; @@ -90,16 +92,16 @@ export function checkRolePermission(options: PermissionsCheckInput) { } export function addRole(existingRole: string, roleToAdd: keyof typeof roles) { - const _roles = existingRole.length === 0 ? [] : existingRole.split(','); - if (_roles.includes(roleToAdd)) return existingRole; + const _roles = (existingRole.length === 0 ? [] : existingRole.split(',')) as Role[]; + if (_roles.includes(roleToAdd)) return _roles; _roles.push(roleToAdd); - return _roles.join(','); + return _roles; } export function removeRole(existingRole: string, roleToRemove: keyof typeof roles) { - let _roles = existingRole.length === 0 ? [] : existingRole.split(','); + let _roles = (existingRole.length === 0 ? [] : existingRole.split(',')) as Role[]; if (_roles.includes(roleToRemove)) { _roles = _roles.filter((r) => r !== roleToRemove); } - return _roles.join(','); + return _roles; } From 1bd115b05c8665b928d8ffd0fdc691e5014ac78c Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 20:40:08 -0500 Subject: [PATCH 51/85] util function to clear query data on sign out --- src/lib/auth/client.svelte.ts | 7 +++-- src/routes/(account)/account/+page.svelte | 34 ++++++++++------------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/lib/auth/client.svelte.ts b/src/lib/auth/client.svelte.ts index f4373f9..d9ab074 100644 --- a/src/lib/auth/client.svelte.ts +++ b/src/lib/auth/client.svelte.ts @@ -11,7 +11,7 @@ import { } from 'better-auth/client/plugins'; import { passkeyClient } from '@better-auth/passkey/client'; import { ac, roles } from './permissions'; -import { createQuery } from '@tanstack/svelte-query'; +import { createQuery, type QueryClient } from '@tanstack/svelte-query'; export const authClient = createAuthClient({ plugins: [ @@ -29,7 +29,10 @@ export const authClient = createAuthClient({ ] }); -// export const { signIn, signUp, signOut, ...authClient } = __authClient; +export async function signOutAndClearCache(qc: QueryClient) { + await authClient.signOut(); + qc.clear(); +} export function useSession(initialData?: AuthData) { return createQuery(() => ({ diff --git a/src/routes/(account)/account/+page.svelte b/src/routes/(account)/account/+page.svelte index e935e5e..7c7bc30 100644 --- a/src/routes/(account)/account/+page.svelte +++ b/src/routes/(account)/account/+page.svelte @@ -13,12 +13,15 @@ import MadeWith from '$lib/components/MadeWith.svelte'; import { posthogHandler } from '$lib/utils'; import { resolve } from '$app/paths'; - import { authClient, useSession } from '$lib/auth/client.svelte'; + import { signOutAndClearCache, useSession } from '$lib/auth/client.svelte'; import type { PageProps } from './$types'; import * as Tabs from '$lib/components/ui/tabs'; import PasskeysCard from './_cards/passkeys-card.svelte'; + import Profile from '../_cards/profile.svelte'; + import { useQueryClient } from '@tanstack/svelte-query'; let { data }: PageProps = $props(); + const queryClient = useQueryClient(); const { data: session } = useSession(data.userInitialData); @@ -52,16 +55,18 @@
-

{session?.user.name || 'Undefined'}

+

{session?.user.name}

{#if isAdmin} Administrator {/if} + {#if session?.user.username} + {session.user.username} + {:else} + {session?.user.email} + {/if}
-
- Account + Profile Passkeys - - - - Account - - Make changes to your account here. Click save when you're done. - - - - - - - + + From d71a814b871e3403790043beb95dc1e6c8f106d1 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 21:31:11 -0500 Subject: [PATCH 52/85] add bun types --- bun.lock | 5 +++++ package.json | 1 + 2 files changed, 6 insertions(+) diff --git a/bun.lock b/bun.lock index ae446ee..b6e129e 100644 --- a/bun.lock +++ b/bun.lock @@ -72,6 +72,7 @@ "@react-email/preview-server": "5.2.3", "@sveltejs/vite-plugin-svelte": "^6.2.1", "@tailwindcss/vite": "^4.1.18", + "@types/bun": "^1.3.6", "@types/node": "^22.19.3", "@types/nodemailer": "^7.0.5", "@types/react": "^19.2.8", @@ -904,6 +905,8 @@ "@types/aws-lambda": ["@types/aws-lambda@8.10.159", "", {}, "sha512-SAP22WSGNN12OQ8PlCzGzRCZ7QDCwI85dQZbmpz7+mAk+L7j+wI7qnvmdKh+o7A5LaOp6QnOZ2NJphAZQTTHQg=="], + "@types/bun": ["@types/bun@1.3.6", "", { "dependencies": { "bun-types": "1.3.6" } }, "sha512-uWCv6FO/8LcpREhenN1d1b6fcspAB+cefwD7uti8C8VffIv0Um08TKMn98FynpTiU38+y2dUO55T11NgDt8VAA=="], + "@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="], "@types/cors": ["@types/cors@2.8.19", "", { "dependencies": { "@types/node": "*" } }, "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg=="], @@ -1018,6 +1021,8 @@ "bun": ["bun@1.3.6", "", { "optionalDependencies": { "@oven/bun-darwin-aarch64": "1.3.6", "@oven/bun-darwin-x64": "1.3.6", "@oven/bun-darwin-x64-baseline": "1.3.6", "@oven/bun-linux-aarch64": "1.3.6", "@oven/bun-linux-aarch64-musl": "1.3.6", "@oven/bun-linux-x64": "1.3.6", "@oven/bun-linux-x64-baseline": "1.3.6", "@oven/bun-linux-x64-musl": "1.3.6", "@oven/bun-linux-x64-musl-baseline": "1.3.6", "@oven/bun-windows-x64": "1.3.6", "@oven/bun-windows-x64-baseline": "1.3.6" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ], "bin": { "bun": "bin/bun.exe", "bunx": "bin/bunx.exe" } }, "sha512-Tn98GlZVN2WM7+lg/uGn5DzUao37Yc0PUz7yzYHdeF5hd+SmHQGbCUIKE4Sspdgtxn49LunK3mDNBC2Qn6GJjw=="], + "bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="], + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], "camelcase": ["camelcase@8.0.0", "", {}, "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA=="], diff --git a/package.json b/package.json index 5a5fc80..3841ca8 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@react-email/preview-server": "5.2.3", "@sveltejs/vite-plugin-svelte": "^6.2.1", "@tailwindcss/vite": "^4.1.18", + "@types/bun": "^1.3.6", "@types/node": "^22.19.3", "@types/nodemailer": "^7.0.5", "@types/react": "^19.2.8", From a5027caf1996627592ad43f4dce4a76c2693abc1 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 21:31:46 -0500 Subject: [PATCH 53/85] profile verification --- src/lib/orpc/server/router/account.ts | 181 +++++++++++------- src/routes/(account)/account/+page.svelte | 2 +- .../(account)/account/_cards/profile.svelte | 92 +++++++++ 3 files changed, 206 insertions(+), 69 deletions(-) create mode 100644 src/routes/(account)/account/_cards/profile.svelte diff --git a/src/lib/orpc/server/router/account.ts b/src/lib/orpc/server/router/account.ts index ff33e12..54b4fb3 100644 --- a/src/lib/orpc/server/router/account.ts +++ b/src/lib/orpc/server/router/account.ts @@ -2,14 +2,16 @@ import { o, protectedProcedure } from '../shared'; import { eq } from 'drizzle-orm'; import { serverEnv } from '$lib/env/server'; import type { Context } from '../context'; -import type { db as dbClient, schema as dbSchema } from '$lib/server/db'; +import type DB from '$lib/server/db'; // eslint-disable-next-line @typescript-eslint/no-unused-vars import { RequestError } from 'octokit'; import { githubApp, octokit } from '$lib/github'; import { generateState } from 'arctic'; -import { githubOAuth } from '$lib/server/auth'; +// import { githubOAuth } from '$lib/server/auth'; import type { User } from '$lib/server/db/schema'; import { ORPCError } from '@orpc/server'; +import { auth } from '$lib/auth/server'; +import { addRole, checkRolePermission } from '$lib/auth/permissions'; // ############################################# // # ACCOUNT ROUTER # @@ -32,7 +34,7 @@ async function hasPendingInvite(ctx: Context & { user: { username: string } }) { */ export async function updateInvitedUser( username: string, - db: { client: typeof dbClient; schema: typeof dbSchema }, + db: typeof DB, githubApp: typeof import('$lib/github').githubApp ) { let result: User; @@ -70,17 +72,72 @@ export const accountRouter = { return { user: context.user }; }), whoamiWithProfile: protectedProcedure.handler(async ({ context }) => { - await updateInvitedUser( - context.user.username, - { client: context.db, schema: context.dbSchema }, - context.githubApp - ); - const [userStatus] = await context.db - .select() - .from(context.dbSchema.profile) - .where(eq(context.dbSchema.profile.linkedUserId, context.user.id)); + // await updateInvitedUser( + // context.user.username, + // { client: context.db.client, schema: context.db.schema }, + // context.githubApp + // ); + // const [userStatus] = await context.db.client + // .select() + // .from(context.db.schema.profile) + // .where(eq(context.db.schema.profile.linkedUserId, context.user.id)); return { user: context.user, session: context.session, userStatus }; }), + + canCreateProfile: protectedProcedure.route({ method: 'GET' }).handler(({ context }) => { + return checkRolePermission({ + roles: context.user.role || '', + permissions: { profile: ['create', 'update'] } + }); + }), + + canRequestVerification: protectedProcedure + .route({ method: 'GET' }) + .handler(async ({ context }) => { + // For now, only people with a linked UVM NetID can request verification + const accounts = await context.db.client + .select() + .from(context.db.schema.account) + .where(eq(context.db.schema.account.userId, context.user.id)); + + for (const acc of accounts) { + if (acc.providerId === 'uvm-netid') return true; + } + + return false; + }), + + requestVerification: protectedProcedure.handler(async ({ context }) => { + const accounts = await context.db.client + .select() + .from(context.db.schema.account) + .where(eq(context.db.schema.account.userId, context.user.id)); + + for (const acc of accounts) { + if (acc.providerId === 'uvm-netid') { + await context.db.client + .update(context.db.schema.user) + .set({ role: addRole(context.user.role || '', 'verifiedUser').join(',') }) + .where(eq(context.db.schema.user.id, context.user.id)); + + return true; + } + } + return false; + }), + + hasUvmProfile: protectedProcedure.handler(async ({ context }) => { + const accounts = await context.db.client + .select() + .from(context.db.schema.account) + .where(eq(context.db.schema.account.userId, context.user.id)); + + for (const acc of accounts) { + if (acc.providerId === 'uvm-netid') return true; + } + + return false; + }), hasPendingInvite: protectedProcedure.handler(async ({ context }) => { const pendingInvite = await hasPendingInvite(context); return { hasPendingInvite: pendingInvite }; @@ -88,29 +145,29 @@ export const accountRouter = { sendInviteMutation: protectedProcedure.route({ method: 'POST' }).handler(async ({ context }) => { const rpclogger = context.logger.child({ procedure: 'account.sendInvite' }); // Make sure DB state is accurate - const userstatus = await updateInvitedUser( - context.user.username, - { client: context.db, schema: context.dbSchema }, - context.githubApp - ); - if (userstatus.isOrgMember) { - rpclogger.info('User is already a member of the organization'); - throw new ORPCError('UNAUTHORIZED', { - message: 'You are already a member of the organization' - }); - } + // const userstatus = await updateInvitedUser( + // context.user.username, + // { client: context.db.client, schema: context.db.schema }, + // context.githubApp + // ); + // if (userstatus.isOrgMember) { + // rpclogger.info('User is already a member of the organization'); + // throw new ORPCError('UNAUTHORIZED', { + // message: 'You are already a member of the organization' + // }); + // } - const pendingInvite = await hasPendingInvite(context); - if (pendingInvite) { - rpclogger.warn('User already has a pending invite'); - throw new ORPCError('UNAUTHORIZED', { message: 'You already have a pending invite' }); - } + // const pendingInvite = await hasPendingInvite(context); + // if (pendingInvite) { + // rpclogger.warn('User already has a pending invite'); + // throw new ORPCError('UNAUTHORIZED', { message: 'You already have a pending invite' }); + // } - await context.githubApp.rest.orgs.createInvitation({ - org: serverEnv.PUBLIC_GITHUB_ORGNAME, - invitee_id: context.user.githubId, - role: 'direct_member' - }); + // await context.githubApp.rest.orgs.createInvitation({ + // org: serverEnv.PUBLIC_GITHUB_ORGNAME, + // invitee_id: context.user.githubId, + // role: 'direct_member' + // }); return { invited: true }; }), @@ -120,15 +177,15 @@ export const accountRouter = { const rpclogger = context.logger.child({ procedure: 'account.refreshInvite' }); // Make sure DB state is accurate - const userstatus = await updateInvitedUser( - context.user.username, - { client: context.db, schema: context.dbSchema }, - context.githubApp - ); - if (userstatus.isOrgMember) { - rpclogger.info('User is already a member of the organization'); - return { refreshed: true, isMember: true }; - } + // const userstatus = await updateInvitedUser( + // context.user.username, + // { client: context.db.client, schema: context.db.schema }, + // context.githubApp + // ); + // if (userstatus.isOrgMember) { + // rpclogger.info('User is already a member of the organization'); + // return { refreshed: true, isMember: true }; + // } const pendingInvite = await hasPendingInvite(context); if (!pendingInvite) { @@ -144,18 +201,18 @@ export const accountRouter = { rpclogger.info('User org membership status', { isMember }); - if (isMember) { - rpclogger.info('User is a member of the organization, updating user status'); - const result = await updateInvitedUser( - context.user.username, - { client: context.db, schema: context.dbSchema }, - context.githubApp - ); - rpclogger.info('User status updated', { - isOrgMember: result.isOrgMember, - isOrgAdmin: result.isOrgAdmin - }); - } + // if (isMember) { + // rpclogger.info('User is a member of the organization, updating user status'); + // const result = await updateInvitedUser( + // context.user.username, + // { client: context.db.client, schema: context.db.schema }, + // context.githubApp + // ); + // rpclogger.info('User status updated', { + // isOrgMember: result.isOrgMember, + // isOrgAdmin: result.isOrgAdmin + // }); + // } return { refreshed: true, isMember }; }) @@ -197,19 +254,7 @@ export async function authenticatedUserOrgStatus(username: string, accessToken: } export const authRouter = { - getOAuthUrlMutation: o.route({ method: 'POST' }).handler(({ context }) => { - const state = generateState(); - const url = githubOAuth.createAuthorizationURL(state, ['read:user', 'user:email']); - - context.cookies.set('github_oauth_state', state, { - path: '/', - httpOnly: true, - maxAge: 60 * 10, - sameSite: 'lax' - }); - - return { - url: url.toString() - }; + getOAuthUrlMutation: o.route({ method: 'POST' }).handler(({ context: _ }) => { + return false; }) }; diff --git a/src/routes/(account)/account/+page.svelte b/src/routes/(account)/account/+page.svelte index 7c7bc30..ca33db7 100644 --- a/src/routes/(account)/account/+page.svelte +++ b/src/routes/(account)/account/+page.svelte @@ -17,7 +17,7 @@ import type { PageProps } from './$types'; import * as Tabs from '$lib/components/ui/tabs'; import PasskeysCard from './_cards/passkeys-card.svelte'; - import Profile from '../_cards/profile.svelte'; + import Profile from './_cards/profile.svelte'; import { useQueryClient } from '@tanstack/svelte-query'; let { data }: PageProps = $props(); diff --git a/src/routes/(account)/account/_cards/profile.svelte b/src/routes/(account)/account/_cards/profile.svelte new file mode 100644 index 0000000..834e540 --- /dev/null +++ b/src/routes/(account)/account/_cards/profile.svelte @@ -0,0 +1,92 @@ + + + + + + + Your Profile + Set important information related to your participation in the hackathon. + + {#if profilePermissionQuery.data === true} + Yippee! + {:else if profilePermissionQuery.data === false && canRequestVerificationQuery.status === 'success'} + {#if canRequestVerificationQuery.data} + +

Your account can request automatic verification!

+ +
+ {:else} + +
+
+
+ +
+
+

+ Your account cannot request verification +

+
+

+ To be automatically verified, your account must have a linked UVM NetID profile or + an email address associated with Middlebury College or Champlain College. +

+

+ Mentors, judges, and other event participants can contact the hackathon organizers + to have their account manually approved. +

+
+
+
+
+
+ {/if} + {:else} + Loading + {/if} +
From e4346b7a05796fb84a1491811a55585ee352e0e6 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 21:32:04 -0500 Subject: [PATCH 54/85] style fixes --- .../account/_cards/passkeys-card.svelte | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/routes/(account)/account/_cards/passkeys-card.svelte b/src/routes/(account)/account/_cards/passkeys-card.svelte index fada254..5ff4c02 100644 --- a/src/routes/(account)/account/_cards/passkeys-card.svelte +++ b/src/routes/(account)/account/_cards/passkeys-card.svelte @@ -57,19 +57,19 @@ Actions - {#if !passkeyQuery.data && passkeyQuery.status !== 'success'} - {#if passkeyQuery.status === 'pending'} - Loading passkeys... - - {:else if passkeyQuery.status === 'error'} - Cannot load passkeys - - {/if} - {:else} - + + {#if !passkeyQuery.data && passkeyQuery.status !== 'success'} + {#if passkeyQuery.status === 'pending'} + Loading passkeys... + + {:else if passkeyQuery.status === 'error'} + Cannot load passkeys + + {/if} + {:else} {#each passkeyQuery.data as passkey (passkey.id)} {passkey.name} @@ -90,8 +90,8 @@ >No passkeys registered {/if} - - {/if} + {/if} + From 28286740fc0321a22844be0cd7e2e8c997e0e71b Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Mon, 19 Jan 2026 21:32:13 -0500 Subject: [PATCH 55/85] base welcome page --- src/routes/(account)/welcome/+page.svelte | 47 +++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/routes/(account)/welcome/+page.svelte diff --git a/src/routes/(account)/welcome/+page.svelte b/src/routes/(account)/welcome/+page.svelte new file mode 100644 index 0000000..905fd54 --- /dev/null +++ b/src/routes/(account)/welcome/+page.svelte @@ -0,0 +1,47 @@ + + + + + + Account Home | HackHelp + + +
+

Welcome!

+ + Profile + Note that UVM users will have their profile information overridden to match their UVM + accounts + + + + +
+ +

{session?.user.name || 'Undefined'}

+
+ {session?.user.username} +
+
+
+ +
+
From 3665e6daac1996a9b169c2796ce379d3ea2481ae Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Wed, 28 Jan 2026 13:07:50 -0500 Subject: [PATCH 56/85] temp schema updates --- src/lib/server/db/schema.ts | 129 ++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 63 deletions(-) diff --git a/src/lib/server/db/schema.ts b/src/lib/server/db/schema.ts index 5e00d2c..f8511aa 100644 --- a/src/lib/server/db/schema.ts +++ b/src/lib/server/db/schema.ts @@ -1,84 +1,87 @@ -import { pgTable, text, integer } from 'drizzle-orm/pg-core'; +import { pgTable, text, integer, boolean, timestamp, json } from 'drizzle-orm/pg-core'; import { createId as cuid2 } from '@paralleldrive/cuid2'; -import { boolean } from 'drizzle-orm/pg-core'; -import { timestamp } from 'drizzle-orm/pg-core'; import { customAlphabet } from 'nanoid'; import type { WorkRooms } from '$lib/utils'; -export const user = pgTable('user', { - id: text('id').primaryKey().$defaultFn(cuid2), - githubId: integer('github_id').notNull(), - username: text('username').notNull(), - fullName: text('full_name'), - isOrgAdmin: boolean().default(false).notNull(), - isOrgMember: boolean().default(false).notNull(), - teamId: text('team_id').references(() => team.id) +import { user, session } from './auth'; + +export const configuration = pgTable('configuration', { + key: text('key').primaryKey(), + value: json('value') }); +// export const user = pgTable('user', { +// id: text('id').primaryKey().$defaultFn(cuid2), +// githubId: integer('github_id').notNull(), +// username: text('username').notNull(), +// fullName: text('full_name'), +// isOrgAdmin: boolean().default(false).notNull(), +// isOrgMember: boolean().default(false).notNull(), +// teamId: text('team_id').references(() => team.id) +// }); + export type PersonRole = 'admin' | 'mentor' | 'competitor'; -export const profile = pgTable('profile', { - username: text('username').notNull().primaryKey(), - role: text('role').$type().default('competitor'), - givenName: text('given_name'), - email: text('email'), - isWhitelisted: boolean().default(false).notNull(), - isBanned: boolean().default(false).notNull(), - linkedUserId: text('linked_user_id').references(() => user.id) -}); +// export const profile = pgTable('profile', { +// id: text('id').primaryKey().$defaultFn(cuid2), +// primaryRole: text('role').$type().default('competitor'), +// linkedUserId: text('linked_user_id').references(() => user.id, { onDelete: 'cascade' }) +// }); -export const session = pgTable('session', { - id: text('id').primaryKey().$defaultFn(cuid2), - userId: text('user_id') - .notNull() - .references(() => user.id), - expiresAt: timestamp('expires_at').notNull() -}); +// export const session = pgTable('session', { +// id: text('id').primaryKey().$defaultFn(cuid2), +// userId: text('user_id') +// .notNull() +// .references(() => user.id), +// expiresAt: timestamp('expires_at').notNull() +// }); -const simpleCode = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 6); +// const simpleCode = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 6); -export const team = pgTable('team', { - id: text('id').primaryKey().$defaultFn(cuid2), - githubId: integer('github_id').notNull(), - githubSlug: text('github_slug').notNull(), - name: text('name').notNull(), - joinCode: text('join_code').notNull().unique().$defaultFn(simpleCode), - canJoin: boolean().default(true).notNull(), - selectedChallengeId: text('selected_challenge_id').references(() => challenge.id) -}); +// export const team = pgTable('team', { +// id: text('id').primaryKey().$defaultFn(cuid2), +// githubId: integer('github_id').notNull(), +// githubSlug: text('github_slug').notNull(), +// name: text('name').notNull(), +// joinCode: text('join_code').notNull().unique().$defaultFn(simpleCode), +// canJoin: boolean().default(true).notNull(), +// selectedChallengeId: text('selected_challenge_id').references(() => challenge.id) +// }); export const TICKET_RESOLUTION_STATUS = ['open', 'assigned', 'inProgress', 'closed'] as const; export type TicketResolutionStatus = (typeof TICKET_RESOLUTION_STATUS)[number]; -export const ticket = pgTable('ticket', { - id: text('id').primaryKey().$defaultFn(cuid2), - teamId: text('team_id').references(() => team.id), - challengeId: text('challenge_id').references(() => challenge.id), - createdAt: timestamp('created_at').notNull(), - issueNumber: integer('issue_number').notNull(), - repository: text('repository').notNull(), - title: text('title').notNull(), - location: text('location').notNull().$type(), - locationDescription: text('location_description'), - assignedMentor: text('assigned_mentor').references(() => user.id), - resolutionStatus: text('resolution_status') - .default('open') - .notNull() - .$type() -}); +// export const ticket = pgTable('ticket', { +// id: text('id').primaryKey().$defaultFn(cuid2), +// teamId: text('team_id').references(() => team.id), +// challengeId: text('challenge_id').references(() => challenge.id), +// createdAt: timestamp('created_at').notNull(), +// issueNumber: integer('issue_number').notNull(), +// repository: text('repository').notNull(), +// title: text('title').notNull(), +// location: text('location').notNull().$type(), +// locationDescription: text('location_description'), +// assignedMentor: text('assigned_mentor').references(() => user.id), +// resolutionStatus: text('resolution_status') +// .default('open') +// .notNull() +// .$type() +// }); -export const challenge = pgTable('challenge', { - id: text('id').primaryKey().$defaultFn(cuid2), - title: text('title').notNull(), - linkedRepo: text('linked_repo').notNull() -}); +// export const challenge = pgTable('challenge', { +// id: text('id').primaryKey().$defaultFn(cuid2), +// title: text('title').notNull(), +// linkedRepo: text('linked_repo').notNull() +// }); + +export * from './auth'; -export type Session = typeof session.$inferSelect; +// export type Session = typeof session.$inferSelect; -export type User = typeof user.$inferSelect; +// export type User = typeof user.$inferSelect; -export type Team = typeof team.$inferSelect; +// export type Team = typeof team.$inferSelect; -export type Ticket = typeof ticket.$inferSelect; +// export type Ticket = typeof ticket.$inferSelect; -export type Challenge = typeof challenge.$inferSelect; +// export type Challenge = typeof challenge.$inferSelect; From 53db6e837f227d7f3afe6ff757dd7499ce5f3255 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Wed, 28 Jan 2026 13:08:01 -0500 Subject: [PATCH 57/85] hacky request logger --- src/hooks.server.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 015f93e..ee53624 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -9,6 +9,10 @@ export const handle: Handle = async ({ event, resolve }) => { headers: event.request.headers }); + if (new URL(event.request.url).pathname.startsWith('/api/auth')) { + console.log({ request: event.request }); + } + // Make session and user available on server if (session) { event.locals.auth = { From b60969c53dfde64890acbc3d7ffe3ace01e7a43b Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Thu, 29 Jan 2026 17:18:15 -0500 Subject: [PATCH 58/85] Account linking for UVM NetID and GitHub (rough outline) --- src/routes/(account)/account/+page.svelte | 10 ++++ .../account/_cards/github-account.svelte | 52 +++++++++++++++++++ .../account/_cards/uvmnetid-account.svelte | 51 ++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 src/routes/(account)/account/_cards/github-account.svelte create mode 100644 src/routes/(account)/account/_cards/uvmnetid-account.svelte diff --git a/src/routes/(account)/account/+page.svelte b/src/routes/(account)/account/+page.svelte index ca33db7..6b5112b 100644 --- a/src/routes/(account)/account/+page.svelte +++ b/src/routes/(account)/account/+page.svelte @@ -19,6 +19,8 @@ import PasskeysCard from './_cards/passkeys-card.svelte'; import Profile from './_cards/profile.svelte'; import { useQueryClient } from '@tanstack/svelte-query'; + import UVMNetIDAccount from './_cards/uvmnetid-account.svelte'; + import GithubAccount from './_cards/github-account.svelte'; let { data }: PageProps = $props(); const queryClient = useQueryClient(); @@ -87,6 +89,8 @@ Profile Passkeys + UVM NetID + GitHub @@ -94,6 +98,12 @@ + + + + + +
diff --git a/src/routes/(account)/account/_cards/github-account.svelte b/src/routes/(account)/account/_cards/github-account.svelte new file mode 100644 index 0000000..9104e69 --- /dev/null +++ b/src/routes/(account)/account/_cards/github-account.svelte @@ -0,0 +1,52 @@ + + + + + GitHub + Link your GitHub account to gain access to programming resources. + + {#if accountQuery.status === 'success'} + {#if githubAccount} + Yippee! + {:else} + + + + {/if} + {:else} + Loading + {/if} + diff --git a/src/routes/(account)/account/_cards/uvmnetid-account.svelte b/src/routes/(account)/account/_cards/uvmnetid-account.svelte new file mode 100644 index 0000000..f15c989 --- /dev/null +++ b/src/routes/(account)/account/_cards/uvmnetid-account.svelte @@ -0,0 +1,51 @@ + + + + + UVM NetID + Link your UVM NetID to make your account eligible for automatic verification. + + {#if accountQuery.status === 'success'} + {#if uvmNetIdAccount} + Yippee! + {:else} + + + + {/if} + {:else} + Loading + {/if} + From 3806de34cef12bebe32f202b54f4c659268aa99a Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Thu, 29 Jan 2026 17:28:33 -0500 Subject: [PATCH 59/85] gate github linking behind profile verification --- src/routes/(account)/account/+page.svelte | 17 ++++++++++++----- .../(account)/account/_cards/profile.svelte | 9 +++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/routes/(account)/account/+page.svelte b/src/routes/(account)/account/+page.svelte index 6b5112b..f0df9a5 100644 --- a/src/routes/(account)/account/+page.svelte +++ b/src/routes/(account)/account/+page.svelte @@ -18,15 +18,18 @@ import * as Tabs from '$lib/components/ui/tabs'; import PasskeysCard from './_cards/passkeys-card.svelte'; import Profile from './_cards/profile.svelte'; - import { useQueryClient } from '@tanstack/svelte-query'; + import { createQuery, useQueryClient } from '@tanstack/svelte-query'; import UVMNetIDAccount from './_cards/uvmnetid-account.svelte'; import GithubAccount from './_cards/github-account.svelte'; + import { orpc } from '$lib/orpc/client/index.svelte'; let { data }: PageProps = $props(); const queryClient = useQueryClient(); const { data: session } = useSession(data.userInitialData); + let profilePermissionQuery = createQuery(orpc.account.canCreateProfile.queryOptions); + let isAdmin = $derived( session?.user.role ? session.user.role.split(',').includes('admin') : false ); @@ -90,7 +93,9 @@ Profile Passkeys UVM NetID - GitHub + {#if profilePermissionQuery.data === true} + GitHub + {/if} @@ -101,9 +106,11 @@ - - - + {#if profilePermissionQuery.data === true} + + + + {/if}
diff --git a/src/routes/(account)/account/_cards/profile.svelte b/src/routes/(account)/account/_cards/profile.svelte index 834e540..e38e326 100644 --- a/src/routes/(account)/account/_cards/profile.svelte +++ b/src/routes/(account)/account/_cards/profile.svelte @@ -81,6 +81,15 @@ to have their account manually approved.

+ +
+ Getting your profile verified will: +
    +
  • Make you eligible to participate in the hackathon
  • +
  • Enable access to resources on GitHub
  • +
  • Allow you to join or create teams
  • +
+
From e138c2a0a8e194f5743aa001cc167c87a05ab33f Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Thu, 29 Jan 2026 20:05:43 -0500 Subject: [PATCH 60/85] shared query options --- src/routes/(account)/account/_cards/accounts.ts | 7 +++++++ .../(account)/account/_cards/github-account.svelte | 8 +++----- .../(account)/account/_cards/uvmnetid-account.svelte | 12 ++++++------ 3 files changed, 16 insertions(+), 11 deletions(-) create mode 100644 src/routes/(account)/account/_cards/accounts.ts diff --git a/src/routes/(account)/account/_cards/accounts.ts b/src/routes/(account)/account/_cards/accounts.ts new file mode 100644 index 0000000..6b8299d --- /dev/null +++ b/src/routes/(account)/account/_cards/accounts.ts @@ -0,0 +1,7 @@ +import { authClient } from '$lib/auth/client.svelte'; +import { queryOptions } from '@tanstack/svelte-query'; + +export const accountsQueryOptions = queryOptions({ + queryKey: ['auth', 'accounts'], + queryFn: () => authClient.listAccounts().then((d) => d.data) +}); diff --git a/src/routes/(account)/account/_cards/github-account.svelte b/src/routes/(account)/account/_cards/github-account.svelte index 9104e69..623824d 100644 --- a/src/routes/(account)/account/_cards/github-account.svelte +++ b/src/routes/(account)/account/_cards/github-account.svelte @@ -4,11 +4,9 @@ import * as Card from '$lib/components/ui/card'; import { createMutation, createQuery } from '@tanstack/svelte-query'; import LoaderCircle from 'lucide-svelte/icons/loader-circle'; + import { accountsQueryOptions } from './accounts'; - let accountQuery = createQuery(() => ({ - queryKey: ['auth', 'accounts'], - queryFn: () => authClient.listAccounts().then((d) => d.data) - })); + let accountQuery = createQuery(() => accountsQueryOptions); let githubAccount = $derived.by(() => { let providerAccounts = accountQuery.data @@ -22,7 +20,7 @@ // TODO Figure out which GitHub OAuth scopes are required to auto-accept org invites on behalf of the user mutationFn: () => authClient.linkSocial({ provider: 'github' }), onSettled: (_d, _e, _v, _r, ctx) => - ctx.client.invalidateQueries({ queryKey: ['auth', 'accounts'] }) + ctx.client.invalidateQueries({ queryKey: accountsQueryOptions.queryKey }) })); diff --git a/src/routes/(account)/account/_cards/uvmnetid-account.svelte b/src/routes/(account)/account/_cards/uvmnetid-account.svelte index f15c989..8e6ba3b 100644 --- a/src/routes/(account)/account/_cards/uvmnetid-account.svelte +++ b/src/routes/(account)/account/_cards/uvmnetid-account.svelte @@ -4,11 +4,9 @@ import * as Card from '$lib/components/ui/card'; import { createMutation, createQuery } from '@tanstack/svelte-query'; import LoaderCircle from 'lucide-svelte/icons/loader-circle'; + import { accountsQueryOptions } from './accounts'; - let accountQuery = createQuery(() => ({ - queryKey: ['auth', 'accounts'], - queryFn: () => authClient.listAccounts().then((d) => d.data) - })); + let accountQuery = createQuery(() => accountsQueryOptions); let uvmNetIdAccount = $derived.by(() => { let providerAccounts = accountQuery.data @@ -21,7 +19,7 @@ mutationKey: ['auth', 'accounts', 'uvm-netid'], mutationFn: () => authClient.oauth2.link({ providerId: 'uvm-netid', callbackURL: '/account' }), onSettled: (_d, _e, _v, _r, ctx) => - ctx.client.invalidateQueries({ queryKey: ['auth', 'accounts'] }) + ctx.client.invalidateQueries({ queryKey: accountsQueryOptions.queryKey }) })); @@ -34,7 +32,9 @@ {#if accountQuery.status === 'success'} {#if uvmNetIdAccount} - Yippee! + + Account ID: {uvmNetIdAccount.accountId} + {:else}
- + {#if session.status === 'success'} + {#if session.data === null} + + {:else} + + {/if} + {:else if session.status === 'error'} + + {/if} diff --git a/src/routes/auth/error/errors.ts b/src/routes/auth/error/errors.ts new file mode 100644 index 0000000..2a374ad --- /dev/null +++ b/src/routes/auth/error/errors.ts @@ -0,0 +1,4 @@ +export const errorExplanations = { + "email_doesn't_match": + 'Linking failed because your account email does not match the provider email. If you are trying to link your UVM NetID, please update your account email to match the format netid@uvm.edu' +}; From 55cf888c6e57ceb325dc6a911d3bf3ed58e87f07 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 30 Jan 2026 11:58:30 -0500 Subject: [PATCH 65/85] update env docs --- .env.example | 6 +----- README.md | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/.env.example b/.env.example index 3d5415a..7d45d75 100644 --- a/.env.example +++ b/.env.example @@ -29,8 +29,4 @@ UVM_NETID_OIDC_DISCOVERY_URL= # This example URL applies to servers that use STARTTLS on port 587. ?pool=true enables connection pooling. SMTP_URL="smtp://user:pass@smtp.example.com:587/?pool=true" # Email account to send from -PUBLIC_SMTP_FROM="user@example.com" - -# --- Miscellaneous --- -PUBLIC_SHOW_CHALLENGES= -WHITELIST_ENDPOINT_TOKEN= \ No newline at end of file +PUBLIC_SMTP_FROM="user@example.com" \ No newline at end of file diff --git a/README.md b/README.md index 34b11ea..5354b7f 100644 --- a/README.md +++ b/README.md @@ -20,14 +20,22 @@ The connection string with the credentials as set in the repo is `postgres://csc #### Set up environment variables -| Env Var | Description | -| -------------------------- | ------------------------------------------------------- | -| `DATABASE_URL` | The url of your PostgreSQL database | -| `GITHUB_APP_ID` | | -| `GITHUB_APP_PRIVATE_KEY` | | -| `GITHUB_APP_CLIENT_ID` | OAuth Client ID of the Github App | -| `GITHUB_APP_CLIENT_SECRET` | OAuth Client Secret of the Github App | -| `PUBLIC_GITHUB_ORGNAME` | The slug of the GitHub Org that HackHelp should control | +See `.env.example` for all required environment variables + +#### GitHub App Credentials + +##### Permissions + +**Repository permissions** + +- Administration: Read & Write +- Contents: Read +- Issues: Read & Write + +**Organization permissions** + +- Administration: Read & Write +- Members: Read & Write ### Get Started From 914b7f81edcc3c24ea610c1afde7cea1a5f59360 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 30 Jan 2026 11:59:14 -0500 Subject: [PATCH 66/85] make the account linking buttons actually do something --- src/routes/(account)/account/_cards/github-account.svelte | 5 ++++- src/routes/(account)/account/_cards/uvmnetid-account.svelte | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/routes/(account)/account/_cards/github-account.svelte b/src/routes/(account)/account/_cards/github-account.svelte index 623824d..c9dcac2 100644 --- a/src/routes/(account)/account/_cards/github-account.svelte +++ b/src/routes/(account)/account/_cards/github-account.svelte @@ -36,7 +36,10 @@ Yippee! {:else} - +
+
+ +
+
+
+ Organization Status: + {githubProfile.data?.orgStatus} +
+ {#if githubProfile.data?.orgStatus !== 'joined'} + + {/if} + {:else}
- - - diff --git a/src/routes/admin/users/users-table.svelte b/src/routes/admin/users/users-table.svelte deleted file mode 100644 index 6d39b15..0000000 --- a/src/routes/admin/users/users-table.svelte +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - Full Name - Username - Email - Role - - Whitelisted - Joined Team - - - - - {#if users.data} - {#each users.data.users as user (user.user.id)} - - {user.profile && user.profile.givenName - ? user.profile.givenName - : `${user.user.fullName} (GitHub)`} - {user.user.username} - {user.profile?.email} - {user.profile?.role ?? 'unknown'} - - {#if user.profile?.isWhitelisted} - - {:else} - - {/if} - - - {#if user.user.teamId !== null} - - {:else} - - {/if} - - - - - - {/each} - {/if} - - From c060b75d80c629965478cb1a207e9d444f942cef Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 30 Jan 2026 16:07:36 -0500 Subject: [PATCH 77/85] move 2025 stuff to `old` folder so routes don't conflict --- src/routes/{ => old}/admin/+layout.server.ts | 0 src/routes/{ => old}/admin/+layout.svelte | 0 src/routes/{ => old}/admin/+page.svelte | 0 src/routes/{ => old}/admin/all-tickets-table-card.svelte | 0 src/routes/{ => old}/admin/analytics/+page.svelte | 0 src/routes/{ => old}/admin/my-ticket-table-card.svelte | 0 src/routes/{ => old}/admin/teams/+page.server.ts | 0 src/routes/{ => old}/admin/teams/+page.svelte | 0 src/routes/{ => old}/admin/teams/[teamId]/+page.server.ts | 0 src/routes/{ => old}/admin/teams/[teamId]/+page.svelte | 0 src/routes/{ => old}/admin/teams/create-team.svelte | 0 src/routes/{ => old}/admin/teams/team-view-card.svelte | 0 src/routes/{ => old}/admin/teams/teams-datatable.svelte | 0 src/routes/{ => old}/admin/teams/teams-table.svelte | 0 src/routes/{ => old}/admin/ticket-assignee-combobox.svelte | 0 src/routes/{ => old}/admin/ticket-state-changer.svelte | 0 src/routes/{ => old}/admin/ticket-view-card.svelte | 0 src/routes/{ => old}/admin/tickets/+page.svelte | 0 src/routes/{ => old}/home/ bottomleft-card.svelte | 0 src/routes/{ => old}/home/+layout.server.ts | 0 src/routes/{ => old}/home/+layout.svelte | 0 src/routes/{ => old}/home/+page.server.ts | 0 src/routes/{ => old}/home/+page.svelte | 0 src/routes/{ => old}/home/challenge-selector-sheet.svelte | 0 src/routes/{ => old}/home/repo-creator-sheet.svelte | 0 src/routes/{ => old}/home/team-card.svelte | 0 src/routes/{ => old}/home/team-modify-sheet.svelte | 0 src/routes/{ => old}/home/ticket-create-combobox.svelte | 0 src/routes/{ => old}/home/ticket-create-form.svelte | 0 src/routes/{ => old}/home/ticket-create-sheet.svelte | 0 src/routes/{ => old}/home/ticket-table-card.svelte | 0 src/routes/{ => old}/join-team/+layout.server.ts | 0 src/routes/{ => old}/join-team/+layout.svelte | 0 src/routes/{ => old}/join-team/+page.server.ts | 0 src/routes/{ => old}/join-team/+page.svelte | 0 src/routes/{ => old}/join-team/join-existing-team.svelte | 0 36 files changed, 0 insertions(+), 0 deletions(-) rename src/routes/{ => old}/admin/+layout.server.ts (100%) rename src/routes/{ => old}/admin/+layout.svelte (100%) rename src/routes/{ => old}/admin/+page.svelte (100%) rename src/routes/{ => old}/admin/all-tickets-table-card.svelte (100%) rename src/routes/{ => old}/admin/analytics/+page.svelte (100%) rename src/routes/{ => old}/admin/my-ticket-table-card.svelte (100%) rename src/routes/{ => old}/admin/teams/+page.server.ts (100%) rename src/routes/{ => old}/admin/teams/+page.svelte (100%) rename src/routes/{ => old}/admin/teams/[teamId]/+page.server.ts (100%) rename src/routes/{ => old}/admin/teams/[teamId]/+page.svelte (100%) rename src/routes/{ => old}/admin/teams/create-team.svelte (100%) rename src/routes/{ => old}/admin/teams/team-view-card.svelte (100%) rename src/routes/{ => old}/admin/teams/teams-datatable.svelte (100%) rename src/routes/{ => old}/admin/teams/teams-table.svelte (100%) rename src/routes/{ => old}/admin/ticket-assignee-combobox.svelte (100%) rename src/routes/{ => old}/admin/ticket-state-changer.svelte (100%) rename src/routes/{ => old}/admin/ticket-view-card.svelte (100%) rename src/routes/{ => old}/admin/tickets/+page.svelte (100%) rename src/routes/{ => old}/home/ bottomleft-card.svelte (100%) rename src/routes/{ => old}/home/+layout.server.ts (100%) rename src/routes/{ => old}/home/+layout.svelte (100%) rename src/routes/{ => old}/home/+page.server.ts (100%) rename src/routes/{ => old}/home/+page.svelte (100%) rename src/routes/{ => old}/home/challenge-selector-sheet.svelte (100%) rename src/routes/{ => old}/home/repo-creator-sheet.svelte (100%) rename src/routes/{ => old}/home/team-card.svelte (100%) rename src/routes/{ => old}/home/team-modify-sheet.svelte (100%) rename src/routes/{ => old}/home/ticket-create-combobox.svelte (100%) rename src/routes/{ => old}/home/ticket-create-form.svelte (100%) rename src/routes/{ => old}/home/ticket-create-sheet.svelte (100%) rename src/routes/{ => old}/home/ticket-table-card.svelte (100%) rename src/routes/{ => old}/join-team/+layout.server.ts (100%) rename src/routes/{ => old}/join-team/+layout.svelte (100%) rename src/routes/{ => old}/join-team/+page.server.ts (100%) rename src/routes/{ => old}/join-team/+page.svelte (100%) rename src/routes/{ => old}/join-team/join-existing-team.svelte (100%) diff --git a/src/routes/admin/+layout.server.ts b/src/routes/old/admin/+layout.server.ts similarity index 100% rename from src/routes/admin/+layout.server.ts rename to src/routes/old/admin/+layout.server.ts diff --git a/src/routes/admin/+layout.svelte b/src/routes/old/admin/+layout.svelte similarity index 100% rename from src/routes/admin/+layout.svelte rename to src/routes/old/admin/+layout.svelte diff --git a/src/routes/admin/+page.svelte b/src/routes/old/admin/+page.svelte similarity index 100% rename from src/routes/admin/+page.svelte rename to src/routes/old/admin/+page.svelte diff --git a/src/routes/admin/all-tickets-table-card.svelte b/src/routes/old/admin/all-tickets-table-card.svelte similarity index 100% rename from src/routes/admin/all-tickets-table-card.svelte rename to src/routes/old/admin/all-tickets-table-card.svelte diff --git a/src/routes/admin/analytics/+page.svelte b/src/routes/old/admin/analytics/+page.svelte similarity index 100% rename from src/routes/admin/analytics/+page.svelte rename to src/routes/old/admin/analytics/+page.svelte diff --git a/src/routes/admin/my-ticket-table-card.svelte b/src/routes/old/admin/my-ticket-table-card.svelte similarity index 100% rename from src/routes/admin/my-ticket-table-card.svelte rename to src/routes/old/admin/my-ticket-table-card.svelte diff --git a/src/routes/admin/teams/+page.server.ts b/src/routes/old/admin/teams/+page.server.ts similarity index 100% rename from src/routes/admin/teams/+page.server.ts rename to src/routes/old/admin/teams/+page.server.ts diff --git a/src/routes/admin/teams/+page.svelte b/src/routes/old/admin/teams/+page.svelte similarity index 100% rename from src/routes/admin/teams/+page.svelte rename to src/routes/old/admin/teams/+page.svelte diff --git a/src/routes/admin/teams/[teamId]/+page.server.ts b/src/routes/old/admin/teams/[teamId]/+page.server.ts similarity index 100% rename from src/routes/admin/teams/[teamId]/+page.server.ts rename to src/routes/old/admin/teams/[teamId]/+page.server.ts diff --git a/src/routes/admin/teams/[teamId]/+page.svelte b/src/routes/old/admin/teams/[teamId]/+page.svelte similarity index 100% rename from src/routes/admin/teams/[teamId]/+page.svelte rename to src/routes/old/admin/teams/[teamId]/+page.svelte diff --git a/src/routes/admin/teams/create-team.svelte b/src/routes/old/admin/teams/create-team.svelte similarity index 100% rename from src/routes/admin/teams/create-team.svelte rename to src/routes/old/admin/teams/create-team.svelte diff --git a/src/routes/admin/teams/team-view-card.svelte b/src/routes/old/admin/teams/team-view-card.svelte similarity index 100% rename from src/routes/admin/teams/team-view-card.svelte rename to src/routes/old/admin/teams/team-view-card.svelte diff --git a/src/routes/admin/teams/teams-datatable.svelte b/src/routes/old/admin/teams/teams-datatable.svelte similarity index 100% rename from src/routes/admin/teams/teams-datatable.svelte rename to src/routes/old/admin/teams/teams-datatable.svelte diff --git a/src/routes/admin/teams/teams-table.svelte b/src/routes/old/admin/teams/teams-table.svelte similarity index 100% rename from src/routes/admin/teams/teams-table.svelte rename to src/routes/old/admin/teams/teams-table.svelte diff --git a/src/routes/admin/ticket-assignee-combobox.svelte b/src/routes/old/admin/ticket-assignee-combobox.svelte similarity index 100% rename from src/routes/admin/ticket-assignee-combobox.svelte rename to src/routes/old/admin/ticket-assignee-combobox.svelte diff --git a/src/routes/admin/ticket-state-changer.svelte b/src/routes/old/admin/ticket-state-changer.svelte similarity index 100% rename from src/routes/admin/ticket-state-changer.svelte rename to src/routes/old/admin/ticket-state-changer.svelte diff --git a/src/routes/admin/ticket-view-card.svelte b/src/routes/old/admin/ticket-view-card.svelte similarity index 100% rename from src/routes/admin/ticket-view-card.svelte rename to src/routes/old/admin/ticket-view-card.svelte diff --git a/src/routes/admin/tickets/+page.svelte b/src/routes/old/admin/tickets/+page.svelte similarity index 100% rename from src/routes/admin/tickets/+page.svelte rename to src/routes/old/admin/tickets/+page.svelte diff --git a/src/routes/home/ bottomleft-card.svelte b/src/routes/old/home/ bottomleft-card.svelte similarity index 100% rename from src/routes/home/ bottomleft-card.svelte rename to src/routes/old/home/ bottomleft-card.svelte diff --git a/src/routes/home/+layout.server.ts b/src/routes/old/home/+layout.server.ts similarity index 100% rename from src/routes/home/+layout.server.ts rename to src/routes/old/home/+layout.server.ts diff --git a/src/routes/home/+layout.svelte b/src/routes/old/home/+layout.svelte similarity index 100% rename from src/routes/home/+layout.svelte rename to src/routes/old/home/+layout.svelte diff --git a/src/routes/home/+page.server.ts b/src/routes/old/home/+page.server.ts similarity index 100% rename from src/routes/home/+page.server.ts rename to src/routes/old/home/+page.server.ts diff --git a/src/routes/home/+page.svelte b/src/routes/old/home/+page.svelte similarity index 100% rename from src/routes/home/+page.svelte rename to src/routes/old/home/+page.svelte diff --git a/src/routes/home/challenge-selector-sheet.svelte b/src/routes/old/home/challenge-selector-sheet.svelte similarity index 100% rename from src/routes/home/challenge-selector-sheet.svelte rename to src/routes/old/home/challenge-selector-sheet.svelte diff --git a/src/routes/home/repo-creator-sheet.svelte b/src/routes/old/home/repo-creator-sheet.svelte similarity index 100% rename from src/routes/home/repo-creator-sheet.svelte rename to src/routes/old/home/repo-creator-sheet.svelte diff --git a/src/routes/home/team-card.svelte b/src/routes/old/home/team-card.svelte similarity index 100% rename from src/routes/home/team-card.svelte rename to src/routes/old/home/team-card.svelte diff --git a/src/routes/home/team-modify-sheet.svelte b/src/routes/old/home/team-modify-sheet.svelte similarity index 100% rename from src/routes/home/team-modify-sheet.svelte rename to src/routes/old/home/team-modify-sheet.svelte diff --git a/src/routes/home/ticket-create-combobox.svelte b/src/routes/old/home/ticket-create-combobox.svelte similarity index 100% rename from src/routes/home/ticket-create-combobox.svelte rename to src/routes/old/home/ticket-create-combobox.svelte diff --git a/src/routes/home/ticket-create-form.svelte b/src/routes/old/home/ticket-create-form.svelte similarity index 100% rename from src/routes/home/ticket-create-form.svelte rename to src/routes/old/home/ticket-create-form.svelte diff --git a/src/routes/home/ticket-create-sheet.svelte b/src/routes/old/home/ticket-create-sheet.svelte similarity index 100% rename from src/routes/home/ticket-create-sheet.svelte rename to src/routes/old/home/ticket-create-sheet.svelte diff --git a/src/routes/home/ticket-table-card.svelte b/src/routes/old/home/ticket-table-card.svelte similarity index 100% rename from src/routes/home/ticket-table-card.svelte rename to src/routes/old/home/ticket-table-card.svelte diff --git a/src/routes/join-team/+layout.server.ts b/src/routes/old/join-team/+layout.server.ts similarity index 100% rename from src/routes/join-team/+layout.server.ts rename to src/routes/old/join-team/+layout.server.ts diff --git a/src/routes/join-team/+layout.svelte b/src/routes/old/join-team/+layout.svelte similarity index 100% rename from src/routes/join-team/+layout.svelte rename to src/routes/old/join-team/+layout.svelte diff --git a/src/routes/join-team/+page.server.ts b/src/routes/old/join-team/+page.server.ts similarity index 100% rename from src/routes/join-team/+page.server.ts rename to src/routes/old/join-team/+page.server.ts diff --git a/src/routes/join-team/+page.svelte b/src/routes/old/join-team/+page.svelte similarity index 100% rename from src/routes/join-team/+page.svelte rename to src/routes/old/join-team/+page.svelte diff --git a/src/routes/join-team/join-existing-team.svelte b/src/routes/old/join-team/join-existing-team.svelte similarity index 100% rename from src/routes/join-team/join-existing-team.svelte rename to src/routes/old/join-team/join-existing-team.svelte From 4e84494d31d89516ceac8c5d35b1acb0d7833a3c Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 30 Jan 2026 16:12:01 -0500 Subject: [PATCH 78/85] refactor UserDropdown to new auth stuff --- src/lib/components/UserDropdown.svelte | 44 ++++++++++++++++---------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/src/lib/components/UserDropdown.svelte b/src/lib/components/UserDropdown.svelte index c90430a..37e8fb5 100644 --- a/src/lib/components/UserDropdown.svelte +++ b/src/lib/components/UserDropdown.svelte @@ -4,20 +4,24 @@ import { buttonVariants } from './ui/button'; import * as DropdownMenu from './ui/dropdown-menu'; - import type { User } from '$lib/server/db/schema'; import { goto } from '$app/navigation'; import { posthogHandler } from '$lib/utils'; - import { createQuery } from '@tanstack/svelte-query'; - import { orpc } from '$lib/orpc/client/index.svelte'; import { resolve } from '$app/paths'; + import type { AuthData } from '$lib/auth/server.server'; + import { signOutAndClearCache, useSession } from '$lib/auth/client.svelte'; + import { useQueryClient } from '@tanstack/svelte-query'; type Props = { - user: User; + authData: AuthData; }; - const { user }: Props = $props(); + const { authData }: Props = $props(); - let accountData = createQuery(() => orpc.account.whoami.queryOptions({ initialData: { user } })); - const image = `https://avatars.githubusercontent.com/u/${accountData.data.user.githubId}`; + const qc = useQueryClient(); + + const userInfo = useSession(authData); + + const roles = $derived((userInfo.data?.user.role || '').split(',')); + const isAdmin = $derived(roles.includes('admin')); @@ -25,31 +29,39 @@ class={buttonVariants({ variant: 'secondary', size: 'icon', class: 'rounded-full' })} > - + Toggle user menu - {accountData.data.user.fullName} + {userInfo.data?.user.name} - {#if accountData.data.user.isOrgAdmin} + {#if isAdmin} {#snippet child({ props })} - Admin + Admin {/snippet} + {/if} + {#if roles.includes('mentor') || isAdmin} {#snippet child({ props })} - Competitor Home + Mentor Home + {/snippet} + {/if} + {#if roles.includes('judge') || isAdmin} + {#snippet child({ props })} + Judge Home {/snippet} {/if} - {#snippet child({ props })} - Settings + Account Settings {/snippet} @@ -58,9 +70,9 @@ {/snippet} Date: Fri, 30 Jan 2026 16:13:42 -0500 Subject: [PATCH 79/85] scaffold new auth section --- src/routes/(authed)/+layout.server.ts | 15 +++++ src/routes/(authed)/+layout.svelte | 10 ++++ src/routes/(authed)/_components/header.svelte | 57 +++++++++++++++++++ src/routes/(authed)/admin/+page.svelte | 5 ++ src/routes/(authed)/home/+page.svelte | 5 ++ src/routes/(authed)/judging/+page.svelte | 5 ++ src/routes/(authed)/mentor/+page.svelte | 5 ++ 7 files changed, 102 insertions(+) create mode 100644 src/routes/(authed)/+layout.server.ts create mode 100644 src/routes/(authed)/+layout.svelte create mode 100644 src/routes/(authed)/_components/header.svelte create mode 100644 src/routes/(authed)/admin/+page.svelte create mode 100644 src/routes/(authed)/home/+page.svelte create mode 100644 src/routes/(authed)/judging/+page.svelte create mode 100644 src/routes/(authed)/mentor/+page.svelte diff --git a/src/routes/(authed)/+layout.server.ts b/src/routes/(authed)/+layout.server.ts new file mode 100644 index 0000000..51cd34c --- /dev/null +++ b/src/routes/(authed)/+layout.server.ts @@ -0,0 +1,15 @@ +import { redirect, type ServerLoadEvent } from '@sveltejs/kit'; + +export const load = (event: ServerLoadEvent) => { + if (!event.locals.auth.session) { + return redirect(302, '/login'); + } + + if (!(event.locals.auth.user.role ?? '').split(',').includes('verifiedUser')) { + return redirect(302, '/account'); + } + + return { + authData: event.locals.auth + }; +}; diff --git a/src/routes/(authed)/+layout.svelte b/src/routes/(authed)/+layout.svelte new file mode 100644 index 0000000..ef9a0c0 --- /dev/null +++ b/src/routes/(authed)/+layout.svelte @@ -0,0 +1,10 @@ + + +
+ +{@render children()} diff --git a/src/routes/(authed)/_components/header.svelte b/src/routes/(authed)/_components/header.svelte new file mode 100644 index 0000000..b53355c --- /dev/null +++ b/src/routes/(authed)/_components/header.svelte @@ -0,0 +1,57 @@ + + +
+ + + {#if browser} + + {/if} + + +
+ + +
+
diff --git a/src/routes/(authed)/admin/+page.svelte b/src/routes/(authed)/admin/+page.svelte new file mode 100644 index 0000000..785601b --- /dev/null +++ b/src/routes/(authed)/admin/+page.svelte @@ -0,0 +1,5 @@ + diff --git a/src/routes/(authed)/home/+page.svelte b/src/routes/(authed)/home/+page.svelte new file mode 100644 index 0000000..785601b --- /dev/null +++ b/src/routes/(authed)/home/+page.svelte @@ -0,0 +1,5 @@ + diff --git a/src/routes/(authed)/judging/+page.svelte b/src/routes/(authed)/judging/+page.svelte new file mode 100644 index 0000000..785601b --- /dev/null +++ b/src/routes/(authed)/judging/+page.svelte @@ -0,0 +1,5 @@ + diff --git a/src/routes/(authed)/mentor/+page.svelte b/src/routes/(authed)/mentor/+page.svelte new file mode 100644 index 0000000..785601b --- /dev/null +++ b/src/routes/(authed)/mentor/+page.svelte @@ -0,0 +1,5 @@ + From f9770cb31f50b6e34c538162709706c254d688ad Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 30 Jan 2026 16:49:19 -0500 Subject: [PATCH 80/85] header link config --- src/routes/(authed)/_components/header.svelte | 26 +++++++++---------- src/routes/(authed)/_components/header.ts | 25 ++++++++++++++++++ 2 files changed, 38 insertions(+), 13 deletions(-) create mode 100644 src/routes/(authed)/_components/header.ts diff --git a/src/routes/(authed)/_components/header.svelte b/src/routes/(authed)/_components/header.svelte index b53355c..11d21ef 100644 --- a/src/routes/(authed)/_components/header.svelte +++ b/src/routes/(authed)/_components/header.svelte @@ -5,28 +5,28 @@ import Logo from '$lib/components/Logo.svelte'; import WidthWarning from '$lib/components/WidthWarning.svelte'; import { browser } from '$app/environment'; + import type { AuthData } from '$lib/auth/server.server'; type Props = { authData: AuthData; }; const { authData }: Props = $props(); - const links = [ - { - href: '/admin', - text: 'Dashboard' - }, - { - href: '/admin/teams', - text: 'Teams' - }, - { - href: '/admin/users', - text: 'Users' + import { headerNavLinks } from './header'; + + let links = $derived.by(() => { + for (const k of Object.keys(headerNavLinks)) { + if (page.url.pathname.startsWith(k)) { + return headerNavLinks[k]; + } } - ]; + return []; + }); + + console.log({ links }); +
diff --git a/src/routes/(authed)/_components/header.ts b/src/routes/(authed)/_components/header.ts new file mode 100644 index 0000000..b6e98b4 --- /dev/null +++ b/src/routes/(authed)/_components/header.ts @@ -0,0 +1,25 @@ +type Links = { href: string; text: string }[]; + +type HeaderNavConfig = Record; + +export const headerNavLinks: HeaderNavConfig = { + '/home': [ + { text: 'Dashboard', href: '/home' }, + { text: 'Challenge', href: '/challenge' } + ], + '/admin': [ + { text: 'Dashboard', href: '/admin' }, + { text: 'Users', href: '/admin/users' }, + { text: 'Teams', href: '/admin/teams' }, + { text: 'Tickets', href: '/mentor/tickets' } + ], + '/mentor': [ + { text: 'Dashboard', href: '/mentor' }, + { text: 'Teams', href: '/admin/teams' }, + { text: 'Tickets', href: '/mentor/tickets' } + ], + '/judging': [ + { text: 'Dashboard', href: '/judging' }, + { text: 'Teams', href: '/admin/teams' } + ] +} as const; From 16ec0f1cea9d3908822c165eb85de8f96e96972d Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 30 Jan 2026 16:50:25 -0500 Subject: [PATCH 81/85] ensure full reload on sign out + show something in the top of the dropdown --- src/lib/components/UserDropdown.svelte | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lib/components/UserDropdown.svelte b/src/lib/components/UserDropdown.svelte index 37e8fb5..f609538 100644 --- a/src/lib/components/UserDropdown.svelte +++ b/src/lib/components/UserDropdown.svelte @@ -36,7 +36,11 @@ Toggle user menu - {userInfo.data?.user.name} + {userInfo.data?.user.name || + userInfo.data?.user.username || + userInfo.data?.user.email} {#if isAdmin} { await signOutAndClearCache(qc); posthogHandler((posthog) => posthog.reset()); - await goto(resolve('/(auth)/login')); + await goto(resolve('/(auth)/login'), { replaceState: true, invalidateAll: true }); }}>Logout {/snippet} Date: Fri, 30 Jan 2026 17:24:20 -0500 Subject: [PATCH 82/85] get rid of useSession hook in favor of query options. fixes reactivity --- src/lib/auth/client.svelte.ts | 15 ++++++--------- src/lib/components/UserDropdown.svelte | 9 ++++++--- src/routes/(account)/account/+page.svelte | 11 +++++++---- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/lib/auth/client.svelte.ts b/src/lib/auth/client.svelte.ts index 2e0bb1b..b20c177 100644 --- a/src/lib/auth/client.svelte.ts +++ b/src/lib/auth/client.svelte.ts @@ -1,6 +1,6 @@ import { createAuthClient } from 'better-auth/svelte'; import { inferAdditionalFields } from 'better-auth/client/plugins'; -import type { auth, AuthData } from './server.server'; +import type { auth } from './server.server'; import { adminClient, emailOTPClient, @@ -11,7 +11,7 @@ import { } from 'better-auth/client/plugins'; import { passkeyClient } from '@better-auth/passkey/client'; import { ac, roles } from './permissions'; -import { createQuery, type QueryClient } from '@tanstack/svelte-query'; +import { queryOptions, type QueryClient } from '@tanstack/svelte-query'; export const authClient = createAuthClient({ plugins: [ @@ -34,10 +34,7 @@ export async function signOutAndClearCache(qc: QueryClient) { qc.clear(); } -export function useSession(initialData?: AuthData) { - return createQuery(() => ({ - queryKey: ['auth', 'user'], - queryFn: () => authClient.getSession().then((r) => r.data), - initialData: initialData - })); -} +export const sessionQueryOptions = queryOptions({ + queryKey: ['auth', 'user'], + queryFn: () => authClient.getSession().then((r) => r.data) +}); diff --git a/src/lib/components/UserDropdown.svelte b/src/lib/components/UserDropdown.svelte index f609538..ed39fb7 100644 --- a/src/lib/components/UserDropdown.svelte +++ b/src/lib/components/UserDropdown.svelte @@ -8,8 +8,8 @@ import { posthogHandler } from '$lib/utils'; import { resolve } from '$app/paths'; import type { AuthData } from '$lib/auth/server.server'; - import { signOutAndClearCache, useSession } from '$lib/auth/client.svelte'; - import { useQueryClient } from '@tanstack/svelte-query'; + import { sessionQueryOptions, signOutAndClearCache } from '$lib/auth/client.svelte'; + import { createQuery, useQueryClient } from '@tanstack/svelte-query'; type Props = { authData: AuthData; @@ -18,7 +18,10 @@ const qc = useQueryClient(); - const userInfo = useSession(authData); + const userInfo = createQuery(() => ({ + ...sessionQueryOptions, + initialData: authData + })); const roles = $derived((userInfo.data?.user.role || '').split(',')); const isAdmin = $derived(roles.includes('admin')); diff --git a/src/routes/(account)/account/+page.svelte b/src/routes/(account)/account/+page.svelte index b27b1c1..3715399 100644 --- a/src/routes/(account)/account/+page.svelte +++ b/src/routes/(account)/account/+page.svelte @@ -13,7 +13,7 @@ import MadeWith from '$lib/components/MadeWith.svelte'; import { posthogHandler } from '$lib/utils'; import { resolve } from '$app/paths'; - import { signOutAndClearCache, useSession } from '$lib/auth/client.svelte'; + import { sessionQueryOptions, signOutAndClearCache } from '$lib/auth/client.svelte'; import type { PageProps } from './$types'; import * as Tabs from '$lib/components/ui/tabs'; import PasskeysCard from './_cards/passkeys-card.svelte'; @@ -26,7 +26,10 @@ let { data }: PageProps = $props(); const queryClient = useQueryClient(); - const { data: session } = useSession(data.userInitialData); + const session = createQuery(() => ({ + ...sessionQueryOptions, + initialData: data.userInitialData + })); let profilePermissionQuery = createQuery(orpc.account.canCreateProfile.queryOptions); @@ -55,12 +58,12 @@ >Profile - +
-

{session?.user.name}

+

{session.data?.user.name}

{#if isAdmin} Administrator Date: Fri, 30 Jan 2026 17:24:30 -0500 Subject: [PATCH 83/85] account page ui rework --- src/routes/(account)/account/+page.svelte | 62 ++++++++++++----------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/src/routes/(account)/account/+page.svelte b/src/routes/(account)/account/+page.svelte index 3715399..c2fba4d 100644 --- a/src/routes/(account)/account/+page.svelte +++ b/src/routes/(account)/account/+page.svelte @@ -33,9 +33,8 @@ let profilePermissionQuery = createQuery(orpc.account.canCreateProfile.queryOptions); - let isAdmin = $derived( - session?.user.role ? session.user.role.split(',').includes('admin') : false - ); + const roles = $derived((session.data?.user.role || '').split(',')); + const isAdmin = $derived(roles.includes('admin')); @@ -44,19 +43,36 @@

Account

- + {#if roles.includes('verifiedUser') && !roles.includes('judge') && !roles.includes('mentor') && !isAdmin} + + {/if} +
ProfileProfile + @@ -69,24 +85,10 @@ >Administrator {/if} - {#if session?.user.username} - {session.user.username} - {:else} - {session?.user.email} - {/if}
-
-
- +
+ {session.data?.user.email} +
From 12226e922cdae42025af4932d5b7423ff81cc6fb Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 30 Jan 2026 17:24:49 -0500 Subject: [PATCH 84/85] option to set a user's profile photo to match their github pfp --- src/lib/orpc/server/router/account.ts | 13 +++++++++++++ .../account/_cards/github-account.svelte | 17 +++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/lib/orpc/server/router/account.ts b/src/lib/orpc/server/router/account.ts index 84857c8..bf40a39 100644 --- a/src/lib/orpc/server/router/account.ts +++ b/src/lib/orpc/server/router/account.ts @@ -224,6 +224,19 @@ export const accountRouter = { await context.db.client .delete(context.db.schema.account) .where(eq(context.db.schema.account.id, providerAccount.id)); + }), + + setProfilePhotoToGithub: protectedProcedure.handler(async ({ context }) => { + const { user } = await getGithubUserInformation(context); + + await context.db.client + .update(context.db.schema.user) + .set({ image: user.avatar_url }) + .where(eq(context.db.schema.user.id, context.user.id)); + + return { + avatarUrl: user.avatar_url + }; }) }; diff --git a/src/routes/(account)/account/_cards/github-account.svelte b/src/routes/(account)/account/_cards/github-account.svelte index ab56a0f..ee0596c 100644 --- a/src/routes/(account)/account/_cards/github-account.svelte +++ b/src/routes/(account)/account/_cards/github-account.svelte @@ -58,6 +58,13 @@ ]) }) ); + + let setGithubPfpMutation = createMutation(() => + orpc.account.setProfilePhotoToGithub.mutationOptions({ + onSettled: async (_d, _e, _v, _r, ctx) => + await Promise.allSettled([ctx.client.invalidateQueries({ queryKey: ['auth', 'user'] })]) + }) + ); @@ -106,6 +113,16 @@ {/if} Join Org {/if} + + {:else} From 115a8fdb711720214c34d9d42f3e121ffd913e81 Mon Sep 17 00:00:00 2001 From: Henrik VT Date: Fri, 30 Jan 2026 17:46:30 -0500 Subject: [PATCH 85/85] confetti for good measure --- bun.lock | 3 +++ package.json | 1 + src/routes/(account)/account/_cards/github-account.svelte | 7 +++++++ src/routes/(account)/account/_cards/passkeys-card.svelte | 5 +++++ .../(account)/account/_cards/uvmnetid-account.svelte | 6 +++++- 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/bun.lock b/bun.lock index b6e129e..b15cb36 100644 --- a/bun.lock +++ b/bun.lock @@ -57,6 +57,7 @@ "superjson": "^2.2.6", "svelte": "^5.47.0", "svelte-adapter-bun": "^1.0.1", + "svelte-confetti": "^2.3.2", "svelte-octicons": "^18.20.0", "svelte-sonner": "^1.0.7", "sveltekit-superforms": "^2.29.1", @@ -1663,6 +1664,8 @@ "svelte-check": ["svelte-check@4.3.5", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "chokidar": "^4.0.1", "fdir": "^6.2.0", "picocolors": "^1.0.0", "sade": "^1.7.4" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": ">=5.0.0" }, "bin": { "svelte-check": "bin/svelte-check" } }, "sha512-e4VWZETyXaKGhpkxOXP+B/d0Fp/zKViZoJmneZWe/05Y2aqSKj3YN2nLfYPJBQ87WEiY4BQCQ9hWGu9mPT1a1Q=="], + "svelte-confetti": ["svelte-confetti@2.3.2", "", { "peerDependencies": { "svelte": ">=5.0.0" } }, "sha512-cfIwoGqMPYWRYDUz2g7mG1uHYWy7VBepelQdzCC3j/M42UrAqaBYmIi9xaoQfow4fbINHO9WuARnTyK2bjjGQg=="], + "svelte-eslint-parser": ["svelte-eslint-parser@1.4.1", "", { "dependencies": { "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.0.0", "espree": "^10.0.0", "postcss": "^8.4.49", "postcss-scss": "^4.0.9", "postcss-selector-parser": "^7.0.0" }, "peerDependencies": { "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["svelte"] }, "sha512-1eqkfQ93goAhjAXxZiu1SaKI9+0/sxp4JIWQwUpsz7ybehRE5L8dNuz7Iry7K22R47p5/+s9EM+38nHV2OlgXA=="], "svelte-octicons": ["svelte-octicons@18.20.1", "", {}, "sha512-MScj3daTXySSY8gvUudtaLVbLCWwdHibr2co3UDX+XjeouRDH3aOLGP8PYMnYfe2pRVBEIn9XmdNZ8r6urUVAQ=="], diff --git a/package.json b/package.json index 3841ca8..bf77ff5 100644 --- a/package.json +++ b/package.json @@ -104,6 +104,7 @@ "superjson": "^2.2.6", "svelte": "^5.47.0", "svelte-adapter-bun": "^1.0.1", + "svelte-confetti": "^2.3.2", "svelte-octicons": "^18.20.0", "svelte-sonner": "^1.0.7", "sveltekit-superforms": "^2.29.1", diff --git a/src/routes/(account)/account/_cards/github-account.svelte b/src/routes/(account)/account/_cards/github-account.svelte index ee0596c..1a0d4bd 100644 --- a/src/routes/(account)/account/_cards/github-account.svelte +++ b/src/routes/(account)/account/_cards/github-account.svelte @@ -8,6 +8,7 @@ import { orpc } from '$lib/orpc/client/index.svelte'; import * as Avatar from '$lib/components/ui/avatar'; import { Badge } from '$lib/components/ui/badge'; + import Confetti from 'svelte-confetti'; let accountQuery = createQuery(() => accountsQueryOptions); @@ -76,6 +77,9 @@ {#if accountQuery.status === 'success'} {#if githubAccount} + {#if linkMutation.isSuccess} + + {/if}
@@ -123,6 +127,9 @@ {/if} Match profile photo to github + {#if setGithubPfpMutation.isSuccess} + + {/if} {:else} diff --git a/src/routes/(account)/account/_cards/passkeys-card.svelte b/src/routes/(account)/account/_cards/passkeys-card.svelte index 5ff4c02..4b0b8a5 100644 --- a/src/routes/(account)/account/_cards/passkeys-card.svelte +++ b/src/routes/(account)/account/_cards/passkeys-card.svelte @@ -8,6 +8,7 @@ import * as Table from '$lib/components/ui/table'; import Trash from 'lucide-svelte/icons/trash'; import { createMutation, createQuery } from '@tanstack/svelte-query'; + import Confetti from 'svelte-confetti'; let passkeyQuery = createQuery(() => ({ queryKey: ['auth', 'passkeys'], @@ -106,5 +107,9 @@ disabled={addPasskeyButtonDisabled} aria-disabled={addPasskeyButtonDisabled}>Register Passkey + + {#if addPasskeyMutation.isSuccess} + + {/if} diff --git a/src/routes/(account)/account/_cards/uvmnetid-account.svelte b/src/routes/(account)/account/_cards/uvmnetid-account.svelte index 6a1c9a3..97ffe21 100644 --- a/src/routes/(account)/account/_cards/uvmnetid-account.svelte +++ b/src/routes/(account)/account/_cards/uvmnetid-account.svelte @@ -5,6 +5,7 @@ import { createMutation, createQuery } from '@tanstack/svelte-query'; import LoaderCircle from 'lucide-svelte/icons/loader-circle'; import { accountsQueryOptions } from './accounts'; + import { Confetti } from 'svelte-confetti'; let accountQuery = createQuery(() => accountsQueryOptions); @@ -29,7 +30,10 @@ })); - + + {#if linkMutation.isSuccess} + + {/if} UVM NetID