diff --git a/package.json b/package.json index 1e9dcfe..d5819ff 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@storybook/test": "^8.4.7", "@sveltejs/adapter-node": "^5.2.9", "@sveltejs/enhanced-img": "^0.4.4", - "@sveltejs/kit": "^2.15.1", + "@sveltejs/kit": "^2.15.2", "@sveltejs/vite-plugin-svelte": "^5.0.3", "@types/cookie": "^1.0.0", "@types/node": "^22.10.5", @@ -63,7 +63,7 @@ "svelte-preprocess": "^6.0.3", "svelte-sequential-preprocessor": "^2.0.2", "svelte-sonner": "^0.3.28", - "sveltekit-flash-message": "^2.4.4", + "sveltekit-flash-message": "^2.4.5", "sveltekit-superforms": "^2.22.1", "tailwind-merge": "^2.6.0", "tailwind-variants": "^0.3.0", @@ -92,8 +92,8 @@ "@oslojs/webauthn": "^1.0.0", "@scalar/hono-api-reference": "^0.5.162", "@tailwindcss/container-queries": "^0.1.1", - "@tailwindcss/forms": "^0.5.9", - "@tailwindcss/typography": "^0.5.15", + "@tailwindcss/forms": "^0.5.10", + "@tailwindcss/typography": "^0.5.16", "arctic": "^3.1.0", "argon2": "^0.41.1", "dayjs": "^1.11.13", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2f5f06a..d34286a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,7 +19,7 @@ importers: version: 0.4.2(hono@4.6.16)(zod@3.24.1) '@inlang/paraglide-sveltekit': specifier: ^0.15.4 - version: 0.15.4(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0))) + version: 0.15.4(@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0))) '@internationalized/date': specifier: ^3.5.5 version: 3.6.0 @@ -54,11 +54,11 @@ importers: specifier: ^0.1.1 version: 0.1.1(tailwindcss@3.4.17) '@tailwindcss/forms': - specifier: ^0.5.9 - version: 0.5.9(tailwindcss@3.4.17) + specifier: ^0.5.10 + version: 0.5.10(tailwindcss@3.4.17) '@tailwindcss/typography': - specifier: ^0.5.15 - version: 0.5.15(tailwindcss@3.4.17) + specifier: ^0.5.16 + version: 0.5.16(tailwindcss@3.4.17) arctic: specifier: ^3.1.0 version: 3.1.0 @@ -170,13 +170,13 @@ importers: version: 8.4.7(storybook@8.4.7) '@sveltejs/adapter-node': specifier: ^5.2.9 - version: 5.2.11(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0))) + version: 5.2.11(@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0))) '@sveltejs/enhanced-img': specifier: ^0.4.4 version: 0.4.4(rollup@4.29.1)(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)) '@sveltejs/kit': - specifier: ^2.15.1 - version: 2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)) + specifier: ^2.15.2 + version: 2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)) '@sveltejs/vite-plugin-svelte': specifier: ^5.0.3 version: 5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)) @@ -212,7 +212,7 @@ importers: version: 0.30.1 formsnap: specifier: ^2.0.0 - version: 2.0.0(svelte@5.16.5)(sveltekit-superforms@2.22.1(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(@types/json-schema@7.0.15)(svelte@5.16.5)(typescript@5.7.2)) + version: 2.0.0(svelte@5.16.5)(sveltekit-superforms@2.22.1(@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(@types/json-schema@7.0.15)(svelte@5.16.5)(typescript@5.7.2)) lucide-svelte: specifier: ^0.469.0 version: 0.469.0(svelte@5.16.5) @@ -241,11 +241,11 @@ importers: specifier: ^0.3.28 version: 0.3.28(svelte@5.16.5) sveltekit-flash-message: - specifier: ^2.4.4 - version: 2.4.4(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5) + specifier: ^2.4.5 + version: 2.4.5(@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5) sveltekit-superforms: specifier: ^2.22.1 - version: 2.22.1(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(@types/json-schema@7.0.15)(svelte@5.16.5)(typescript@5.7.2) + version: 2.22.1(@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(@types/json-schema@7.0.15)(svelte@5.16.5)(typescript@5.7.2) tailwind-merge: specifier: ^2.6.0 version: 2.6.0 @@ -2206,8 +2206,8 @@ packages: svelte: ^5.0.0 vite: '>= 5.0.0' - '@sveltejs/kit@2.15.1': - resolution: {integrity: sha512-8t7D3hQHbUDMiaQ2RVnjJJ/+Ur4Fn/tkeySJCsHtX346Q9cp3LAnav8xXdfuqYNJwpUGX0x3BqF1uvbmXQw93A==} + '@sveltejs/kit@2.15.2': + resolution: {integrity: sha512-p208T1kdM6zd8k4YXIUM60pLWQ8dZqehXSiqn4NulXHyHibX53uIAL2xtNL8GjxX2IVPqPRT978MwVYhCKExdQ==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -2238,15 +2238,15 @@ packages: peerDependencies: tailwindcss: '>=3.2.0' - '@tailwindcss/forms@0.5.9': - resolution: {integrity: sha512-tM4XVr2+UVTxXJzey9Twx48c1gcxFStqn1pQz0tRsX8o3DvxhN5oY5pvyAbUx7VTaZxpej4Zzvc6h+1RJBzpIg==} + '@tailwindcss/forms@0.5.10': + resolution: {integrity: sha512-utI1ONF6uf/pPNO68kmN1b8rEwNXv3czukalo8VtJH8ksIkZXr3Q3VYudZLkCsDd4Wku120uF02hYK25XGPorw==} peerDependencies: - tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20' + tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1' - '@tailwindcss/typography@0.5.15': - resolution: {integrity: sha512-AqhlCXl+8grUz8uqExv5OTtgpjuVIwFTSXTrh8y9/pw6q2ek7fJ+Y8ZEVw7EB2DCcuCOtEjf9w3+J3rzts01uA==} + '@tailwindcss/typography@0.5.16': + resolution: {integrity: sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==} peerDependencies: - tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20' + tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' '@testing-library/dom@10.4.0': resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} @@ -4724,8 +4724,8 @@ packages: resolution: {integrity: sha512-sWJRa4qOfRdSORSVw9GhfDEwsbsYsegnDzBevUCF6k/Eis/QqCu9lJ6I0+d/E2wOWCjOhlcJ3+jl/Iur+5mmCw==} engines: {node: '>=10.0.0'} - sveltekit-flash-message@2.4.4: - resolution: {integrity: sha512-CFN03chH/FMEJcBZ/8zKm7RqGee/pwb57Spbbx8QCQPhe7N9ofZHd9iYV2vVy4E9glBo/oQ1IG7VQje6L092wg==} + sveltekit-flash-message@2.4.5: + resolution: {integrity: sha512-CPJwgZbXkPs7Tsl8vK81d6FPqWO4NiuwAkx57zaOIuhDu9wSq0V4rc4TuRtVwWTjOmHwnXClRana+WCXwKHOFQ==} peerDependencies: '@sveltejs/kit': 1.x || 2.x svelte: 3.x || 4.x || >=5.0.0-next.51 @@ -5964,12 +5964,12 @@ snapshots: - debug - supports-color - '@inlang/paraglide-sveltekit@0.15.4(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))': + '@inlang/paraglide-sveltekit@0.15.4(@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))': dependencies: '@inlang/paraglide-js': 1.11.7 '@inlang/paraglide-vite': 1.3.4 '@lix-js/client': 2.2.1 - '@sveltejs/kit': 2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)) + '@sveltejs/kit': 2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)) commander: 12.1.0 dedent: 1.5.1 devalue: 4.3.3 @@ -6851,12 +6851,12 @@ snapshots: dependencies: storybook: 8.4.7 - '@sveltejs/adapter-node@5.2.11(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))': + '@sveltejs/adapter-node@5.2.11(@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))': dependencies: '@rollup/plugin-commonjs': 28.0.2(rollup@4.29.1) '@rollup/plugin-json': 6.1.0(rollup@4.29.1) '@rollup/plugin-node-resolve': 16.0.0(rollup@4.29.1) - '@sveltejs/kit': 2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)) + '@sveltejs/kit': 2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)) rollup: 4.29.1 '@sveltejs/enhanced-img@0.4.4(rollup@4.29.1)(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0))': @@ -6871,7 +6871,7 @@ snapshots: transitivePeerDependencies: - rollup - '@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0))': + '@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0))': dependencies: '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)) '@types/cookie': 0.6.0 @@ -6919,12 +6919,12 @@ snapshots: dependencies: tailwindcss: 3.4.17 - '@tailwindcss/forms@0.5.9(tailwindcss@3.4.17)': + '@tailwindcss/forms@0.5.10(tailwindcss@3.4.17)': dependencies: mini-svg-data-uri: 1.4.4 tailwindcss: 3.4.17 - '@tailwindcss/typography@0.5.15(tailwindcss@3.4.17)': + '@tailwindcss/typography@0.5.16(tailwindcss@3.4.17)': dependencies: lodash.castarray: 4.4.0 lodash.isplainobject: 4.0.6 @@ -8070,11 +8070,11 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 - formsnap@2.0.0(svelte@5.16.5)(sveltekit-superforms@2.22.1(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(@types/json-schema@7.0.15)(svelte@5.16.5)(typescript@5.7.2)): + formsnap@2.0.0(svelte@5.16.5)(sveltekit-superforms@2.22.1(@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(@types/json-schema@7.0.15)(svelte@5.16.5)(typescript@5.7.2)): dependencies: svelte: 5.16.5 svelte-toolbelt: 0.5.0(svelte@5.16.5) - sveltekit-superforms: 2.22.1(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(@types/json-schema@7.0.15)(svelte@5.16.5)(typescript@5.7.2) + sveltekit-superforms: 2.22.1(@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(@types/json-schema@7.0.15)(svelte@5.16.5)(typescript@5.7.2) forwarded@0.2.0: {} @@ -9452,14 +9452,14 @@ snapshots: transitivePeerDependencies: - supports-color - sveltekit-flash-message@2.4.4(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5): + sveltekit-flash-message@2.4.5(@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5): dependencies: - '@sveltejs/kit': 2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)) + '@sveltejs/kit': 2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)) svelte: 5.16.5 - sveltekit-superforms@2.22.1(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(@types/json-schema@7.0.15)(svelte@5.16.5)(typescript@5.7.2): + sveltekit-superforms@2.22.1(@sveltejs/kit@2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(@types/json-schema@7.0.15)(svelte@5.16.5)(typescript@5.7.2): dependencies: - '@sveltejs/kit': 2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)) + '@sveltejs/kit': 2.15.2(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)))(svelte@5.16.5)(vite@6.0.7(@types/node@22.10.5)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.7.0)) devalue: 5.1.1 memoize-weak: 1.0.2 svelte: 5.16.5 diff --git a/src/lib/dtos/settings/profile/update-profile.dto.ts b/src/lib/dtos/settings/profile/update-profile.dto.ts new file mode 100644 index 0000000..45f4732 --- /dev/null +++ b/src/lib/dtos/settings/profile/update-profile.dto.ts @@ -0,0 +1,22 @@ +import { z } from 'zod'; + +const MAX_UPLOAD_SIZE = 1024 * 1024 * 3; // 3MB +const ACCEPTED_FILE_TYPES = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp']; + +export const updateProfileDto = z.object({ + first_name: z + .string() + .trim() + .min(1, { message: 'Must be at least 1 characters' }) + .max(50, { message: 'Must be less than 50 characters' }) + .optional(), + last_name: z + .string() + .trim() + .min(1, { message: 'Must be at least 1 characters' }) + .max(50, { message: 'Must be less than 50 characters' }) + .optional(), + username: z.string().trim().min(3, { message: 'Must be at least 3 characters' }).max(50, { message: 'Must be less than 50 characters' }), +}); + +export type UpdateProfileDto = z.infer; diff --git a/src/lib/server/api/users/dtos/update-user.dto.ts b/src/lib/server/api/users/dtos/update-user.dto.ts index 0ca5123..9111f35 100644 --- a/src/lib/server/api/users/dtos/update-user.dto.ts +++ b/src/lib/server/api/users/dtos/update-user.dto.ts @@ -3,7 +3,9 @@ import { userDto } from './user.dto'; export const updateUserDto = userDto .pick({ - avatar: true + avatar: true, + first_name: true, + last_name: true }) .optional(); diff --git a/src/lib/server/api/users/dtos/user.dto.ts b/src/lib/server/api/users/dtos/user.dto.ts index cb9027d..c9e8faf 100644 --- a/src/lib/server/api/users/dtos/user.dto.ts +++ b/src/lib/server/api/users/dtos/user.dto.ts @@ -6,6 +6,9 @@ const ACCEPTED_FILE_TYPES = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp export const userDto = z.object({ id: z.string(), email: z.string().email(), + first_name: z.string().trim().min(1, { message: 'Must be at least 1 characters' }).max(50, { message: 'Must be less than 50 characters' }), + last_name: z.string().trim().min(1, { message: 'Must be at least 1 characters' }).max(50, { message: 'Must be less than 50 characters' }), + username: z.string().trim().min(3, { message: 'Must be at least 3 characters' }).max(50, { message: 'Must be less than 50 characters' }), avatar: z .instanceof(File) .optional() diff --git a/src/lib/server/api/users/user_roles.repository.ts b/src/lib/server/api/users/user_roles.repository.ts index 051582e..446ca39 100644 --- a/src/lib/server/api/users/user_roles.repository.ts +++ b/src/lib/server/api/users/user_roles.repository.ts @@ -36,4 +36,8 @@ export class UserRolesRepository { async delete(id: string, db = this.drizzle.db) { return db.delete(user_roles_table).where(eq(user_roles_table.id, id)).returning().then(takeFirstOrThrow); } + + async deleteAllByUserId(userId: string, db = this.drizzle.db) { + return db.delete(user_roles_table).where(eq(user_roles_table.user_id, userId)); + } } diff --git a/src/lib/server/api/users/user_roles.service.ts b/src/lib/server/api/users/user_roles.service.ts index 6cadc24..f9c5c5d 100644 --- a/src/lib/server/api/users/user_roles.service.ts +++ b/src/lib/server/api/users/user_roles.service.ts @@ -48,4 +48,13 @@ export class UserRolesService { trx, ); } + + async removeAllRolesFromUser(userId: string, trx: Transaction | null = null) { + if (!trx) { + return this.userRolesRepository.deleteAllByUserId(userId); + } + + return this.userRolesRepository.deleteAllByUserId(userId, trx); + + } } diff --git a/src/lib/server/api/users/users.controller.ts b/src/lib/server/api/users/users.controller.ts index de8f6ae..38cf87e 100644 --- a/src/lib/server/api/users/users.controller.ts +++ b/src/lib/server/api/users/users.controller.ts @@ -12,6 +12,7 @@ import { rateLimit } from '../common/middleware/rate-limit.middleware'; import { changePasswordDto } from '$lib/dtos/settings/password/change-password.dto'; import { StatusCodes } from '$lib/constants/status-codes'; import { SessionsService } from '../iam/sessions/sessions.service'; +import { updateProfileDto } from '$lib/dtos/settings/profile/update-profile.dto'; @injectable() export class UsersController extends Controller { @@ -67,6 +68,18 @@ export class UsersController extends Controller { console.error('Error updating password', error); return c.json({ error: 'Unable to update password' }, StatusCodes.INTERNAL_SERVER_ERROR); } + }) + .put('/me/profile', authState('session'), zValidator('json', updateProfileDto), async (c) => { + c.var.logger.debug(`Update profile: ${JSON.stringify(c.req.valid('json'))}`); + await this.usersService.update(c.var.session.userId, c.req.valid('json')); + const user = await this.usersRepository.findOneByIdOrThrow(c.var.session.userId); + return c.json(user); + }) + .delete('/me', authState('session'), async (c) => { + await this.usersService.delete(c.var.session.userId); + await this.sessionsService.invalidateSession(''); + this.sessionsService.deleteSessionCookie(); + return c.json({ message: 'User deleted' }); }); } } diff --git a/src/lib/server/api/users/users.repository.ts b/src/lib/server/api/users/users.repository.ts index ac795f4..8760e17 100644 --- a/src/lib/server/api/users/users.repository.ts +++ b/src/lib/server/api/users/users.repository.ts @@ -8,7 +8,7 @@ import { DrizzleRepository } from '../common/factories/drizzle-repository.factor /* -------------------------------------------------------------------------- */ /* Types */ /* -------------------------------------------------------------------------- */ -type Create = Pick, 'avatar' | 'email' | 'username'>; +type Create = Pick, 'avatar' | 'email' | 'username' | 'first_name' | 'last_name'>; type Update = Partial; /* -------------------------------------------------------------------------- */ @@ -38,7 +38,9 @@ export class UsersRepository extends DrizzleRepository { async findOneByIdOrThrow(id: string, db = this.drizzle.db) { const user = await this.findOneById(id, db); - if (!user) throw NotFound('User not found'); + if (!user) { + throw NotFound('User not found'); + } return user; } diff --git a/src/lib/server/api/users/users.service.ts b/src/lib/server/api/users/users.service.ts index 17bfee3..114d274 100644 --- a/src/lib/server/api/users/users.service.ts +++ b/src/lib/server/api/users/users.service.ts @@ -9,27 +9,33 @@ import { UsersRepository } from './users.repository'; import { UserRolesService } from './user_roles.service'; import { RoleName } from '../roles/tables/roles.table'; import { BadRequest } from '../common/utils/exceptions'; +import { LoggerService } from '../common/services/logger.service'; +import type { UpdateProfileDto } from '$lib/dtos/settings/profile/update-profile.dto'; @injectable() export class UsersService { constructor( private drizzleService = inject(DrizzleService), private credentialsRepository = inject(CredentialsRepository), + private loggerService = inject(LoggerService), private usersRepository = inject(UsersRepository), private userRoleService = inject(UserRolesService), private storageService = inject(StorageService), private tokenService = inject(TokensService) ) {} - async update(userId: string, updateUserDto: UpdateUserDto) { + async update(userId: string, updateUserDto: UpdateProfileDto) { + let key: string | null = null; if (updateUserDto?.avatar) { - const { key } = await this.storageService.upload({ file: updateUserDto.avatar }); - await this.usersRepository.update(userId, { avatar: key }); + const response = await this.storageService.upload({ file: updateUserDto.avatar }); + key = response?.key; } + this.loggerService.log.info(`Updating user ${userId}, with avatar: ${key}, first_name: ${updateUserDto?.first_name}, last_name: ${updateUserDto?.last_name}`); + await this.usersRepository.update(userId, { avatar: key, first_name: updateUserDto?.first_name ?? '', last_name: updateUserDto?.last_name ?? '' }); } async createEmail(email: string) { - return this.usersRepository.create({ avatar: null, email, username: email }); + return this.usersRepository.create({ avatar: null, email, username: email, first_name: '', last_name: '' }); } async createWithPassword(username: string, password: string, email?: string | undefined) { @@ -46,7 +52,7 @@ export class UsersService { return await this.drizzleService.db.transaction(async (trx) => { const createdUser = await this.usersRepository.create( - { username, email: email || '', avatar: null }, + { username, email: email || '', avatar: null, first_name: '', last_name: '' }, trx, ); @@ -104,4 +110,12 @@ export class UsersService { const { password } = data; return this.tokenService.verifyHashedToken(password, credential.secret_data); } + + async delete(userId: string) { + return await this.drizzleService.db.transaction(async (trx) => { + const deletedUser = await this.usersRepository.delete(userId, trx); + // await this.userRoleService.removeAllRolesFromUser(userId, trx); + return deletedUser; + }); + } } diff --git a/src/routes/(app)/(protected)/settings/+layout.svelte b/src/routes/(app)/(protected)/settings/+layout.svelte index 08c87e7..dbbecb2 100644 --- a/src/routes/(app)/(protected)/settings/+layout.svelte +++ b/src/routes/(app)/(protected)/settings/+layout.svelte @@ -1,5 +1,5 @@ + + diff --git a/src/routes/(app)/(protected)/settings/update-profile-card.svelte b/src/routes/(app)/(protected)/settings/update-profile-card.svelte new file mode 100644 index 0000000..7239a9b --- /dev/null +++ b/src/routes/(app)/(protected)/settings/update-profile-card.svelte @@ -0,0 +1,83 @@ + + + + Acme | Settings + + + + + Update Profile + + +
+

Your Profile

+
+ + + {#snippet children({ props })} + Username + + {/snippet} + + + + + + + {#snippet children({ props })} + First Name + + {/snippet} + + + + + + + {#snippet children({ props })} + Last Name + + {/snippet} + + + + + +
+
+ + updateProfileFormSubmit()}>Update Profile + +