diff --git a/apps/sveltekit-example-app/package.json b/apps/sveltekit-example-app/package.json index e64b594..9d7028b 100644 --- a/apps/sveltekit-example-app/package.json +++ b/apps/sveltekit-example-app/package.json @@ -16,20 +16,24 @@ "typecheck": "svelte-check --tsconfig ./tsconfig.json" }, "dependencies": { - "@packages/example-pkg": "workspace:*" + "@packages/example-pkg": "workspace:*", + "@packages/lucia-auth": "workspace:*" }, "devDependencies": { "@sveltejs/adapter-auto": "3.2.0", "@sveltejs/kit": "2.5.5", "@sveltejs/vite-plugin-svelte": "3.0.2", + "@tailwindcss/forms": "0.5.7", "@toolchain/eslint-config": "workspace:*", "@toolchain/vitest-config": "workspace:*", "autoprefixer": "10.4.19", "postcss": "8.4.38", "svelte": "4.2.12", "svelte-check": "3.6.9", + "sveltekit-superforms": "2.12.2", "tailwindcss": "3.4.3", "tslib": "2.6.2", - "vite": "5.2.8" + "vite": "5.2.8", + "zod": "3.22.4" } } diff --git a/apps/sveltekit-example-app/src/app.d.ts b/apps/sveltekit-example-app/src/app.d.ts index 367926a..5a3cbd0 100644 --- a/apps/sveltekit-example-app/src/app.d.ts +++ b/apps/sveltekit-example-app/src/app.d.ts @@ -1,9 +1,14 @@ // See https://kit.svelte.dev/docs/types#app // for information about these interfaces +import type { Session, User } from '@packages/lucia-auth' + declare global { namespace App { // interface Error {} - // interface Locals {} + interface Locals { + user: User | null + session: Session | null + } // interface PageData {} // interface PageState {} // interface Platform {} diff --git a/apps/sveltekit-example-app/src/hooks.server.ts b/apps/sveltekit-example-app/src/hooks.server.ts new file mode 100644 index 0000000..2bbe5b7 --- /dev/null +++ b/apps/sveltekit-example-app/src/hooks.server.ts @@ -0,0 +1,35 @@ +import { lucia } from '@packages/lucia-auth' + +import type { Handle } from '@sveltejs/kit' + +export const handle: Handle = async ({ event, resolve }) => { + const sessionId = event.cookies.get(lucia.sessionCookieName) + if (!sessionId) { + event.locals.user = null + event.locals.session = null + return resolve(event) + } + + const { user, session } = await lucia.validateSession(sessionId) + + if (session?.fresh) { + const sessionCookie = lucia.createSessionCookie(session.id) + event.cookies.set(sessionCookie.name, sessionCookie.value, { + path: '.', + ...sessionCookie.attributes, + }) + } + + if (!session) { + const sessionCookie = lucia.createBlankSessionCookie() + event.cookies.set(sessionCookie.name, sessionCookie.value, { + path: '.', + ...sessionCookie.attributes, + }) + } + + event.locals.user = user + event.locals.session = session + + return resolve(event) +} diff --git a/apps/sveltekit-example-app/src/lib/index.ts b/apps/sveltekit-example-app/src/lib/index.ts index 225bdea..fc7d37e 100644 --- a/apps/sveltekit-example-app/src/lib/index.ts +++ b/apps/sveltekit-example-app/src/lib/index.ts @@ -1,2 +1,15 @@ // place files you want to import through the `$lib` alias in this folder. -export {} +import { z } from 'zod' + +const password = z.string().min(6).max(255) + +export const schema = z + .object({ + email: z.string().email(), + password: password, + password_confirm: password, + }) + .refine((data) => data.password === data.password_confirm, { + message: 'Passwords do not match', + path: ['password_confirm'], + }) diff --git a/apps/sveltekit-example-app/src/routes/sign-up/+page.server.ts b/apps/sveltekit-example-app/src/routes/sign-up/+page.server.ts new file mode 100644 index 0000000..e0a68bb --- /dev/null +++ b/apps/sveltekit-example-app/src/routes/sign-up/+page.server.ts @@ -0,0 +1,41 @@ +import { fail } from '@sveltejs/kit' +import { message, setError, superValidate } from 'sveltekit-superforms' +import { zod } from 'sveltekit-superforms/adapters' + +import { schema } from '$lib' +import { lucia } from '@packages/lucia-auth' +import { createUser } from '@packages/lucia-auth/repository' + +import type { Actions, PageServerLoad } from './$types.js' + +export const load = (async () => { + const form = await superValidate(zod(schema)) + return { form } +}) satisfies PageServerLoad + +export const actions = { + default: async ({ request, cookies }) => { + const form = await superValidate(request, zod(schema)) + + if (!form.valid) { + return fail(400, { form }) + } + + try { + const userId = await createUser({ username: form.data.email, password: form.data.password }) + if (userId) { + const session = await lucia.createSession(userId, {}) + const sessionCookie = lucia.createSessionCookie(session.id) + cookies.set(sessionCookie.name, sessionCookie.value, { + path: '.', + ...sessionCookie.attributes, + }) + return message(form, 'Form posted successfully!') + } + } catch (err) { + if (err instanceof Error) { + return setError(form, 'email', 'E-mail already exists.') + } + } + }, +} satisfies Actions diff --git a/apps/sveltekit-example-app/src/routes/sign-up/+page.svelte b/apps/sveltekit-example-app/src/routes/sign-up/+page.svelte new file mode 100644 index 0000000..e034066 --- /dev/null +++ b/apps/sveltekit-example-app/src/routes/sign-up/+page.svelte @@ -0,0 +1,56 @@ + + +{#if $message}

{$message}

{/if} + +
+ + + + {#if $errors.email}{$errors.email}{/if} + + + + {#if $errors.password}{$errors.password}{/if} + + + + {#if $errors.password_confirm} + {$errors.password_confirm} + {/if} +
+ +
+
+ +
+ +
diff --git a/apps/sveltekit-example-app/tailwind.config.js b/apps/sveltekit-example-app/tailwind.config.js index 35887e5..625856c 100644 --- a/apps/sveltekit-example-app/tailwind.config.js +++ b/apps/sveltekit-example-app/tailwind.config.js @@ -1,10 +1,12 @@ +import forms from '@tailwindcss/forms' + /** @type {import('tailwindcss').Config} */ const config = { content: ['./src/**/*.{html,js,svelte,ts}'], theme: { extend: {}, }, - plugins: [], + plugins: [forms], } export default config diff --git a/packages/drizzledb-pg/src/schema/index.ts b/packages/drizzledb-pg/src/schema/index.ts index 020ca08..a50b79b 100644 --- a/packages/drizzledb-pg/src/schema/index.ts +++ b/packages/drizzledb-pg/src/schema/index.ts @@ -8,7 +8,7 @@ export const authSchema = pgSchema('auth') export const users = authSchema.table('users', { id: uuid('id').primaryKey().defaultRandom(), - username: citext('user_name').notNull(), + username: citext('username').notNull().unique(), hashedPassword: text('hashed_password').notNull(), }) diff --git a/packages/lucia-auth/package.json b/packages/lucia-auth/package.json index 45d5449..cdd8680 100644 --- a/packages/lucia-auth/package.json +++ b/packages/lucia-auth/package.json @@ -5,7 +5,10 @@ "description": "Lucia Auth Client", "license": "UNLICENSED", "type": "module", - "exports": "./src/index.ts", + "exports": { + ".": "./src/index.ts", + "./repository": "./src/repository/index.ts" + }, "scripts": { "clean": "del .turbo coverage", "lint": "eslint .", diff --git a/packages/lucia-auth/src/repository/index.ts b/packages/lucia-auth/src/repository/index.ts new file mode 100644 index 0000000..e4a618b --- /dev/null +++ b/packages/lucia-auth/src/repository/index.ts @@ -0,0 +1,23 @@ +import { Argon2id } from 'oslo/password' + +import { db } from '@packages/drizzledb-pg/client' +import * as schema from '@packages/drizzledb-pg/schema' +import { users } from '@packages/drizzledb-pg/schema' + +export type NewUser = Omit & { + password: string +} + +export type User = typeof schema.users.$inferSelect + +export const createUser = async (user: NewUser): Promise => { + const hashedPassword = await new Argon2id().hash(user.password) + return db + .insert(schema.users) + .values({ username: user.username, hashedPassword }) + .returning({ id: users.id }) + .then((res) => res[0]?.id) + .catch((err) => { + throw err + }) +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 675a0f6..e08ecef 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,6 +44,9 @@ importers: '@packages/example-pkg': specifier: workspace:* version: link:../../packages/example-pkg + '@packages/lucia-auth': + specifier: workspace:* + version: link:../../packages/lucia-auth devDependencies: '@sveltejs/adapter-auto': specifier: 3.2.0 @@ -54,6 +57,9 @@ importers: '@sveltejs/vite-plugin-svelte': specifier: 3.0.2 version: 3.0.2(svelte@4.2.12)(vite@5.2.8) + '@tailwindcss/forms': + specifier: 0.5.7 + version: 0.5.7(tailwindcss@3.4.3) '@toolchain/eslint-config': specifier: workspace:* version: link:../../toolchain/eslint-config @@ -72,6 +78,9 @@ importers: svelte-check: specifier: 3.6.9 version: 3.6.9(postcss@8.4.38)(svelte@4.2.12) + sveltekit-superforms: + specifier: 2.12.2 + version: 2.12.2(@sveltejs/kit@2.5.5)(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.20.2)(svelte@4.2.12) tailwindcss: specifier: 3.4.3 version: 3.4.3 @@ -80,7 +89,10 @@ importers: version: 2.6.2 vite: specifier: 5.2.8 - version: 5.2.8(@types/node@20.12.4) + version: 5.2.8 + zod: + specifier: 3.22.4 + version: 3.22.4 packages/drizzledb-pg: dependencies: @@ -166,7 +178,7 @@ importers: dependencies: '@aws-appsync/eslint-plugin': specifier: 1.6.0 - version: 1.6.0(@eslint/eslintrc@3.0.2)(eslint@8.57.0)(prettier@3.2.5)(typescript@5.4.3) + version: 1.6.0(@eslint/eslintrc@3.0.2)(eslint@8.57.0)(prettier@2.8.8)(typescript@5.4.3) '@eslint/js': specifier: 8.57.0 version: 8.57.0 @@ -259,7 +271,7 @@ packages: '@jridgewell/trace-mapping': 0.3.25 dev: false - /@aws-appsync/eslint-plugin@1.6.0(@eslint/eslintrc@3.0.2)(eslint@8.57.0)(prettier@3.2.5)(typescript@5.4.3): + /@aws-appsync/eslint-plugin@1.6.0(@eslint/eslintrc@3.0.2)(eslint@8.57.0)(prettier@2.8.8)(typescript@5.4.3): resolution: {integrity: sha512-Sl6hrXBvfGH0RN/Qwj/xgzKlPORv334rBMjfN0NCB74LRyR9QEBcJvybg8odzZ7HvcIc2+Ym7RZVo0oRweLeEA==} peerDependencies: eslint: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -272,7 +284,7 @@ packages: '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.4.3) '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.4.3) eslint: 8.57.0 - pretty-quick: 3.3.1(prettier@3.2.5) + pretty-quick: 3.3.1(prettier@2.8.8) typescript: 5.4.3 transitivePeerDependencies: - '@eslint/eslintrc' @@ -1183,6 +1195,37 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: false + /@gcornut/valibot-json-schema@0.0.27(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.20.2)(valibot@0.30.0): + resolution: {integrity: sha512-xcMaUStVgQzPrK3d7PuLFbQ+3qSp6LzaLExAm52E3FKmUfjQa7Sw5cDK6Hfu/8WT0yfGsuSCuJ5uT1sosjR9Qg==} + hasBin: true + requiresBuild: true + peerDependencies: + '@types/json-schema': '>= 7.0.14' + esbuild: '>= 0.18.20' + esbuild-runner: '>= 2.2.2' + valibot: '>= 0.21.0' + dependencies: + '@types/json-schema': 7.0.15 + esbuild: 0.20.2 + esbuild-runner: 2.2.2(esbuild@0.20.2) + valibot: 0.30.0 + dev: true + optional: true + + /@hapi/hoek@9.3.0: + resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} + requiresBuild: true + dev: true + optional: true + + /@hapi/topo@5.1.0: + resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} + requiresBuild: true + dependencies: + '@hapi/hoek': 9.3.0 + dev: true + optional: true + /@humanwhocodes/config-array@0.11.14: resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} @@ -1916,6 +1959,13 @@ packages: resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} dev: true + /@poppinss/macroable@1.0.2: + resolution: {integrity: sha512-xhhEcEvhQC8mP5oOr5hbE4CmUgmw/IPV1jhpGg2xSkzoFrt9i8YVqBQt9744EFesi5F7pBheWozg63RUBM/5JA==} + engines: {node: '>=18.16.0'} + requiresBuild: true + dev: true + optional: true + /@rollup/rollup-android-arm-eabi@4.14.0: resolution: {integrity: sha512-jwXtxYbRt1V+CdQSy6Z+uZti7JF5irRKF8hlKfEnF/xJpcNGuuiZMBvuoYM+x9sr9iWGnzrlM0+9hvQ1kgkf1w==} cpu: [arm] @@ -2021,10 +2071,42 @@ packages: requiresBuild: true optional: true + /@sideway/address@4.1.5: + resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} + requiresBuild: true + dependencies: + '@hapi/hoek': 9.3.0 + dev: true + optional: true + + /@sideway/formula@3.0.1: + resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} + requiresBuild: true + dev: true + optional: true + + /@sideway/pinpoint@2.0.0: + resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} + requiresBuild: true + dev: true + optional: true + /@sinclair/typebox@0.27.8: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: false + /@sinclair/typebox@0.32.20: + resolution: {integrity: sha512-ziK497ILSIYMxD/thl496idIb03IZPlha04itLQu1xAFQbumWZ+Dj4PMMCkDRpAYhvVSdmRlTjGu2B2MA5RplQ==} + requiresBuild: true + dev: true + optional: true + + /@sodaru/yup-to-json-schema@2.0.1: + resolution: {integrity: sha512-lWb0Wiz8KZ9ip/dY1eUqt7fhTPmL24p6Hmv5Fd9pzlzAdw/YNcWZr+tiCT4oZ4Zyxzi9+1X4zv82o7jYvcFxYA==} + requiresBuild: true + dev: true + optional: true + /@sveltejs/adapter-auto@3.2.0(@sveltejs/kit@2.5.5): resolution: {integrity: sha512-She5nKT47kwHE18v9NMe6pbJcvULr82u0V3yZ0ej3n1laWKGgkgdEABE9/ak5iDPs93LqsBkuIo51kkwCLBjJA==} peerDependencies: @@ -2058,7 +2140,7 @@ packages: sirv: 2.0.4 svelte: 4.2.12 tiny-glob: 0.2.9 - vite: 5.2.8(@types/node@20.12.4) + vite: 5.2.8 dev: true /@sveltejs/vite-plugin-svelte-inspector@2.0.0(@sveltejs/vite-plugin-svelte@3.0.2)(svelte@4.2.12)(vite@5.2.8): @@ -2072,7 +2154,7 @@ packages: '@sveltejs/vite-plugin-svelte': 3.0.2(svelte@4.2.12)(vite@5.2.8) debug: 4.3.4 svelte: 4.2.12 - vite: 5.2.8(@types/node@20.12.4) + vite: 5.2.8 transitivePeerDependencies: - supports-color dev: true @@ -2091,12 +2173,21 @@ packages: magic-string: 0.30.7 svelte: 4.2.12 svelte-hmr: 0.15.3(svelte@4.2.12) - vite: 5.2.8(@types/node@20.12.4) + vite: 5.2.8 vitefu: 0.2.5(vite@5.2.8) transitivePeerDependencies: - supports-color dev: true + /@tailwindcss/forms@0.5.7(tailwindcss@3.4.3): + resolution: {integrity: sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==} + peerDependencies: + tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1' + dependencies: + mini-svg-data-uri: 1.4.4 + tailwindcss: 3.4.3 + dev: true + /@tybys/wasm-util@0.8.1: resolution: {integrity: sha512-GSsTwyBl4pIzsxAY5wroZdyQKyhXk0d8PCRZtrSZ2WEB1cBdrp2EgGBwHOGCZtIIPun/DL3+AykCv+J6fyRH4Q==} requiresBuild: true @@ -2167,6 +2258,12 @@ packages: resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} dev: false + /@types/validator@13.11.9: + resolution: {integrity: sha512-FCTsikRozryfayPuiI46QzH3fnrOoctTjvOYZkho9BTFLCOZ2rgZJHMOVgCOfttjPJcgOx52EpkY0CMfy87MIw==} + requiresBuild: true + dev: true + optional: true + /@typescript-eslint/eslint-plugin@7.5.0(@typescript-eslint/parser@7.5.0)(eslint@8.57.0)(typescript@5.4.3): resolution: {integrity: sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ==} engines: {node: ^18.18.0 || >=20.0.0} @@ -2405,6 +2502,29 @@ packages: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} dev: false + /@vinejs/compiler@2.5.0: + resolution: {integrity: sha512-hg4ekaB5Y2zh+IWzBiC/WCDWrIfpVnKu/ubUvelKlidc/VbulsexoFRw5kJGHZenPVI5YzNnDeTdYSALkTV7jQ==} + engines: {node: '>=18.0.0'} + requiresBuild: true + dev: true + optional: true + + /@vinejs/vine@1.8.0: + resolution: {integrity: sha512-Qq3XxbA26jzqS9ICifkqzT399lMQZ2fWtqeV3luI2as+UIK7qDifJFU2Q4W3q3IB5VXoWxgwAZSZEO0em9I/qQ==} + engines: {node: '>=18.16.0'} + requiresBuild: true + dependencies: + '@poppinss/macroable': 1.0.2 + '@types/validator': 13.11.9 + '@vinejs/compiler': 2.5.0 + camelcase: 8.0.0 + dayjs: 1.11.10 + dlv: 1.1.3 + normalize-url: 8.0.1 + validator: 13.11.0 + dev: true + optional: true + /@vitest/coverage-v8@1.4.0(vitest@1.4.0): resolution: {integrity: sha512-4hDGyH1SvKpgZnIByr9LhGgCEuF9DKM34IBLCC/fVfy24Z3+PZ+Ii9hsVBsHvY1umM1aGPEjceRkzxCfcQ10wg==} peerDependencies: @@ -2582,6 +2702,12 @@ packages: dependencies: dequal: 2.0.3 + /arktype@1.0.29-alpha: + resolution: {integrity: sha512-glMLgVhIQRSkR3tymiS+POAcWVJH09sfrgic0jHnyFL8BlhHAJZX2BzdImU9zYr1y9NBqy+U93ZNrRTHXsKRDw==} + requiresBuild: true + dev: true + optional: true + /array-buffer-byte-length@1.0.1: resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} engines: {node: '>= 0.4'} @@ -2794,6 +2920,13 @@ packages: engines: {node: '>=14.16'} dev: true + /camelcase@8.0.0: + resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} + engines: {node: '>=16'} + requiresBuild: true + dev: true + optional: true + /caniuse-lite@1.0.30001600: resolution: {integrity: sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==} @@ -3070,6 +3203,12 @@ packages: engines: {node: '>=12'} dev: true + /dayjs@1.11.10: + resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==} + requiresBuild: true + dev: true + optional: true + /debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -3540,6 +3679,18 @@ packages: - supports-color dev: true + /esbuild-runner@2.2.2(esbuild@0.20.2): + resolution: {integrity: sha512-fRFVXcmYVmSmtYm2mL8RlUASt2TDkGh3uRcvHFOKNr/T58VrfVeKD9uT9nlgxk96u0LS0ehS/GY7Da/bXWKkhw==} + hasBin: true + peerDependencies: + esbuild: '*' + dependencies: + esbuild: 0.20.2 + source-map-support: 0.5.21 + tslib: 2.4.0 + dev: true + optional: true + /esbuild@0.18.20: resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} engines: {node: '>=12'} @@ -4750,6 +4901,18 @@ packages: hasBin: true dev: true + /joi@17.12.3: + resolution: {integrity: sha512-2RRziagf555owrm9IRVtdKynOBeITiDpuZqIpgwqXShPncPKNiRQoiGsl/T8SQdq+8ugRzH2LqY67irr2y/d+g==} + requiresBuild: true + 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 + dev: true + optional: true + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -4818,6 +4981,10 @@ packages: engines: {'0': node >= 0.2.0} dev: true + /just-clone@6.2.0: + resolution: {integrity: sha512-1IynUYEc/HAwxhi3WDpIpxJbZpMCvvrrmZVqvj9EhpvbH8lls7HhdhiByjL7DkAaWlLIzpC0Xc/VPvy/UxLNjA==} + dev: true + /keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} dependencies: @@ -5061,6 +5228,10 @@ packages: dev: false optional: true + /memoize-weak@1.0.2: + resolution: {integrity: sha512-gj39xkrjEw7nCn4nJ1M5ms6+MyMlyiGmttzsqAUsAKn6bYKwuTHh/AO3cKPF8IBrTIYTxb0wWXFs3E//Y8VoWQ==} + dev: true + /memoizee@0.4.15: resolution: {integrity: sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==} dependencies: @@ -5123,6 +5294,11 @@ packages: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} + /mini-svg-data-uri@1.4.4: + resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} + hasBin: true + dev: true + /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: @@ -5246,6 +5422,13 @@ packages: engines: {node: '>=0.10.0'} dev: true + /normalize-url@8.0.1: + resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==} + engines: {node: '>=14.16'} + requiresBuild: true + dev: true + optional: true + /npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} @@ -5847,10 +6030,17 @@ packages: prettier-plugin-svelte: 3.2.2(prettier@3.2.5)(svelte@4.2.12) dev: true + /prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: false + /prettier@3.2.5: resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} engines: {node: '>=14'} hasBin: true + dev: true /pretty-format@29.7.0: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} @@ -5861,7 +6051,7 @@ packages: react-is: 18.2.0 dev: false - /pretty-quick@3.3.1(prettier@3.2.5): + /pretty-quick@3.3.1(prettier@2.8.8): resolution: {integrity: sha512-3b36UXfYQ+IXXqex6mCca89jC8u0mYLqFAN5eTQKoXO6oCQYcIVYZEB/5AlBHI7JPYygReM2Vv6Vom/Gln7fBg==} engines: {node: '>=10.13'} hasBin: true @@ -5874,10 +6064,16 @@ packages: mri: 1.2.0 picocolors: 1.0.0 picomatch: 3.0.1 - prettier: 3.2.5 + prettier: 2.8.8 tslib: 2.6.2 dev: false + /property-expr@2.0.6: + resolution: {integrity: sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==} + requiresBuild: true + dev: true + optional: true + /pump@3.0.0: resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} dependencies: @@ -6424,6 +6620,13 @@ packages: copy-anything: 3.0.5 dev: true + /superstruct@1.0.4: + resolution: {integrity: sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ==} + engines: {node: '>=14.0.0'} + requiresBuild: true + dev: true + optional: true + /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -6561,6 +6764,36 @@ packages: magic-string: 0.30.7 periscopic: 3.1.0 + /sveltekit-superforms@2.12.2(@sveltejs/kit@2.5.5)(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.20.2)(svelte@4.2.12): + resolution: {integrity: sha512-fFOXaluP1os/Tamx7gzwhT3tXPAfqZ8KYRC0UfXdXeUtlUIUfiGrIifDJ26/9uePmF8Zhqy2M0XjG8W9kQnJpg==} + peerDependencies: + '@sveltejs/kit': 1.x || 2.x + svelte: 3.x || 4.x || >=5.0.0-next.51 + dependencies: + '@sveltejs/kit': 2.5.5(@sveltejs/vite-plugin-svelte@3.0.2)(svelte@4.2.12)(vite@5.2.8) + devalue: 4.3.2 + just-clone: 6.2.0 + memoize-weak: 1.0.2 + svelte: 4.2.12 + ts-deepmerge: 7.0.0 + optionalDependencies: + '@gcornut/valibot-json-schema': 0.0.27(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.20.2)(valibot@0.30.0) + '@sinclair/typebox': 0.32.20 + '@sodaru/yup-to-json-schema': 2.0.1 + '@vinejs/vine': 1.8.0 + arktype: 1.0.29-alpha + joi: 17.12.3 + superstruct: 1.0.4 + valibot: 0.30.0 + yup: 1.4.0 + zod: 3.22.4 + zod-to-json-schema: 3.22.5(zod@3.22.4) + transitivePeerDependencies: + - '@types/json-schema' + - esbuild + - esbuild-runner + dev: true + /synckit@0.9.0: resolution: {integrity: sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==} engines: {node: ^14.18.0 || >=16.0.0} @@ -6647,6 +6880,12 @@ packages: next-tick: 1.1.0 dev: true + /tiny-case@1.0.3: + resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==} + requiresBuild: true + dev: true + optional: true + /tiny-glob@0.2.9: resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} dependencies: @@ -6679,6 +6918,12 @@ packages: dependencies: is-number: 7.0.0 + /toposort@2.0.2: + resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} + requiresBuild: true + dev: true + optional: true + /totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} @@ -6707,6 +6952,11 @@ packages: typescript: 5.4.3 dev: false + /ts-deepmerge@7.0.0: + resolution: {integrity: sha512-WZ/iAJrKDhdINv1WG6KZIGHrZDar6VfhftG1QJFpVbOYZMYJLJOvZOo1amictRXVdBXZIgBHKswMTXzElngprA==} + engines: {node: '>=14.13.1'} + dev: true + /ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} dev: true @@ -6720,6 +6970,11 @@ packages: strip-bom: 3.0.0 dev: false + /tslib@2.4.0: + resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + dev: true + optional: true + /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} requiresBuild: true @@ -6827,6 +7082,13 @@ packages: engines: {node: '>=10'} dev: true + /type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + requiresBuild: true + dev: true + optional: true + /type-fest@3.13.1: resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} engines: {node: '>=14.16'} @@ -6928,12 +7190,25 @@ packages: convert-source-map: 2.0.0 dev: false + /valibot@0.30.0: + resolution: {integrity: sha512-5POBdbSkM+3nvJ6ZlyQHsggisfRtyT4tVTo1EIIShs6qCdXJnyWU5TJ68vr8iTg5zpOLjXLRiBqNx+9zwZz/rA==} + requiresBuild: true + dev: true + optional: true + /validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} dependencies: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 + /validator@13.11.0: + resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} + engines: {node: '>= 0.10'} + requiresBuild: true + dev: true + optional: true + /vite-node@1.4.0(@types/node@20.12.4): resolution: {integrity: sha512-VZDAseqjrHgNd4Kh8icYHWzTKSCZMhia7GyHfhtzLW33fZlG9SwsB6CEhgyVOWkJfJ2pFLrp/Gj1FSfAiqH9Lw==} engines: {node: ^18.0.0 || >=20.0.0} @@ -6955,6 +7230,41 @@ packages: - terser dev: false + /vite@5.2.8: + resolution: {integrity: sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + esbuild: 0.20.2 + postcss: 8.4.38 + rollup: 4.14.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + /vite@5.2.8(@types/node@20.12.4): resolution: {integrity: sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==} engines: {node: ^18.0.0 || >=20.0.0} @@ -6989,6 +7299,7 @@ packages: rollup: 4.14.0 optionalDependencies: fsevents: 2.3.3 + dev: false /vitefu@0.2.5(vite@5.2.8): resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} @@ -6998,7 +7309,7 @@ packages: vite: optional: true dependencies: - vite: 5.2.8(@types/node@20.12.4) + vite: 5.2.8 dev: true /vitest@1.4.0(@types/node@20.12.4): @@ -7188,6 +7499,17 @@ packages: resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} engines: {node: '>=12.20'} + /yup@1.4.0: + resolution: {integrity: sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==} + requiresBuild: true + dependencies: + property-expr: 2.0.6 + tiny-case: 1.0.3 + toposort: 2.0.2 + type-fest: 2.19.0 + dev: true + optional: true + /znv@0.4.0(zod@3.22.4): resolution: {integrity: sha512-6/pGsQhBisLzKdyC90mUCRgYDtCfQ4aQ68sDybexq3GMzqqkp662GH6qIyuCHJC1i72hJPHbWAhccTJVuZUQfA==} peerDependencies: @@ -7197,5 +7519,16 @@ packages: zod: 3.22.4 dev: false + /zod-to-json-schema@3.22.5(zod@3.22.4): + resolution: {integrity: sha512-+akaPo6a0zpVCCseDed504KBJUQpEW5QZw7RMneNmKw+fGaML1Z9tUNLnHHAC8x6dzVRO1eB2oEMyZRnuBZg7Q==} + requiresBuild: true + peerDependencies: + zod: ^3.22.4 + dependencies: + zod: 3.22.4 + dev: true + optional: true + /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + requiresBuild: true