diff --git a/.env.example b/.env.example index 7b3b671..a539bcd 100644 --- a/.env.example +++ b/.env.example @@ -18,6 +18,12 @@ ADMIN_PASSWORD= TWO_FACTOR_TIMEOUT=300000 +# OAuth +GITHUB_CLIENT_ID="" +GITHUB_CLIENT_SECRET="" +GOOGLE_CLIENT_ID="" +GOOGLE_CLIENT_SECRET="" + # Public PUBLIC_SITE_NAME='Bored Game' diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2af8905 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License Copyright (c) 2024 Bradley Shellnut + +Permission is hereby granted, +free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice +(including the next paragraph) shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO +EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/drizzle.config.ts b/drizzle.config.ts index b90a261..e9ec449 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -1,5 +1,5 @@ import 'dotenv/config' -import env from '$lib/server/api/common/env' +import env from './src/lib/server/api/common/env' import { defineConfig } from 'drizzle-kit' export default defineConfig({ diff --git a/package.json b/package.json index e04cff2..c56b854 100644 --- a/package.json +++ b/package.json @@ -27,19 +27,20 @@ "@faker-js/faker": "^8.4.1", "@melt-ui/pp": "^0.3.2", "@melt-ui/svelte": "^0.83.0", - "@playwright/test": "^1.47.0", - "@sveltejs/adapter-auto": "^3.2.4", - "@sveltejs/enhanced-img": "^0.3.4", - "@sveltejs/kit": "^2.5.26", + "@playwright/test": "^1.47.2", + "@sveltejs/adapter-auto": "^3.2.5", + "@sveltejs/enhanced-img": "^0.3.8", + "@sveltejs/kit": "^2.5.28", "@sveltejs/vite-plugin-svelte": "^3.1.2", "@types/cookie": "^0.6.0", "@types/node": "^20.16.5", - "@types/pg": "^8.11.9", + "@types/pg": "^8.11.10", "@typescript-eslint/eslint-plugin": "^7.18.0", "@typescript-eslint/parser": "^7.18.0", + "arctic": "^1.9.2", "autoprefixer": "^10.4.20", "drizzle-kit": "^0.23.2", - "eslint": "^8.57.0", + "eslint": "^8.57.1", "eslint-config-prettier": "^9.1.0", "eslint-plugin-svelte": "2.36.0-next.13", "just-clone": "^6.2.0", @@ -47,13 +48,12 @@ "lucia": "3.2.0", "lucide-svelte": "^0.408.0", "nodemailer": "^6.9.15", - "postcss": "^8.4.45", + "postcss": "^8.4.47", "postcss-import": "^16.1.0", "postcss-load-config": "^5.1.0", "postcss-preset-env": "^9.6.0", "prettier": "^3.3.3", "prettier-plugin-svelte": "^3.2.6", - "sass": "^1.78.0", "satori": "^0.10.14", "satori-html": "^0.3.2", "svelte": "5.0.0-next.175", @@ -64,13 +64,13 @@ "svelte-sequential-preprocessor": "^2.0.1", "sveltekit-flash-message": "^2.4.4", "sveltekit-rate-limiter": "^0.5.2", - "sveltekit-superforms": "^2.17.0", - "tailwindcss": "^3.4.11", + "sveltekit-superforms": "^2.19.0", + "tailwindcss": "^3.4.12", "ts-node": "^10.9.2", "tslib": "^2.7.0", "tsx": "^4.19.1", "typescript": "^5.6.2", - "vite": "^5.4.4", + "vite": "^5.4.7", "vitest": "^1.6.0", "zod": "^3.23.8" }, @@ -88,14 +88,13 @@ "@neondatabase/serverless": "^0.9.5", "@paralleldrive/cuid2": "^2.2.2", "@resvg/resvg-js": "^2.6.2", - "@sveltejs/adapter-node": "^5.2.2", - "@sveltejs/adapter-vercel": "^5.4.3", + "@sveltejs/adapter-node": "^5.2.4", + "@sveltejs/adapter-vercel": "^5.4.4", "@types/feather-icons": "^4.29.4", "@vercel/og": "^0.5.20", - "arctic": "^1.9.2", - "bits-ui": "^0.21.13", + "bits-ui": "^0.21.15", "boardgamegeekclient": "^1.9.1", - "bullmq": "^5.13.0", + "bullmq": "^5.13.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "cookie": "^0.6.0", @@ -106,7 +105,7 @@ "feather-icons": "^4.29.2", "formsnap": "^1.0.1", "handlebars": "^4.7.8", - "hono": "^4.6.1", + "hono": "^4.6.2", "hono-rate-limiter": "^0.4.0", "html-entities": "^2.5.2", "iconify-icon": "^2.1.0", @@ -116,7 +115,7 @@ "loader": "^2.1.1", "open-props": "^1.7.6", "oslo": "^1.2.1", - "pg": "^8.12.0", + "pg": "^8.13.0", "postgres": "^3.4.4", "qrcode": "^1.5.4", "radix-svelte": "^0.9.0", @@ -129,5 +128,6 @@ "tailwindcss-animate": "^1.0.7", "tsyringe": "^4.8.0", "zod-to-json-schema": "^3.23.3" - } -} + }, + "license": "MIT" +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1bcf7f5..b13a638 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,13 +13,13 @@ importers: version: 5.1.0 '@hono/swagger-ui': specifier: ^0.4.1 - version: 0.4.1(hono@4.6.1) + version: 0.4.1(hono@4.6.2) '@hono/zod-openapi': specifier: ^0.15.3 - version: 0.15.3(hono@4.6.1)(zod@3.23.8) + version: 0.15.3(hono@4.6.2)(zod@3.23.8) '@hono/zod-validator': specifier: ^0.2.2 - version: 0.2.2(hono@4.6.1)(zod@3.23.8) + version: 0.2.2(hono@4.6.2)(zod@3.23.8) '@iconify-icons/line-md': specifier: ^1.2.30 version: 1.2.30 @@ -31,7 +31,7 @@ importers: version: 3.5.5 '@lucia-auth/adapter-drizzle': specifier: ^1.1.0 - version: 1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4))(lucia@3.2.0) + version: 1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4))(lucia@3.2.0) '@lukeed/uuid': specifier: ^2.0.1 version: 2.0.1 @@ -45,29 +45,26 @@ importers: specifier: ^2.6.2 version: 2.6.2 '@sveltejs/adapter-node': - specifier: ^5.2.2 - version: 5.2.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))) + specifier: ^5.2.4 + version: 5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) '@sveltejs/adapter-vercel': - specifier: ^5.4.3 - version: 5.4.3(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))) + specifier: ^5.4.4 + version: 5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) '@types/feather-icons': specifier: ^4.29.4 version: 4.29.4 '@vercel/og': specifier: ^0.5.20 version: 0.5.20 - arctic: - specifier: ^1.9.2 - version: 1.9.2 bits-ui: - specifier: ^0.21.13 - version: 0.21.13(svelte@5.0.0-next.175) + specifier: ^0.21.15 + version: 0.21.15(svelte@5.0.0-next.175) boardgamegeekclient: specifier: ^1.9.1 version: 1.9.1 bullmq: - specifier: ^5.13.0 - version: 5.13.0 + specifier: ^5.13.2 + version: 5.13.2 class-variance-authority: specifier: ^0.7.0 version: 0.7.0 @@ -85,25 +82,25 @@ importers: version: 11.0.6 drizzle-orm: specifier: ^0.32.2 - version: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4) + version: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4) drizzle-zod: specifier: ^0.5.1 - version: 0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4))(zod@3.23.8) + version: 0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4))(zod@3.23.8) feather-icons: specifier: ^4.29.2 version: 4.29.2 formsnap: specifier: ^1.0.1 - version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)) + version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)) handlebars: specifier: ^4.7.8 version: 4.7.8 hono: - specifier: ^4.6.1 - version: 4.6.1 + specifier: ^4.6.2 + version: 4.6.2 hono-rate-limiter: specifier: ^0.4.0 - version: 0.4.0(hono@4.6.1) + version: 0.4.0(hono@4.6.2) html-entities: specifier: ^2.5.2 version: 2.5.2 @@ -129,8 +126,8 @@ importers: specifier: ^1.2.1 version: 1.2.1 pg: - specifier: ^8.12.0 - version: 8.12.0 + specifier: ^8.13.0 + version: 8.13.0 postgres: specifier: ^3.4.4 version: 3.4.4 @@ -157,10 +154,10 @@ importers: version: 2.5.2 tailwind-variants: specifier: ^0.2.1 - version: 0.2.1(tailwindcss@3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))) + version: 0.2.1(tailwindcss@3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))) tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))) + version: 1.0.7(tailwindcss@3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))) tsyringe: specifier: ^4.8.0 version: 4.8.0 @@ -181,20 +178,20 @@ importers: specifier: ^0.83.0 version: 0.83.0(svelte@5.0.0-next.175) '@playwright/test': - specifier: ^1.47.0 - version: 1.47.0 + specifier: ^1.47.2 + version: 1.47.2 '@sveltejs/adapter-auto': - specifier: ^3.2.4 - version: 3.2.4(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))) + specifier: ^3.2.5 + version: 3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) '@sveltejs/enhanced-img': - specifier: ^0.3.4 - version: 0.3.4(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + specifier: ^0.3.8 + version: 0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@sveltejs/kit': - specifier: ^2.5.26 - version: 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + specifier: ^2.5.28 + version: 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@sveltejs/vite-plugin-svelte': specifier: ^3.1.2 - version: 3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + version: 3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@types/cookie': specifier: ^0.6.0 version: 0.6.0 @@ -202,29 +199,32 @@ importers: specifier: ^20.16.5 version: 20.16.5 '@types/pg': - specifier: ^8.11.9 - version: 8.11.9 + specifier: ^8.11.10 + version: 8.11.10 '@typescript-eslint/eslint-plugin': specifier: ^7.18.0 - version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0)(typescript@5.6.2) + version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2) '@typescript-eslint/parser': specifier: ^7.18.0 - version: 7.18.0(eslint@8.57.0)(typescript@5.6.2) + version: 7.18.0(eslint@8.57.1)(typescript@5.6.2) + arctic: + specifier: ^1.9.2 + version: 1.9.2 autoprefixer: specifier: ^10.4.20 - version: 10.4.20(postcss@8.4.45) + version: 10.4.20(postcss@8.4.47) drizzle-kit: specifier: ^0.23.2 version: 0.23.2 eslint: - specifier: ^8.57.0 - version: 8.57.0 + specifier: ^8.57.1 + version: 8.57.1 eslint-config-prettier: specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.0) + version: 9.1.0(eslint@8.57.1) eslint-plugin-svelte: specifier: 2.36.0-next.13 - version: 2.36.0-next.13(eslint@8.57.0)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + version: 2.36.0-next.13(eslint@8.57.1)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) just-clone: specifier: ^6.2.0 version: 6.2.0 @@ -241,26 +241,23 @@ importers: specifier: ^6.9.15 version: 6.9.15 postcss: - specifier: ^8.4.45 - version: 8.4.45 + specifier: ^8.4.47 + version: 8.4.47 postcss-import: specifier: ^16.1.0 - version: 16.1.0(postcss@8.4.45) + version: 16.1.0(postcss@8.4.47) postcss-load-config: specifier: ^5.1.0 - version: 5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1) + version: 5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1) postcss-preset-env: specifier: ^9.6.0 - version: 9.6.0(postcss@8.4.45) + version: 9.6.0(postcss@8.4.47) prettier: specifier: ^3.3.3 version: 3.3.3 prettier-plugin-svelte: specifier: ^3.2.6 version: 3.2.6(prettier@3.3.3)(svelte@5.0.0-next.175) - sass: - specifier: ^1.78.0 - version: 1.78.0 satori: specifier: ^0.10.14 version: 0.10.14 @@ -272,7 +269,7 @@ importers: version: 5.0.0-next.175 svelte-check: specifier: ^3.8.6 - version: 3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175) + version: 3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175) svelte-headless-table: specifier: ^0.18.2 version: 0.18.2(svelte@5.0.0-next.175) @@ -281,22 +278,22 @@ importers: version: 3.1.4(svelte@5.0.0-next.175)(typescript@5.6.2) svelte-preprocess: specifier: ^6.0.2 - version: 6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2) + version: 6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175)(typescript@5.6.2) svelte-sequential-preprocessor: specifier: ^2.0.1 version: 2.0.1 sveltekit-flash-message: specifier: ^2.4.4 - version: 2.4.4(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175) + version: 2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175) sveltekit-rate-limiter: specifier: ^0.5.2 - version: 0.5.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))) + version: 0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) sveltekit-superforms: - specifier: ^2.17.0 - version: 2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175) + specifier: ^2.19.0 + version: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) tailwindcss: - specifier: ^3.4.11 - version: 3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + specifier: ^3.4.12 + version: 3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@20.16.5)(typescript@5.6.2) @@ -310,11 +307,11 @@ importers: specifier: ^5.6.2 version: 5.6.2 vite: - specifier: ^5.4.4 - version: 5.4.4(@types/node@20.16.5)(sass@1.78.0) + specifier: ^5.4.7 + version: 5.4.7(@types/node@20.16.5)(sass@1.79.1) vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@20.16.5)(sass@1.78.0) + version: 1.6.0(@types/node@20.16.5)(sass@1.79.1) zod: specifier: ^3.23.8 version: 3.23.8 @@ -329,11 +326,11 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@ark/schema@0.2.0': - resolution: {integrity: sha512-IkNWCSHdjaoemMXpps4uFHEAQzwJPbTAS8K2vcQpk90sa+eNBuPSVyB/81/Qyl1VYW0iX3ceGC5NL/OznQv1jg==} + '@ark/schema@0.10.0': + resolution: {integrity: sha512-zpfXwWLOzj9aUK+dXQ6aleJAOgle4/WrHDop5CMX2M88dFQ85NdH8O0v0pvMAQnfFcaQAZ/nVDYLlBJsFc09XA==} - '@ark/util@0.1.0': - resolution: {integrity: sha512-qCLYICQoCy3kEKDVwirQp8qvxhY7NJd8BhhoHaj1l3wCFAk9NUbcDsxAkPStZEMdPI/d7NcbGJe8SWZuRG2twQ==} + '@ark/util@0.10.0': + resolution: {integrity: sha512-uK+9VU5doGMYOoOZVE+XaSs1vYACoaEJdrDkuBx26S4X7y3ChyKsPnIg/9pIw2vUySph1GkAXbvBnfVE2GmXgQ==} '@asteasolutions/zod-to-openapi@7.1.1': resolution: {integrity: sha512-lF0d1gAc0lYLO9/BAGivwTwE2Sh9h6CHuDcbk5KnGBfIuAsAkDC+Fdat4dkQY3CS/zUWKHRmFEma0B7X132Ymw==} @@ -1225,8 +1222,8 @@ packages: resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@eslint/js@8.57.0': - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} + '@eslint/js@8.57.1': + resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} '@exodus/schemasafe@1.3.0': @@ -1276,8 +1273,8 @@ packages: hono: '>=3.9.0' zod: ^3.19.1 - '@humanwhocodes/config-array@0.11.14': - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + '@humanwhocodes/config-array@0.13.0': + resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} deprecated: Use @eslint/config-array instead @@ -1706,8 +1703,8 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@playwright/test@1.47.0': - resolution: {integrity: sha512-SgAdlSwYVpToI4e/IH19IHHWvoijAYH5hu2MWSXptRypLSnzj51PcGD+rsOXFayde4P9ZLi+loXVwArg6IUkCA==} + '@playwright/test@1.47.2': + resolution: {integrity: sha512-jTXRsoSPONAs8Za9QEQdyjFn+0ZQFjCiIztAIF6bi1HqhBzG9Ma7g1WotyiGqFSBRZjIEqMdT8RUlbk1QVhzCQ==} engines: {node: '>=18'} hasBin: true @@ -1941,29 +1938,29 @@ packages: '@sodaru/yup-to-json-schema@2.0.1': resolution: {integrity: sha512-lWb0Wiz8KZ9ip/dY1eUqt7fhTPmL24p6Hmv5Fd9pzlzAdw/YNcWZr+tiCT4oZ4Zyxzi9+1X4zv82o7jYvcFxYA==} - '@sveltejs/adapter-auto@3.2.4': - resolution: {integrity: sha512-a64AKYbfTUrVwU0xslzv1Jf3M8bj0IwhptaXmhgIkjXspBXhD0od9JiItQHchijpLMGdEDcYBlvqySkEawv6mQ==} + '@sveltejs/adapter-auto@3.2.5': + resolution: {integrity: sha512-27LR+uKccZ62lgq4N/hvyU2G+hTP9fxWEAfnZcl70HnyfAjMSsGk1z/SjAPXNCD1mVJIE7IFu3TQ8cQ/UH3c0A==} peerDependencies: '@sveltejs/kit': ^2.0.0 - '@sveltejs/adapter-node@5.2.2': - resolution: {integrity: sha512-BCX4zP0cf86TXpmvLQTnnT/tp7P12UMezf+5LwljP1MJC1fFzn9XOXpAHQCyP+pyHGy2K7p5gY0LyLcZFAL02w==} + '@sveltejs/adapter-node@5.2.4': + resolution: {integrity: sha512-L9Kngx1ce2SMCbyGBbRaJovl5lzdwH650SzOa50txAAssMfWLj2f8yPsA2eCX8EhT6AxD4RHLNrVa5W8VUYz8w==} peerDependencies: '@sveltejs/kit': ^2.4.0 - '@sveltejs/adapter-vercel@5.4.3': - resolution: {integrity: sha512-srZBkMpeaa7lflO1ZGdKTW3jWHscE9rdAkyxgRlVMVyugjcPOZ3dcpEfpoM4wtVCbpEOdHniWqQR9yL+zs4ybA==} + '@sveltejs/adapter-vercel@5.4.4': + resolution: {integrity: sha512-KORoxxqB2H5DrxpCHc9Yfijcgvmoaaz6G6eKHEg9fRlTsujJkxN26C0x4YlcgxqDU4dLIi1wfSLHpuZD0E4Irg==} peerDependencies: '@sveltejs/kit': ^2.4.0 - '@sveltejs/enhanced-img@0.3.4': - resolution: {integrity: sha512-eX+ob5uWr0bTLMKeG9nhhM84aR88hqiLiyEfWZPX7ijhk/wlmYSUX9nOiaVHh2ct1U+Ju9Hhb90Copw+ZNOB8w==} + '@sveltejs/enhanced-img@0.3.8': + resolution: {integrity: sha512-n66u46ZeqHltiTm0BEjWptYmCrCY0EltEEvakmC7d5o5ZejDbOvOWm914mebbRKaP2Bezv65TNCod/wqvw/0KA==} peerDependencies: svelte: ^4.0.0 || ^5.0.0-next.0 vite: '>= 5.0.0' - '@sveltejs/kit@2.5.26': - resolution: {integrity: sha512-8l1JTIM2L+bS8ebq1E+nGjv/YSKSnD9Q19bYIUkc41vaEG2JjVUx6ikvPIJv2hkQAuqJLzoPrXlKk4KcyWOv3Q==} + '@sveltejs/kit@2.5.28': + resolution: {integrity: sha512-/O7pvFGBsQPcFa9UrW8eUC5uHTOXLsUp3SN0dY6YmRAL9nfPSrJsSJk//j5vMpinSshzUjteAFcfQTU+04Ka1w==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -2019,12 +2016,12 @@ packages: '@types/node@20.16.5': resolution: {integrity: sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==} + '@types/pg@8.11.10': + resolution: {integrity: sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==} + '@types/pg@8.11.6': resolution: {integrity: sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ==} - '@types/pg@8.11.9': - resolution: {integrity: sha512-M4mYeJZRBD9lCBCGa72F44uKSV9eJrAFfjlPJagdA6pgIr2OPJULFB7nqnZzOdqXG0qzHlgtZKzTdIgbmHitSg==} - '@types/pug@2.0.10': resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==} @@ -2034,6 +2031,22 @@ packages: '@types/validator@13.12.1': resolution: {integrity: sha512-w0URwf7BQb0rD/EuiG12KP0bailHKHP5YVviJG9zw3ykAokL0TuxU2TUqMB7EwZ59bDHYdeTIvjI5m0S7qHfOA==} + '@typeschema/class-validator@0.2.0': + resolution: {integrity: sha512-zq0qeflVu1Z6D0ttkqAWZMtxJeNEQ70yo/025sV0jujiOOgQx38JXrky77nSWWPp2E1KIMtgkToQbkzkXyW5yg==} + peerDependencies: + class-validator: ^0.14.1 + peerDependenciesMeta: + class-validator: + optional: true + + '@typeschema/core@0.14.0': + resolution: {integrity: sha512-Ia6PtZHcL3KqsAWXjMi5xIyZ7XMH4aSnOQes8mfMLx+wGFGtGRNlwe6Y7cYvX+WfNK67OL0/HSe9t8QDygV0/w==} + peerDependencies: + '@types/json-schema': ^7.0.15 + peerDependenciesMeta: + '@types/json-schema': + optional: true + '@typescript-eslint/eslint-plugin@7.18.0': resolution: {integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==} engines: {node: ^18.18.0 || >=20.0.0} @@ -2215,8 +2228,8 @@ packages: aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - arktype@2.0.0-beta.0: - resolution: {integrity: sha512-fE3ssMiXjr/bLqFPzlDhRlXngdyHQreu7p7i8+dtcY1CA+f8WrVUcue6JxywhnqEJXPG4HOcIwQcC+q4VfeUMQ==} + arktype@2.0.0-rc.8: + resolution: {integrity: sha512-ByrqjptsavUCUL9ptts6BUL2LCNkVZyniOdaBw76dlBQ6gYIhYSeycuuj4gRFwcAafszOnAPD2fAqHK7bbo/Zw==} array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} @@ -2256,8 +2269,8 @@ packages: bindings@1.5.0: resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} - bits-ui@0.21.13: - resolution: {integrity: sha512-7nmOh6Ig7ND4DXZHv1FhNsY9yUGrad0+mf3tc4YN//3MgnJT1LnHtk4HZAKgmxCOe7txSX7/39LtYHbkrXokAQ==} + bits-ui@0.21.15: + resolution: {integrity: sha512-+m5WSpJnFdCcNdXSTIVC1WYBozipO03qRh03GFWgrdxoHiolCfwW71EYG4LPCWYPG6KcTZV0Cj6iHSiZ7cdKdg==} peerDependencies: svelte: ^4.0.0 || ^5.0.0-next.118 @@ -2295,8 +2308,8 @@ packages: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} - bullmq@5.13.0: - resolution: {integrity: sha512-rE7v3jMZZGsEhfMhLZwADwuHdqJPTTGHBM8C+SpxF9GzyZ+7pvC80EP5bOZJPPRzbmyhvIPJCVd0bchUZiQF+w==} + bullmq@5.13.2: + resolution: {integrity: sha512-McGE8k3mrCvdUHdU0sHkTKDS1xr4pff+hbEKBY51wk5S6Za0gkuejYA620VQTo3Zz37E/NVWMgumwiXPQ3yZcA==} bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} @@ -2347,10 +2360,17 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + chokidar@4.0.0: + resolution: {integrity: sha512-mxIojEAQcuEvT/lyXq+jf/3cO/KoA6z4CeNDGGevTybECPOMFCnQy3OPahluUkbqgPNGw5Bi78UC7Po6Lhy+NA==} + engines: {node: '>= 14.16.0'} + chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} + class-validator@0.14.1: + resolution: {integrity: sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==} + class-variance-authority@0.7.0: resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==} @@ -2787,8 +2807,8 @@ packages: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} + eslint@8.57.1: + resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true @@ -3043,9 +3063,9 @@ packages: peerDependencies: hono: ^4.1.1 - hono@4.6.1: - resolution: {integrity: sha512-6NGwvttY1+HAFii08VYiEKI6ETPAFbpLntpm2M/MogEsAFWdZV74UNT+2M4bmqX90cIQhjlpBSP+tO+CfB0uww==} - engines: {node: '>=16.0.0'} + hono@4.6.2: + resolution: {integrity: sha512-v+39817TgAhetmHUEli8O0uHDmxp2Up3DnhS4oUZXOl5IQ9np9tYtldd42e5zgdLVS0wsOoXQNZ6mx+BGmEvCA==} + engines: {node: '>=16.9.0'} html-entities@2.5.2: resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} @@ -3219,6 +3239,9 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + libphonenumber-js@1.11.8: + resolution: {integrity: sha512-0fv/YKpJBAgXKy0kaS3fnqoUVN8901vUYAKIGD/MWZaDfhJt1nZjPL3ZzdZBt/G8G8Hw2J1xOIrXWdNHFHPAvg==} + lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} @@ -3616,8 +3639,8 @@ packages: pg-cloudflare@1.1.1: resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==} - pg-connection-string@2.6.4: - resolution: {integrity: sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==} + pg-connection-string@2.7.0: + resolution: {integrity: sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==} pg-int8@1.0.1: resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} @@ -3627,14 +3650,17 @@ packages: resolution: {integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==} engines: {node: '>=4'} - pg-pool@3.6.2: - resolution: {integrity: sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==} + pg-pool@3.7.0: + resolution: {integrity: sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g==} peerDependencies: pg: '>=8.0' pg-protocol@1.6.1: resolution: {integrity: sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==} + pg-protocol@1.7.0: + resolution: {integrity: sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==} + pg-types@2.2.0: resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} engines: {node: '>=4'} @@ -3643,8 +3669,8 @@ packages: resolution: {integrity: sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==} engines: {node: '>=10'} - pg@8.12.0: - resolution: {integrity: sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ==} + pg@8.13.0: + resolution: {integrity: sha512-34wkUTh3SxTClfoHB3pQ7bIMvw9dpFU1audQQeZG837fmHfHpr14n/AELVDoOYVDW2h5RDWU78tFjkD+erSBsw==} engines: {node: '>= 8.0.0'} peerDependencies: pg-native: '>=3.0.1' @@ -3673,13 +3699,13 @@ packages: pkg-types@1.2.0: resolution: {integrity: sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==} - playwright-core@1.47.0: - resolution: {integrity: sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg==} + playwright-core@1.47.2: + resolution: {integrity: sha512-3JvMfF+9LJfe16l7AbSmU555PaTl2tPyQsVInqm3id16pdDfvZ8TTZ/pyzmkbDrZTQefyzU7AIHlZqQnxpqHVQ==} engines: {node: '>=18'} hasBin: true - playwright@1.47.0: - resolution: {integrity: sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww==} + playwright@1.47.2: + resolution: {integrity: sha512-nx1cLMmQWqmA3UsnjaaokyoUpdVaaDhJhMoxX2qj3McpjnsqFHs516QAKYhqHAgOP+oCFTEOCOAaD1RgD/RQfA==} engines: {node: '>=18'} hasBin: true @@ -3922,8 +3948,8 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.4.45: - resolution: {integrity: sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==} + postcss@8.4.47: + resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} engines: {node: ^10 || ^12 || >=14} postgres-array@2.0.0: @@ -4041,6 +4067,10 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + readdirp@4.0.1: + resolution: {integrity: sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==} + engines: {node: '>= 14.16.0'} + redis-errors@1.2.0: resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} engines: {node: '>=4'} @@ -4115,8 +4145,8 @@ packages: sander@0.5.1: resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==} - sass@1.78.0: - resolution: {integrity: sha512-AaIqGSrjo5lA2Yg7RvFZrlXDBCp3nV4XP73GrLGvdRWWwk+8H3l0SDvq/5bA4eF+0RFPLuWUk3E+P1U/YqnpsQ==} + sass@1.79.1: + resolution: {integrity: sha512-+mA7svoNKeL0DiJqZGeR/ZGUu8he4I8o3jyUcOFyo4eBJrwNgIMmAEwCMo/N2Y3wdjOBcRzoNxZIOtrtMX8EXg==} engines: {node: '>=14.0.0'} hasBin: true @@ -4207,8 +4237,8 @@ packages: resolution: {integrity: sha512-o7npfeJE6wi6J9l0/5LKshFzZ2rMatRiCDwYeDQaOzqdzRJwALhX7mk/A/ecg6wjMu7wdZbmXfD2S/vpOg0bdQ==} hasBin: true - source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} source-map-support@0.5.21: @@ -4453,8 +4483,8 @@ packages: peerDependencies: '@sveltejs/kit': 1.x || 2.x - sveltekit-superforms@2.17.0: - resolution: {integrity: sha512-QrX8pkcmE0XoeVU42zMhsah4FoDrgtPc/4cZEr38rDlgU+DE0xNc5J0E7z1456sUJNbFjaB0+HZwwAkX0vYqaA==} + sveltekit-superforms@2.19.0: + resolution: {integrity: sha512-WJmdYf8WpuDkl6zxdRP72R+wDefx1OhIQYKdsIQqNkFntNq0/BUrkMdUr1i7d/FbX0gS1A9GRflCx3WiYQlAXg==} peerDependencies: '@sveltejs/kit': 1.x || 2.x svelte: 3.x || 4.x || >=5.0.0-next.51 @@ -4476,8 +4506,8 @@ packages: peerDependencies: tailwindcss: '>=3.0.0 || insiders' - tailwindcss@3.4.11: - resolution: {integrity: sha512-qhEuBcLemjSJk5ajccN9xJFtM/h0AVCPaA6C92jNP+M2J8kX+eMJHI7R2HFKUvvAsMpcfLILMCFYSeDwpMmlUg==} + tailwindcss@3.4.12: + resolution: {integrity: sha512-Htf/gHj2+soPb9UayUNci/Ja3d8pTmu9ONTfh4QY8r3MATTZOzmv6UYWF7ZwikEIC8okpfqmGqrmDehua8mF8w==} engines: {node: '>=14.0.0'} hasBin: true @@ -4679,8 +4709,8 @@ packages: engines: {node: ^18.0.0 || >=20.0.0} hasBin: true - vite@5.4.4: - resolution: {integrity: sha512-RHFCkULitycHVTtelJ6jQLd+KSAAzOgEYorV32R2q++M6COBjKJR6BxqClwp5sf0XaBDjVMuJ9wnNfyAJwjMkA==} + vite@5.4.7: + resolution: {integrity: sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -4852,12 +4882,12 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@ark/schema@0.2.0': + '@ark/schema@0.10.0': dependencies: - '@ark/util': 0.1.0 + '@ark/util': 0.10.0 optional: true - '@ark/util@0.1.0': + '@ark/util@0.10.0': optional: true '@asteasolutions/zod-to-openapi@7.1.1(zod@3.23.8)': @@ -4939,201 +4969,201 @@ snapshots: '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-cascade-layers@4.0.6(postcss@8.4.45)': + '@csstools/postcss-cascade-layers@4.0.6(postcss@8.4.47)': dependencies: '@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.1.2) - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - '@csstools/postcss-color-function@3.0.19(postcss@8.4.45)': + '@csstools/postcss-color-function@3.0.19(postcss@8.4.47)': dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-color-mix-function@2.0.19(postcss@8.4.45)': + '@csstools/postcss-color-mix-function@2.0.19(postcss@8.4.47)': dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-content-alt-text@1.0.0(postcss@8.4.45)': + '@csstools/postcss-content-alt-text@1.0.0(postcss@8.4.47)': dependencies: '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-exponential-functions@1.0.9(postcss@8.4.45)': + '@csstools/postcss-exponential-functions@1.0.9(postcss@8.4.47)': dependencies: '@csstools/css-calc': 1.2.4(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-font-format-keywords@3.0.2(postcss@8.4.45)': + '@csstools/postcss-font-format-keywords@3.0.2(postcss@8.4.47)': dependencies: - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 postcss-value-parser: 4.2.0 - '@csstools/postcss-gamut-mapping@1.0.11(postcss@8.4.45)': + '@csstools/postcss-gamut-mapping@1.0.11(postcss@8.4.47)': dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-gradients-interpolation-method@4.0.20(postcss@8.4.45)': + '@csstools/postcss-gradients-interpolation-method@4.0.20(postcss@8.4.47)': dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-hwb-function@3.0.18(postcss@8.4.45)': + '@csstools/postcss-hwb-function@3.0.18(postcss@8.4.47)': dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-ic-unit@3.0.7(postcss@8.4.45)': + '@csstools/postcss-ic-unit@3.0.7(postcss@8.4.47)': dependencies: - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 postcss-value-parser: 4.2.0 - '@csstools/postcss-initial@1.0.1(postcss@8.4.45)': + '@csstools/postcss-initial@1.0.1(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-is-pseudo-class@4.0.8(postcss@8.4.45)': + '@csstools/postcss-is-pseudo-class@4.0.8(postcss@8.4.47)': dependencies: '@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.1.2) - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - '@csstools/postcss-light-dark-function@1.0.8(postcss@8.4.45)': + '@csstools/postcss-light-dark-function@1.0.8(postcss@8.4.47)': dependencies: '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-logical-float-and-clear@2.0.1(postcss@8.4.45)': + '@csstools/postcss-logical-float-and-clear@2.0.1(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-logical-overflow@1.0.1(postcss@8.4.45)': + '@csstools/postcss-logical-overflow@1.0.1(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-logical-overscroll-behavior@1.0.1(postcss@8.4.45)': + '@csstools/postcss-logical-overscroll-behavior@1.0.1(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-logical-resize@2.0.1(postcss@8.4.45)': + '@csstools/postcss-logical-resize@2.0.1(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - '@csstools/postcss-logical-viewport-units@2.0.11(postcss@8.4.45)': + '@csstools/postcss-logical-viewport-units@2.0.11(postcss@8.4.47)': dependencies: '@csstools/css-tokenizer': 2.4.1 - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-media-minmax@1.1.8(postcss@8.4.45)': + '@csstools/postcss-media-minmax@1.1.8(postcss@8.4.47)': dependencies: '@csstools/css-calc': 1.2.4(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 '@csstools/media-query-list-parser': 2.1.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-media-queries-aspect-ratio-number-values@2.0.11(postcss@8.4.45)': + '@csstools/postcss-media-queries-aspect-ratio-number-values@2.0.11(postcss@8.4.47)': dependencies: '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 '@csstools/media-query-list-parser': 2.1.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-nested-calc@3.0.2(postcss@8.4.45)': + '@csstools/postcss-nested-calc@3.0.2(postcss@8.4.47)': dependencies: - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 postcss-value-parser: 4.2.0 - '@csstools/postcss-normalize-display-values@3.0.2(postcss@8.4.45)': + '@csstools/postcss-normalize-display-values@3.0.2(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - '@csstools/postcss-oklab-function@3.0.19(postcss@8.4.45)': + '@csstools/postcss-oklab-function@3.0.19(postcss@8.4.47)': dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-progressive-custom-properties@3.3.0(postcss@8.4.45)': + '@csstools/postcss-progressive-custom-properties@3.3.0(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - '@csstools/postcss-relative-color-syntax@2.0.19(postcss@8.4.45)': + '@csstools/postcss-relative-color-syntax@2.0.19(postcss@8.4.47)': dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-scope-pseudo-class@3.0.1(postcss@8.4.45)': + '@csstools/postcss-scope-pseudo-class@3.0.1(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - '@csstools/postcss-stepped-value-functions@3.0.10(postcss@8.4.45)': + '@csstools/postcss-stepped-value-functions@3.0.10(postcss@8.4.47)': dependencies: '@csstools/css-calc': 1.2.4(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-text-decoration-shorthand@3.0.7(postcss@8.4.45)': + '@csstools/postcss-text-decoration-shorthand@3.0.7(postcss@8.4.47)': dependencies: '@csstools/color-helpers': 4.2.1 - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - '@csstools/postcss-trigonometric-functions@3.0.10(postcss@8.4.45)': + '@csstools/postcss-trigonometric-functions@3.0.10(postcss@8.4.47)': dependencies: '@csstools/css-calc': 1.2.4(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-unset-value@3.0.1(postcss@8.4.45)': + '@csstools/postcss-unset-value@3.0.1(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 '@csstools/selector-resolve-nested@1.1.0(postcss-selector-parser@6.1.2)': dependencies: @@ -5143,9 +5173,9 @@ snapshots: dependencies: postcss-selector-parser: 6.1.2 - '@csstools/utilities@1.0.0(postcss@8.4.45)': + '@csstools/utilities@1.0.0(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 '@drizzle-team/brocli@0.8.2': {} @@ -5450,9 +5480,9 @@ snapshots: '@esbuild/win32-x64@0.23.1': optional: true - '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.1)': dependencies: - eslint: 8.57.0 + eslint: 8.57.1 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.11.0': {} @@ -5471,7 +5501,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@8.57.0': {} + '@eslint/js@8.57.1': {} '@exodus/schemasafe@1.3.0': optional: true @@ -5508,23 +5538,23 @@ snapshots: '@hapi/hoek': 9.3.0 optional: true - '@hono/swagger-ui@0.4.1(hono@4.6.1)': + '@hono/swagger-ui@0.4.1(hono@4.6.2)': dependencies: - hono: 4.6.1 + hono: 4.6.2 - '@hono/zod-openapi@0.15.3(hono@4.6.1)(zod@3.23.8)': + '@hono/zod-openapi@0.15.3(hono@4.6.2)(zod@3.23.8)': dependencies: '@asteasolutions/zod-to-openapi': 7.1.1(zod@3.23.8) - '@hono/zod-validator': 0.2.2(hono@4.6.1)(zod@3.23.8) - hono: 4.6.1 + '@hono/zod-validator': 0.2.2(hono@4.6.2)(zod@3.23.8) + hono: 4.6.2 zod: 3.23.8 - '@hono/zod-validator@0.2.2(hono@4.6.1)(zod@3.23.8)': + '@hono/zod-validator@0.2.2(hono@4.6.2)(zod@3.23.8)': dependencies: - hono: 4.6.1 + hono: 4.6.2 zod: 3.23.8 - '@humanwhocodes/config-array@0.11.14': + '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 debug: 4.3.6 @@ -5664,9 +5694,9 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@lucia-auth/adapter-drizzle@1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4))(lucia@3.2.0)': + '@lucia-auth/adapter-drizzle@1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4))(lucia@3.2.0)': dependencies: - drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4) + drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4) lucia: 3.2.0 '@lukeed/csprng@1.1.0': {} @@ -5888,9 +5918,9 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@playwright/test@1.47.0': + '@playwright/test@1.47.2': dependencies: - playwright: 1.47.0 + playwright: 1.47.2 '@polka/url@1.0.0-next.25': {} @@ -6063,41 +6093,41 @@ snapshots: '@sodaru/yup-to-json-schema@2.0.1': optional: true - '@sveltejs/adapter-auto@3.2.4(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))': + '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': dependencies: - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) import-meta-resolve: 4.1.0 - '@sveltejs/adapter-node@5.2.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))': + '@sveltejs/adapter-node@5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': dependencies: '@rollup/plugin-commonjs': 26.0.1(rollup@4.21.2) '@rollup/plugin-json': 6.1.0(rollup@4.21.2) '@rollup/plugin-node-resolve': 15.2.3(rollup@4.21.2) - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) rollup: 4.21.2 - '@sveltejs/adapter-vercel@5.4.3(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))': + '@sveltejs/adapter-vercel@5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': dependencies: - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@vercel/nft': 0.27.4 esbuild: 0.21.5 transitivePeerDependencies: - encoding - supports-color - '@sveltejs/enhanced-img@0.3.4(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))': + '@sveltejs/enhanced-img@0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: magic-string: 0.30.11 svelte: 5.0.0-next.175 svelte-parse-markup: 0.1.5(svelte@5.0.0-next.175) - vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) vite-imagetools: 7.0.4(rollup@4.21.2) transitivePeerDependencies: - rollup - '@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))': + '@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.0.0 @@ -6111,28 +6141,28 @@ snapshots: sirv: 2.0.4 svelte: 5.0.0-next.175 tiny-glob: 0.2.9 - vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) - '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))': + '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) debug: 4.3.6 svelte: 5.0.0-next.175 - vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))': + '@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) debug: 4.3.6 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.11 svelte: 5.0.0-next.175 svelte-hmr: 0.16.0(svelte@5.0.0-next.175) - vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) - vitefu: 0.2.5(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) + vitefu: 0.2.5(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) transitivePeerDependencies: - supports-color @@ -6166,13 +6196,13 @@ snapshots: dependencies: undici-types: 6.19.8 - '@types/pg@8.11.6': + '@types/pg@8.11.10': dependencies: '@types/node': 20.16.5 pg-protocol: 1.6.1 pg-types: 4.0.2 - '@types/pg@8.11.9': + '@types/pg@8.11.6': dependencies: '@types/node': 20.16.5 pg-protocol: 1.6.1 @@ -6185,15 +6215,29 @@ snapshots: '@types/validator@13.12.1': optional: true - '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0)(typescript@5.6.2)': + '@typeschema/class-validator@0.2.0(@types/json-schema@7.0.15)(class-validator@0.14.1)': + dependencies: + '@typeschema/core': 0.14.0(@types/json-schema@7.0.15) + optionalDependencies: + class-validator: 0.14.1 + transitivePeerDependencies: + - '@types/json-schema' + optional: true + + '@typeschema/core@0.14.0(@types/json-schema@7.0.15)': + optionalDependencies: + '@types/json-schema': 7.0.15 + optional: true + + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2)': dependencies: '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 7.18.0(eslint@8.57.0)(typescript@5.6.2) + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.6.2) '@typescript-eslint/scope-manager': 7.18.0 - '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.0)(typescript@5.6.2) - '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.6.2) + '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.1)(typescript@5.6.2) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.6.2) '@typescript-eslint/visitor-keys': 7.18.0 - eslint: 8.57.0 + eslint: 8.57.1 graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -6203,14 +6247,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.6.2)': + '@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2)': dependencies: '@typescript-eslint/scope-manager': 7.18.0 '@typescript-eslint/types': 7.18.0 '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.2) '@typescript-eslint/visitor-keys': 7.18.0 debug: 4.3.6 - eslint: 8.57.0 + eslint: 8.57.1 optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: @@ -6221,12 +6265,12 @@ snapshots: '@typescript-eslint/types': 7.18.0 '@typescript-eslint/visitor-keys': 7.18.0 - '@typescript-eslint/type-utils@7.18.0(eslint@8.57.0)(typescript@5.6.2)': + '@typescript-eslint/type-utils@7.18.0(eslint@8.57.1)(typescript@5.6.2)': dependencies: '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.2) - '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.6.2) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.6.2) debug: 4.3.6 - eslint: 8.57.0 + eslint: 8.57.1 ts-api-utils: 1.3.0(typescript@5.6.2) optionalDependencies: typescript: 5.6.2 @@ -6250,13 +6294,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@7.18.0(eslint@8.57.0)(typescript@5.6.2)': + '@typescript-eslint/utils@7.18.0(eslint@8.57.1)(typescript@5.6.2)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) '@typescript-eslint/scope-manager': 7.18.0 '@typescript-eslint/types': 7.18.0 '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.2) - eslint: 8.57.0 + eslint: 8.57.1 transitivePeerDependencies: - supports-color - typescript @@ -6414,10 +6458,10 @@ snapshots: dependencies: dequal: 2.0.3 - arktype@2.0.0-beta.0: + arktype@2.0.0-rc.8: dependencies: - '@ark/schema': 0.2.0 - '@ark/util': 0.1.0 + '@ark/schema': 0.10.0 + '@ark/util': 0.10.0 optional: true array-flatten@1.1.1: {} @@ -6428,14 +6472,14 @@ snapshots: async-sema@3.1.1: {} - autoprefixer@10.4.20(postcss@8.4.45): + autoprefixer@10.4.20(postcss@8.4.47): dependencies: browserslist: 4.23.3 caniuse-lite: 1.0.30001655 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.1.0 - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 axobject-query@4.1.0: {} @@ -6450,7 +6494,7 @@ snapshots: dependencies: file-uri-to-path: 1.0.0 - bits-ui@0.21.13(svelte@5.0.0-next.175): + bits-ui@0.21.15(svelte@5.0.0-next.175): dependencies: '@internationalized/date': 3.5.5 '@melt-ui/svelte': 0.76.2(svelte@5.0.0-next.175) @@ -6508,7 +6552,7 @@ snapshots: builtin-modules@3.3.0: {} - bullmq@5.13.0: + bullmq@5.13.2: dependencies: cron-parser: 4.9.0 ioredis: 5.4.1 @@ -6576,8 +6620,20 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + chokidar@4.0.0: + dependencies: + readdirp: 4.0.1 + optional: true + chownr@2.0.0: {} + class-validator@0.14.1: + dependencies: + '@types/validator': 13.12.1 + libphonenumber-js: 1.11.8 + validator: 13.12.0 + optional: true + class-variance-authority@0.7.0: dependencies: clsx: 2.0.0 @@ -6658,25 +6714,25 @@ snapshots: css-background-parser@0.1.0: {} - css-blank-pseudo@6.0.2(postcss@8.4.45): + css-blank-pseudo@6.0.2(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 css-box-shadow@1.0.0-3: {} css-color-keywords@1.0.0: {} - css-has-pseudo@6.0.5(postcss@8.4.45): + css-has-pseudo@6.0.5(postcss@8.4.47): dependencies: '@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.1.2) - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 postcss-value-parser: 4.2.0 - css-prefers-color-scheme@9.0.1(postcss@8.4.45): + css-prefers-color-scheme@9.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 css-to-react-native@3.2.0: dependencies: @@ -6687,7 +6743,7 @@ snapshots: css-tree@2.3.1: dependencies: mdn-data: 2.0.30 - source-map-js: 1.2.0 + source-map-js: 1.2.1 cssdb@8.1.0: {} @@ -6769,16 +6825,16 @@ snapshots: transitivePeerDependencies: - supports-color - drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4): + drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4): optionalDependencies: '@neondatabase/serverless': 0.9.5 - '@types/pg': 8.11.9 - pg: 8.12.0 + '@types/pg': 8.11.10 + pg: 8.13.0 postgres: 3.4.4 - drizzle-zod@0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4))(zod@3.23.8): + drizzle-zod@0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4))(zod@3.23.8): dependencies: - drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4) + drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4) zod: 3.23.8 eastasianwidth@0.2.0: {} @@ -6927,27 +6983,27 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-compat-utils@0.5.1(eslint@8.57.0): + eslint-compat-utils@0.5.1(eslint@8.57.1): dependencies: - eslint: 8.57.0 + eslint: 8.57.1 semver: 7.6.3 - eslint-config-prettier@9.1.0(eslint@8.57.0): + eslint-config-prettier@9.1.0(eslint@8.57.1): dependencies: - eslint: 8.57.0 + eslint: 8.57.1 - eslint-plugin-svelte@2.36.0-next.13(eslint@8.57.0)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): + eslint-plugin-svelte@2.36.0-next.13(eslint@8.57.1)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) '@jridgewell/sourcemap-codec': 1.5.0 debug: 4.3.6 - eslint: 8.57.0 - eslint-compat-utils: 0.5.1(eslint@8.57.0) + eslint: 8.57.1 + eslint-compat-utils: 0.5.1(eslint@8.57.1) esutils: 2.0.3 known-css-properties: 0.30.0 - postcss: 8.4.45 - postcss-load-config: 3.1.4(postcss@8.4.45)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) - postcss-safe-parser: 6.0.0(postcss@8.4.45) + postcss: 8.4.47 + postcss-load-config: 3.1.4(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + postcss-safe-parser: 6.0.0(postcss@8.4.47) postcss-selector-parser: 6.1.2 semver: 7.6.3 svelte-eslint-parser: 0.41.0(svelte@5.0.0-next.175) @@ -6964,13 +7020,13 @@ snapshots: eslint-visitor-keys@3.4.3: {} - eslint@8.57.0: + eslint@8.57.1: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) '@eslint-community/regexpp': 4.11.0 '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 + '@eslint/js': 8.57.1 + '@humanwhocodes/config-array': 0.13.0 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 '@ungap/structured-clone': 1.2.0 @@ -7170,11 +7226,11 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)): + formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)): dependencies: nanoid: 5.0.7 svelte: 5.0.0-next.175 - sveltekit-superforms: 2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175) + sveltekit-superforms: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) forwarded@0.2.0: {} @@ -7307,11 +7363,11 @@ snapshots: hex-rgb@4.3.0: {} - hono-rate-limiter@0.4.0(hono@4.6.1): + hono-rate-limiter@0.4.0(hono@4.6.2): dependencies: - hono: 4.6.1 + hono: 4.6.2 - hono@4.6.1: {} + hono@4.6.2: {} html-entities@2.5.2: {} @@ -7344,7 +7400,8 @@ snapshots: imagetools-core@7.0.1: {} - immutable@4.3.7: {} + immutable@4.3.7: + optional: true import-fresh@3.3.0: dependencies: @@ -7488,6 +7545,9 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + libphonenumber-js@1.11.8: + optional: true + lilconfig@2.1.0: {} lilconfig@3.1.2: {} @@ -7826,18 +7886,20 @@ snapshots: pg-cloudflare@1.1.1: optional: true - pg-connection-string@2.6.4: {} + pg-connection-string@2.7.0: {} pg-int8@1.0.1: {} pg-numeric@1.0.2: {} - pg-pool@3.6.2(pg@8.12.0): + pg-pool@3.7.0(pg@8.13.0): dependencies: - pg: 8.12.0 + pg: 8.13.0 pg-protocol@1.6.1: {} + pg-protocol@1.7.0: {} + pg-types@2.2.0: dependencies: pg-int8: 1.0.1 @@ -7856,11 +7918,11 @@ snapshots: postgres-interval: 3.0.0 postgres-range: 1.1.4 - pg@8.12.0: + pg@8.13.0: dependencies: - pg-connection-string: 2.6.4 - pg-pool: 3.6.2(pg@8.12.0) - pg-protocol: 1.6.1 + pg-connection-string: 2.7.0 + pg-pool: 3.7.0(pg@8.13.0) + pg-protocol: 1.7.0 pg-types: 2.2.0 pgpass: 1.0.5 optionalDependencies: @@ -7884,281 +7946,281 @@ snapshots: mlly: 1.7.1 pathe: 1.1.2 - playwright-core@1.47.0: {} + playwright-core@1.47.2: {} - playwright@1.47.0: + playwright@1.47.2: dependencies: - playwright-core: 1.47.0 + playwright-core: 1.47.2 optionalDependencies: fsevents: 2.3.2 pngjs@5.0.0: {} - postcss-attribute-case-insensitive@6.0.3(postcss@8.4.45): + postcss-attribute-case-insensitive@6.0.3(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - postcss-clamp@4.1.0(postcss@8.4.45): + postcss-clamp@4.1.0(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-color-functional-notation@6.0.14(postcss@8.4.45): + postcss-color-functional-notation@6.0.14(postcss@8.4.47): dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - postcss-color-hex-alpha@9.0.4(postcss@8.4.45): + postcss-color-hex-alpha@9.0.4(postcss@8.4.47): dependencies: - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-color-rebeccapurple@9.0.3(postcss@8.4.45): + postcss-color-rebeccapurple@9.0.3(postcss@8.4.47): dependencies: - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-custom-media@10.0.8(postcss@8.4.45): + postcss-custom-media@10.0.8(postcss@8.4.47): dependencies: '@csstools/cascade-layer-name-parser': 1.0.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 '@csstools/media-query-list-parser': 2.1.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) - postcss: 8.4.45 + postcss: 8.4.47 - postcss-custom-properties@13.3.12(postcss@8.4.45): + postcss-custom-properties@13.3.12(postcss@8.4.47): dependencies: '@csstools/cascade-layer-name-parser': 1.0.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-custom-selectors@7.1.12(postcss@8.4.45): + postcss-custom-selectors@7.1.12(postcss@8.4.47): dependencies: '@csstools/cascade-layer-name-parser': 1.0.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - postcss-dir-pseudo-class@8.0.1(postcss@8.4.45): + postcss-dir-pseudo-class@8.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - postcss-double-position-gradients@5.0.7(postcss@8.4.45): + postcss-double-position-gradients@5.0.7(postcss@8.4.47): dependencies: - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-focus-visible@9.0.1(postcss@8.4.45): + postcss-focus-visible@9.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - postcss-focus-within@8.0.1(postcss@8.4.45): + postcss-focus-within@8.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - postcss-font-variant@5.0.0(postcss@8.4.45): + postcss-font-variant@5.0.0(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - postcss-gap-properties@5.0.1(postcss@8.4.45): + postcss-gap-properties@5.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - postcss-image-set-function@6.0.3(postcss@8.4.45): + postcss-image-set-function@6.0.3(postcss@8.4.47): dependencies: - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-import@15.1.0(postcss@8.4.45): + postcss-import@15.1.0(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.8 - postcss-import@16.1.0(postcss@8.4.45): + postcss-import@16.1.0(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.8 - postcss-js@4.0.1(postcss@8.4.45): + postcss-js@4.0.1(postcss@8.4.47): dependencies: camelcase-css: 2.0.1 - postcss: 8.4.45 + postcss: 8.4.47 - postcss-lab-function@6.0.19(postcss@8.4.45): + postcss-lab-function@6.0.19(postcss@8.4.47): dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - postcss-load-config@3.1.4(postcss@8.4.45)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): + postcss-load-config@3.1.4(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): dependencies: lilconfig: 2.1.0 yaml: 1.10.2 optionalDependencies: - postcss: 8.4.45 + postcss: 8.4.47 ts-node: 10.9.2(@types/node@20.16.5)(typescript@5.6.2) - postcss-load-config@4.0.2(postcss@8.4.45)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): + postcss-load-config@4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): dependencies: lilconfig: 3.1.2 yaml: 2.5.1 optionalDependencies: - postcss: 8.4.45 + postcss: 8.4.47 ts-node: 10.9.2(@types/node@20.16.5)(typescript@5.6.2) - postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1): + postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1): dependencies: lilconfig: 3.1.2 yaml: 2.5.1 optionalDependencies: jiti: 1.21.6 - postcss: 8.4.45 + postcss: 8.4.47 tsx: 4.19.1 - postcss-logical@7.0.1(postcss@8.4.45): + postcss-logical@7.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-nested@6.2.0(postcss@8.4.45): + postcss-nested@6.2.0(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - postcss-nesting@12.1.5(postcss@8.4.45): + postcss-nesting@12.1.5(postcss@8.4.47): dependencies: '@csstools/selector-resolve-nested': 1.1.0(postcss-selector-parser@6.1.2) '@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.1.2) - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - postcss-opacity-percentage@2.0.0(postcss@8.4.45): + postcss-opacity-percentage@2.0.0(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - postcss-overflow-shorthand@5.0.1(postcss@8.4.45): + postcss-overflow-shorthand@5.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-page-break@3.0.4(postcss@8.4.45): + postcss-page-break@3.0.4(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - postcss-place@9.0.1(postcss@8.4.45): + postcss-place@9.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-preset-env@9.6.0(postcss@8.4.45): + postcss-preset-env@9.6.0(postcss@8.4.47): dependencies: - '@csstools/postcss-cascade-layers': 4.0.6(postcss@8.4.45) - '@csstools/postcss-color-function': 3.0.19(postcss@8.4.45) - '@csstools/postcss-color-mix-function': 2.0.19(postcss@8.4.45) - '@csstools/postcss-content-alt-text': 1.0.0(postcss@8.4.45) - '@csstools/postcss-exponential-functions': 1.0.9(postcss@8.4.45) - '@csstools/postcss-font-format-keywords': 3.0.2(postcss@8.4.45) - '@csstools/postcss-gamut-mapping': 1.0.11(postcss@8.4.45) - '@csstools/postcss-gradients-interpolation-method': 4.0.20(postcss@8.4.45) - '@csstools/postcss-hwb-function': 3.0.18(postcss@8.4.45) - '@csstools/postcss-ic-unit': 3.0.7(postcss@8.4.45) - '@csstools/postcss-initial': 1.0.1(postcss@8.4.45) - '@csstools/postcss-is-pseudo-class': 4.0.8(postcss@8.4.45) - '@csstools/postcss-light-dark-function': 1.0.8(postcss@8.4.45) - '@csstools/postcss-logical-float-and-clear': 2.0.1(postcss@8.4.45) - '@csstools/postcss-logical-overflow': 1.0.1(postcss@8.4.45) - '@csstools/postcss-logical-overscroll-behavior': 1.0.1(postcss@8.4.45) - '@csstools/postcss-logical-resize': 2.0.1(postcss@8.4.45) - '@csstools/postcss-logical-viewport-units': 2.0.11(postcss@8.4.45) - '@csstools/postcss-media-minmax': 1.1.8(postcss@8.4.45) - '@csstools/postcss-media-queries-aspect-ratio-number-values': 2.0.11(postcss@8.4.45) - '@csstools/postcss-nested-calc': 3.0.2(postcss@8.4.45) - '@csstools/postcss-normalize-display-values': 3.0.2(postcss@8.4.45) - '@csstools/postcss-oklab-function': 3.0.19(postcss@8.4.45) - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/postcss-relative-color-syntax': 2.0.19(postcss@8.4.45) - '@csstools/postcss-scope-pseudo-class': 3.0.1(postcss@8.4.45) - '@csstools/postcss-stepped-value-functions': 3.0.10(postcss@8.4.45) - '@csstools/postcss-text-decoration-shorthand': 3.0.7(postcss@8.4.45) - '@csstools/postcss-trigonometric-functions': 3.0.10(postcss@8.4.45) - '@csstools/postcss-unset-value': 3.0.1(postcss@8.4.45) - autoprefixer: 10.4.20(postcss@8.4.45) + '@csstools/postcss-cascade-layers': 4.0.6(postcss@8.4.47) + '@csstools/postcss-color-function': 3.0.19(postcss@8.4.47) + '@csstools/postcss-color-mix-function': 2.0.19(postcss@8.4.47) + '@csstools/postcss-content-alt-text': 1.0.0(postcss@8.4.47) + '@csstools/postcss-exponential-functions': 1.0.9(postcss@8.4.47) + '@csstools/postcss-font-format-keywords': 3.0.2(postcss@8.4.47) + '@csstools/postcss-gamut-mapping': 1.0.11(postcss@8.4.47) + '@csstools/postcss-gradients-interpolation-method': 4.0.20(postcss@8.4.47) + '@csstools/postcss-hwb-function': 3.0.18(postcss@8.4.47) + '@csstools/postcss-ic-unit': 3.0.7(postcss@8.4.47) + '@csstools/postcss-initial': 1.0.1(postcss@8.4.47) + '@csstools/postcss-is-pseudo-class': 4.0.8(postcss@8.4.47) + '@csstools/postcss-light-dark-function': 1.0.8(postcss@8.4.47) + '@csstools/postcss-logical-float-and-clear': 2.0.1(postcss@8.4.47) + '@csstools/postcss-logical-overflow': 1.0.1(postcss@8.4.47) + '@csstools/postcss-logical-overscroll-behavior': 1.0.1(postcss@8.4.47) + '@csstools/postcss-logical-resize': 2.0.1(postcss@8.4.47) + '@csstools/postcss-logical-viewport-units': 2.0.11(postcss@8.4.47) + '@csstools/postcss-media-minmax': 1.1.8(postcss@8.4.47) + '@csstools/postcss-media-queries-aspect-ratio-number-values': 2.0.11(postcss@8.4.47) + '@csstools/postcss-nested-calc': 3.0.2(postcss@8.4.47) + '@csstools/postcss-normalize-display-values': 3.0.2(postcss@8.4.47) + '@csstools/postcss-oklab-function': 3.0.19(postcss@8.4.47) + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/postcss-relative-color-syntax': 2.0.19(postcss@8.4.47) + '@csstools/postcss-scope-pseudo-class': 3.0.1(postcss@8.4.47) + '@csstools/postcss-stepped-value-functions': 3.0.10(postcss@8.4.47) + '@csstools/postcss-text-decoration-shorthand': 3.0.7(postcss@8.4.47) + '@csstools/postcss-trigonometric-functions': 3.0.10(postcss@8.4.47) + '@csstools/postcss-unset-value': 3.0.1(postcss@8.4.47) + autoprefixer: 10.4.20(postcss@8.4.47) browserslist: 4.23.3 - css-blank-pseudo: 6.0.2(postcss@8.4.45) - css-has-pseudo: 6.0.5(postcss@8.4.45) - css-prefers-color-scheme: 9.0.1(postcss@8.4.45) + css-blank-pseudo: 6.0.2(postcss@8.4.47) + css-has-pseudo: 6.0.5(postcss@8.4.47) + css-prefers-color-scheme: 9.0.1(postcss@8.4.47) cssdb: 8.1.0 - postcss: 8.4.45 - postcss-attribute-case-insensitive: 6.0.3(postcss@8.4.45) - postcss-clamp: 4.1.0(postcss@8.4.45) - postcss-color-functional-notation: 6.0.14(postcss@8.4.45) - postcss-color-hex-alpha: 9.0.4(postcss@8.4.45) - postcss-color-rebeccapurple: 9.0.3(postcss@8.4.45) - postcss-custom-media: 10.0.8(postcss@8.4.45) - postcss-custom-properties: 13.3.12(postcss@8.4.45) - postcss-custom-selectors: 7.1.12(postcss@8.4.45) - postcss-dir-pseudo-class: 8.0.1(postcss@8.4.45) - postcss-double-position-gradients: 5.0.7(postcss@8.4.45) - postcss-focus-visible: 9.0.1(postcss@8.4.45) - postcss-focus-within: 8.0.1(postcss@8.4.45) - postcss-font-variant: 5.0.0(postcss@8.4.45) - postcss-gap-properties: 5.0.1(postcss@8.4.45) - postcss-image-set-function: 6.0.3(postcss@8.4.45) - postcss-lab-function: 6.0.19(postcss@8.4.45) - postcss-logical: 7.0.1(postcss@8.4.45) - postcss-nesting: 12.1.5(postcss@8.4.45) - postcss-opacity-percentage: 2.0.0(postcss@8.4.45) - postcss-overflow-shorthand: 5.0.1(postcss@8.4.45) - postcss-page-break: 3.0.4(postcss@8.4.45) - postcss-place: 9.0.1(postcss@8.4.45) - postcss-pseudo-class-any-link: 9.0.2(postcss@8.4.45) - postcss-replace-overflow-wrap: 4.0.0(postcss@8.4.45) - postcss-selector-not: 7.0.2(postcss@8.4.45) + postcss: 8.4.47 + postcss-attribute-case-insensitive: 6.0.3(postcss@8.4.47) + postcss-clamp: 4.1.0(postcss@8.4.47) + postcss-color-functional-notation: 6.0.14(postcss@8.4.47) + postcss-color-hex-alpha: 9.0.4(postcss@8.4.47) + postcss-color-rebeccapurple: 9.0.3(postcss@8.4.47) + postcss-custom-media: 10.0.8(postcss@8.4.47) + postcss-custom-properties: 13.3.12(postcss@8.4.47) + postcss-custom-selectors: 7.1.12(postcss@8.4.47) + postcss-dir-pseudo-class: 8.0.1(postcss@8.4.47) + postcss-double-position-gradients: 5.0.7(postcss@8.4.47) + postcss-focus-visible: 9.0.1(postcss@8.4.47) + postcss-focus-within: 8.0.1(postcss@8.4.47) + postcss-font-variant: 5.0.0(postcss@8.4.47) + postcss-gap-properties: 5.0.1(postcss@8.4.47) + postcss-image-set-function: 6.0.3(postcss@8.4.47) + postcss-lab-function: 6.0.19(postcss@8.4.47) + postcss-logical: 7.0.1(postcss@8.4.47) + postcss-nesting: 12.1.5(postcss@8.4.47) + postcss-opacity-percentage: 2.0.0(postcss@8.4.47) + postcss-overflow-shorthand: 5.0.1(postcss@8.4.47) + postcss-page-break: 3.0.4(postcss@8.4.47) + postcss-place: 9.0.1(postcss@8.4.47) + postcss-pseudo-class-any-link: 9.0.2(postcss@8.4.47) + postcss-replace-overflow-wrap: 4.0.0(postcss@8.4.47) + postcss-selector-not: 7.0.2(postcss@8.4.47) - postcss-pseudo-class-any-link@9.0.2(postcss@8.4.45): + postcss-pseudo-class-any-link@9.0.2(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - postcss-replace-overflow-wrap@4.0.0(postcss@8.4.45): + postcss-replace-overflow-wrap@4.0.0(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - postcss-safe-parser@6.0.0(postcss@8.4.45): + postcss-safe-parser@6.0.0(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - postcss-scss@4.0.9(postcss@8.4.45): + postcss-scss@4.0.9(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - postcss-selector-not@7.0.2(postcss@8.4.45): + postcss-selector-not@7.0.2(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 postcss-selector-parser@6.1.2: @@ -8168,11 +8230,11 @@ snapshots: postcss-value-parser@4.2.0: {} - postcss@8.4.45: + postcss@8.4.47: dependencies: nanoid: 3.3.7 picocolors: 1.1.0 - source-map-js: 1.2.0 + source-map-js: 1.2.1 postgres-array@2.0.0: {} @@ -8270,6 +8332,9 @@ snapshots: dependencies: picomatch: 2.3.1 + readdirp@4.0.1: + optional: true + redis-errors@1.2.0: {} redis-parser@3.0.0: @@ -8350,11 +8415,12 @@ snapshots: mkdirp: 0.5.6 rimraf: 2.7.1 - sass@1.78.0: + sass@1.79.1: dependencies: - chokidar: 3.6.0 + chokidar: 4.0.0 immutable: 4.3.7 - source-map-js: 1.2.0 + source-map-js: 1.2.1 + optional: true satori-html@0.3.2: dependencies: @@ -8500,7 +8566,7 @@ snapshots: minimist: 1.2.8 sander: 0.5.1 - source-map-js@1.2.0: {} + source-map-js@1.2.1: {} source-map-support@0.5.21: dependencies: @@ -8578,14 +8644,14 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-check@3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175): + svelte-check@3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175): dependencies: '@jridgewell/trace-mapping': 0.3.25 chokidar: 3.6.0 picocolors: 1.1.0 sade: 1.8.1 svelte: 5.0.0-next.175 - svelte-preprocess: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2) + svelte-preprocess: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175)(typescript@5.6.2) typescript: 5.6.2 transitivePeerDependencies: - '@babel/core' @@ -8603,8 +8669,8 @@ snapshots: eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 espree: 9.6.1 - postcss: 8.4.45 - postcss-scss: 4.0.9(postcss@8.4.45) + postcss: 8.4.47 + postcss-scss: 4.0.9(postcss@8.4.47) optionalDependencies: svelte: 5.0.0-next.175 @@ -8641,7 +8707,7 @@ snapshots: dependencies: svelte: 5.0.0-next.175 - svelte-preprocess@5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2): + svelte-preprocess@5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175)(typescript@5.6.2): dependencies: '@types/pug': 2.0.10 detect-indent: 6.1.0 @@ -8650,18 +8716,18 @@ snapshots: strip-indent: 3.0.0 svelte: 5.0.0-next.175 optionalDependencies: - postcss: 8.4.45 - postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1) - sass: 1.78.0 + postcss: 8.4.47 + postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1) + sass: 1.79.1 typescript: 5.6.2 - svelte-preprocess@6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2): + svelte-preprocess@6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175)(typescript@5.6.2): dependencies: svelte: 5.0.0-next.175 optionalDependencies: - postcss: 8.4.45 - postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1) - sass: 1.78.0 + postcss: 8.4.47 + postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1) + sass: 1.79.1 typescript: 5.6.2 svelte-render@2.0.1(svelte@5.0.0-next.175): @@ -8715,19 +8781,19 @@ snapshots: magic-string: 0.30.11 zimmerframe: 1.1.2 - sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175): + sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) svelte: 5.0.0-next.175 - sveltekit-rate-limiter@0.5.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))): + sveltekit-rate-limiter@0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))): dependencies: '@isaacs/ttlcache': 1.4.1 - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) - sveltekit-superforms@2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175): + sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) devalue: 5.0.0 just-clone: 6.2.0 memoize-weak: 1.0.2 @@ -8738,8 +8804,10 @@ snapshots: '@gcornut/valibot-json-schema': 0.31.0 '@sinclair/typebox': 0.32.35 '@sodaru/yup-to-json-schema': 2.0.1 + '@typeschema/class-validator': 0.2.0(@types/json-schema@7.0.15)(class-validator@0.14.1) '@vinejs/vine': 1.8.0 - arktype: 2.0.0-beta.0 + arktype: 2.0.0-rc.8 + class-validator: 0.14.1 joi: 17.13.3 json-schema-to-ts: 3.1.1 superstruct: 2.0.2 @@ -8747,21 +8815,23 @@ snapshots: yup: 1.4.0 zod: 3.23.8 zod-to-json-schema: 3.23.3(zod@3.23.8) + transitivePeerDependencies: + - '@types/json-schema' tabbable@6.2.0: {} tailwind-merge@2.5.2: {} - tailwind-variants@0.2.1(tailwindcss@3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))): + tailwind-variants@0.2.1(tailwindcss@3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))): dependencies: tailwind-merge: 2.5.2 - tailwindcss: 3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + tailwindcss: 3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) - tailwindcss-animate@1.0.7(tailwindcss@3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))): + tailwindcss-animate@1.0.7(tailwindcss@3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))): dependencies: - tailwindcss: 3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + tailwindcss: 3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) - tailwindcss@3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): + tailwindcss@3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -8777,11 +8847,11 @@ snapshots: normalize-path: 3.0.0 object-hash: 3.0.0 picocolors: 1.1.0 - postcss: 8.4.45 - postcss-import: 15.1.0(postcss@8.4.45) - postcss-js: 4.0.1(postcss@8.4.45) - postcss-load-config: 4.0.2(postcss@8.4.45)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) - postcss-nested: 6.2.0(postcss@8.4.45) + postcss: 8.4.47 + postcss-import: 15.1.0(postcss@8.4.47) + postcss-js: 4.0.1(postcss@8.4.47) + postcss-load-config: 4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + postcss-nested: 6.2.0(postcss@8.4.47) postcss-selector-parser: 6.1.2 resolve: 1.22.8 sucrase: 3.35.0 @@ -8958,13 +9028,13 @@ snapshots: transitivePeerDependencies: - rollup - vite-node@1.6.0(@types/node@20.16.5)(sass@1.78.0): + vite-node@1.6.0(@types/node@20.16.5)(sass@1.79.1): dependencies: cac: 6.7.14 debug: 4.3.6 pathe: 1.1.2 picocolors: 1.1.0 - vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) transitivePeerDependencies: - '@types/node' - less @@ -8976,21 +9046,21 @@ snapshots: - supports-color - terser - vite@5.4.4(@types/node@20.16.5)(sass@1.78.0): + vite@5.4.7(@types/node@20.16.5)(sass@1.79.1): dependencies: esbuild: 0.21.5 - postcss: 8.4.45 + postcss: 8.4.47 rollup: 4.21.2 optionalDependencies: '@types/node': 20.16.5 fsevents: 2.3.3 - sass: 1.78.0 + sass: 1.79.1 - vitefu@0.2.5(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)): + vitefu@0.2.5(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)): optionalDependencies: - vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) - vitest@1.6.0(@types/node@20.16.5)(sass@1.78.0): + vitest@1.6.0(@types/node@20.16.5)(sass@1.79.1): dependencies: '@vitest/expect': 1.6.0 '@vitest/runner': 1.6.0 @@ -9009,8 +9079,8 @@ snapshots: strip-literal: 2.1.0 tinybench: 2.9.0 tinypool: 0.8.4 - vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) - vite-node: 1.6.0(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) + vite-node: 1.6.0(@types/node@20.16.5)(sass@1.79.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 20.16.5 diff --git a/src/lib/server/api/common/env.ts b/src/lib/server/api/common/env.ts index 17796e8..5dd1157 100644 --- a/src/lib/server/api/common/env.ts +++ b/src/lib/server/api/common/env.ts @@ -17,6 +17,10 @@ const EnvSchema = z.object({ DATABASE_DB: z.string(), DB_MIGRATING: stringBoolean, DB_SEEDING: stringBoolean, + GITHUB_CLIENT_ID: z.string(), + GITHUB_CLIENT_SECRET: z.string(), + GOOGLE_CLIENT_ID: z.string(), + GOOGLE_CLIENT_SECRET: z.string(), NODE_ENV: z.string().default('development'), ORIGIN: z.string(), PUBLIC_SITE_NAME: z.string(), diff --git a/src/lib/server/api/common/types/oauth.ts b/src/lib/server/api/common/types/oauth.ts new file mode 100644 index 0000000..60e8bbd --- /dev/null +++ b/src/lib/server/api/common/types/oauth.ts @@ -0,0 +1,11 @@ +export type OAuthUser = { + sub: string; + given_name?: string; + family_name?: string; + picture?: string; + username: string; + email?: string; + email_verified?: boolean; +} + +export type OAuthProviders = 'github' | 'google' | 'apple' \ No newline at end of file diff --git a/src/lib/server/api/controllers/collection.controller.ts b/src/lib/server/api/controllers/collection.controller.ts index 86dfcc5..5cc94cd 100644 --- a/src/lib/server/api/controllers/collection.controller.ts +++ b/src/lib/server/api/controllers/collection.controller.ts @@ -18,6 +18,11 @@ export class CollectionController extends Controller { console.log('collections service', collections) return c.json({ collections }) }) + .get('/count', requireAuth, async (c) => { + const user = c.var.user + const collections = await this.collectionsService.findAllByUserIdWithDetails(user.id) + return c.json({ collections }) + }) .get('/:cuid', requireAuth, async (c) => { const cuid = c.req.param('cuid') const collection = await this.collectionsService.findOneByCuid(cuid) diff --git a/src/lib/server/api/controllers/oauth.controller.ts b/src/lib/server/api/controllers/oauth.controller.ts new file mode 100644 index 0000000..6a542d0 --- /dev/null +++ b/src/lib/server/api/controllers/oauth.controller.ts @@ -0,0 +1,150 @@ +import 'reflect-metadata' +import { Controller } from '$lib/server/api/common/types/controller' +import { LuciaService } from '$lib/server/api/services/lucia.service' +import { OAuthService } from '$lib/server/api/services/oauth.service' +import { github, google } from '$lib/server/auth' +import { OAuth2RequestError } from 'arctic' +import { getCookie, setCookie } from 'hono/cookie' +import { TimeSpan } from 'oslo' +import { inject, injectable } from 'tsyringe' +import type {OAuthUser} from "$lib/server/api/common/types/oauth"; + +@injectable() +export class OAuthController extends Controller { + constructor( + @inject(LuciaService) private luciaService: LuciaService, + @inject(OAuthService) private oauthService: OAuthService, + ) { + super() + } + + routes() { + return this.controller + .get('/github', async (c) => { + try { + const code = c.req.query('code')?.toString() ?? null + const state = c.req.query('state')?.toString() ?? null + const storedState = getCookie(c).github_oauth_state ?? null + + if (!code || !state || !storedState || state !== storedState) { + return c.body(null, 400) + } + + const tokens = await github.validateAuthorizationCode(code) + const githubUserResponse = await fetch('https://api.github.com/user', { + headers: { + Authorization: `Bearer ${tokens.accessToken}`, + }, + }) + const githubUser: GitHubUser = await githubUserResponse.json() + + const oAuthUser: OAuthUser = { + sub: `${githubUser.id}`, + username: githubUser.login, + email: undefined + } + + const userId = await this.oauthService.handleOAuthUser(oAuthUser, 'github') + + const session = await this.luciaService.lucia.createSession(userId, {}) + const sessionCookie = this.luciaService.lucia.createSessionCookie(session.id) + + setCookie(c, sessionCookie.name, sessionCookie.value, { + path: sessionCookie.attributes.path, + maxAge: + sessionCookie?.attributes?.maxAge && sessionCookie?.attributes?.maxAge < new TimeSpan(365, 'd').seconds() + ? sessionCookie.attributes.maxAge + : new TimeSpan(2, 'w').seconds(), + domain: sessionCookie.attributes.domain, + sameSite: sessionCookie.attributes.sameSite as any, + secure: sessionCookie.attributes.secure, + httpOnly: sessionCookie.attributes.httpOnly, + expires: sessionCookie.attributes.expires, + }) + + return c.json({ message: 'ok' }) + } catch (error) { + console.error(error) + // the specific error message depends on the provider + if (error instanceof OAuth2RequestError) { + // invalid code + return c.body(null, 400) + } + return c.body(null, 500) + } + }) + .get('/google', async (c) => { + try { + const code = c.req.query('code')?.toString() ?? null + const state = c.req.query('state')?.toString() ?? null + const storedState = getCookie(c).google_oauth_state ?? null + const storedCodeVerifier = getCookie(c).google_oauth_code_verifier ?? null + + if (!code || !storedState || !storedCodeVerifier || state !== storedState) { + return c.body(null, 400) + } + + const tokens = await google.validateAuthorizationCode(code, storedCodeVerifier) + const googleUserResponse = await fetch("https://openidconnect.googleapis.com/v1/userinfo", { + headers: { + Authorization: `Bearer ${tokens.accessToken}`, + }, + }) + const googleUser: GoogleUser = await googleUserResponse.json() + + const oAuthUser: OAuthUser = { + sub: googleUser.sub, + given_name: googleUser.given_name, + family_name: googleUser.family_name, + picture: googleUser.picture, + username: googleUser.email, + email: googleUser.email, + email_verified: googleUser.email_verified, + } + + const userId = await this.oauthService.handleOAuthUser(oAuthUser, 'google') + + const session = await this.luciaService.lucia.createSession(userId, {}) + const sessionCookie = this.luciaService.lucia.createSessionCookie(session.id) + + setCookie(c, sessionCookie.name, sessionCookie.value, { + path: sessionCookie.attributes.path, + maxAge: + sessionCookie?.attributes?.maxAge && sessionCookie?.attributes?.maxAge < new TimeSpan(365, 'd').seconds() + ? sessionCookie.attributes.maxAge + : new TimeSpan(2, 'w').seconds(), + domain: sessionCookie.attributes.domain, + sameSite: sessionCookie.attributes.sameSite as any, + secure: sessionCookie.attributes.secure, + httpOnly: sessionCookie.attributes.httpOnly, + expires: sessionCookie.attributes.expires, + }) + + return c.json({ message: 'ok' }) + } catch (error) { + console.error(error) + // the specific error message depends on the provider + if (error instanceof OAuth2RequestError) { + // invalid code + return c.body(null, 400) + } + return c.body(null, 500) + } + }) + } +} + +interface GitHubUser { + id: number + login: string +} + +interface GoogleUser { + sub: string + name: string + given_name: string + family_name: string + picture: string + email: string + email_verified: boolean +} diff --git a/src/lib/server/api/databases/migrations/0001_pink_the_enforcers.sql b/src/lib/server/api/databases/migrations/0001_pink_the_enforcers.sql new file mode 100644 index 0000000..1135b5e --- /dev/null +++ b/src/lib/server/api/databases/migrations/0001_pink_the_enforcers.sql @@ -0,0 +1,2 @@ +ALTER TABLE "users" ADD COLUMN "email_verified" boolean DEFAULT false;--> statement-breakpoint +ALTER TABLE "users" ADD COLUMN "picture" text; \ No newline at end of file diff --git a/src/lib/server/api/databases/migrations/meta/0001_snapshot.json b/src/lib/server/api/databases/migrations/meta/0001_snapshot.json new file mode 100644 index 0000000..ae9ae5b --- /dev/null +++ b/src/lib/server/api/databases/migrations/meta/0001_snapshot.json @@ -0,0 +1,1876 @@ +{ + "id": "e1230cae-67ce-4669-885a-3d3fe4462f9e", + "prevId": "4760134e-48bb-47db-b431-56903dad6e24", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.categories": { + "name": "categories", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "categories_cuid_unique": { + "name": "categories_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.categories_to_external_ids": { + "name": "categories_to_external_ids", + "schema": "", + "columns": { + "category_id": { + "name": "category_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "categories_to_external_ids_category_id_categories_id_fk": { + "name": "categories_to_external_ids_category_id_categories_id_fk", + "tableFrom": "categories_to_external_ids", + "tableTo": "categories", + "columnsFrom": [ + "category_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "categories_to_external_ids_external_id_external_ids_id_fk": { + "name": "categories_to_external_ids_external_id_external_ids_id_fk", + "tableFrom": "categories_to_external_ids", + "tableTo": "external_ids", + "columnsFrom": [ + "external_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "categories_to_external_ids_category_id_external_id_pk": { + "name": "categories_to_external_ids_category_id_external_id_pk", + "columns": [ + "category_id", + "external_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.categories_to_games": { + "name": "categories_to_games", + "schema": "", + "columns": { + "category_id": { + "name": "category_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "categories_to_games_category_id_categories_id_fk": { + "name": "categories_to_games_category_id_categories_id_fk", + "tableFrom": "categories_to_games", + "tableTo": "categories", + "columnsFrom": [ + "category_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "categories_to_games_game_id_games_id_fk": { + "name": "categories_to_games_game_id_games_id_fk", + "tableFrom": "categories_to_games", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "categories_to_games_category_id_game_id_pk": { + "name": "categories_to_games_category_id_game_id_pk", + "columns": [ + "category_id", + "game_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.collection_items": { + "name": "collection_items", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "collection_id": { + "name": "collection_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "times_played": { + "name": "times_played", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "collection_items_collection_id_collections_id_fk": { + "name": "collection_items_collection_id_collections_id_fk", + "tableFrom": "collection_items", + "tableTo": "collections", + "columnsFrom": [ + "collection_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "collection_items_game_id_games_id_fk": { + "name": "collection_items_game_id_games_id_fk", + "tableFrom": "collection_items", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "collection_items_cuid_unique": { + "name": "collection_items_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.collections": { + "name": "collections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'My Collection'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "collections_user_id_users_id_fk": { + "name": "collections_user_id_users_id_fk", + "tableFrom": "collections", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "collections_cuid_unique": { + "name": "collections_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.credentials": { + "name": "credentials", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'password'" + }, + "secret_data": { + "name": "secret_data", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "credentials_user_id_users_id_fk": { + "name": "credentials_user_id_users_id_fk", + "tableFrom": "credentials", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.expansions": { + "name": "expansions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "base_game_id": { + "name": "base_game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "expansions_base_game_id_games_id_fk": { + "name": "expansions_base_game_id_games_id_fk", + "tableFrom": "expansions", + "tableTo": "games", + "columnsFrom": [ + "base_game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "expansions_game_id_games_id_fk": { + "name": "expansions_game_id_games_id_fk", + "tableFrom": "expansions", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "expansions_cuid_unique": { + "name": "expansions_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.external_ids": { + "name": "external_ids", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "external_id_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "external_ids_cuid_unique": { + "name": "external_ids_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.federated_identity": { + "name": "federated_identity", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "identity_provider": { + "name": "identity_provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "federated_user_id": { + "name": "federated_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "federated_username": { + "name": "federated_username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "federated_identity_user_id_users_id_fk": { + "name": "federated_identity_user_id_users_id_fk", + "tableFrom": "federated_identity", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.games": { + "name": "games", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "year_published": { + "name": "year_published", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "min_players": { + "name": "min_players", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "max_players": { + "name": "max_players", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "playtime": { + "name": "playtime", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "min_playtime": { + "name": "min_playtime", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "max_playtime": { + "name": "max_playtime", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "min_age": { + "name": "min_age", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "image_url": { + "name": "image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "thumb_url": { + "name": "thumb_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_sync_at": { + "name": "last_sync_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "search_index": { + "name": "search_index", + "columns": [ + { + "expression": "(\n\t\t\t\tsetweight(to_tsvector('english', \"name\"), 'A') ||\n setweight(to_tsvector('english', \"slug\"), 'B')\n )", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "games_cuid_unique": { + "name": "games_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.games_to_external_ids": { + "name": "games_to_external_ids", + "schema": "", + "columns": { + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "games_to_external_ids_game_id_games_id_fk": { + "name": "games_to_external_ids_game_id_games_id_fk", + "tableFrom": "games_to_external_ids", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "games_to_external_ids_external_id_external_ids_id_fk": { + "name": "games_to_external_ids_external_id_external_ids_id_fk", + "tableFrom": "games_to_external_ids", + "tableTo": "external_ids", + "columnsFrom": [ + "external_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "games_to_external_ids_game_id_external_id_pk": { + "name": "games_to_external_ids_game_id_external_id_pk", + "columns": [ + "game_id", + "external_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.mechanics": { + "name": "mechanics", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mechanics_cuid_unique": { + "name": "mechanics_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.mechanics_to_external_ids": { + "name": "mechanics_to_external_ids", + "schema": "", + "columns": { + "mechanic_id": { + "name": "mechanic_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "mechanics_to_external_ids_mechanic_id_mechanics_id_fk": { + "name": "mechanics_to_external_ids_mechanic_id_mechanics_id_fk", + "tableFrom": "mechanics_to_external_ids", + "tableTo": "mechanics", + "columnsFrom": [ + "mechanic_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "mechanics_to_external_ids_external_id_external_ids_id_fk": { + "name": "mechanics_to_external_ids_external_id_external_ids_id_fk", + "tableFrom": "mechanics_to_external_ids", + "tableTo": "external_ids", + "columnsFrom": [ + "external_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "mechanics_to_external_ids_mechanic_id_external_id_pk": { + "name": "mechanics_to_external_ids_mechanic_id_external_id_pk", + "columns": [ + "mechanic_id", + "external_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.mechanics_to_games": { + "name": "mechanics_to_games", + "schema": "", + "columns": { + "mechanic_id": { + "name": "mechanic_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "mechanics_to_games_mechanic_id_mechanics_id_fk": { + "name": "mechanics_to_games_mechanic_id_mechanics_id_fk", + "tableFrom": "mechanics_to_games", + "tableTo": "mechanics", + "columnsFrom": [ + "mechanic_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "mechanics_to_games_game_id_games_id_fk": { + "name": "mechanics_to_games_game_id_games_id_fk", + "tableFrom": "mechanics_to_games", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "mechanics_to_games_mechanic_id_game_id_pk": { + "name": "mechanics_to_games_mechanic_id_game_id_pk", + "columns": [ + "mechanic_id", + "game_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.password_reset_tokens": { + "name": "password_reset_tokens", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "password_reset_tokens_user_id_users_id_fk": { + "name": "password_reset_tokens_user_id_users_id_fk", + "tableFrom": "password_reset_tokens", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.publishers": { + "name": "publishers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "publishers_cuid_unique": { + "name": "publishers_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.publishers_to_external_ids": { + "name": "publishers_to_external_ids", + "schema": "", + "columns": { + "publisher_id": { + "name": "publisher_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "publishers_to_external_ids_publisher_id_publishers_id_fk": { + "name": "publishers_to_external_ids_publisher_id_publishers_id_fk", + "tableFrom": "publishers_to_external_ids", + "tableTo": "publishers", + "columnsFrom": [ + "publisher_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "publishers_to_external_ids_external_id_external_ids_id_fk": { + "name": "publishers_to_external_ids_external_id_external_ids_id_fk", + "tableFrom": "publishers_to_external_ids", + "tableTo": "external_ids", + "columnsFrom": [ + "external_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "publishers_to_external_ids_publisher_id_external_id_pk": { + "name": "publishers_to_external_ids_publisher_id_external_id_pk", + "columns": [ + "publisher_id", + "external_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.publishers_to_games": { + "name": "publishers_to_games", + "schema": "", + "columns": { + "publisher_id": { + "name": "publisher_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "publishers_to_games_publisher_id_publishers_id_fk": { + "name": "publishers_to_games_publisher_id_publishers_id_fk", + "tableFrom": "publishers_to_games", + "tableTo": "publishers", + "columnsFrom": [ + "publisher_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "publishers_to_games_game_id_games_id_fk": { + "name": "publishers_to_games_game_id_games_id_fk", + "tableFrom": "publishers_to_games", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "publishers_to_games_publisher_id_game_id_pk": { + "name": "publishers_to_games_publisher_id_game_id_pk", + "columns": [ + "publisher_id", + "game_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.recovery_codes": { + "name": "recovery_codes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "used": { + "name": "used", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "recovery_codes_user_id_users_id_fk": { + "name": "recovery_codes_user_id_users_id_fk", + "tableFrom": "recovery_codes", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.roles": { + "name": "roles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "roles_cuid_unique": { + "name": "roles_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + }, + "roles_name_unique": { + "name": "roles_name_unique", + "nullsNotDistinct": false, + "columns": [ + "name" + ] + } + } + }, + "public.sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "ip_country": { + "name": "ip_country", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "two_factor_auth_enabled": { + "name": "two_factor_auth_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "is_two_factor_authenticated": { + "name": "is_two_factor_authenticated", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.two_factor": { + "name": "two_factor", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret": { + "name": "secret", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "initiated_time": { + "name": "initiated_time", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "two_factor_user_id_users_id_fk": { + "name": "two_factor_user_id_users_id_fk", + "tableFrom": "two_factor", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "two_factor_cuid_unique": { + "name": "two_factor_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + }, + "two_factor_user_id_unique": { + "name": "two_factor_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + } + } + }, + "public.user_roles": { + "name": "user_roles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "primary": { + "name": "primary", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_roles_user_id_users_id_fk": { + "name": "user_roles_user_id_users_id_fk", + "tableFrom": "user_roles", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_roles_role_id_roles_id_fk": { + "name": "user_roles_role_id_roles_id_fk", + "tableFrom": "user_roles", + "tableTo": "roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_roles_cuid_unique": { + "name": "user_roles_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "verified": { + "name": "verified", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "receive_email": { + "name": "receive_email", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "picture": { + "name": "picture", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mfa_enabled": { + "name": "mfa_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "theme": { + "name": "theme", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'system'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_cuid_unique": { + "name": "users_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + }, + "users_username_unique": { + "name": "users_username_unique", + "nullsNotDistinct": false, + "columns": [ + "username" + ] + }, + "users_email_unique": { + "name": "users_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + } + }, + "public.wishlist_items": { + "name": "wishlist_items", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "wishlist_id": { + "name": "wishlist_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "wishlist_items_wishlist_id_wishlists_id_fk": { + "name": "wishlist_items_wishlist_id_wishlists_id_fk", + "tableFrom": "wishlist_items", + "tableTo": "wishlists", + "columnsFrom": [ + "wishlist_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "wishlist_items_game_id_games_id_fk": { + "name": "wishlist_items_game_id_games_id_fk", + "tableFrom": "wishlist_items", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "wishlist_items_cuid_unique": { + "name": "wishlist_items_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.wishlists": { + "name": "wishlists", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'My Wishlist'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "wishlists_user_id_users_id_fk": { + "name": "wishlists_user_id_users_id_fk", + "tableFrom": "wishlists", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "wishlists_cuid_unique": { + "name": "wishlists_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + } + }, + "enums": { + "public.external_id_type": { + "name": "external_id_type", + "schema": "public", + "values": [ + "game", + "category", + "mechanic", + "publisher", + "designer", + "artist" + ] + } + }, + "schemas": {}, + "sequences": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/src/lib/server/api/databases/migrations/meta/_journal.json b/src/lib/server/api/databases/migrations/meta/_journal.json index 1f88a00..6022f03 100644 --- a/src/lib/server/api/databases/migrations/meta/_journal.json +++ b/src/lib/server/api/databases/migrations/meta/_journal.json @@ -8,6 +8,13 @@ "when": 1725489682980, "tag": "0000_volatile_warhawk", "breakpoints": true + }, + { + "idx": 1, + "version": "7", + "when": 1726877846811, + "tag": "0001_pink_the_enforcers", + "breakpoints": true } ] } \ No newline at end of file diff --git a/src/lib/server/api/databases/tables/collections.table.ts b/src/lib/server/api/databases/tables/collections.table.ts index 715bf4d..4b483df 100644 --- a/src/lib/server/api/databases/tables/collections.table.ts +++ b/src/lib/server/api/databases/tables/collections.table.ts @@ -3,6 +3,7 @@ import { type InferSelectModel, relations } from 'drizzle-orm' import { pgTable, text, uuid } from 'drizzle-orm/pg-core' import { timestamps } from '../../common/utils/table' import { usersTable } from './users.table' +import { collection_items } from './collectionItems.table' export const collections = pgTable('collections', { id: uuid('id').primaryKey().defaultRandom(), @@ -16,11 +17,12 @@ export const collections = pgTable('collections', { ...timestamps, }) -export const collection_relations = relations(collections, ({ one }) => ({ +export const collection_relations = relations(collections, ({ one, many }) => ({ user: one(usersTable, { fields: [collections.user_id], references: [usersTable.id], }), + collection_items: many(collection_items), })) export type Collections = InferSelectModel diff --git a/src/lib/server/api/databases/tables/users.table.ts b/src/lib/server/api/databases/tables/users.table.ts index 2836dba..c244bbd 100644 --- a/src/lib/server/api/databases/tables/users.table.ts +++ b/src/lib/server/api/databases/tables/users.table.ts @@ -15,6 +15,8 @@ export const usersTable = pgTable('users', { last_name: text('last_name'), verified: boolean('verified').default(false), receive_email: boolean('receive_email').default(false), + email_verified: boolean('email_verified').default(false), + picture: text('picture'), mfa_enabled: boolean('mfa_enabled').notNull().default(false), theme: text('theme').default('system'), ...timestamps, diff --git a/src/lib/server/api/index.ts b/src/lib/server/api/index.ts index 8dd5adb..3106d86 100644 --- a/src/lib/server/api/index.ts +++ b/src/lib/server/api/index.ts @@ -1,6 +1,7 @@ import 'reflect-metadata' import { CollectionController } from '$lib/server/api/controllers/collection.controller' import { MfaController } from '$lib/server/api/controllers/mfa.controller' +import { OAuthController } from '$lib/server/api/controllers/oauth.controller' import { SignupController } from '$lib/server/api/controllers/signup.controller' import { UserController } from '$lib/server/api/controllers/user.controller' import { WishlistController } from '$lib/server/api/controllers/wishlist.controller' @@ -44,6 +45,7 @@ const routes = app .route('/me', container.resolve(IamController).routes()) .route('/user', container.resolve(UserController).routes()) .route('/login', container.resolve(LoginController).routes()) + .route('/oauth', container.resolve(OAuthController).routes()) .route('/signup', container.resolve(SignupController).routes()) .route('/wishlists', container.resolve(WishlistController).routes()) .route('/collections', container.resolve(CollectionController).routes()) diff --git a/src/lib/server/api/repositories/collections.repository.ts b/src/lib/server/api/repositories/collections.repository.ts index c6f097b..c351714 100644 --- a/src/lib/server/api/repositories/collections.repository.ts +++ b/src/lib/server/api/repositories/collections.repository.ts @@ -51,6 +51,23 @@ export class CollectionsRepository { }) } + async findAllByUserIdWithDetails(userId: string, db = this.drizzle.db) { + return db.query.collections.findMany({ + where: eq(collections.user_id, userId), + columns: { + cuid: true, + name: true, + }, + with: { + collection_items: { + columns: { + cuid: true, + }, + }, + }, + }) + } + async create(data: CreateCollection, db = this.drizzle.db) { return db.insert(collections).values(data).returning().then(takeFirstOrThrow) } diff --git a/src/lib/server/api/repositories/credentials.repository.ts b/src/lib/server/api/repositories/credentials.repository.ts index 0671a40..bdd8de5 100644 --- a/src/lib/server/api/repositories/credentials.repository.ts +++ b/src/lib/server/api/repositories/credentials.repository.ts @@ -44,7 +44,7 @@ export class CredentialsRepository { } async findOneByIdOrThrow(id: string, db = this.drizzle.db) { - const credentials = await this.findOneById(id) + const credentials = await this.findOneById(id, db) if (!credentials) throw Error('Credentials not found') return credentials } diff --git a/src/lib/server/api/repositories/federated_identity.repository.ts b/src/lib/server/api/repositories/federated_identity.repository.ts new file mode 100644 index 0000000..2180590 --- /dev/null +++ b/src/lib/server/api/repositories/federated_identity.repository.ts @@ -0,0 +1,28 @@ +import { type InferInsertModel, and, eq } from 'drizzle-orm' +import { inject, injectable } from 'tsyringe' +import { takeFirstOrThrow } from '../common/utils/repository' +import { federatedIdentityTable } from '../databases/tables' +import { DrizzleService } from '../services/drizzle.service' + +export type CreateFederatedIdentity = InferInsertModel + +@injectable() +export class FederatedIdentityRepository { + constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} + + async findOneByUserIdAndProvider(userId: string, provider: string) { + return this.drizzle.db.query.federatedIdentityTable.findFirst({ + where: and(eq(federatedIdentityTable.user_id, userId), eq(federatedIdentityTable.identity_provider, provider)), + }) + } + + async findOneByFederatedUserIdAndProvider(federatedUserId: string, provider: string) { + return this.drizzle.db.query.federatedIdentityTable.findFirst({ + where: and(eq(federatedIdentityTable.federated_user_id, federatedUserId), eq(federatedIdentityTable.identity_provider, provider)), + }) + } + + async create(data: CreateFederatedIdentity, db = this.drizzle.db) { + return db.insert(federatedIdentityTable).values(data).returning().then(takeFirstOrThrow) + } +} diff --git a/src/lib/server/api/repositories/roles.repository.ts b/src/lib/server/api/repositories/roles.repository.ts index 2750d5c..4d9f283 100644 --- a/src/lib/server/api/repositories/roles.repository.ts +++ b/src/lib/server/api/repositories/roles.repository.ts @@ -28,29 +28,29 @@ export class RolesRepository { constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} async findOneById(id: string, db = this.drizzle.db) { - return db.query.roles.findFirst({ + return db.query.rolesTable.findFirst({ where: eq(rolesTable.id, id), }) } async findOneByIdOrThrow(id: string, db = this.drizzle.db) { - const role = await this.findOneById(id) + const role = await this.findOneById(id, db) if (!role) throw Error('Role not found') return role } async findAll(db = this.drizzle.db) { - return db.query.roles.findMany() + return db.query.rolesTable.findMany() } async findOneByName(name: string, db = this.drizzle.db) { - return db.query.roles.findFirst({ + return db.query.rolesTable.findFirst({ where: eq(rolesTable.name, name), }) } async findOneByNameOrThrow(name: string, db = this.drizzle.db) { - const role = await this.findOneByName(name) + const role = await this.findOneByName(name, db) if (!role) throw Error('Role not found') return role } diff --git a/src/lib/server/api/repositories/user_roles.repository.ts b/src/lib/server/api/repositories/user_roles.repository.ts index 737bc0c..ef95b74 100644 --- a/src/lib/server/api/repositories/user_roles.repository.ts +++ b/src/lib/server/api/repositories/user_roles.repository.ts @@ -33,8 +33,8 @@ export class UserRolesRepository { }) } - async findOneByIdOrThrow(id: string) { - const userRole = await this.findOneById(id) + async findOneByIdOrThrow(id: string, db = this.drizzle.db) { + const userRole = await this.findOneById(id, db) if (!userRole) throw Error('User not found') return userRole } diff --git a/src/lib/server/api/services/collections.service.ts b/src/lib/server/api/services/collections.service.ts index 4e0a009..ccdbcbc 100644 --- a/src/lib/server/api/services/collections.service.ts +++ b/src/lib/server/api/services/collections.service.ts @@ -1,37 +1,50 @@ -import { inject, injectable } from "tsyringe"; -import { generateRandomAnimalName } from "$lib/utils/randomDataUtil"; -import { CollectionsRepository } from "../repositories/collections.repository"; +import type { db } from '$lib/server/api/packages/drizzle' +import { generateRandomAnimalName } from '$lib/utils/randomDataUtil' +import { inject, injectable } from 'tsyringe' +import { CollectionsRepository } from '../repositories/collections.repository' @injectable() export class CollectionsService { - constructor( - @inject(CollectionsRepository) private readonly collectionsRepository: CollectionsRepository - ) { } + constructor(@inject(CollectionsRepository) private readonly collectionsRepository: CollectionsRepository) {} async findOneByUserId(userId: string) { - return this.collectionsRepository.findOneByUserId(userId); + return this.collectionsRepository.findOneByUserId(userId) } async findAllByUserId(userId: string) { - return this.collectionsRepository.findAllByUserId(userId); + return this.collectionsRepository.findAllByUserId(userId) + } + + async findAllByUserIdWithDetails(userId: string) { + return this.collectionsRepository.findAllByUserIdWithDetails(userId) } async findOneById(id: string) { - return this.collectionsRepository.findOneById(id); + return this.collectionsRepository.findOneById(id) } async findOneByCuid(cuid: string) { - return this.collectionsRepository.findOneByCuid(cuid); + return this.collectionsRepository.findOneByCuid(cuid) } - async createEmptyNoName(userId: string) { - return this.createEmpty(userId, null); + async createEmptyNoName(userId: string, trx: Parameters[0]>[0] | null = null) { + return this.createEmpty(userId, null, trx) } - async createEmpty(userId: string, name: string | null) { - return this.collectionsRepository.create({ - user_id: userId, - name: name ?? generateRandomAnimalName(), - }); + async createEmpty(userId: string, name: string | null, trx: Parameters[0]>[0] | null = null) { + if (!trx) { + return this.collectionsRepository.create({ + user_id: userId, + name: name ?? generateRandomAnimalName(), + }) + } + + return this.collectionsRepository.create( + { + user_id: userId, + name: name ?? generateRandomAnimalName(), + }, + trx, + ) } -} \ No newline at end of file +} diff --git a/src/lib/server/api/services/oauth.service.ts b/src/lib/server/api/services/oauth.service.ts new file mode 100644 index 0000000..ef563c6 --- /dev/null +++ b/src/lib/server/api/services/oauth.service.ts @@ -0,0 +1,27 @@ +import { inject, injectable } from 'tsyringe' +import { FederatedIdentityRepository } from '../repositories/federated_identity.repository' +import { UsersService } from './users.service' +import type {OAuthUser, OAuthProviders} from "$lib/server/api/common/types/oauth"; + +@injectable() +export class OAuthService { + constructor( + @inject(FederatedIdentityRepository) private readonly federatedIdentityRepository: FederatedIdentityRepository, + @inject(UsersService) private readonly usersService: UsersService, + ) {} + + async handleOAuthUser(oAuthUser: OAuthUser, oauthProvider: OAuthProviders) { + const federatedUser = await this.federatedIdentityRepository.findOneByFederatedUserIdAndProvider(oAuthUser.sub, oauthProvider) + + if (federatedUser) { + return federatedUser.user_id + } + + const user = await this.usersService.createOAuthUser(oAuthUser, oauthProvider) + + if (!user) { + throw new Error('Failed to create user') + } + return user.id + } +} diff --git a/src/lib/server/api/services/user_roles.service.ts b/src/lib/server/api/services/user_roles.service.ts index 04ad1d0..ea80eff 100644 --- a/src/lib/server/api/services/user_roles.service.ts +++ b/src/lib/server/api/services/user_roles.service.ts @@ -1,39 +1,51 @@ -import {inject, injectable} from "tsyringe"; -import {type CreateUserRole, UserRolesRepository} from "$lib/server/api/repositories/user_roles.repository"; -import {RolesService} from "$lib/server/api/services/roles.service"; +import type { db } from '$lib/server/api/packages/drizzle' +import { type CreateUserRole, UserRolesRepository } from '$lib/server/api/repositories/user_roles.repository' +import { RolesService } from '$lib/server/api/services/roles.service' +import { inject, injectable } from 'tsyringe' @injectable() export class UserRolesService { constructor( - @inject(UserRolesRepository) private readonly userRolesRepository: UserRolesRepository, - @inject(RolesService) private readonly rolesService: RolesService - ) { } + @inject(UserRolesRepository) private readonly userRolesRepository: UserRolesRepository, + @inject(RolesService) private readonly rolesService: RolesService, + ) {} async findOneById(id: string) { - return this.userRolesRepository.findOneById(id); + return this.userRolesRepository.findOneById(id) } async findAllByUserId(userId: string) { - return this.userRolesRepository.findAllByUserId(userId); + return this.userRolesRepository.findAllByUserId(userId) } async create(data: CreateUserRole) { - return this.userRolesRepository.create(data); + return this.userRolesRepository.create(data) } - async addRoleToUser(userId: string, roleName: string, primary = false) { + async addRoleToUser(userId: string, roleName: string, primary = false, trx: Parameters[0]>[0] | null = null) { // Find the role by its name - const role = await this.rolesService.findOneByNameOrThrow(roleName); + const role = await this.rolesService.findOneByNameOrThrow(roleName) if (!role || !role.id) { - throw new Error(`Role with name ${roleName} not found`); + throw new Error(`Role with name ${roleName} not found`) + } + + if (!trx) { + return this.userRolesRepository.create({ + user_id: userId, + role_id: role.id, + primary, + }) } // Create a UserRole entry linking the user and the role - return this.userRolesRepository.create({ - user_id: userId, - role_id: role.id, - primary, - }); + return this.userRolesRepository.create( + { + user_id: userId, + role_id: role.id, + primary, + }, + trx, + ) } -} \ No newline at end of file +} diff --git a/src/lib/server/api/services/users.service.ts b/src/lib/server/api/services/users.service.ts index f067809..172908f 100644 --- a/src/lib/server/api/services/users.service.ts +++ b/src/lib/server/api/services/users.service.ts @@ -1,21 +1,28 @@ import type { SignupUsernameEmailDto } from '$lib/server/api/dtos/signup-username-email.dto' import { CredentialsRepository } from '$lib/server/api/repositories/credentials.repository' +import { FederatedIdentityRepository } from '$lib/server/api/repositories/federated_identity.repository' +import { WishlistsRepository } from '$lib/server/api/repositories/wishlists.repository' import { TokensService } from '$lib/server/api/services/tokens.service' import { UserRolesService } from '$lib/server/api/services/user_roles.service' import { inject, injectable } from 'tsyringe' -import { CredentialsType } from '../databases/tables' +import {CredentialsType, RoleName} from '../databases/tables' import { type UpdateUser, UsersRepository } from '../repositories/users.repository' import { CollectionsService } from './collections.service' +import { DrizzleService } from './drizzle.service' import { WishlistsService } from './wishlists.service' +import type {OAuthUser} from "$lib/server/api/common/types/oauth"; @injectable() export class UsersService { constructor( @inject(CollectionsService) private readonly collectionsService: CollectionsService, @inject(CredentialsRepository) private readonly credentialsRepository: CredentialsRepository, + @inject(DrizzleService) private readonly drizzleService: DrizzleService, + @inject(FederatedIdentityRepository) private readonly federatedIdentityRepository: FederatedIdentityRepository, @inject(TokensService) private readonly tokenService: TokensService, @inject(UsersRepository) private readonly usersRepository: UsersRepository, @inject(UserRolesService) private readonly userRolesService: UserRolesService, + @inject(WishlistsRepository) private readonly wishlistsRepository: WishlistsRepository, @inject(WishlistsService) private readonly wishlistsService: WishlistsService, ) {} @@ -23,34 +30,76 @@ export class UsersService { const { firstName, lastName, email, username, password } = data const hashedPassword = await this.tokenService.createHashedToken(password) - const user = await this.usersRepository.create({ - first_name: firstName, - last_name: lastName, - email, - username, + return await this.drizzleService.db.transaction(async (trx) => { + const createdUser = await this.usersRepository.create( + { + first_name: firstName, + last_name: lastName, + email, + username, + }, + trx, + ) + + if (!createdUser) { + return null + } + + const credentials = await this.credentialsRepository.create( + { + user_id: createdUser.id, + type: CredentialsType.PASSWORD, + secret_data: hashedPassword, + }, + trx, + ) + + if (!credentials) { + await this.usersRepository.delete(createdUser.id) + return null + } + + await this.userRolesService.addRoleToUser(createdUser.id, RoleName.USER, true, trx) + + await this.wishlistsService.createEmptyNoName(createdUser.id, trx) + await this.collectionsService.createEmptyNoName(createdUser.id, trx) }) + } - if (!user) { - return null - } + async createOAuthUser(oAuthUser: OAuthUser, oauthProvider: string) { + return await this.drizzleService.db.transaction(async (trx) => { + const createdUser = await this.usersRepository.create( + { + username: oAuthUser.username || oAuthUser.username, + email: oAuthUser.email || null, + first_name: oAuthUser.given_name || null, + last_name: oAuthUser.family_name || null, + picture: oAuthUser.picture || null, + email_verified: oAuthUser.email_verified || false, + }, + trx, + ) - const credentials = await this.credentialsRepository.create({ - user_id: user.id, - type: CredentialsType.PASSWORD, - secret_data: hashedPassword, + if (!createdUser) { + return null + } + + await this.federatedIdentityRepository.create( + { + identity_provider: oauthProvider, + user_id: createdUser.id, + federated_user_id: oAuthUser.sub, + federated_username: oAuthUser.email || oAuthUser.username, + }, + trx, + ) + + await this.userRolesService.addRoleToUser(createdUser.id, RoleName.USER, true, trx) + + await this.wishlistsService.createEmptyNoName(createdUser.id, trx) + await this.collectionsService.createEmptyNoName(createdUser.id, trx) + return createdUser }) - - if (!credentials) { - await this.usersRepository.delete(user.id) - return null - } - - await this.userRolesService.addRoleToUser(user.id, 'user', true) - - await this.wishlistsService.createEmptyNoName(user.id) - await this.collectionsService.createEmptyNoName(user.id) - - return user } async updateUser(userId: string, data: UpdateUser) { diff --git a/src/lib/server/api/services/wishlists.service.ts b/src/lib/server/api/services/wishlists.service.ts index f7326a1..b06b174 100644 --- a/src/lib/server/api/services/wishlists.service.ts +++ b/src/lib/server/api/services/wishlists.service.ts @@ -1,34 +1,41 @@ -import { inject, injectable } from "tsyringe"; -import { WishlistsRepository } from "../repositories/wishlists.repository"; -import { generateRandomAnimalName } from "$lib/utils/randomDataUtil"; +import type { db } from '$lib/server/api/packages/drizzle' +import { generateRandomAnimalName } from '$lib/utils/randomDataUtil' +import { inject, injectable } from 'tsyringe' +import { WishlistsRepository } from '../repositories/wishlists.repository' @injectable() export class WishlistsService { - - constructor( - @inject(WishlistsRepository) private readonly wishlistsRepository: WishlistsRepository - ) { } + constructor(@inject(WishlistsRepository) private readonly wishlistsRepository: WishlistsRepository) {} async findAllByUserId(userId: string) { - return this.wishlistsRepository.findAllByUserId(userId); + return this.wishlistsRepository.findAllByUserId(userId) } async findOneById(id: string) { - return this.wishlistsRepository.findOneById(id); + return this.wishlistsRepository.findOneById(id) } async findOneByCuid(cuid: string) { - return this.wishlistsRepository.findOneByCuid(cuid); + return this.wishlistsRepository.findOneByCuid(cuid) } - async createEmptyNoName(userId: string) { - return this.createEmpty(userId, null); + async createEmptyNoName(userId: string, trx: Parameters[0]>[0] | null = null) { + return this.createEmpty(userId, null, trx) } - async createEmpty(userId: string, name: string | null) { - return this.wishlistsRepository.create({ - user_id: userId, - name: name ?? generateRandomAnimalName(), - }); + async createEmpty(userId: string, name: string | null, trx: Parameters[0]>[0] | null = null) { + if (!trx) { + return this.wishlistsRepository.create({ + user_id: userId, + name: name ?? generateRandomAnimalName(), + }) + } + return this.wishlistsRepository.create( + { + user_id: userId, + name: name ?? generateRandomAnimalName(), + }, + trx, + ) } -} \ No newline at end of file +} diff --git a/src/lib/server/auth.ts b/src/lib/server/auth.ts new file mode 100644 index 0000000..e06aa3e --- /dev/null +++ b/src/lib/server/auth.ts @@ -0,0 +1,6 @@ +import env from "$lib/server/api/common/env"; +import { GitHub, Google } from "arctic"; + +export const github = new GitHub(env.GITHUB_CLIENT_ID, env.GITHUB_CLIENT_SECRET); + +export const google = new Google(env.GOOGLE_CLIENT_ID, env.GOOGLE_CLIENT_SECRET, `${env.ORIGIN}/auth/callback/google`); \ No newline at end of file diff --git a/src/routes/(app)/(protected)/collections/+page.server.ts b/src/routes/(app)/(protected)/collections/+page.server.ts index 7dc3e2e..881f050 100644 --- a/src/routes/(app)/(protected)/collections/+page.server.ts +++ b/src/routes/(app)/(protected)/collections/+page.server.ts @@ -1,13 +1,12 @@ import { notSignedInMessage } from '$lib/flashMessages' +import { collection_items, collections, gamesTable } from '$lib/server/api/databases/tables' import { db } from '$lib/server/api/packages/drizzle' -import { userNotAuthenticated } from '$lib/server/auth-utils' import { modifyListGameSchema } from '$lib/validations/zod-schemas' import { type Actions, error, fail } from '@sveltejs/kit' import { and, eq } from 'drizzle-orm' import { redirect } from 'sveltekit-flash-message/server' import { zod } from 'sveltekit-superforms/adapters' import { superValidate } from 'sveltekit-superforms/server' -import { collection_items, collections, gamesTable } from '../../../../lib/server/api/databases/tables' export async function load(event) { const { locals } = event @@ -18,23 +17,10 @@ export async function load(event) { } try { - const userCollections = await db.query.collections.findMany({ - columns: { - cuid: true, - name: true, - created_at: true, - }, - where: eq(collections.user_id, authedUser.id), - }) - console.log('collections', userCollections) - - if (userCollections?.length === 0) { - console.log('Collection was not found') - return fail(404, {}) - } + const { data, error } = await locals.api.collections.$get().then(locals.parseApiResponse) return { - collections: userCollections, + collections: data?.collections || [], } } catch (e) { console.error(e) diff --git a/src/routes/(app)/(protected)/collections/+page.svelte b/src/routes/(app)/(protected)/collections/+page.svelte index 81f993f..6d600b9 100644 --- a/src/routes/(app)/(protected)/collections/+page.svelte +++ b/src/routes/(app)/(protected)/collections/+page.svelte @@ -1,24 +1,34 @@ Your Collections | Bored Game +

Your Collections

-
{#if collections.length === 0}

You have no collections

{:else} {#each collections as collection} -
+ + + {collection.name} + + +

Number of items:

+

Created at: {new Date(collection.createdAt).toLocaleString()}

+
+
+ {/each} {/if}
@@ -30,10 +40,6 @@ width: 100%; } - .collections { - margin: 2rem 0; - } - .collection-list { display: grid; grid-template-columns: repeat(3, minmax(200px, 1fr)); diff --git a/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte b/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte index 450233c..70a1054 100644 --- a/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte +++ b/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte @@ -40,7 +40,7 @@ console.log('items', items)
{#if items.length === 0} -

No gamesTable in your collection

+

No games in your collection

{:else} {#each items as game (game.game_id)} diff --git a/src/routes/(app)/(protected)/settings/profile/+page.server.ts b/src/routes/(app)/(protected)/settings/profile/+page.server.ts index 77cab00..1841c32 100644 --- a/src/routes/(app)/(protected)/settings/profile/+page.server.ts +++ b/src/routes/(app)/(protected)/settings/profile/+page.server.ts @@ -18,14 +18,6 @@ export const load: PageServerLoad = async (event) => { throw redirect(302, '/login', notSignedInMessage, event) } - console.log('authedUser', authedUser) - // if (userNotAuthenticated(user, session)) { - // redirect(302, '/login', notSignedInMessage, event); - // } - // const dbUser = await db.query.usersTable.findFirst({ - // where: eq(usersTable.id, user!.id!), - // }); - const profileForm = await superValidate(zod(updateProfileSchema), { defaults: { firstName: authedUser?.firstName ?? '', diff --git a/src/routes/(app)/privacy/+page.svelte b/src/routes/(app)/privacy/+page.svelte index 97bcf66..4711f47 100644 --- a/src/routes/(app)/privacy/+page.svelte +++ b/src/routes/(app)/privacy/+page.svelte @@ -1,5 +1,5 @@

Privacy Policy

-

Last Updated: September 13th, 2023

+

Last Updated: September 19th, 2024

At Bored Game, we respect your privacy and are committed to protecting your personal information. We collect only the personal information that is necessary for us to provide our services to you. diff --git a/src/routes/(auth)/auth/callback/github/+server.ts b/src/routes/(auth)/auth/callback/github/+server.ts new file mode 100644 index 0000000..5453600 --- /dev/null +++ b/src/routes/(auth)/auth/callback/github/+server.ts @@ -0,0 +1,26 @@ +import { StatusCodes } from '$lib/constants/status-codes' +import type { RequestEvent } from '@sveltejs/kit' +import { redirect } from 'sveltekit-flash-message/server' + +export async function GET(event: RequestEvent): Promise { + const { locals, url } = event + const code = url.searchParams.get('code') + const state = url.searchParams.get('state') + console.log('code', code, 'state', state) + + const { data, error } = await locals.api.oauth.github.$get({ query: { code, state } }).then(locals.parseApiResponse) + + if (error) { + return new Response(JSON.stringify(error), { + status: 400, + }) + } + + if (!data) { + return new Response(JSON.stringify({ message: 'Invalid request' }), { + status: 400, + }) + } + + redirect(StatusCodes.TEMPORARY_REDIRECT, '/') +} diff --git a/src/routes/(auth)/auth/callback/google/+server.ts b/src/routes/(auth)/auth/callback/google/+server.ts new file mode 100644 index 0000000..5bc0ad4 --- /dev/null +++ b/src/routes/(auth)/auth/callback/google/+server.ts @@ -0,0 +1,26 @@ +import { StatusCodes } from '$lib/constants/status-codes' +import type { RequestEvent } from '@sveltejs/kit' +import { redirect } from 'sveltekit-flash-message/server' + +export async function GET(event: RequestEvent): Promise { + const { locals, url } = event + const code = url.searchParams.get('code') + const state = url.searchParams.get('state') + console.log('code', code, 'state', state) + + const { data, error } = await locals.api.oauth.google.$get({ query: { code, state } }).then(locals.parseApiResponse) + + if (error) { + return new Response(JSON.stringify(error), { + status: 400, + }) + } + + if (!data) { + return new Response(JSON.stringify({ message: 'Invalid request' }), { + status: 400, + }) + } + + redirect(StatusCodes.TEMPORARY_REDIRECT, '/') +} diff --git a/src/routes/(auth)/login/+page.server.ts b/src/routes/(auth)/login/+page.server.ts index a2b90e9..a08e5d1 100644 --- a/src/routes/(auth)/login/+page.server.ts +++ b/src/routes/(auth)/login/+page.server.ts @@ -1,3 +1,4 @@ +import { StatusCodes } from '$lib/constants/status-codes' import { signinUsernameDto } from '$lib/dtos/signin-username.dto' import { type Actions, fail } from '@sveltejs/kit' import { redirect } from 'sveltekit-flash-message/server' @@ -136,6 +137,8 @@ export const actions: Actions = { form.data.username = '' form.data.password = '' + redirect(StatusCodes.TEMPORARY_REDIRECT, '/') + // if ( // twoFactorDetails?.enabled && // twoFactorDetails?.secret !== null && diff --git a/src/routes/(auth)/login/+page.svelte b/src/routes/(auth)/login/+page.svelte index 195f233..662bab1 100644 --- a/src/routes/(auth)/login/+page.svelte +++ b/src/routes/(auth)/login/+page.svelte @@ -1,41 +1,41 @@ @@ -47,8 +47,10 @@ Log into your account - + {@render usernamePasswordForm()} + or sign in with + {@render oAuthButtons()}

By clicking continue, you agree to our @@ -86,5 +88,17 @@ {/snippet} +{#snippet oAuthButtons()} +

+{/snippet} + \ No newline at end of file diff --git a/src/routes/(auth)/login/apple/+server.ts b/src/routes/(auth)/login/apple/+server.ts new file mode 100644 index 0000000..d9e5c33 --- /dev/null +++ b/src/routes/(auth)/login/apple/+server.ts @@ -0,0 +1,20 @@ +import { github } from '$lib/server/auth' +import { redirect } from '@sveltejs/kit' +import { generateState } from 'arctic' + +import type { RequestEvent } from '@sveltejs/kit' + +export async function GET(event: RequestEvent): Promise { + const state = generateState() + const url = await github.createAuthorizationURL(state) + + event.cookies.set('github_oauth_state', state, { + path: '/', + secure: import.meta.env.PROD, + httpOnly: true, + maxAge: 60 * 10, + sameSite: 'lax', + }) + + redirect(302, url.toString()) +} diff --git a/src/routes/(auth)/login/github/+server.ts b/src/routes/(auth)/login/github/+server.ts new file mode 100644 index 0000000..d9e5c33 --- /dev/null +++ b/src/routes/(auth)/login/github/+server.ts @@ -0,0 +1,20 @@ +import { github } from '$lib/server/auth' +import { redirect } from '@sveltejs/kit' +import { generateState } from 'arctic' + +import type { RequestEvent } from '@sveltejs/kit' + +export async function GET(event: RequestEvent): Promise { + const state = generateState() + const url = await github.createAuthorizationURL(state) + + event.cookies.set('github_oauth_state', state, { + path: '/', + secure: import.meta.env.PROD, + httpOnly: true, + maxAge: 60 * 10, + sameSite: 'lax', + }) + + redirect(302, url.toString()) +} diff --git a/src/routes/(auth)/login/google/+server.ts b/src/routes/(auth)/login/google/+server.ts new file mode 100644 index 0000000..98da6dd --- /dev/null +++ b/src/routes/(auth)/login/google/+server.ts @@ -0,0 +1,33 @@ +import { google } from '$lib/server/auth' +import { redirect } from '@sveltejs/kit' +import { generateCodeVerifier, generateState } from 'arctic' + +import type { RequestEvent } from '@sveltejs/kit' + +// Google Login +export async function GET(event: RequestEvent): Promise { + const state = generateState() + const codeVerifier = generateCodeVerifier(); + + const url = await google.createAuthorizationURL(state, codeVerifier, { + scopes: ["profile", "email", "openid"] + }) + + event.cookies.set('google_oauth_state', state, { + path: '/', + secure: import.meta.env.PROD, + httpOnly: true, + maxAge: 60 * 10, + sameSite: 'lax', + }) + + event.cookies.set('google_oauth_code_verifier', codeVerifier, { + path: '/', + secure: import.meta.env.PROD, + httpOnly: true, + maxAge: 60 * 10, + sameSite: 'lax', + }) + + redirect(302, url.toString()) +} diff --git a/src/routes/(auth)/login/spotify/+server.ts b/src/routes/(auth)/login/spotify/+server.ts new file mode 100644 index 0000000..d9e5c33 --- /dev/null +++ b/src/routes/(auth)/login/spotify/+server.ts @@ -0,0 +1,20 @@ +import { github } from '$lib/server/auth' +import { redirect } from '@sveltejs/kit' +import { generateState } from 'arctic' + +import type { RequestEvent } from '@sveltejs/kit' + +export async function GET(event: RequestEvent): Promise { + const state = generateState() + const url = await github.createAuthorizationURL(state) + + event.cookies.set('github_oauth_state', state, { + path: '/', + secure: import.meta.env.PROD, + httpOnly: true, + maxAge: 60 * 10, + sameSite: 'lax', + }) + + redirect(302, url.toString()) +} diff --git a/src/routes/(auth)/login/tidal/+server.ts b/src/routes/(auth)/login/tidal/+server.ts new file mode 100644 index 0000000..d9e5c33 --- /dev/null +++ b/src/routes/(auth)/login/tidal/+server.ts @@ -0,0 +1,20 @@ +import { github } from '$lib/server/auth' +import { redirect } from '@sveltejs/kit' +import { generateState } from 'arctic' + +import type { RequestEvent } from '@sveltejs/kit' + +export async function GET(event: RequestEvent): Promise { + const state = generateState() + const url = await github.createAuthorizationURL(state) + + event.cookies.set('github_oauth_state', state, { + path: '/', + secure: import.meta.env.PROD, + httpOnly: true, + maxAge: 60 * 10, + sameSite: 'lax', + }) + + redirect(302, url.toString()) +}