diff --git a/package.json b/package.json index 9cebec6..5d4c785 100644 --- a/package.json +++ b/package.json @@ -67,8 +67,8 @@ "sveltekit-superforms": "^2.17.0", "tailwindcss": "^3.4.10", "ts-node": "^10.9.2", - "tslib": "^2.6.3", - "tsx": "^4.17.0", + "tslib": "^2.7.0", + "tsx": "^4.18.0", "typescript": "^5.5.4", "vite": "^5.4.2", "vitest": "^1.6.0", @@ -77,7 +77,7 @@ "type": "module", "dependencies": { "@fontsource/fira-mono": "^5.0.14", - "@hono/swagger-ui": "^0.4.0", + "@hono/swagger-ui": "^0.4.1", "@hono/zod-openapi": "^0.15.3", "@hono/zod-validator": "^0.2.2", "@iconify-icons/line-md": "^1.2.30", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1ffc797..739aaed 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^5.0.14 version: 5.0.14 '@hono/swagger-ui': - specifier: ^0.4.0 - version: 0.4.0(hono@4.5.8) + specifier: ^0.4.1 + version: 0.4.1(hono@4.5.8) '@hono/zod-openapi': specifier: ^0.15.3 version: 0.15.3(hono@4.5.8)(zod@3.23.8) @@ -248,7 +248,7 @@ importers: version: 16.1.0(postcss@8.4.41) postcss-load-config: specifier: ^5.1.0 - version: 5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.17.0) + version: 5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.18.0) postcss-preset-env: specifier: ^9.6.0 version: 9.6.0(postcss@8.4.41) @@ -272,7 +272,7 @@ importers: version: 5.0.0-next.175 svelte-check: specifier: ^3.8.6 - version: 3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.17.0))(postcss@8.4.41)(sass@1.77.8)(svelte@5.0.0-next.175) + version: 3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.18.0))(postcss@8.4.41)(sass@1.77.8)(svelte@5.0.0-next.175) svelte-headless-table: specifier: ^0.18.2 version: 0.18.2(svelte@5.0.0-next.175) @@ -281,7 +281,7 @@ importers: version: 3.1.3(svelte@5.0.0-next.175)(typescript@5.5.4) svelte-preprocess: specifier: ^6.0.2 - version: 6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.17.0))(postcss@8.4.41)(sass@1.77.8)(svelte@5.0.0-next.175)(typescript@5.5.4) + version: 6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.18.0))(postcss@8.4.41)(sass@1.77.8)(svelte@5.0.0-next.175)(typescript@5.5.4) svelte-sequential-preprocessor: specifier: ^2.0.1 version: 2.0.1 @@ -301,11 +301,11 @@ importers: specifier: ^10.9.2 version: 10.9.2(@types/node@20.16.1)(typescript@5.5.4) tslib: - specifier: ^2.6.3 - version: 2.6.3 + specifier: ^2.7.0 + version: 2.7.0 tsx: - specifier: ^4.17.0 - version: 4.17.0 + specifier: ^4.18.0 + version: 4.18.0 typescript: specifier: ^5.5.4 version: 5.5.4 @@ -1270,8 +1270,8 @@ packages: '@hapi/topo@5.1.0': resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} - '@hono/swagger-ui@0.4.0': - resolution: {integrity: sha512-8lF+dexzgV2HRM1R/gf49E5djroq4jVMYMSwLkSF9pT0I6sYhuqirFDCRFrBtbbLCBsKzw6f2MF5rS+WY3d7Nw==} + '@hono/swagger-ui@0.4.1': + resolution: {integrity: sha512-kPaJatHffeYQ3yVkHo878hCqwfapqx54FczJVJ+eRWt8J4biyVVMIdCAJb6MyA8bcnHUoTmUpPc7OJAV1VTg2g==} peerDependencies: hono: '*' @@ -4734,8 +4734,11 @@ packages: tslib@2.6.3: resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} - tsx@4.17.0: - resolution: {integrity: sha512-eN4mnDA5UMKDt4YZixo9tBioibaMBpoxBkD+rIPAjVmYERSG0/dWEY1CEFuV89CgASlKL499q8AhmkMnnjtOJg==} + tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + + tsx@4.18.0: + resolution: {integrity: sha512-a1jaKBSVQkd6yEc1/NI7G6yHFfefIcuf3QJST7ZEyn4oQnxLYrZR5uZAM8UrwUa3Ge8suiZHcNS1gNrEvmobqg==} engines: {node: '>=18.0.0'} hasBin: true @@ -5320,17 +5323,17 @@ snapshots: '@emnapi/core@0.45.0': dependencies: - tslib: 2.6.3 + tslib: 2.7.0 optional: true '@emnapi/runtime@0.45.0': dependencies: - tslib: 2.6.3 + tslib: 2.7.0 optional: true '@emnapi/runtime@1.2.0': dependencies: - tslib: 2.6.3 + tslib: 2.7.0 optional: true '@esbuild-kit/core-utils@3.3.2': @@ -5692,7 +5695,7 @@ snapshots: '@hapi/hoek': 9.3.0 optional: true - '@hono/swagger-ui@0.4.0(hono@4.5.8)': + '@hono/swagger-ui@0.4.1(hono@4.5.8)': dependencies: hono: 4.5.8 @@ -6370,7 +6373,7 @@ snapshots: '@swc/helpers@0.5.11': dependencies: - tslib: 2.6.3 + tslib: 2.7.0 '@tsconfig/node10@1.0.11': {} @@ -6382,7 +6385,7 @@ snapshots: '@tybys/wasm-util@0.8.3': dependencies: - tslib: 2.6.3 + tslib: 2.7.0 optional: true '@types/cookie@0.6.0': {} @@ -6754,7 +6757,7 @@ snapshots: msgpackr: 1.11.0 node-abort-controller: 3.1.1 semver: 7.6.3 - tslib: 2.6.3 + tslib: 2.7.0 uuid: 9.0.1 transitivePeerDependencies: - supports-color @@ -8298,14 +8301,14 @@ snapshots: postcss: 8.4.41 ts-node: 10.9.2(@types/node@20.16.1)(typescript@5.5.4) - postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.17.0): + postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.18.0): dependencies: lilconfig: 3.1.1 yaml: 2.4.2 optionalDependencies: jiti: 1.21.6 postcss: 8.4.41 - tsx: 4.17.0 + tsx: 4.18.0 postcss-logical@7.0.1(postcss@8.4.41): dependencies: @@ -8875,14 +8878,14 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-check@3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.17.0))(postcss@8.4.41)(sass@1.77.8)(svelte@5.0.0-next.175): + svelte-check@3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.18.0))(postcss@8.4.41)(sass@1.77.8)(svelte@5.0.0-next.175): dependencies: '@jridgewell/trace-mapping': 0.3.25 chokidar: 3.6.0 picocolors: 1.0.0 sade: 1.8.1 svelte: 5.0.0-next.175 - svelte-preprocess: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.17.0))(postcss@8.4.41)(sass@1.77.8)(svelte@5.0.0-next.175)(typescript@5.5.4) + svelte-preprocess: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.18.0))(postcss@8.4.41)(sass@1.77.8)(svelte@5.0.0-next.175)(typescript@5.5.4) typescript: 5.5.4 transitivePeerDependencies: - '@babel/core' @@ -8938,7 +8941,7 @@ snapshots: dependencies: svelte: 5.0.0-next.175 - svelte-preprocess@5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.17.0))(postcss@8.4.41)(sass@1.77.8)(svelte@5.0.0-next.175)(typescript@5.5.4): + svelte-preprocess@5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.18.0))(postcss@8.4.41)(sass@1.77.8)(svelte@5.0.0-next.175)(typescript@5.5.4): dependencies: '@types/pug': 2.0.10 detect-indent: 6.1.0 @@ -8948,16 +8951,16 @@ snapshots: svelte: 5.0.0-next.175 optionalDependencies: postcss: 8.4.41 - postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.17.0) + postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.18.0) sass: 1.77.8 typescript: 5.5.4 - svelte-preprocess@6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.17.0))(postcss@8.4.41)(sass@1.77.8)(svelte@5.0.0-next.175)(typescript@5.5.4): + svelte-preprocess@6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.18.0))(postcss@8.4.41)(sass@1.77.8)(svelte@5.0.0-next.175)(typescript@5.5.4): dependencies: svelte: 5.0.0-next.175 optionalDependencies: postcss: 8.4.41 - postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.17.0) + postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.41)(tsx@4.18.0) sass: 1.77.8 typescript: 5.5.4 @@ -9169,7 +9172,9 @@ snapshots: tslib@2.6.3: {} - tsx@4.17.0: + tslib@2.7.0: {} + + tsx@4.18.0: dependencies: esbuild: 0.23.0 get-tsconfig: 4.7.5 diff --git a/src/env.ts b/src/env.ts index 469b805..33366fa 100644 --- a/src/env.ts +++ b/src/env.ts @@ -10,21 +10,22 @@ const stringBoolean = z.coerce .default('false'); const EnvSchema = z.object({ - NODE_ENV: z.string().default('development'), + ADMIN_USERNAME: z.string(), + ADMIN_PASSWORD: z.string(), DATABASE_USER: z.string(), DATABASE_PASSWORD: z.string(), DATABASE_HOST: z.string(), DATABASE_PORT: z.coerce.number(), DATABASE_DB: z.string(), + DB_MIGRATING: stringBoolean, + DB_SEEDING: stringBoolean, + NODE_ENV: z.string().default('development'), PUBLIC_SITE_NAME: z.string(), PUBLIC_SITE_URL: z.string(), PUBLIC_UMAMI_DO_NOT_TRACK: z.string(), PUBLIC_UMAMI_ID: z.string(), PUBLIC_UMAMI_URL: z.string(), - DB_MIGRATING: stringBoolean, - DB_SEEDING: stringBoolean, - ADMIN_USERNAME: z.string(), - ADMIN_PASSWORD: z.string(), + REDIS_URL: z.string(), TWO_FACTOR_TIMEOUT: z.coerce.number().default(300000), }); @@ -37,9 +38,9 @@ try { } catch (error) { if (error instanceof ZodError) { let message = 'Missing required values in .env:\n'; - error.issues.forEach((issue) => { - message += issue.path[0] + '\n'; - }); + for (const issue of error.issues) { + message += `${issue.path[0]}\n`; + } const e = new Error(message); e.stack = ''; throw e; diff --git a/src/lib/server/api/common/config.ts b/src/lib/server/api/common/config.ts index 8f82d9d..35d0ae9 100644 --- a/src/lib/server/api/common/config.ts +++ b/src/lib/server/api/common/config.ts @@ -2,13 +2,14 @@ import env from '../../../../env'; const isPreview = process.env.VERCEL_ENV === 'preview' || process.env.VERCEL_ENV === 'development'; -let domain; +let domain: string; if (process.env.NODE_ENV === 'production' || process.env.VERCEL_ENV === 'production') { domain = 'boredgame.vercel.app'; -} else if (isPreview) { +} else if (isPreview && process.env.VERCEL_BRANCH_URL !== undefined) { domain = process.env.VERCEL_BRANCH_URL; } else { domain = 'localhost'; } -export const config = { ...env, isProduction: process.env.NODE_ENV === 'production' || process.env.VERCEL_ENV === 'production', domain }; +export const config = { ...env, isProduction: process.env.NODE_ENV === 'production' + || process.env.VERCEL_ENV === 'production', domain }; diff --git a/src/lib/server/api/controllers/collection.controller.ts b/src/lib/server/api/controllers/collection.controller.ts index 7bc8379..8f61bd1 100644 --- a/src/lib/server/api/controllers/collection.controller.ts +++ b/src/lib/server/api/controllers/collection.controller.ts @@ -24,8 +24,8 @@ export class CollectionController implements Controller { }) .get('/:cuid', requireAuth, async (c) => { const cuid = c.req.param('cuid'); - const user = await this.collectionsService.findOneByCuid(cuid); - return c.json({ user }); + const collection = await this.collectionsService.findOneByCuid(cuid); + return c.json({ collection }); }); } } diff --git a/src/lib/server/api/controllers/wishlist.controller.ts b/src/lib/server/api/controllers/wishlist.controller.ts index 3a8dbb7..90fdc15 100644 --- a/src/lib/server/api/controllers/wishlist.controller.ts +++ b/src/lib/server/api/controllers/wishlist.controller.ts @@ -23,7 +23,6 @@ export class WishlistController implements Controller { }) .get('/:cuid', requireAuth, async (c) => { const cuid = c.req.param('cuid') - console.log(cuid) const wishlist = await this.wishlistsService.findOneByCuid(cuid) return c.json({ wishlist }); }); diff --git a/src/routes/(app)/(protected)/collections/+page.server.ts b/src/routes/(app)/(protected)/collections/+page.server.ts index bd734aa..07e63b5 100644 --- a/src/routes/(app)/(protected)/collections/+page.server.ts +++ b/src/routes/(app)/(protected)/collections/+page.server.ts @@ -4,8 +4,8 @@ import { superValidate } from 'sveltekit-superforms/server'; import { zod } from 'sveltekit-superforms/adapters'; import { redirect } from 'sveltekit-flash-message/server'; import { modifyListGameSchema } from '$lib/validations/zod-schemas'; -import db from '../../../../db'; -import { collection_items, collections, games } from '$db/schema'; +import { db } from '$lib/server/api/infrastructure/database'; +import { collection_items, collections, games } from '$lib/server/api/infrastructure/database/tables'; import { notSignedInMessage } from '$lib/flashMessages'; import { userNotAuthenticated } from '$lib/server/auth-utils'; diff --git a/src/routes/(app)/(protected)/collections/[id]/+error.svelte b/src/routes/(app)/(protected)/collections/[cuid]/+error.svelte similarity index 100% rename from src/routes/(app)/(protected)/collections/[id]/+error.svelte rename to src/routes/(app)/(protected)/collections/[cuid]/+error.svelte diff --git a/src/routes/(app)/(protected)/collections/[id]/+page.server.ts b/src/routes/(app)/(protected)/collections/[cuid]/+page.server.ts similarity index 51% rename from src/routes/(app)/(protected)/collections/[id]/+page.server.ts rename to src/routes/(app)/(protected)/collections/[cuid]/+page.server.ts index b99d52c..c8e3e45 100644 --- a/src/routes/(app)/(protected)/collections/[id]/+page.server.ts +++ b/src/routes/(app)/(protected)/collections/[cuid]/+page.server.ts @@ -3,100 +3,126 @@ import { and, eq } from 'drizzle-orm'; import { zod } from 'sveltekit-superforms/adapters'; import { superValidate } from 'sveltekit-superforms/server'; import { redirect } from 'sveltekit-flash-message/server'; -import { type ListGame, modifyListGameSchema } from '$lib/validations/zod-schemas'; -import db from '../../../../../db'; +import { modifyListGameSchema } from '$lib/validations/zod-schemas'; +import { db } from '$lib/server/api/infrastructure/database'; import { notSignedInMessage } from '$lib/flashMessages.js'; -import { collections, games, collection_items } from '$db/schema'; -import { search_schema } from '$lib/zodValidation'; +import { collections, games, collection_items } from '$lib/server/api/infrastructure/database/tables'; import { userNotAuthenticated } from '$lib/server/auth-utils'; export async function load(event) { - const { locals, params, url } = event; - const { user, session } = locals; - const { id } = params; + const { params, locals } = event; + const { cuid } = params; - if (userNotAuthenticated(user, session)) { - redirect(302, '/login', notSignedInMessage, event); - } - const searchParams = Object.fromEntries(url?.searchParams); - console.log('searchParams', searchParams); - const q = searchParams?.q; - const limit = parseInt(searchParams?.limit) || 10; - const skip = parseInt(searchParams?.skip) || 0; - - const searchData = { - q, - limit, - skip, - }; - - const searchForm = await superValidate(searchData, zod(search_schema)); - const listManageForm = await superValidate(zod(modifyListGameSchema)); - - const collection = await db.query.collections.findFirst({ - columns: { - id: true, - cuid: true, - name: true, - }, - where: and(eq(collections.user_id, user!.id!), eq(collections.cuid, id)), - }); - console.log('collection', collection); - - if (!collection) { - console.log('Collection was not found'); - error(404, 'Collection was not found'); + const authedUser = await locals.getAuthedUser(); + if (!authedUser) { + throw redirect(302, '/login', notSignedInMessage, event); } - const collectionItems = await db.query.collection_items.findMany({ - columns: { - collection_id: true, - times_played: true, - }, - where: eq(collection_items.collection_id, collection.id), - with: { - game: { - columns: { - id: true, - name: true, - thumb_url: true, - }, - }, - }, - offset: skip, - limit, - }); + try { + const { data, errors } = await locals.api.collections[':cuid'].$get({ + param: { cuid } + }).then(locals.parseApiResponse); - console.log('collection_items', collectionItems); - - const items: ListGame[] = []; - for (const item of collectionItems) { - console.log('item', item); - const game = item.game; - if (game) { - items.push({ - game_id: '', - in_wishlist: false, - wishlist_id: '', - id: game.id, - collection_id: item.collection_id, - game_name: game.name ?? "Game doesn't have a name", - thumb_url: game.thumb_url, - times_played: item.times_played ?? 0, - in_collection: true, - }); + if (errors) { + return error(500, 'Failed to fetch collection'); } + + const { collection } = data; + + if (!collection) { + redirect(302, '/404'); + } + + console.log('collection', collection); + + return { + collection, + }; + } catch (e) { + console.error(e); } - return { - searchForm, - listManageForm, - collection: { - name: collection.name, - cuid: collection.cuid ?? '', - }, - items, - }; + redirect(302, '/404'); + + // const searchParams = Object.fromEntries(url?.searchParams); + // console.log('searchParams', searchParams); + // const q = searchParams?.q; + // const limit = parseInt(searchParams?.limit) || 10; + // const skip = parseInt(searchParams?.skip) || 0; + // + // const searchData = { + // q, + // limit, + // skip, + // }; + // + // const searchForm = await superValidate(searchData, zod(search_schema)); + // const listManageForm = await superValidate(zod(modifyListGameSchema)); + // + // const collection = await db.query.collections.findFirst({ + // columns: { + // id: true, + // cuid: true, + // name: true, + // }, + // where: and(eq(collections.user_id, user!.id!), eq(collections.cuid, id)), + // }); + // console.log('collection', collection); + + // if (!collection) { + // console.log('Collection was not found'); + // error(404, 'Collection was not found'); + // } + // + // const collectionItems = await db.query.collection_items.findMany({ + // columns: { + // collection_id: true, + // times_played: true, + // }, + // where: eq(collection_items.collection_id, collection.id), + // with: { + // game: { + // columns: { + // id: true, + // name: true, + // thumb_url: true, + // }, + // }, + // }, + // offset: skip, + // limit, + // }); + // + // console.log('collection_items', collectionItems); + // + // const items: ListGame[] = []; + // for (const item of collectionItems) { + // console.log('item', item); + // const game = item.game; + // if (game) { + // items.push({ + // game_id: '', + // in_wishlist: false, + // wishlist_id: '', + // id: game.id, + // collection_id: item.collection_id, + // game_name: game.name ?? "Game doesn't have a name", + // thumb_url: game.thumb_url, + // times_played: item.times_played ?? 0, + // in_collection: true, + // }); + // } + // } + // + // return { + // searchForm, + // listManageForm, + // collection: { + // name: collection.name, + // cuid: collection.cuid ?? '', + // }, + // items, + // }; } export const actions: Actions = { diff --git a/src/routes/(app)/(protected)/collections/[id]/+page.svelte b/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte similarity index 100% rename from src/routes/(app)/(protected)/collections/[id]/+page.svelte rename to src/routes/(app)/(protected)/collections/[cuid]/+page.svelte 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 9b92587..a074ba2 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 @@ -12,8 +12,8 @@ import { redirect, setFlash } from 'sveltekit-flash-message/server'; import type { PageServerLoad } from '../../$types'; import { addTwoFactorSchema, removeTwoFactorSchema } from '$lib/validations/account'; import { notSignedInMessage } from '$lib/flashMessages'; -import db from '../../../../../../db'; -import { recoveryCodes, twoFactor, usersTable } from '$db/schema'; +import db from '$lib/server/api/infrastructure/database'; +import { recoveryCodes, twoFactor, usersTable } from '$lib/server/api/infrastructure/database/tables'; import { userNotAuthenticated } from '$lib/server/auth-utils'; import env from '../../../../../../env'; diff --git a/src/routes/(app)/(protected)/wishlists/[cuid]/+page.server.ts b/src/routes/(app)/(protected)/wishlists/[cuid]/+page.server.ts index abaf1d3..1e60741 100644 --- a/src/routes/(app)/(protected)/wishlists/[cuid]/+page.server.ts +++ b/src/routes/(app)/(protected)/wishlists/[cuid]/+page.server.ts @@ -28,9 +28,7 @@ export async function load(event) { if (errors) { return error(500, 'Failed to fetch wishlist'); } - console.log('data', data); const { wishlist } = data; - console.log('wishlist', wishlist); if (!wishlist) { redirect(302, '/404');