From e4ff068fe1d3f146fd5bc64da7fc5a87b0c8b048 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Tue, 11 Jun 2024 19:12:12 -0700 Subject: [PATCH] Starting over migrations, revert schema date string type, using two variables in session for knowing if 2FA is valid, adding checks everywhere on protected routes and APIs. --- drizzle.config.ts | 2 +- package.json | 8 +- pnpm-lock.yaml | 376 +++- src/db/migrate.ts | 5 +- ...changeling.sql => 0000_flippant_slyde.sql} | 14 +- .../migrations/0001_acoustic_thunderbolt.sql | 1 - src/db/migrations/0002_striped_darkhawk.sql | 7 - src/db/migrations/0003_flippant_avengers.sql | 5 - src/db/migrations/meta/0000_snapshot.json | 22 +- src/db/migrations/meta/0001_snapshot.json | 1540 ----------------- src/db/migrations/meta/0002_snapshot.json | 1540 ----------------- src/db/migrations/meta/0003_snapshot.json | 1540 ----------------- src/db/migrations/meta/_journal.json | 25 +- src/db/schema/categories.ts | 4 +- src/db/schema/collectionItems.ts | 4 +- src/db/schema/collections.ts | 4 +- src/db/schema/expansions.ts | 4 +- src/db/schema/games.ts | 18 +- src/db/schema/index.ts | 3 +- src/db/schema/mechanics.ts | 4 +- src/db/schema/passwordResetTokens.ts | 4 +- src/db/schema/publishers.ts | 4 +- src/db/schema/recoveryCodes.ts | 4 +- src/db/schema/roles.ts | 4 +- src/db/schema/sessions.ts | 4 + src/db/schema/userRoles.ts | 4 +- src/db/schema/users.ts | 4 +- src/db/schema/wishlistItems.ts | 4 +- src/db/schema/wishlists.ts | 4 +- src/db/seed.ts | 60 +- src/db/seeds/data/roles.json | 0 src/db/seeds/data/users.json | 23 + src/db/seeds/roles.ts | 30 + src/db/seeds/users.ts | 41 + src/lib/server/auth-utils.ts | 13 +- src/lib/server/auth.ts | 2 + .../(app)/(protected)/admin/+layout.server.ts | 5 +- .../(protected)/admin/users/+page.server.ts | 8 +- .../(protected)/collections/+page.server.ts | 5 +- .../collections/[id]/+page.server.ts | 36 +- .../collections/add/+page.server.ts | 15 +- .../collections/add/bgg/+page.server.ts | 21 +- .../(app)/(protected)/list/+layout.server.ts | 5 +- .../(protected)/list/[id]/+page.server.ts | 39 +- .../(app)/(protected)/profile/+page.server.ts | 5 +- .../security/password/change/+page.server.ts | 13 +- .../security/two-factor/+page.server.ts | 12 +- .../two-factor/recovery-codes/+page.server.ts | 7 +- .../(protected)/wishlists/+page.server.ts | 37 +- .../wishlists/[id]/+page.server.ts | 31 +- src/routes/(auth)/login/+page.server.ts | 18 +- src/routes/(auth)/totp/+page.server.ts | 30 +- 52 files changed, 718 insertions(+), 4900 deletions(-) rename src/db/migrations/{0000_spotty_changeling.sql => 0000_flippant_slyde.sql} (97%) delete mode 100644 src/db/migrations/0001_acoustic_thunderbolt.sql delete mode 100644 src/db/migrations/0002_striped_darkhawk.sql delete mode 100644 src/db/migrations/0003_flippant_avengers.sql delete mode 100644 src/db/migrations/meta/0001_snapshot.json delete mode 100644 src/db/migrations/meta/0002_snapshot.json delete mode 100644 src/db/migrations/meta/0003_snapshot.json create mode 100644 src/db/seeds/data/roles.json create mode 100644 src/db/seeds/data/users.json create mode 100644 src/db/seeds/roles.ts create mode 100644 src/db/seeds/users.ts diff --git a/drizzle.config.ts b/drizzle.config.ts index 02c36d3..fb14921 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -10,7 +10,7 @@ export default defineConfig({ port: Number(process.env.DATABASE_PORT) || 5432, user: process.env.DATABASE_USER, password: process.env.DATABASE_PASSWORD, - database: process.env.DATABASE || 'boredgame', + database: process.env.DATABASE_DB || 'boredgame', ssl: process.env.DATABASE_HOST !== 'localhost', }, // Print all statements diff --git a/package.json b/package.json index a0fde8a..573decf 100644 --- a/package.json +++ b/package.json @@ -36,10 +36,10 @@ "@typescript-eslint/parser": "^7.12.0", "autoprefixer": "^10.4.19", "dotenv": "^16.4.5", - "drizzle-kit": "^0.22.6", + "drizzle-kit": "^0.22.7", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-svelte": "^2.39.0", + "eslint-plugin-svelte": "^2.39.3", "just-clone": "^6.2.0", "just-debounce-it": "^3.2.0", "postcss": "^8.4.38", @@ -59,11 +59,11 @@ "svelte-sequential-preprocessor": "^2.0.1", "sveltekit-flash-message": "^2.4.4", "sveltekit-rate-limiter": "^0.5.1", - "sveltekit-superforms": "^2.14.0", + "sveltekit-superforms": "^2.15.1", "tailwindcss": "^3.4.4", "ts-node": "^10.9.2", "tslib": "^2.6.3", - "tsx": "^4.14.1", + "tsx": "^4.15.1", "typescript": "^5.4.5", "vite": "^5.2.13", "vitest": "^1.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 233e63b..3f52d9d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -61,7 +61,7 @@ importers: version: 4.29.2 formsnap: specifier: ^1.0.0 - version: 1.0.0(svelte@4.2.18)(sveltekit-superforms@2.14.0(@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(@types/json-schema@7.0.15)(esbuild-runner@2.2.2(esbuild@0.19.12))(esbuild@0.19.12)(svelte@4.2.18)) + version: 1.0.0(svelte@4.2.18)(sveltekit-superforms@2.15.1(@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18)) html-entities: specifier: ^2.5.2 version: 2.5.2 @@ -166,8 +166,8 @@ importers: specifier: ^16.4.5 version: 16.4.5 drizzle-kit: - specifier: ^0.22.6 - version: 0.22.6 + specifier: ^0.22.7 + version: 0.22.7 eslint: specifier: ^8.57.0 version: 8.57.0 @@ -175,8 +175,8 @@ importers: specifier: ^9.1.0 version: 9.1.0(eslint@8.57.0) eslint-plugin-svelte: - specifier: ^2.39.0 - version: 2.39.0(eslint@8.57.0)(svelte@4.2.18)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)) + specifier: ^2.39.3 + version: 2.39.3(eslint@8.57.0)(svelte@4.2.18)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)) just-clone: specifier: ^6.2.0 version: 6.2.0 @@ -191,7 +191,7 @@ importers: version: 16.1.0(postcss@8.4.38) postcss-load-config: specifier: ^5.1.0 - version: 5.1.0(jiti@1.21.3)(postcss@8.4.38)(tsx@4.14.1) + version: 5.1.0(jiti@1.21.3)(postcss@8.4.38)(tsx@4.15.1) postcss-preset-env: specifier: ^9.5.14 version: 9.5.14(postcss@8.4.38) @@ -215,7 +215,7 @@ importers: version: 4.2.18 svelte-check: specifier: ^3.8.0 - version: 3.8.0(postcss-load-config@5.1.0(jiti@1.21.3)(postcss@8.4.38)(tsx@4.14.1))(postcss@8.4.38)(sass@1.77.4)(svelte@4.2.18) + version: 3.8.0(postcss-load-config@5.1.0(jiti@1.21.3)(postcss@8.4.38)(tsx@4.15.1))(postcss@8.4.38)(sass@1.77.4)(svelte@4.2.18) svelte-headless-table: specifier: ^0.18.2 version: 0.18.2(svelte@4.2.18) @@ -224,7 +224,7 @@ importers: version: 3.1.2(svelte@4.2.18)(typescript@5.4.5) svelte-preprocess: specifier: ^5.1.4 - version: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.3)(postcss@8.4.38)(tsx@4.14.1))(postcss@8.4.38)(sass@1.77.4)(svelte@4.2.18)(typescript@5.4.5) + version: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.3)(postcss@8.4.38)(tsx@4.15.1))(postcss@8.4.38)(sass@1.77.4)(svelte@4.2.18)(typescript@5.4.5) svelte-sequential-preprocessor: specifier: ^2.0.1 version: 2.0.1 @@ -235,8 +235,8 @@ importers: specifier: ^0.5.1 version: 0.5.1(@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4))) sveltekit-superforms: - specifier: ^2.14.0 - version: 2.14.0(@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(@types/json-schema@7.0.15)(esbuild-runner@2.2.2(esbuild@0.19.12))(esbuild@0.19.12)(svelte@4.2.18) + specifier: ^2.15.1 + version: 2.15.1(@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18) tailwindcss: specifier: ^3.4.4 version: 3.4.4(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)) @@ -247,8 +247,8 @@ importers: specifier: ^2.6.3 version: 2.6.3 tsx: - specifier: ^4.14.1 - version: 4.14.1 + specifier: ^4.15.1 + version: 4.15.1 typescript: specifier: ^5.4.5 version: 5.4.5 @@ -272,11 +272,11 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@arktype/schema@0.1.7': - resolution: {integrity: sha512-xeaS/0EiuT5kUQGC9DqLv0vnjFpbEILmaBQF9CrLhamR0v8c+eUNM6z5u6DgzqPZbDFMmtfiCdikUTT1VueWXw==} + '@arktype/schema@0.1.13': + resolution: {integrity: sha512-qZjtCAKrnhsixDWsEGJtosWfi4bLpAg4OnnICVYTer/6v5hwlhsdYpYobTSJUc5eiBoI5Ai/kcNfYaQISshY2g==} - '@arktype/util@0.0.45': - resolution: {integrity: sha512-WPzoElBZK1NxYzT8PnoNsnulohgRU7PRKkJUoqeGvuFqP/Egv7tRNnvcJCE0MboHUnWaPTy/5Psjm/4iOvbWiw==} + '@arktype/util@0.0.48': + resolution: {integrity: sha512-U5FO5EUAJ4LoYtLSyAMmTf6CEVgslObfSQuua2zoK5Tv2FB3aESVQ3rdLfhuz+coRhlzlynbkmimyoQWwQT+aQ==} '@babel/runtime@7.24.5': resolution: {integrity: sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==} @@ -547,6 +547,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.18.20': resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} engines: {node: '>=12'} @@ -565,6 +571,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.18.20': resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} engines: {node: '>=12'} @@ -583,6 +595,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.18.20': resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} engines: {node: '>=12'} @@ -601,6 +619,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.18.20': resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} engines: {node: '>=12'} @@ -619,6 +643,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.18.20': resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} engines: {node: '>=12'} @@ -637,6 +667,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.18.20': resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} engines: {node: '>=12'} @@ -655,6 +691,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.18.20': resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} engines: {node: '>=12'} @@ -673,6 +715,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.18.20': resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} engines: {node: '>=12'} @@ -691,6 +739,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.18.20': resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} engines: {node: '>=12'} @@ -709,6 +763,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.18.20': resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} engines: {node: '>=12'} @@ -727,6 +787,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.18.20': resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} engines: {node: '>=12'} @@ -745,6 +811,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.18.20': resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} engines: {node: '>=12'} @@ -763,6 +835,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.18.20': resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} engines: {node: '>=12'} @@ -781,6 +859,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.18.20': resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} engines: {node: '>=12'} @@ -799,6 +883,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.18.20': resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} engines: {node: '>=12'} @@ -817,6 +907,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.18.20': resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} engines: {node: '>=12'} @@ -835,6 +931,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-x64@0.18.20': resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} engines: {node: '>=12'} @@ -853,6 +955,12 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-x64@0.18.20': resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} engines: {node: '>=12'} @@ -871,6 +979,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + '@esbuild/sunos-x64@0.18.20': resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} engines: {node: '>=12'} @@ -889,6 +1003,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.18.20': resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} engines: {node: '>=12'} @@ -907,6 +1027,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.18.20': resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} engines: {node: '>=12'} @@ -925,6 +1051,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.18.20': resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} engines: {node: '>=12'} @@ -943,6 +1075,12 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -979,14 +1117,9 @@ packages: '@fontsource/fira-mono@5.0.13': resolution: {integrity: sha512-fZDjR2BdAqmauEbTjcIT62zYzbOgDa5+IQH34D2k8Pxmy1T815mAqQkZciWZVQ9dc/BgdTtTUV9HJ2ulBNwchg==} - '@gcornut/valibot-json-schema@0.0.27': - resolution: {integrity: sha512-xcMaUStVgQzPrK3d7PuLFbQ+3qSp6LzaLExAm52E3FKmUfjQa7Sw5cDK6Hfu/8WT0yfGsuSCuJ5uT1sosjR9Qg==} + '@gcornut/valibot-json-schema@0.31.0': + resolution: {integrity: sha512-3xGptCurm23e7nuPQkdrE5rEs1FeTPHhAUsBuwwqG4/YeZLwJOoYZv+fmsppUEfo5y9lzUwNQrNqLS/q7HMc7g==} hasBin: true - peerDependencies: - '@types/json-schema': '>= 7.0.14' - esbuild: '>= 0.18.20' - esbuild-runner: '>= 2.2.2' - valibot: '>= 0.21.0' '@hapi/hoek@9.3.0': resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -1935,8 +2068,8 @@ packages: aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - arktype@2.0.0-dev.15: - resolution: {integrity: sha512-V8/jyfU/ISl9uSzTNZMgj/sYOI1QNxhVaqcS+spWamF/jx4eDFMqBVdhAGysJhKyLC+Qi2yNw5f1YQuaOMEeGw==} + arktype@2.0.0-dev.21: + resolution: {integrity: sha512-dgHCjb3FK4BGvG2LuXqgdWXstbFmiYowSy0jiKnyk4KVcMT5DyIJ9d1nbQM3ztiAL3hIPmPdkmpfxUqR+BoOBQ==} array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} @@ -2242,8 +2375,8 @@ packages: resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} engines: {node: '>=12'} - drizzle-kit@0.22.6: - resolution: {integrity: sha512-TE4mBMeVJvySjYxwKeUOMrzytFSKnpMyp6kBnm+aascu9P+hCMrGvnJhOAO94C3wmt144CoHZQWQCOoP/EFl8A==} + drizzle-kit@0.22.7: + resolution: {integrity: sha512-9THPCb2l1GPt7wxhws9LvTR0YG565ZlVgTuqGMwjs590Kch1pXu4GyjEArVijSF5m0OBj3qgdeKmuJXhKXgWFw==} hasBin: true drizzle-orm@0.31.2: @@ -2376,6 +2509,11 @@ packages: engines: {node: '>=12'} hasBin: true + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} @@ -2399,8 +2537,8 @@ packages: peerDependencies: eslint: '>=7.0.0' - eslint-plugin-svelte@2.39.0: - resolution: {integrity: sha512-FXktBLXsrxbA+6ZvJK2z/sQOrUKyzSg3fNWK5h0reSCjr2fjAsc9ai/s/JvSl4Hgvz3nYVtTIMwarZH5RcB7BA==} + eslint-plugin-svelte@2.39.3: + resolution: {integrity: sha512-uXsHW+VOSHRI3VgoDit4CURKos9wDque6CuaBNw8z6UyF5Rfc2XHmNEsRvvOd+VmMUtS+wC9bvwArv2tt4TFGA==} engines: {node: ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0-0 || ^9.0.0-0 @@ -3713,8 +3851,8 @@ packages: peerDependencies: svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 - svelte-eslint-parser@0.36.0: - resolution: {integrity: sha512-/6YmUSr0FAVxW8dXNdIMydBnddPMHzaHirAZ7RrT21XYdgGGZMh0LQG6CZsvAFS4r2Y4ItUuCQc8TQ3urB30mQ==} + svelte-eslint-parser@0.37.0: + resolution: {integrity: sha512-AXd5ar7dcOK+H86JomxcSaWevhs2J7o/xOwg+kDQu98uuATpm+tE5Twp7u8UQCdbWKB34Idu/CZyHmTOxfSQMw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: svelte: ^3.37.0 || ^4.0.0 || ^5.0.0-next.115 @@ -3827,8 +3965,8 @@ packages: peerDependencies: '@sveltejs/kit': 1.x || 2.x - sveltekit-superforms@2.14.0: - resolution: {integrity: sha512-TRN+x2+ENCnvDw70U5HLfmGQGFi4kpevpWaPpQ06AB0Wf5qCYxshbZBofMAXb8KOyetw8dhWpj86AQRPNwhzDg==} + sveltekit-superforms@2.15.1: + resolution: {integrity: sha512-rLzcJTGEzt2oFC1fNYn+ddM25uoCawudHBU7qoLo5gp/JLMRNhtX9gbBMt8imMLo4VcB8339VtxBRcWiMV1faQ==} peerDependencies: '@sveltejs/kit': 1.x || 2.x svelte: 3.x || 4.x || >=5.0.0-next.51 @@ -3939,8 +4077,8 @@ packages: tslib@2.6.3: resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} - tsx@4.14.1: - resolution: {integrity: sha512-GU8pPJq8DdxcJDSK6Bc64c2jW8zBK2hb0jzwHZDfjapbwu6AqvFnAElnzZ17Xb9TH5a/j6/sicTCVYF+eO/cmA==} + tsx@4.15.1: + resolution: {integrity: sha512-k/6h17jA1KfUR7SpcteOa880zGmF56s8gMIcSqUR5avyNFi9nlCEKpMiHLrzrqyARGr52A/JablmGey1DEWbCA==} engines: {node: '>=18.0.0'} hasBin: true @@ -3995,8 +4133,8 @@ packages: v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - valibot@0.30.0: - resolution: {integrity: sha512-5POBdbSkM+3nvJ6ZlyQHsggisfRtyT4tVTo1EIIShs6qCdXJnyWU5TJ68vr8iTg5zpOLjXLRiBqNx+9zwZz/rA==} + valibot@0.31.1: + resolution: {integrity: sha512-2YYIhPrnVSz/gfT2/iXVTrSj92HwchCt9Cga/6hX4B26iCz9zkIsGTS0HjDYTZfTi1Un0X6aRvhBi1cfqs/i0Q==} validator@13.11.0: resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} @@ -4180,12 +4318,12 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@arktype/schema@0.1.7': + '@arktype/schema@0.1.13': dependencies: - '@arktype/util': 0.0.45 + '@arktype/util': 0.0.48 optional: true - '@arktype/util@0.0.45': + '@arktype/util@0.0.48': optional: true '@babel/runtime@7.24.5': @@ -4457,6 +4595,9 @@ snapshots: '@esbuild/aix-ppc64@0.20.2': optional: true + '@esbuild/aix-ppc64@0.21.5': + optional: true + '@esbuild/android-arm64@0.18.20': optional: true @@ -4466,6 +4607,9 @@ snapshots: '@esbuild/android-arm64@0.20.2': optional: true + '@esbuild/android-arm64@0.21.5': + optional: true + '@esbuild/android-arm@0.18.20': optional: true @@ -4475,6 +4619,9 @@ snapshots: '@esbuild/android-arm@0.20.2': optional: true + '@esbuild/android-arm@0.21.5': + optional: true + '@esbuild/android-x64@0.18.20': optional: true @@ -4484,6 +4631,9 @@ snapshots: '@esbuild/android-x64@0.20.2': optional: true + '@esbuild/android-x64@0.21.5': + optional: true + '@esbuild/darwin-arm64@0.18.20': optional: true @@ -4493,6 +4643,9 @@ snapshots: '@esbuild/darwin-arm64@0.20.2': optional: true + '@esbuild/darwin-arm64@0.21.5': + optional: true + '@esbuild/darwin-x64@0.18.20': optional: true @@ -4502,6 +4655,9 @@ snapshots: '@esbuild/darwin-x64@0.20.2': optional: true + '@esbuild/darwin-x64@0.21.5': + optional: true + '@esbuild/freebsd-arm64@0.18.20': optional: true @@ -4511,6 +4667,9 @@ snapshots: '@esbuild/freebsd-arm64@0.20.2': optional: true + '@esbuild/freebsd-arm64@0.21.5': + optional: true + '@esbuild/freebsd-x64@0.18.20': optional: true @@ -4520,6 +4679,9 @@ snapshots: '@esbuild/freebsd-x64@0.20.2': optional: true + '@esbuild/freebsd-x64@0.21.5': + optional: true + '@esbuild/linux-arm64@0.18.20': optional: true @@ -4529,6 +4691,9 @@ snapshots: '@esbuild/linux-arm64@0.20.2': optional: true + '@esbuild/linux-arm64@0.21.5': + optional: true + '@esbuild/linux-arm@0.18.20': optional: true @@ -4538,6 +4703,9 @@ snapshots: '@esbuild/linux-arm@0.20.2': optional: true + '@esbuild/linux-arm@0.21.5': + optional: true + '@esbuild/linux-ia32@0.18.20': optional: true @@ -4547,6 +4715,9 @@ snapshots: '@esbuild/linux-ia32@0.20.2': optional: true + '@esbuild/linux-ia32@0.21.5': + optional: true + '@esbuild/linux-loong64@0.18.20': optional: true @@ -4556,6 +4727,9 @@ snapshots: '@esbuild/linux-loong64@0.20.2': optional: true + '@esbuild/linux-loong64@0.21.5': + optional: true + '@esbuild/linux-mips64el@0.18.20': optional: true @@ -4565,6 +4739,9 @@ snapshots: '@esbuild/linux-mips64el@0.20.2': optional: true + '@esbuild/linux-mips64el@0.21.5': + optional: true + '@esbuild/linux-ppc64@0.18.20': optional: true @@ -4574,6 +4751,9 @@ snapshots: '@esbuild/linux-ppc64@0.20.2': optional: true + '@esbuild/linux-ppc64@0.21.5': + optional: true + '@esbuild/linux-riscv64@0.18.20': optional: true @@ -4583,6 +4763,9 @@ snapshots: '@esbuild/linux-riscv64@0.20.2': optional: true + '@esbuild/linux-riscv64@0.21.5': + optional: true + '@esbuild/linux-s390x@0.18.20': optional: true @@ -4592,6 +4775,9 @@ snapshots: '@esbuild/linux-s390x@0.20.2': optional: true + '@esbuild/linux-s390x@0.21.5': + optional: true + '@esbuild/linux-x64@0.18.20': optional: true @@ -4601,6 +4787,9 @@ snapshots: '@esbuild/linux-x64@0.20.2': optional: true + '@esbuild/linux-x64@0.21.5': + optional: true + '@esbuild/netbsd-x64@0.18.20': optional: true @@ -4610,6 +4799,9 @@ snapshots: '@esbuild/netbsd-x64@0.20.2': optional: true + '@esbuild/netbsd-x64@0.21.5': + optional: true + '@esbuild/openbsd-x64@0.18.20': optional: true @@ -4619,6 +4811,9 @@ snapshots: '@esbuild/openbsd-x64@0.20.2': optional: true + '@esbuild/openbsd-x64@0.21.5': + optional: true + '@esbuild/sunos-x64@0.18.20': optional: true @@ -4628,6 +4823,9 @@ snapshots: '@esbuild/sunos-x64@0.20.2': optional: true + '@esbuild/sunos-x64@0.21.5': + optional: true + '@esbuild/win32-arm64@0.18.20': optional: true @@ -4637,6 +4835,9 @@ snapshots: '@esbuild/win32-arm64@0.20.2': optional: true + '@esbuild/win32-arm64@0.21.5': + optional: true + '@esbuild/win32-ia32@0.18.20': optional: true @@ -4646,6 +4847,9 @@ snapshots: '@esbuild/win32-ia32@0.20.2': optional: true + '@esbuild/win32-ia32@0.21.5': + optional: true + '@esbuild/win32-x64@0.18.20': optional: true @@ -4655,6 +4859,9 @@ snapshots: '@esbuild/win32-x64@0.20.2': optional: true + '@esbuild/win32-x64@0.21.5': + optional: true + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': dependencies: eslint: 8.57.0 @@ -4698,12 +4905,13 @@ snapshots: '@fontsource/fira-mono@5.0.13': {} - '@gcornut/valibot-json-schema@0.0.27(@types/json-schema@7.0.15)(esbuild-runner@2.2.2(esbuild@0.19.12))(esbuild@0.19.12)(valibot@0.30.0)': + '@gcornut/valibot-json-schema@0.31.0': dependencies: + valibot: 0.31.1 + optionalDependencies: '@types/json-schema': 7.0.15 - esbuild: 0.19.12 - esbuild-runner: 2.2.2(esbuild@0.19.12) - valibot: 0.30.0 + esbuild: 0.21.5 + esbuild-runner: 2.2.2(esbuild@0.21.5) optional: true '@hapi/hoek@9.3.0': @@ -5575,10 +5783,10 @@ snapshots: dependencies: dequal: 2.0.3 - arktype@2.0.0-dev.15: + arktype@2.0.0-dev.21: dependencies: - '@arktype/schema': 0.1.7 - '@arktype/util': 0.0.45 + '@arktype/schema': 0.1.13 + '@arktype/util': 0.0.48 optional: true array-union@2.1.0: {} @@ -5852,7 +6060,7 @@ snapshots: dotenv@16.4.5: {} - drizzle-kit@0.22.6: + drizzle-kit@0.22.7: dependencies: '@esbuild-kit/esm-loader': 2.6.5 esbuild: 0.19.12 @@ -5888,9 +6096,9 @@ snapshots: transitivePeerDependencies: - supports-color - esbuild-runner@2.2.2(esbuild@0.19.12): + esbuild-runner@2.2.2(esbuild@0.21.5): dependencies: - esbuild: 0.19.12 + esbuild: 0.21.5 source-map-support: 0.5.21 tslib: 2.4.0 optional: true @@ -5972,6 +6180,32 @@ snapshots: '@esbuild/win32-ia32': 0.20.2 '@esbuild/win32-x64': 0.20.2 + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + escalade@3.1.2: {} escape-html@1.0.3: {} @@ -5987,11 +6221,10 @@ snapshots: dependencies: eslint: 8.57.0 - eslint-plugin-svelte@2.39.0(eslint@8.57.0)(svelte@4.2.18)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)): + eslint-plugin-svelte@2.39.3(eslint@8.57.0)(svelte@4.2.18)(ts-node@10.9.2(@types/node@20.14.2)(typescript@5.4.5)): dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@jridgewell/sourcemap-codec': 1.4.15 - debug: 4.3.5 eslint: 8.57.0 eslint-compat-utils: 0.5.1(eslint@8.57.0) esutils: 2.0.3 @@ -6001,11 +6234,10 @@ snapshots: postcss-safe-parser: 6.0.0(postcss@8.4.38) postcss-selector-parser: 6.1.0 semver: 7.6.2 - svelte-eslint-parser: 0.36.0(svelte@4.2.18) + svelte-eslint-parser: 0.37.0(svelte@4.2.18) optionalDependencies: svelte: 4.2.18 transitivePeerDependencies: - - supports-color - ts-node eslint-scope@7.2.2: @@ -6166,11 +6398,11 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - formsnap@1.0.0(svelte@4.2.18)(sveltekit-superforms@2.14.0(@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(@types/json-schema@7.0.15)(esbuild-runner@2.2.2(esbuild@0.19.12))(esbuild@0.19.12)(svelte@4.2.18)): + formsnap@1.0.0(svelte@4.2.18)(sveltekit-superforms@2.15.1(@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18)): dependencies: nanoid: 5.0.7 svelte: 4.2.18 - sveltekit-superforms: 2.14.0(@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(@types/json-schema@7.0.15)(esbuild-runner@2.2.2(esbuild@0.19.12))(esbuild@0.19.12)(svelte@4.2.18) + sveltekit-superforms: 2.15.1(@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18) fraction.js@4.3.7: {} @@ -6883,14 +7115,14 @@ snapshots: postcss: 8.4.38 ts-node: 10.9.2(@types/node@20.14.2)(typescript@5.4.5) - postcss-load-config@5.1.0(jiti@1.21.3)(postcss@8.4.38)(tsx@4.14.1): + postcss-load-config@5.1.0(jiti@1.21.3)(postcss@8.4.38)(tsx@4.15.1): dependencies: lilconfig: 3.1.1 yaml: 2.4.2 optionalDependencies: jiti: 1.21.3 postcss: 8.4.38 - tsx: 4.14.1 + tsx: 4.15.1 postcss-logical@7.0.1(postcss@8.4.38): dependencies: @@ -7379,7 +7611,7 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-check@3.8.0(postcss-load-config@5.1.0(jiti@1.21.3)(postcss@8.4.38)(tsx@4.14.1))(postcss@8.4.38)(sass@1.77.4)(svelte@4.2.18): + svelte-check@3.8.0(postcss-load-config@5.1.0(jiti@1.21.3)(postcss@8.4.38)(tsx@4.15.1))(postcss@8.4.38)(sass@1.77.4)(svelte@4.2.18): dependencies: '@jridgewell/trace-mapping': 0.3.25 chokidar: 3.6.0 @@ -7388,7 +7620,7 @@ snapshots: picocolors: 1.0.0 sade: 1.8.1 svelte: 4.2.18 - svelte-preprocess: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.3)(postcss@8.4.38)(tsx@4.14.1))(postcss@8.4.38)(sass@1.77.4)(svelte@4.2.18)(typescript@5.4.5) + svelte-preprocess: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.3)(postcss@8.4.38)(tsx@4.15.1))(postcss@8.4.38)(sass@1.77.4)(svelte@4.2.18)(typescript@5.4.5) typescript: 5.4.5 transitivePeerDependencies: - '@babel/core' @@ -7401,7 +7633,7 @@ snapshots: - stylus - sugarss - svelte-eslint-parser@0.36.0(svelte@4.2.18): + svelte-eslint-parser@0.37.0(svelte@4.2.18): dependencies: eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 @@ -7444,7 +7676,7 @@ snapshots: dependencies: svelte: 4.2.18 - svelte-preprocess@5.1.4(postcss-load-config@5.1.0(jiti@1.21.3)(postcss@8.4.38)(tsx@4.14.1))(postcss@8.4.38)(sass@1.77.4)(svelte@4.2.18)(typescript@5.4.5): + svelte-preprocess@5.1.4(postcss-load-config@5.1.0(jiti@1.21.3)(postcss@8.4.38)(tsx@4.15.1))(postcss@8.4.38)(sass@1.77.4)(svelte@4.2.18)(typescript@5.4.5): dependencies: '@types/pug': 2.0.10 detect-indent: 6.1.0 @@ -7454,7 +7686,7 @@ snapshots: svelte: 4.2.18 optionalDependencies: postcss: 8.4.38 - postcss-load-config: 5.1.0(jiti@1.21.3)(postcss@8.4.38)(tsx@4.14.1) + postcss-load-config: 5.1.0(jiti@1.21.3)(postcss@8.4.38)(tsx@4.15.1) sass: 1.77.4 typescript: 5.4.5 @@ -7503,7 +7735,7 @@ snapshots: '@isaacs/ttlcache': 1.4.1 '@sveltejs/kit': 2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)) - sveltekit-superforms@2.14.0(@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(@types/json-schema@7.0.15)(esbuild-runner@2.2.2(esbuild@0.19.12))(esbuild@0.19.12)(svelte@4.2.18): + sveltekit-superforms@2.15.1(@sveltejs/kit@2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18): dependencies: '@sveltejs/kit': 2.5.10(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)))(svelte@4.2.18)(vite@5.2.13(@types/node@20.14.2)(sass@1.77.4)) devalue: 5.0.0 @@ -7513,22 +7745,18 @@ snapshots: ts-deepmerge: 7.0.0 optionalDependencies: '@exodus/schemasafe': 1.3.0 - '@gcornut/valibot-json-schema': 0.0.27(@types/json-schema@7.0.15)(esbuild-runner@2.2.2(esbuild@0.19.12))(esbuild@0.19.12)(valibot@0.30.0) + '@gcornut/valibot-json-schema': 0.31.0 '@sinclair/typebox': 0.32.31 '@sodaru/yup-to-json-schema': 2.0.1 '@vinejs/vine': 1.8.0 - arktype: 2.0.0-dev.15 + arktype: 2.0.0-dev.21 joi: 17.13.1 json-schema-to-ts: 3.1.0 superstruct: 1.0.4 - valibot: 0.30.0 + valibot: 0.31.1 yup: 1.4.0 zod: 3.23.8 zod-to-json-schema: 3.23.0(zod@3.23.8) - transitivePeerDependencies: - - '@types/json-schema' - - esbuild - - esbuild-runner tabbable@6.2.0: {} @@ -7652,9 +7880,9 @@ snapshots: tslib@2.6.3: {} - tsx@4.14.1: + tsx@4.15.1: dependencies: - esbuild: 0.20.2 + esbuild: 0.21.5 get-tsconfig: 4.7.5 optionalDependencies: fsevents: 2.3.3 @@ -7699,7 +7927,7 @@ snapshots: v8-compile-cache-lib@3.0.1: {} - valibot@0.30.0: + valibot@0.31.1: optional: true validator@13.11.0: diff --git a/src/db/migrate.ts b/src/db/migrate.ts index 685c9e9..47060da 100644 --- a/src/db/migrate.ts +++ b/src/db/migrate.ts @@ -1,5 +1,6 @@ import 'dotenv/config'; import postgres from 'postgres'; +import config from '../../drizzle.config'; import { drizzle } from 'drizzle-orm/postgres-js'; import { migrate } from 'drizzle-orm/postgres-js/migrator'; @@ -10,12 +11,12 @@ const connection = postgres({ password: process.env.DATABASE_PASSWORD || '', database: process.env.DATABASE_DB || 'boredgame', ssl: process.env.NODE_ENV === 'development' ? false : 'require', - max: 1 + max: 1, }); const db = drizzle(connection); try { - await migrate(db, { migrationsFolder: 'drizzle' }); + await migrate(db, { migrationsFolder: config.out! }); console.log('Migrations complete'); } catch (e) { console.error(e); diff --git a/src/db/migrations/0000_spotty_changeling.sql b/src/db/migrations/0000_flippant_slyde.sql similarity index 97% rename from src/db/migrations/0000_spotty_changeling.sql rename to src/db/migrations/0000_flippant_slyde.sql index a1d43cf..a2d1378 100644 --- a/src/db/migrations/0000_spotty_changeling.sql +++ b/src/db/migrations/0000_flippant_slyde.sql @@ -52,8 +52,8 @@ CREATE TABLE IF NOT EXISTS "external_ids" ( CREATE TABLE IF NOT EXISTS "games" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "cuid" text, - "name" text, - "slug" text, + "name" text NOT NULL, + "slug" text NOT NULL, "description" text, "year_published" integer, "min_players" integer, @@ -152,7 +152,9 @@ CREATE TABLE IF NOT EXISTS "sessions" ( "user_id" uuid NOT NULL, "expires_at" timestamp with time zone NOT NULL, "ip_country" text, - "ip_address" text + "ip_address" text, + "two_factor_auth_enabled" boolean DEFAULT false, + "is_two_factor_authenticated" boolean DEFAULT false ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "user_roles" ( @@ -357,6 +359,6 @@ EXCEPTION END $$; --> statement-breakpoint CREATE INDEX IF NOT EXISTS "search_index" ON "games" USING gin (( - setweight(to_tsvector('english', "name"), 'A') || - setweight(to_tsvector('english', "slug"), 'B') - )); \ No newline at end of file + setweight(to_tsvector('english', "name"), 'A') || + setweight(to_tsvector('english', "slug"), 'B') + )); \ No newline at end of file diff --git a/src/db/migrations/0001_acoustic_thunderbolt.sql b/src/db/migrations/0001_acoustic_thunderbolt.sql deleted file mode 100644 index 630c727..0000000 --- a/src/db/migrations/0001_acoustic_thunderbolt.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE "sessions" ADD COLUMN "is_two_factor_authenticated" boolean DEFAULT false; \ No newline at end of file diff --git a/src/db/migrations/0002_striped_darkhawk.sql b/src/db/migrations/0002_striped_darkhawk.sql deleted file mode 100644 index fa3c198..0000000 --- a/src/db/migrations/0002_striped_darkhawk.sql +++ /dev/null @@ -1,7 +0,0 @@ -DROP INDEX IF EXISTS "search_index";--> statement-breakpoint -ALTER TABLE "games" ALTER COLUMN "name" SET NOT NULL;--> statement-breakpoint -ALTER TABLE "games" ALTER COLUMN "slug" SET NOT NULL;--> statement-breakpoint -CREATE INDEX IF NOT EXISTS "search_index" ON "games" USING gin (( - setweight(to_tsvector('english', "name"), 'A') || - setweight(to_tsvector('english', "slug"), 'B') - )); \ No newline at end of file diff --git a/src/db/migrations/0003_flippant_avengers.sql b/src/db/migrations/0003_flippant_avengers.sql deleted file mode 100644 index c4decd1..0000000 --- a/src/db/migrations/0003_flippant_avengers.sql +++ /dev/null @@ -1,5 +0,0 @@ -DROP INDEX IF EXISTS "search_index";--> statement-breakpoint -CREATE INDEX IF NOT EXISTS "search_index" ON "games" USING gin (( - setweight(to_tsvector('english', "name"), 'A') || - setweight(to_tsvector('english', "slug"), 'B') - )); \ No newline at end of file diff --git a/src/db/migrations/meta/0000_snapshot.json b/src/db/migrations/meta/0000_snapshot.json index c0a452f..1d8cec7 100644 --- a/src/db/migrations/meta/0000_snapshot.json +++ b/src/db/migrations/meta/0000_snapshot.json @@ -1,5 +1,5 @@ { - "id": "9622fc3a-51a1-4f66-8535-fd1ceaf46fc2", + "id": "d62b05e0-f6b5-4fad-b160-bb378e0ad3a0", "prevId": "00000000-0000-0000-0000-000000000000", "version": "7", "dialect": "postgresql", @@ -403,13 +403,13 @@ "name": "name", "type": "text", "primaryKey": false, - "notNull": false + "notNull": true }, "slug": { "name": "slug", "type": "text", "primaryKey": false, - "notNull": false + "notNull": true }, "description": { "name": "description", @@ -503,7 +503,7 @@ "name": "search_index", "columns": [ { - "expression": "(\n\t\t\t\t\t\tsetweight(to_tsvector('english', \"name\"), 'A') ||\n\t\t\t\t\t\tsetweight(to_tsvector('english', \"slug\"), 'B')\n\t\t\t\t\t)", + "expression": "(\n setweight(to_tsvector('english', \"name\"), 'A') ||\n setweight(to_tsvector('english', \"slug\"), 'B')\n )", "asc": true, "isExpression": true, "nulls": "last" @@ -1130,6 +1130,20 @@ "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": {}, diff --git a/src/db/migrations/meta/0001_snapshot.json b/src/db/migrations/meta/0001_snapshot.json deleted file mode 100644 index 88c85f9..0000000 --- a/src/db/migrations/meta/0001_snapshot.json +++ /dev/null @@ -1,1540 +0,0 @@ -{ - "id": "e889c835-a89b-4da1-a25b-4a53cbc1c7ee", - "prevId": "9622fc3a-51a1-4f66-8535-fd1ceaf46fc2", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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.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": true - }, - "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.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": false - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "search_index": { - "name": "search_index", - "columns": [ - { - "expression": "(\n\t\t\t\t\t\tsetweight(to_tsvector('english', \"name\"), 'A') ||\n\t\t\t\t\t\tsetweight(to_tsvector('english', \"slug\"), 'B')\n\t\t\t\t\t)", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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 - }, - "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.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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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 - }, - "hashed_password": { - "name": "hashed_password", - "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 - }, - "theme": { - "name": "theme", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'system'" - }, - "two_factor_secret": { - "name": "two_factor_secret", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "''" - }, - "two_factor_enabled": { - "name": "two_factor_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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": {}, - "schemas": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/src/db/migrations/meta/0002_snapshot.json b/src/db/migrations/meta/0002_snapshot.json deleted file mode 100644 index 2c87455..0000000 --- a/src/db/migrations/meta/0002_snapshot.json +++ /dev/null @@ -1,1540 +0,0 @@ -{ - "id": "691e52a6-648a-41a4-9eb3-48a93fa0d3cf", - "prevId": "e889c835-a89b-4da1-a25b-4a53cbc1c7ee", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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.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": true - }, - "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.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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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\t\t\t\tsetweight(to_tsvector('english', \"slug\"), 'B')\n\t\t\t)", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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 - }, - "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.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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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 - }, - "hashed_password": { - "name": "hashed_password", - "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 - }, - "theme": { - "name": "theme", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'system'" - }, - "two_factor_secret": { - "name": "two_factor_secret", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "''" - }, - "two_factor_enabled": { - "name": "two_factor_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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": {}, - "schemas": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/src/db/migrations/meta/0003_snapshot.json b/src/db/migrations/meta/0003_snapshot.json deleted file mode 100644 index e508d86..0000000 --- a/src/db/migrations/meta/0003_snapshot.json +++ /dev/null @@ -1,1540 +0,0 @@ -{ - "id": "500f0ff6-fd55-48af-9029-0fae234b078f", - "prevId": "691e52a6-648a-41a4-9eb3-48a93fa0d3cf", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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.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": true - }, - "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.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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "search_index": { - "name": "search_index", - "columns": [ - { - "expression": "(\n setweight(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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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 - }, - "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.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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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 - }, - "hashed_password": { - "name": "hashed_password", - "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 - }, - "theme": { - "name": "theme", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'system'" - }, - "two_factor_secret": { - "name": "two_factor_secret", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "''" - }, - "two_factor_enabled": { - "name": "two_factor_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp", - "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": {}, - "schemas": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/src/db/migrations/meta/_journal.json b/src/db/migrations/meta/_journal.json index 0996618..9a5d5b2 100644 --- a/src/db/migrations/meta/_journal.json +++ b/src/db/migrations/meta/_journal.json @@ -5,29 +5,8 @@ { "idx": 0, "version": "7", - "when": 1717548517806, - "tag": "0000_spotty_changeling", - "breakpoints": true - }, - { - "idx": 1, - "version": "7", - "when": 1717891533784, - "tag": "0001_acoustic_thunderbolt", - "breakpoints": true - }, - { - "idx": 2, - "version": "7", - "when": 1717891822622, - "tag": "0002_striped_darkhawk", - "breakpoints": true - }, - { - "idx": 3, - "version": "7", - "when": 1717891852881, - "tag": "0003_flippant_avengers", + "when": 1718038929675, + "tag": "0000_flippant_slyde", "breakpoints": true } ] diff --git a/src/db/schema/categories.ts b/src/db/schema/categories.ts index f954806..e0f88cc 100644 --- a/src/db/schema/categories.ts +++ b/src/db/schema/categories.ts @@ -11,8 +11,8 @@ const categories = pgTable('categories', { .$defaultFn(() => cuid2()), name: text('name'), slug: text('slug'), - created_at: timestamp('created_at', { mode: 'string' }).notNull().defaultNow(), - updated_at: timestamp('updated_at', { mode: 'string' }).notNull().defaultNow(), + created_at: timestamp('created_at').notNull().defaultNow(), + updated_at: timestamp('updated_at').notNull().defaultNow(), }); export type Categories = InferSelectModel; diff --git a/src/db/schema/collectionItems.ts b/src/db/schema/collectionItems.ts index 9a3c01e..7ab9859 100644 --- a/src/db/schema/collectionItems.ts +++ b/src/db/schema/collectionItems.ts @@ -16,8 +16,8 @@ const collection_items = pgTable('collection_items', { .notNull() .references(() => games.id, { onDelete: 'cascade' }), times_played: integer('times_played').default(0), - created_at: timestamp('created_at', { mode: 'string' }).notNull().defaultNow(), - updated_at: timestamp('updated_at', { mode: 'string' }).notNull().defaultNow(), + created_at: timestamp('created_at').notNull().defaultNow(), + updated_at: timestamp('updated_at').notNull().defaultNow(), }); export type CollectionItems = InferSelectModel; diff --git a/src/db/schema/collections.ts b/src/db/schema/collections.ts index 3526947..91949c0 100644 --- a/src/db/schema/collections.ts +++ b/src/db/schema/collections.ts @@ -12,8 +12,8 @@ const collections = pgTable('collections', { .notNull() .references(() => users.id, { onDelete: 'cascade' }), name: text('name').notNull().default('My Collection'), - created_at: timestamp('created_at', { mode: 'string' }).notNull().defaultNow(), - updated_at: timestamp('updated_at', { mode: 'string' }).notNull().defaultNow(), + created_at: timestamp('created_at').notNull().defaultNow(), + updated_at: timestamp('updated_at').notNull().defaultNow(), }); export const collection_relations = relations(collections, ({ one }) => ({ diff --git a/src/db/schema/expansions.ts b/src/db/schema/expansions.ts index 28388fd..f29f83d 100644 --- a/src/db/schema/expansions.ts +++ b/src/db/schema/expansions.ts @@ -14,8 +14,8 @@ export const expansions = pgTable('expansions', { game_id: uuid('game_id') .notNull() .references(() => games.id, { onDelete: 'restrict', onUpdate: 'cascade' }), - created_at: timestamp('created_at', { mode: 'string' }).notNull().defaultNow(), - updated_at: timestamp('updated_at', { mode: 'string' }).notNull().defaultNow(), + created_at: timestamp('created_at').notNull().defaultNow(), + updated_at: timestamp('updated_at').notNull().defaultNow(), }); export type Expansions = InferSelectModel; diff --git a/src/db/schema/games.ts b/src/db/schema/games.ts index 9760c53..3feab97 100644 --- a/src/db/schema/games.ts +++ b/src/db/schema/games.ts @@ -27,18 +27,18 @@ const games = pgTable( thumb_url: text('thumb_url'), url: text('url'), last_sync_at: timestamp('last_sync_at'), - created_at: timestamp('created_at', { mode: 'string' }).notNull().defaultNow(), - updated_at: timestamp('updated_at', { mode: 'string' }).notNull().defaultNow(), + created_at: timestamp('created_at').notNull().defaultNow(), + updated_at: timestamp('updated_at').notNull().defaultNow(), }, (table) => ({ - searchIndex: index('search_index').using( - 'gin', - sql`( - setweight(to_tsvector('english', ${table.name}), 'A') || + searchIndex: index('search_index').using( + 'gin', + sql`( + setweight(to_tsvector('english', ${table.name}), 'A') || setweight(to_tsvector('english', ${table.slug}), 'B') - )` - ), - }) + )`, + ), + }), ); export const gameRelations = relations(games, ({ many }) => ({ diff --git a/src/db/schema/index.ts b/src/db/schema/index.ts index 96e5b05..7e64ec8 100644 --- a/src/db/schema/index.ts +++ b/src/db/schema/index.ts @@ -5,7 +5,7 @@ export { password_reset_token_relations, type PasswordResetTokens, } from './passwordResetTokens'; -export { default as sessions } from './sessions'; +export { default as sessions, type Sessions } from './sessions'; export { default as roles, role_relations, type Roles } from './roles'; export { default as userRoles, user_role_relations, type UserRoles } from './userRoles'; export { default as collections, collection_relations, type Collections } from './collections'; @@ -23,6 +23,7 @@ export { export { default as externalIds, type ExternalIds, type ExternalIdType } from './externalIds'; export { default as games, gameRelations, type Games } from './games'; export { default as gamesToExternalIds } from './gamesToExternalIds'; +export { default as expansions, expansions_relations, type Expansions } from './expansions'; export { default as publishers, publishers_relations, type Publishers } from './publishers'; export { default as publishers_to_games, publishers_to_games_relations } from './publishersToGames'; export { default as publishersToExternalIds } from './publishersToExternalIds'; diff --git a/src/db/schema/mechanics.ts b/src/db/schema/mechanics.ts index f8200c7..1f2944e 100644 --- a/src/db/schema/mechanics.ts +++ b/src/db/schema/mechanics.ts @@ -11,8 +11,8 @@ const mechanics = pgTable('mechanics', { .$defaultFn(() => cuid2()), name: text('name'), slug: text('slug'), - created_at: timestamp('created_at', { mode: 'string' }).notNull().defaultNow(), - updated_at: timestamp('updated_at', { mode: 'string' }).notNull().defaultNow(), + created_at: timestamp('created_at').notNull().defaultNow(), + updated_at: timestamp('updated_at').notNull().defaultNow(), }); export type Mechanics = InferSelectModel; diff --git a/src/db/schema/passwordResetTokens.ts b/src/db/schema/passwordResetTokens.ts index 84b4f5a..af7afeb 100644 --- a/src/db/schema/passwordResetTokens.ts +++ b/src/db/schema/passwordResetTokens.ts @@ -10,8 +10,8 @@ const password_reset_tokens = pgTable('password_reset_tokens', { user_id: uuid('user_id') .notNull() .references(() => users.id, { onDelete: 'cascade' }), - expires_at: timestamp('expires_at', { mode: 'string' }), - created_at: timestamp('created_at', { mode: 'string' }).notNull().defaultNow(), + expires_at: timestamp('expires_at'), + created_at: timestamp('created_at').notNull().defaultNow(), }); export type PasswordResetTokens = InferSelectModel; diff --git a/src/db/schema/publishers.ts b/src/db/schema/publishers.ts index c323a91..989bef8 100644 --- a/src/db/schema/publishers.ts +++ b/src/db/schema/publishers.ts @@ -11,8 +11,8 @@ const publishers = pgTable('publishers', { .$defaultFn(() => cuid2()), name: text('name'), slug: text('slug'), - created_at: timestamp('created_at', { mode: 'string' }).notNull().defaultNow(), - updated_at: timestamp('updated_at', { mode: 'string' }).notNull().defaultNow(), + created_at: timestamp('created_at').notNull().defaultNow(), + updated_at: timestamp('updated_at').notNull().defaultNow(), }); export type Publishers = InferSelectModel; diff --git a/src/db/schema/recoveryCodes.ts b/src/db/schema/recoveryCodes.ts index 84e07d5..904d8ea 100644 --- a/src/db/schema/recoveryCodes.ts +++ b/src/db/schema/recoveryCodes.ts @@ -9,8 +9,8 @@ const recovery_codes = pgTable('recovery_codes', { .references(() => users.id), code: text('code').notNull(), used: boolean('used').default(false), - created_at: timestamp('created_at', { mode: 'string' }).notNull().defaultNow(), - updated_at: timestamp('updated_at', { mode: 'string' }).notNull().defaultNow(), + created_at: timestamp('created_at').notNull().defaultNow(), + updated_at: timestamp('updated_at').notNull().defaultNow(), }); export type RecoveryCodes = InferSelectModel; diff --git a/src/db/schema/roles.ts b/src/db/schema/roles.ts index 105a927..65b1b05 100644 --- a/src/db/schema/roles.ts +++ b/src/db/schema/roles.ts @@ -10,8 +10,8 @@ const roles = pgTable('roles', { .$defaultFn(() => cuid2()) .notNull(), name: text('name').unique().notNull(), - created_at: timestamp('created_at', { mode: 'string' }).notNull().defaultNow(), - updated_at: timestamp('updated_at', { mode: 'string' }).notNull().defaultNow(), + created_at: timestamp('created_at').notNull().defaultNow(), + updated_at: timestamp('updated_at').notNull().defaultNow(), }); export type Roles = InferSelectModel; diff --git a/src/db/schema/sessions.ts b/src/db/schema/sessions.ts index 3e67166..79c3b21 100644 --- a/src/db/schema/sessions.ts +++ b/src/db/schema/sessions.ts @@ -1,4 +1,5 @@ import { boolean, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core'; +import { type InferSelectModel } from 'drizzle-orm'; import users from './users'; const sessions = pgTable('sessions', { @@ -12,7 +13,10 @@ const sessions = pgTable('sessions', { }).notNull(), ipCountry: text('ip_country'), ipAddress: text('ip_address'), + twoFactorAuthEnabled: boolean('two_factor_auth_enabled').default(false), isTwoFactorAuthenticated: boolean('is_two_factor_authenticated').default(false), }); +export type Sessions = InferSelectModel; + export default sessions; diff --git a/src/db/schema/userRoles.ts b/src/db/schema/userRoles.ts index f6e92e3..735f78b 100644 --- a/src/db/schema/userRoles.ts +++ b/src/db/schema/userRoles.ts @@ -16,8 +16,8 @@ const user_roles = pgTable('user_roles', { .notNull() .references(() => roles.id, { onDelete: 'cascade' }), primary: boolean('primary').default(false), - created_at: timestamp('created_at', { mode: 'string' }).notNull().defaultNow(), - updated_at: timestamp('updated_at', { mode: 'string' }).notNull().defaultNow(), + created_at: timestamp('created_at').notNull().defaultNow(), + updated_at: timestamp('updated_at').notNull().defaultNow(), }); export const user_role_relations = relations(user_roles, ({ one }) => ({ diff --git a/src/db/schema/users.ts b/src/db/schema/users.ts index 70af196..c075563 100644 --- a/src/db/schema/users.ts +++ b/src/db/schema/users.ts @@ -18,8 +18,8 @@ const users = pgTable('users', { theme: text('theme').default('system'), two_factor_secret: text('two_factor_secret').default(''), two_factor_enabled: boolean('two_factor_enabled').default(false), - created_at: timestamp('created_at', { mode: 'string' }).notNull().defaultNow(), - updated_at: timestamp('updated_at', { mode: 'string' }).notNull().defaultNow(), + created_at: timestamp('created_at').notNull().defaultNow(), + updated_at: timestamp('updated_at').notNull().defaultNow(), }); export const user_relations = relations(users, ({ many }) => ({ diff --git a/src/db/schema/wishlistItems.ts b/src/db/schema/wishlistItems.ts index 206b33c..13be952 100644 --- a/src/db/schema/wishlistItems.ts +++ b/src/db/schema/wishlistItems.ts @@ -15,8 +15,8 @@ const wishlist_items = pgTable('wishlist_items', { game_id: uuid('game_id') .notNull() .references(() => games.id, { onDelete: 'cascade' }), - created_at: timestamp('created_at', { mode: 'string' }).notNull().defaultNow(), - updated_at: timestamp('updated_at', { mode: 'string' }).notNull().defaultNow(), + created_at: timestamp('created_at').notNull().defaultNow(), + updated_at: timestamp('updated_at').notNull().defaultNow(), }); export type WishlistItems = InferSelectModel; diff --git a/src/db/schema/wishlists.ts b/src/db/schema/wishlists.ts index 52dc37d..74aeb2e 100644 --- a/src/db/schema/wishlists.ts +++ b/src/db/schema/wishlists.ts @@ -12,8 +12,8 @@ const wishlists = pgTable('wishlists', { .notNull() .references(() => users.id, { onDelete: 'cascade' }), name: text('name').notNull().default('My Wishlist'), - created_at: timestamp('created_at', { mode: 'string' }).notNull().defaultNow(), - updated_at: timestamp('updated_at', { mode: 'string' }).notNull().defaultNow(), + created_at: timestamp('created_at').notNull().defaultNow(), + updated_at: timestamp('updated_at').notNull().defaultNow(), }); export type Wishlists = InferSelectModel; diff --git a/src/db/seed.ts b/src/db/seed.ts index fce7bb2..479eb87 100644 --- a/src/db/seed.ts +++ b/src/db/seed.ts @@ -1,20 +1,50 @@ -import 'dotenv/config'; -import { drizzle } from 'drizzle-orm/node-postgres'; -import pg from 'pg'; -import * as schema from './schema'; +import { Table, getTableName, sql } from 'drizzle-orm'; import { Argon2id } from 'oslo/password'; +import { ADMIN_USERNAME, DB_SEEDING } from '$env/static/private'; +import { db } from '../db'; +import * as schema from './schema'; +import * as seeds from './seeds'; -// create the connection -const pool = new pg.Pool({ - user: process.env.DATABASE_USER, - password: process.env.DATABASE_PASSWORD, - host: process.env.DATABASE_HOST, - port: Number(process.env.DATABASE_PORT).valueOf(), - database: process.env.DATABASE_DB, - ssl: process.env.DATABASE_HOST !== 'localhost', -}); +if (!DB_SEEDING) { + throw new Error('You must set DB_SEEDING to "true" when running seeds'); +} -const db = drizzle(pool, { schema: schema }); +async function resetTable(db: db, table: Table) { + return db.execute(sql.raw(`TRUNCATE TABLE ${getTableName(table)} RESTART IDENTITY CASCADE`)); +} + +for (const table of [ + schema.categories, + schema.categoriesToExternalIds, + schema.categories_to_games, + schema.collection_items, + schema.collections, + schema.expansions, + schema.externalIds, + schema.games, + schema.gamesToExternalIds, + schema.mechanics, + schema.mechanicsToExternalIds, + schema.mechanics_to_games, + schema.password_reset_tokens, + schema.publishers, + schema.publishersToExternalIds, + schema.publishers_to_games, + schema.recoveryCodes, + schema.roles, + schema.sessions, + schema.userRoles, + schema.users, + schema.wishlists, + schema.wishlist_items, +]) { + // await db.delete(table); // clear tables without truncating / resetting ids + await resetTable(db, table); +} + +await seeds.roles(db); + +await connection.end(); console.log('Creating roles ...'); const adminRole = await db @@ -42,7 +72,7 @@ console.log('Admin Role: ', adminRole); const adminUser = await db .insert(schema.users) .values({ - username: `${process.env.ADMIN_USERNAME}`, + username: `${ADMIN_USERNAME}`, email: '', hashed_password: await new Argon2id().hash(`${process.env.ADMIN_PASSWORD}`), first_name: 'Brad', diff --git a/src/db/seeds/data/roles.json b/src/db/seeds/data/roles.json new file mode 100644 index 0000000..e69de29 diff --git a/src/db/seeds/data/users.json b/src/db/seeds/data/users.json new file mode 100644 index 0000000..64dd254 --- /dev/null +++ b/src/db/seeds/data/users.json @@ -0,0 +1,23 @@ +[ + { + "first_name": "John", + "last_name": "Smith", + "username": "john.smith", + "email": "john.smith@example.com", + "password": "password" + }, + { + "first_name": "Jane", + "last_name": "Doe", + "username": "jane.doe", + "email": "jane.doe@example.com", + "password": "password" + }, + { + "first_name": "Michael", + "last_name": "Jones", + "username": "michael.jones", + "email": "michael.jones@example.com", + "password": "password" + } +] \ No newline at end of file diff --git a/src/db/seeds/roles.ts b/src/db/seeds/roles.ts new file mode 100644 index 0000000..485afac --- /dev/null +++ b/src/db/seeds/roles.ts @@ -0,0 +1,30 @@ +import { eq } from 'drizzle-orm'; +import type db from '@/db'; +import * as schema from '@/db/schema'; +import roles from './data/roles.json'; + +// console.log('Creating roles ...'); +// const adminRole = await db +// .insert(schema.roles) +// .values([{ name: 'admin' }]) +// .onConflictDoNothing() +// .returning(); +// const userRole = await db +// .insert(schema.roles) +// .values([{ name: 'user' }]) +// .onConflictDoNothing() +// .returning(); +// await db +// .insert(schema.roles) +// .values([{ name: 'editor' }]) +// .onConflictDoNothing(); +// await db +// .insert(schema.roles) +// .values([{ name: 'moderator' }]) +// .onConflictDoNothing(); +// console.log('Roles created.'); + +export default async function seed(db: db) { + await db.insert(schema.roles).values({ name: 'user' }); + await db.insert(schema.roles).values({ name: 'admin' }); +} diff --git a/src/db/seeds/users.ts b/src/db/seeds/users.ts new file mode 100644 index 0000000..734cb2b --- /dev/null +++ b/src/db/seeds/users.ts @@ -0,0 +1,41 @@ +import { eq } from 'drizzle-orm'; +import * as argon2 from 'argon2'; +import type db from '@/db'; +import * as schema from '@/db/schema'; +import users from './data/users.json'; + +async function getCityId(db: db, cityName: string) { + const city = await db.query.city.findFirst({ + where: eq(schema.city.name, cityName), + }); + if (!city) { + throw new Error('Unknown city name: ' + cityName); + } + return city.id; +} + +export default async function seed(db: db) { + await Promise.all( + users.map(async (user) => { + const [insertedUser] = await db + .insert(schema.user) + .values({ + ...user, + emailVerified: true, + phoneVerified: true, + password: await argon2.hash(user.password), + }) + .returning(); + await Promise.all( + user.addresses.map(async (address) => { + await db.insert(schema.address).values({ + ...address, + streetAddress1: address.street_address, + userId: insertedUser.id, + cityId: await getCityId(db, address.city), + }); + }), + ); + }), + ); +} diff --git a/src/lib/server/auth-utils.ts b/src/lib/server/auth-utils.ts index b807830..eac9ccf 100644 --- a/src/lib/server/auth-utils.ts +++ b/src/lib/server/auth-utils.ts @@ -1,4 +1,4 @@ -import { generateIdFromEntropySize } from 'lucia'; +import { generateIdFromEntropySize, type Session, type User } from 'lucia'; import { TimeSpan, createDate } from 'oslo'; import { eq } from 'drizzle-orm'; import db from '../../db'; @@ -15,3 +15,14 @@ export async function createPasswordResetToken(userId: string): Promise }); return tokenId; } + +/** + * Checks if the user is fully authenticated. + * + * @param user - The user object. + * @param session - The session object. + * @returns True if the user is fully authenticated, otherwise false. + */ +export function userFullyAuthenticated(user: User | null, session: Session | null) { + return user && session && (!session.isTwoFactorAuthEnabled || session.isTwoFactorAuthenticated); +} diff --git a/src/lib/server/auth.ts b/src/lib/server/auth.ts index 32bb26b..f4dffa9 100644 --- a/src/lib/server/auth.ts +++ b/src/lib/server/auth.ts @@ -20,6 +20,7 @@ export const lucia = new Lucia(adapter, { return { ipCountry: attributes.ip_country, ipAddress: attributes.ip_address, + isTwoFactorAuthEnabled: attributes.twoFactorAuthEnabled, isTwoFactorAuthenticated: attributes.isTwoFactorAuthenticated, }; }, @@ -54,6 +55,7 @@ declare module 'lucia' { interface DatabaseSessionAttributes { ip_country: string; ip_address: string; + twoFactorAuthEnabled: boolean; isTwoFactorAuthenticated: boolean; } interface DatabaseUserAttributes { diff --git a/src/routes/(app)/(protected)/admin/+layout.server.ts b/src/routes/(app)/(protected)/admin/+layout.server.ts index 29aeb84..fcad175 100644 --- a/src/routes/(app)/(protected)/admin/+layout.server.ts +++ b/src/routes/(app)/(protected)/admin/+layout.server.ts @@ -3,14 +3,15 @@ import { forbiddenMessage, notSignedInMessage } from '$lib/flashMessages'; import { eq } from 'drizzle-orm'; import db from '../../../../db'; import { user_roles } from '$db/schema'; +import { userFullyAuthenticated } from '$lib/server/auth-utils'; export const load = loadFlash(async (event) => { const { locals } = event; - if (!locals?.user) { + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { redirect(302, '/login', notSignedInMessage, event); } - const { user } = locals; const userRoles = await db.query.user_roles.findMany({ where: eq(user_roles.user_id, user.id), with: { diff --git a/src/routes/(app)/(protected)/admin/users/+page.server.ts b/src/routes/(app)/(protected)/admin/users/+page.server.ts index 2608744..8479c03 100644 --- a/src/routes/(app)/(protected)/admin/users/+page.server.ts +++ b/src/routes/(app)/(protected)/admin/users/+page.server.ts @@ -2,11 +2,13 @@ import { redirect } from 'sveltekit-flash-message/server'; import type { PageServerLoad } from './$types'; import { notSignedInMessage } from '$lib/flashMessages'; import db from '../../../../../db'; +import { userFullyAuthenticated } from '$lib/server/auth-utils'; export const load: PageServerLoad = async (event) => { - // TODO: Ensure admin user - if (!event.locals.user) { - redirect(302, '/login', notSignedInMessage, event); + const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + return fail(401); } const users = await db.query.users.findMany({ diff --git a/src/routes/(app)/(protected)/collections/+page.server.ts b/src/routes/(app)/(protected)/collections/+page.server.ts index c9f4b5f..1848f70 100644 --- a/src/routes/(app)/(protected)/collections/+page.server.ts +++ b/src/routes/(app)/(protected)/collections/+page.server.ts @@ -8,10 +8,11 @@ import { search_schema } from '$lib/zodValidation.js'; import db from '../../../../db'; import { collection_items, collections, games } from '$db/schema'; import { notSignedInMessage } from '$lib/flashMessages'; +import { userFullyAuthenticated } from '$lib/server/auth-utils'; export async function load(event) { - const user = event.locals.user; - if (!user) { + const { user, session } = event.locals; + if (userFullyAuthenticated(user, session)) { redirect(302, '/login', notSignedInMessage, event); } diff --git a/src/routes/(app)/(protected)/collections/[id]/+page.server.ts b/src/routes/(app)/(protected)/collections/[id]/+page.server.ts index 75f0601..27de484 100644 --- a/src/routes/(app)/(protected)/collections/[id]/+page.server.ts +++ b/src/routes/(app)/(protected)/collections/[id]/+page.server.ts @@ -8,16 +8,16 @@ import db from '../../../../../db'; import { notSignedInMessage } from '$lib/flashMessages.js'; import { collections, games, collection_items } from '$db/schema'; import { search_schema } from '$lib/zodValidation'; -import type { UICollection } from '$lib/types'; +import { userFullyAuthenticated } from '$lib/server/auth-utils'; export async function load(event) { const { locals, params, url } = event; - const { user } = locals; + const { user, session } = locals; const { id } = params; - if (!user) { + + if (userFullyAuthenticated(user, session)) { redirect(302, '/login', notSignedInMessage, event); } - const searchParams = Object.fromEntries(url?.searchParams); console.log('searchParams', searchParams); const q = searchParams?.q; @@ -102,12 +102,14 @@ export async function load(event) { export const actions: Actions = { // Add game to a wishlist add: async (event) => { - const form = await superValidate(event, zod(modifyListGameSchema)); - - if (!event.locals.user) { - return fail(401, {}); + const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + return fail(401); } + const form = await superValidate(event, zod(modifyListGameSchema)); + const user = event.locals.user; const game = await db.query.games.findFirst({ where: eq(games.id, form.data.id), @@ -148,15 +150,19 @@ export const actions: Actions = { } }, // Create new wishlist - create: async ({ locals }) => { - if (!locals.user) { + create: async (event) => { + const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { return fail(401); } return error(405, 'Method not allowed'); }, // Delete a wishlist - delete: async ({ locals }) => { - if (!locals.user) { + delete: async (event) => { + const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { return fail(401); } return error(405, 'Method not allowed'); @@ -164,11 +170,11 @@ export const actions: Actions = { // Remove game from a wishlist remove: async (event) => { const { locals } = event; - const form = await superValidate(event, zod(modifyListGameSchema)); - - if (!locals.user) { + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { return fail(401); } + const form = await superValidate(event, zod(modifyListGameSchema)); const game = await db.query.games.findFirst({ where: eq(games.id, form.data.id), diff --git a/src/routes/(app)/(protected)/collections/add/+page.server.ts b/src/routes/(app)/(protected)/collections/add/+page.server.ts index 5245b71..c6fbd4f 100644 --- a/src/routes/(app)/(protected)/collections/add/+page.server.ts +++ b/src/routes/(app)/(protected)/collections/add/+page.server.ts @@ -1,13 +1,14 @@ -import { redirect } from "@sveltejs/kit"; -import type { PageServerLoad } from "../$types"; -import { notSignedInMessage } from "$lib/flashMessages"; +import { redirect } from '@sveltejs/kit'; +import type { PageServerLoad } from '../$types'; +import { notSignedInMessage } from '$lib/flashMessages'; +import { userFullyAuthenticated } from '$lib/server/auth-utils'; export async function load(event) { const { locals } = event; - const user = locals.user; - if (!user) { + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { redirect(302, '/login', notSignedInMessage, event); } - return {} -} \ No newline at end of file + return {}; +} diff --git a/src/routes/(app)/(protected)/collections/add/bgg/+page.server.ts b/src/routes/(app)/(protected)/collections/add/bgg/+page.server.ts index 96c52e9..5bbfdbb 100644 --- a/src/routes/(app)/(protected)/collections/add/bgg/+page.server.ts +++ b/src/routes/(app)/(protected)/collections/add/bgg/+page.server.ts @@ -1,16 +1,19 @@ -import { redirect } from "@sveltejs/kit"; -import { superValidate } from "sveltekit-superforms/server"; +import { redirect } from '@sveltejs/kit'; +import { superValidate } from 'sveltekit-superforms/server'; import { zod } from 'sveltekit-superforms/adapters'; -import type { PageServerLoad } from "../$types"; -import { BggForm } from "$lib/zodValidation"; +import type { PageServerLoad } from '../$types'; +import { BggForm } from '$lib/zodValidation'; +import { userFullyAuthenticated } from '$lib/server/auth-utils'; +import { notSignedInMessage } from '$lib/flashMessages'; -export const load: PageServerLoad = async ({ locals, fetch }) => { - const user = locals.user; - if (!user) { - redirect(302, '/login'); +export const load: PageServerLoad = async (event) => { + const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + redirect(302, '/login', notSignedInMessage, event); } const form = await superValidate({}, zod(BggForm)); return { form }; -} \ No newline at end of file +}; diff --git a/src/routes/(app)/(protected)/list/+layout.server.ts b/src/routes/(app)/(protected)/list/+layout.server.ts index 4e35753..bbf445b 100644 --- a/src/routes/(app)/(protected)/list/+layout.server.ts +++ b/src/routes/(app)/(protected)/list/+layout.server.ts @@ -2,9 +2,12 @@ import { fail } from '@sveltejs/kit'; import { eq } from 'drizzle-orm'; import db from '../../../../db'; import { wishlists } from '$db/schema'; +import { userFullyAuthenticated } from '$lib/server/auth-utils'; +import { notSignedInMessage } from '$lib/flashMessages'; export async function load({ locals }) { - if (!locals.user) { + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { throw fail(401); } diff --git a/src/routes/(app)/(protected)/list/[id]/+page.server.ts b/src/routes/(app)/(protected)/list/[id]/+page.server.ts index 2a65b36..0bb5762 100644 --- a/src/routes/(app)/(protected)/list/[id]/+page.server.ts +++ b/src/routes/(app)/(protected)/list/[id]/+page.server.ts @@ -5,11 +5,14 @@ import { superValidate } from 'sveltekit-superforms/server'; import db from '../../../../../db'; import { modifyListGameSchema } from '$lib/validations/zod-schemas'; import { games, wishlist_items, wishlists } from '$db/schema'; +import { userFullyAuthenticated } from '$lib/server/auth-utils'; +import { notSignedInMessage } from '$lib/flashMessages'; -export async function load({ params, locals }) { - const user = locals.user; - if (!user) { - redirect(302, '/login'); +export async function load(event) { + const { params, locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + redirect(302, '/login', notSignedInMessage, event); } try { @@ -40,6 +43,10 @@ export const actions: Actions = { // Add game to a wishlist add: async (event) => { const { params, locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + return fail(401); + } const form = await superValidate(event, zod(modifyListGameSchema)); if (!locals.user) { @@ -92,21 +99,27 @@ export const actions: Actions = { }; }, // Create new wishlist - create: async ({ locals }) => { - if (!locals.user) { - throw fail(401); + create: async (event) => { + const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + return fail(401); } }, // Delete a wishlist - delete: async ({ locals }) => { - if (!locals.user) { - throw fail(401); + delete: async (event) => { + const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + return fail(401); } }, // Remove game from a wishlist - remove: async ({ locals }) => { - if (!locals.user) { - throw fail(401); + remove: async (event) => { + const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + return fail(401); } }, }; diff --git a/src/routes/(app)/(protected)/profile/+page.server.ts b/src/routes/(app)/(protected)/profile/+page.server.ts index 048af07..c3a6880 100644 --- a/src/routes/(app)/(protected)/profile/+page.server.ts +++ b/src/routes/(app)/(protected)/profile/+page.server.ts @@ -9,9 +9,12 @@ import { notSignedInMessage } from '$lib/flashMessages'; import db from '../../../../db'; import type { PageServerLoad } from './$types'; import { users } from '$db/schema'; +import { userFullyAuthenticated } from '$lib/server/auth-utils'; export const load: PageServerLoad = async (event) => { - if (!event.locals.user) { + const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { redirect(302, '/login', notSignedInMessage, event); } diff --git a/src/routes/(app)/(protected)/profile/security/password/change/+page.server.ts b/src/routes/(app)/(protected)/profile/security/password/change/+page.server.ts index 8c54a83..d698e3a 100644 --- a/src/routes/(app)/(protected)/profile/security/password/change/+page.server.ts +++ b/src/routes/(app)/(protected)/profile/security/password/change/+page.server.ts @@ -11,12 +11,13 @@ import { lucia } from '$lib/server/auth.js'; import { users } from '$db/schema'; import { notSignedInMessage } from '$lib/flashMessages'; import type { Cookie } from 'lucia'; +import { userFullyAuthenticated } from '$lib/server/auth-utils'; export const load: PageServerLoad = async (event) => { const form = await superValidate(event, zod(changeUserPasswordSchema)); - const user = event.locals.user; - - if (!user) { + const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { redirect(302, '/login', notSignedInMessage, event); } @@ -32,6 +33,12 @@ export const load: PageServerLoad = async (event) => { export const actions: Actions = { default: async (event) => { + const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + return fail(401); + } + const form = await superValidate(event, zod(changeUserPasswordSchema)); if (!form.valid) { diff --git a/src/routes/(app)/(protected)/profile/security/two-factor/+page.server.ts b/src/routes/(app)/(protected)/profile/security/two-factor/+page.server.ts index 7ed80b1..3cd15d4 100644 --- a/src/routes/(app)/(protected)/profile/security/two-factor/+page.server.ts +++ b/src/routes/(app)/(protected)/profile/security/two-factor/+page.server.ts @@ -13,13 +13,15 @@ import { addTwoFactorSchema, removeTwoFactorSchema } from '$lib/validations/acco import { notSignedInMessage } from '$lib/flashMessages'; import db from '../../../../../../db'; import { recovery_codes, users } from '$db/schema'; +import { userFullyAuthenticated } from '$lib/server/auth-utils'; export const load: PageServerLoad = async (event) => { const addTwoFactorForm = await superValidate(event, zod(addTwoFactorSchema)); const removeTwoFactorForm = await superValidate(event, zod(removeTwoFactorSchema)); - const user = event.locals.user; - if (!user) { + const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { redirect(302, '/login', notSignedInMessage, event); } @@ -67,6 +69,12 @@ export const load: PageServerLoad = async (event) => { export const actions: Actions = { enableTwoFactor: async (event) => { + const { params, locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + return fail(401); + } + const addTwoFactorForm = await superValidate(event, zod(addTwoFactorSchema)); if (!addTwoFactorForm.valid) { diff --git a/src/routes/(app)/(protected)/profile/security/two-factor/recovery-codes/+page.server.ts b/src/routes/(app)/(protected)/profile/security/two-factor/recovery-codes/+page.server.ts index f5d4aca..010ba2a 100644 --- a/src/routes/(app)/(protected)/profile/security/two-factor/recovery-codes/+page.server.ts +++ b/src/routes/(app)/(protected)/profile/security/two-factor/recovery-codes/+page.server.ts @@ -6,11 +6,12 @@ import { redirect } from 'sveltekit-flash-message/server'; import { notSignedInMessage } from '$lib/flashMessages'; import type { PageServerLoad } from '../../../$types'; import { recovery_codes, users } from '$db/schema'; +import { userFullyAuthenticated } from '$lib/server/auth-utils'; export const load: PageServerLoad = async (event) => { - const user = event.locals.user; - - if (!user) { + const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { redirect(302, '/login', notSignedInMessage, event); } diff --git a/src/routes/(app)/(protected)/wishlists/+page.server.ts b/src/routes/(app)/(protected)/wishlists/+page.server.ts index 7d7234f..494f79c 100644 --- a/src/routes/(app)/(protected)/wishlists/+page.server.ts +++ b/src/routes/(app)/(protected)/wishlists/+page.server.ts @@ -7,10 +7,12 @@ import { modifyListGameSchema } from '$lib/validations/zod-schemas'; import db from '../../../../db'; import { notSignedInMessage } from '$lib/flashMessages.js'; import { games, wishlist_items, wishlists } from '$db/schema'; +import { userFullyAuthenticated } from '$lib/server/auth-utils'; export async function load(event) { - const user = event.locals.user; - if (!user) { + const { params, locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { redirect(302, '/login', notSignedInMessage, event); } @@ -38,13 +40,13 @@ export const actions: Actions = { // Add game to a wishlist add: async (event) => { const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + return fail(401); + } const form = await superValidate(event, zod(modifyListGameSchema)); try { - if (!locals.user) { - redirect(302, '/login', notSignedInMessage, event); - } - const game = await db.query.games.findFirst({ where: eq(games.id, form.data.id), }); @@ -86,28 +88,31 @@ export const actions: Actions = { // Create new wishlist create: async (event) => { const { locals } = event; - if (!locals.user) { - redirect(302, '/login', notSignedInMessage, event); + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + return fail(401); } return error(405, 'Method not allowed'); }, // Delete a wishlist - delete: async ({ locals }) => { - if (!locals.user) { - redirect(302, '/login'); + delete: async (event) => { + const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + return fail(401); } return error(405, 'Method not allowed'); }, // Remove game from a wishlist remove: async (event) => { - const { locals } = event; + const { params, locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + return fail(401); + } const form = await superValidate(event, zod(modifyListGameSchema)); try { - if (!locals.user) { - redirect(302, '/login', notSignedInMessage, event); - } - const game = await db.query.games.findFirst({ where: eq(games.id, form.data.id), }); diff --git a/src/routes/(app)/(protected)/wishlists/[id]/+page.server.ts b/src/routes/(app)/(protected)/wishlists/[id]/+page.server.ts index 4d56a44..380c34c 100644 --- a/src/routes/(app)/(protected)/wishlists/[id]/+page.server.ts +++ b/src/routes/(app)/(protected)/wishlists/[id]/+page.server.ts @@ -7,11 +7,13 @@ import { modifyListGameSchema } from '$lib/validations/zod-schemas'; import db from '../../../../../db'; import { notSignedInMessage } from '$lib/flashMessages.js'; import { games, wishlist_items, wishlists } from '$db/schema'; +import { userFullyAuthenticated } from '$lib/server/auth-utils'; export async function load(event) { const { params, locals } = event; + const { user, session } = locals; const { id } = params; - if (!locals.user) { + if (userFullyAuthenticated(user, session)) { redirect(302, '/login', notSignedInMessage, event); } @@ -41,13 +43,13 @@ export const actions: Actions = { // Add game to a wishlist add: async (event) => { const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + return fail(401); + } const form = await superValidate(event, zod(modifyListGameSchema)); try { - if (!locals.user) { - redirect(302, '/login', notSignedInMessage, event); - } - const game = await db.query.games.findFirst({ where: eq(games.id, form.data.id), }); @@ -89,28 +91,31 @@ export const actions: Actions = { // Create new wishlist create: async (event) => { const { locals } = event; - if (!locals.user) { - redirect(302, '/login', notSignedInMessage, event); + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + return fail(401); } return error(405, 'Method not allowed'); }, // Delete a wishlist delete: async ({ locals }) => { - if (!locals.user) { - redirect(302, '/login'); + const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + return fail(401); } return error(405, 'Method not allowed'); }, // Remove game from a wishlist remove: async (event) => { const { locals } = event; + const { user, session } = locals; + if (userFullyAuthenticated(user, session)) { + return fail(401); + } const form = await superValidate(event, zod(modifyListGameSchema)); try { - if (!locals.user) { - redirect(302, '/login', notSignedInMessage, event); - } - const game = await db.query.games.findFirst({ where: eq(games.id, form.data.id), }); diff --git a/src/routes/(auth)/login/+page.server.ts b/src/routes/(auth)/login/+page.server.ts index 21ea6dc..c1576bc 100644 --- a/src/routes/(auth)/login/+page.server.ts +++ b/src/routes/(auth)/login/+page.server.ts @@ -10,7 +10,7 @@ import { RateLimiter } from 'sveltekit-rate-limiter/server'; import db from '../../../db'; import { lucia } from '$lib/server/auth'; import { signInSchema } from '$lib/validations/auth'; -import { users, recovery_codes } from '$db/schema'; +import { users, recoveryCodes, type Users } from '$db/schema'; import type { PageServerLoad } from './$types'; export const load: PageServerLoad = async (event) => { @@ -49,10 +49,14 @@ export const actions: Actions = { let session; let sessionCookie; - const user = await db.query.users.findFirst({ + const user: Users | undefined = await db.query.users.findFirst({ where: eq(users.username, form.data.username), }); + if (!user) { + form.data.password = ''; + return setError(form, 'username', 'Your username or password is incorrect.'); + } try { const password = form.data.password; @@ -76,6 +80,10 @@ export const actions: Actions = { session = await lucia.createSession(user.id, { ip_country: locals.country, ip_address: locals.ip, + twoFactorAuthEnabled: + user?.two_factor_enabled && + user?.two_factor_secret !== null && + user?.two_factor_secret !== '', isTwoFactorAuthenticated: false, }); console.log('logging in session', session); @@ -97,7 +105,11 @@ export const actions: Actions = { form.data.username = ''; form.data.password = ''; - if (user?.two_factor_enabled && user?.two_factor_secret) { + if ( + user?.two_factor_enabled && + user?.two_factor_secret !== null && + user?.two_factor_secret !== '' + ) { console.log('redirecting to TOTP page'); const message = { type: 'success', message: 'Please enter your TOTP code.' } as const; redirect(302, '/totp', message, event); diff --git a/src/routes/(auth)/totp/+page.server.ts b/src/routes/(auth)/totp/+page.server.ts index ffa0f16..0366d43 100644 --- a/src/routes/(auth)/totp/+page.server.ts +++ b/src/routes/(auth)/totp/+page.server.ts @@ -12,21 +12,30 @@ import { lucia } from '$lib/server/auth'; import { totpSchema } from '$lib/validations/auth'; import { users, recovery_codes } from '$db/schema'; import type { PageServerLoad } from './$types'; +import { notSignedInMessage } from '$lib/flashMessages'; export const load: PageServerLoad = async (event) => { - if (event.locals.user) { - const user = event.locals.user; + const { user, session } = event.locals; + + if (!user || !session) { + redirect(302, '/login', notSignedInMessage, event); + } + + if (user && session) { const dbUser = await db.query.users.findFirst({ where: eq(users.username, user.username), }); - const session = event.locals.session; const isTwoFactorAuthenticated = session?.isTwoFactorAuthenticated; console.log('session', session); console.log('isTwoFactorAuthenticated', isTwoFactorAuthenticated); - if (isTwoFactorAuthenticated && dbUser?.two_factor_enabled && dbUser?.two_factor_secret) { + if ( + isTwoFactorAuthenticated && + dbUser?.two_factor_enabled && + dbUser?.two_factor_secret !== '' + ) { const message = { type: 'success', message: 'You are already signed in' } as const; throw redirect('/', message, event); } @@ -68,7 +77,11 @@ export const actions: Actions = { const isTwoFactorAuthenticated = session?.isTwoFactorAuthenticated; - if (isTwoFactorAuthenticated && dbUser?.two_factor_enabled && dbUser?.two_factor_secret) { + if ( + isTwoFactorAuthenticated && + dbUser?.two_factor_enabled && + dbUser?.two_factor_secret !== '' + ) { const message = { type: 'success', message: 'You are already signed in' } as const; throw redirect('/', message, event); } @@ -86,12 +99,12 @@ export const actions: Actions = { try { const totpToken = form?.data?.totpToken; - if (dbUser?.two_factor_enabled && dbUser?.two_factor_secret && !totpToken) { + if (dbUser?.two_factor_enabled && dbUser?.two_factor_secret !== '' && !totpToken) { return fail(400, { form, }); - } else if (dbUser?.two_factor_enabled && dbUser?.two_factor_secret && totpToken) { - console.log('totpToken',totpToken); + } else if (dbUser?.two_factor_enabled && dbUser?.two_factor_secret !== '' && totpToken) { + console.log('totpToken', totpToken); const validOTP = await new TOTPController().verify( totpToken, decodeHex(dbUser.two_factor_secret), @@ -113,6 +126,7 @@ export const actions: Actions = { const newSession = await lucia.createSession(dbUser.id, { ip_country: locals.country, ip_address: locals.ip, + twoFactorAuthEnabled: true, isTwoFactorAuthenticated: true, }); console.log('logging in session', newSession);