From e723c7b66a1ba239bf805cff342755b01bfa8470 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Wed, 4 Sep 2024 16:04:41 -0700 Subject: [PATCH 01/29] Refactor hono again. --- .env.example | 30 + drizzle.config.ts | 2 +- oldApis/games/[id]/+server.ts | 20 +- oldApis/games/search/+server.ts | 94 +- oldApis/publisher/[id]/+server.ts | 18 +- .../common/interfaces/controller.interface.ts | 8 - .../common/interfaces/repository.interface.ts | 5 - .../server/api/common/types/async-service.ts | 3 + src/lib/server/api/common/types/config.ts | 26 + src/lib/server/api/common/types/controller.ts | 11 + .../email.interface.ts => types/email.ts} | 0 .../{types/index.ts => common/types/hono.ts} | 0 .../{repository.utils.ts => repository.ts} | 0 .../common/utils/{table.utils.ts => table.ts} | 0 .../api/controllers/collection.controller.ts | 12 +- .../server/api/controllers/iam.controller.ts | 18 +- .../api/controllers/login.controller.ts | 18 +- .../server/api/controllers/mfa.controller.ts | 13 +- .../api/controllers/signup.controller.ts | 18 +- .../server/api/controllers/user.controller.ts | 12 +- .../api/controllers/wishlist.controller.ts | 12 +- src/lib/server/api/databases/migrate.ts | 6 +- ...ng_stick.sql => 0000_volatile_warhawk.sql} | 39 +- .../migrations/0001_noisy_sally_floyd.sql | 2 - .../migrations/0002_fancy_valkyrie.sql | 1 - .../migrations/0003_worried_taskmaster.sql | 32 - .../migrations/0004_heavy_sphinx.sql | 1 - .../migrations/0005_true_mathemanic.sql | 1 - .../migrations/meta/0000_snapshot.json | 159 +- .../migrations/meta/0001_snapshot.json | 1728 --------------- .../migrations/meta/0002_snapshot.json | 1728 --------------- .../migrations/meta/0003_snapshot.json | 1856 ---------------- .../migrations/meta/0004_snapshot.json | 1863 ----------------- .../migrations/meta/0005_snapshot.json | 1863 ----------------- .../databases/migrations/meta/_journal.json | 39 +- src/lib/server/api/databases/seed.ts | 38 +- src/lib/server/api/databases/seeds/roles.ts | 4 +- src/lib/server/api/databases/seeds/users.ts | 25 +- .../api/databases/tables/categories.table.ts | 6 +- .../tables/categoriesToExternalIds.table.ts | 34 + .../tables/categoriesToExternalIdsTable.ts | 37 - ...sToGames.ts => categoriesToGames.table.ts} | 21 +- ...ctionItems.ts => collectionItems.table.ts} | 14 +- .../{collections.ts => collections.table.ts} | 2 +- .../api/databases/tables/credentials.table.ts | 2 +- .../api/databases/tables/expansions.table.ts | 32 + .../server/api/databases/tables/expansions.ts | 32 - .../api/databases/tables/externalIds.table.ts | 16 + .../api/databases/tables/externalIds.ts | 23 - .../tables/federatedIdentity.table.ts | 2 +- .../tables/{games.ts => games.table.ts} | 18 +- .../tables/gamesToExternalIds.table.ts | 22 + .../databases/tables/gamesToExternalIds.ts | 22 - src/lib/server/api/databases/tables/index.ts | 52 +- .../api/databases/tables/mechanics.table.ts | 23 + .../server/api/databases/tables/mechanics.ts | 23 - .../tables/mechanicsToExternalIds.table.ts | 22 + .../tables/mechanicsToExternalIds.ts | 22 - .../tables/mechanicsToGames.table.ts | 34 + .../api/databases/tables/mechanicsToGames.ts | 34 - ...Tokens.ts => passwordResetTokens.table.ts} | 4 +- .../api/databases/tables/publishers.table.ts | 23 + .../server/api/databases/tables/publishers.ts | 23 - .../tables/publishersToExternalIds.table.ts | 22 + .../tables/publishersToExternalIds.ts | 22 - ...sToGames.ts => publishersToGames.table.ts} | 26 +- .../databases/tables/recovery-codes.table.ts | 2 +- .../tables/{roles.ts => roles.table.ts} | 10 +- .../api/databases/tables/two-factor.table.ts | 2 +- .../{userRoles.ts => userRoles.table.ts} | 12 +- .../api/databases/tables/users.table.ts | 4 +- ...ishlistItems.ts => wishlistItems.table.ts} | 20 +- .../{wishlists.ts => wishlists.table.ts} | 10 +- src/lib/server/api/index.ts | 2 +- .../server/api/middleware/auth.middleware.ts | 10 +- .../api/middleware/rate-limiter.middleware.ts | 9 +- .../api/middleware/require-auth.middleware.ts | 15 + src/lib/server/api/packages/lucia.ts | 63 - .../repositories/collections.repository.ts | 41 +- .../repositories/credentials.repository.ts | 55 +- .../repositories/recovery-codes.repository.ts | 19 +- .../api/repositories/roles.repository.ts | 49 +- .../api/repositories/user_roles.repository.ts | 29 +- .../api/repositories/users.repository.ts | 39 +- .../api/repositories/wishlists.repository.ts | 53 +- .../server/api/services/drizzle.service.ts | 33 + src/lib/server/api/services/iam.service.ts | 6 +- .../api/services/loginrequest.service.ts | 6 +- src/lib/server/api/services/lucia.service.ts | 45 + src/lib/server/api/services/redis.service.ts | 18 + src/lib/utils/db/categoryUtils.ts | 8 +- src/lib/utils/db/expansionUtils.ts | 10 +- src/lib/utils/db/gameUtils.ts | 90 +- src/lib/utils/db/mechanicUtils.ts | 22 +- src/lib/utils/db/publisherUtils.ts | 30 +- .../admin/users/[id]/+page.server.ts | 8 +- .../(protected)/admin/users/[id]/+page.svelte | 14 +- .../admin/users/[id]/add-roles-form.svelte | 56 +- .../(protected)/collections/+page.server.ts | 6 +- .../collections/[cuid]/+page.server.ts | 6 +- .../collections/[cuid]/+page.svelte | 52 +- .../(app)/(protected)/list/+layout.server.ts | 4 +- .../(app)/(protected)/list/+layout.svelte | 6 +- .../(protected)/list/[id]/+page.server.ts | 20 +- .../(app)/(protected)/list/[id]/+page.svelte | 12 +- .../(protected)/wishlists/+page.server.ts | 12 +- .../(app)/(protected)/wishlists/+page.svelte | 8 +- .../wishlists/[cuid]/+page.server.ts | 14 +- .../(protected)/wishlists/[cuid]/+page.svelte | 10 +- src/routes/(app)/+page.server.ts | 8 +- src/routes/(app)/+page.svelte | 36 +- src/routes/(app)/about/+page.svelte | 2 +- src/routes/(app)/game/[id]/+page.server.ts | 10 +- src/routes/(app)/search/+error.svelte | 4 +- src/routes/(app)/search/+page.server.ts | 175 +- src/routes/(app)/search/+page.svelte | 62 +- src/routes/(auth)/+layout.svelte | 12 +- src/routes/(auth)/login/+page.server.ts | 5 - src/routes/(auth)/signup/+page.server.ts | 2 +- src/routes/(auth)/totp/+page.server.ts | 18 +- src/routes/+layout.svelte | 117 +- src/search/actions.ts | 72 +- 122 files changed, 1420 insertions(+), 10361 deletions(-) create mode 100644 .env.example delete mode 100644 src/lib/server/api/common/interfaces/controller.interface.ts delete mode 100644 src/lib/server/api/common/interfaces/repository.interface.ts create mode 100644 src/lib/server/api/common/types/async-service.ts create mode 100644 src/lib/server/api/common/types/config.ts create mode 100644 src/lib/server/api/common/types/controller.ts rename src/lib/server/api/common/{interfaces/email.interface.ts => types/email.ts} (100%) rename src/lib/server/api/{types/index.ts => common/types/hono.ts} (100%) rename src/lib/server/api/common/utils/{repository.utils.ts => repository.ts} (100%) rename src/lib/server/api/common/utils/{table.utils.ts => table.ts} (100%) rename src/lib/server/api/databases/migrations/{0000_dazzling_stick.sql => 0000_volatile_warhawk.sql} (92%) delete mode 100644 src/lib/server/api/databases/migrations/0001_noisy_sally_floyd.sql delete mode 100644 src/lib/server/api/databases/migrations/0002_fancy_valkyrie.sql delete mode 100644 src/lib/server/api/databases/migrations/0003_worried_taskmaster.sql delete mode 100644 src/lib/server/api/databases/migrations/0004_heavy_sphinx.sql delete mode 100644 src/lib/server/api/databases/migrations/0005_true_mathemanic.sql delete mode 100644 src/lib/server/api/databases/migrations/meta/0001_snapshot.json delete mode 100644 src/lib/server/api/databases/migrations/meta/0002_snapshot.json delete mode 100644 src/lib/server/api/databases/migrations/meta/0003_snapshot.json delete mode 100644 src/lib/server/api/databases/migrations/meta/0004_snapshot.json delete mode 100644 src/lib/server/api/databases/migrations/meta/0005_snapshot.json create mode 100644 src/lib/server/api/databases/tables/categoriesToExternalIds.table.ts delete mode 100644 src/lib/server/api/databases/tables/categoriesToExternalIdsTable.ts rename src/lib/server/api/databases/tables/{categoriesToGames.ts => categoriesToGames.table.ts} (65%) rename src/lib/server/api/databases/tables/{collectionItems.ts => collectionItems.table.ts} (70%) rename src/lib/server/api/databases/tables/{collections.ts => collections.table.ts} (91%) create mode 100644 src/lib/server/api/databases/tables/expansions.table.ts delete mode 100644 src/lib/server/api/databases/tables/expansions.ts create mode 100644 src/lib/server/api/databases/tables/externalIds.table.ts delete mode 100644 src/lib/server/api/databases/tables/externalIds.ts rename src/lib/server/api/databases/tables/{games.ts => games.table.ts} (69%) create mode 100644 src/lib/server/api/databases/tables/gamesToExternalIds.table.ts delete mode 100644 src/lib/server/api/databases/tables/gamesToExternalIds.ts create mode 100644 src/lib/server/api/databases/tables/mechanics.table.ts delete mode 100644 src/lib/server/api/databases/tables/mechanics.ts create mode 100644 src/lib/server/api/databases/tables/mechanicsToExternalIds.table.ts delete mode 100644 src/lib/server/api/databases/tables/mechanicsToExternalIds.ts create mode 100644 src/lib/server/api/databases/tables/mechanicsToGames.table.ts delete mode 100644 src/lib/server/api/databases/tables/mechanicsToGames.ts rename src/lib/server/api/databases/tables/{passwordResetTokens.ts => passwordResetTokens.table.ts} (82%) create mode 100644 src/lib/server/api/databases/tables/publishers.table.ts delete mode 100644 src/lib/server/api/databases/tables/publishers.ts create mode 100644 src/lib/server/api/databases/tables/publishersToExternalIds.table.ts delete mode 100644 src/lib/server/api/databases/tables/publishersToExternalIds.ts rename src/lib/server/api/databases/tables/{publishersToGames.ts => publishersToGames.table.ts} (50%) rename src/lib/server/api/databases/tables/{roles.ts => roles.table.ts} (59%) rename src/lib/server/api/databases/tables/{userRoles.ts => userRoles.table.ts} (74%) rename src/lib/server/api/databases/tables/{wishlistItems.ts => wishlistItems.table.ts} (56%) rename src/lib/server/api/databases/tables/{wishlists.ts => wishlists.table.ts} (66%) create mode 100644 src/lib/server/api/middleware/require-auth.middleware.ts delete mode 100644 src/lib/server/api/packages/lucia.ts create mode 100644 src/lib/server/api/services/drizzle.service.ts create mode 100644 src/lib/server/api/services/lucia.service.ts create mode 100644 src/lib/server/api/services/redis.service.ts diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..7b3b671 --- /dev/null +++ b/.env.example @@ -0,0 +1,30 @@ +# Private +ORIGIN=http://localhost:5173 + +NODE_ENV=development + +DATABASE_USER='postgres' +DATABASE_PASSWORD='postgres' +DATABASE_HOST='localhost' +DATABASE_PORT=5432 +DATABASE_DB='postgres' + +REDIS_URL='redis://127.0.0.1:6379/0' + +DB_MIGRATING='false' +DB_SEEDING='false' +ADMIN_USERNAME= +ADMIN_PASSWORD= + +TWO_FACTOR_TIMEOUT=300000 + +# Public + +PUBLIC_SITE_NAME='Bored Game' +PUBLIC_SITE_URL='http://localhost:5173' +PUBLIC_UMAMI_DO_NOT_TRACK=true +PUBLIC_UMAMI_URL= +PUBLIC_UMAMI_ID= + +# quick setting for key-combo only +SVELTE_INSPECTOR_TOGGLE=control-shift-i diff --git a/drizzle.config.ts b/drizzle.config.ts index f4618ee..3f213c5 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -5,7 +5,7 @@ import env from './src/env' export default defineConfig({ dialect: 'postgresql', out: './src/lib/server/api/databases/migrations', - schema: './src/lib/server/api/databases/tables/drizzle.ts', + schema: './src/lib/server/api/databases/tables/*.table.ts', dbCredentials: { host: env.DATABASE_HOST || 'localhost', port: Number(env.DATABASE_PORT) || 5432, diff --git a/oldApis/games/[id]/+server.ts b/oldApis/games/[id]/+server.ts index afe3581..8f10e6c 100644 --- a/oldApis/games/[id]/+server.ts +++ b/oldApis/games/[id]/+server.ts @@ -1,20 +1,20 @@ -import { error, json } from '@sveltejs/kit'; -import { getGame } from '$lib/utils/db/gameUtils.js'; +import { getGame } from '$lib/utils/db/gameUtils.js' +import { error, json } from '@sveltejs/kit' export const GET = async ({ locals, params }) => { - const game_id = Number(params.id).valueOf(); + const game_id = Number(params.id).valueOf() // TODO: Debounce excessive calls and possibly throttle if (isNaN(game_id) || !isFinite(game_id)) { - error(400, { message: 'Invalid game id' }); + error(400, { message: 'Invalid game id' }) } try { - return json(await getGame(locals, params.id)); + return json(await getGame(locals, params.id)) } catch (e) { - console.error(e); - return new Response('Could not get games', { - status: 500 - }); + console.error(e) + return new Response('Could not get gamesTable', { + status: 500, + }) } -} \ No newline at end of file +} diff --git a/oldApis/games/search/+server.ts b/oldApis/games/search/+server.ts index 1df29da..aac02df 100644 --- a/oldApis/games/search/+server.ts +++ b/oldApis/games/search/+server.ts @@ -1,44 +1,34 @@ -import { error, json } from '@sveltejs/kit'; -import db from '../../../../db'; -import { asc, desc, eq, ilike, or } from 'drizzle-orm'; -import { games } from '$db/schema'; -import kebabCase from 'just-kebab-case'; -import { - FilterSchema, - PaginationSchema, - SearchSchema, - SortSchema, -} from '$lib/validations/zod-schemas'; +import { games } from '$db/schema' +import { FilterSchema, PaginationSchema, SearchSchema, SortSchema } from '$lib/validations/zod-schemas' +import { error, json } from '@sveltejs/kit' +import { asc, desc, eq, ilike, or } from 'drizzle-orm' +import kebabCase from 'just-kebab-case' +import db from '../../../../db' // Search a user's collection export const GET = async ({ url, locals }) => { - const searchParams = Object.fromEntries(url.searchParams); + const searchParams = Object.fromEntries(url.searchParams) - const searchGames = PaginationSchema.merge(FilterSchema) - .merge(SortSchema) - .merge(SearchSchema) - .parse(searchParams); + const searchGames = PaginationSchema.merge(FilterSchema).merge(SortSchema).merge(SearchSchema).parse(searchParams) if (searchGames.status !== 'success') { - error(400, 'Invalid request'); + error(400, 'Invalid request') } - const q = searchParams?.q?.trim() || ''; - const limit = parseInt(searchParams?.limit) || 10; - const skip = parseInt(searchParams?.skip) || 0; - const order: OrderDirection = searchParams?.order === 'desc' ? 'desc' : 'asc'; - const exact = searchParams?.exact === 'true'; - let orderBy = searchParams?.orderBy || 'slug'; + const q = searchParams?.q?.trim() || '' + const limit = parseInt(searchParams?.limit) || 10 + const skip = parseInt(searchParams?.skip) || 0 + const order: OrderDirection = searchParams?.order === 'desc' ? 'desc' : 'asc' + const exact = searchParams?.exact === 'true' + let orderBy = searchParams?.orderBy || 'slug' if (orderBy === 'name') { - orderBy = 'slug'; + orderBy = 'slug' } - console.log( - `q: ${q}, limit: ${limit}, skip: ${skip}, order: ${order}, exact: ${exact}, orderBy: ${orderBy}`, - ); - console.log(exact); + console.log(`q: ${q}, limit: ${limit}, skip: ${skip}, order: ${order}, exact: ${exact}, orderBy: ${orderBy}`) + console.log(exact) if (exact) { - console.log('Exact Search API'); + console.log('Exact Search API') const game = await db.query.games.findFirst({ where: eq(games.name, q), columns: { @@ -47,14 +37,14 @@ export const GET = async ({ url, locals }) => { slug: true, thumb_url: true, }, - }); + }) if (!game) { - error(404, { message: 'No games found' }); + error(404, { message: 'No gamesTable found' }) } - const foundGames = [game]; - console.log('Games found in Exact Search API', JSON.stringify(foundGames, null, 2)); - return json(foundGames); + const foundGames = [game] + console.log('Games found in Exact Search API', JSON.stringify(foundGames, null, 2)) + return json(foundGames) } else { const foundGames = (await db @@ -68,37 +58,37 @@ export const GET = async ({ url, locals }) => { .where(or(ilike(games.name, `%${q}%`), ilike(games.slug, `%${kebabCase(q)}%`))) .orderBy(getOrderDirection(order)(getOrderBy(orderBy))) .offset(skip) - .limit(limit)) || []; + .limit(limit)) || [] // const foundGames = await db.select({ - // id: games.id, - // name: games.name, - // slug: games.slug, - // thumb_url: games.thumb_url + // id: gamesTable.id, + // name: gamesTable.name, + // slug: gamesTable.slug, + // thumb_url: gamesTable.thumb_url // }) - // .from(games) - // .where(sql`to_tsvector('simple', ${games.name}) || to_tsvector('simple', ${games.slug}) @@ to_tsquery('simple', ${q})`) + // .from(gamesTable) + // .where(sql`to_tsvector('simple', ${gamesTable.name}) || to_tsvector('simple', ${gamesTable.slug}) @@ to_tsquery('simple', ${q})`) // .orderBy(sql`${orderBy} ${order}`).offset(skip).limit(limit) || []; if (foundGames.length === 0) { - error(404, { message: 'No games found' }); + error(404, { message: 'No gamesTable found' }) } - console.log('Games found in Search API', JSON.stringify(foundGames, null, 2)); - return json(foundGames); + console.log('Games found in Search API', JSON.stringify(foundGames, null, 2)) + return json(foundGames) } -}; +} -type OrderDirection = 'asc' | 'desc'; +type OrderDirection = 'asc' | 'desc' const getOrderDirection = (direction: OrderDirection) => { - return direction === 'asc' ? asc : desc; -}; + return direction === 'asc' ? asc : desc +} const getOrderBy = (orderBy: string) => { switch (orderBy) { case 'name': - return games.name; + return games.name case 'slug': - return games.slug; + return games.slug default: - return games.slug; + return games.slug } -}; +} diff --git a/oldApis/publisher/[id]/+server.ts b/oldApis/publisher/[id]/+server.ts index 6f2d9d6..9d5a51d 100644 --- a/oldApis/publisher/[id]/+server.ts +++ b/oldApis/publisher/[id]/+server.ts @@ -1,19 +1,19 @@ -import { getPublisher, updatePublisher } from '$lib/utils/db/publisherUtils.js'; -import type { Publishers } from '$db/schema'; +import type { Publishers } from '$db/schema' +import { getPublisher, updatePublisher } from '$lib/utils/db/publisherUtils.js' export async function GET({ locals, params }) { try { - return await getPublisher(locals, params.id); + return await getPublisher(locals, params.id) } catch (e) { - console.error(e); - return new Response('Could not get publishers', { + console.error(e) + return new Response('Could not get publishersTable', { status: 500, - }); + }) } } export async function PUT({ locals, params, request }) { - const data: Publishers = await request.json(); - const publisherId = params.id; - return await updatePublisher(locals, data, publisherId); + const data: Publishers = await request.json() + const publisherId = params.id + return await updatePublisher(locals, data, publisherId) } diff --git a/src/lib/server/api/common/interfaces/controller.interface.ts b/src/lib/server/api/common/interfaces/controller.interface.ts deleted file mode 100644 index 7bb91a2..0000000 --- a/src/lib/server/api/common/interfaces/controller.interface.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Hono } from 'hono' -import type { BlankSchema } from 'hono/types' -import type { HonoTypes } from '../../types' - -export interface Controller { - controller: Hono - routes(): any -} diff --git a/src/lib/server/api/common/interfaces/repository.interface.ts b/src/lib/server/api/common/interfaces/repository.interface.ts deleted file mode 100644 index fc96e24..0000000 --- a/src/lib/server/api/common/interfaces/repository.interface.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { DatabaseProvider } from '$lib/server/api/providers/database.provider' - -export interface Repository { - trxHost(trx: DatabaseProvider): any -} diff --git a/src/lib/server/api/common/types/async-service.ts b/src/lib/server/api/common/types/async-service.ts new file mode 100644 index 0000000..868e17e --- /dev/null +++ b/src/lib/server/api/common/types/async-service.ts @@ -0,0 +1,3 @@ +export abstract class AsyncService { + async init(): Promise {} +} diff --git a/src/lib/server/api/common/types/config.ts b/src/lib/server/api/common/types/config.ts new file mode 100644 index 0000000..1a53090 --- /dev/null +++ b/src/lib/server/api/common/types/config.ts @@ -0,0 +1,26 @@ +export interface Config { + isProduction: boolean + api: ApiConfig + storage: StorageConfig + redis: RedisConfig + postgres: PostgresConfig +} + +interface ApiConfig { + origin: string +} + +interface StorageConfig { + accessKey: string + secretKey: string + bucket: string + url: string +} + +interface RedisConfig { + url: string +} + +interface PostgresConfig { + url: string +} diff --git a/src/lib/server/api/common/types/controller.ts b/src/lib/server/api/common/types/controller.ts new file mode 100644 index 0000000..fd77884 --- /dev/null +++ b/src/lib/server/api/common/types/controller.ts @@ -0,0 +1,11 @@ +import { Hono } from 'hono' +import type { BlankSchema } from 'hono/types' +import type { HonoTypes } from './hono' + +export abstract class Controller { + protected readonly controller: Hono + constructor() { + this.controller = new Hono() + } + abstract routes(): Hono +} diff --git a/src/lib/server/api/common/interfaces/email.interface.ts b/src/lib/server/api/common/types/email.ts similarity index 100% rename from src/lib/server/api/common/interfaces/email.interface.ts rename to src/lib/server/api/common/types/email.ts diff --git a/src/lib/server/api/types/index.ts b/src/lib/server/api/common/types/hono.ts similarity index 100% rename from src/lib/server/api/types/index.ts rename to src/lib/server/api/common/types/hono.ts diff --git a/src/lib/server/api/common/utils/repository.utils.ts b/src/lib/server/api/common/utils/repository.ts similarity index 100% rename from src/lib/server/api/common/utils/repository.utils.ts rename to src/lib/server/api/common/utils/repository.ts diff --git a/src/lib/server/api/common/utils/table.utils.ts b/src/lib/server/api/common/utils/table.ts similarity index 100% rename from src/lib/server/api/common/utils/table.utils.ts rename to src/lib/server/api/common/utils/table.ts diff --git a/src/lib/server/api/controllers/collection.controller.ts b/src/lib/server/api/controllers/collection.controller.ts index 169e6b5..56a53aa 100644 --- a/src/lib/server/api/controllers/collection.controller.ts +++ b/src/lib/server/api/controllers/collection.controller.ts @@ -1,16 +1,14 @@ import 'reflect-metadata' -import type { Controller } from '$lib/server/api/common/interfaces/controller.interface' +import { Controller } from '$lib/server/api/common/types/controller' import { CollectionsService } from '$lib/server/api/services/collections.service' -import { Hono } from 'hono' import { inject, injectable } from 'tsyringe' import { requireAuth } from '../middleware/auth.middleware' -import type { HonoTypes } from '../types' @injectable() -export class CollectionController implements Controller { - controller = new Hono() - - constructor(@inject(CollectionsService) private readonly collectionsService: CollectionsService) {} +export class CollectionController extends Controller { + constructor(@inject(CollectionsService) private readonly collectionsService: CollectionsService) { + super() + } routes() { return this.controller diff --git a/src/lib/server/api/controllers/iam.controller.ts b/src/lib/server/api/controllers/iam.controller.ts index df28fb0..708b7ef 100644 --- a/src/lib/server/api/controllers/iam.controller.ts +++ b/src/lib/server/api/controllers/iam.controller.ts @@ -1,26 +1,24 @@ import { StatusCodes } from '$lib/constants/status-codes' -import type { Controller } from '$lib/server/api/common/interfaces/controller.interface' +import { Controller } from '$lib/server/api/common/types/controller' import { updateEmailDto } from '$lib/server/api/dtos/update-email.dto' import { updateProfileDto } from '$lib/server/api/dtos/update-profile.dto' import { verifyPasswordDto } from '$lib/server/api/dtos/verify-password.dto' import { limiter } from '$lib/server/api/middleware/rate-limiter.middleware' -import { LuciaProvider } from '$lib/server/api/providers/lucia.provider' import { IamService } from '$lib/server/api/services/iam.service' +import { LuciaService } from '$lib/server/api/services/lucia.service' import { zValidator } from '@hono/zod-validator' -import { Hono } from 'hono' import { setCookie } from 'hono/cookie' import { inject, injectable } from 'tsyringe' import { requireAuth } from '../middleware/auth.middleware' -import type { HonoTypes } from '../types' @injectable() -export class IamController implements Controller { - controller = new Hono() - +export class IamController extends Controller { constructor( @inject(IamService) private readonly iamService: IamService, - @inject(LuciaProvider) private lucia: LuciaProvider, - ) {} + @inject(LuciaService) private luciaService: LuciaService, + ) { + super() + } routes() { return this.controller @@ -59,7 +57,7 @@ export class IamController implements Controller { .post('/logout', requireAuth, async (c) => { const sessionId = c.var.session.id await this.iamService.logout(sessionId) - const sessionCookie = this.lucia.createBlankSessionCookie() + const sessionCookie = this.luciaService.lucia.createBlankSessionCookie() setCookie(c, sessionCookie.name, sessionCookie.value, { path: sessionCookie.attributes.path, maxAge: sessionCookie.attributes.maxAge, diff --git a/src/lib/server/api/controllers/login.controller.ts b/src/lib/server/api/controllers/login.controller.ts index df9ed50..ea12bf3 100644 --- a/src/lib/server/api/controllers/login.controller.ts +++ b/src/lib/server/api/controllers/login.controller.ts @@ -1,30 +1,28 @@ import 'reflect-metadata' -import type { Controller } from '$lib/server/api/common/interfaces/controller.interface' +import { Controller } from '$lib/server/api/common/types/controller' import { signinUsernameDto } from '$lib/server/api/dtos/signin-username.dto' -import { LuciaProvider } from '$lib/server/api/providers/lucia.provider' +import { LuciaService } from '$lib/server/api/services/lucia.service' import { zValidator } from '@hono/zod-validator' -import { Hono } from 'hono' import { setCookie } from 'hono/cookie' import { TimeSpan } from 'oslo' import { inject, injectable } from 'tsyringe' import { limiter } from '../middleware/rate-limiter.middleware' import { LoginRequestsService } from '../services/loginrequest.service' -import type { HonoTypes } from '../types' @injectable() -export class LoginController implements Controller { - controller = new Hono() - +export class LoginController extends Controller { constructor( @inject(LoginRequestsService) private readonly loginRequestsService: LoginRequestsService, - @inject(LuciaProvider) private lucia: LuciaProvider, - ) {} + @inject(LuciaService) private luciaService: LuciaService, + ) { + super() + } routes() { return this.controller.post('/', zValidator('json', signinUsernameDto), limiter({ limit: 10, minutes: 60 }), async (c) => { const { username, password } = c.req.valid('json') const session = await this.loginRequestsService.verify({ username, password }, c.req) - const sessionCookie = this.lucia.createSessionCookie(session.id) + const sessionCookie = this.luciaService.lucia.createSessionCookie(session.id) console.log('set cookie', sessionCookie) setCookie(c, sessionCookie.name, sessionCookie.value, { path: sessionCookie.attributes.path, diff --git a/src/lib/server/api/controllers/mfa.controller.ts b/src/lib/server/api/controllers/mfa.controller.ts index 9285b79..8f90e03 100644 --- a/src/lib/server/api/controllers/mfa.controller.ts +++ b/src/lib/server/api/controllers/mfa.controller.ts @@ -1,27 +1,24 @@ import 'reflect-metadata' import { StatusCodes } from '$lib/constants/status-codes' -import type { Controller } from '$lib/server/api/common/interfaces/controller.interface' +import { Controller } from '$lib/server/api/common/types/controller' import { verifyTotpDto } from '$lib/server/api/dtos/verify-totp.dto' -import { db } from '$lib/server/api/packages/drizzle' import { RecoveryCodesService } from '$lib/server/api/services/recovery-codes.service' import { TotpService } from '$lib/server/api/services/totp.service' import { UsersService } from '$lib/server/api/services/users.service' import { zValidator } from '@hono/zod-validator' -import { Hono } from 'hono' import { inject, injectable } from 'tsyringe' import { CredentialsType } from '../databases/tables' import { requireAuth } from '../middleware/auth.middleware' -import type { HonoTypes } from '../types' @injectable() -export class MfaController implements Controller { - controller = new Hono() - +export class MfaController extends Controller { constructor( @inject(RecoveryCodesService) private readonly recoveryCodesService: RecoveryCodesService, @inject(TotpService) private readonly totpService: TotpService, @inject(UsersService) private readonly usersService: UsersService, - ) {} + ) { + super() + } routes() { return this.controller diff --git a/src/lib/server/api/controllers/signup.controller.ts b/src/lib/server/api/controllers/signup.controller.ts index 67a7b24..40b1699 100644 --- a/src/lib/server/api/controllers/signup.controller.ts +++ b/src/lib/server/api/controllers/signup.controller.ts @@ -1,26 +1,24 @@ import 'reflect-metadata' -import type { Controller } from '$lib/server/api/common/interfaces/controller.interface' +import { Controller } from '$lib/server/api/common/types/controller' import { signupUsernameEmailDto } from '$lib/server/api/dtos/signup-username-email.dto' import { limiter } from '$lib/server/api/middleware/rate-limiter.middleware' -import { LuciaProvider } from '$lib/server/api/providers/lucia.provider' import { LoginRequestsService } from '$lib/server/api/services/loginrequest.service' +import { LuciaService } from '$lib/server/api/services/lucia.service' import { UsersService } from '$lib/server/api/services/users.service' import { zValidator } from '@hono/zod-validator' -import { Hono } from 'hono' import { setCookie } from 'hono/cookie' import { TimeSpan } from 'oslo' import { inject, injectable } from 'tsyringe' -import type { HonoTypes } from '../types' @injectable() -export class SignupController implements Controller { - controller = new Hono() - +export class SignupController extends Controller { constructor( @inject(UsersService) private readonly usersService: UsersService, @inject(LoginRequestsService) private readonly loginRequestService: LoginRequestsService, - @inject(LuciaProvider) private lucia: LuciaProvider, - ) {} + @inject(LuciaService) private luciaService: LuciaService, + ) { + super() + } routes() { return this.controller.post('/', zValidator('json', signupUsernameEmailDto), limiter({ limit: 10, minutes: 60 }), async (c) => { @@ -38,7 +36,7 @@ export class SignupController implements Controller { } const session = await this.loginRequestService.createUserSession(user.id, c.req, undefined) - const sessionCookie = this.lucia.createSessionCookie(session.id) + const sessionCookie = this.luciaService.lucia.createSessionCookie(session.id) console.log('set cookie', sessionCookie) setCookie(c, sessionCookie.name, sessionCookie.value, { path: sessionCookie.attributes.path, diff --git a/src/lib/server/api/controllers/user.controller.ts b/src/lib/server/api/controllers/user.controller.ts index ec8d7a1..e7c5deb 100644 --- a/src/lib/server/api/controllers/user.controller.ts +++ b/src/lib/server/api/controllers/user.controller.ts @@ -1,16 +1,14 @@ import 'reflect-metadata' -import type { Controller } from '$lib/server/api/common/interfaces/controller.interface' +import { Controller } from '$lib/server/api/common/types/controller' import { UsersService } from '$lib/server/api/services/users.service' -import { Hono } from 'hono' import { inject, injectable } from 'tsyringe' import { requireAuth } from '../middleware/auth.middleware' -import type { HonoTypes } from '../types' @injectable() -export class UserController implements Controller { - controller = new Hono() - - constructor(@inject(UsersService) private readonly usersService: UsersService) {} +export class UserController extends Controller { + constructor(@inject(UsersService) private readonly usersService: UsersService) { + super() + } routes() { return this.controller diff --git a/src/lib/server/api/controllers/wishlist.controller.ts b/src/lib/server/api/controllers/wishlist.controller.ts index 9c19d37..44a4a11 100644 --- a/src/lib/server/api/controllers/wishlist.controller.ts +++ b/src/lib/server/api/controllers/wishlist.controller.ts @@ -1,16 +1,14 @@ import 'reflect-metadata' -import type { Controller } from '$lib/server/api/common/interfaces/controller.interface' +import { Controller } from '$lib/server/api/common/types/controller' import { WishlistsService } from '$lib/server/api/services/wishlists.service' -import { Hono } from 'hono' import { inject, injectable } from 'tsyringe' import { requireAuth } from '../middleware/auth.middleware' -import type { HonoTypes } from '../types' @injectable() -export class WishlistController implements Controller { - controller = new Hono() - - constructor(@inject(WishlistsService) private readonly wishlistsService: WishlistsService) {} +export class WishlistController extends Controller { + constructor(@inject(WishlistsService) private readonly wishlistsService: WishlistsService) { + super() + } routes() { return this.controller diff --git a/src/lib/server/api/databases/migrate.ts b/src/lib/server/api/databases/migrate.ts index d476b12..369b93f 100644 --- a/src/lib/server/api/databases/migrate.ts +++ b/src/lib/server/api/databases/migrate.ts @@ -17,7 +17,11 @@ const connection = postgres({ const db = drizzle(connection) try { - await migrate(db, { migrationsFolder: config.out! }) + if (!config.out) { + console.error('No migrations folder specified in drizzle.config.ts') + process.exit() + } + await migrate(db, { migrationsFolder: config.out }) console.log('Migrations complete') } catch (e) { console.error(e) diff --git a/src/lib/server/api/databases/migrations/0000_dazzling_stick.sql b/src/lib/server/api/databases/migrations/0000_volatile_warhawk.sql similarity index 92% rename from src/lib/server/api/databases/migrations/0000_dazzling_stick.sql rename to src/lib/server/api/databases/migrations/0000_volatile_warhawk.sql index d02362e..661f48f 100644 --- a/src/lib/server/api/databases/migrations/0000_dazzling_stick.sql +++ b/src/lib/server/api/databases/migrations/0000_volatile_warhawk.sql @@ -47,6 +47,15 @@ CREATE TABLE IF NOT EXISTS "collections" ( CONSTRAINT "collections_cuid_unique" UNIQUE("cuid") ); --> statement-breakpoint +CREATE TABLE IF NOT EXISTS "credentials" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "user_id" uuid NOT NULL, + "type" text DEFAULT 'password' NOT NULL, + "secret_data" text NOT NULL, + "created_at" timestamp with time zone DEFAULT now() NOT NULL, + "updated_at" timestamp with time zone DEFAULT now() NOT NULL +); +--> statement-breakpoint CREATE TABLE IF NOT EXISTS "expansions" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "cuid" text, @@ -65,6 +74,16 @@ CREATE TABLE IF NOT EXISTS "external_ids" ( CONSTRAINT "external_ids_cuid_unique" UNIQUE("cuid") ); --> statement-breakpoint +CREATE TABLE IF NOT EXISTS "federated_identity" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "user_id" uuid NOT NULL, + "identity_provider" text NOT NULL, + "federated_user_id" text NOT NULL, + "federated_username" text NOT NULL, + "created_at" timestamp with time zone DEFAULT now() NOT NULL, + "updated_at" timestamp with time zone DEFAULT now() NOT NULL +); +--> statement-breakpoint CREATE TABLE IF NOT EXISTS "games" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "cuid" text, @@ -177,9 +196,9 @@ CREATE TABLE IF NOT EXISTS "sessions" ( CREATE TABLE IF NOT EXISTS "two_factor" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "cuid" text, - "two_factor_secret" text NOT NULL, - "two_factor_enabled" boolean DEFAULT false NOT NULL, - "initiated_time" timestamp with time zone NOT NULL, + "secret" text NOT NULL, + "enabled" boolean DEFAULT false NOT NULL, + "initiated_time" timestamp with time zone, "user_id" uuid NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL, @@ -202,12 +221,12 @@ CREATE TABLE IF NOT EXISTS "users" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "cuid" text, "username" text, - "hashed_password" text, "email" text, "first_name" text, "last_name" text, "verified" boolean DEFAULT false, "receive_email" boolean DEFAULT false, + "mfa_enabled" boolean DEFAULT false NOT NULL, "theme" text DEFAULT 'system', "created_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL, @@ -278,6 +297,12 @@ EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "credentials" ADD CONSTRAINT "credentials_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +--> statement-breakpoint DO $$ BEGIN ALTER TABLE "expansions" ADD CONSTRAINT "expansions_base_game_id_games_id_fk" FOREIGN KEY ("base_game_id") REFERENCES "public"."games"("id") ON DELETE restrict ON UPDATE cascade; EXCEPTION @@ -290,6 +315,12 @@ EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "federated_identity" ADD CONSTRAINT "federated_identity_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +--> statement-breakpoint DO $$ BEGIN ALTER TABLE "games_to_external_ids" ADD CONSTRAINT "games_to_external_ids_game_id_games_id_fk" FOREIGN KEY ("game_id") REFERENCES "public"."games"("id") ON DELETE restrict ON UPDATE cascade; EXCEPTION diff --git a/src/lib/server/api/databases/migrations/0001_noisy_sally_floyd.sql b/src/lib/server/api/databases/migrations/0001_noisy_sally_floyd.sql deleted file mode 100644 index 5809aa6..0000000 --- a/src/lib/server/api/databases/migrations/0001_noisy_sally_floyd.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE "two_factor" RENAME COLUMN "two_factor_secret" TO "secret";--> statement-breakpoint -ALTER TABLE "two_factor" RENAME COLUMN "two_factor_enabled" TO "enabled"; \ No newline at end of file diff --git a/src/lib/server/api/databases/migrations/0002_fancy_valkyrie.sql b/src/lib/server/api/databases/migrations/0002_fancy_valkyrie.sql deleted file mode 100644 index e05cd36..0000000 --- a/src/lib/server/api/databases/migrations/0002_fancy_valkyrie.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE "two_factor" ALTER COLUMN "initiated_time" DROP NOT NULL; \ No newline at end of file diff --git a/src/lib/server/api/databases/migrations/0003_worried_taskmaster.sql b/src/lib/server/api/databases/migrations/0003_worried_taskmaster.sql deleted file mode 100644 index c395895..0000000 --- a/src/lib/server/api/databases/migrations/0003_worried_taskmaster.sql +++ /dev/null @@ -1,32 +0,0 @@ -CREATE TABLE IF NOT EXISTS "credentials" ( - "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, - "user_id" uuid NOT NULL, - "type" text DEFAULT 'password' NOT NULL, - "secret_data" text NOT NULL, - "created_at" timestamp with time zone DEFAULT now() NOT NULL, - "updated_at" timestamp with time zone DEFAULT now() NOT NULL -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "federated_identity" ( - "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, - "user_id" uuid NOT NULL, - "identity_provider" text NOT NULL, - "federated_user_id" text NOT NULL, - "federated_username" text NOT NULL, - "created_at" timestamp with time zone DEFAULT now() NOT NULL, - "updated_at" timestamp with time zone DEFAULT now() NOT NULL -); ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "credentials" ADD CONSTRAINT "credentials_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "federated_identity" ADD CONSTRAINT "federated_identity_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; ---> statement-breakpoint -ALTER TABLE "users" DROP COLUMN IF EXISTS "hashed_password"; \ No newline at end of file diff --git a/src/lib/server/api/databases/migrations/0004_heavy_sphinx.sql b/src/lib/server/api/databases/migrations/0004_heavy_sphinx.sql deleted file mode 100644 index 70a7029..0000000 --- a/src/lib/server/api/databases/migrations/0004_heavy_sphinx.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE "users" ADD COLUMN "enabled" boolean DEFAULT false NOT NULL; \ No newline at end of file diff --git a/src/lib/server/api/databases/migrations/0005_true_mathemanic.sql b/src/lib/server/api/databases/migrations/0005_true_mathemanic.sql deleted file mode 100644 index a37a946..0000000 --- a/src/lib/server/api/databases/migrations/0005_true_mathemanic.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE "users" RENAME COLUMN "enabled" TO "mfa_enabled"; \ No newline at end of file diff --git a/src/lib/server/api/databases/migrations/meta/0000_snapshot.json b/src/lib/server/api/databases/migrations/meta/0000_snapshot.json index 91e2a6e..3814642 100644 --- a/src/lib/server/api/databases/migrations/meta/0000_snapshot.json +++ b/src/lib/server/api/databases/migrations/meta/0000_snapshot.json @@ -1,5 +1,5 @@ { - "id": "e120d11a-bf28-4c96-9f2f-96e23e23c7e2", + "id": "4760134e-48bb-47db-b431-56903dad6e24", "prevId": "00000000-0000-0000-0000-000000000000", "version": "7", "dialect": "postgresql", @@ -338,6 +338,70 @@ } } }, + "public.credentials": { + "name": "credentials", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'password'" + }, + "secret_data": { + "name": "secret_data", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "credentials_user_id_users_id_fk": { + "name": "credentials_user_id_users_id_fk", + "tableFrom": "credentials", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, "public.expansions": { "name": "expansions", "schema": "", @@ -466,6 +530,75 @@ } } }, + "public.federated_identity": { + "name": "federated_identity", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "identity_provider": { + "name": "identity_provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "federated_user_id": { + "name": "federated_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "federated_username": { + "name": "federated_username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "federated_identity_user_id_users_id_fk": { + "name": "federated_identity_user_id_users_id_fk", + "tableFrom": "federated_identity", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, "public.games": { "name": "games", "schema": "", @@ -1273,14 +1406,14 @@ "primaryKey": false, "notNull": false }, - "two_factor_secret": { - "name": "two_factor_secret", + "secret": { + "name": "secret", "type": "text", "primaryKey": false, "notNull": true }, - "two_factor_enabled": { - "name": "two_factor_enabled", + "enabled": { + "name": "enabled", "type": "boolean", "primaryKey": false, "notNull": true, @@ -1290,7 +1423,7 @@ "name": "initiated_time", "type": "timestamp with time zone", "primaryKey": false, - "notNull": true + "notNull": false }, "user_id": { "name": "user_id", @@ -1461,12 +1594,6 @@ "primaryKey": false, "notNull": false }, - "hashed_password": { - "name": "hashed_password", - "type": "text", - "primaryKey": false, - "notNull": false - }, "email": { "name": "email", "type": "text", @@ -1499,6 +1626,13 @@ "notNull": false, "default": false }, + "mfa_enabled": { + "name": "mfa_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, "theme": { "name": "theme", "type": "text", @@ -1720,6 +1854,7 @@ } }, "schemas": {}, + "sequences": {}, "_meta": { "columns": {}, "schemas": {}, diff --git a/src/lib/server/api/databases/migrations/meta/0001_snapshot.json b/src/lib/server/api/databases/migrations/meta/0001_snapshot.json deleted file mode 100644 index 4de88b6..0000000 --- a/src/lib/server/api/databases/migrations/meta/0001_snapshot.json +++ /dev/null @@ -1,1728 +0,0 @@ -{ - "id": "52e7c416-89cb-4c6a-9118-68a03cfc2920", - "prevId": "e120d11a-bf28-4c96-9f2f-96e23e23c7e2", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.categories": { - "name": "categories", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "categories_cuid_unique": { - "name": "categories_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.categories_to_external_ids": { - "name": "categories_to_external_ids", - "schema": "", - "columns": { - "category_id": { - "name": "category_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "categories_to_external_ids_category_id_categories_id_fk": { - "name": "categories_to_external_ids_category_id_categories_id_fk", - "tableFrom": "categories_to_external_ids", - "tableTo": "categories", - "columnsFrom": [ - "category_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "categories_to_external_ids_external_id_external_ids_id_fk": { - "name": "categories_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "categories_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "categories_to_external_ids_category_id_external_id_pk": { - "name": "categories_to_external_ids_category_id_external_id_pk", - "columns": [ - "category_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.categories_to_games": { - "name": "categories_to_games", - "schema": "", - "columns": { - "category_id": { - "name": "category_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "categories_to_games_category_id_categories_id_fk": { - "name": "categories_to_games_category_id_categories_id_fk", - "tableFrom": "categories_to_games", - "tableTo": "categories", - "columnsFrom": [ - "category_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "categories_to_games_game_id_games_id_fk": { - "name": "categories_to_games_game_id_games_id_fk", - "tableFrom": "categories_to_games", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "categories_to_games_category_id_game_id_pk": { - "name": "categories_to_games_category_id_game_id_pk", - "columns": [ - "category_id", - "game_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.collection_items": { - "name": "collection_items", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "collection_id": { - "name": "collection_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "times_played": { - "name": "times_played", - "type": "integer", - "primaryKey": false, - "notNull": false, - "default": 0 - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "collection_items_collection_id_collections_id_fk": { - "name": "collection_items_collection_id_collections_id_fk", - "tableFrom": "collection_items", - "tableTo": "collections", - "columnsFrom": [ - "collection_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "collection_items_game_id_games_id_fk": { - "name": "collection_items_game_id_games_id_fk", - "tableFrom": "collection_items", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "collection_items_cuid_unique": { - "name": "collection_items_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.collections": { - "name": "collections", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'My Collection'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "collections_user_id_users_id_fk": { - "name": "collections_user_id_users_id_fk", - "tableFrom": "collections", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "collections_cuid_unique": { - "name": "collections_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.expansions": { - "name": "expansions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "base_game_id": { - "name": "base_game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "expansions_base_game_id_games_id_fk": { - "name": "expansions_base_game_id_games_id_fk", - "tableFrom": "expansions", - "tableTo": "games", - "columnsFrom": [ - "base_game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "expansions_game_id_games_id_fk": { - "name": "expansions_game_id_games_id_fk", - "tableFrom": "expansions", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "expansions_cuid_unique": { - "name": "expansions_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.external_ids": { - "name": "external_ids", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "external_id_type", - "typeSchema": "public", - "primaryKey": false, - "notNull": false - }, - "external_id": { - "name": "external_id", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "external_ids_cuid_unique": { - "name": "external_ids_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.games": { - "name": "games", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "year_published": { - "name": "year_published", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "min_players": { - "name": "min_players", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "max_players": { - "name": "max_players", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "playtime": { - "name": "playtime", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "min_playtime": { - "name": "min_playtime", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "max_playtime": { - "name": "max_playtime", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "min_age": { - "name": "min_age", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "image_url": { - "name": "image_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "thumb_url": { - "name": "thumb_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "url": { - "name": "url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "last_sync_at": { - "name": "last_sync_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "search_index": { - "name": "search_index", - "columns": [ - { - "expression": "(\n\t\t\t\tsetweight(to_tsvector('english', \"name\"), 'A') ||\n setweight(to_tsvector('english', \"slug\"), 'B')\n )", - "asc": true, - "isExpression": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "gin", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "games_cuid_unique": { - "name": "games_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.games_to_external_ids": { - "name": "games_to_external_ids", - "schema": "", - "columns": { - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "games_to_external_ids_game_id_games_id_fk": { - "name": "games_to_external_ids_game_id_games_id_fk", - "tableFrom": "games_to_external_ids", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "games_to_external_ids_external_id_external_ids_id_fk": { - "name": "games_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "games_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "games_to_external_ids_game_id_external_id_pk": { - "name": "games_to_external_ids_game_id_external_id_pk", - "columns": [ - "game_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.mechanics": { - "name": "mechanics", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "mechanics_cuid_unique": { - "name": "mechanics_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.mechanics_to_external_ids": { - "name": "mechanics_to_external_ids", - "schema": "", - "columns": { - "mechanic_id": { - "name": "mechanic_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "mechanics_to_external_ids_mechanic_id_mechanics_id_fk": { - "name": "mechanics_to_external_ids_mechanic_id_mechanics_id_fk", - "tableFrom": "mechanics_to_external_ids", - "tableTo": "mechanics", - "columnsFrom": [ - "mechanic_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "mechanics_to_external_ids_external_id_external_ids_id_fk": { - "name": "mechanics_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "mechanics_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "mechanics_to_external_ids_mechanic_id_external_id_pk": { - "name": "mechanics_to_external_ids_mechanic_id_external_id_pk", - "columns": [ - "mechanic_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.mechanics_to_games": { - "name": "mechanics_to_games", - "schema": "", - "columns": { - "mechanic_id": { - "name": "mechanic_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "mechanics_to_games_mechanic_id_mechanics_id_fk": { - "name": "mechanics_to_games_mechanic_id_mechanics_id_fk", - "tableFrom": "mechanics_to_games", - "tableTo": "mechanics", - "columnsFrom": [ - "mechanic_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "mechanics_to_games_game_id_games_id_fk": { - "name": "mechanics_to_games_game_id_games_id_fk", - "tableFrom": "mechanics_to_games", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "mechanics_to_games_mechanic_id_game_id_pk": { - "name": "mechanics_to_games_mechanic_id_game_id_pk", - "columns": [ - "mechanic_id", - "game_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.password_reset_tokens": { - "name": "password_reset_tokens", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "password_reset_tokens_user_id_users_id_fk": { - "name": "password_reset_tokens_user_id_users_id_fk", - "tableFrom": "password_reset_tokens", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.publishers": { - "name": "publishers", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "publishers_cuid_unique": { - "name": "publishers_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.publishers_to_external_ids": { - "name": "publishers_to_external_ids", - "schema": "", - "columns": { - "publisher_id": { - "name": "publisher_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "publishers_to_external_ids_publisher_id_publishers_id_fk": { - "name": "publishers_to_external_ids_publisher_id_publishers_id_fk", - "tableFrom": "publishers_to_external_ids", - "tableTo": "publishers", - "columnsFrom": [ - "publisher_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "publishers_to_external_ids_external_id_external_ids_id_fk": { - "name": "publishers_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "publishers_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "publishers_to_external_ids_publisher_id_external_id_pk": { - "name": "publishers_to_external_ids_publisher_id_external_id_pk", - "columns": [ - "publisher_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.publishers_to_games": { - "name": "publishers_to_games", - "schema": "", - "columns": { - "publisher_id": { - "name": "publisher_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "publishers_to_games_publisher_id_publishers_id_fk": { - "name": "publishers_to_games_publisher_id_publishers_id_fk", - "tableFrom": "publishers_to_games", - "tableTo": "publishers", - "columnsFrom": [ - "publisher_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "publishers_to_games_game_id_games_id_fk": { - "name": "publishers_to_games_game_id_games_id_fk", - "tableFrom": "publishers_to_games", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "publishers_to_games_publisher_id_game_id_pk": { - "name": "publishers_to_games_publisher_id_game_id_pk", - "columns": [ - "publisher_id", - "game_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.recovery_codes": { - "name": "recovery_codes", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "code": { - "name": "code", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "used": { - "name": "used", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "recovery_codes_user_id_users_id_fk": { - "name": "recovery_codes_user_id_users_id_fk", - "tableFrom": "recovery_codes", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.roles": { - "name": "roles", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "roles_cuid_unique": { - "name": "roles_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - }, - "roles_name_unique": { - "name": "roles_name_unique", - "nullsNotDistinct": false, - "columns": [ - "name" - ] - } - } - }, - "public.sessions": { - "name": "sessions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "ip_country": { - "name": "ip_country", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "ip_address": { - "name": "ip_address", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "two_factor_auth_enabled": { - "name": "two_factor_auth_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "is_two_factor_authenticated": { - "name": "is_two_factor_authenticated", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - } - }, - "indexes": {}, - "foreignKeys": { - "sessions_user_id_users_id_fk": { - "name": "sessions_user_id_users_id_fk", - "tableFrom": "sessions", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.two_factor": { - "name": "two_factor", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "secret": { - "name": "secret", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "initiated_time": { - "name": "initiated_time", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "two_factor_user_id_users_id_fk": { - "name": "two_factor_user_id_users_id_fk", - "tableFrom": "two_factor", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "two_factor_cuid_unique": { - "name": "two_factor_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - }, - "two_factor_user_id_unique": { - "name": "two_factor_user_id_unique", - "nullsNotDistinct": false, - "columns": [ - "user_id" - ] - } - } - }, - "public.user_roles": { - "name": "user_roles", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "role_id": { - "name": "role_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "primary": { - "name": "primary", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "user_roles_user_id_users_id_fk": { - "name": "user_roles_user_id_users_id_fk", - "tableFrom": "user_roles", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "user_roles_role_id_roles_id_fk": { - "name": "user_roles_role_id_roles_id_fk", - "tableFrom": "user_roles", - "tableTo": "roles", - "columnsFrom": [ - "role_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_roles_cuid_unique": { - "name": "user_roles_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.users": { - "name": "users", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "username": { - "name": "username", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "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'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "users_cuid_unique": { - "name": "users_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - }, - "users_username_unique": { - "name": "users_username_unique", - "nullsNotDistinct": false, - "columns": [ - "username" - ] - }, - "users_email_unique": { - "name": "users_email_unique", - "nullsNotDistinct": false, - "columns": [ - "email" - ] - } - } - }, - "public.wishlist_items": { - "name": "wishlist_items", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "wishlist_id": { - "name": "wishlist_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "wishlist_items_wishlist_id_wishlists_id_fk": { - "name": "wishlist_items_wishlist_id_wishlists_id_fk", - "tableFrom": "wishlist_items", - "tableTo": "wishlists", - "columnsFrom": [ - "wishlist_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "wishlist_items_game_id_games_id_fk": { - "name": "wishlist_items_game_id_games_id_fk", - "tableFrom": "wishlist_items", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "wishlist_items_cuid_unique": { - "name": "wishlist_items_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.wishlists": { - "name": "wishlists", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'My Wishlist'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "wishlists_user_id_users_id_fk": { - "name": "wishlists_user_id_users_id_fk", - "tableFrom": "wishlists", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "wishlists_cuid_unique": { - "name": "wishlists_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - } - }, - "enums": { - "public.external_id_type": { - "name": "external_id_type", - "schema": "public", - "values": [ - "game", - "category", - "mechanic", - "publisher", - "designer", - "artist" - ] - } - }, - "schemas": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/src/lib/server/api/databases/migrations/meta/0002_snapshot.json b/src/lib/server/api/databases/migrations/meta/0002_snapshot.json deleted file mode 100644 index 8f50271..0000000 --- a/src/lib/server/api/databases/migrations/meta/0002_snapshot.json +++ /dev/null @@ -1,1728 +0,0 @@ -{ - "id": "79adee85-e57c-4a9f-87df-835457b68129", - "prevId": "52e7c416-89cb-4c6a-9118-68a03cfc2920", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.categories": { - "name": "categories", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "categories_cuid_unique": { - "name": "categories_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.categories_to_external_ids": { - "name": "categories_to_external_ids", - "schema": "", - "columns": { - "category_id": { - "name": "category_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "categories_to_external_ids_category_id_categories_id_fk": { - "name": "categories_to_external_ids_category_id_categories_id_fk", - "tableFrom": "categories_to_external_ids", - "tableTo": "categories", - "columnsFrom": [ - "category_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "categories_to_external_ids_external_id_external_ids_id_fk": { - "name": "categories_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "categories_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "categories_to_external_ids_category_id_external_id_pk": { - "name": "categories_to_external_ids_category_id_external_id_pk", - "columns": [ - "category_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.categories_to_games": { - "name": "categories_to_games", - "schema": "", - "columns": { - "category_id": { - "name": "category_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "categories_to_games_category_id_categories_id_fk": { - "name": "categories_to_games_category_id_categories_id_fk", - "tableFrom": "categories_to_games", - "tableTo": "categories", - "columnsFrom": [ - "category_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "categories_to_games_game_id_games_id_fk": { - "name": "categories_to_games_game_id_games_id_fk", - "tableFrom": "categories_to_games", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "categories_to_games_category_id_game_id_pk": { - "name": "categories_to_games_category_id_game_id_pk", - "columns": [ - "category_id", - "game_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.collection_items": { - "name": "collection_items", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "collection_id": { - "name": "collection_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "times_played": { - "name": "times_played", - "type": "integer", - "primaryKey": false, - "notNull": false, - "default": 0 - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "collection_items_collection_id_collections_id_fk": { - "name": "collection_items_collection_id_collections_id_fk", - "tableFrom": "collection_items", - "tableTo": "collections", - "columnsFrom": [ - "collection_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "collection_items_game_id_games_id_fk": { - "name": "collection_items_game_id_games_id_fk", - "tableFrom": "collection_items", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "collection_items_cuid_unique": { - "name": "collection_items_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.collections": { - "name": "collections", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'My Collection'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "collections_user_id_users_id_fk": { - "name": "collections_user_id_users_id_fk", - "tableFrom": "collections", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "collections_cuid_unique": { - "name": "collections_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.expansions": { - "name": "expansions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "base_game_id": { - "name": "base_game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "expansions_base_game_id_games_id_fk": { - "name": "expansions_base_game_id_games_id_fk", - "tableFrom": "expansions", - "tableTo": "games", - "columnsFrom": [ - "base_game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "expansions_game_id_games_id_fk": { - "name": "expansions_game_id_games_id_fk", - "tableFrom": "expansions", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "expansions_cuid_unique": { - "name": "expansions_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.external_ids": { - "name": "external_ids", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "external_id_type", - "typeSchema": "public", - "primaryKey": false, - "notNull": false - }, - "external_id": { - "name": "external_id", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "external_ids_cuid_unique": { - "name": "external_ids_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.games": { - "name": "games", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "year_published": { - "name": "year_published", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "min_players": { - "name": "min_players", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "max_players": { - "name": "max_players", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "playtime": { - "name": "playtime", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "min_playtime": { - "name": "min_playtime", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "max_playtime": { - "name": "max_playtime", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "min_age": { - "name": "min_age", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "image_url": { - "name": "image_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "thumb_url": { - "name": "thumb_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "url": { - "name": "url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "last_sync_at": { - "name": "last_sync_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "search_index": { - "name": "search_index", - "columns": [ - { - "expression": "(\n\t\t\t\tsetweight(to_tsvector('english', \"name\"), 'A') ||\n setweight(to_tsvector('english', \"slug\"), 'B')\n )", - "asc": true, - "isExpression": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "gin", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "games_cuid_unique": { - "name": "games_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.games_to_external_ids": { - "name": "games_to_external_ids", - "schema": "", - "columns": { - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "games_to_external_ids_game_id_games_id_fk": { - "name": "games_to_external_ids_game_id_games_id_fk", - "tableFrom": "games_to_external_ids", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "games_to_external_ids_external_id_external_ids_id_fk": { - "name": "games_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "games_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "games_to_external_ids_game_id_external_id_pk": { - "name": "games_to_external_ids_game_id_external_id_pk", - "columns": [ - "game_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.mechanics": { - "name": "mechanics", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "mechanics_cuid_unique": { - "name": "mechanics_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.mechanics_to_external_ids": { - "name": "mechanics_to_external_ids", - "schema": "", - "columns": { - "mechanic_id": { - "name": "mechanic_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "mechanics_to_external_ids_mechanic_id_mechanics_id_fk": { - "name": "mechanics_to_external_ids_mechanic_id_mechanics_id_fk", - "tableFrom": "mechanics_to_external_ids", - "tableTo": "mechanics", - "columnsFrom": [ - "mechanic_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "mechanics_to_external_ids_external_id_external_ids_id_fk": { - "name": "mechanics_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "mechanics_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "mechanics_to_external_ids_mechanic_id_external_id_pk": { - "name": "mechanics_to_external_ids_mechanic_id_external_id_pk", - "columns": [ - "mechanic_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.mechanics_to_games": { - "name": "mechanics_to_games", - "schema": "", - "columns": { - "mechanic_id": { - "name": "mechanic_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "mechanics_to_games_mechanic_id_mechanics_id_fk": { - "name": "mechanics_to_games_mechanic_id_mechanics_id_fk", - "tableFrom": "mechanics_to_games", - "tableTo": "mechanics", - "columnsFrom": [ - "mechanic_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "mechanics_to_games_game_id_games_id_fk": { - "name": "mechanics_to_games_game_id_games_id_fk", - "tableFrom": "mechanics_to_games", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "mechanics_to_games_mechanic_id_game_id_pk": { - "name": "mechanics_to_games_mechanic_id_game_id_pk", - "columns": [ - "mechanic_id", - "game_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.password_reset_tokens": { - "name": "password_reset_tokens", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "password_reset_tokens_user_id_users_id_fk": { - "name": "password_reset_tokens_user_id_users_id_fk", - "tableFrom": "password_reset_tokens", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.publishers": { - "name": "publishers", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "publishers_cuid_unique": { - "name": "publishers_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.publishers_to_external_ids": { - "name": "publishers_to_external_ids", - "schema": "", - "columns": { - "publisher_id": { - "name": "publisher_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "publishers_to_external_ids_publisher_id_publishers_id_fk": { - "name": "publishers_to_external_ids_publisher_id_publishers_id_fk", - "tableFrom": "publishers_to_external_ids", - "tableTo": "publishers", - "columnsFrom": [ - "publisher_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "publishers_to_external_ids_external_id_external_ids_id_fk": { - "name": "publishers_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "publishers_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "publishers_to_external_ids_publisher_id_external_id_pk": { - "name": "publishers_to_external_ids_publisher_id_external_id_pk", - "columns": [ - "publisher_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.publishers_to_games": { - "name": "publishers_to_games", - "schema": "", - "columns": { - "publisher_id": { - "name": "publisher_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "publishers_to_games_publisher_id_publishers_id_fk": { - "name": "publishers_to_games_publisher_id_publishers_id_fk", - "tableFrom": "publishers_to_games", - "tableTo": "publishers", - "columnsFrom": [ - "publisher_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "publishers_to_games_game_id_games_id_fk": { - "name": "publishers_to_games_game_id_games_id_fk", - "tableFrom": "publishers_to_games", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "publishers_to_games_publisher_id_game_id_pk": { - "name": "publishers_to_games_publisher_id_game_id_pk", - "columns": [ - "publisher_id", - "game_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.recovery_codes": { - "name": "recovery_codes", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "code": { - "name": "code", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "used": { - "name": "used", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "recovery_codes_user_id_users_id_fk": { - "name": "recovery_codes_user_id_users_id_fk", - "tableFrom": "recovery_codes", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.roles": { - "name": "roles", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "roles_cuid_unique": { - "name": "roles_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - }, - "roles_name_unique": { - "name": "roles_name_unique", - "nullsNotDistinct": false, - "columns": [ - "name" - ] - } - } - }, - "public.sessions": { - "name": "sessions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "ip_country": { - "name": "ip_country", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "ip_address": { - "name": "ip_address", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "two_factor_auth_enabled": { - "name": "two_factor_auth_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "is_two_factor_authenticated": { - "name": "is_two_factor_authenticated", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - } - }, - "indexes": {}, - "foreignKeys": { - "sessions_user_id_users_id_fk": { - "name": "sessions_user_id_users_id_fk", - "tableFrom": "sessions", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.two_factor": { - "name": "two_factor", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "secret": { - "name": "secret", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "initiated_time": { - "name": "initiated_time", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "two_factor_user_id_users_id_fk": { - "name": "two_factor_user_id_users_id_fk", - "tableFrom": "two_factor", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "two_factor_cuid_unique": { - "name": "two_factor_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - }, - "two_factor_user_id_unique": { - "name": "two_factor_user_id_unique", - "nullsNotDistinct": false, - "columns": [ - "user_id" - ] - } - } - }, - "public.user_roles": { - "name": "user_roles", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "role_id": { - "name": "role_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "primary": { - "name": "primary", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "user_roles_user_id_users_id_fk": { - "name": "user_roles_user_id_users_id_fk", - "tableFrom": "user_roles", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "user_roles_role_id_roles_id_fk": { - "name": "user_roles_role_id_roles_id_fk", - "tableFrom": "user_roles", - "tableTo": "roles", - "columnsFrom": [ - "role_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_roles_cuid_unique": { - "name": "user_roles_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.users": { - "name": "users", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "username": { - "name": "username", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "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'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "users_cuid_unique": { - "name": "users_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - }, - "users_username_unique": { - "name": "users_username_unique", - "nullsNotDistinct": false, - "columns": [ - "username" - ] - }, - "users_email_unique": { - "name": "users_email_unique", - "nullsNotDistinct": false, - "columns": [ - "email" - ] - } - } - }, - "public.wishlist_items": { - "name": "wishlist_items", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "wishlist_id": { - "name": "wishlist_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "wishlist_items_wishlist_id_wishlists_id_fk": { - "name": "wishlist_items_wishlist_id_wishlists_id_fk", - "tableFrom": "wishlist_items", - "tableTo": "wishlists", - "columnsFrom": [ - "wishlist_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "wishlist_items_game_id_games_id_fk": { - "name": "wishlist_items_game_id_games_id_fk", - "tableFrom": "wishlist_items", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "wishlist_items_cuid_unique": { - "name": "wishlist_items_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.wishlists": { - "name": "wishlists", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'My Wishlist'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "wishlists_user_id_users_id_fk": { - "name": "wishlists_user_id_users_id_fk", - "tableFrom": "wishlists", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "wishlists_cuid_unique": { - "name": "wishlists_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - } - }, - "enums": { - "public.external_id_type": { - "name": "external_id_type", - "schema": "public", - "values": [ - "game", - "category", - "mechanic", - "publisher", - "designer", - "artist" - ] - } - }, - "schemas": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/src/lib/server/api/databases/migrations/meta/0003_snapshot.json b/src/lib/server/api/databases/migrations/meta/0003_snapshot.json deleted file mode 100644 index a5213e7..0000000 --- a/src/lib/server/api/databases/migrations/meta/0003_snapshot.json +++ /dev/null @@ -1,1856 +0,0 @@ -{ - "id": "5a4165ba-0d5a-4a58-aa14-e68e3e41a181", - "prevId": "79adee85-e57c-4a9f-87df-835457b68129", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.categories": { - "name": "categories", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "categories_cuid_unique": { - "name": "categories_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.categories_to_external_ids": { - "name": "categories_to_external_ids", - "schema": "", - "columns": { - "category_id": { - "name": "category_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "categories_to_external_ids_category_id_categories_id_fk": { - "name": "categories_to_external_ids_category_id_categories_id_fk", - "tableFrom": "categories_to_external_ids", - "tableTo": "categories", - "columnsFrom": [ - "category_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "categories_to_external_ids_external_id_external_ids_id_fk": { - "name": "categories_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "categories_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "categories_to_external_ids_category_id_external_id_pk": { - "name": "categories_to_external_ids_category_id_external_id_pk", - "columns": [ - "category_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.categories_to_games": { - "name": "categories_to_games", - "schema": "", - "columns": { - "category_id": { - "name": "category_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "categories_to_games_category_id_categories_id_fk": { - "name": "categories_to_games_category_id_categories_id_fk", - "tableFrom": "categories_to_games", - "tableTo": "categories", - "columnsFrom": [ - "category_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "categories_to_games_game_id_games_id_fk": { - "name": "categories_to_games_game_id_games_id_fk", - "tableFrom": "categories_to_games", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "categories_to_games_category_id_game_id_pk": { - "name": "categories_to_games_category_id_game_id_pk", - "columns": [ - "category_id", - "game_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.collection_items": { - "name": "collection_items", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "collection_id": { - "name": "collection_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "times_played": { - "name": "times_played", - "type": "integer", - "primaryKey": false, - "notNull": false, - "default": 0 - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "collection_items_collection_id_collections_id_fk": { - "name": "collection_items_collection_id_collections_id_fk", - "tableFrom": "collection_items", - "tableTo": "collections", - "columnsFrom": [ - "collection_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "collection_items_game_id_games_id_fk": { - "name": "collection_items_game_id_games_id_fk", - "tableFrom": "collection_items", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "collection_items_cuid_unique": { - "name": "collection_items_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.collections": { - "name": "collections", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'My Collection'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "collections_user_id_users_id_fk": { - "name": "collections_user_id_users_id_fk", - "tableFrom": "collections", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "collections_cuid_unique": { - "name": "collections_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.credentials": { - "name": "credentials", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'password'" - }, - "secret_data": { - "name": "secret_data", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "credentials_user_id_users_id_fk": { - "name": "credentials_user_id_users_id_fk", - "tableFrom": "credentials", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.expansions": { - "name": "expansions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "base_game_id": { - "name": "base_game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "expansions_base_game_id_games_id_fk": { - "name": "expansions_base_game_id_games_id_fk", - "tableFrom": "expansions", - "tableTo": "games", - "columnsFrom": [ - "base_game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "expansions_game_id_games_id_fk": { - "name": "expansions_game_id_games_id_fk", - "tableFrom": "expansions", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "expansions_cuid_unique": { - "name": "expansions_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.external_ids": { - "name": "external_ids", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "external_id_type", - "typeSchema": "public", - "primaryKey": false, - "notNull": false - }, - "external_id": { - "name": "external_id", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "external_ids_cuid_unique": { - "name": "external_ids_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.federated_identity": { - "name": "federated_identity", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "identity_provider": { - "name": "identity_provider", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "federated_user_id": { - "name": "federated_user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "federated_username": { - "name": "federated_username", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "federated_identity_user_id_users_id_fk": { - "name": "federated_identity_user_id_users_id_fk", - "tableFrom": "federated_identity", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.games": { - "name": "games", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "year_published": { - "name": "year_published", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "min_players": { - "name": "min_players", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "max_players": { - "name": "max_players", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "playtime": { - "name": "playtime", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "min_playtime": { - "name": "min_playtime", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "max_playtime": { - "name": "max_playtime", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "min_age": { - "name": "min_age", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "image_url": { - "name": "image_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "thumb_url": { - "name": "thumb_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "url": { - "name": "url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "last_sync_at": { - "name": "last_sync_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "search_index": { - "name": "search_index", - "columns": [ - { - "expression": "(\n\t\t\t\tsetweight(to_tsvector('english', \"name\"), 'A') ||\n setweight(to_tsvector('english', \"slug\"), 'B')\n )", - "asc": true, - "isExpression": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "gin", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "games_cuid_unique": { - "name": "games_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.games_to_external_ids": { - "name": "games_to_external_ids", - "schema": "", - "columns": { - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "games_to_external_ids_game_id_games_id_fk": { - "name": "games_to_external_ids_game_id_games_id_fk", - "tableFrom": "games_to_external_ids", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "games_to_external_ids_external_id_external_ids_id_fk": { - "name": "games_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "games_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "games_to_external_ids_game_id_external_id_pk": { - "name": "games_to_external_ids_game_id_external_id_pk", - "columns": [ - "game_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.mechanics": { - "name": "mechanics", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "mechanics_cuid_unique": { - "name": "mechanics_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.mechanics_to_external_ids": { - "name": "mechanics_to_external_ids", - "schema": "", - "columns": { - "mechanic_id": { - "name": "mechanic_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "mechanics_to_external_ids_mechanic_id_mechanics_id_fk": { - "name": "mechanics_to_external_ids_mechanic_id_mechanics_id_fk", - "tableFrom": "mechanics_to_external_ids", - "tableTo": "mechanics", - "columnsFrom": [ - "mechanic_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "mechanics_to_external_ids_external_id_external_ids_id_fk": { - "name": "mechanics_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "mechanics_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "mechanics_to_external_ids_mechanic_id_external_id_pk": { - "name": "mechanics_to_external_ids_mechanic_id_external_id_pk", - "columns": [ - "mechanic_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.mechanics_to_games": { - "name": "mechanics_to_games", - "schema": "", - "columns": { - "mechanic_id": { - "name": "mechanic_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "mechanics_to_games_mechanic_id_mechanics_id_fk": { - "name": "mechanics_to_games_mechanic_id_mechanics_id_fk", - "tableFrom": "mechanics_to_games", - "tableTo": "mechanics", - "columnsFrom": [ - "mechanic_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "mechanics_to_games_game_id_games_id_fk": { - "name": "mechanics_to_games_game_id_games_id_fk", - "tableFrom": "mechanics_to_games", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "mechanics_to_games_mechanic_id_game_id_pk": { - "name": "mechanics_to_games_mechanic_id_game_id_pk", - "columns": [ - "mechanic_id", - "game_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.password_reset_tokens": { - "name": "password_reset_tokens", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "password_reset_tokens_user_id_users_id_fk": { - "name": "password_reset_tokens_user_id_users_id_fk", - "tableFrom": "password_reset_tokens", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.publishers": { - "name": "publishers", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "publishers_cuid_unique": { - "name": "publishers_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.publishers_to_external_ids": { - "name": "publishers_to_external_ids", - "schema": "", - "columns": { - "publisher_id": { - "name": "publisher_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "publishers_to_external_ids_publisher_id_publishers_id_fk": { - "name": "publishers_to_external_ids_publisher_id_publishers_id_fk", - "tableFrom": "publishers_to_external_ids", - "tableTo": "publishers", - "columnsFrom": [ - "publisher_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "publishers_to_external_ids_external_id_external_ids_id_fk": { - "name": "publishers_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "publishers_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "publishers_to_external_ids_publisher_id_external_id_pk": { - "name": "publishers_to_external_ids_publisher_id_external_id_pk", - "columns": [ - "publisher_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.publishers_to_games": { - "name": "publishers_to_games", - "schema": "", - "columns": { - "publisher_id": { - "name": "publisher_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "publishers_to_games_publisher_id_publishers_id_fk": { - "name": "publishers_to_games_publisher_id_publishers_id_fk", - "tableFrom": "publishers_to_games", - "tableTo": "publishers", - "columnsFrom": [ - "publisher_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "publishers_to_games_game_id_games_id_fk": { - "name": "publishers_to_games_game_id_games_id_fk", - "tableFrom": "publishers_to_games", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "publishers_to_games_publisher_id_game_id_pk": { - "name": "publishers_to_games_publisher_id_game_id_pk", - "columns": [ - "publisher_id", - "game_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.recovery_codes": { - "name": "recovery_codes", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "code": { - "name": "code", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "used": { - "name": "used", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "recovery_codes_user_id_users_id_fk": { - "name": "recovery_codes_user_id_users_id_fk", - "tableFrom": "recovery_codes", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.roles": { - "name": "roles", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "roles_cuid_unique": { - "name": "roles_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - }, - "roles_name_unique": { - "name": "roles_name_unique", - "nullsNotDistinct": false, - "columns": [ - "name" - ] - } - } - }, - "public.sessions": { - "name": "sessions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "ip_country": { - "name": "ip_country", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "ip_address": { - "name": "ip_address", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "two_factor_auth_enabled": { - "name": "two_factor_auth_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "is_two_factor_authenticated": { - "name": "is_two_factor_authenticated", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - } - }, - "indexes": {}, - "foreignKeys": { - "sessions_user_id_users_id_fk": { - "name": "sessions_user_id_users_id_fk", - "tableFrom": "sessions", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.two_factor": { - "name": "two_factor", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "secret": { - "name": "secret", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "initiated_time": { - "name": "initiated_time", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "two_factor_user_id_users_id_fk": { - "name": "two_factor_user_id_users_id_fk", - "tableFrom": "two_factor", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "two_factor_cuid_unique": { - "name": "two_factor_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - }, - "two_factor_user_id_unique": { - "name": "two_factor_user_id_unique", - "nullsNotDistinct": false, - "columns": [ - "user_id" - ] - } - } - }, - "public.user_roles": { - "name": "user_roles", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "role_id": { - "name": "role_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "primary": { - "name": "primary", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "user_roles_user_id_users_id_fk": { - "name": "user_roles_user_id_users_id_fk", - "tableFrom": "user_roles", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "user_roles_role_id_roles_id_fk": { - "name": "user_roles_role_id_roles_id_fk", - "tableFrom": "user_roles", - "tableTo": "roles", - "columnsFrom": [ - "role_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_roles_cuid_unique": { - "name": "user_roles_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.users": { - "name": "users", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "username": { - "name": "username", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "first_name": { - "name": "first_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "last_name": { - "name": "last_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "verified": { - "name": "verified", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "receive_email": { - "name": "receive_email", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "theme": { - "name": "theme", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'system'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "users_cuid_unique": { - "name": "users_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - }, - "users_username_unique": { - "name": "users_username_unique", - "nullsNotDistinct": false, - "columns": [ - "username" - ] - }, - "users_email_unique": { - "name": "users_email_unique", - "nullsNotDistinct": false, - "columns": [ - "email" - ] - } - } - }, - "public.wishlist_items": { - "name": "wishlist_items", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "wishlist_id": { - "name": "wishlist_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "wishlist_items_wishlist_id_wishlists_id_fk": { - "name": "wishlist_items_wishlist_id_wishlists_id_fk", - "tableFrom": "wishlist_items", - "tableTo": "wishlists", - "columnsFrom": [ - "wishlist_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "wishlist_items_game_id_games_id_fk": { - "name": "wishlist_items_game_id_games_id_fk", - "tableFrom": "wishlist_items", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "wishlist_items_cuid_unique": { - "name": "wishlist_items_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.wishlists": { - "name": "wishlists", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'My Wishlist'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "wishlists_user_id_users_id_fk": { - "name": "wishlists_user_id_users_id_fk", - "tableFrom": "wishlists", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "wishlists_cuid_unique": { - "name": "wishlists_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - } - }, - "enums": { - "public.external_id_type": { - "name": "external_id_type", - "schema": "public", - "values": [ - "game", - "category", - "mechanic", - "publisher", - "designer", - "artist" - ] - } - }, - "schemas": {}, - "sequences": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/src/lib/server/api/databases/migrations/meta/0004_snapshot.json b/src/lib/server/api/databases/migrations/meta/0004_snapshot.json deleted file mode 100644 index 11e04b2..0000000 --- a/src/lib/server/api/databases/migrations/meta/0004_snapshot.json +++ /dev/null @@ -1,1863 +0,0 @@ -{ - "id": "ee44907c-0c2a-4aa0-8e3a-59cf74321c7a", - "prevId": "5a4165ba-0d5a-4a58-aa14-e68e3e41a181", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.categories": { - "name": "categories", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "categories_cuid_unique": { - "name": "categories_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.categories_to_external_ids": { - "name": "categories_to_external_ids", - "schema": "", - "columns": { - "category_id": { - "name": "category_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "categories_to_external_ids_category_id_categories_id_fk": { - "name": "categories_to_external_ids_category_id_categories_id_fk", - "tableFrom": "categories_to_external_ids", - "tableTo": "categories", - "columnsFrom": [ - "category_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "categories_to_external_ids_external_id_external_ids_id_fk": { - "name": "categories_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "categories_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "categories_to_external_ids_category_id_external_id_pk": { - "name": "categories_to_external_ids_category_id_external_id_pk", - "columns": [ - "category_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.categories_to_games": { - "name": "categories_to_games", - "schema": "", - "columns": { - "category_id": { - "name": "category_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "categories_to_games_category_id_categories_id_fk": { - "name": "categories_to_games_category_id_categories_id_fk", - "tableFrom": "categories_to_games", - "tableTo": "categories", - "columnsFrom": [ - "category_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "categories_to_games_game_id_games_id_fk": { - "name": "categories_to_games_game_id_games_id_fk", - "tableFrom": "categories_to_games", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "categories_to_games_category_id_game_id_pk": { - "name": "categories_to_games_category_id_game_id_pk", - "columns": [ - "category_id", - "game_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.collection_items": { - "name": "collection_items", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "collection_id": { - "name": "collection_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "times_played": { - "name": "times_played", - "type": "integer", - "primaryKey": false, - "notNull": false, - "default": 0 - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "collection_items_collection_id_collections_id_fk": { - "name": "collection_items_collection_id_collections_id_fk", - "tableFrom": "collection_items", - "tableTo": "collections", - "columnsFrom": [ - "collection_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "collection_items_game_id_games_id_fk": { - "name": "collection_items_game_id_games_id_fk", - "tableFrom": "collection_items", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "collection_items_cuid_unique": { - "name": "collection_items_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.collections": { - "name": "collections", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'My Collection'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "collections_user_id_users_id_fk": { - "name": "collections_user_id_users_id_fk", - "tableFrom": "collections", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "collections_cuid_unique": { - "name": "collections_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.credentials": { - "name": "credentials", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'password'" - }, - "secret_data": { - "name": "secret_data", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "credentials_user_id_users_id_fk": { - "name": "credentials_user_id_users_id_fk", - "tableFrom": "credentials", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.expansions": { - "name": "expansions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "base_game_id": { - "name": "base_game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "expansions_base_game_id_games_id_fk": { - "name": "expansions_base_game_id_games_id_fk", - "tableFrom": "expansions", - "tableTo": "games", - "columnsFrom": [ - "base_game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "expansions_game_id_games_id_fk": { - "name": "expansions_game_id_games_id_fk", - "tableFrom": "expansions", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "expansions_cuid_unique": { - "name": "expansions_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.external_ids": { - "name": "external_ids", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "external_id_type", - "typeSchema": "public", - "primaryKey": false, - "notNull": false - }, - "external_id": { - "name": "external_id", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "external_ids_cuid_unique": { - "name": "external_ids_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.federated_identity": { - "name": "federated_identity", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "identity_provider": { - "name": "identity_provider", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "federated_user_id": { - "name": "federated_user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "federated_username": { - "name": "federated_username", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "federated_identity_user_id_users_id_fk": { - "name": "federated_identity_user_id_users_id_fk", - "tableFrom": "federated_identity", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.games": { - "name": "games", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "year_published": { - "name": "year_published", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "min_players": { - "name": "min_players", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "max_players": { - "name": "max_players", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "playtime": { - "name": "playtime", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "min_playtime": { - "name": "min_playtime", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "max_playtime": { - "name": "max_playtime", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "min_age": { - "name": "min_age", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "image_url": { - "name": "image_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "thumb_url": { - "name": "thumb_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "url": { - "name": "url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "last_sync_at": { - "name": "last_sync_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "search_index": { - "name": "search_index", - "columns": [ - { - "expression": "(\n\t\t\t\tsetweight(to_tsvector('english', \"name\"), 'A') ||\n setweight(to_tsvector('english', \"slug\"), 'B')\n )", - "asc": true, - "isExpression": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "gin", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "games_cuid_unique": { - "name": "games_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.games_to_external_ids": { - "name": "games_to_external_ids", - "schema": "", - "columns": { - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "games_to_external_ids_game_id_games_id_fk": { - "name": "games_to_external_ids_game_id_games_id_fk", - "tableFrom": "games_to_external_ids", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "games_to_external_ids_external_id_external_ids_id_fk": { - "name": "games_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "games_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "games_to_external_ids_game_id_external_id_pk": { - "name": "games_to_external_ids_game_id_external_id_pk", - "columns": [ - "game_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.mechanics": { - "name": "mechanics", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "mechanics_cuid_unique": { - "name": "mechanics_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.mechanics_to_external_ids": { - "name": "mechanics_to_external_ids", - "schema": "", - "columns": { - "mechanic_id": { - "name": "mechanic_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "mechanics_to_external_ids_mechanic_id_mechanics_id_fk": { - "name": "mechanics_to_external_ids_mechanic_id_mechanics_id_fk", - "tableFrom": "mechanics_to_external_ids", - "tableTo": "mechanics", - "columnsFrom": [ - "mechanic_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "mechanics_to_external_ids_external_id_external_ids_id_fk": { - "name": "mechanics_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "mechanics_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "mechanics_to_external_ids_mechanic_id_external_id_pk": { - "name": "mechanics_to_external_ids_mechanic_id_external_id_pk", - "columns": [ - "mechanic_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.mechanics_to_games": { - "name": "mechanics_to_games", - "schema": "", - "columns": { - "mechanic_id": { - "name": "mechanic_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "mechanics_to_games_mechanic_id_mechanics_id_fk": { - "name": "mechanics_to_games_mechanic_id_mechanics_id_fk", - "tableFrom": "mechanics_to_games", - "tableTo": "mechanics", - "columnsFrom": [ - "mechanic_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "mechanics_to_games_game_id_games_id_fk": { - "name": "mechanics_to_games_game_id_games_id_fk", - "tableFrom": "mechanics_to_games", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "mechanics_to_games_mechanic_id_game_id_pk": { - "name": "mechanics_to_games_mechanic_id_game_id_pk", - "columns": [ - "mechanic_id", - "game_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.password_reset_tokens": { - "name": "password_reset_tokens", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "password_reset_tokens_user_id_users_id_fk": { - "name": "password_reset_tokens_user_id_users_id_fk", - "tableFrom": "password_reset_tokens", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.publishers": { - "name": "publishers", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "publishers_cuid_unique": { - "name": "publishers_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.publishers_to_external_ids": { - "name": "publishers_to_external_ids", - "schema": "", - "columns": { - "publisher_id": { - "name": "publisher_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "publishers_to_external_ids_publisher_id_publishers_id_fk": { - "name": "publishers_to_external_ids_publisher_id_publishers_id_fk", - "tableFrom": "publishers_to_external_ids", - "tableTo": "publishers", - "columnsFrom": [ - "publisher_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "publishers_to_external_ids_external_id_external_ids_id_fk": { - "name": "publishers_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "publishers_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "publishers_to_external_ids_publisher_id_external_id_pk": { - "name": "publishers_to_external_ids_publisher_id_external_id_pk", - "columns": [ - "publisher_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.publishers_to_games": { - "name": "publishers_to_games", - "schema": "", - "columns": { - "publisher_id": { - "name": "publisher_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "publishers_to_games_publisher_id_publishers_id_fk": { - "name": "publishers_to_games_publisher_id_publishers_id_fk", - "tableFrom": "publishers_to_games", - "tableTo": "publishers", - "columnsFrom": [ - "publisher_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "publishers_to_games_game_id_games_id_fk": { - "name": "publishers_to_games_game_id_games_id_fk", - "tableFrom": "publishers_to_games", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "publishers_to_games_publisher_id_game_id_pk": { - "name": "publishers_to_games_publisher_id_game_id_pk", - "columns": [ - "publisher_id", - "game_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.recovery_codes": { - "name": "recovery_codes", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "code": { - "name": "code", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "used": { - "name": "used", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "recovery_codes_user_id_users_id_fk": { - "name": "recovery_codes_user_id_users_id_fk", - "tableFrom": "recovery_codes", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.roles": { - "name": "roles", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "roles_cuid_unique": { - "name": "roles_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - }, - "roles_name_unique": { - "name": "roles_name_unique", - "nullsNotDistinct": false, - "columns": [ - "name" - ] - } - } - }, - "public.sessions": { - "name": "sessions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "ip_country": { - "name": "ip_country", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "ip_address": { - "name": "ip_address", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "two_factor_auth_enabled": { - "name": "two_factor_auth_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "is_two_factor_authenticated": { - "name": "is_two_factor_authenticated", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - } - }, - "indexes": {}, - "foreignKeys": { - "sessions_user_id_users_id_fk": { - "name": "sessions_user_id_users_id_fk", - "tableFrom": "sessions", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.two_factor": { - "name": "two_factor", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "secret": { - "name": "secret", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "initiated_time": { - "name": "initiated_time", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "two_factor_user_id_users_id_fk": { - "name": "two_factor_user_id_users_id_fk", - "tableFrom": "two_factor", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "two_factor_cuid_unique": { - "name": "two_factor_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - }, - "two_factor_user_id_unique": { - "name": "two_factor_user_id_unique", - "nullsNotDistinct": false, - "columns": [ - "user_id" - ] - } - } - }, - "public.user_roles": { - "name": "user_roles", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "role_id": { - "name": "role_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "primary": { - "name": "primary", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "user_roles_user_id_users_id_fk": { - "name": "user_roles_user_id_users_id_fk", - "tableFrom": "user_roles", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "user_roles_role_id_roles_id_fk": { - "name": "user_roles_role_id_roles_id_fk", - "tableFrom": "user_roles", - "tableTo": "roles", - "columnsFrom": [ - "role_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_roles_cuid_unique": { - "name": "user_roles_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.users": { - "name": "users", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "username": { - "name": "username", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "first_name": { - "name": "first_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "last_name": { - "name": "last_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "verified": { - "name": "verified", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "receive_email": { - "name": "receive_email", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "theme": { - "name": "theme", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'system'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "users_cuid_unique": { - "name": "users_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - }, - "users_username_unique": { - "name": "users_username_unique", - "nullsNotDistinct": false, - "columns": [ - "username" - ] - }, - "users_email_unique": { - "name": "users_email_unique", - "nullsNotDistinct": false, - "columns": [ - "email" - ] - } - } - }, - "public.wishlist_items": { - "name": "wishlist_items", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "wishlist_id": { - "name": "wishlist_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "wishlist_items_wishlist_id_wishlists_id_fk": { - "name": "wishlist_items_wishlist_id_wishlists_id_fk", - "tableFrom": "wishlist_items", - "tableTo": "wishlists", - "columnsFrom": [ - "wishlist_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "wishlist_items_game_id_games_id_fk": { - "name": "wishlist_items_game_id_games_id_fk", - "tableFrom": "wishlist_items", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "wishlist_items_cuid_unique": { - "name": "wishlist_items_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.wishlists": { - "name": "wishlists", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'My Wishlist'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "wishlists_user_id_users_id_fk": { - "name": "wishlists_user_id_users_id_fk", - "tableFrom": "wishlists", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "wishlists_cuid_unique": { - "name": "wishlists_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - } - }, - "enums": { - "public.external_id_type": { - "name": "external_id_type", - "schema": "public", - "values": [ - "game", - "category", - "mechanic", - "publisher", - "designer", - "artist" - ] - } - }, - "schemas": {}, - "sequences": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/src/lib/server/api/databases/migrations/meta/0005_snapshot.json b/src/lib/server/api/databases/migrations/meta/0005_snapshot.json deleted file mode 100644 index c82db66..0000000 --- a/src/lib/server/api/databases/migrations/meta/0005_snapshot.json +++ /dev/null @@ -1,1863 +0,0 @@ -{ - "id": "b7874689-9dc9-4171-9115-5b6333a0f995", - "prevId": "ee44907c-0c2a-4aa0-8e3a-59cf74321c7a", - "version": "7", - "dialect": "postgresql", - "tables": { - "public.categories": { - "name": "categories", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "categories_cuid_unique": { - "name": "categories_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.categories_to_external_ids": { - "name": "categories_to_external_ids", - "schema": "", - "columns": { - "category_id": { - "name": "category_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "categories_to_external_ids_category_id_categories_id_fk": { - "name": "categories_to_external_ids_category_id_categories_id_fk", - "tableFrom": "categories_to_external_ids", - "tableTo": "categories", - "columnsFrom": [ - "category_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "categories_to_external_ids_external_id_external_ids_id_fk": { - "name": "categories_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "categories_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "categories_to_external_ids_category_id_external_id_pk": { - "name": "categories_to_external_ids_category_id_external_id_pk", - "columns": [ - "category_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.categories_to_games": { - "name": "categories_to_games", - "schema": "", - "columns": { - "category_id": { - "name": "category_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "categories_to_games_category_id_categories_id_fk": { - "name": "categories_to_games_category_id_categories_id_fk", - "tableFrom": "categories_to_games", - "tableTo": "categories", - "columnsFrom": [ - "category_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "categories_to_games_game_id_games_id_fk": { - "name": "categories_to_games_game_id_games_id_fk", - "tableFrom": "categories_to_games", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "categories_to_games_category_id_game_id_pk": { - "name": "categories_to_games_category_id_game_id_pk", - "columns": [ - "category_id", - "game_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.collection_items": { - "name": "collection_items", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "collection_id": { - "name": "collection_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "times_played": { - "name": "times_played", - "type": "integer", - "primaryKey": false, - "notNull": false, - "default": 0 - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "collection_items_collection_id_collections_id_fk": { - "name": "collection_items_collection_id_collections_id_fk", - "tableFrom": "collection_items", - "tableTo": "collections", - "columnsFrom": [ - "collection_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "collection_items_game_id_games_id_fk": { - "name": "collection_items_game_id_games_id_fk", - "tableFrom": "collection_items", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "collection_items_cuid_unique": { - "name": "collection_items_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.collections": { - "name": "collections", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'My Collection'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "collections_user_id_users_id_fk": { - "name": "collections_user_id_users_id_fk", - "tableFrom": "collections", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "collections_cuid_unique": { - "name": "collections_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.credentials": { - "name": "credentials", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "type": { - "name": "type", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'password'" - }, - "secret_data": { - "name": "secret_data", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "credentials_user_id_users_id_fk": { - "name": "credentials_user_id_users_id_fk", - "tableFrom": "credentials", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.expansions": { - "name": "expansions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "base_game_id": { - "name": "base_game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "expansions_base_game_id_games_id_fk": { - "name": "expansions_base_game_id_games_id_fk", - "tableFrom": "expansions", - "tableTo": "games", - "columnsFrom": [ - "base_game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "expansions_game_id_games_id_fk": { - "name": "expansions_game_id_games_id_fk", - "tableFrom": "expansions", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "expansions_cuid_unique": { - "name": "expansions_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.external_ids": { - "name": "external_ids", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "type": { - "name": "type", - "type": "external_id_type", - "typeSchema": "public", - "primaryKey": false, - "notNull": false - }, - "external_id": { - "name": "external_id", - "type": "text", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "external_ids_cuid_unique": { - "name": "external_ids_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.federated_identity": { - "name": "federated_identity", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "identity_provider": { - "name": "identity_provider", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "federated_user_id": { - "name": "federated_user_id", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "federated_username": { - "name": "federated_username", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "federated_identity_user_id_users_id_fk": { - "name": "federated_identity_user_id_users_id_fk", - "tableFrom": "federated_identity", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.games": { - "name": "games", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "description": { - "name": "description", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "year_published": { - "name": "year_published", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "min_players": { - "name": "min_players", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "max_players": { - "name": "max_players", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "playtime": { - "name": "playtime", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "min_playtime": { - "name": "min_playtime", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "max_playtime": { - "name": "max_playtime", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "min_age": { - "name": "min_age", - "type": "integer", - "primaryKey": false, - "notNull": false - }, - "image_url": { - "name": "image_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "thumb_url": { - "name": "thumb_url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "url": { - "name": "url", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "last_sync_at": { - "name": "last_sync_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": { - "search_index": { - "name": "search_index", - "columns": [ - { - "expression": "(\n\t\t\t\tsetweight(to_tsvector('english', \"name\"), 'A') ||\n setweight(to_tsvector('english', \"slug\"), 'B')\n )", - "asc": true, - "isExpression": true, - "nulls": "last" - } - ], - "isUnique": false, - "concurrently": false, - "method": "gin", - "with": {} - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "games_cuid_unique": { - "name": "games_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.games_to_external_ids": { - "name": "games_to_external_ids", - "schema": "", - "columns": { - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "games_to_external_ids_game_id_games_id_fk": { - "name": "games_to_external_ids_game_id_games_id_fk", - "tableFrom": "games_to_external_ids", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "games_to_external_ids_external_id_external_ids_id_fk": { - "name": "games_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "games_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "games_to_external_ids_game_id_external_id_pk": { - "name": "games_to_external_ids_game_id_external_id_pk", - "columns": [ - "game_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.mechanics": { - "name": "mechanics", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "mechanics_cuid_unique": { - "name": "mechanics_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.mechanics_to_external_ids": { - "name": "mechanics_to_external_ids", - "schema": "", - "columns": { - "mechanic_id": { - "name": "mechanic_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "mechanics_to_external_ids_mechanic_id_mechanics_id_fk": { - "name": "mechanics_to_external_ids_mechanic_id_mechanics_id_fk", - "tableFrom": "mechanics_to_external_ids", - "tableTo": "mechanics", - "columnsFrom": [ - "mechanic_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "mechanics_to_external_ids_external_id_external_ids_id_fk": { - "name": "mechanics_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "mechanics_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "mechanics_to_external_ids_mechanic_id_external_id_pk": { - "name": "mechanics_to_external_ids_mechanic_id_external_id_pk", - "columns": [ - "mechanic_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.mechanics_to_games": { - "name": "mechanics_to_games", - "schema": "", - "columns": { - "mechanic_id": { - "name": "mechanic_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "mechanics_to_games_mechanic_id_mechanics_id_fk": { - "name": "mechanics_to_games_mechanic_id_mechanics_id_fk", - "tableFrom": "mechanics_to_games", - "tableTo": "mechanics", - "columnsFrom": [ - "mechanic_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "mechanics_to_games_game_id_games_id_fk": { - "name": "mechanics_to_games_game_id_games_id_fk", - "tableFrom": "mechanics_to_games", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "mechanics_to_games_mechanic_id_game_id_pk": { - "name": "mechanics_to_games_mechanic_id_game_id_pk", - "columns": [ - "mechanic_id", - "game_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.password_reset_tokens": { - "name": "password_reset_tokens", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "password_reset_tokens_user_id_users_id_fk": { - "name": "password_reset_tokens_user_id_users_id_fk", - "tableFrom": "password_reset_tokens", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.publishers": { - "name": "publishers", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "slug": { - "name": "slug", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "publishers_cuid_unique": { - "name": "publishers_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.publishers_to_external_ids": { - "name": "publishers_to_external_ids", - "schema": "", - "columns": { - "publisher_id": { - "name": "publisher_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "external_id": { - "name": "external_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "publishers_to_external_ids_publisher_id_publishers_id_fk": { - "name": "publishers_to_external_ids_publisher_id_publishers_id_fk", - "tableFrom": "publishers_to_external_ids", - "tableTo": "publishers", - "columnsFrom": [ - "publisher_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "publishers_to_external_ids_external_id_external_ids_id_fk": { - "name": "publishers_to_external_ids_external_id_external_ids_id_fk", - "tableFrom": "publishers_to_external_ids", - "tableTo": "external_ids", - "columnsFrom": [ - "external_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "publishers_to_external_ids_publisher_id_external_id_pk": { - "name": "publishers_to_external_ids_publisher_id_external_id_pk", - "columns": [ - "publisher_id", - "external_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.publishers_to_games": { - "name": "publishers_to_games", - "schema": "", - "columns": { - "publisher_id": { - "name": "publisher_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "publishers_to_games_publisher_id_publishers_id_fk": { - "name": "publishers_to_games_publisher_id_publishers_id_fk", - "tableFrom": "publishers_to_games", - "tableTo": "publishers", - "columnsFrom": [ - "publisher_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - }, - "publishers_to_games_game_id_games_id_fk": { - "name": "publishers_to_games_game_id_games_id_fk", - "tableFrom": "publishers_to_games", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "restrict", - "onUpdate": "cascade" - } - }, - "compositePrimaryKeys": { - "publishers_to_games_publisher_id_game_id_pk": { - "name": "publishers_to_games_publisher_id_game_id_pk", - "columns": [ - "publisher_id", - "game_id" - ] - } - }, - "uniqueConstraints": {} - }, - "public.recovery_codes": { - "name": "recovery_codes", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "code": { - "name": "code", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "used": { - "name": "used", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "recovery_codes_user_id_users_id_fk": { - "name": "recovery_codes_user_id_users_id_fk", - "tableFrom": "recovery_codes", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.roles": { - "name": "roles", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "roles_cuid_unique": { - "name": "roles_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - }, - "roles_name_unique": { - "name": "roles_name_unique", - "nullsNotDistinct": false, - "columns": [ - "name" - ] - } - } - }, - "public.sessions": { - "name": "sessions", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "expires_at": { - "name": "expires_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true - }, - "ip_country": { - "name": "ip_country", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "ip_address": { - "name": "ip_address", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "two_factor_auth_enabled": { - "name": "two_factor_auth_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "is_two_factor_authenticated": { - "name": "is_two_factor_authenticated", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - } - }, - "indexes": {}, - "foreignKeys": { - "sessions_user_id_users_id_fk": { - "name": "sessions_user_id_users_id_fk", - "tableFrom": "sessions", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "public.two_factor": { - "name": "two_factor", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "secret": { - "name": "secret", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "enabled": { - "name": "enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "initiated_time": { - "name": "initiated_time", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "two_factor_user_id_users_id_fk": { - "name": "two_factor_user_id_users_id_fk", - "tableFrom": "two_factor", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "two_factor_cuid_unique": { - "name": "two_factor_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - }, - "two_factor_user_id_unique": { - "name": "two_factor_user_id_unique", - "nullsNotDistinct": false, - "columns": [ - "user_id" - ] - } - } - }, - "public.user_roles": { - "name": "user_roles", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "role_id": { - "name": "role_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "primary": { - "name": "primary", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "user_roles_user_id_users_id_fk": { - "name": "user_roles_user_id_users_id_fk", - "tableFrom": "user_roles", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "user_roles_role_id_roles_id_fk": { - "name": "user_roles_role_id_roles_id_fk", - "tableFrom": "user_roles", - "tableTo": "roles", - "columnsFrom": [ - "role_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "user_roles_cuid_unique": { - "name": "user_roles_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.users": { - "name": "users", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "username": { - "name": "username", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "first_name": { - "name": "first_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "last_name": { - "name": "last_name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "verified": { - "name": "verified", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "receive_email": { - "name": "receive_email", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "mfa_enabled": { - "name": "mfa_enabled", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "theme": { - "name": "theme", - "type": "text", - "primaryKey": false, - "notNull": false, - "default": "'system'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "users_cuid_unique": { - "name": "users_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - }, - "users_username_unique": { - "name": "users_username_unique", - "nullsNotDistinct": false, - "columns": [ - "username" - ] - }, - "users_email_unique": { - "name": "users_email_unique", - "nullsNotDistinct": false, - "columns": [ - "email" - ] - } - } - }, - "public.wishlist_items": { - "name": "wishlist_items", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "wishlist_id": { - "name": "wishlist_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "game_id": { - "name": "game_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "wishlist_items_wishlist_id_wishlists_id_fk": { - "name": "wishlist_items_wishlist_id_wishlists_id_fk", - "tableFrom": "wishlist_items", - "tableTo": "wishlists", - "columnsFrom": [ - "wishlist_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - }, - "wishlist_items_game_id_games_id_fk": { - "name": "wishlist_items_game_id_games_id_fk", - "tableFrom": "wishlist_items", - "tableTo": "games", - "columnsFrom": [ - "game_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "wishlist_items_cuid_unique": { - "name": "wishlist_items_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - }, - "public.wishlists": { - "name": "wishlists", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "uuid", - "primaryKey": true, - "notNull": true, - "default": "gen_random_uuid()" - }, - "cuid": { - "name": "cuid", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "user_id": { - "name": "user_id", - "type": "uuid", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": true, - "default": "'My Wishlist'" - }, - "created_at": { - "name": "created_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamp with time zone", - "primaryKey": false, - "notNull": true, - "default": "now()" - } - }, - "indexes": {}, - "foreignKeys": { - "wishlists_user_id_users_id_fk": { - "name": "wishlists_user_id_users_id_fk", - "tableFrom": "wishlists", - "tableTo": "users", - "columnsFrom": [ - "user_id" - ], - "columnsTo": [ - "id" - ], - "onDelete": "cascade", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": { - "wishlists_cuid_unique": { - "name": "wishlists_cuid_unique", - "nullsNotDistinct": false, - "columns": [ - "cuid" - ] - } - } - } - }, - "enums": { - "public.external_id_type": { - "name": "external_id_type", - "schema": "public", - "values": [ - "game", - "category", - "mechanic", - "publisher", - "designer", - "artist" - ] - } - }, - "schemas": {}, - "sequences": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} \ No newline at end of file diff --git a/src/lib/server/api/databases/migrations/meta/_journal.json b/src/lib/server/api/databases/migrations/meta/_journal.json index 3fa0832..1f88a00 100644 --- a/src/lib/server/api/databases/migrations/meta/_journal.json +++ b/src/lib/server/api/databases/migrations/meta/_journal.json @@ -5,43 +5,8 @@ { "idx": 0, "version": "7", - "when": 1720625651245, - "tag": "0000_dazzling_stick", - "breakpoints": true - }, - { - "idx": 1, - "version": "7", - "when": 1720625948784, - "tag": "0001_noisy_sally_floyd", - "breakpoints": true - }, - { - "idx": 2, - "version": "7", - "when": 1720626020902, - "tag": "0002_fancy_valkyrie", - "breakpoints": true - }, - { - "idx": 3, - "version": "7", - "when": 1723593488634, - "tag": "0003_worried_taskmaster", - "breakpoints": true - }, - { - "idx": 4, - "version": "7", - "when": 1725055403926, - "tag": "0004_heavy_sphinx", - "breakpoints": true - }, - { - "idx": 5, - "version": "7", - "when": 1725055643756, - "tag": "0005_true_mathemanic", + "when": 1725489682980, + "tag": "0000_volatile_warhawk", "breakpoints": true } ] diff --git a/src/lib/server/api/databases/seed.ts b/src/lib/server/api/databases/seed.ts index de83be1..2457c9d 100644 --- a/src/lib/server/api/databases/seed.ts +++ b/src/lib/server/api/databases/seed.ts @@ -1,14 +1,18 @@ -import { Table, getTableName, sql } from 'drizzle-orm' +import 'reflect-metadata' +import { DrizzleService } from '$lib/server/api/services/drizzle.service' +import { type Table, getTableName, sql } from 'drizzle-orm' +import type { NodePgDatabase } from 'drizzle-orm/node-postgres' import env from '../../../../env' -import { db, pool } from '../packages/drizzle' import * as seeds from './seeds' import * as schema from './tables' +const drizzleService = new DrizzleService() + if (!env.DB_SEEDING) { throw new Error('You must set DB_SEEDING to "true" when running seeds') } -async function resetTable(db: db, table: Table) { +async function resetTable(db: NodePgDatabase, table: Table) { return db.execute(sql.raw(`TRUNCATE TABLE ${getTableName(table)} RESTART IDENTITY CASCADE`)) } @@ -19,33 +23,33 @@ for (const table of [ schema.collection_items, schema.collections, schema.credentialsTable, - schema.expansions, - schema.externalIds, + schema.expansionsTable, + schema.externalIdsTable, schema.federatedIdentityTable, - schema.games, - schema.gamesToExternalIds, - schema.mechanics, - schema.mechanicsToExternalIds, + schema.gamesTable, + schema.gamesToExternalIdsTable, + schema.mechanicsTable, + schema.mechanicsToExternalIdsTable, schema.mechanics_to_games, schema.password_reset_tokens, - schema.publishers, - schema.publishersToExternalIds, + schema.publishersTable, + schema.publishersToExternalIdsTable, schema.publishers_to_games, schema.recoveryCodesTable, - schema.roles, + schema.rolesTable, schema.sessionsTable, schema.twoFactorTable, schema.user_roles, schema.usersTable, schema.wishlist_items, - schema.wishlists, + schema.wishlistsTable, ]) { // await db.delete(table); // clear tables without truncating / resetting ids - await resetTable(db, table) + await resetTable(drizzleService.db, table) } -await seeds.roles(db) -await seeds.users(db) +await seeds.roles(drizzleService.db) +await seeds.users(drizzleService.db) -await pool.end() +await drizzleService.dispose() process.exit() diff --git a/src/lib/server/api/databases/seeds/roles.ts b/src/lib/server/api/databases/seeds/roles.ts index 518899c..35cefcd 100644 --- a/src/lib/server/api/databases/seeds/roles.ts +++ b/src/lib/server/api/databases/seeds/roles.ts @@ -3,9 +3,9 @@ import { type db } from '$lib/server/api/packages/drizzle' import roles from './data/roles.json' export default async function seed(db: db) { - console.log('Creating roles ...') + console.log('Creating rolesTable ...') for (const role of roles) { - await db.insert(schema.roles).values(role).onConflictDoNothing() + await db.insert(schema.rolesTable).values(role).onConflictDoNothing() } console.log('Roles created.') } diff --git a/src/lib/server/api/databases/seeds/users.ts b/src/lib/server/api/databases/seeds/users.ts index 23ae9f6..c9e6eeb 100644 --- a/src/lib/server/api/databases/seeds/users.ts +++ b/src/lib/server/api/databases/seeds/users.ts @@ -1,29 +1,18 @@ import * as schema from '$lib/server/api/databases/tables' -import { type db } from '$lib/server/api/packages/drizzle' +import type { db } from '$lib/server/api/packages/drizzle' import { eq } from 'drizzle-orm' import { Argon2id } from 'oslo/password' import { config } from '../../configs/config' import users from './data/users.json' -type JsonUser = { - id: string - username: string - email: string - password: string - roles: { - name: string - primary: boolean - }[] -} - type JsonRole = { name: string primary: boolean } export default async function seed(db: db) { - const adminRole = await db.select().from(schema.roles).where(eq(schema.roles.name, 'admin')) - const userRole = await db.select().from(schema.roles).where(eq(schema.roles.name, 'user')) + const adminRole = await db.select().from(schema.rolesTable).where(eq(schema.rolesTable.name, 'admin')) + const userRole = await db.select().from(schema.rolesTable).where(eq(schema.rolesTable.name, 'user')) console.log('Admin Role: ', adminRole) const adminUser = await db @@ -48,7 +37,7 @@ export default async function seed(db: db) { await db.insert(schema.collections).values({ user_id: adminUser[0].id }).onConflictDoNothing() - await db.insert(schema.wishlists).values({ user_id: adminUser[0].id }).onConflictDoNothing() + await db.insert(schema.wishlistsTable).values({ user_id: adminUser[0].id }).onConflictDoNothing() await db .insert(schema.user_roles) @@ -85,11 +74,11 @@ export default async function seed(db: db) { secret_data: await new Argon2id().hash(user.password), }) await db.insert(schema.collections).values({ user_id: insertedUser?.id }) - await db.insert(schema.wishlists).values({ user_id: insertedUser?.id }) + await db.insert(schema.wishlistsTable).values({ user_id: insertedUser?.id }) await Promise.all( user.roles.map(async (role: JsonRole) => { - const foundRole = await db.query.roles.findFirst({ - where: eq(schema.roles.name, role.name), + const foundRole = await db.query.rolesTable.findFirst({ + where: eq(schema.rolesTable.name, role.name), }) if (!foundRole) { throw new Error('Role not found') diff --git a/src/lib/server/api/databases/tables/categories.table.ts b/src/lib/server/api/databases/tables/categories.table.ts index eff7cc5..8f32634 100644 --- a/src/lib/server/api/databases/tables/categories.table.ts +++ b/src/lib/server/api/databases/tables/categories.table.ts @@ -1,9 +1,9 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' import { createId as cuid2 } from '@paralleldrive/cuid2' import { type InferSelectModel, relations } from 'drizzle-orm' import { pgTable, text, uuid } from 'drizzle-orm/pg-core' -import { categoriesToExternalIdsTable } from './categoriesToExternalIdsTable' -import { categories_to_games_table } from './categoriesToGames' +import { timestamps } from '../../common/utils/table' +import { categoriesToExternalIdsTable } from './categoriesToExternalIds.table' +import { categories_to_games_table } from './categoriesToGames.table' export const categoriesTable = pgTable('categories', { id: uuid('id').primaryKey().defaultRandom(), diff --git a/src/lib/server/api/databases/tables/categoriesToExternalIds.table.ts b/src/lib/server/api/databases/tables/categoriesToExternalIds.table.ts new file mode 100644 index 0000000..6825bf4 --- /dev/null +++ b/src/lib/server/api/databases/tables/categoriesToExternalIds.table.ts @@ -0,0 +1,34 @@ +import { relations } from 'drizzle-orm' +import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core' +import { categoriesTable } from './categories.table' +import { externalIdsTable } from './externalIds.table' + +export const categoriesToExternalIdsTable = pgTable( + 'categories_to_external_ids', + { + categoryId: uuid('category_id') + .notNull() + .references(() => categoriesTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), + externalId: uuid('external_id') + .notNull() + .references(() => externalIdsTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), + }, + (table) => { + return { + categoriesToExternalIdsPkey: primaryKey({ + columns: [table.categoryId, table.externalId], + }), + } + }, +) + +export const categoriesToExternalIdsRelations = relations(categoriesToExternalIdsTable, ({ one }) => ({ + category: one(categoriesTable, { + fields: [categoriesToExternalIdsTable.categoryId], + references: [categoriesTable.id], + }), + externalId: one(externalIdsTable, { + fields: [categoriesToExternalIdsTable.externalId], + references: [externalIdsTable.id], + }), +})) diff --git a/src/lib/server/api/databases/tables/categoriesToExternalIdsTable.ts b/src/lib/server/api/databases/tables/categoriesToExternalIdsTable.ts deleted file mode 100644 index c8ab5f3..0000000 --- a/src/lib/server/api/databases/tables/categoriesToExternalIdsTable.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core'; -import { categoriesTable } from './categories.table'; -import { externalIds } from './externalIds'; -import { relations } from 'drizzle-orm'; - -export const categoriesToExternalIdsTable = pgTable( - 'categories_to_external_ids', - { - categoryId: uuid('category_id') - .notNull() - .references(() => categoriesTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), - externalId: uuid('external_id') - .notNull() - .references(() => externalIds.id, { onDelete: 'restrict', onUpdate: 'cascade' }), - }, - (table) => { - return { - categoriesToExternalIdsPkey: primaryKey({ - columns: [table.categoryId, table.externalId], - }), - }; - }, -); - -export const categoriesToExternalIdsRelations = relations( - categoriesToExternalIdsTable, - ({ one }) => ({ - category: one(categoriesTable, { - fields: [categoriesToExternalIdsTable.categoryId], - references: [categoriesTable.id], - }), - externalId: one(externalIds, { - fields: [categoriesToExternalIdsTable.externalId], - references: [externalIds.id], - }), - }), -); diff --git a/src/lib/server/api/databases/tables/categoriesToGames.ts b/src/lib/server/api/databases/tables/categoriesToGames.table.ts similarity index 65% rename from src/lib/server/api/databases/tables/categoriesToGames.ts rename to src/lib/server/api/databases/tables/categoriesToGames.table.ts index a977fdd..80bb6c5 100644 --- a/src/lib/server/api/databases/tables/categoriesToGames.ts +++ b/src/lib/server/api/databases/tables/categoriesToGames.table.ts @@ -1,7 +1,7 @@ -import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core'; -import { relations } from 'drizzle-orm'; -import { categoriesTable } from './categories.table'; -import { games } from './games'; +import { relations } from 'drizzle-orm' +import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core' +import { gamesTable } from '././games.table' +import { categoriesTable } from './categories.table' export const categories_to_games_table = pgTable( 'categories_to_games', @@ -11,25 +11,24 @@ export const categories_to_games_table = pgTable( .references(() => categoriesTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), game_id: uuid('game_id') .notNull() - .references(() => games.id, { onDelete: 'restrict', onUpdate: 'cascade' }), + .references(() => gamesTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), }, (table) => { return { categoriesToGamesPkey: primaryKey({ columns: [table.category_id, table.game_id], }), - }; + } }, -); +) export const categories_to_games_relations = relations(categories_to_games_table, ({ one }) => ({ category: one(categoriesTable, { fields: [categories_to_games_table.category_id], references: [categoriesTable.id], }), - game: one(games, { + game: one(gamesTable, { fields: [categories_to_games_table.game_id], - references: [games.id], + references: [gamesTable.id], }), -})); - +})) diff --git a/src/lib/server/api/databases/tables/collectionItems.ts b/src/lib/server/api/databases/tables/collectionItems.table.ts similarity index 70% rename from src/lib/server/api/databases/tables/collectionItems.ts rename to src/lib/server/api/databases/tables/collectionItems.table.ts index 8466605..722a707 100644 --- a/src/lib/server/api/databases/tables/collectionItems.ts +++ b/src/lib/server/api/databases/tables/collectionItems.table.ts @@ -1,9 +1,9 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' import { createId as cuid2 } from '@paralleldrive/cuid2' import { type InferSelectModel, relations } from 'drizzle-orm' import { integer, pgTable, text, uuid } from 'drizzle-orm/pg-core' -import { collections } from './collections' -import { games } from './games' +import { timestamps } from '../../common/utils/table' +import { gamesTable } from '././games.table' +import { collections } from './collections.table' export const collection_items = pgTable('collection_items', { id: uuid('id').primaryKey().defaultRandom(), @@ -15,20 +15,20 @@ export const collection_items = pgTable('collection_items', { .references(() => collections.id, { onDelete: 'cascade' }), game_id: uuid('game_id') .notNull() - .references(() => games.id, { onDelete: 'cascade' }), + .references(() => gamesTable.id, { onDelete: 'cascade' }), times_played: integer('times_played').default(0), ...timestamps, }) -export type CollectionItems = InferSelectModel +export type CollectionItemsTable = InferSelectModel export const collection_item_relations = relations(collection_items, ({ one }) => ({ collection: one(collections, { fields: [collection_items.collection_id], references: [collections.id], }), - game: one(games, { + game: one(gamesTable, { fields: [collection_items.game_id], - references: [games.id], + references: [gamesTable.id], }), })) diff --git a/src/lib/server/api/databases/tables/collections.ts b/src/lib/server/api/databases/tables/collections.table.ts similarity index 91% rename from src/lib/server/api/databases/tables/collections.ts rename to src/lib/server/api/databases/tables/collections.table.ts index ed1499e..715bf4d 100644 --- a/src/lib/server/api/databases/tables/collections.ts +++ b/src/lib/server/api/databases/tables/collections.table.ts @@ -1,7 +1,7 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' import { createId as cuid2 } from '@paralleldrive/cuid2' import { type InferSelectModel, relations } from 'drizzle-orm' import { pgTable, text, uuid } from 'drizzle-orm/pg-core' +import { timestamps } from '../../common/utils/table' import { usersTable } from './users.table' export const collections = pgTable('collections', { diff --git a/src/lib/server/api/databases/tables/credentials.table.ts b/src/lib/server/api/databases/tables/credentials.table.ts index f0204b5..8226397 100644 --- a/src/lib/server/api/databases/tables/credentials.table.ts +++ b/src/lib/server/api/databases/tables/credentials.table.ts @@ -1,6 +1,6 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' import { type InferSelectModel } from 'drizzle-orm' import { pgTable, text, uuid } from 'drizzle-orm/pg-core' +import { timestamps } from '../../common/utils/table' import { usersTable } from './users.table' export enum CredentialsType { diff --git a/src/lib/server/api/databases/tables/expansions.table.ts b/src/lib/server/api/databases/tables/expansions.table.ts new file mode 100644 index 0000000..fc9e634 --- /dev/null +++ b/src/lib/server/api/databases/tables/expansions.table.ts @@ -0,0 +1,32 @@ +import { createId as cuid2 } from '@paralleldrive/cuid2' +import { type InferSelectModel, relations } from 'drizzle-orm' +import { pgTable, text, uuid } from 'drizzle-orm/pg-core' +import { timestamps } from '../../common/utils/table' +import { gamesTable } from '././games.table' + +export const expansionsTable = pgTable('expansions', { + id: uuid('id').primaryKey().defaultRandom(), + cuid: text('cuid') + .unique() + .$defaultFn(() => cuid2()), + base_game_id: uuid('base_game_id') + .notNull() + .references(() => gamesTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), + game_id: uuid('game_id') + .notNull() + .references(() => gamesTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), + ...timestamps, +}) + +export type Expansions = InferSelectModel + +export const expansion_relations = relations(expansionsTable, ({ one }) => ({ + baseGame: one(gamesTable, { + fields: [expansionsTable.base_game_id], + references: [gamesTable.id], + }), + game: one(gamesTable, { + fields: [expansionsTable.game_id], + references: [gamesTable.id], + }), +})) diff --git a/src/lib/server/api/databases/tables/expansions.ts b/src/lib/server/api/databases/tables/expansions.ts deleted file mode 100644 index fa6dd26..0000000 --- a/src/lib/server/api/databases/tables/expansions.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' -import { createId as cuid2 } from '@paralleldrive/cuid2' -import { type InferSelectModel, relations } from 'drizzle-orm' -import { pgTable, text, uuid } from 'drizzle-orm/pg-core' -import { games } from './games' - -export const expansions = pgTable('expansions', { - id: uuid('id').primaryKey().defaultRandom(), - cuid: text('cuid') - .unique() - .$defaultFn(() => cuid2()), - base_game_id: uuid('base_game_id') - .notNull() - .references(() => games.id, { onDelete: 'restrict', onUpdate: 'cascade' }), - game_id: uuid('game_id') - .notNull() - .references(() => games.id, { onDelete: 'restrict', onUpdate: 'cascade' }), - ...timestamps, -}) - -export type Expansions = InferSelectModel - -export const expansion_relations = relations(expansions, ({ one }) => ({ - baseGame: one(games, { - fields: [expansions.base_game_id], - references: [games.id], - }), - game: one(games, { - fields: [expansions.game_id], - references: [games.id], - }), -})) diff --git a/src/lib/server/api/databases/tables/externalIds.table.ts b/src/lib/server/api/databases/tables/externalIds.table.ts new file mode 100644 index 0000000..0df8f31 --- /dev/null +++ b/src/lib/server/api/databases/tables/externalIds.table.ts @@ -0,0 +1,16 @@ +import { createId as cuid2 } from '@paralleldrive/cuid2' +import type { InferSelectModel } from 'drizzle-orm' +import { pgEnum, pgTable, text, uuid } from 'drizzle-orm/pg-core' + +export const externalIdType = pgEnum('external_id_type', ['game', 'category', 'mechanic', 'publisher', 'designer', 'artist']) + +export const externalIdsTable = pgTable('external_ids', { + id: uuid('id').primaryKey().defaultRandom(), + cuid: text('cuid') + .unique() + .$defaultFn(() => cuid2()), + type: externalIdType('type'), + externalId: text('external_id').notNull(), +}) + +export type ExternalIds = InferSelectModel diff --git a/src/lib/server/api/databases/tables/externalIds.ts b/src/lib/server/api/databases/tables/externalIds.ts deleted file mode 100644 index 80c1033..0000000 --- a/src/lib/server/api/databases/tables/externalIds.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { pgEnum, pgTable, text, uuid } from 'drizzle-orm/pg-core'; -import { createId as cuid2 } from '@paralleldrive/cuid2'; -import type { InferSelectModel } from 'drizzle-orm'; - -export const externalIdType = pgEnum('external_id_type', [ - 'game', - 'category', - 'mechanic', - 'publisher', - 'designer', - 'artist', -]); - -export const externalIds = pgTable('external_ids', { - id: uuid('id').primaryKey().defaultRandom(), - cuid: text('cuid') - .unique() - .$defaultFn(() => cuid2()), - type: externalIdType('type'), - externalId: text('external_id').notNull(), -}); - -export type ExternalIds = InferSelectModel; diff --git a/src/lib/server/api/databases/tables/federatedIdentity.table.ts b/src/lib/server/api/databases/tables/federatedIdentity.table.ts index 311683c..35b409b 100644 --- a/src/lib/server/api/databases/tables/federatedIdentity.table.ts +++ b/src/lib/server/api/databases/tables/federatedIdentity.table.ts @@ -1,6 +1,6 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' import { type InferSelectModel } from 'drizzle-orm' import { pgTable, text, uuid } from 'drizzle-orm/pg-core' +import { timestamps } from '../../common/utils/table' import { usersTable } from './users.table' export const federatedIdentityTable = pgTable('federated_identity', { diff --git a/src/lib/server/api/databases/tables/games.ts b/src/lib/server/api/databases/tables/games.table.ts similarity index 69% rename from src/lib/server/api/databases/tables/games.ts rename to src/lib/server/api/databases/tables/games.table.ts index 3767bc2..c2eb49e 100644 --- a/src/lib/server/api/databases/tables/games.ts +++ b/src/lib/server/api/databases/tables/games.table.ts @@ -1,13 +1,13 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' import { createId as cuid2 } from '@paralleldrive/cuid2' import { type InferSelectModel, relations, sql } from 'drizzle-orm' import { index, integer, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core' -import { categories_to_games_table } from './categoriesToGames' -import { gamesToExternalIds } from './gamesToExternalIds' -import { mechanics_to_games } from './mechanicsToGames' -import { publishers_to_games } from './publishersToGames' +import { timestamps } from '../../common/utils/table' +import { categories_to_games_table } from './categoriesToGames.table' +import { gamesToExternalIdsTable } from './gamesToExternalIds.table' +import { mechanics_to_games } from './mechanicsToGames.table' +import { publishers_to_games } from './publishersToGames.table' -export const games = pgTable( +export const gamesTable = pgTable( 'games', { id: uuid('id').primaryKey().defaultRandom(), @@ -41,11 +41,11 @@ export const games = pgTable( }), ) -export const gameRelations = relations(games, ({ many }) => ({ +export const gameRelations = relations(gamesTable, ({ many }) => ({ categories_to_games: many(categories_to_games_table), mechanics_to_games: many(mechanics_to_games), publishers_to_games: many(publishers_to_games), - gamesToExternalIds: many(gamesToExternalIds), + gamesToExternalIds: many(gamesToExternalIdsTable), })) -export type Games = InferSelectModel +export type Games = InferSelectModel diff --git a/src/lib/server/api/databases/tables/gamesToExternalIds.table.ts b/src/lib/server/api/databases/tables/gamesToExternalIds.table.ts new file mode 100644 index 0000000..8b19da3 --- /dev/null +++ b/src/lib/server/api/databases/tables/gamesToExternalIds.table.ts @@ -0,0 +1,22 @@ +import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core' +import { gamesTable } from '././games.table' +import { externalIdsTable } from './externalIds.table' + +export const gamesToExternalIdsTable = pgTable( + 'games_to_external_ids', + { + gameId: uuid('game_id') + .notNull() + .references(() => gamesTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), + externalId: uuid('external_id') + .notNull() + .references(() => externalIdsTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), + }, + (table) => { + return { + gamesToExternalIdsPkey: primaryKey({ + columns: [table.gameId, table.externalId], + }), + } + }, +) diff --git a/src/lib/server/api/databases/tables/gamesToExternalIds.ts b/src/lib/server/api/databases/tables/gamesToExternalIds.ts deleted file mode 100644 index b625924..0000000 --- a/src/lib/server/api/databases/tables/gamesToExternalIds.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core'; -import {games} from './games'; -import {externalIds} from './externalIds'; - -export const gamesToExternalIds = pgTable( - 'games_to_external_ids', - { - gameId: uuid('game_id') - .notNull() - .references(() => games.id, { onDelete: 'restrict', onUpdate: 'cascade' }), - externalId: uuid('external_id') - .notNull() - .references(() => externalIds.id, { onDelete: 'restrict', onUpdate: 'cascade' }), - }, - (table) => { - return { - gamesToExternalIdsPkey: primaryKey({ - columns: [table.gameId, table.externalId], - }), - }; - }, -); diff --git a/src/lib/server/api/databases/tables/index.ts b/src/lib/server/api/databases/tables/index.ts index 3f96c54..006272a 100644 --- a/src/lib/server/api/databases/tables/index.ts +++ b/src/lib/server/api/databases/tables/index.ts @@ -1,26 +1,26 @@ -export * from './categories.table'; -export * from './categoriesToExternalIdsTable'; -export * from './categoriesToGames'; -export * from './collectionItems'; -export * from './collections'; -export * from './credentials.table'; -export * from './expansions'; -export * from './externalIds'; -export * from './federatedIdentity.table'; -export * from './games'; -export * from './gamesToExternalIds'; -export * from './mechanics'; -export * from './mechanicsToExternalIds'; -export * from './mechanicsToGames' -export * from './passwordResetTokens'; -export * from './publishers'; -export * from './publishersToExternalIds'; -export * from './publishersToGames'; -export * from './recovery-codes.table'; -export * from './roles'; -export * from './sessions.table'; -export * from './two-factor.table'; -export * from './userRoles'; -export * from './users.table'; -export * from './wishlistItems'; -export * from './wishlists'; \ No newline at end of file +export * from './categories.table' +export * from './categoriesToExternalIds.table' +export * from './categoriesToGames.table' +export * from './collectionItems.table' +export * from './collections.table' +export * from './credentials.table' +export * from './expansions.table' +export * from './externalIds.table' +export * from './federatedIdentity.table' +export * from './games.table' +export * from './gamesToExternalIds.table' +export * from './mechanics.table' +export * from './mechanicsToExternalIds.table' +export * from './mechanicsToGames.table' +export * from './passwordResetTokens.table' +export * from './publishers.table' +export * from './publishersToExternalIds.table' +export * from './publishersToGames.table' +export * from './recovery-codes.table' +export * from './roles.table' +export * from './sessions.table' +export * from './two-factor.table' +export * from './userRoles.table' +export * from './users.table' +export * from './wishlistItems.table' +export * from './wishlists.table' diff --git a/src/lib/server/api/databases/tables/mechanics.table.ts b/src/lib/server/api/databases/tables/mechanics.table.ts new file mode 100644 index 0000000..fab6757 --- /dev/null +++ b/src/lib/server/api/databases/tables/mechanics.table.ts @@ -0,0 +1,23 @@ +import { createId as cuid2 } from '@paralleldrive/cuid2' +import { type InferSelectModel, relations } from 'drizzle-orm' +import { pgTable, text, uuid } from 'drizzle-orm/pg-core' +import { timestamps } from '../../common/utils/table' +import { mechanicsToExternalIdsTable } from './mechanicsToExternalIds.table' +import { mechanics_to_games } from './mechanicsToGames.table' + +export const mechanicsTable = pgTable('mechanics', { + id: uuid('id').primaryKey().defaultRandom(), + cuid: text('cuid') + .unique() + .$defaultFn(() => cuid2()), + name: text('name'), + slug: text('slug'), + ...timestamps, +}) + +export type Mechanics = InferSelectModel + +export const mechanics_relations = relations(mechanicsTable, ({ many }) => ({ + mechanics_to_games: many(mechanics_to_games), + mechanicsToExternalIds: many(mechanicsToExternalIdsTable), +})) diff --git a/src/lib/server/api/databases/tables/mechanics.ts b/src/lib/server/api/databases/tables/mechanics.ts deleted file mode 100644 index b017a7b..0000000 --- a/src/lib/server/api/databases/tables/mechanics.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' -import { createId as cuid2 } from '@paralleldrive/cuid2' -import { type InferSelectModel, relations } from 'drizzle-orm' -import { pgTable, text, uuid } from 'drizzle-orm/pg-core' -import { mechanicsToExternalIds } from './mechanicsToExternalIds' -import { mechanics_to_games } from './mechanicsToGames' - -export const mechanics = pgTable('mechanics', { - id: uuid('id').primaryKey().defaultRandom(), - cuid: text('cuid') - .unique() - .$defaultFn(() => cuid2()), - name: text('name'), - slug: text('slug'), - ...timestamps, -}) - -export type Mechanics = InferSelectModel - -export const mechanics_relations = relations(mechanics, ({ many }) => ({ - mechanics_to_games: many(mechanics_to_games), - mechanicsToExternalIds: many(mechanicsToExternalIds), -})) diff --git a/src/lib/server/api/databases/tables/mechanicsToExternalIds.table.ts b/src/lib/server/api/databases/tables/mechanicsToExternalIds.table.ts new file mode 100644 index 0000000..bb28cac --- /dev/null +++ b/src/lib/server/api/databases/tables/mechanicsToExternalIds.table.ts @@ -0,0 +1,22 @@ +import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core' +import { externalIdsTable } from './externalIds.table' +import { mechanicsTable } from './mechanics.table' + +export const mechanicsToExternalIdsTable = pgTable( + 'mechanics_to_external_ids', + { + mechanicId: uuid('mechanic_id') + .notNull() + .references(() => mechanicsTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), + externalId: uuid('external_id') + .notNull() + .references(() => externalIdsTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), + }, + (table) => { + return { + mechanicsToExternalIdsPkey: primaryKey({ + columns: [table.mechanicId, table.externalId], + }), + } + }, +) diff --git a/src/lib/server/api/databases/tables/mechanicsToExternalIds.ts b/src/lib/server/api/databases/tables/mechanicsToExternalIds.ts deleted file mode 100644 index b755eab..0000000 --- a/src/lib/server/api/databases/tables/mechanicsToExternalIds.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core'; -import {mechanics} from './mechanics'; -import {externalIds} from './externalIds'; - -export const mechanicsToExternalIds = pgTable( - 'mechanics_to_external_ids', - { - mechanicId: uuid('mechanic_id') - .notNull() - .references(() => mechanics.id, { onDelete: 'restrict', onUpdate: 'cascade' }), - externalId: uuid('external_id') - .notNull() - .references(() => externalIds.id, { onDelete: 'restrict', onUpdate: 'cascade' }), - }, - (table) => { - return { - mechanicsToExternalIdsPkey: primaryKey({ - columns: [table.mechanicId, table.externalId], - }), - }; - }, -); diff --git a/src/lib/server/api/databases/tables/mechanicsToGames.table.ts b/src/lib/server/api/databases/tables/mechanicsToGames.table.ts new file mode 100644 index 0000000..eaf9e5a --- /dev/null +++ b/src/lib/server/api/databases/tables/mechanicsToGames.table.ts @@ -0,0 +1,34 @@ +import { relations } from 'drizzle-orm' +import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core' +import { gamesTable } from '././games.table' +import { mechanicsTable } from './mechanics.table' + +export const mechanics_to_games = pgTable( + 'mechanics_to_games', + { + mechanic_id: uuid('mechanic_id') + .notNull() + .references(() => mechanicsTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), + game_id: uuid('game_id') + .notNull() + .references(() => gamesTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), + }, + (table) => { + return { + mechanicsToGamesPkey: primaryKey({ + columns: [table.mechanic_id, table.game_id], + }), + } + }, +) + +export const mechanics_to_games_relations = relations(mechanics_to_games, ({ one }) => ({ + mechanic: one(mechanicsTable, { + fields: [mechanics_to_games.mechanic_id], + references: [mechanicsTable.id], + }), + game: one(gamesTable, { + fields: [mechanics_to_games.game_id], + references: [gamesTable.id], + }), +})) diff --git a/src/lib/server/api/databases/tables/mechanicsToGames.ts b/src/lib/server/api/databases/tables/mechanicsToGames.ts deleted file mode 100644 index c81cde4..0000000 --- a/src/lib/server/api/databases/tables/mechanicsToGames.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core'; -import { relations } from 'drizzle-orm'; -import {mechanics} from './mechanics'; -import {games} from './games'; - -export const mechanics_to_games = pgTable( - 'mechanics_to_games', - { - mechanic_id: uuid('mechanic_id') - .notNull() - .references(() => mechanics.id, { onDelete: 'restrict', onUpdate: 'cascade' }), - game_id: uuid('game_id') - .notNull() - .references(() => games.id, { onDelete: 'restrict', onUpdate: 'cascade' }), - }, - (table) => { - return { - mechanicsToGamesPkey: primaryKey({ - columns: [table.mechanic_id, table.game_id], - }), - }; - }, -); - -export const mechanics_to_games_relations = relations(mechanics_to_games, ({ one }) => ({ - mechanic: one(mechanics, { - fields: [mechanics_to_games.mechanic_id], - references: [mechanics.id], - }), - game: one(games, { - fields: [mechanics_to_games.game_id], - references: [games.id], - }), -})); diff --git a/src/lib/server/api/databases/tables/passwordResetTokens.ts b/src/lib/server/api/databases/tables/passwordResetTokens.table.ts similarity index 82% rename from src/lib/server/api/databases/tables/passwordResetTokens.ts rename to src/lib/server/api/databases/tables/passwordResetTokens.table.ts index 9531e0e..df5444f 100644 --- a/src/lib/server/api/databases/tables/passwordResetTokens.ts +++ b/src/lib/server/api/databases/tables/passwordResetTokens.table.ts @@ -1,7 +1,7 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' import { createId as cuid2 } from '@paralleldrive/cuid2' import { type InferSelectModel, relations } from 'drizzle-orm' import { pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core' +import { timestamps } from '../../common/utils/table' import { usersTable } from './users.table' export const password_reset_tokens = pgTable('password_reset_tokens', { @@ -15,7 +15,7 @@ export const password_reset_tokens = pgTable('password_reset_tokens', { ...timestamps, }) -export type PasswordResetTokens = InferSelectModel +export type PasswordResetTokensTable = InferSelectModel export const password_reset_token_relations = relations(password_reset_tokens, ({ one }) => ({ user: one(usersTable, { diff --git a/src/lib/server/api/databases/tables/publishers.table.ts b/src/lib/server/api/databases/tables/publishers.table.ts new file mode 100644 index 0000000..8102539 --- /dev/null +++ b/src/lib/server/api/databases/tables/publishers.table.ts @@ -0,0 +1,23 @@ +import { createId as cuid2 } from '@paralleldrive/cuid2' +import { type InferSelectModel, relations } from 'drizzle-orm' +import { pgTable, text, uuid } from 'drizzle-orm/pg-core' +import { timestamps } from '../../common/utils/table' +import { publishersToExternalIdsTable } from './publishersToExternalIds.table' +import { publishers_to_games } from './publishersToGames.table' + +export const publishersTable = pgTable('publishers', { + id: uuid('id').primaryKey().defaultRandom(), + cuid: text('cuid') + .unique() + .$defaultFn(() => cuid2()), + name: text('name'), + slug: text('slug'), + ...timestamps, +}) + +export type Publishers = InferSelectModel + +export const publishers_relations = relations(publishersTable, ({ many }) => ({ + publishers_to_games: many(publishers_to_games), + publishersToExternalIds: many(publishersToExternalIdsTable), +})) diff --git a/src/lib/server/api/databases/tables/publishers.ts b/src/lib/server/api/databases/tables/publishers.ts deleted file mode 100644 index e501f4c..0000000 --- a/src/lib/server/api/databases/tables/publishers.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' -import { createId as cuid2 } from '@paralleldrive/cuid2' -import { type InferSelectModel, relations } from 'drizzle-orm' -import { pgTable, text, uuid } from 'drizzle-orm/pg-core' -import { publishersToExternalIds } from './publishersToExternalIds' -import { publishers_to_games } from './publishersToGames' - -export const publishers = pgTable('publishers', { - id: uuid('id').primaryKey().defaultRandom(), - cuid: text('cuid') - .unique() - .$defaultFn(() => cuid2()), - name: text('name'), - slug: text('slug'), - ...timestamps, -}) - -export type Publishers = InferSelectModel - -export const publishers_relations = relations(publishers, ({ many }) => ({ - publishers_to_games: many(publishers_to_games), - publishersToExternalIds: many(publishersToExternalIds), -})) diff --git a/src/lib/server/api/databases/tables/publishersToExternalIds.table.ts b/src/lib/server/api/databases/tables/publishersToExternalIds.table.ts new file mode 100644 index 0000000..d16786b --- /dev/null +++ b/src/lib/server/api/databases/tables/publishersToExternalIds.table.ts @@ -0,0 +1,22 @@ +import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core' +import { externalIdsTable } from './externalIds.table' +import { publishersTable } from './publishers.table' + +export const publishersToExternalIdsTable = pgTable( + 'publishers_to_external_ids', + { + publisherId: uuid('publisher_id') + .notNull() + .references(() => publishersTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), + externalId: uuid('external_id') + .notNull() + .references(() => externalIdsTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), + }, + (table) => { + return { + publishersToExternalIdsPkey: primaryKey({ + columns: [table.publisherId, table.externalId], + }), + } + }, +) diff --git a/src/lib/server/api/databases/tables/publishersToExternalIds.ts b/src/lib/server/api/databases/tables/publishersToExternalIds.ts deleted file mode 100644 index 1f630d8..0000000 --- a/src/lib/server/api/databases/tables/publishersToExternalIds.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core'; -import {publishers} from './publishers'; -import {externalIds} from './externalIds'; - -export const publishersToExternalIds = pgTable( - 'publishers_to_external_ids', - { - publisherId: uuid('publisher_id') - .notNull() - .references(() => publishers.id, { onDelete: 'restrict', onUpdate: 'cascade' }), - externalId: uuid('external_id') - .notNull() - .references(() => externalIds.id, { onDelete: 'restrict', onUpdate: 'cascade' }), - }, - (table) => { - return { - publishersToExternalIdsPkey: primaryKey({ - columns: [table.publisherId, table.externalId], - }), - }; - }, -); diff --git a/src/lib/server/api/databases/tables/publishersToGames.ts b/src/lib/server/api/databases/tables/publishersToGames.table.ts similarity index 50% rename from src/lib/server/api/databases/tables/publishersToGames.ts rename to src/lib/server/api/databases/tables/publishersToGames.table.ts index f2c2d24..3d772a2 100644 --- a/src/lib/server/api/databases/tables/publishersToGames.ts +++ b/src/lib/server/api/databases/tables/publishersToGames.table.ts @@ -1,34 +1,34 @@ -import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core'; -import { relations } from 'drizzle-orm'; -import {publishers} from './publishers'; -import {games} from './games'; +import { relations } from 'drizzle-orm' +import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core' +import { gamesTable } from '././games.table' +import { publishersTable } from './publishers.table' export const publishers_to_games = pgTable( 'publishers_to_games', { publisher_id: uuid('publisher_id') .notNull() - .references(() => publishers.id, { onDelete: 'restrict', onUpdate: 'cascade' }), + .references(() => publishersTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), game_id: uuid('game_id') .notNull() - .references(() => games.id, { onDelete: 'restrict', onUpdate: 'cascade' }), + .references(() => gamesTable.id, { onDelete: 'restrict', onUpdate: 'cascade' }), }, (table) => { return { publishersToGamesPkey: primaryKey({ columns: [table.publisher_id, table.game_id], }), - }; + } }, -); +) export const publishers_to_games_relations = relations(publishers_to_games, ({ one }) => ({ - publisher: one(publishers, { + publisher: one(publishersTable, { fields: [publishers_to_games.publisher_id], - references: [publishers.id], + references: [publishersTable.id], }), - game: one(games, { + game: one(gamesTable, { fields: [publishers_to_games.game_id], - references: [games.id], + references: [gamesTable.id], }), -})); +})) diff --git a/src/lib/server/api/databases/tables/recovery-codes.table.ts b/src/lib/server/api/databases/tables/recovery-codes.table.ts index 1429da0..d79e469 100644 --- a/src/lib/server/api/databases/tables/recovery-codes.table.ts +++ b/src/lib/server/api/databases/tables/recovery-codes.table.ts @@ -1,6 +1,6 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' import type { InferSelectModel } from 'drizzle-orm' import { boolean, pgTable, text, uuid } from 'drizzle-orm/pg-core' +import { timestamps } from '../../common/utils/table' import { usersTable } from './users.table' export const recoveryCodesTable = pgTable('recovery_codes', { diff --git a/src/lib/server/api/databases/tables/roles.ts b/src/lib/server/api/databases/tables/roles.table.ts similarity index 59% rename from src/lib/server/api/databases/tables/roles.ts rename to src/lib/server/api/databases/tables/roles.table.ts index 0630396..1dfcfc2 100644 --- a/src/lib/server/api/databases/tables/roles.ts +++ b/src/lib/server/api/databases/tables/roles.table.ts @@ -1,10 +1,10 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' import { createId as cuid2 } from '@paralleldrive/cuid2' import { type InferSelectModel, relations } from 'drizzle-orm' import { pgTable, text, uuid } from 'drizzle-orm/pg-core' -import { user_roles } from './userRoles' +import { timestamps } from '../../common/utils/table' +import { user_roles } from './userRoles.table' -export const roles = pgTable('roles', { +export const rolesTable = pgTable('roles', { id: uuid('id').primaryKey().defaultRandom(), cuid: text('cuid') .unique() @@ -14,8 +14,8 @@ export const roles = pgTable('roles', { ...timestamps, }) -export type Roles = InferSelectModel +export type Roles = InferSelectModel -export const role_relations = relations(roles, ({ many }) => ({ +export const role_relations = relations(rolesTable, ({ many }) => ({ user_roles: many(user_roles), })) diff --git a/src/lib/server/api/databases/tables/two-factor.table.ts b/src/lib/server/api/databases/tables/two-factor.table.ts index a8ce4d7..f5e794f 100644 --- a/src/lib/server/api/databases/tables/two-factor.table.ts +++ b/src/lib/server/api/databases/tables/two-factor.table.ts @@ -1,7 +1,7 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' import { createId as cuid2 } from '@paralleldrive/cuid2' import { type InferSelectModel, relations } from 'drizzle-orm' import { boolean, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core' +import { timestamps } from '../../common/utils/table' import { usersTable } from './users.table' export const twoFactorTable = pgTable('two_factor', { diff --git a/src/lib/server/api/databases/tables/userRoles.ts b/src/lib/server/api/databases/tables/userRoles.table.ts similarity index 74% rename from src/lib/server/api/databases/tables/userRoles.ts rename to src/lib/server/api/databases/tables/userRoles.table.ts index 265bf88..e55d121 100644 --- a/src/lib/server/api/databases/tables/userRoles.ts +++ b/src/lib/server/api/databases/tables/userRoles.table.ts @@ -1,8 +1,8 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' import { createId as cuid2 } from '@paralleldrive/cuid2' import { type InferSelectModel, relations } from 'drizzle-orm' import { boolean, pgTable, text, uuid } from 'drizzle-orm/pg-core' -import { roles } from './roles' +import { timestamps } from '../../common/utils/table' +import { rolesTable } from './roles.table' import { usersTable } from './users.table' export const user_roles = pgTable('user_roles', { @@ -15,15 +15,15 @@ export const user_roles = pgTable('user_roles', { .references(() => usersTable.id, { onDelete: 'cascade' }), role_id: uuid('role_id') .notNull() - .references(() => roles.id, { onDelete: 'cascade' }), + .references(() => rolesTable.id, { onDelete: 'cascade' }), primary: boolean('primary').default(false), ...timestamps, }) export const user_role_relations = relations(user_roles, ({ one }) => ({ - role: one(roles, { + role: one(rolesTable, { fields: [user_roles.role_id], - references: [roles.id], + references: [rolesTable.id], }), user: one(usersTable, { fields: [user_roles.user_id], @@ -31,4 +31,4 @@ export const user_role_relations = relations(user_roles, ({ one }) => ({ }), })) -export type UserRoles = InferSelectModel +export type UserRolesTable = InferSelectModel diff --git a/src/lib/server/api/databases/tables/users.table.ts b/src/lib/server/api/databases/tables/users.table.ts index 93850c0..2836dba 100644 --- a/src/lib/server/api/databases/tables/users.table.ts +++ b/src/lib/server/api/databases/tables/users.table.ts @@ -1,8 +1,8 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' import { createId as cuid2 } from '@paralleldrive/cuid2' import { type InferSelectModel, relations } from 'drizzle-orm' import { boolean, pgTable, text, uuid } from 'drizzle-orm/pg-core' -import { user_roles } from './userRoles' +import { timestamps } from '../../common/utils/table' +import { user_roles } from './userRoles.table' export const usersTable = pgTable('users', { id: uuid('id').primaryKey().defaultRandom(), diff --git a/src/lib/server/api/databases/tables/wishlistItems.ts b/src/lib/server/api/databases/tables/wishlistItems.table.ts similarity index 56% rename from src/lib/server/api/databases/tables/wishlistItems.ts rename to src/lib/server/api/databases/tables/wishlistItems.table.ts index e9d57c8..358395d 100644 --- a/src/lib/server/api/databases/tables/wishlistItems.ts +++ b/src/lib/server/api/databases/tables/wishlistItems.table.ts @@ -1,9 +1,9 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' import { createId as cuid2 } from '@paralleldrive/cuid2' import { type InferSelectModel, relations } from 'drizzle-orm' import { pgTable, text, uuid } from 'drizzle-orm/pg-core' -import { games } from './games' -import { wishlists } from './wishlists' +import { timestamps } from '../../common/utils/table' +import { gamesTable } from '././games.table' +import { wishlistsTable } from './wishlists.table' export const wishlist_items = pgTable('wishlist_items', { id: uuid('id').primaryKey().defaultRandom(), @@ -12,22 +12,22 @@ export const wishlist_items = pgTable('wishlist_items', { .$defaultFn(() => cuid2()), wishlist_id: uuid('wishlist_id') .notNull() - .references(() => wishlists.id, { onDelete: 'cascade' }), + .references(() => wishlistsTable.id, { onDelete: 'cascade' }), game_id: uuid('game_id') .notNull() - .references(() => games.id, { onDelete: 'cascade' }), + .references(() => gamesTable.id, { onDelete: 'cascade' }), ...timestamps, }) -export type WishlistItems = InferSelectModel +export type WishlistItemsTable = InferSelectModel export const wishlist_item_relations = relations(wishlist_items, ({ one }) => ({ - wishlist: one(wishlists, { + wishlist: one(wishlistsTable, { fields: [wishlist_items.wishlist_id], - references: [wishlists.id], + references: [wishlistsTable.id], }), - game: one(games, { + game: one(gamesTable, { fields: [wishlist_items.game_id], - references: [games.id], + references: [gamesTable.id], }), })) diff --git a/src/lib/server/api/databases/tables/wishlists.ts b/src/lib/server/api/databases/tables/wishlists.table.ts similarity index 66% rename from src/lib/server/api/databases/tables/wishlists.ts rename to src/lib/server/api/databases/tables/wishlists.table.ts index 10dbec9..34f7bf8 100644 --- a/src/lib/server/api/databases/tables/wishlists.ts +++ b/src/lib/server/api/databases/tables/wishlists.table.ts @@ -1,10 +1,10 @@ -import { timestamps } from '$lib/server/api/common/utils/table.utils' import { createId as cuid2 } from '@paralleldrive/cuid2' import { type InferSelectModel, relations } from 'drizzle-orm' import { pgTable, text, uuid } from 'drizzle-orm/pg-core' +import { timestamps } from '../../common/utils/table' import { usersTable } from './users.table' -export const wishlists = pgTable('wishlists', { +export const wishlistsTable = pgTable('wishlists', { id: uuid('id').primaryKey().defaultRandom(), cuid: text('cuid') .unique() @@ -16,11 +16,11 @@ export const wishlists = pgTable('wishlists', { ...timestamps, }) -export type Wishlists = InferSelectModel +export type Wishlists = InferSelectModel -export const wishlists_relations = relations(wishlists, ({ one }) => ({ +export const wishlists_relations = relations(wishlistsTable, ({ one }) => ({ user: one(usersTable, { - fields: [wishlists.user_id], + fields: [wishlistsTable.user_id], references: [usersTable.id], }), })) diff --git a/src/lib/server/api/index.ts b/src/lib/server/api/index.ts index 18ba883..3815af9 100644 --- a/src/lib/server/api/index.ts +++ b/src/lib/server/api/index.ts @@ -45,7 +45,7 @@ const routes = app .route('/user', container.resolve(UserController).routes()) .route('/login', container.resolve(LoginController).routes()) .route('/signup', container.resolve(SignupController).routes()) - .route('/wishlists', container.resolve(WishlistController).routes()) + .route('/wishlistsTable', container.resolve(WishlistController).routes()) .route('/collections', container.resolve(CollectionController).routes()) .route('/mfa', container.resolve(MfaController).routes()) .get('/', (c) => c.json({ message: 'Server is healthy' })) diff --git a/src/lib/server/api/middleware/auth.middleware.ts b/src/lib/server/api/middleware/auth.middleware.ts index 5d2eab7..3cc3766 100644 --- a/src/lib/server/api/middleware/auth.middleware.ts +++ b/src/lib/server/api/middleware/auth.middleware.ts @@ -1,10 +1,14 @@ +import { LuciaService } from '$lib/server/api/services/lucia.service' import type { MiddlewareHandler } from 'hono' import { createMiddleware } from 'hono/factory' import type { Session, User } from 'lucia' import { verifyRequestOrigin } from 'oslo/request' +import { container } from 'tsyringe' import { Unauthorized } from '../common/exceptions' -import { lucia } from '../packages/lucia' -import type { HonoTypes } from '../types' +import type { HonoTypes } from '../common/types/hono' + +// resolve dependencies from the container +const { lucia } = container.resolve(LuciaService) export const verifyOrigin: MiddlewareHandler = createMiddleware(async (c, next) => { if (c.req.method === 'GET') { @@ -27,7 +31,7 @@ export const validateAuthSession: MiddlewareHandler = createMiddlewar } const { session, user } = await lucia.validateSession(sessionId) - if (session && session.fresh) { + if (session?.fresh) { c.header('Set-Cookie', lucia.createSessionCookie(session.id).serialize(), { append: true }) } if (!session) { diff --git a/src/lib/server/api/middleware/rate-limiter.middleware.ts b/src/lib/server/api/middleware/rate-limiter.middleware.ts index 9b49d10..97f0919 100644 --- a/src/lib/server/api/middleware/rate-limiter.middleware.ts +++ b/src/lib/server/api/middleware/rate-limiter.middleware.ts @@ -1,10 +1,11 @@ import { rateLimiter } from 'hono-rate-limiter' -import RedisClient from 'ioredis' import { RedisStore } from 'rate-limit-redis' -import { config } from '../configs/config' -import type { HonoTypes } from '../types' +import { container } from 'tsyringe' +import type { HonoTypes } from '../common/types/hono' +import { RedisService } from '../services/redis.service' -const client = new RedisClient(config.REDIS_URL) +// resolve dependencies from the container +const { client } = container.resolve(RedisService) export function limiter({ limit, diff --git a/src/lib/server/api/middleware/require-auth.middleware.ts b/src/lib/server/api/middleware/require-auth.middleware.ts new file mode 100644 index 0000000..5ca6e09 --- /dev/null +++ b/src/lib/server/api/middleware/require-auth.middleware.ts @@ -0,0 +1,15 @@ +import { Unauthorized } from '$lib/server/api/common/exceptions' +import type { MiddlewareHandler } from 'hono' +import { createMiddleware } from 'hono/factory' +import type { Session, User } from 'lucia' + +export const requireAuth: MiddlewareHandler<{ + Variables: { + session: Session + user: User + } +}> = createMiddleware(async (c, next) => { + const user = c.var.user + if (!user) throw Unauthorized('You must be logged in to access this resource') + return next() +}) diff --git a/src/lib/server/api/packages/lucia.ts b/src/lib/server/api/packages/lucia.ts deleted file mode 100644 index 825e478..0000000 --- a/src/lib/server/api/packages/lucia.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { DrizzlePostgreSQLAdapter } from '@lucia-auth/adapter-drizzle' -// lib/server/lucia.ts -import { Lucia, TimeSpan } from 'lucia' -import { config } from '../configs/config' -import { sessionsTable, usersTable } from '../databases/tables' -import { db } from './drizzle' - -const adapter = new DrizzlePostgreSQLAdapter(db, sessionsTable, usersTable) - -export const lucia = new Lucia(adapter, { - getSessionAttributes: (attributes) => { - return { - ipCountry: attributes.ip_country, - ipAddress: attributes.ip_address, - isTwoFactorAuthEnabled: attributes.twoFactorAuthEnabled, - isTwoFactorAuthenticated: attributes.isTwoFactorAuthenticated, - } - }, - getUserAttributes: (attributes) => { - return { - // ...attributes, - username: attributes.username, - email: attributes.email, - firstName: attributes.first_name, - lastName: attributes.last_name, - mfa_enabled: attributes.mfa_enabled, - theme: attributes.theme, - } - }, - sessionExpiresIn: new TimeSpan(2, 'w'), // 2 weeks - sessionCookie: { - name: 'session', - expires: false, // session cookies have very long lifespan (2 years) - attributes: { - // set to `true` when using HTTPS - secure: config.isProduction, - sameSite: 'strict', - domain: config.domain, - }, - }, -}) - -declare module 'lucia' { - interface Register { - Lucia: typeof lucia - DatabaseUserAttributes: DatabaseUserAttributes - DatabaseSessionAttributes: DatabaseSessionAttributes - } - interface DatabaseSessionAttributes { - ip_country: string - ip_address: string - twoFactorAuthEnabled: boolean - isTwoFactorAuthenticated: boolean - } - interface DatabaseUserAttributes { - username: string - email: string - first_name: string - last_name: string - mfa_enabled: boolean - theme: string - } -} diff --git a/src/lib/server/api/repositories/collections.repository.ts b/src/lib/server/api/repositories/collections.repository.ts index fa5669d..c6f097b 100644 --- a/src/lib/server/api/repositories/collections.repository.ts +++ b/src/lib/server/api/repositories/collections.repository.ts @@ -1,6 +1,5 @@ -import type { Repository } from '$lib/server/api/common/interfaces/repository.interface' -import { takeFirstOrThrow } from '$lib/server/api/common/utils/repository.utils' -import { DatabaseProvider } from '$lib/server/api/providers/database.provider' +import { takeFirstOrThrow } from '$lib/server/api/common/utils/repository' +import { DrizzleService } from '$lib/server/api/services/drizzle.service' import { type InferInsertModel, eq } from 'drizzle-orm' import { inject, injectable } from 'tsyringe' import { collections } from '../databases/tables' @@ -9,15 +8,15 @@ export type CreateCollection = InferInsertModel export type UpdateCollection = Partial @injectable() -export class CollectionsRepository implements Repository { - constructor(@inject(DatabaseProvider) private readonly db: DatabaseProvider) {} +export class CollectionsRepository { + constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} - async findAll() { - return this.db.query.collections.findMany() + async findAll(db = this.drizzle.db) { + return db.query.collections.findMany() } - async findOneById(id: string) { - return this.db.query.collections.findFirst({ + async findOneById(id: string, db = this.drizzle.db) { + return db.query.collections.findFirst({ where: eq(collections.id, id), columns: { cuid: true, @@ -26,8 +25,8 @@ export class CollectionsRepository implements Repository { }) } - async findOneByCuid(cuid: string) { - return this.db.query.collections.findFirst({ + async findOneByCuid(cuid: string, db = this.drizzle.db) { + return db.query.collections.findFirst({ where: eq(collections.cuid, cuid), columns: { cuid: true, @@ -36,8 +35,8 @@ export class CollectionsRepository implements Repository { }) } - async findOneByUserId(userId: string) { - return this.db.query.collections.findFirst({ + async findOneByUserId(userId: string, db = this.drizzle.db) { + return db.query.collections.findFirst({ where: eq(collections.user_id, userId), columns: { cuid: true, @@ -46,21 +45,17 @@ export class CollectionsRepository implements Repository { }) } - async findAllByUserId(userId: string) { - return this.db.query.collections.findMany({ + async findAllByUserId(userId: string, db = this.drizzle.db) { + return db.query.collections.findMany({ where: eq(collections.user_id, userId), }) } - async create(data: CreateCollection) { - return this.db.insert(collections).values(data).returning().then(takeFirstOrThrow) + async create(data: CreateCollection, db = this.drizzle.db) { + return db.insert(collections).values(data).returning().then(takeFirstOrThrow) } - async update(id: string, data: UpdateCollection) { - return this.db.update(collections).set(data).where(eq(collections.id, id)).returning().then(takeFirstOrThrow) - } - - trxHost(trx: DatabaseProvider) { - return new CollectionsRepository(trx) + async update(id: string, data: UpdateCollection, db = this.drizzle.db) { + return db.update(collections).set(data).where(eq(collections.id, id)).returning().then(takeFirstOrThrow) } } diff --git a/src/lib/server/api/repositories/credentials.repository.ts b/src/lib/server/api/repositories/credentials.repository.ts index 1ff99e9..11f56c5 100644 --- a/src/lib/server/api/repositories/credentials.repository.ts +++ b/src/lib/server/api/repositories/credentials.repository.ts @@ -1,75 +1,70 @@ import 'reflect-metadata' -import type { Repository } from '$lib/server/api/common/interfaces/repository.interface' import { CredentialsType, credentialsTable } from '$lib/server/api/databases/tables/credentials.table' -import { DatabaseProvider } from '$lib/server/api/providers/database.provider' +import { DrizzleService } from '$lib/server/api/services/drizzle.service' import { type InferInsertModel, and, eq } from 'drizzle-orm' import { inject, injectable } from 'tsyringe' -import { takeFirstOrThrow } from '../common/utils/repository.utils' +import { takeFirstOrThrow } from '../common/utils/repository' export type CreateCredentials = InferInsertModel export type UpdateCredentials = Partial @injectable() -export class CredentialsRepository implements Repository { - constructor(@inject(DatabaseProvider) private readonly db: DatabaseProvider) {} +export class CredentialsRepository { + constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} - async findOneByUserId(userId: string) { - return this.db.query.credentialsTable.findFirst({ + async findOneByUserId(userId: string, db = this.drizzle.db) { + return db.query.credentialsTable.findFirst({ where: eq(credentialsTable.user_id, userId), }) } - async findOneByUserIdAndType(userId: string, type: CredentialsType) { - return this.db.query.credentialsTable.findFirst({ + async findOneByUserIdAndType(userId: string, type: CredentialsType, db = this.drizzle.db) { + return db.query.credentialsTable.findFirst({ where: and(eq(credentialsTable.user_id, userId), eq(credentialsTable.type, type)), }) } - async findPasswordCredentialsByUserId(userId: string) { - return this.db.query.credentialsTable.findFirst({ + async findPasswordCredentialsByUserId(userId: string, db = this.drizzle.db) { + return db.query.credentialsTable.findFirst({ where: and(eq(credentialsTable.user_id, userId), eq(credentialsTable.type, CredentialsType.PASSWORD)), }) } - async findTOTPCredentialsByUserId(userId: string) { - return this.db.query.credentialsTable.findFirst({ + async findTOTPCredentialsByUserId(userId: string, db = this.drizzle.db) { + return db.query.credentialsTable.findFirst({ where: and(eq(credentialsTable.user_id, userId), eq(credentialsTable.type, CredentialsType.TOTP)), }) } - async findOneById(id: string) { - return this.db.query.credentialsTable.findFirst({ + async findOneById(id: string, db = this.drizzle.db) { + return db.query.credentialsTable.findFirst({ where: eq(credentialsTable.id, id), }) } - async findOneByIdOrThrow(id: string) { + async findOneByIdOrThrow(id: string, db = this.drizzle.db) { const credentials = await this.findOneById(id) if (!credentials) throw Error('Credentials not found') return credentials } - async create(data: CreateCredentials) { - return this.db.insert(credentialsTable).values(data).returning().then(takeFirstOrThrow) + async create(data: CreateCredentials, db = this.drizzle.db) { + return db.insert(credentialsTable).values(data).returning().then(takeFirstOrThrow) } - async update(id: string, data: UpdateCredentials) { - return this.db.update(credentialsTable).set(data).where(eq(credentialsTable.id, id)).returning().then(takeFirstOrThrow) + async update(id: string, data: UpdateCredentials, db = this.drizzle.db) { + return db.update(credentialsTable).set(data).where(eq(credentialsTable.id, id)).returning().then(takeFirstOrThrow) } - async delete(id: string) { - return this.db.delete(credentialsTable).where(eq(credentialsTable.id, id)) + async delete(id: string, db = this.drizzle.db) { + return db.delete(credentialsTable).where(eq(credentialsTable.id, id)) } - async deleteByUserId(userId: string) { - return this.db.delete(credentialsTable).where(eq(credentialsTable.user_id, userId)) + async deleteByUserId(userId: string, db = this.drizzle.db) { + return db.delete(credentialsTable).where(eq(credentialsTable.user_id, userId)) } - async deleteByUserIdAndType(userId: string, type: CredentialsType) { - return this.db.delete(credentialsTable).where(and(eq(credentialsTable.user_id, userId), eq(credentialsTable.type, type))) - } - - trxHost(trx: DatabaseProvider) { - return new CredentialsRepository(trx) + async deleteByUserIdAndType(userId: string, type: CredentialsType, db = this.drizzle.db) { + return db.delete(credentialsTable).where(and(eq(credentialsTable.user_id, userId), eq(credentialsTable.type, type))) } } diff --git a/src/lib/server/api/repositories/recovery-codes.repository.ts b/src/lib/server/api/repositories/recovery-codes.repository.ts index 6fdc7f0..996195e 100644 --- a/src/lib/server/api/repositories/recovery-codes.repository.ts +++ b/src/lib/server/api/repositories/recovery-codes.repository.ts @@ -1,6 +1,5 @@ import 'reflect-metadata' -import type { Repository } from '$lib/server/api/common/interfaces/repository.interface' -import { DatabaseProvider } from '$lib/server/api/providers/database.provider' +import { DrizzleService } from '$lib/server/api/services/drizzle.service' import { type InferInsertModel, eq } from 'drizzle-orm' import { inject, injectable } from 'tsyringe' import { recoveryCodesTable } from '../databases/tables' @@ -8,20 +7,16 @@ import { recoveryCodesTable } from '../databases/tables' export type CreateRecoveryCodes = InferInsertModel @injectable() -export class RecoveryCodesRepository implements Repository { - constructor(@inject(DatabaseProvider) private readonly db: DatabaseProvider) {} +export class RecoveryCodesRepository { + constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} - async findAllByUserId(userId: string) { - return this.db.query.recoveryCodesTable.findFirst({ + async findAllByUserId(userId: string, db = this.drizzle.db) { + return db.query.recoveryCodesTable.findFirst({ where: eq(recoveryCodesTable.userId, userId), }) } - async deleteAllByUserId(userId: string) { - return this.db.delete(recoveryCodesTable).where(eq(recoveryCodesTable.userId, userId)) - } - - trxHost(trx: DatabaseProvider) { - return new RecoveryCodesRepository(trx) + async deleteAllByUserId(userId: string, db = this.drizzle.db) { + return db.delete(recoveryCodesTable).where(eq(recoveryCodesTable.userId, userId)) } } diff --git a/src/lib/server/api/repositories/roles.repository.ts b/src/lib/server/api/repositories/roles.repository.ts index e940f4b..2750d5c 100644 --- a/src/lib/server/api/repositories/roles.repository.ts +++ b/src/lib/server/api/repositories/roles.repository.ts @@ -1,9 +1,8 @@ -import type { Repository } from '$lib/server/api/common/interfaces/repository.interface' -import { DatabaseProvider } from '$lib/server/api/providers/database.provider' +import { DrizzleService } from '$lib/server/api/services/drizzle.service' import { type InferInsertModel, eq } from 'drizzle-orm' import { inject, injectable } from 'tsyringe' -import { takeFirstOrThrow } from '../common/utils/repository.utils' -import { roles } from '../databases/tables' +import { takeFirstOrThrow } from '../common/utils/repository' +import { rolesTable } from '../databases/tables' /* -------------------------------------------------------------------------- */ /* Repository */ @@ -21,54 +20,50 @@ storing data. They should not contain any business logic, only database queries. In our case the method 'trxHost' is used to set the transaction context. */ -export type CreateRole = InferInsertModel +export type CreateRole = InferInsertModel export type UpdateRole = Partial @injectable() -export class RolesRepository implements Repository { - constructor(@inject(DatabaseProvider) private readonly db: DatabaseProvider) {} +export class RolesRepository { + constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} - async findOneById(id: string) { - return this.db.query.roles.findFirst({ - where: eq(roles.id, id), + async findOneById(id: string, db = this.drizzle.db) { + return db.query.roles.findFirst({ + where: eq(rolesTable.id, id), }) } - async findOneByIdOrThrow(id: string) { + async findOneByIdOrThrow(id: string, db = this.drizzle.db) { const role = await this.findOneById(id) if (!role) throw Error('Role not found') return role } - async findAll() { - return this.db.query.roles.findMany() + async findAll(db = this.drizzle.db) { + return db.query.roles.findMany() } - async findOneByName(name: string) { - return this.db.query.roles.findFirst({ - where: eq(roles.name, name), + async findOneByName(name: string, db = this.drizzle.db) { + return db.query.roles.findFirst({ + where: eq(rolesTable.name, name), }) } - async findOneByNameOrThrow(name: string) { + async findOneByNameOrThrow(name: string, db = this.drizzle.db) { const role = await this.findOneByName(name) if (!role) throw Error('Role not found') return role } - async create(data: CreateRole) { - return this.db.insert(roles).values(data).returning().then(takeFirstOrThrow) + async create(data: CreateRole, db = this.drizzle.db) { + return db.insert(rolesTable).values(data).returning().then(takeFirstOrThrow) } - async update(id: string, data: UpdateRole) { - return this.db.update(roles).set(data).where(eq(roles.id, id)).returning().then(takeFirstOrThrow) + async update(id: string, data: UpdateRole, db = this.drizzle.db) { + return db.update(rolesTable).set(data).where(eq(rolesTable.id, id)).returning().then(takeFirstOrThrow) } - async delete(id: string) { - return this.db.delete(roles).where(eq(roles.id, id)).returning().then(takeFirstOrThrow) - } - - trxHost(trx: DatabaseProvider) { - return new RolesRepository(trx) + async delete(id: string, db = this.drizzle.db) { + return db.delete(rolesTable).where(eq(rolesTable.id, id)).returning().then(takeFirstOrThrow) } } diff --git a/src/lib/server/api/repositories/user_roles.repository.ts b/src/lib/server/api/repositories/user_roles.repository.ts index 90e2823..737bc0c 100644 --- a/src/lib/server/api/repositories/user_roles.repository.ts +++ b/src/lib/server/api/repositories/user_roles.repository.ts @@ -1,8 +1,7 @@ -import type { Repository } from '$lib/server/api/common/interfaces/repository.interface' -import { DatabaseProvider } from '$lib/server/api/providers/database.provider' +import { DrizzleService } from '$lib/server/api/services/drizzle.service' import { type InferInsertModel, eq } from 'drizzle-orm' import { inject, injectable } from 'tsyringe' -import { takeFirstOrThrow } from '../common/utils/repository.utils' +import { takeFirstOrThrow } from '../common/utils/repository' import { user_roles } from '../databases/tables' /* -------------------------------------------------------------------------- */ @@ -25,11 +24,11 @@ export type CreateUserRole = InferInsertModel export type UpdateUserRole = Partial @injectable() -export class UserRolesRepository implements Repository { - constructor(@inject(DatabaseProvider) private readonly db: DatabaseProvider) {} +export class UserRolesRepository { + constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} - async findOneById(id: string) { - return this.db.query.user_roles.findFirst({ + async findOneById(id: string, db = this.drizzle.db) { + return db.query.user_roles.findFirst({ where: eq(user_roles.id, id), }) } @@ -40,21 +39,17 @@ export class UserRolesRepository implements Repository { return userRole } - async findAllByUserId(userId: string) { - return this.db.query.user_roles.findMany({ + async findAllByUserId(userId: string, db = this.drizzle.db) { + return db.query.user_roles.findMany({ where: eq(user_roles.user_id, userId), }) } - async create(data: CreateUserRole) { - return this.db.insert(user_roles).values(data).returning().then(takeFirstOrThrow) + async create(data: CreateUserRole, db = this.drizzle.db) { + return db.insert(user_roles).values(data).returning().then(takeFirstOrThrow) } - async delete(id: string) { - return this.db.delete(user_roles).where(eq(user_roles.id, id)).returning().then(takeFirstOrThrow) - } - - trxHost(trx: DatabaseProvider) { - return new UserRolesRepository(trx) + async delete(id: string, db = this.drizzle.db) { + return db.delete(user_roles).where(eq(user_roles.id, id)).returning().then(takeFirstOrThrow) } } diff --git a/src/lib/server/api/repositories/users.repository.ts b/src/lib/server/api/repositories/users.repository.ts index b44b1da..240c66c 100644 --- a/src/lib/server/api/repositories/users.repository.ts +++ b/src/lib/server/api/repositories/users.repository.ts @@ -1,9 +1,8 @@ -import type { Repository } from '$lib/server/api/common/interfaces/repository.interface' import { usersTable } from '$lib/server/api/databases/tables/users.table' -import { DatabaseProvider } from '$lib/server/api/providers/database.provider' +import { DrizzleService } from '$lib/server/api/services/drizzle.service' import { type InferInsertModel, eq } from 'drizzle-orm' import { inject, injectable } from 'tsyringe' -import { takeFirstOrThrow } from '../common/utils/repository.utils' +import { takeFirstOrThrow } from '../common/utils/repository' /* -------------------------------------------------------------------------- */ /* Repository */ @@ -25,46 +24,42 @@ export type CreateUser = InferInsertModel export type UpdateUser = Partial @injectable() -export class UsersRepository implements Repository { - constructor(@inject(DatabaseProvider) private readonly db: DatabaseProvider) {} +export class UsersRepository { + constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} - async findOneById(id: string) { - return this.db.query.usersTable.findFirst({ + async findOneById(id: string, db = this.drizzle.db) { + return db.query.usersTable.findFirst({ where: eq(usersTable.id, id), }) } - async findOneByIdOrThrow(id: string) { + async findOneByIdOrThrow(id: string, db = this.drizzle.db) { const user = await this.findOneById(id) if (!user) throw Error('User not found') return user } - async findOneByUsername(username: string) { - return this.db.query.usersTable.findFirst({ + async findOneByUsername(username: string, db = this.drizzle.db) { + return db.query.usersTable.findFirst({ where: eq(usersTable.username, username), }) } - async findOneByEmail(email: string) { - return this.db.query.usersTable.findFirst({ + async findOneByEmail(email: string, db = this.drizzle.db) { + return db.query.usersTable.findFirst({ where: eq(usersTable.email, email), }) } - async create(data: CreateUser) { - return this.db.insert(usersTable).values(data).returning().then(takeFirstOrThrow) + async create(data: CreateUser, db = this.drizzle.db) { + return db.insert(usersTable).values(data).returning().then(takeFirstOrThrow) } - async update(id: string, data: UpdateUser) { - return this.db.update(usersTable).set(data).where(eq(usersTable.id, id)).returning().then(takeFirstOrThrow) + async update(id: string, data: UpdateUser, db = this.drizzle.db) { + return db.update(usersTable).set(data).where(eq(usersTable.id, id)).returning().then(takeFirstOrThrow) } - async delete(id: string) { - return this.db.delete(usersTable).where(eq(usersTable.id, id)).returning().then(takeFirstOrThrow) - } - - trxHost(trx: DatabaseProvider) { - return new UsersRepository(trx) + async delete(id: string, db = this.drizzle.db) { + return db.delete(usersTable).where(eq(usersTable.id, id)).returning().then(takeFirstOrThrow) } } diff --git a/src/lib/server/api/repositories/wishlists.repository.ts b/src/lib/server/api/repositories/wishlists.repository.ts index 00c074b..3e84863 100644 --- a/src/lib/server/api/repositories/wishlists.repository.ts +++ b/src/lib/server/api/repositories/wishlists.repository.ts @@ -1,24 +1,23 @@ -import type { Repository } from '$lib/server/api/common/interfaces/repository.interface' -import { DatabaseProvider } from '$lib/server/api/providers/database.provider' +import { DrizzleService } from '$lib/server/api/services/drizzle.service' import { type InferInsertModel, eq } from 'drizzle-orm' import { inject, injectable } from 'tsyringe' -import { takeFirstOrThrow } from '../common/utils/repository.utils' -import { wishlists } from '../databases/tables' +import { takeFirstOrThrow } from '../common/utils/repository' +import { wishlistsTable } from '../databases/tables' -export type CreateWishlist = InferInsertModel +export type CreateWishlist = InferInsertModel export type UpdateWishlist = Partial @injectable() -export class WishlistsRepository implements Repository { - constructor(@inject(DatabaseProvider) private readonly db: DatabaseProvider) {} +export class WishlistsRepository { + constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} - async findAll() { - return this.db.query.wishlists.findMany() + async findAll(db = this.drizzle.db) { + return db.query.wishlists.findMany() } - async findOneById(id: string) { - return this.db.query.wishlists.findFirst({ - where: eq(wishlists.id, id), + async findOneById(id: string, db = this.drizzle.db) { + return db.query.wishlists.findFirst({ + where: eq(wishlistsTable.id, id), columns: { cuid: true, name: true, @@ -26,9 +25,9 @@ export class WishlistsRepository implements Repository { }) } - async findOneByCuid(cuid: string) { - return this.db.query.wishlists.findFirst({ - where: eq(wishlists.cuid, cuid), + async findOneByCuid(cuid: string, db = this.drizzle.db) { + return db.query.wishlists.findFirst({ + where: eq(wishlistsTable.cuid, cuid), columns: { cuid: true, name: true, @@ -36,9 +35,9 @@ export class WishlistsRepository implements Repository { }) } - async findOneByUserId(userId: string) { - return this.db.query.wishlists.findFirst({ - where: eq(wishlists.user_id, userId), + async findOneByUserId(userId: string, db = this.drizzle.db) { + return db.query.wishlists.findFirst({ + where: eq(wishlistsTable.user_id, userId), columns: { cuid: true, name: true, @@ -46,9 +45,9 @@ export class WishlistsRepository implements Repository { }) } - async findAllByUserId(userId: string) { - return this.db.query.wishlists.findMany({ - where: eq(wishlists.user_id, userId), + async findAllByUserId(userId: string, db = this.drizzle.db) { + return db.query.wishlists.findMany({ + where: eq(wishlistsTable.user_id, userId), columns: { cuid: true, name: true, @@ -56,15 +55,11 @@ export class WishlistsRepository implements Repository { }) } - async create(data: CreateWishlist) { - return this.db.insert(wishlists).values(data).returning().then(takeFirstOrThrow) + async create(data: CreateWishlist, db = this.drizzle.db) { + return db.insert(wishlistsTable).values(data).returning().then(takeFirstOrThrow) } - async update(id: string, data: UpdateWishlist) { - return this.db.update(wishlists).set(data).where(eq(wishlists.id, id)).returning().then(takeFirstOrThrow) - } - - trxHost(trx: DatabaseProvider) { - return new WishlistsRepository(trx) + async update(id: string, data: UpdateWishlist, db = this.drizzle.db) { + return db.update(wishlistsTable).set(data).where(eq(wishlistsTable.id, id)).returning().then(takeFirstOrThrow) } } diff --git a/src/lib/server/api/services/drizzle.service.ts b/src/lib/server/api/services/drizzle.service.ts new file mode 100644 index 0000000..03057d4 --- /dev/null +++ b/src/lib/server/api/services/drizzle.service.ts @@ -0,0 +1,33 @@ +import { config } from '$lib/server/api/configs/config' +import * as schema from '$lib/server/api/databases/tables' +import { type NodePgDatabase, drizzle } from 'drizzle-orm/node-postgres' +import pg from 'pg' +import { type Disposable, injectable } from 'tsyringe' + +@injectable() +export class DrizzleService implements Disposable { + protected readonly pool: pg.Pool + readonly db: NodePgDatabase + readonly schema: typeof schema = schema + + constructor() { + const pool = new pg.Pool({ + user: config.DATABASE_USER, + password: config.DATABASE_PASSWORD, + host: config.DATABASE_HOST, + port: Number(config.DATABASE_PORT).valueOf(), + database: config.DATABASE_DB, + ssl: config.DATABASE_HOST !== 'localhost', + max: config.DB_MIGRATING || config.DB_SEEDING ? 1 : undefined, + }) + this.pool = pool + this.db = drizzle(pool, { + schema, + logger: config.NODE_ENV === 'development', + }) + } + + dispose(): Promise | void { + this.pool.end() + } +} diff --git a/src/lib/server/api/services/iam.service.ts b/src/lib/server/api/services/iam.service.ts index f7b3599..0c3bc6e 100644 --- a/src/lib/server/api/services/iam.service.ts +++ b/src/lib/server/api/services/iam.service.ts @@ -1,7 +1,7 @@ import type { UpdateEmailDto } from '$lib/server/api/dtos/update-email.dto' import type { UpdateProfileDto } from '$lib/server/api/dtos/update-profile.dto' import type { VerifyPasswordDto } from '$lib/server/api/dtos/verify-password.dto' -import { LuciaProvider } from '$lib/server/api/providers/lucia.provider' +import { LuciaService } from '$lib/server/api/services/lucia.service' import { UsersService } from '$lib/server/api/services/users.service' import { inject, injectable } from 'tsyringe' @@ -25,12 +25,12 @@ simple as possible. This makes the service easier to read, test and understand. @injectable() export class IamService { constructor( - @inject(LuciaProvider) private readonly lucia: LuciaProvider, + @inject(LuciaService) private luciaService: LuciaService, @inject(UsersService) private readonly usersService: UsersService, ) {} async logout(sessionId: string) { - return this.lucia.invalidateSession(sessionId) + return this.luciaService.lucia.invalidateSession(sessionId) } async updateProfile(userId: string, data: UpdateProfileDto) { diff --git a/src/lib/server/api/services/loginrequest.service.ts b/src/lib/server/api/services/loginrequest.service.ts index 6748eb8..4f93c9c 100644 --- a/src/lib/server/api/services/loginrequest.service.ts +++ b/src/lib/server/api/services/loginrequest.service.ts @@ -1,10 +1,10 @@ import type { SigninUsernameDto } from '$lib/server/api/dtos/signin-username.dto' +import { LuciaService } from '$lib/server/api/services/lucia.service' import type { HonoRequest } from 'hono' import { inject, injectable } from 'tsyringe' import { BadRequest } from '../common/exceptions' import type { Credentials } from '../databases/tables' import { DatabaseProvider } from '../providers/database.provider' -import { LuciaProvider } from '../providers/lucia.provider' import { CredentialsRepository } from '../repositories/credentials.repository' import { UsersRepository } from '../repositories/users.repository' import { MailerService } from './mailer.service' @@ -13,7 +13,7 @@ import { TokensService } from './tokens.service' @injectable() export class LoginRequestsService { constructor( - @inject(LuciaProvider) private readonly lucia: LuciaProvider, + @inject(LuciaService) private luciaService: LuciaService, @inject(DatabaseProvider) private readonly db: DatabaseProvider, @inject(TokensService) private readonly tokensService: TokensService, @inject(MailerService) private readonly mailerService: MailerService, @@ -60,7 +60,7 @@ export class LoginRequestsService { async createUserSession(existingUserId: string, req: HonoRequest, totpCredentials: Credentials | undefined) { const requestIpAddress = req.header('x-real-ip') const requestIpCountry = req.header('x-vercel-ip-country') - return this.lucia.createSession(existingUserId, { + return this.luciaService.lucia.createSession(existingUserId, { ip_country: requestIpCountry || 'unknown', ip_address: requestIpAddress || 'unknown', twoFactorAuthEnabled: !!totpCredentials && totpCredentials?.secret_data !== null && totpCredentials?.secret_data !== '', diff --git a/src/lib/server/api/services/lucia.service.ts b/src/lib/server/api/services/lucia.service.ts new file mode 100644 index 0000000..63df397 --- /dev/null +++ b/src/lib/server/api/services/lucia.service.ts @@ -0,0 +1,45 @@ +import { config } from '$lib/server/api/configs/config' +import { DrizzleService } from '$lib/server/api/services/drizzle.service' +import { DrizzlePostgreSQLAdapter } from '@lucia-auth/adapter-drizzle' +import { Lucia, TimeSpan } from 'lucia' +import { inject, injectable } from 'tsyringe' + +@injectable() +export class LuciaService { + readonly lucia: Lucia + constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) { + const adapter = new DrizzlePostgreSQLAdapter(this.drizzle.db, this.drizzle.schema.sessionsTable, this.drizzle.schema.usersTable) + this.lucia = new Lucia(adapter, { + sessionExpiresIn: new TimeSpan(2, 'w'), // 2 weeks + sessionCookie: { + name: 'session', + expires: false, // session cookies have very long lifespan (2 years) + attributes: { + // set to `true` when using HTTPS + secure: config.isProduction, + sameSite: 'strict', + domain: config.domain, + }, + }, + getSessionAttributes: (attributes) => { + return { + ipCountry: attributes.ip_country, + ipAddress: attributes.ip_address, + isTwoFactorAuthEnabled: attributes.twoFactorAuthEnabled, + isTwoFactorAuthenticated: attributes.isTwoFactorAuthenticated, + } + }, + getUserAttributes: (attributes) => { + return { + // ...attributes, + username: attributes.username, + email: attributes.email, + firstName: attributes.first_name, + lastName: attributes.last_name, + mfa_enabled: attributes.mfa_enabled, + theme: attributes.theme, + } + }, + }) + } +} diff --git a/src/lib/server/api/services/redis.service.ts b/src/lib/server/api/services/redis.service.ts new file mode 100644 index 0000000..d451bce --- /dev/null +++ b/src/lib/server/api/services/redis.service.ts @@ -0,0 +1,18 @@ +import { config } from '$lib/server/api/configs/config' +import { Redis } from 'ioredis' +import { type Disposable, injectable } from 'tsyringe' + +@injectable() +export class RedisService implements Disposable { + readonly client: Redis + + constructor() { + this.client = new Redis(config.REDIS_URL, { + maxRetriesPerRequest: null, + }) + } + + async dispose(): Promise { + this.client.disconnect() + } +} diff --git a/src/lib/utils/db/categoryUtils.ts b/src/lib/utils/db/categoryUtils.ts index 780685d..392d267 100644 --- a/src/lib/utils/db/categoryUtils.ts +++ b/src/lib/utils/db/categoryUtils.ts @@ -1,5 +1,5 @@ import { PUBLIC_SITE_URL } from '$env/static/public' -import { type Categories, type Mechanics, categoriesTable, categoriesToExternalIdsTable, externalIds } from '$lib/server/api/databases/tables' +import { type Categories, type Mechanics, categoriesTable, categoriesToExternalIdsTable, externalIdsTable } from '$lib/server/api/databases/tables' import { db } from '$lib/server/api/packages/drizzle' import { error } from '@sveltejs/kit' import { eq } from 'drizzle-orm' @@ -12,7 +12,7 @@ export async function createCategory(locals: App.Locals, category: Categories, e try { const dbExternalId = await db.query.externalIds.findFirst({ - where: eq(externalIds.externalId, externalId), + where: eq(externalIdsTable.externalId, externalId), }) if (dbExternalId) { @@ -48,12 +48,12 @@ export async function createCategory(locals: App.Locals, category: Categories, e }) .returning() const dbExternalIds = await transaction - .insert(externalIds) + .insert(externalIdsTable) .values({ externalId, type: 'category', }) - .returning({ id: externalIds.id }) + .returning({ id: externalIdsTable.id }) await transaction.insert(categoriesToExternalIdsTable).values({ categoryId: dbCategory[0].id, externalId: dbExternalIds[0].id, diff --git a/src/lib/utils/db/expansionUtils.ts b/src/lib/utils/db/expansionUtils.ts index d6ff8db..07bea23 100644 --- a/src/lib/utils/db/expansionUtils.ts +++ b/src/lib/utils/db/expansionUtils.ts @@ -1,5 +1,5 @@ import { PUBLIC_SITE_URL } from '$env/static/public' -import { type Expansions, expansions } from '$lib/server/api/databases/tables' +import { type Expansions, expansionsTable } from '$lib/server/api/databases/tables' import { db } from '$lib/server/api/packages/drizzle' import { error } from '@sveltejs/kit' import { and, eq } from 'drizzle-orm' @@ -11,7 +11,7 @@ export async function createExpansion(locals: App.Locals, expansion: Expansions) try { const foundExpansion = await db.query.expansions.findFirst({ - where: and(eq(expansions.base_game_id, expansion.base_game_id), eq(expansions.game_id, expansion.game_id)), + where: and(eq(expansionsTable.base_game_id, expansion.base_game_id), eq(expansionsTable.game_id, expansion.game_id)), columns: { id: true, game_id: true, @@ -32,7 +32,7 @@ export async function createExpansion(locals: App.Locals, expansion: Expansions) console.log('Creating expansion', JSON.stringify(expansion, null, 2)) const dbExpansion = await db - .insert(expansions) + .insert(expansionsTable) .values({ base_game_id: expansion.base_game_id, game_id: expansion.game_id, @@ -146,7 +146,7 @@ export async function createExpansion(locals: App.Locals, expansion: Expansions) // id: gameId // }, // data: { -// expansions: { +// expansionsTable: { // connect: { // id: expansion.id // } @@ -160,7 +160,7 @@ export async function createExpansion(locals: App.Locals, expansion: Expansions) // id: baseGameId // }, // data: { -// expansions: { +// expansionsTable: { // connect: { // id: expansion.id // } diff --git a/src/lib/utils/db/gameUtils.ts b/src/lib/utils/db/gameUtils.ts index b8a375b..50e79dc 100644 --- a/src/lib/utils/db/gameUtils.ts +++ b/src/lib/utils/db/gameUtils.ts @@ -1,5 +1,5 @@ import { PUBLIC_SITE_URL } from '$env/static/public' -import { type Games, externalIds, games, gamesToExternalIds } from '$lib/server/api/databases/tables' +import { type Games, externalIdsTable, gamesTable, gamesToExternalIdsTable } from '$lib/server/api/databases/tables' import { db } from '$lib/server/api/packages/drizzle' import { error } from '@sveltejs/kit' import { eq } from 'drizzle-orm' @@ -12,11 +12,11 @@ export async function getGame(locals: App.Locals, id: string) { try { return await db.query.games.findFirst({ - where: eq(games.id, id), + where: eq(gamesTable.id, id), }) } catch (e) { console.error(e) - return new Response('Could not get games', { + return new Response('Could not get gamesTable', { status: 500, }) } @@ -29,18 +29,18 @@ export async function createGame(locals: App.Locals, game: Games, externalId: st try { const dbExternalId = await db.query.externalIds.findFirst({ - where: eq(externalIds.externalId, externalId), + where: eq(externalIdsTable.externalId, externalId), }) if (dbExternalId) { const foundGame = await db .select({ - id: games.id, - name: games.name, - slug: games.slug, + id: gamesTable.id, + name: gamesTable.name, + slug: gamesTable.slug, }) - .from(games) - .leftJoin(gamesToExternalIds, eq(gamesToExternalIds.externalId, externalId)) + .from(gamesTable) + .leftJoin(gamesToExternalIdsTable, eq(gamesToExternalIdsTable.externalId, externalId)) console.log('Game already exists', foundGame) if (foundGame.length > 0) { console.log('Game name', foundGame[0].name) @@ -58,7 +58,7 @@ export async function createGame(locals: App.Locals, game: Games, externalId: st console.log('Creating game', JSON.stringify(game, null, 2)) await db.transaction(async (transaction) => { dbGames = await transaction - .insert(games) + .insert(gamesTable) .values({ name: game.name, slug: kebabCase(game.name || game.slug || ''), @@ -75,13 +75,13 @@ export async function createGame(locals: App.Locals, game: Games, externalId: st }) .returning() const dbExternalIds = await transaction - .insert(externalIds) + .insert(externalIdsTable) .values({ externalId, type: 'game', }) - .returning({ id: externalIds.id }) - await transaction.insert(gamesToExternalIds).values({ + .returning({ id: externalIdsTable.id }) + await transaction.insert(gamesToExternalIdsTable).values({ gameId: dbGames[0].id, externalId: dbExternalIds[0].id, }) @@ -115,7 +115,7 @@ export async function createOrUpdateGameMinimal(locals: App.Locals, game: Games, console.log('Creating game', JSON.stringify(game, null, 2)) await db.transaction(async (transaction) => { dbGames = await transaction - .insert(games) + .insert(gamesTable) .values({ name: game.name, slug: kebabCase(game.name ?? game.slug ?? ''), @@ -131,7 +131,7 @@ export async function createOrUpdateGameMinimal(locals: App.Locals, game: Games, max_playtime: game.max_playtime, }) .onConflictDoUpdate({ - target: games.id, + target: gamesTable.id, set: { name: game.name, slug: kebabCase(game.name || game.slug || ''), @@ -149,15 +149,15 @@ export async function createOrUpdateGameMinimal(locals: App.Locals, game: Games, }) .returning() const dbExternalIds = await transaction - .insert(externalIds) + .insert(externalIdsTable) .values({ externalId, type: 'game', }) .onConflictDoNothing() - .returning({ id: externalIds.id }) + .returning({ id: externalIdsTable.id }) await transaction - .insert(gamesToExternalIds) + .insert(gamesToExternalIdsTable) .values({ gameId: dbGames[0].id, externalId: dbExternalIds[0].id, @@ -189,18 +189,18 @@ export async function createOrUpdateGame(locals: App.Locals, game: Games, extern try { const externalUrl = `https://boardgamegeek.com/boardgame/${externalId}` const dbExternalId = await db.query.externalIds.findFirst({ - where: eq(externalIds.externalId, externalId), + where: eq(externalIdsTable.externalId, externalId), }) if (dbExternalId) { const foundGame = await db .select({ - id: games.id, - name: games.name, - slug: games.slug, + id: gamesTable.id, + name: gamesTable.name, + slug: gamesTable.slug, }) - .from(games) - .leftJoin(gamesToExternalIds, eq(gamesToExternalIds.externalId, externalId)) + .from(gamesTable) + .leftJoin(gamesToExternalIdsTable, eq(gamesToExternalIdsTable.externalId, externalId)) console.log('Game already exists', foundGame) if (foundGame.length > 0) { console.log('Game name', foundGame[0].name) @@ -218,7 +218,7 @@ export async function createOrUpdateGame(locals: App.Locals, game: Games, extern console.log('Creating game', JSON.stringify(game, null, 2)) await db.transaction(async (transaction) => { dbGames = await transaction - .insert(games) + .insert(gamesTable) .values({ name: game.name, slug: kebabCase(game.name || game.slug || ''), @@ -234,7 +234,7 @@ export async function createOrUpdateGame(locals: App.Locals, game: Games, extern max_playtime: game.max_playtime, }) .onConflictDoUpdate({ - target: games.id, + target: gamesTable.id, set: { name: game.name, slug: kebabCase(game.name || game.slug || ''), @@ -252,15 +252,15 @@ export async function createOrUpdateGame(locals: App.Locals, game: Games, extern }) .returning() const dbExternalIds = await transaction - .insert(externalIds) + .insert(externalIdsTable) .values({ externalId, type: 'game', }) .onConflictDoNothing() - .returning({ id: externalIds.id }) + .returning({ id: externalIdsTable.id }) await transaction - .insert(gamesToExternalIds) + .insert(gamesToExternalIdsTable) .values({ gameId: dbGames[0].id, externalId: dbExternalIds[0].id, @@ -291,7 +291,7 @@ export async function updateGame(locals: App.Locals, game: Games, id: string) { try { const dbGame = await db - .update(games) + .update(gamesTable) .set({ name: game.name, slug: kebabCase(game.name || game.slug || ''), @@ -306,7 +306,7 @@ export async function updateGame(locals: App.Locals, game: Games, id: string) { min_playtime: game.min_playtime, max_playtime: game.max_playtime, }) - .where(eq(games.id, id)) + .where(eq(gamesTable.id, id)) .returning() return new Response(JSON.stringify(dbGame[0]), { headers: { @@ -315,7 +315,7 @@ export async function updateGame(locals: App.Locals, game: Games, id: string) { }) } catch (e) { console.error(e) - return new Response('Could not get publishers', { + return new Response('Could not get publishersTable', { status: 500, }) } @@ -323,17 +323,17 @@ export async function updateGame(locals: App.Locals, game: Games, id: string) { // console.log('Creating or updating game', JSON.stringify(game, null, 2)); // const categoryIds = game.categories; -// const mechanicIds = game.mechanics; -// const publisherIds = game.publishers; +// const mechanicIds = game.mechanicsTable; +// const publisherIds = game.publishersTable; // const designerIds = game.designers; // const artistIds = game.artists; -// // const expansionIds = game.expansions; +// // const expansionIds = game.expansionsTable; // const externalUrl = `https://boardgamegeek.com/boardgame/${game.external_id}`; // console.log('categoryIds', categoryIds); // console.log('mechanicIds', mechanicIds); // await db.transaction(async (transaction) => { // const dbGame = await db.transaction(async (transaction) => { -// transaction.insert(games).values({ +// transaction.insert(gamesTable).values({ // name: game.name, // slug: kebabCase(game.name || ''), // description: game.description, @@ -349,7 +349,7 @@ export async function updateGame(locals: App.Locals, game: Games, id: string) { // year_published: game.year_published || 0, // last_sync_at: new Date(), // }).onConflictDoUpdate({ -// target: games.id, set: { +// target: gamesTable.id, set: { // name: game.name, // slug: kebabCase(game.name), // description: game.description, @@ -369,13 +369,13 @@ export async function updateGame(locals: App.Locals, game: Games, id: string) { // }); // // TODO: Connect to everything else // }); -// await db.insert(games).values({ +// await db.insert(gamesTable).values({ // include: { -// mechanics: true, -// publishers: true, +// mechanicsTable: true, +// publishersTable: true, // designers: true, // artists: true, -// expansions: true +// expansionsTable: true // }, // where: { // external_id: game.external_id @@ -398,10 +398,10 @@ export async function updateGame(locals: App.Locals, game: Games, id: string) { // categories: { // connect: categoryIds // }, -// mechanics: { +// mechanicsTable: { // connect: mechanicIds // }, -// publishers: { +// publishersTable: { // connect: publisherIds // }, // designers: { @@ -429,10 +429,10 @@ export async function updateGame(locals: App.Locals, game: Games, id: string) { // categories: { // connect: categoryIds // }, -// mechanics: { +// mechanicsTable: { // connect: mechanicIds // }, -// publishers: { +// publishersTable: { // connect: publisherIds // }, // designers: { diff --git a/src/lib/utils/db/mechanicUtils.ts b/src/lib/utils/db/mechanicUtils.ts index 4d963c0..071c9c9 100644 --- a/src/lib/utils/db/mechanicUtils.ts +++ b/src/lib/utils/db/mechanicUtils.ts @@ -1,5 +1,5 @@ import { PUBLIC_SITE_URL } from '$env/static/public' -import { type Mechanics, externalIds, mechanics, mechanicsToExternalIds } from '$lib/server/api/databases/tables' +import { type Mechanics, externalIdsTable, mechanicsTable, mechanicsToExternalIdsTable } from '$lib/server/api/databases/tables' import { db } from '$lib/server/api/packages/drizzle' import { error } from '@sveltejs/kit' import { eq } from 'drizzle-orm' @@ -12,18 +12,18 @@ export async function createMechanic(locals: App.Locals, mechanic: Mechanics, ex try { const dbExternalId = await db.query.externalIds.findFirst({ - where: eq(externalIds.externalId, externalId), + where: eq(externalIdsTable.externalId, externalId), }) if (dbExternalId) { const foundMechanic = await db .select({ - id: mechanics.id, - name: mechanics.name, - slug: mechanics.slug, + id: mechanicsTable.id, + name: mechanicsTable.name, + slug: mechanicsTable.slug, }) - .from(mechanics) - .leftJoin(mechanicsToExternalIds, eq(mechanicsToExternalIds.externalId, externalId)) + .from(mechanicsTable) + .leftJoin(mechanicsToExternalIdsTable, eq(mechanicsToExternalIdsTable.externalId, externalId)) console.log('Mechanic already exists', foundMechanic) if (foundMechanic.length > 0) { console.log('Mechanic name', foundMechanic[0].name) @@ -41,20 +41,20 @@ export async function createMechanic(locals: App.Locals, mechanic: Mechanics, ex console.log('Creating mechanic', JSON.stringify(mechanic, null, 2)) await db.transaction(async (transaction) => { dbMechanics = await transaction - .insert(mechanics) + .insert(mechanicsTable) .values({ name: mechanic.name, slug: kebabCase(mechanic.name || mechanic.slug || ''), }) .returning() const dbExternalIds = await transaction - .insert(externalIds) + .insert(externalIdsTable) .values({ externalId, type: 'mechanic', }) - .returning({ id: externalIds.id }) - await transaction.insert(mechanicsToExternalIds).values({ + .returning({ id: externalIdsTable.id }) + await transaction.insert(mechanicsToExternalIdsTable).values({ mechanicId: dbMechanics[0].id, externalId: dbExternalIds[0].id, }) diff --git a/src/lib/utils/db/publisherUtils.ts b/src/lib/utils/db/publisherUtils.ts index a66fe4e..576094d 100644 --- a/src/lib/utils/db/publisherUtils.ts +++ b/src/lib/utils/db/publisherUtils.ts @@ -1,12 +1,12 @@ import { PUBLIC_SITE_URL } from '$env/static/public' -import { type Publishers, externalIds, publishers, publishersToExternalIds } from '$lib/server/api/databases/tables' +import { type Publishers, externalIdsTable, publishersTable, publishersToExternalIdsTable } from '$lib/server/api/databases/tables' import { db } from '$lib/server/api/packages/drizzle' import { error } from '@sveltejs/kit' import { eq } from 'drizzle-orm' import kebabCase from 'just-kebab-case' export async function getPublisher(locals: App.Locals, id: string) { - const publisher = await db.select().from(publishers).where(eq(publishers.id, id)) + const publisher = await db.select().from(publishersTable).where(eq(publishersTable.id, id)) if (publisher.length === 0) { error(404, 'not found') } @@ -24,12 +24,12 @@ export async function updatePublisher(locals: App.Locals, publisher: Publishers, try { const dbPublisher = await db - .update(publishers) + .update(publishersTable) .set({ name: publisher.name, slug: kebabCase(publisher.name || ''), }) - .where(eq(publishers.id, id)) + .where(eq(publishersTable.id, id)) .returning() return new Response(JSON.stringify(dbPublisher[0]), { headers: { @@ -38,7 +38,7 @@ export async function updatePublisher(locals: App.Locals, publisher: Publishers, }) } catch (e) { console.error(e) - return new Response('Could not get publishers', { + return new Response('Could not get publishersTable', { status: 500, }) } @@ -51,18 +51,18 @@ export async function createPublisher(locals: App.Locals, publisher: Publishers, try { const dbExternalId = await db.query.externalIds.findFirst({ - where: eq(externalIds.externalId, externalId), + where: eq(externalIdsTable.externalId, externalId), }) if (dbExternalId) { const foundPublisher = await db .select({ - id: publishers.id, - name: publishers.name, - slug: publishers.slug, + id: publishersTable.id, + name: publishersTable.name, + slug: publishersTable.slug, }) - .from(publishers) - .leftJoin(publishersToExternalIds, eq(publishersToExternalIds.externalId, externalId)) + .from(publishersTable) + .leftJoin(publishersToExternalIdsTable, eq(publishersToExternalIdsTable.externalId, externalId)) console.log('Publisher already exists', foundPublisher) if (foundPublisher.length > 0) { console.log('Publisher name', foundPublisher[0].name) @@ -80,20 +80,20 @@ export async function createPublisher(locals: App.Locals, publisher: Publishers, console.log('Creating publisher', JSON.stringify(publisher, null, 2)) await db.transaction(async (transaction) => { dbPublishers = await transaction - .insert(publishers) + .insert(publishersTable) .values({ name: publisher.name, slug: kebabCase(publisher.name || publisher.slug || ''), }) .returning() const dbExternalIds = await transaction - .insert(externalIds) + .insert(externalIdsTable) .values({ externalId, type: 'publisher', }) - .returning({ id: externalIds.id }) - await transaction.insert(publishersToExternalIds).values({ + .returning({ id: externalIdsTable.id }) + await transaction.insert(publishersToExternalIdsTable).values({ publisherId: dbPublishers[0].id, externalId: dbExternalIds[0].id, }) diff --git a/src/routes/(app)/(protected)/admin/users/[id]/+page.server.ts b/src/routes/(app)/(protected)/admin/users/[id]/+page.server.ts index 85bdbd7..ab2f1cf 100644 --- a/src/routes/(app)/(protected)/admin/users/[id]/+page.server.ts +++ b/src/routes/(app)/(protected)/admin/users/[id]/+page.server.ts @@ -1,5 +1,5 @@ import { forbiddenMessage, notSignedInMessage } from '$lib/flashMessages' -import { roles, user_roles, usersTable } from '$lib/server/api/databases/tables' +import { rolesTable, user_roles, usersTable } from '$lib/server/api/databases/tables' import { db } from '$lib/server/api/packages/drizzle' import { and, eq, inArray, not } from 'drizzle-orm' import { redirect } from 'sveltekit-flash-message/server' @@ -40,7 +40,7 @@ export const load: PageServerLoad = async (event) => { let availableRoles: { name: string; cuid: string }[] = [] if (currentRoleIds?.length > 0) { availableRoles = await db.query.roles.findMany({ - where: not(inArray(roles.cuid, currentRoleIds)), + where: not(inArray(rolesTable.cuid, currentRoleIds)), columns: { name: true, cuid: true, @@ -86,7 +86,7 @@ export const actions = { const data = await request.formData() const role = data.get('role') const dbRole = await db.query.roles.findFirst({ - where: eq(roles.cuid, role?.toString() ?? ''), + where: eq(rolesTable.cuid, role?.toString() ?? ''), }) console.log('dbRole', dbRole) if (dbRole) { @@ -126,7 +126,7 @@ export const actions = { const data = await request.formData() const role = data.get('role') const dbRole = await db.query.roles.findFirst({ - where: eq(roles.cuid, role?.toString() ?? ''), + where: eq(rolesTable.cuid, role?.toString() ?? ''), }) console.log('dbRole', dbRole) if (dbRole) { diff --git a/src/routes/(app)/(protected)/admin/users/[id]/+page.svelte b/src/routes/(app)/(protected)/admin/users/[id]/+page.svelte index 91cbd87..1c9fdf1 100644 --- a/src/routes/(app)/(protected)/admin/users/[id]/+page.svelte +++ b/src/routes/(app)/(protected)/admin/users/[id]/+page.svelte @@ -1,13 +1,13 @@

User Details

diff --git a/src/routes/(app)/(protected)/admin/users/[id]/add-roles-form.svelte b/src/routes/(app)/(protected)/admin/users/[id]/add-roles-form.svelte index 5e8f10e..27b7fc4 100644 --- a/src/routes/(app)/(protected)/admin/users/[id]/add-roles-form.svelte +++ b/src/routes/(app)/(protected)/admin/users/[id]/add-roles-form.svelte @@ -1,38 +1,34 @@
@@ -40,7 +36,7 @@
Roles - Select the roles you want to add to the user. + Select the rolesTable you want to add to the user.
diff --git a/src/routes/(app)/(protected)/collections/+page.server.ts b/src/routes/(app)/(protected)/collections/+page.server.ts index 55bad0b..fa3230d 100644 --- a/src/routes/(app)/(protected)/collections/+page.server.ts +++ b/src/routes/(app)/(protected)/collections/+page.server.ts @@ -7,7 +7,7 @@ import { and, eq } from 'drizzle-orm' import { redirect } from 'sveltekit-flash-message/server' import { zod } from 'sveltekit-superforms/adapters' import { superValidate } from 'sveltekit-superforms/server' -import { collection_items, collections, games } from '../../../../lib/server/api/databases/tables' +import { collection_items, collections, gamesTable } from '../../../../lib/server/api/databases/tables' export async function load(event) { const { user, session } = event.locals @@ -54,7 +54,7 @@ export const actions: Actions = { const user = event.locals.user const game = await db.query.games.findFirst({ - where: eq(games.id, form.data.id), + where: eq(gamesTable.id, form.data.id), }) if (!game) { @@ -115,7 +115,7 @@ export const actions: Actions = { } const game = await db.query.games.findFirst({ - where: eq(games.id, form.data.id), + where: eq(gamesTable.id, form.data.id), }) if (!game) { diff --git a/src/routes/(app)/(protected)/collections/[cuid]/+page.server.ts b/src/routes/(app)/(protected)/collections/[cuid]/+page.server.ts index fff5ac2..25121ca 100644 --- a/src/routes/(app)/(protected)/collections/[cuid]/+page.server.ts +++ b/src/routes/(app)/(protected)/collections/[cuid]/+page.server.ts @@ -7,7 +7,7 @@ import { and, eq } from 'drizzle-orm' import { redirect } from 'sveltekit-flash-message/server' import { zod } from 'sveltekit-superforms/adapters' import { superValidate } from 'sveltekit-superforms/server' -import { collection_items, collections, games } from '../../../../../lib/server/api/databases/tables' +import { collection_items, collections, gamesTable } from '../../../../../lib/server/api/databases/tables' export async function load(event) { const { params, locals } = event @@ -139,7 +139,7 @@ export const actions: Actions = { const form = await superValidate(event, zod(modifyListGameSchema)) const game = await db.query.games.findFirst({ - where: eq(games.id, form.data.id), + where: eq(gamesTable.id, form.data.id), }) if (!game) { @@ -204,7 +204,7 @@ export const actions: Actions = { const form = await superValidate(event, zod(modifyListGameSchema)) const game = await db.query.games.findFirst({ - where: eq(games.id, form.data.id), + where: eq(gamesTable.id, form.data.id), }) if (!game) { diff --git a/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte b/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte index 3cb772d..b840239 100644 --- a/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte +++ b/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte @@ -1,33 +1,33 @@ @@ -40,7 +40,7 @@
{#if items.length === 0} -

No games in your collection

+

No gamesTable in your collection

{:else} {#each items as game (game.game_id)} diff --git a/src/routes/(app)/(protected)/list/+layout.server.ts b/src/routes/(app)/(protected)/list/+layout.server.ts index 30ca610..fd76692 100644 --- a/src/routes/(app)/(protected)/list/+layout.server.ts +++ b/src/routes/(app)/(protected)/list/+layout.server.ts @@ -1,5 +1,5 @@ import { notSignedInMessage } from '$lib/flashMessages' -import { wishlists } from '$lib/server/api/databases/tables' +import { wishlistsTable } from '$lib/server/api/databases/tables' import { db } from '$lib/server/api/packages/drizzle' import { eq } from 'drizzle-orm' import { redirect } from 'sveltekit-flash-message/server' @@ -14,7 +14,7 @@ export async function load(event) { try { const dbWishlists = await db.query.wishlists.findMany({ - where: eq(wishlists.user_id, authedUser.id), + where: eq(wishlistsTable.user_id, authedUser.id), }) return { diff --git a/src/routes/(app)/(protected)/list/+layout.svelte b/src/routes/(app)/(protected)/list/+layout.svelte index 6d59e3a..21bc4cf 100644 --- a/src/routes/(app)/(protected)/list/+layout.svelte +++ b/src/routes/(app)/(protected)/list/+layout.svelte @@ -1,8 +1,8 @@
\ No newline at end of file diff --git a/src/routes/(app)/(protected)/wishlists/+page.server.ts b/src/routes/(app)/(protected)/wishlists/+page.server.ts index db80d2c..d461cfc 100644 --- a/src/routes/(app)/(protected)/wishlists/+page.server.ts +++ b/src/routes/(app)/(protected)/wishlists/+page.server.ts @@ -1,5 +1,5 @@ import { notSignedInMessage } from '$lib/flashMessages.js' -import { games, wishlist_items, wishlists } from '$lib/server/api/databases/tables' +import { gamesTable, wishlist_items, wishlistsTable } from '$lib/server/api/databases/tables' import { db } from '$lib/server/api/packages/drizzle' import { userNotAuthenticated } from '$lib/server/auth-utils' import { modifyListGameSchema } from '$lib/validations/zod-schemas' @@ -23,7 +23,7 @@ export async function load(event) { name: true, createdAt: true, }, - where: eq(wishlists.user_id, authedUser.id), + where: eq(wishlistsTable.user_id, authedUser.id), }) console.log('wishlists', userWishlists) @@ -50,7 +50,7 @@ export const actions: Actions = { try { const game = await db.query.games.findFirst({ - where: eq(games.id, form.data.id), + where: eq(gamesTable.id, form.data.id), }) if (!game) { @@ -65,7 +65,7 @@ export const actions: Actions = { if (game) { const wishlist = await db.query.wishlists.findFirst({ - where: eq(wishlists.user_id, authedUser.id), + where: eq(wishlistsTable.user_id, authedUser.id), }) if (!wishlist) { @@ -117,7 +117,7 @@ export const actions: Actions = { try { const game = await db.query.games.findFirst({ - where: eq(games.id, form.data.id), + where: eq(gamesTable.id, form.data.id), }) if (!game) { @@ -132,7 +132,7 @@ export const actions: Actions = { if (game) { const wishlist = await db.query.wishlists.findFirst({ - where: eq(wishlists.user_id, authedUser.id), + where: eq(wishlistsTable.user_id, authedUser.id), }) if (!wishlist) { diff --git a/src/routes/(app)/(protected)/wishlists/+page.svelte b/src/routes/(app)/(protected)/wishlists/+page.svelte index 9678631..a65577f 100644 --- a/src/routes/(app)/(protected)/wishlists/+page.svelte +++ b/src/routes/(app)/(protected)/wishlists/+page.svelte @@ -1,18 +1,18 @@ Your Wishlists | Bored Game -

Your wishlists

+

Your wishlistsTable

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

You have no wishlists

+

You have no wishlistsTable

{:else} {#each wishlists as wishlist}
diff --git a/src/routes/(app)/(protected)/wishlists/[cuid]/+page.server.ts b/src/routes/(app)/(protected)/wishlists/[cuid]/+page.server.ts index 5093585..e622159 100644 --- a/src/routes/(app)/(protected)/wishlists/[cuid]/+page.server.ts +++ b/src/routes/(app)/(protected)/wishlists/[cuid]/+page.server.ts @@ -7,7 +7,7 @@ import { and, eq } from 'drizzle-orm' import { redirect } from 'sveltekit-flash-message/server' import { zod } from 'sveltekit-superforms/adapters' import { superValidate } from 'sveltekit-superforms/server' -import { games, wishlist_items, wishlists } from '../../../../../lib/server/api/databases/tables' +import { gamesTable, wishlist_items, wishlistsTable } from '../../../../../lib/server/api/databases/tables' export async function load(event) { const { params, locals } = event @@ -24,8 +24,8 @@ export async function load(event) { param: { cuid }, }) .then(locals.parseApiResponse) - // const wishlist = await db.query.wishlists.findMany({ - // where: and(eq(wishlists.user_id, authedUser.id), eq(wishlists.cuid, cuid)), + // const wishlist = await db.query.wishlistsTable.findMany({ + // where: and(eq(wishlistsTable.user_id, authedUser.id), eq(wishlistsTable.cuid, cuid)), // }); if (errors) { return error(500, 'Failed to fetch wishlist') @@ -59,7 +59,7 @@ export const actions: Actions = { try { const game = await db.query.games.findFirst({ - where: eq(games.id, form.data.id), + where: eq(gamesTable.id, form.data.id), }) if (!game) { @@ -74,7 +74,7 @@ export const actions: Actions = { if (game) { const wishlist = await db.query.wishlists.findFirst({ - where: eq(wishlists.user_id, user!.id!), + where: eq(wishlistsTable.user_id, user!.id!), }) if (!wishlist) { @@ -125,7 +125,7 @@ export const actions: Actions = { try { const game = await db.query.games.findFirst({ - where: eq(games.id, form.data.id), + where: eq(gamesTable.id, form.data.id), }) if (!game) { @@ -140,7 +140,7 @@ export const actions: Actions = { if (game) { const wishlist = await db.query.wishlists.findFirst({ - where: eq(wishlists.user_id, user!.id!), + where: eq(wishlistsTable.user_id, user!.id!), }) if (!wishlist) { diff --git a/src/routes/(app)/(protected)/wishlists/[cuid]/+page.svelte b/src/routes/(app)/(protected)/wishlists/[cuid]/+page.svelte index 12ea5c4..4eb0cca 100644 --- a/src/routes/(app)/(protected)/wishlists/[cuid]/+page.svelte +++ b/src/routes/(app)/(protected)/wishlists/[cuid]/+page.svelte @@ -1,9 +1,9 @@ @@ -18,7 +18,7 @@ {/each} {:else} -

Sorry no games found!

+

Sorry no gamesTable found!

{/if}
diff --git a/src/routes/(app)/+page.server.ts b/src/routes/(app)/+page.server.ts index ad7d0cc..e8606fe 100644 --- a/src/routes/(app)/+page.server.ts +++ b/src/routes/(app)/+page.server.ts @@ -2,7 +2,7 @@ import { db } from '$lib/server/api/packages/drizzle' import { fail } from '@sveltejs/kit' import { eq } from 'drizzle-orm' import type { MetaTagsProps } from 'svelte-meta-tags' -import { collections, usersTable, wishlists } from '../../lib/server/api/databases/tables' +import { collections, usersTable, wishlistsTable } from '../../lib/server/api/databases/tables' import type { PageServerLoad } from './$types' // import { userFullyAuthenticated } from '$lib/server/auth-utils'; @@ -24,7 +24,7 @@ export const load: PageServerLoad = async (event) => { url: new URL(url.pathname, url.origin).href, locale: 'en_US', title: 'Home', - description: 'Bored Game, keep track of your games', + description: 'Bored Game, keep track of your gamesTable', images: [image], siteName: 'Bored Game', }, @@ -33,7 +33,7 @@ export const load: PageServerLoad = async (event) => { site: '@boredgame', cardType: 'summary_large_image', title: 'Home | Bored Game', - description: 'Bored Game, keep track of your games', + description: 'Bored Game, keep track of your gamesTable', image: `${new URL(url.pathname, url.origin).href}og?header=Bored Game&page=Home&content=Keep track of your games`, imageAlt: 'Home | Bored Game', }, @@ -44,7 +44,7 @@ export const load: PageServerLoad = async (event) => { const { data: collectionsData, error: collectionsError } = await locals.api.collections.$get().then(locals.parseApiResponse) if (wishlistsError || collectionsError) { - return fail(500, 'Failed to fetch wishlists or collections') + return fail(500, 'Failed to fetch wishlistsTable or collections') } console.log('Wishlists', wishlistsData.wishlists) diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte index d2a5055..63d16cb 100644 --- a/src/routes/(app)/+page.svelte +++ b/src/routes/(app)/+page.svelte @@ -1,31 +1,31 @@
{#if user}

Welcome, {welcomeName}!

-

You wishlists:

+

You wishlistsTable:

{#each wishlists as wishlist} {wishlist.name} {/each} @@ -38,7 +38,7 @@
{:else}

Welcome to Bored Game!

-

Track the board games you own, the ones you want, and whether you play them enough.

+

Track the board gamesTable you own, the ones you want, and whether you play them enough.

Get started by joining the wait list or log in if you already have an account.

{/if}
diff --git a/src/routes/(app)/about/+page.svelte b/src/routes/(app)/about/+page.svelte index 9dd3f37..f2b6915 100644 --- a/src/routes/(app)/about/+page.svelte +++ b/src/routes/(app)/about/+page.svelte @@ -6,7 +6,7 @@

About Bored Game

-

One day we were bored and wanted to play one of our board games.

+

One day we were bored and wanted to play one of our board gamesTable.

Our problem was that we didn't know which one to play.

Rather than just pick a game I decided to make this overcomplicated solution.

I hope you enjoy using it!

diff --git a/src/routes/(app)/game/[id]/+page.server.ts b/src/routes/(app)/game/[id]/+page.server.ts index 8fd02b9..7e37c23 100644 --- a/src/routes/(app)/game/[id]/+page.server.ts +++ b/src/routes/(app)/game/[id]/+page.server.ts @@ -1,4 +1,4 @@ -import { collection_items, collections, expansions, games, wishlist_items, wishlists } from '$lib/server/api/databases/tables' +import { collection_items, collections, expansionsTable, gamesTable, wishlist_items, wishlistsTable } from '$lib/server/api/databases/tables' import { db } from '$lib/server/api/packages/drizzle' import { createCategory } from '$lib/utils/db/categoryUtils' import { createExpansion } from '$lib/utils/db/expansionUtils' @@ -15,7 +15,7 @@ export const load: PageServerLoad = async ({ params, locals, fetch }) => { const { user } = locals const { id } = params const game = await db.query.games.findFirst({ - where: eq(games.id, id), + where: eq(gamesTable.id, id), with: { publishers_to_games: { with: { @@ -62,7 +62,7 @@ export const load: PageServerLoad = async ({ params, locals, fetch }) => { } const gameExpansions = await db.query.expansions.findMany({ - where: eq(expansions.base_game_id, game.id), + where: eq(expansionsTable.base_game_id, game.id), with: { game: { columns: { @@ -78,7 +78,7 @@ export const load: PageServerLoad = async ({ params, locals, fetch }) => { let wishlistItem if (user) { const wishlist = await db.query.wishlists.findFirst({ - where: eq(wishlists.user_id, user.id), + where: eq(wishlistsTable.user_id, user.id), }) // TODO: Select wishlist items based on wishlist @@ -155,7 +155,7 @@ async function syncGameAndConnectedData(locals: App.Locals, game: Game, eventFet boredGame.categories = categories boredGame.mechanics = mechanics boredGame.publishers = publishers - // boredGame.expansions = expansions; + // boredGame.expansionsTable = expansionsTable; return createOrUpdateGame(locals, boredGame, externalGame.external_id) } } diff --git a/src/routes/(app)/search/+error.svelte b/src/routes/(app)/search/+error.svelte index f26c443..808e9a2 100644 --- a/src/routes/(app)/search/+error.svelte +++ b/src/routes/(app)/search/+error.svelte @@ -1,5 +1,5 @@ -

There was an error searching for games! 🤦‍♂️

-

Please try again later. 🙇🏼

+

There was an error searching for gamesTable! 🤦

+

Please try again later. 🙇

\ No newline at end of file diff --git a/src/routes/(app)/(protected)/settings/+layout.svelte b/src/routes/(app)/(protected)/settings/+layout.svelte new file mode 100644 index 0000000..c4620d3 --- /dev/null +++ b/src/routes/(app)/(protected)/settings/+layout.svelte @@ -0,0 +1,15 @@ + + + + {@render children()} + \ No newline at end of file diff --git a/src/routes/(app)/(protected)/settings/+page.server.ts b/src/routes/(app)/(protected)/settings/+page.server.ts new file mode 100644 index 0000000..38077bd --- /dev/null +++ b/src/routes/(app)/(protected)/settings/+page.server.ts @@ -0,0 +1,8 @@ +// +page.server.ts +import { redirect } from '@sveltejs/kit' +import type { PageServerLoad } from './$types' + +export const load: PageServerLoad = async () => { + // Redirect to a different page + throw redirect(307, '/settings/profile') +} diff --git a/src/routes/(app)/(protected)/profile/+page.server.ts b/src/routes/(app)/(protected)/settings/profile/+page.server.ts similarity index 88% rename from src/routes/(app)/(protected)/profile/+page.server.ts rename to src/routes/(app)/(protected)/settings/profile/+page.server.ts index 15e4e46..77cab00 100644 --- a/src/routes/(app)/(protected)/profile/+page.server.ts +++ b/src/routes/(app)/(protected)/settings/profile/+page.server.ts @@ -1,9 +1,6 @@ -import { updateEmailDto } from '$lib/dtos/update-email.dto' -import { updateProfileDto } from '$lib/dtos/update-profile.dto' import { notSignedInMessage } from '$lib/flashMessages' import { usersTable } from '$lib/server/api/databases/tables' import { db } from '$lib/server/api/packages/drizzle' -import { changeEmailSchema, profileSchema } from '$lib/validations/account' import { type Actions, fail } from '@sveltejs/kit' import { eq } from 'drizzle-orm' import { redirect } from 'sveltekit-flash-message/server' @@ -11,6 +8,7 @@ import { zod } from 'sveltekit-superforms/adapters' import { message, setError, superValidate } from 'sveltekit-superforms/server' import { z } from 'zod' import type { PageServerLoad } from './$types' +import { updateEmailSchema, updateProfileSchema } from './schemas' export const load: PageServerLoad = async (event) => { const { locals } = event @@ -28,14 +26,14 @@ export const load: PageServerLoad = async (event) => { // where: eq(usersTable.id, user!.id!), // }); - const profileForm = await superValidate(zod(profileSchema), { + const profileForm = await superValidate(zod(updateProfileSchema), { defaults: { firstName: authedUser?.firstName ?? '', lastName: authedUser?.lastName ?? '', username: authedUser?.username ?? '', }, }) - const emailForm = await superValidate(zod(changeEmailSchema), { + const emailForm = await superValidate(zod(updateEmailSchema), { defaults: { email: authedUser?.email ?? '', }, @@ -66,7 +64,7 @@ export const actions: Actions = { redirect(302, '/login', notSignedInMessage, event) } - const form = await superValidate(event, zod(updateProfileDto)) + const form = await superValidate(event, zod(updateProfileSchema)) const { error } = await locals.api.me.update.profile.$put({ json: form.data }).then(locals.parseApiResponse) console.log('data from profile update', error) @@ -84,7 +82,7 @@ export const actions: Actions = { return message(form, { type: 'success', message: 'Profile updated successfully!' }) }, changeEmail: async (event) => { - const form = await superValidate(event, zod(updateEmailDto)) + const form = await superValidate(event, zod(updateEmailSchema)) const newEmail = form.data?.email if (!form.valid || !newEmail || (newEmail !== '' && !changeEmailIfNotEmpty.safeParse(form.data).success)) { diff --git a/src/routes/(app)/(protected)/profile/+page.svelte b/src/routes/(app)/(protected)/settings/profile/+page.svelte similarity index 73% rename from src/routes/(app)/(protected)/profile/+page.svelte rename to src/routes/(app)/(protected)/settings/profile/+page.svelte index 7434d86..7943447 100644 --- a/src/routes/(app)/(protected)/profile/+page.svelte +++ b/src/routes/(app)/(protected)/settings/profile/+page.svelte @@ -1,27 +1,24 @@ + +
+ {#if !hasSetupTwoFactor} +

Multi Factor Authentication is: Disabled

+ + {:else} +

Multi Factor Authentication is: Enabled

+ + {/if} +
+
+ +
\ No newline at end of file diff --git a/src/routes/(app)/(protected)/profile/security/password/change/+page.server.ts b/src/routes/(app)/(protected)/settings/security/change/password/+page.server.ts similarity index 94% rename from src/routes/(app)/(protected)/profile/security/password/change/+page.server.ts rename to src/routes/(app)/(protected)/settings/security/change/password/+page.server.ts index c2b9f75..e708aa5 100644 --- a/src/routes/(app)/(protected)/profile/security/password/change/+page.server.ts +++ b/src/routes/(app)/(protected)/settings/security/change/password/+page.server.ts @@ -1,6 +1,6 @@ import { notSignedInMessage } from '$lib/flashMessages' +import { usersTable } from '$lib/server/api/databases/tables' import { db } from '$lib/server/api/packages/drizzle' -import { changeUserPasswordSchema } from '$lib/validations/account' import { type Actions, fail } from '@sveltejs/kit' import { eq } from 'drizzle-orm' import type { Cookie } from 'lucia' @@ -8,8 +8,8 @@ import { Argon2id } from 'oslo/password' import { redirect } from 'sveltekit-flash-message/server' import { zod } from 'sveltekit-superforms/adapters' import { setError, superValidate } from 'sveltekit-superforms/server' -import type { PageServerLoad } from '../../../$types' -import { usersTable } from '../../../../../../../lib/server/api/databases/tables' +import type { PageServerLoad } from './$types' +import { changeUserPasswordSchema } from './schemas' export const load: PageServerLoad = async (event) => { const { locals } = event diff --git a/src/routes/(app)/(protected)/profile/security/password/change/+page.svelte b/src/routes/(app)/(protected)/settings/security/change/password/+page.svelte similarity index 67% rename from src/routes/(app)/(protected)/profile/security/password/change/+page.svelte rename to src/routes/(app)/(protected)/settings/security/change/password/+page.svelte index e5c7422..302379a 100644 --- a/src/routes/(app)/(protected)/profile/security/password/change/+page.svelte +++ b/src/routes/(app)/(protected)/settings/security/change/password/+page.svelte @@ -1,22 +1,22 @@ diff --git a/src/routes/(app)/(protected)/settings/security/change/password/schemas.ts b/src/routes/(app)/(protected)/settings/security/change/password/schemas.ts new file mode 100644 index 0000000..ffb4ed8 --- /dev/null +++ b/src/routes/(app)/(protected)/settings/security/change/password/schemas.ts @@ -0,0 +1,81 @@ +import { z } from 'zod' + +export const changeUserPasswordSchema = z + .object({ + current_password: z.string({ required_error: 'Current Password is required' }), + password: z.string({ required_error: 'Password is required' }).trim(), + confirm_password: z.string({ required_error: 'Confirm Password is required' }).trim(), + }) + .superRefine(({ confirm_password, password }, ctx) => { + refinePasswords(confirm_password, password, ctx) + }) + +export type ChangeUserPasswordSchema = typeof changeUserPasswordSchema + +const refinePasswords = async (confirm_password: string, password: string, ctx: z.RefinementCtx) => { + comparePasswords(confirm_password, password, ctx) + checkPasswordStrength(password, ctx) +} + +const comparePasswords = async (confirm_password: string, password: string, ctx: z.RefinementCtx) => { + if (confirm_password !== password) { + ctx.addIssue({ + code: 'custom', + message: 'Password and Confirm Password must match', + path: ['confirm_password'], + }) + } +} + +const checkPasswordStrength = async (password: string, ctx: z.RefinementCtx) => { + const minimumLength = password.length < 8 + const maximumLength = password.length > 128 + const containsUppercase = (ch: string) => /[A-Z]/.test(ch) + const containsLowercase = (ch: string) => /[a-z]/.test(ch) + const containsSpecialChar = (ch: string) => /[`!@#$%^&*()_\-+=\[\]{};':"\\|,.<>\/?~ ]/.test(ch) + let countOfUpperCase = 0 + let countOfLowerCase = 0 + let countOfNumbers = 0 + let countOfSpecialChar = 0 + for (let i = 0; i < password.length; i++) { + const char = password.charAt(i) + if (!Number.isNaN(+char)) { + countOfNumbers++ + } else if (containsUppercase(char)) { + countOfUpperCase++ + } else if (containsLowercase(char)) { + countOfLowerCase++ + } else if (containsSpecialChar(char)) { + countOfSpecialChar++ + } + } + + let errorMessage = 'Your password:' + + if (countOfLowerCase < 1) { + errorMessage = ' Must have at least one lowercase letter. ' + } + if (countOfNumbers < 1) { + errorMessage += ' Must have at least one number. ' + } + if (countOfUpperCase < 1) { + errorMessage += ' Must have at least one uppercase letter. ' + } + if (countOfSpecialChar < 1) { + errorMessage += ' Must have at least one special character.' + } + if (minimumLength) { + errorMessage += ' Be at least 8 characters long.' + } + if (maximumLength) { + errorMessage += ' Be less than 128 characters long.' + } + + if (errorMessage.length > 'Your password:'.length) { + ctx.addIssue({ + code: 'custom', + message: errorMessage, + path: ['password'], + }) + } +} diff --git a/src/routes/(app)/(protected)/settings/security/mfa/+page.server.ts b/src/routes/(app)/(protected)/settings/security/mfa/+page.server.ts new file mode 100644 index 0000000..e87d84b --- /dev/null +++ b/src/routes/(app)/(protected)/settings/security/mfa/+page.server.ts @@ -0,0 +1,25 @@ +import { notSignedInMessage } from '$lib/flashMessages' +import env from '$lib/server/api/common/env' +import { addTwoFactorSchema, removeTwoFactorSchema } from '$lib/validations/account' +import { type Actions, fail } from '@sveltejs/kit' +import kebabCase from 'just-kebab-case' +import { base32, decodeHex } from 'oslo/encoding' +import { createTOTPKeyURI } from 'oslo/otp' +import QRCode from 'qrcode' +import { redirect } from 'sveltekit-flash-message/server' +import { zod } from 'sveltekit-superforms/adapters' +import { setError, superValidate } from 'sveltekit-superforms/server' +import type { PageServerLoad } from '../../$types' + +export const load: PageServerLoad = async (event) => { + const { locals } = event + + const authedUser = await locals.getAuthedUser() + if (!authedUser) { + throw redirect(302, '/login', notSignedInMessage, event) + } + + return {} +} + +export const actions: Actions = {} diff --git a/src/routes/(app)/(protected)/settings/security/mfa/+page.svelte b/src/routes/(app)/(protected)/settings/security/mfa/+page.svelte new file mode 100644 index 0000000..0ed96a6 --- /dev/null +++ b/src/routes/(app)/(protected)/settings/security/mfa/+page.svelte @@ -0,0 +1,57 @@ + + +

Two-factor authentication

+ + + + Two-Factor Methods + + +
+
+
+

Authenticator app {#if hardwareTokenEnabled}Configured{/if}

+

Use an authenticator app or browser extension to get two-factor authentication codes when prompted.

+
+ +
+
+
+

Security Keys {#if hardwareTokenEnabled}Configured{/if}

+

+ Security keys are webauthn credentials that can only be used as a second factor of authentication. +

+
+ +
+
+
+
+ + \ No newline at end of file diff --git a/src/routes/(app)/(protected)/profile/security/mfa/recovery-codes/+page.server.ts b/src/routes/(app)/(protected)/settings/security/mfa/recovery-codes/+page.server.ts similarity index 100% rename from src/routes/(app)/(protected)/profile/security/mfa/recovery-codes/+page.server.ts rename to src/routes/(app)/(protected)/settings/security/mfa/recovery-codes/+page.server.ts diff --git a/src/routes/(app)/(protected)/profile/security/mfa/recovery-codes/+page.svelte b/src/routes/(app)/(protected)/settings/security/mfa/recovery-codes/+page.svelte similarity index 100% rename from src/routes/(app)/(protected)/profile/security/mfa/recovery-codes/+page.svelte rename to src/routes/(app)/(protected)/settings/security/mfa/recovery-codes/+page.svelte diff --git a/src/routes/(app)/(protected)/profile/security/mfa/+page.server.ts b/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.server.ts similarity index 95% rename from src/routes/(app)/(protected)/profile/security/mfa/+page.server.ts rename to src/routes/(app)/(protected)/settings/security/mfa/totp/+page.server.ts index c7fb19e..4d6577a 100644 --- a/src/routes/(app)/(protected)/profile/security/mfa/+page.server.ts +++ b/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.server.ts @@ -1,6 +1,5 @@ import { notSignedInMessage } from '$lib/flashMessages' -import { addTwoFactorSchema, removeTwoFactorSchema } from '$lib/validations/account' -import env from '$src/env' +import env from '$lib/server/api/common/env' import { type Actions, fail } from '@sveltejs/kit' import kebabCase from 'just-kebab-case' import { base32, decodeHex } from 'oslo/encoding' @@ -10,6 +9,7 @@ import { redirect } from 'sveltekit-flash-message/server' import { zod } from 'sveltekit-superforms/adapters' import { setError, superValidate } from 'sveltekit-superforms/server' import type { PageServerLoad } from '../../$types' +import { addTwoFactorSchema, removeTwoFactorSchema } from './schemas' export const load: PageServerLoad = async (event) => { const { locals } = event @@ -125,7 +125,7 @@ export const actions: Actions = { return setError(addTwoFactorForm, 'two_factor_code', 'Invalid code') } - redirect(302, '/profile/security/mfa/recovery-codes') + redirect(302, '/settings/security/mfa/recovery-codes') }, disableTotp: async (event) => { const { locals } = event @@ -162,7 +162,7 @@ export const actions: Actions = { redirect( 302, - '/profile/security/mfa', + '/settings/security/mfa', { type: 'success', message: 'Two-Factor Authentication has been disabled.', diff --git a/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.svelte b/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.svelte new file mode 100644 index 0000000..b52ba0b --- /dev/null +++ b/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.svelte @@ -0,0 +1,83 @@ + + +
+

Two-Factor Authentication

+ + {#if twoFactorEnabled} +

Currently you have two factor authentication enabled

+

To disable two factor authentication, please enter your current password.

+ + + + Current Password + + + Please enter your current password. + + + Disable Two Factor Authentication + + {:else} +

Please scan the following QR Code

+ QR Code +
+ + + Enter Code + + + This is the code from your authenticator app. + + + + + Enter Password + + + Please enter your current password. + + + Submit +
+ Secret: {secret} + {/if} +
+ + \ No newline at end of file diff --git a/src/routes/(app)/(protected)/settings/security/mfa/totp/schemas.ts b/src/routes/(app)/(protected)/settings/security/mfa/totp/schemas.ts new file mode 100644 index 0000000..fd14c28 --- /dev/null +++ b/src/routes/(app)/(protected)/settings/security/mfa/totp/schemas.ts @@ -0,0 +1,14 @@ +import { z } from 'zod' + +export const addTwoFactorSchema = z.object({ + current_password: z.string({ required_error: 'Current Password is required' }), + two_factor_code: z.string({ required_error: 'Two Factor Code is required' }).trim(), +}) + +export type AddTwoFactorSchema = typeof addTwoFactorSchema + +export const removeTwoFactorSchema = addTwoFactorSchema.pick({ + current_password: true, +}) + +export type RemoveTwoFactorSchema = typeof removeTwoFactorSchema diff --git a/src/routes/(app)/(protected)/wishlists/+page.server.ts b/src/routes/(app)/(protected)/wishlists/+page.server.ts index d461cfc..f211518 100644 --- a/src/routes/(app)/(protected)/wishlists/+page.server.ts +++ b/src/routes/(app)/(protected)/wishlists/+page.server.ts @@ -90,18 +90,20 @@ export const actions: Actions = { // Create new wishlist create: async (event) => { const { locals } = event - const { user, session } = locals - if (userNotAuthenticated(user, session)) { - return fail(401) + + const authedUser = await locals.getAuthedUser() + if (!authedUser) { + throw redirect(302, '/login', notSignedInMessage, event) } return error(405, 'Method not allowed') }, // Delete a wishlist delete: async (event) => { const { locals } = event - const { user, session } = locals - if (userNotAuthenticated(user, session)) { - return fail(401) + + const authedUser = await locals.getAuthedUser() + if (!authedUser) { + throw redirect(302, '/login', notSignedInMessage, event) } return error(405, 'Method not allowed') }, @@ -116,7 +118,7 @@ export const actions: Actions = { const form = await superValidate(event, zod(modifyListGameSchema)) try { - const game = await db.query.games.findFirst({ + const game = await db.query.gamesTable.findFirst({ where: eq(gamesTable.id, form.data.id), }) @@ -131,7 +133,7 @@ export const actions: Actions = { } if (game) { - const wishlist = await db.query.wishlists.findFirst({ + const wishlist = await db.query.wishlistsTable.findFirst({ where: eq(wishlistsTable.user_id, authedUser.id), }) diff --git a/src/routes/(app)/(protected)/wishlists/[cuid]/+page.server.ts b/src/routes/(app)/(protected)/wishlists/[cuid]/+page.server.ts index e622159..2ec8923 100644 --- a/src/routes/(app)/(protected)/wishlists/[cuid]/+page.server.ts +++ b/src/routes/(app)/(protected)/wishlists/[cuid]/+page.server.ts @@ -51,14 +51,15 @@ export const actions: Actions = { // Add game to a wishlist add: async (event) => { const { locals } = event - const { user, session } = locals - if (userNotAuthenticated(user, session)) { - return fail(401) + + const authedUser = await locals.getAuthedUser() + if (!authedUser) { + throw redirect(302, '/login', notSignedInMessage, event) } const form = await superValidate(event, zod(modifyListGameSchema)) try { - const game = await db.query.games.findFirst({ + const game = await db.query.gamesTable.findFirst({ where: eq(gamesTable.id, form.data.id), }) @@ -73,8 +74,8 @@ export const actions: Actions = { } if (game) { - const wishlist = await db.query.wishlists.findFirst({ - where: eq(wishlistsTable.user_id, user!.id!), + const wishlist = await db.query.wishlistsTable.findFirst({ + where: eq(wishlistsTable.user_id, authedUser.id), }) if (!wishlist) { @@ -99,32 +100,35 @@ export const actions: Actions = { // Create new wishlist create: async (event) => { const { locals } = event - const { user, session } = locals - if (userNotAuthenticated(user, session)) { - return fail(401) + + const authedUser = await locals.getAuthedUser() + if (!authedUser) { + throw redirect(302, '/login', notSignedInMessage, event) } return error(405, 'Method not allowed') }, // Delete a wishlist delete: async (event) => { const { locals } = event - const { user, session } = locals - if (userNotAuthenticated(user, session)) { - return fail(401) + + const authedUser = await locals.getAuthedUser() + if (!authedUser) { + throw redirect(302, '/login', notSignedInMessage, event) } return error(405, 'Method not allowed') }, // Remove game from a wishlist remove: async (event) => { const { locals } = event - const { user, session } = locals - if (userNotAuthenticated(user, session)) { - return fail(401) + + const authedUser = await locals.getAuthedUser() + if (!authedUser) { + throw redirect(302, '/login', notSignedInMessage, event) } const form = await superValidate(event, zod(modifyListGameSchema)) try { - const game = await db.query.games.findFirst({ + const game = await db.query.gamesTable.findFirst({ where: eq(gamesTable.id, form.data.id), }) @@ -139,8 +143,8 @@ export const actions: Actions = { } if (game) { - const wishlist = await db.query.wishlists.findFirst({ - where: eq(wishlistsTable.user_id, user!.id!), + const wishlist = await db.query.wishlistsTable.findFirst({ + where: eq(wishlistsTable.user_id, authedUser.id), }) if (!wishlist) { diff --git a/src/routes/(auth)/login/+page.server.ts b/src/routes/(auth)/login/+page.server.ts index 3672bd7..a2b90e9 100644 --- a/src/routes/(auth)/login/+page.server.ts +++ b/src/routes/(auth)/login/+page.server.ts @@ -47,7 +47,9 @@ export const actions: Actions = { const form = await superValidate(event, zod(signinUsernameDto)) const { error } = await locals.api.login.$post({ json: form.data }).then(locals.parseApiResponse) - if (error) return setError(form, 'username', error) + if (error) { + return setError(form, 'username', error) + } if (!form.valid) { form.data.password = '' diff --git a/src/routes/(auth)/password/reset/+page.server.ts b/src/routes/(auth)/password/reset/+page.server.ts index 6b2a20f..70de114 100644 --- a/src/routes/(auth)/password/reset/+page.server.ts +++ b/src/routes/(auth)/password/reset/+page.server.ts @@ -1,57 +1,56 @@ -import { fail, error, type Actions } from '@sveltejs/kit'; -import { zod } from 'sveltekit-superforms/adapters'; -import { setError, superValidate } from 'sveltekit-superforms/server'; -import { redirect } from 'sveltekit-flash-message/server'; -import type { PageServerLoad } from './$types'; -import {resetPasswordEmailSchema, resetPasswordTokenSchema} from "$lib/validations/auth"; -import {StatusCodes} from "$lib/constants/status-codes"; -import {userFullyAuthenticated} from "$lib/server/auth-utils"; +import { StatusCodes } from '$lib/constants/status-codes' +import { notSignedInMessage } from '$lib/flashMessages' +import { resetPasswordEmailSchema, resetPasswordTokenSchema } from '$lib/validations/auth' +import { type Actions, error, fail } from '@sveltejs/kit' +import { redirect } from 'sveltekit-flash-message/server' +import { zod } from 'sveltekit-superforms/adapters' +import { setError, superValidate } from 'sveltekit-superforms/server' +import type { PageServerLoad } from './$types' export const load: PageServerLoad = async () => { return { emailForm: await superValidate(zod(resetPasswordEmailSchema)), tokenForm: await superValidate(zod(resetPasswordTokenSchema)), - }; -}; + } +} export const actions = { passwordReset: async (event) => { - const { request, locals } = event; - const { user, session } = locals; + const { request, locals } = event - if (userFullyAuthenticated(user, session)) { - const message = { type: 'success', message: 'You are already signed in' } as const; - throw redirect('/', message, event); + const authedUser = await locals.getAuthedUser() + if (!authedUser) { + throw redirect(302, '/login', notSignedInMessage, event) } - const emailForm = await superValidate(request, zod(resetPasswordEmailSchema)); + const emailForm = await superValidate(request, zod(resetPasswordEmailSchema)) if (!emailForm.valid) { - return fail(StatusCodes.BAD_REQUEST, { emailForm }); + return fail(StatusCodes.BAD_REQUEST, { emailForm }) } // const error = {}; // // const { error } = await locals.api.iam.login.request.$post({ json: emailRegisterForm.data }).then(locals.parseApiResponse); // if (error) { // return setError(emailForm, 'email', error); // } - return { emailForm }; + return { emailForm } }, verifyToken: async (event) => { - const { request, locals } = event; - const { user, session } = locals; - if (userFullyAuthenticated(user, session)) { - const message = { type: 'success', message: 'You are already signed in' } as const; - throw redirect('/', message, event); + const { request, locals } = event + + const authedUser = await locals.getAuthedUser() + if (!authedUser) { + throw redirect(302, '/login', notSignedInMessage, event) } - const tokenForm = await superValidate(request, zod(resetPasswordTokenSchema)); + const tokenForm = await superValidate(request, zod(resetPasswordTokenSchema)) if (!tokenForm.valid) { - return fail(StatusCodes.BAD_REQUEST, { tokenForm }); + return fail(StatusCodes.BAD_REQUEST, { tokenForm }) } - const error = {}; + const error = {} // const { error } = await locals.api.iam.login.verify.$post({ json: emailSignInForm.data }).then(locals.parseApiResponse) if (error) { - return setError(tokenForm, 'token', error); + return setError(tokenForm, 'token', error) } - redirect(301, '/'); - } -}; + redirect(301, '/') + }, +} diff --git a/src/routes/(auth)/totp/+page.server.ts b/src/routes/(auth)/totp/+page.server.ts index 480b36b..9b05025 100644 --- a/src/routes/(auth)/totp/+page.server.ts +++ b/src/routes/(auth)/totp/+page.server.ts @@ -1,4 +1,5 @@ import { notSignedInMessage } from '$lib/flashMessages' +import env from '$lib/server/api/common/env' import { twoFactorTable, usersTable } from '$lib/server/api/databases/tables' import { db } from '$lib/server/api/packages/drizzle' import { recoveryCodeSchema, totpSchema } from '$lib/validations/auth' @@ -9,7 +10,6 @@ import { redirect } from 'sveltekit-flash-message/server' import { RateLimiter } from 'sveltekit-rate-limiter/server' import { zod } from 'sveltekit-superforms/adapters' import { superValidate } from 'sveltekit-superforms/server' -import env from '../../../env' import type { PageServerLoad, RequestEvent } from './$types' export const load: PageServerLoad = async (event) => { diff --git a/svelte.config.js b/svelte.config.js index 7ead23b..71dd300 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -25,6 +25,7 @@ const config = { $db: './src/lib/server/api/infrastructure/database', $server: './src/server', $lib: './src/lib', + $routes: './src/routes', $src: './src', $state: './src/state', $styles: './src/styles', From 3b338801661f780febd5474f956044a1c9884a0f Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Mon, 9 Sep 2024 19:25:16 -0700 Subject: [PATCH 06/29] Creating APIs for changing user password and calling it in change password. Cleaned up CSS layout styles and got settings nav correct. --- package.json | 2 +- pnpm-lock.yaml | 10 +- src/lib/components/Header.svelte | 119 +++++++++--------- src/lib/components/LeftNav.svelte | 77 ------------ src/lib/components/ui/input/input.svelte | 2 +- src/lib/components/ui/toggle/index.ts | 4 +- src/lib/components/ui/toggle/toggle.svelte | 2 +- src/lib/page_loading_indicator.svelte | 65 +++++----- src/lib/server/api/common/config.ts | 2 - src/lib/server/api/common/exceptions.ts | 28 ++--- .../api/controllers/collection.controller.ts | 2 +- .../server/api/controllers/iam.controller.ts | 31 ++++- .../server/api/controllers/mfa.controller.ts | 2 +- .../server/api/controllers/user.controller.ts | 2 +- .../api/controllers/wishlist.controller.ts | 2 +- .../server/api/dtos/change-password.dto.ts | 17 +++ src/lib/server/api/dtos/update-profile.dto.ts | 23 ++-- src/lib/server/api/jobs/auth-cleanup.job.ts | 6 +- .../server/api/middleware/auth.middleware.ts | 13 -- src/lib/server/api/services/iam.service.ts | 7 ++ src/lib/server/api/services/users.service.ts | 16 +++ .../(app)/(protected)/settings/+layout.svelte | 76 ++++++++++- .../security/change/password/+page.server.ts | 45 ++----- .../security/change/password/+page.svelte | 24 +++- .../security/change/password/schemas.ts | 4 +- .../settings/security/mfa/+page.server.ts | 19 ++- .../settings/security/mfa/+page.svelte | 6 +- src/routes/(app)/+layout.server.ts | 26 ++-- src/routes/(app)/+layout.svelte | 50 ++++---- src/routes/(app)/+page.server.ts | 6 +- src/routes/+layout.svelte | 19 +-- 31 files changed, 350 insertions(+), 357 deletions(-) delete mode 100644 src/lib/components/LeftNav.svelte create mode 100644 src/lib/server/api/dtos/change-password.dto.ts diff --git a/package.json b/package.json index e4997a2..bddfaf3 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ }, "type": "module", "dependencies": { - "@fontsource/fira-mono": "^5.0.14", + "@fontsource/fira-mono": "^5.0.15", "@hono/swagger-ui": "^0.4.1", "@hono/zod-openapi": "^0.15.3", "@hono/zod-validator": "^0.2.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c00d4b2..94e8b55 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@fontsource/fira-mono': - specifier: ^5.0.14 - version: 5.0.14 + specifier: ^5.0.15 + version: 5.0.15 '@hono/swagger-ui': specifier: ^0.4.1 version: 0.4.1(hono@4.5.11) @@ -1245,8 +1245,8 @@ packages: '@floating-ui/utils@0.2.7': resolution: {integrity: sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==} - '@fontsource/fira-mono@5.0.14': - resolution: {integrity: sha512-4IKa+cuHipk/vr2frgZh4pyR2XcoQk/j3zmMlo8uuAGUB3IPLpQlgN6Qm5d3RfRZ7dXGlTn/PWiAJeU8bkmD4w==} + '@fontsource/fira-mono@5.0.15': + resolution: {integrity: sha512-wc3TpF2GBbtFDKNbb444BrC3mEKuoPLITSYCKweNIrqBvAalIfJGloY/MVrmSGaMNgaAKUpdgy4eAWPLkUVzaA==} '@gcornut/valibot-json-schema@0.31.0': resolution: {integrity: sha512-3xGptCurm23e7nuPQkdrE5rEs1FeTPHhAUsBuwwqG4/YeZLwJOoYZv+fmsppUEfo5y9lzUwNQrNqLS/q7HMc7g==} @@ -5489,7 +5489,7 @@ snapshots: '@floating-ui/utils@0.2.7': {} - '@fontsource/fira-mono@5.0.14': {} + '@fontsource/fira-mono@5.0.15': {} '@gcornut/valibot-json-schema@0.31.0': dependencies: diff --git a/src/lib/components/Header.svelte b/src/lib/components/Header.svelte index f614316..4b3a06b 100644 --- a/src/lib/components/Header.svelte +++ b/src/lib/components/Header.svelte @@ -4,15 +4,10 @@ import { invalidateAll } from '$app/navigation' import Logo from '$components/logo.svelte' import * as Avatar from '$components/ui/avatar' import * as DropdownMenu from '$components/ui/dropdown-menu' -import type { Users } from '$db/schema' -import { ListChecks, ListTodo, LogOut, User } from 'lucide-svelte' +import { ListChecks, ListTodo, LogOut, Settings } from 'lucide-svelte' import toast from 'svelte-french-toast' -type HeaderProps = { - user: Users | null -} - -let { user = null }: HeaderProps = $props() +let { user = null } = $props() let avatar: string = $derived(user?.username?.slice(0, 1).toUpperCase() || ':)') @@ -28,39 +23,48 @@ let avatar: string = $derived(user?.username?.slice(0, 1).toUpperCase() || ':)')
+ + +{#snippet userDropdown()} + + + + + {avatar} + + + + + + Account + + + + + Settings + + + + + + Collections + + + + + + Wishlists + + + + { return async ({ result }) => { console.log(result); if (result.type === 'success' || result.type === 'redirect') { @@ -76,26 +80,21 @@ let avatar: string = $derived(user?.username?.slice(0, 1).toUpperCase() || ':)') await applyAction(result); }; }} - action="/logout" - method="POST" - > - - - - - - - {:else} - Login - Sign Up - {/if} - - + action="/logout" + method="POST" + > + + + + + + +{/snippet} \ No newline at end of file diff --git a/src/lib/components/ui/input/input.svelte b/src/lib/components/ui/input/input.svelte index cab1457..477d325 100644 --- a/src/lib/components/ui/input/input.svelte +++ b/src/lib/components/ui/input/input.svelte @@ -1,7 +1,7 @@
diff --git a/src/lib/server/api/common/config.ts b/src/lib/server/api/common/config.ts index 518c73f..0daf6d4 100644 --- a/src/lib/server/api/common/config.ts +++ b/src/lib/server/api/common/config.ts @@ -34,5 +34,3 @@ export const config: Config = { max: env.DB_MIGRATING || env.DB_SEEDING ? 1 : undefined, }, } - -console.log('config', config) diff --git a/src/lib/server/api/common/exceptions.ts b/src/lib/server/api/common/exceptions.ts index fee54c4..cbda928 100644 --- a/src/lib/server/api/common/exceptions.ts +++ b/src/lib/server/api/common/exceptions.ts @@ -1,26 +1,26 @@ -import { StatusCodes } from '$lib/constants/status-codes'; -import { HTTPException } from 'hono/http-exception'; +import { StatusCodes } from '$lib/constants/status-codes' +import { HTTPException } from 'hono/http-exception' -export function TooManyRequests(message: string = 'Too many requests') { - return new HTTPException(StatusCodes.TOO_MANY_REQUESTS, { message }); +export function TooManyRequests(message = 'Too many requests') { + return new HTTPException(StatusCodes.TOO_MANY_REQUESTS, { message }) } -export function Forbidden(message: string = 'Forbidden') { - return new HTTPException(StatusCodes.FORBIDDEN, { message }); +export function Forbidden(message = 'Forbidden') { + return new HTTPException(StatusCodes.FORBIDDEN, { message }) } -export function Unauthorized(message: string = 'Unauthorized') { - return new HTTPException(StatusCodes.UNAUTHORIZED, { message }); +export function Unauthorized(message = 'Unauthorized') { + return new HTTPException(StatusCodes.UNAUTHORIZED, { message }) } -export function NotFound(message: string = 'Not Found') { - return new HTTPException(StatusCodes.NOT_FOUND, { message }); +export function NotFound(message = 'Not Found') { + return new HTTPException(StatusCodes.NOT_FOUND, { message }) } -export function BadRequest(message: string = 'Bad Request') { - return new HTTPException(StatusCodes.BAD_REQUEST, { message }); +export function BadRequest(message = 'Bad Request') { + return new HTTPException(StatusCodes.BAD_REQUEST, { message }) } -export function InternalError(message: string = 'Internal Error') { - return new HTTPException(StatusCodes.INTERNAL_SERVER_ERROR, { message }); +export function InternalError(message = 'Internal Error') { + return new HTTPException(StatusCodes.INTERNAL_SERVER_ERROR, { message }) } diff --git a/src/lib/server/api/controllers/collection.controller.ts b/src/lib/server/api/controllers/collection.controller.ts index 56a53aa..86dfcc5 100644 --- a/src/lib/server/api/controllers/collection.controller.ts +++ b/src/lib/server/api/controllers/collection.controller.ts @@ -2,7 +2,7 @@ import 'reflect-metadata' import { Controller } from '$lib/server/api/common/types/controller' import { CollectionsService } from '$lib/server/api/services/collections.service' import { inject, injectable } from 'tsyringe' -import { requireAuth } from '../middleware/auth.middleware' +import { requireAuth } from '../middleware/require-auth.middleware' @injectable() export class CollectionController extends Controller { diff --git a/src/lib/server/api/controllers/iam.controller.ts b/src/lib/server/api/controllers/iam.controller.ts index 708b7ef..0d2010c 100644 --- a/src/lib/server/api/controllers/iam.controller.ts +++ b/src/lib/server/api/controllers/iam.controller.ts @@ -1,20 +1,23 @@ import { StatusCodes } from '$lib/constants/status-codes' import { Controller } from '$lib/server/api/common/types/controller' +import { changePasswordDto } from '$lib/server/api/dtos/change-password.dto' import { updateEmailDto } from '$lib/server/api/dtos/update-email.dto' import { updateProfileDto } from '$lib/server/api/dtos/update-profile.dto' import { verifyPasswordDto } from '$lib/server/api/dtos/verify-password.dto' import { limiter } from '$lib/server/api/middleware/rate-limiter.middleware' import { IamService } from '$lib/server/api/services/iam.service' +import { LoginRequestsService } from '$lib/server/api/services/loginrequest.service' import { LuciaService } from '$lib/server/api/services/lucia.service' import { zValidator } from '@hono/zod-validator' import { setCookie } from 'hono/cookie' import { inject, injectable } from 'tsyringe' -import { requireAuth } from '../middleware/auth.middleware' +import { requireAuth } from '../middleware/require-auth.middleware' @injectable() export class IamController extends Controller { constructor( @inject(IamService) private readonly iamService: IamService, + @inject(LoginRequestsService) private readonly loginRequestService: LoginRequestsService, @inject(LuciaService) private luciaService: LuciaService, ) { super() @@ -45,6 +48,32 @@ export class IamController extends Controller { } return c.json({}, StatusCodes.OK) }) + .put('/update/password', requireAuth, zValidator('json', changePasswordDto), limiter({ limit: 10, minutes: 60 }), async (c) => { + const user = c.var.user + const { password, confirm_password } = c.req.valid('json') + if (password !== confirm_password) { + return c.json('Passwords do not match', StatusCodes.BAD_REQUEST) + } + try { + await this.iamService.updatePassword(user.id, { password, confirm_password }) + await this.luciaService.lucia.invalidateUserSessions(user.id) + await this.loginRequestService.createUserSession(user.id, c.req, undefined) + const sessionCookie = this.luciaService.lucia.createBlankSessionCookie() + setCookie(c, sessionCookie.name, sessionCookie.value, { + path: sessionCookie.attributes.path, + maxAge: sessionCookie.attributes.maxAge, + domain: sessionCookie.attributes.domain, + sameSite: sessionCookie.attributes.sameSite as any, + secure: sessionCookie.attributes.secure, + httpOnly: sessionCookie.attributes.httpOnly, + expires: sessionCookie.attributes.expires, + }) + return c.json({ status: 'success' }) + } catch (error) { + console.error('Error updating password', error) + return c.json('Error updating password', StatusCodes.BAD_REQUEST) + } + }) .post('/update/email', requireAuth, zValidator('json', updateEmailDto), limiter({ limit: 10, minutes: 60 }), async (c) => { const user = c.var.user const { email } = c.req.valid('json') diff --git a/src/lib/server/api/controllers/mfa.controller.ts b/src/lib/server/api/controllers/mfa.controller.ts index f70aa04..b08b8c1 100644 --- a/src/lib/server/api/controllers/mfa.controller.ts +++ b/src/lib/server/api/controllers/mfa.controller.ts @@ -8,7 +8,7 @@ import { UsersService } from '$lib/server/api/services/users.service' import { zValidator } from '@hono/zod-validator' import { inject, injectable } from 'tsyringe' import { CredentialsType } from '../databases/tables' -import { requireAuth } from '../middleware/auth.middleware' +import { requireAuth } from '../middleware/require-auth.middleware' @injectable() export class MfaController extends Controller { diff --git a/src/lib/server/api/controllers/user.controller.ts b/src/lib/server/api/controllers/user.controller.ts index e7c5deb..c05cd2e 100644 --- a/src/lib/server/api/controllers/user.controller.ts +++ b/src/lib/server/api/controllers/user.controller.ts @@ -2,7 +2,7 @@ import 'reflect-metadata' import { Controller } from '$lib/server/api/common/types/controller' import { UsersService } from '$lib/server/api/services/users.service' import { inject, injectable } from 'tsyringe' -import { requireAuth } from '../middleware/auth.middleware' +import { requireAuth } from '../middleware/require-auth.middleware' @injectable() export class UserController extends Controller { diff --git a/src/lib/server/api/controllers/wishlist.controller.ts b/src/lib/server/api/controllers/wishlist.controller.ts index 44a4a11..1a8da1c 100644 --- a/src/lib/server/api/controllers/wishlist.controller.ts +++ b/src/lib/server/api/controllers/wishlist.controller.ts @@ -2,7 +2,7 @@ import 'reflect-metadata' import { Controller } from '$lib/server/api/common/types/controller' import { WishlistsService } from '$lib/server/api/services/wishlists.service' import { inject, injectable } from 'tsyringe' -import { requireAuth } from '../middleware/auth.middleware' +import { requireAuth } from '../middleware/require-auth.middleware' @injectable() export class WishlistController extends Controller { diff --git a/src/lib/server/api/dtos/change-password.dto.ts b/src/lib/server/api/dtos/change-password.dto.ts new file mode 100644 index 0000000..b624722 --- /dev/null +++ b/src/lib/server/api/dtos/change-password.dto.ts @@ -0,0 +1,17 @@ +import { refinePasswords } from '$lib/validations/account' +import { z } from 'zod' + +export const changePasswordDto = z + .object({ + password: z.string({ required_error: 'Password is required' }).trim(), + confirm_password: z + .string({ required_error: 'Confirm Password is required' }) + .trim() + .min(8, { message: 'Must be at least 8 characters' }) + .max(128, { message: 'Must be less than 128 characters' }), + }) + .superRefine(({ confirm_password, password }, ctx) => { + return refinePasswords(confirm_password, password, ctx) + }) + +export type ChangePasswordDto = z.infer diff --git a/src/lib/server/api/dtos/update-profile.dto.ts b/src/lib/server/api/dtos/update-profile.dto.ts index 9ea0c6f..1ce379b 100644 --- a/src/lib/server/api/dtos/update-profile.dto.ts +++ b/src/lib/server/api/dtos/update-profile.dto.ts @@ -1,23 +1,14 @@ -import { z } from "zod"; +import { z } from 'zod' export const updateProfileDto = z.object({ firstName: z .string() .trim() - .min(3, {message: 'Must be at least 3 characters'}) - .max(50, {message: 'Must be less than 50 characters'}) + .min(3, { message: 'Must be at least 3 characters' }) + .max(50, { message: 'Must be less than 50 characters' }) .optional(), - lastName: z - .string() - .trim() - .min(3, {message: 'Must be at least 3 characters'}) - .max(50, {message: 'Must be less than 50 characters'}) - .optional(), - username: z - .string() - .trim() - .min(3, {message: 'Must be at least 3 characters'}) - .max(50, {message: 'Must be less than 50 characters'}) -}); + lastName: z.string().trim().min(3, { message: 'Must be at least 3 characters' }).max(50, { message: 'Must be less than 50 characters' }).optional(), + username: z.string().trim().min(3, { message: 'Must be at least 3 characters' }).max(50, { message: 'Must be less than 50 characters' }), +}) -export type UpdateProfileDto = z.infer; +export type UpdateProfileDto = z.infer diff --git a/src/lib/server/api/jobs/auth-cleanup.job.ts b/src/lib/server/api/jobs/auth-cleanup.job.ts index fb2ec6c..efaf1c1 100644 --- a/src/lib/server/api/jobs/auth-cleanup.job.ts +++ b/src/lib/server/api/jobs/auth-cleanup.job.ts @@ -10,11 +10,11 @@ export class AuthCleanupJobs { this.queue = this.jobsService.createQueue('test') /* ---------------------------- Register Workers ---------------------------- */ - this.worker().then((r) => console.log('auth-cleanup job worker started')) + this.worker().then(() => console.log('auth-cleanup job worker started')) } async deleteStaleEmailVerificationRequests() { - await this.queue.add('delete_stale_email_verifiactions', null, { + await this.queue.add('delete_stale_email_verifications', null, { repeat: { pattern: '0 0 * * 0', // Runs once a week at midnight on Sunday }, @@ -31,7 +31,7 @@ export class AuthCleanupJobs { private async worker() { return this.jobsService.createWorker(this.queue.name, async (job) => { - if (job.name === 'delete_stale_email_verifiactions') { + if (job.name === 'delete_stale_email_verifications') { // delete stale email verifications } if (job.name === 'delete_stale_login_requests') { diff --git a/src/lib/server/api/middleware/auth.middleware.ts b/src/lib/server/api/middleware/auth.middleware.ts index 3cc3766..b88418b 100644 --- a/src/lib/server/api/middleware/auth.middleware.ts +++ b/src/lib/server/api/middleware/auth.middleware.ts @@ -1,10 +1,8 @@ import { LuciaService } from '$lib/server/api/services/lucia.service' import type { MiddlewareHandler } from 'hono' import { createMiddleware } from 'hono/factory' -import type { Session, User } from 'lucia' import { verifyRequestOrigin } from 'oslo/request' import { container } from 'tsyringe' -import { Unauthorized } from '../common/exceptions' import type { HonoTypes } from '../common/types/hono' // resolve dependencies from the container @@ -41,14 +39,3 @@ export const validateAuthSession: MiddlewareHandler = createMiddlewar c.set('user', user) return next() }) - -export const requireAuth: MiddlewareHandler<{ - Variables: { - session: Session - user: User - } -}> = createMiddleware(async (c, next) => { - const user = c.var.user - if (!user) throw Unauthorized('You must be logged in to access this resource') - return next() -}) diff --git a/src/lib/server/api/services/iam.service.ts b/src/lib/server/api/services/iam.service.ts index 0c3bc6e..a70e8c3 100644 --- a/src/lib/server/api/services/iam.service.ts +++ b/src/lib/server/api/services/iam.service.ts @@ -1,3 +1,5 @@ +import { CredentialsType } from '$lib/server/api/databases/tables' +import type { ChangePasswordDto } from '$lib/server/api/dtos/change-password.dto' import type { UpdateEmailDto } from '$lib/server/api/dtos/update-email.dto' import type { UpdateProfileDto } from '$lib/server/api/dtos/update-profile.dto' import type { VerifyPasswordDto } from '$lib/server/api/dtos/verify-password.dto' @@ -68,6 +70,11 @@ export class IamService { }) } + async updatePassword(userId: string, data: ChangePasswordDto) { + const { password } = data + await this.usersService.updatePassword(userId, password) + } + async verifyPassword(userId: string, data: VerifyPasswordDto) { const user = await this.usersService.findOneById(userId) if (!user) { diff --git a/src/lib/server/api/services/users.service.ts b/src/lib/server/api/services/users.service.ts index 89e6eea..f067809 100644 --- a/src/lib/server/api/services/users.service.ts +++ b/src/lib/server/api/services/users.service.ts @@ -69,6 +69,22 @@ export class UsersService { return this.usersRepository.findOneById(id) } + async updatePassword(userId: string, password: string) { + const hashedPassword = await this.tokenService.createHashedToken(password) + const currentCredentials = await this.credentialsRepository.findPasswordCredentialsByUserId(userId) + if (!currentCredentials) { + await this.credentialsRepository.create({ + user_id: userId, + type: CredentialsType.PASSWORD, + secret_data: hashedPassword, + }) + } else { + await this.credentialsRepository.update(currentCredentials.id, { + secret_data: hashedPassword, + }) + } + } + async verifyPassword(userId: string, data: { password: string }) { const user = await this.usersRepository.findOneById(userId) if (!user) { diff --git a/src/routes/(app)/(protected)/settings/+layout.svelte b/src/routes/(app)/(protected)/settings/+layout.svelte index c4620d3..81483b4 100644 --- a/src/routes/(app)/(protected)/settings/+layout.svelte +++ b/src/routes/(app)/(protected)/settings/+layout.svelte @@ -1,5 +1,5 @@ - - {@render children()} - \ No newline at end of file +
+ +
+ {@render children()} +
+
+ + diff --git a/src/routes/(app)/(protected)/settings/security/change/password/+page.server.ts b/src/routes/(app)/(protected)/settings/security/change/password/+page.server.ts index e708aa5..1c4e775 100644 --- a/src/routes/(app)/(protected)/settings/security/change/password/+page.server.ts +++ b/src/routes/(app)/(protected)/settings/security/change/password/+page.server.ts @@ -48,33 +48,11 @@ export const actions: Actions = { }) } - console.log('updating profile') - if (!event.locals.user) { - redirect(302, '/login', notSignedInMessage, event) - } - - if (!event.locals.session) { - return fail(401) - } - - const dbUser = await db.query.usersTable.findFirst({ - where: eq(usersTable.id, authedUser.id), - }) - - // if (!dbUser?.hashed_password) { - // form.data.password = ''; - // form.data.confirm_password = ''; - // form.data.current_password = ''; - // return setError( - // form, - // 'Error occurred. Please try again or contact support if you need further help.', - // ); - // } - - const currentPasswordVerified = await new Argon2id().verify( - // dbUser.hashed_password, - form.data.current_password, - ) + const currentPasswordVerified = await locals.api.me.verify.password + .$post({ + json: { password: form.data.current_password }, + }) + .then(locals.parseApiResponse) if (!currentPasswordVerified) { return setError(form, 'current_password', 'Your password is incorrect') @@ -85,16 +63,9 @@ export const actions: Actions = { if (form.data.password !== form.data.confirm_password) { return setError(form, 'Password and confirm password do not match') } - const hashedPassword = await new Argon2id().hash(form.data.password) - await lucia.invalidateUserSessions(authedUser.id) - // await db - // .update(usersTable) - // .set({ hashed_password: hashedPassword }) - // .where(eq(usersTable.id, user.id)); - await lucia.createSession(user.id, { - country: event.locals.session?.ipCountry ?? 'unknown', - }) - sessionCookie = lucia.createBlankSessionCookie() + await locals.api.me.change.password.$put({ + json: { password: form.data.password, confirm_password: form.data.confirm_password }, + }).then(locals.parseApiResponse) } catch (e) { console.error(e) form.data.password = '' diff --git a/src/routes/(app)/(protected)/settings/security/change/password/+page.svelte b/src/routes/(app)/(protected)/settings/security/change/password/+page.svelte index 302379a..1a46b42 100644 --- a/src/routes/(app)/(protected)/settings/security/change/password/+page.svelte +++ b/src/routes/(app)/(protected)/settings/security/change/password/+page.svelte @@ -2,7 +2,8 @@ import * as Alert from '$components/ui/alert' import * as Form from '$components/ui/form' import { Input } from '$components/ui/input' -import { AlertTriangle } from 'lucide-svelte' +import { Toggle } from '$components/ui/toggle' +import { AlertTriangle, EyeIcon, EyeOff } from 'lucide-svelte' import { zodClient } from 'sveltekit-superforms/adapters' import { superForm } from 'sveltekit-superforms/client' import { changeUserPasswordSchema } from './schemas' @@ -16,13 +17,17 @@ const form = superForm(data.form, { multipleSubmits: 'prevent', }) +let hiddenCurrentPassword = $state(true) +let hiddenPassword = $state(true) +let hiddenConfirmPassword = $state(true) + const { form: formData, enhance } = form

Change Password


- + Heads up! @@ -32,21 +37,30 @@ const { form: formData, enhance } = form Current Password - + + + hiddenCurrentPassword = !hiddenCurrentPassword}>{#if hiddenCurrentPassword}{:else}{/if} + New Password - + + + hiddenPassword = !hiddenPassword}>{#if hiddenPassword}{:else}{/if} + Confirm New Password - + + + hiddenConfirmPassword = !hiddenConfirmPassword}>{#if hiddenConfirmPassword}{:else}{/if} + diff --git a/src/routes/(app)/(protected)/settings/security/change/password/schemas.ts b/src/routes/(app)/(protected)/settings/security/change/password/schemas.ts index ffb4ed8..a6f3adb 100644 --- a/src/routes/(app)/(protected)/settings/security/change/password/schemas.ts +++ b/src/routes/(app)/(protected)/settings/security/change/password/schemas.ts @@ -13,8 +13,8 @@ export const changeUserPasswordSchema = z export type ChangeUserPasswordSchema = typeof changeUserPasswordSchema const refinePasswords = async (confirm_password: string, password: string, ctx: z.RefinementCtx) => { - comparePasswords(confirm_password, password, ctx) - checkPasswordStrength(password, ctx) + await comparePasswords(confirm_password, password, ctx) + await checkPasswordStrength(password, ctx) } const comparePasswords = async (confirm_password: string, password: string, ctx: z.RefinementCtx) => { diff --git a/src/routes/(app)/(protected)/settings/security/mfa/+page.server.ts b/src/routes/(app)/(protected)/settings/security/mfa/+page.server.ts index e87d84b..d16dcd4 100644 --- a/src/routes/(app)/(protected)/settings/security/mfa/+page.server.ts +++ b/src/routes/(app)/(protected)/settings/security/mfa/+page.server.ts @@ -1,14 +1,6 @@ import { notSignedInMessage } from '$lib/flashMessages' -import env from '$lib/server/api/common/env' -import { addTwoFactorSchema, removeTwoFactorSchema } from '$lib/validations/account' -import { type Actions, fail } from '@sveltejs/kit' -import kebabCase from 'just-kebab-case' -import { base32, decodeHex } from 'oslo/encoding' -import { createTOTPKeyURI } from 'oslo/otp' -import QRCode from 'qrcode' +import type { Actions } from '@sveltejs/kit' import { redirect } from 'sveltekit-flash-message/server' -import { zod } from 'sveltekit-superforms/adapters' -import { setError, superValidate } from 'sveltekit-superforms/server' import type { PageServerLoad } from '../../$types' export const load: PageServerLoad = async (event) => { @@ -19,7 +11,14 @@ export const load: PageServerLoad = async (event) => { throw redirect(302, '/login', notSignedInMessage, event) } - return {} + const { data: totpData, error: totpDataError } = await locals.api.mfa.totp.$get().then(locals.parseApiResponse) + + const totpEnabled = !!totpData + + return { + totpEnabled, + hardwareTokenEnabled: false, + } } export const actions: Actions = {} diff --git a/src/routes/(app)/(protected)/settings/security/mfa/+page.svelte b/src/routes/(app)/(protected)/settings/security/mfa/+page.svelte index 0ed96a6..94b3304 100644 --- a/src/routes/(app)/(protected)/settings/security/mfa/+page.svelte +++ b/src/routes/(app)/(protected)/settings/security/mfa/+page.svelte @@ -5,8 +5,8 @@ import * as Card from '$lib/components/ui/card' const { data } = $props() -const totpEnabled = true -const hardwareTokenEnabled = true +const totpEnabled = data.totpEnabled +const hardwareTokenEnabled = data.hardwareTokenEnabled

Two-factor authentication

@@ -19,7 +19,7 @@ const hardwareTokenEnabled = true
-

Authenticator app {#if hardwareTokenEnabled}Configured{/if}

+

Authenticator app {#if totpEnabled}Configured{/if}

Use an authenticator app or browser extension to get two-factor authentication codes when prompted.

diff --git a/src/routes/(app)/+layout.server.ts b/src/routes/(app)/+layout.server.ts index aa43781..493b195 100644 --- a/src/routes/(app)/+layout.server.ts +++ b/src/routes/(app)/+layout.server.ts @@ -1,24 +1,12 @@ -import { loadFlash } from 'sveltekit-flash-message/server'; -import type { LayoutServerLoad } from '../$types'; -// import { userFullyAuthenticated, userNotFullyAuthenticated } from '$lib/server/auth-utils'; -// import { lucia } from '$lib/server/auth'; +import { loadFlash } from 'sveltekit-flash-message/server' +import type { LayoutServerLoad } from '../$types' export const load: LayoutServerLoad = loadFlash(async (event) => { - const { url, locals, cookies } = event; - const authedUser = await locals.getAuthedUser(); - - // if (userNotFullyAuthenticated(user, session)) { - // await lucia.invalidateSession(locals.session!.id!); - // const sessionCookie = lucia.createBlankSessionCookie(); - // cookies.set(sessionCookie.name, sessionCookie.value, { - // path: '.', - // ...sessionCookie.attributes, - // }); - // } + const { url, locals } = event + const authedUser = await locals.getAuthedUser() return { url: url.pathname, - // user: userFullyAuthenticated(user, session) ? locals.user : null, - user: authedUser, - }; -}); + authedUser, + } +}) diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index 49d18d5..aaab874 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -1,37 +1,39 @@ -
+
+
-
- {@render children()} -
+
+ {@render children()} +
-
+
+
\ No newline at end of file +{@render children()} + \ No newline at end of file From bdbfe7dcf5d743711a6a666d628654218181d56c Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Tue, 10 Sep 2024 17:40:26 -0700 Subject: [PATCH 07/29] Updating password change toggle to use derived and fixing server code to correctly check errors on verify password. --- .../security/change/password/+page.server.ts | 22 +++----- .../security/change/password/+page.svelte | 55 +++++++++++++++---- 2 files changed, 52 insertions(+), 25 deletions(-) diff --git a/src/routes/(app)/(protected)/settings/security/change/password/+page.server.ts b/src/routes/(app)/(protected)/settings/security/change/password/+page.server.ts index 1c4e775..300b45d 100644 --- a/src/routes/(app)/(protected)/settings/security/change/password/+page.server.ts +++ b/src/routes/(app)/(protected)/settings/security/change/password/+page.server.ts @@ -48,24 +48,26 @@ export const actions: Actions = { }) } - const currentPasswordVerified = await locals.api.me.verify.password + const { error: verifyPasswordError } = await locals.api.me.verify.password .$post({ json: { password: form.data.current_password }, }) .then(locals.parseApiResponse) - if (!currentPasswordVerified) { + console.log('verifyPasswordError', verifyPasswordError) + + if (verifyPasswordError) { + console.error(verifyPasswordError) return setError(form, 'current_password', 'Your password is incorrect') } if (authedUser?.username) { - let sessionCookie: Cookie try { if (form.data.password !== form.data.confirm_password) { return setError(form, 'Password and confirm password do not match') } - await locals.api.me.change.password.$put({ + await locals.api.me.update.password.$put({ json: { password: form.data.password, confirm_password: form.data.confirm_password }, - }).then(locals.parseApiResponse) + }) } catch (e) { console.error(e) form.data.password = '' @@ -73,11 +75,6 @@ export const actions: Actions = { form.data.current_password = '' return setError(form, 'current_password', 'Your password is incorrect.') } - event.cookies.set(sessionCookie.name, sessionCookie.value, { - path: '.', - ...sessionCookie.attributes, - }) - const message = { type: 'success', message: 'Password Updated. Please sign in.', @@ -85,10 +82,5 @@ export const actions: Actions = { redirect(302, '/login', message, event) } return setError(form, 'Error occurred. Please try again or contact support if you need further help.') - // TODO: Add toast instead? - // form.data.password = ''; - // form.data.confirm_password = ''; - // form.data.current_password = ''; - // return message(form, 'Profile updated successfully.'); }, } diff --git a/src/routes/(app)/(protected)/settings/security/change/password/+page.svelte b/src/routes/(app)/(protected)/settings/security/change/password/+page.svelte index 1a46b42..fbc8215 100644 --- a/src/routes/(app)/(protected)/settings/security/change/password/+page.svelte +++ b/src/routes/(app)/(protected)/settings/security/change/password/+page.svelte @@ -20,6 +20,11 @@ const form = superForm(data.form, { let hiddenCurrentPassword = $state(true) let hiddenPassword = $state(true) let hiddenConfirmPassword = $state(true) +let currentPasswordInput = $derived(hiddenCurrentPassword ? 'password' : 'text') +let passwordInput = $derived(hiddenPassword ? 'password' : 'text') +let confirmPasswordInput = $derived(hiddenConfirmPassword ? 'password' : 'text') + +// $inspect(hiddenCurrentPassword, hiddenPassword, hiddenConfirmPassword) const { form: formData, enhance } = form @@ -27,19 +32,29 @@ const { form: formData, enhance } = form

Change Password


+ + Heads up! - - Changing your password will log you out of all devices. - + Changing your password will log you out of all devices. Current Password - - hiddenCurrentPassword = !hiddenCurrentPassword}>{#if hiddenCurrentPassword}{:else}{/if} + + (hiddenCurrentPassword = !hiddenCurrentPassword)} + > + {#if hiddenCurrentPassword}{:else}{/if} + @@ -48,8 +63,18 @@ const { form: formData, enhance } = form New Password - - hiddenPassword = !hiddenPassword}>{#if hiddenPassword}{:else}{/if} + + (hiddenPassword = !hiddenPassword)} + > + {#if hiddenPassword}{:else}{/if} + @@ -58,8 +83,18 @@ const { form: formData, enhance } = form Confirm New Password - - hiddenConfirmPassword = !hiddenConfirmPassword}>{#if hiddenConfirmPassword}{:else}{/if} + + (hiddenConfirmPassword = !hiddenConfirmPassword)} + > + {#if hiddenConfirmPassword}{:else}{/if} + @@ -71,4 +106,4 @@ const { form: formData, enhance } = form form { max-width: 20rem; } - \ No newline at end of file + From 68182da4cea8a874480982f1699494648cf13c3f Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Fri, 13 Sep 2024 12:11:41 -0700 Subject: [PATCH 08/29] Fixing iam service tests and formatting other code. --- package.json | 18 +- pnpm-lock.yaml | 334 +++++++++--------- .../repositories/credentials.repository.ts | 1 + .../server/api/tests/hashing.service.test.ts | 40 ++- src/lib/server/api/tests/iam.service.test.ts | 105 ++++++ .../server/api/tests/tokens.service.test.ts | 56 ++- .../server/api/tests/users.service.test.ts | 215 +++++++---- .../collections/[cuid]/+page.server.ts | 5 +- .../collections/[cuid]/+page.svelte | 4 +- .../security/change/password/+page.svelte | 6 +- .../security/mfa/totp/+page.server.ts | 4 +- .../settings/security/mfa/totp/+page.svelte | 4 +- .../settings/security/mfa/totp/schemas.ts | 4 +- .../(app)/(protected)/wishlists/+page.svelte | 32 +- .../(protected)/wishlists/[cuid]/+page.svelte | 39 +- src/routes/(app)/+page.svelte | 4 +- vite.config.ts | 3 +- 17 files changed, 540 insertions(+), 334 deletions(-) create mode 100644 src/lib/server/api/tests/iam.service.test.ts diff --git a/package.json b/package.json index bddfaf3..e04cff2 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@sveltejs/vite-plugin-svelte": "^3.1.2", "@types/cookie": "^0.6.0", "@types/node": "^20.16.5", - "@types/pg": "^8.11.8", + "@types/pg": "^8.11.9", "@typescript-eslint/eslint-plugin": "^7.18.0", "@typescript-eslint/parser": "^7.18.0", "autoprefixer": "^10.4.20", @@ -65,18 +65,18 @@ "sveltekit-flash-message": "^2.4.4", "sveltekit-rate-limiter": "^0.5.2", "sveltekit-superforms": "^2.17.0", - "tailwindcss": "^3.4.10", + "tailwindcss": "^3.4.11", "ts-node": "^10.9.2", "tslib": "^2.7.0", - "tsx": "^4.19.0", - "typescript": "^5.5.4", - "vite": "^5.4.3", + "tsx": "^4.19.1", + "typescript": "^5.6.2", + "vite": "^5.4.4", "vitest": "^1.6.0", "zod": "^3.23.8" }, "type": "module", "dependencies": { - "@fontsource/fira-mono": "^5.0.15", + "@fontsource/fira-mono": "^5.1.0", "@hono/swagger-ui": "^0.4.1", "@hono/zod-openapi": "^0.15.3", "@hono/zod-validator": "^0.2.2", @@ -95,7 +95,7 @@ "arctic": "^1.9.2", "bits-ui": "^0.21.13", "boardgamegeekclient": "^1.9.1", - "bullmq": "^5.12.14", + "bullmq": "^5.13.0", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "cookie": "^0.6.0", @@ -106,7 +106,7 @@ "feather-icons": "^4.29.2", "formsnap": "^1.0.1", "handlebars": "^4.7.8", - "hono": "^4.5.11", + "hono": "^4.6.1", "hono-rate-limiter": "^0.4.0", "html-entities": "^2.5.2", "iconify-icon": "^2.1.0", @@ -128,6 +128,6 @@ "tailwind-variants": "^0.2.1", "tailwindcss-animate": "^1.0.7", "tsyringe": "^4.8.0", - "zod-to-json-schema": "^3.23.2" + "zod-to-json-schema": "^3.23.3" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 94e8b55..1bcf7f5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,17 +9,17 @@ importers: .: dependencies: '@fontsource/fira-mono': - specifier: ^5.0.15 - version: 5.0.15 + specifier: ^5.1.0 + version: 5.1.0 '@hono/swagger-ui': specifier: ^0.4.1 - version: 0.4.1(hono@4.5.11) + version: 0.4.1(hono@4.6.1) '@hono/zod-openapi': specifier: ^0.15.3 - version: 0.15.3(hono@4.5.11)(zod@3.23.8) + version: 0.15.3(hono@4.6.1)(zod@3.23.8) '@hono/zod-validator': specifier: ^0.2.2 - version: 0.2.2(hono@4.5.11)(zod@3.23.8) + version: 0.2.2(hono@4.6.1)(zod@3.23.8) '@iconify-icons/line-md': specifier: ^1.2.30 version: 1.2.30 @@ -31,7 +31,7 @@ importers: version: 3.5.5 '@lucia-auth/adapter-drizzle': specifier: ^1.1.0 - version: 1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.8)(pg@8.12.0)(postgres@3.4.4))(lucia@3.2.0) + version: 1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4))(lucia@3.2.0) '@lukeed/uuid': specifier: ^2.0.1 version: 2.0.1 @@ -46,10 +46,10 @@ importers: version: 2.6.2 '@sveltejs/adapter-node': specifier: ^5.2.2 - version: 5.2.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0))) + version: 5.2.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))) '@sveltejs/adapter-vercel': specifier: ^5.4.3 - version: 5.4.3(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0))) + version: 5.4.3(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))) '@types/feather-icons': specifier: ^4.29.4 version: 4.29.4 @@ -66,8 +66,8 @@ importers: specifier: ^1.9.1 version: 1.9.1 bullmq: - specifier: ^5.12.14 - version: 5.12.14 + specifier: ^5.13.0 + version: 5.13.0 class-variance-authority: specifier: ^0.7.0 version: 0.7.0 @@ -85,25 +85,25 @@ importers: version: 11.0.6 drizzle-orm: specifier: ^0.32.2 - version: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.8)(pg@8.12.0)(postgres@3.4.4) + version: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4) drizzle-zod: specifier: ^0.5.1 - version: 0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.8)(pg@8.12.0)(postgres@3.4.4))(zod@3.23.8) + version: 0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4))(zod@3.23.8) feather-icons: specifier: ^4.29.2 version: 4.29.2 formsnap: specifier: ^1.0.1 - version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)) + version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)) handlebars: specifier: ^4.7.8 version: 4.7.8 hono: - specifier: ^4.5.11 - version: 4.5.11 + specifier: ^4.6.1 + version: 4.6.1 hono-rate-limiter: specifier: ^0.4.0 - version: 0.4.0(hono@4.5.11) + version: 0.4.0(hono@4.6.1) html-entities: specifier: ^2.5.2 version: 2.5.2 @@ -157,16 +157,16 @@ importers: version: 2.5.2 tailwind-variants: specifier: ^0.2.1 - version: 0.2.1(tailwindcss@3.4.10(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.5.4))) + version: 0.2.1(tailwindcss@3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))) tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.10(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.5.4))) + version: 1.0.7(tailwindcss@3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))) tsyringe: specifier: ^4.8.0 version: 4.8.0 zod-to-json-schema: - specifier: ^3.23.2 - version: 3.23.2(zod@3.23.8) + specifier: ^3.23.3 + version: 3.23.3(zod@3.23.8) devDependencies: '@biomejs/biome': specifier: 1.8.3 @@ -185,16 +185,16 @@ importers: version: 1.47.0 '@sveltejs/adapter-auto': specifier: ^3.2.4 - version: 3.2.4(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0))) + version: 3.2.4(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))) '@sveltejs/enhanced-img': specifier: ^0.3.4 - version: 0.3.4(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)) + version: 0.3.4(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) '@sveltejs/kit': specifier: ^2.5.26 - version: 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)) + version: 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) '@sveltejs/vite-plugin-svelte': specifier: ^3.1.2 - version: 3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)) + version: 3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) '@types/cookie': specifier: ^0.6.0 version: 0.6.0 @@ -202,14 +202,14 @@ importers: specifier: ^20.16.5 version: 20.16.5 '@types/pg': - specifier: ^8.11.8 - version: 8.11.8 + specifier: ^8.11.9 + version: 8.11.9 '@typescript-eslint/eslint-plugin': specifier: ^7.18.0 - version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4) + version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0)(typescript@5.6.2) '@typescript-eslint/parser': specifier: ^7.18.0 - version: 7.18.0(eslint@8.57.0)(typescript@5.5.4) + version: 7.18.0(eslint@8.57.0)(typescript@5.6.2) autoprefixer: specifier: ^10.4.20 version: 10.4.20(postcss@8.4.45) @@ -224,7 +224,7 @@ importers: version: 9.1.0(eslint@8.57.0) eslint-plugin-svelte: specifier: 2.36.0-next.13 - version: 2.36.0-next.13(eslint@8.57.0)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.5.4)) + version: 2.36.0-next.13(eslint@8.57.0)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) just-clone: specifier: ^6.2.0 version: 6.2.0 @@ -248,7 +248,7 @@ importers: version: 16.1.0(postcss@8.4.45) postcss-load-config: specifier: ^5.1.0 - version: 5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.0) + version: 5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1) postcss-preset-env: specifier: ^9.6.0 version: 9.6.0(postcss@8.4.45) @@ -272,46 +272,46 @@ importers: version: 5.0.0-next.175 svelte-check: specifier: ^3.8.6 - version: 3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.0))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175) + version: 3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175) svelte-headless-table: specifier: ^0.18.2 version: 0.18.2(svelte@5.0.0-next.175) svelte-meta-tags: specifier: ^3.1.4 - version: 3.1.4(svelte@5.0.0-next.175)(typescript@5.5.4) + version: 3.1.4(svelte@5.0.0-next.175)(typescript@5.6.2) svelte-preprocess: specifier: ^6.0.2 - version: 6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.0))(postcss@8.4.45)(sass@1.78.0)(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.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2) svelte-sequential-preprocessor: specifier: ^2.0.1 version: 2.0.1 sveltekit-flash-message: specifier: ^2.4.4 - version: 2.4.4(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175) + version: 2.4.4(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175) sveltekit-rate-limiter: specifier: ^0.5.2 - version: 0.5.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0))) + version: 0.5.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))) sveltekit-superforms: specifier: ^2.17.0 - version: 2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175) + version: 2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175) tailwindcss: - specifier: ^3.4.10 - version: 3.4.10(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.5.4)) + specifier: ^3.4.11 + version: 3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.16.5)(typescript@5.5.4) + version: 10.9.2(@types/node@20.16.5)(typescript@5.6.2) tslib: specifier: ^2.7.0 version: 2.7.0 tsx: - specifier: ^4.19.0 - version: 4.19.0 + specifier: ^4.19.1 + version: 4.19.1 typescript: - specifier: ^5.5.4 - version: 5.5.4 + specifier: ^5.6.2 + version: 5.6.2 vite: - specifier: ^5.4.3 - version: 5.4.3(@types/node@20.16.5)(sass@1.78.0) + specifier: ^5.4.4 + version: 5.4.4(@types/node@20.16.5)(sass@1.78.0) vitest: specifier: ^1.6.0 version: 1.6.0(@types/node@20.16.5)(sass@1.78.0) @@ -1245,8 +1245,8 @@ packages: '@floating-ui/utils@0.2.7': resolution: {integrity: sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==} - '@fontsource/fira-mono@5.0.15': - resolution: {integrity: sha512-wc3TpF2GBbtFDKNbb444BrC3mEKuoPLITSYCKweNIrqBvAalIfJGloY/MVrmSGaMNgaAKUpdgy4eAWPLkUVzaA==} + '@fontsource/fira-mono@5.1.0': + resolution: {integrity: sha512-6+nftSKApXyN0I9FC5GJuG5TUCh+in5OehtrXRIsHJvq38Pm//oA1kZZYNdXv99JYzLzJ3lzsTAavmS+xGLGDw==} '@gcornut/valibot-json-schema@0.31.0': resolution: {integrity: sha512-3xGptCurm23e7nuPQkdrE5rEs1FeTPHhAUsBuwwqG4/YeZLwJOoYZv+fmsppUEfo5y9lzUwNQrNqLS/q7HMc7g==} @@ -2022,8 +2022,8 @@ packages: '@types/pg@8.11.6': resolution: {integrity: sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ==} - '@types/pg@8.11.8': - resolution: {integrity: sha512-IqpCf8/569txXN/HoP5i1LjXfKZWL76Yr2R77xgeIICUbAYHeoaEZFhYHo2uDftecLWrTJUq63JvQu8q3lnDyA==} + '@types/pg@8.11.9': + resolution: {integrity: sha512-M4mYeJZRBD9lCBCGa72F44uKSV9eJrAFfjlPJagdA6pgIr2OPJULFB7nqnZzOdqXG0qzHlgtZKzTdIgbmHitSg==} '@types/pug@2.0.10': resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==} @@ -2295,8 +2295,8 @@ packages: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} - bullmq@5.12.14: - resolution: {integrity: sha512-mcSQHq9EY+DKtAP6XSmkP+0f1ifFithcpLTwo8WmUauArE9dxk45Gae3Fls1Nwf0Er9MoaDhPcglfe6LV/XCOg==} + bullmq@5.13.0: + resolution: {integrity: sha512-rE7v3jMZZGsEhfMhLZwADwuHdqJPTTGHBM8C+SpxF9GzyZ+7pvC80EP5bOZJPPRzbmyhvIPJCVd0bchUZiQF+w==} bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} @@ -3043,8 +3043,8 @@ packages: peerDependencies: hono: ^4.1.1 - hono@4.5.11: - resolution: {integrity: sha512-62FcjLPtjAFwISVBUshryl+vbHOjg8rE4uIK/dxyR8GpLztunZpwFmfEvmJCUI7xoGh/Sr3CGCDPCmYxVw7wUQ==} + hono@4.6.1: + resolution: {integrity: sha512-6NGwvttY1+HAFii08VYiEKI6ETPAFbpLntpm2M/MogEsAFWdZV74UNT+2M4bmqX90cIQhjlpBSP+tO+CfB0uww==} engines: {node: '>=16.0.0'} html-entities@2.5.2: @@ -4476,8 +4476,8 @@ packages: peerDependencies: tailwindcss: '>=3.0.0 || insiders' - tailwindcss@3.4.10: - resolution: {integrity: sha512-KWZkVPm7yJRhdu4SRSl9d4AK2wM3a50UsvgHZO7xY77NQr2V+fIrEuoDGQcbvswWvFGbS2f6e+jC/6WJm1Dl0w==} + tailwindcss@3.4.11: + resolution: {integrity: sha512-qhEuBcLemjSJk5ajccN9xJFtM/h0AVCPaA6C92jNP+M2J8kX+eMJHI7R2HFKUvvAsMpcfLILMCFYSeDwpMmlUg==} engines: {node: '>=14.0.0'} hasBin: true @@ -4575,8 +4575,8 @@ packages: tslib@2.7.0: resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} - tsx@4.19.0: - resolution: {integrity: sha512-bV30kM7bsLZKZIOCHeMNVMJ32/LuJzLVajkQI/qf92J2Qr08ueLQvW00PUZGiuLPP760UINwupgUj8qrSCPUKg==} + tsx@4.19.1: + resolution: {integrity: sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==} engines: {node: '>=18.0.0'} hasBin: true @@ -4604,8 +4604,8 @@ packages: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} - typescript@5.5.4: - resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} + typescript@5.6.2: + resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} engines: {node: '>=14.17'} hasBin: true @@ -4679,8 +4679,8 @@ packages: engines: {node: ^18.0.0 || >=20.0.0} hasBin: true - vite@5.4.3: - resolution: {integrity: sha512-IH+nl64eq9lJjFqU+/yrRnrHPVTlgy42/+IzbOdaFDVlyLgI/wDlf+FCobXLX1cT0X5+7LMyH1mIy2xJdLfo8Q==} + vite@5.4.4: + resolution: {integrity: sha512-RHFCkULitycHVTtelJ6jQLd+KSAAzOgEYorV32R2q++M6COBjKJR6BxqClwp5sf0XaBDjVMuJ9wnNfyAJwjMkA==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -4835,8 +4835,8 @@ packages: zimmerframe@1.1.2: resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==} - zod-to-json-schema@3.23.2: - resolution: {integrity: sha512-uSt90Gzc/tUfyNqxnjlfBs8W6WSGpNBv0rVsNxP/BVSMHMKGdthPYff4xtCHYloJGM0CFxFsb3NbC0eqPhfImw==} + zod-to-json-schema@3.23.3: + resolution: {integrity: sha512-TYWChTxKQbRJp5ST22o/Irt9KC5nj7CdBKYB/AosCRdj/wxEMvv4NNaj9XVUHDOIp53ZxArGhnw5HMZziPFjog==} peerDependencies: zod: ^3.23.3 @@ -5489,7 +5489,7 @@ snapshots: '@floating-ui/utils@0.2.7': {} - '@fontsource/fira-mono@5.0.15': {} + '@fontsource/fira-mono@5.1.0': {} '@gcornut/valibot-json-schema@0.31.0': dependencies: @@ -5508,20 +5508,20 @@ snapshots: '@hapi/hoek': 9.3.0 optional: true - '@hono/swagger-ui@0.4.1(hono@4.5.11)': + '@hono/swagger-ui@0.4.1(hono@4.6.1)': dependencies: - hono: 4.5.11 + hono: 4.6.1 - '@hono/zod-openapi@0.15.3(hono@4.5.11)(zod@3.23.8)': + '@hono/zod-openapi@0.15.3(hono@4.6.1)(zod@3.23.8)': dependencies: '@asteasolutions/zod-to-openapi': 7.1.1(zod@3.23.8) - '@hono/zod-validator': 0.2.2(hono@4.5.11)(zod@3.23.8) - hono: 4.5.11 + '@hono/zod-validator': 0.2.2(hono@4.6.1)(zod@3.23.8) + hono: 4.6.1 zod: 3.23.8 - '@hono/zod-validator@0.2.2(hono@4.5.11)(zod@3.23.8)': + '@hono/zod-validator@0.2.2(hono@4.6.1)(zod@3.23.8)': dependencies: - hono: 4.5.11 + hono: 4.6.1 zod: 3.23.8 '@humanwhocodes/config-array@0.11.14': @@ -5664,9 +5664,9 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@lucia-auth/adapter-drizzle@1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.8)(pg@8.12.0)(postgres@3.4.4))(lucia@3.2.0)': + '@lucia-auth/adapter-drizzle@1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4))(lucia@3.2.0)': dependencies: - drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.8)(pg@8.12.0)(postgres@3.4.4) + drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4) lucia: 3.2.0 '@lukeed/csprng@1.1.0': {} @@ -6063,41 +6063,41 @@ snapshots: '@sodaru/yup-to-json-schema@2.0.1': optional: true - '@sveltejs/adapter-auto@3.2.4(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))': + '@sveltejs/adapter-auto@3.2.4(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))': dependencies: - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) import-meta-resolve: 4.1.0 - '@sveltejs/adapter-node@5.2.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))': + '@sveltejs/adapter-node@5.2.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))': dependencies: '@rollup/plugin-commonjs': 26.0.1(rollup@4.21.2) '@rollup/plugin-json': 6.1.0(rollup@4.21.2) '@rollup/plugin-node-resolve': 15.2.3(rollup@4.21.2) - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) rollup: 4.21.2 - '@sveltejs/adapter-vercel@5.4.3(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))': + '@sveltejs/adapter-vercel@5.4.3(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))': dependencies: - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) '@vercel/nft': 0.27.4 esbuild: 0.21.5 transitivePeerDependencies: - encoding - supports-color - '@sveltejs/enhanced-img@0.3.4(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0))': + '@sveltejs/enhanced-img@0.3.4(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))': dependencies: magic-string: 0.30.11 svelte: 5.0.0-next.175 svelte-parse-markup: 0.1.5(svelte@5.0.0-next.175) - vite: 5.4.3(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) vite-imagetools: 7.0.4(rollup@4.21.2) transitivePeerDependencies: - rollup - '@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0))': + '@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.0.0 @@ -6111,28 +6111,28 @@ snapshots: sirv: 2.0.4 svelte: 5.0.0-next.175 tiny-glob: 0.2.9 - vite: 5.4.3(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) - '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0))': + '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) debug: 4.3.6 svelte: 5.0.0-next.175 - vite: 5.4.3(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0))': + '@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) debug: 4.3.6 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.11 svelte: 5.0.0-next.175 svelte-hmr: 0.16.0(svelte@5.0.0-next.175) - vite: 5.4.3(@types/node@20.16.5)(sass@1.78.0) - vitefu: 0.2.5(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)) + vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) + vitefu: 0.2.5(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) transitivePeerDependencies: - supports-color @@ -6172,7 +6172,7 @@ snapshots: pg-protocol: 1.6.1 pg-types: 4.0.2 - '@types/pg@8.11.8': + '@types/pg@8.11.9': dependencies: '@types/node': 20.16.5 pg-protocol: 1.6.1 @@ -6185,34 +6185,34 @@ snapshots: '@types/validator@13.12.1': optional: true - '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4)': + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0)(typescript@5.6.2)': dependencies: '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + '@typescript-eslint/parser': 7.18.0(eslint@8.57.0)(typescript@5.6.2) '@typescript-eslint/scope-manager': 7.18.0 - '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.0)(typescript@5.6.2) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.6.2) '@typescript-eslint/visitor-keys': 7.18.0 eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.5.4) + ts-api-utils: 1.3.0(typescript@5.6.2) optionalDependencies: - typescript: 5.5.4 + typescript: 5.6.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4)': + '@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.6.2)': dependencies: '@typescript-eslint/scope-manager': 7.18.0 '@typescript-eslint/types': 7.18.0 - '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4) + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.2) '@typescript-eslint/visitor-keys': 7.18.0 debug: 4.3.6 eslint: 8.57.0 optionalDependencies: - typescript: 5.5.4 + typescript: 5.6.2 transitivePeerDependencies: - supports-color @@ -6221,21 +6221,21 @@ snapshots: '@typescript-eslint/types': 7.18.0 '@typescript-eslint/visitor-keys': 7.18.0 - '@typescript-eslint/type-utils@7.18.0(eslint@8.57.0)(typescript@5.5.4)': + '@typescript-eslint/type-utils@7.18.0(eslint@8.57.0)(typescript@5.6.2)': dependencies: - '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4) - '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.2) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.6.2) debug: 4.3.6 eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.5.4) + ts-api-utils: 1.3.0(typescript@5.6.2) optionalDependencies: - typescript: 5.5.4 + typescript: 5.6.2 transitivePeerDependencies: - supports-color '@typescript-eslint/types@7.18.0': {} - '@typescript-eslint/typescript-estree@7.18.0(typescript@5.5.4)': + '@typescript-eslint/typescript-estree@7.18.0(typescript@5.6.2)': dependencies: '@typescript-eslint/types': 7.18.0 '@typescript-eslint/visitor-keys': 7.18.0 @@ -6244,18 +6244,18 @@ snapshots: is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.5.4) + ts-api-utils: 1.3.0(typescript@5.6.2) optionalDependencies: - typescript: 5.5.4 + typescript: 5.6.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@7.18.0(eslint@8.57.0)(typescript@5.5.4)': + '@typescript-eslint/utils@7.18.0(eslint@8.57.0)(typescript@5.6.2)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@typescript-eslint/scope-manager': 7.18.0 '@typescript-eslint/types': 7.18.0 - '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4) + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.2) eslint: 8.57.0 transitivePeerDependencies: - supports-color @@ -6508,7 +6508,7 @@ snapshots: builtin-modules@3.3.0: {} - bullmq@5.12.14: + bullmq@5.13.0: dependencies: cron-parser: 4.9.0 ioredis: 5.4.1 @@ -6769,16 +6769,16 @@ snapshots: transitivePeerDependencies: - supports-color - drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.8)(pg@8.12.0)(postgres@3.4.4): + drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4): optionalDependencies: '@neondatabase/serverless': 0.9.5 - '@types/pg': 8.11.8 + '@types/pg': 8.11.9 pg: 8.12.0 postgres: 3.4.4 - drizzle-zod@0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.8)(pg@8.12.0)(postgres@3.4.4))(zod@3.23.8): + drizzle-zod@0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4))(zod@3.23.8): dependencies: - drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.8)(pg@8.12.0)(postgres@3.4.4) + drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4) zod: 3.23.8 eastasianwidth@0.2.0: {} @@ -6936,7 +6936,7 @@ snapshots: dependencies: eslint: 8.57.0 - eslint-plugin-svelte@2.36.0-next.13(eslint@8.57.0)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.5.4)): + eslint-plugin-svelte@2.36.0-next.13(eslint@8.57.0)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@jridgewell/sourcemap-codec': 1.5.0 @@ -6946,7 +6946,7 @@ snapshots: esutils: 2.0.3 known-css-properties: 0.30.0 postcss: 8.4.45 - postcss-load-config: 3.1.4(postcss@8.4.45)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.5.4)) + postcss-load-config: 3.1.4(postcss@8.4.45)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) postcss-safe-parser: 6.0.0(postcss@8.4.45) postcss-selector-parser: 6.1.2 semver: 7.6.3 @@ -7170,11 +7170,11 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)): + formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)): dependencies: nanoid: 5.0.7 svelte: 5.0.0-next.175 - sveltekit-superforms: 2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175) + sveltekit-superforms: 2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175) forwarded@0.2.0: {} @@ -7307,11 +7307,11 @@ snapshots: hex-rgb@4.3.0: {} - hono-rate-limiter@0.4.0(hono@4.5.11): + hono-rate-limiter@0.4.0(hono@4.6.1): dependencies: - hono: 4.5.11 + hono: 4.6.1 - hono@4.5.11: {} + hono@4.6.1: {} html-entities@2.5.2: {} @@ -8014,30 +8014,30 @@ snapshots: '@csstools/utilities': 1.0.0(postcss@8.4.45) postcss: 8.4.45 - postcss-load-config@3.1.4(postcss@8.4.45)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.5.4)): + postcss-load-config@3.1.4(postcss@8.4.45)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): dependencies: lilconfig: 2.1.0 yaml: 1.10.2 optionalDependencies: postcss: 8.4.45 - ts-node: 10.9.2(@types/node@20.16.5)(typescript@5.5.4) + ts-node: 10.9.2(@types/node@20.16.5)(typescript@5.6.2) - postcss-load-config@4.0.2(postcss@8.4.45)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.5.4)): + postcss-load-config@4.0.2(postcss@8.4.45)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): dependencies: lilconfig: 3.1.2 yaml: 2.5.1 optionalDependencies: postcss: 8.4.45 - ts-node: 10.9.2(@types/node@20.16.5)(typescript@5.5.4) + ts-node: 10.9.2(@types/node@20.16.5)(typescript@5.6.2) - postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.0): + postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1): dependencies: lilconfig: 3.1.2 yaml: 2.5.1 optionalDependencies: jiti: 1.21.6 postcss: 8.4.45 - tsx: 4.19.0 + tsx: 4.19.1 postcss-logical@7.0.1(postcss@8.4.45): dependencies: @@ -8386,9 +8386,9 @@ snapshots: postcss-value-parser: 4.2.0 yoga-wasm-web: 0.3.3 - schema-dts@1.1.2(typescript@5.5.4): + schema-dts@1.1.2(typescript@5.6.2): dependencies: - typescript: 5.5.4 + typescript: 5.6.2 semver@6.3.1: {} @@ -8578,15 +8578,15 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-check@3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.0))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175): + svelte-check@3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175): dependencies: '@jridgewell/trace-mapping': 0.3.25 chokidar: 3.6.0 picocolors: 1.1.0 sade: 1.8.1 svelte: 5.0.0-next.175 - svelte-preprocess: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.0))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.5.4) - typescript: 5.5.4 + svelte-preprocess: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2) + typescript: 5.6.2 transitivePeerDependencies: - '@babel/core' - coffeescript @@ -8630,9 +8630,9 @@ snapshots: svelte-lazy-loader@1.0.0: {} - svelte-meta-tags@3.1.4(svelte@5.0.0-next.175)(typescript@5.5.4): + svelte-meta-tags@3.1.4(svelte@5.0.0-next.175)(typescript@5.6.2): dependencies: - schema-dts: 1.1.2(typescript@5.5.4) + schema-dts: 1.1.2(typescript@5.6.2) svelte: 5.0.0-next.175 transitivePeerDependencies: - typescript @@ -8641,7 +8641,7 @@ snapshots: dependencies: svelte: 5.0.0-next.175 - svelte-preprocess@5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.0))(postcss@8.4.45)(sass@1.78.0)(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.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2): dependencies: '@types/pug': 2.0.10 detect-indent: 6.1.0 @@ -8651,18 +8651,18 @@ snapshots: svelte: 5.0.0-next.175 optionalDependencies: postcss: 8.4.45 - postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.0) + postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1) sass: 1.78.0 - typescript: 5.5.4 + typescript: 5.6.2 - svelte-preprocess@6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.0))(postcss@8.4.45)(sass@1.78.0)(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.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2): dependencies: svelte: 5.0.0-next.175 optionalDependencies: postcss: 8.4.45 - postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.0) + postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1) sass: 1.78.0 - typescript: 5.5.4 + typescript: 5.6.2 svelte-render@2.0.1(svelte@5.0.0-next.175): dependencies: @@ -8715,19 +8715,19 @@ snapshots: magic-string: 0.30.11 zimmerframe: 1.1.2 - sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175): + sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) svelte: 5.0.0-next.175 - sveltekit-rate-limiter@0.5.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0))): + sveltekit-rate-limiter@0.5.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))): dependencies: '@isaacs/ttlcache': 1.4.1 - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) - sveltekit-superforms@2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175): + sveltekit-superforms@2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) devalue: 5.0.0 just-clone: 6.2.0 memoize-weak: 1.0.2 @@ -8746,22 +8746,22 @@ snapshots: valibot: 0.35.0 yup: 1.4.0 zod: 3.23.8 - zod-to-json-schema: 3.23.2(zod@3.23.8) + zod-to-json-schema: 3.23.3(zod@3.23.8) tabbable@6.2.0: {} tailwind-merge@2.5.2: {} - tailwind-variants@0.2.1(tailwindcss@3.4.10(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.5.4))): + tailwind-variants@0.2.1(tailwindcss@3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))): dependencies: tailwind-merge: 2.5.2 - tailwindcss: 3.4.10(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.5.4)) + tailwindcss: 3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) - tailwindcss-animate@1.0.7(tailwindcss@3.4.10(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.5.4))): + tailwindcss-animate@1.0.7(tailwindcss@3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))): dependencies: - tailwindcss: 3.4.10(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.5.4)) + tailwindcss: 3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) - tailwindcss@3.4.10(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.5.4)): + tailwindcss@3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -8780,7 +8780,7 @@ snapshots: postcss: 8.4.45 postcss-import: 15.1.0(postcss@8.4.45) postcss-js: 4.0.1(postcss@8.4.45) - postcss-load-config: 4.0.2(postcss@8.4.45)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.5.4)) + postcss-load-config: 4.0.2(postcss@8.4.45)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) postcss-nested: 6.2.0(postcss@8.4.45) postcss-selector-parser: 6.1.2 resolve: 1.22.8 @@ -8839,15 +8839,15 @@ snapshots: ts-algebra@2.0.0: optional: true - ts-api-utils@1.3.0(typescript@5.5.4): + ts-api-utils@1.3.0(typescript@5.6.2): dependencies: - typescript: 5.5.4 + typescript: 5.6.2 ts-deepmerge@7.0.1: {} ts-interface-checker@0.1.13: {} - ts-node@10.9.2(@types/node@20.16.5)(typescript@5.5.4): + ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 @@ -8861,7 +8861,7 @@ snapshots: create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 5.5.4 + typescript: 5.6.2 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 @@ -8874,7 +8874,7 @@ snapshots: tslib@2.7.0: {} - tsx@4.19.0: + tsx@4.19.1: dependencies: esbuild: 0.23.1 get-tsconfig: 4.8.0 @@ -8901,7 +8901,7 @@ snapshots: media-typer: 0.3.0 mime-types: 2.1.35 - typescript@5.5.4: {} + typescript@5.6.2: {} ufo@1.5.4: {} @@ -8964,7 +8964,7 @@ snapshots: debug: 4.3.6 pathe: 1.1.2 picocolors: 1.1.0 - vite: 5.4.3(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) transitivePeerDependencies: - '@types/node' - less @@ -8976,7 +8976,7 @@ snapshots: - supports-color - terser - vite@5.4.3(@types/node@20.16.5)(sass@1.78.0): + vite@5.4.4(@types/node@20.16.5)(sass@1.78.0): dependencies: esbuild: 0.21.5 postcss: 8.4.45 @@ -8986,9 +8986,9 @@ snapshots: fsevents: 2.3.3 sass: 1.78.0 - vitefu@0.2.5(vite@5.4.3(@types/node@20.16.5)(sass@1.78.0)): + vitefu@0.2.5(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)): optionalDependencies: - vite: 5.4.3(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) vitest@1.6.0(@types/node@20.16.5)(sass@1.78.0): dependencies: @@ -9009,7 +9009,7 @@ snapshots: strip-literal: 2.1.0 tinybench: 2.9.0 tinypool: 0.8.4 - vite: 5.4.3(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) vite-node: 1.6.0(@types/node@20.16.5)(sass@1.78.0) why-is-node-running: 2.3.0 optionalDependencies: @@ -9117,7 +9117,7 @@ snapshots: zimmerframe@1.1.2: {} - zod-to-json-schema@3.23.2(zod@3.23.8): + zod-to-json-schema@3.23.3(zod@3.23.8): dependencies: zod: 3.23.8 diff --git a/src/lib/server/api/repositories/credentials.repository.ts b/src/lib/server/api/repositories/credentials.repository.ts index 11f56c5..0671a40 100644 --- a/src/lib/server/api/repositories/credentials.repository.ts +++ b/src/lib/server/api/repositories/credentials.repository.ts @@ -7,6 +7,7 @@ import { takeFirstOrThrow } from '../common/utils/repository' export type CreateCredentials = InferInsertModel export type UpdateCredentials = Partial +export type DeleteCredentials = Pick @injectable() export class CredentialsRepository { diff --git a/src/lib/server/api/tests/hashing.service.test.ts b/src/lib/server/api/tests/hashing.service.test.ts index 94c7f89..d7fe080 100644 --- a/src/lib/server/api/tests/hashing.service.test.ts +++ b/src/lib/server/api/tests/hashing.service.test.ts @@ -1,32 +1,38 @@ -import 'reflect-metadata'; -import { container } from 'tsyringe'; -import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; -import { HashingService } from '../services/hashing.service'; +import 'reflect-metadata' +import { container } from 'tsyringe' +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' +import { HashingService } from '../services/hashing.service' describe('HashingService', () => { - let service: HashingService; + let service: HashingService beforeAll(() => { - service = container.resolve(HashingService); - }); + service = container.resolve(HashingService) + }) afterAll(() => { vi.resetAllMocks() - }); + }) describe('Create Hash', () => { it('should create a hash', async () => { - const hash = await service.hash('111'); - expect(hash).not.toBeUndefined(); - expect(hash).not.toBeNull(); - }); + const hash = await service.hash('111') + expect(hash).not.toBeUndefined() + expect(hash).not.toBeNull() + }) }) describe('Verify Hash', () => { it('should verify a hash', async () => { - const hash = await service.hash('111'); - const verifiable = await service.verify(hash, '111'); - expect(verifiable).toBeTruthy(); - }); + const hash = await service.hash('111') + const verifiable = await service.verify(hash, '111') + expect(verifiable).toBeTruthy() + }) + + it('should not verify a hash', async () => { + const hash = await service.hash('111') + const verifiable = await service.verify(hash, '222') + expect(verifiable).toBeFalsy() + }) }) -}) \ No newline at end of file +}) diff --git a/src/lib/server/api/tests/iam.service.test.ts b/src/lib/server/api/tests/iam.service.test.ts new file mode 100644 index 0000000..96d3174 --- /dev/null +++ b/src/lib/server/api/tests/iam.service.test.ts @@ -0,0 +1,105 @@ +import 'reflect-metadata' +import { IamService } from '$lib/server/api/services/iam.service' +import { LuciaService } from '$lib/server/api/services/lucia.service' +import { UsersService } from '$lib/server/api/services/users.service' +import { container } from 'tsyringe' +import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' + +describe('IamService', () => { + let service: IamService + const luciaService = vi.mocked(LuciaService.prototype) + const userService = vi.mocked(UsersService.prototype) + + beforeAll(() => { + service = container + .register(LuciaService, { useValue: luciaService }) + .register(UsersService, { useValue: userService }) + .resolve(IamService) + }) + + beforeEach(() => { + vi.resetAllMocks() + }) + + afterAll(() => { + vi.resetAllMocks() + }) + + describe('Update Profile', () => { + it('should resolve', async () => { + const timeStampDate = new Date() + userService.findOneById = vi.fn().mockResolvedValueOnce({ + id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', + cuid: 'ciglo1j8q0000t9j4xq8d6p5e', + first_name: 'test', + last_name: 'test', + email: 'test@example.com', + username: 'test', + verified: false, + receive_email: false, + mfa_enabled: false, + theme: 'system', + createdAt: timeStampDate, + updatedAt: timeStampDate, + }) + userService.findOneByUsername = vi.fn().mockResolvedValue(undefined) + userService.updateUser = vi.fn().mockResolvedValue({ + id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', + cuid: 'ciglo1j8q0000t9j4xq8d6p5e', + first_name: 'test', + last_name: 'test', + email: 'test@example.com', + username: 'test', + verified: false, + receive_email: false, + mfa_enabled: false, + theme: 'system', + createdAt: timeStampDate, + updatedAt: timeStampDate, + }) + + const spy_userService_findOneById = vi.spyOn(userService, 'findOneById') + const spy_userService_findOneByUsername = vi.spyOn(userService, 'findOneByUsername') + const spy_userService_updateUser = vi.spyOn(userService, 'updateUser') + await expect( + service.updateProfile('3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', { + username: 'test', + }), + ).resolves.toEqual({ + id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', + cuid: 'ciglo1j8q0000t9j4xq8d6p5e', + first_name: 'test', + last_name: 'test', + email: 'test@example.com', + username: 'test', + verified: false, + receive_email: false, + mfa_enabled: false, + theme: 'system', + createdAt: timeStampDate, + updatedAt: timeStampDate, + }) + expect(spy_userService_findOneById).toBeCalledTimes(1) + expect(spy_userService_findOneByUsername).toBeCalledTimes(1) + expect(spy_userService_updateUser).toBeCalledTimes(1) + }) + + it('should error on no user found', async () => { + userService.findOneById = vi.fn().mockResolvedValueOnce(undefined) + + const spy_userService_findOneById = vi.spyOn(userService, 'findOneById') + const spy_userService_findOneByUsername = vi.spyOn(userService, 'findOneByUsername') + const spy_userService_updateUser = vi.spyOn(userService, 'updateUser') + await expect( + service.updateProfile('3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', { + username: 'test', + }), + ).resolves.toEqual({ + error: 'User not found', + }) + expect(spy_userService_findOneById).toBeCalledTimes(1) + expect(spy_userService_findOneByUsername).toBeCalledTimes(0) + expect(spy_userService_updateUser).toBeCalledTimes(0) + }) + }) +}) diff --git a/src/lib/server/api/tests/tokens.service.test.ts b/src/lib/server/api/tests/tokens.service.test.ts index 5c0e34e..ad0aa3b 100644 --- a/src/lib/server/api/tests/tokens.service.test.ts +++ b/src/lib/server/api/tests/tokens.service.test.ts @@ -1,49 +1,47 @@ -import 'reflect-metadata'; -import { container } from 'tsyringe'; -import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; -import { TokensService } from '../services/tokens.service'; -import { HashingService } from '../services/hashing.service'; -import { Argon2id } from 'oslo/password'; +import 'reflect-metadata' +import { Argon2id } from 'oslo/password' +import { container } from 'tsyringe' +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' +import { HashingService } from '../services/hashing.service' +import { TokensService } from '../services/tokens.service' describe('TokensService', () => { - let service: TokensService; - const hashingService = vi.mocked(HashingService.prototype); + let service: TokensService + const hashingService = vi.mocked(HashingService.prototype) beforeAll(() => { - service = container - .register(HashingService, { useValue: hashingService }) - .resolve(TokensService); - }); + service = container.register(HashingService, { useValue: hashingService }).resolve(TokensService) + }) afterAll(() => { vi.resetAllMocks() - }); + }) describe('Generate Token', () => { - const hashedPassword = new Argon2id().hash('111'); + const hashedPassword = new Argon2id().hash('111') - hashingService.hash = vi.fn().mockResolvedValue(hashedPassword); - hashingService.verify = vi.fn().mockResolvedValue(true); + hashingService.hash = vi.fn().mockResolvedValue(hashedPassword) + hashingService.verify = vi.fn().mockResolvedValue(true) - const spy_hashingService_hash = vi.spyOn(hashingService, 'hash'); - const spy_hashingService_verify = vi.spyOn(hashingService, 'verify'); + const spy_hashingService_hash = vi.spyOn(hashingService, 'hash') + const spy_hashingService_verify = vi.spyOn(hashingService, 'verify') it('should resolve', async () => { - await expect(service.createHashedToken('111')).resolves.string + expect(service.createHashedToken('111')).resolves.string }) it('should generate a token that is verifiable', async () => { - const token = await service.createHashedToken('111'); - expect(token).not.toBeUndefined(); - expect(token).not.toBeNull(); - const verifiable = await service.verifyHashedToken(token, '111'); - expect(verifiable).toBeTruthy(); - }); + const token = await service.createHashedToken('111') + expect(token).not.toBeUndefined() + expect(token).not.toBeNull() + const verifiable = await service.verifyHashedToken(token, '111') + expect(verifiable).toBeTruthy() + }) it('should generate a hashed token', async () => { - expect(spy_hashingService_hash).toHaveBeenCalledTimes(2); + expect(spy_hashingService_hash).toHaveBeenCalledTimes(2) }) it('should verify a hashed token', async () => { - expect(spy_hashingService_verify).toHaveBeenCalledTimes(1); + expect(spy_hashingService_verify).toHaveBeenCalledTimes(1) }) - }); -}); \ No newline at end of file + }) +}) diff --git a/src/lib/server/api/tests/users.service.test.ts b/src/lib/server/api/tests/users.service.test.ts index fb40e5f..ec551a2 100644 --- a/src/lib/server/api/tests/users.service.test.ts +++ b/src/lib/server/api/tests/users.service.test.ts @@ -1,44 +1,47 @@ -import 'reflect-metadata'; -import { container } from 'tsyringe'; -import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; -import { UsersService } from '../services/users.service'; -import { CredentialsRepository } from '../repositories/credentials.repository'; -import { TokensService } from '../services/tokens.service'; -import { UserRolesService } from '../services/user_roles.service'; -import { UsersRepository } from '../repositories/users.repository'; -import { Argon2id } from 'oslo/password'; -import { WishlistsService } from '../services/wishlists.service'; -import { CollectionsService } from '../services/collections.service'; +import 'reflect-metadata' +import { CredentialsType } from '$lib/server/api/databases/tables' +import { Argon2id } from 'oslo/password' +import { container } from 'tsyringe' +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' +import { CredentialsRepository } from '../repositories/credentials.repository' +import { UsersRepository } from '../repositories/users.repository' +import { CollectionsService } from '../services/collections.service' +import { TokensService } from '../services/tokens.service' +import { UserRolesService } from '../services/user_roles.service' +import { UsersService } from '../services/users.service' +import { WishlistsService } from '../services/wishlists.service' describe('UsersService', () => { - let service: UsersService; - const credentialsRepository = vi.mocked(CredentialsRepository.prototype); - const tokensService = vi.mocked(TokensService.prototype); - const usersRepository = vi.mocked(UsersRepository.prototype); - const userRolesService = vi.mocked(UserRolesService.prototype); - const wishlistsService = vi.mocked(WishlistsService.prototype); - const collectionsService = vi.mocked(CollectionsService.prototype); + let service: UsersService + const credentialsRepository = vi.mocked(CredentialsRepository.prototype) + const tokensService = vi.mocked(TokensService.prototype) + const usersRepository = vi.mocked(UsersRepository.prototype) + const userRolesService = vi.mocked(UserRolesService.prototype) + const wishlistsService = vi.mocked(WishlistsService.prototype) + const collectionsService = vi.mocked(CollectionsService.prototype) - beforeAll(() => { - service = container - .register(CredentialsRepository, { useValue: credentialsRepository }) + beforeAll(() => { + service = container + .register(CredentialsRepository, { useValue: credentialsRepository }) .register(TokensService, { useValue: tokensService }) .register(UsersRepository, { useValue: usersRepository }) .register(UserRolesService, { useValue: userRolesService }) .register(WishlistsService, { useValue: wishlistsService }) .register(CollectionsService, { useValue: collectionsService }) - .resolve(UsersService); - }); + .resolve(UsersService) + }) - afterAll(() => { - vi.resetAllMocks() - }) + afterAll(() => { + vi.resetAllMocks() + }) describe('Create User', () => { - const hashedPassword = new Argon2id().hash('111'); - tokensService.createHashedToken = vi.fn().mockResolvedValue(hashedPassword) + const date = new Date() - usersRepository.create = vi.fn().mockResolvedValue({ + const hashedPassword = new Argon2id().hash('111') + tokensService.createHashedToken = vi.fn().mockResolvedValue(hashedPassword) + + usersRepository.create = vi.fn().mockResolvedValue({ id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', cuid: 'ciglo1j8q0000t9j4xq8d6p5e', first_name: 'test', @@ -47,17 +50,18 @@ describe('UsersService', () => { username: 'test', verified: false, receive_email: false, + mfa_enabled: false, theme: 'system', - createdAt: new Date(), - updatedAt: new Date() - } satisfies Awaited>) + createdAt: date, + updatedAt: date, + } satisfies Awaited>) credentialsRepository.create = vi.fn().mockResolvedValue({ id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', user_id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - type: 'PASSWORD', - secret_data: hashedPassword - }) + type: CredentialsType.PASSWORD, + secret_data: hashedPassword, + }) satisfies Awaited> userRolesService.addRoleToUser = vi.fn().mockResolvedValue(undefined) @@ -65,40 +69,121 @@ describe('UsersService', () => { collectionsService.createEmptyNoName = vi.fn().mockResolvedValue(undefined) - const spy_tokensService_createHashToken = vi.spyOn(tokensService, 'createHashedToken'); - const spy_usersRepository_create = vi.spyOn(usersRepository, 'create'); - const spy_credentialsRepository_create = vi.spyOn(credentialsRepository, 'create'); - const spy_userRolesService_addRoleToUser = vi.spyOn(userRolesService, 'addRoleToUser'); - const spy_wishlistsService_createEmptyNoName = vi.spyOn(wishlistsService, 'createEmptyNoName'); - const spy_collectionsService_createEmptyNoName = vi.spyOn(collectionsService, 'createEmptyNoName'); + const spy_tokensService_createHashToken = vi.spyOn(tokensService, 'createHashedToken') + const spy_usersRepository_create = vi.spyOn(usersRepository, 'create') + const spy_credentialsRepository_create = vi.spyOn(credentialsRepository, 'create') + const spy_userRolesService_addRoleToUser = vi.spyOn(userRolesService, 'addRoleToUser') + const spy_wishlistsService_createEmptyNoName = vi.spyOn(wishlistsService, 'createEmptyNoName') + const spy_collectionsService_createEmptyNoName = vi.spyOn(collectionsService, 'createEmptyNoName') - it('should resolve', async () => { - await expect(service.create({ - firstName: 'test', - lastName: 'test', + it('should resolve', async () => { + await expect( + service.create({ + firstName: 'test', + lastName: 'test', + email: 'test@example.com', + username: 'test', + password: '111', + confirm_password: '111', + }), + ).resolves.toEqual({ + id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', + cuid: 'ciglo1j8q0000t9j4xq8d6p5e', + first_name: 'test', + last_name: 'test', email: 'test@example.com', username: 'test', - password: '111', - confirm_password: '111' - })).resolves.not.toThrow() - }) - it('should generate a hashed token', async () => { - expect(spy_tokensService_createHashToken).toBeCalledTimes(1) - }) - it('should create a new user', async () => { - expect(spy_usersRepository_create).toHaveBeenCalledTimes(1) - }) - it('should create a new credential', async () => { - expect(spy_credentialsRepository_create).toBeCalledTimes(1) + verified: false, + receive_email: false, + mfa_enabled: false, + theme: 'system', + createdAt: date, + updatedAt: date, + }) }) - it('should add role to user', async () => { - expect(spy_userRolesService_addRoleToUser).toBeCalledTimes(1) + // it('should generate a hashed token', async () => { + // expect(spy_tokensService_createHashToken).toBeCalledTimes(1) + // }) + // it('should create a new user', async () => { + // expect(spy_usersRepository_create).toBeCalledTimes(1) + // }) + // it('should create a new credential', async () => { + // expect(spy_credentialsRepository_create).toBeCalledTimes(1) + // }) + // it('should add role to user', async () => { + // expect(spy_userRolesService_addRoleToUser).toBeCalledTimes(1) + // }) + // it('should create a new wishlist', async () => { + // expect(spy_wishlistsService_createEmptyNoName).toBeCalledTimes(1) + // }) + // it('should create a new collection', async () => { + // expect(spy_collectionsService_createEmptyNoName).toBeCalledTimes(1) + // }) + }) + describe('Update User Password Exiting Credentials', () => { + const hashedPassword = new Argon2id().hash('111') + tokensService.createHashedToken = vi.fn().mockResolvedValue(hashedPassword) satisfies Awaited> + credentialsRepository.update = vi.fn().mockResolvedValue({ + id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', + user_id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', + type: 'PASSWORD', + secret_data: hashedPassword, + }) satisfies Awaited> + credentialsRepository.findPasswordCredentialsByUserId = vi.fn().mockResolvedValue({ + id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', + user_id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', + type: 'PASSWORD', + secret_data: hashedPassword, + }) satisfies Awaited> + + const spy_tokensService_createHashToken = vi.spyOn(tokensService, 'createHashedToken') + const spy_credentialsRepository_findPasswordCredentialsByUserId = vi.spyOn(credentialsRepository, 'findPasswordCredentialsByUserId') + const spy_credentialsRepository_update = vi.spyOn(credentialsRepository, 'update') + + it('should resolve', async () => { + await expect(service.updatePassword('3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', '111')).resolves.toBeUndefined() }) - it('should create a new wishlist', async () => { - expect(spy_wishlistsService_createEmptyNoName).toBeCalledTimes(1) + console.log(spy_tokensService_createHashToken.mock.calls) + it('should generate a hashed token', async () => { + expect(spy_tokensService_createHashToken).toBeCalledTimes(1) }) - it('should create a new collection', async () => { - expect(spy_collectionsService_createEmptyNoName).toBeCalledTimes(1) + console.log(spy_credentialsRepository_findPasswordCredentialsByUserId.mock.calls) + it('should call find password credentials by user id', async () => { + expect(spy_credentialsRepository_findPasswordCredentialsByUserId).toBeCalledTimes(1) }) - }) -}); + console.log(spy_credentialsRepository_update.mock.calls) + it('should update the credential when user has credential', async () => { + expect(spy_credentialsRepository_update).toBeCalledTimes(1) + }) + }) + describe('Update User Password No Existing Credentials', () => { + const hashedPassword = new Argon2id().hash('111') + tokensService.createHashedToken = vi.fn().mockResolvedValue(hashedPassword) satisfies Awaited> + credentialsRepository.findPasswordCredentialsByUserId = vi.fn().mockResolvedValue(null) satisfies Awaited< + ReturnType + > + credentialsRepository.create = vi.fn().mockResolvedValue({ + id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', + user_id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', + type: 'PASSWORD', + secret_data: hashedPassword, + }) satisfies Awaited> + + const spy_tokensService_createHashToken = vi.spyOn(tokensService, 'createHashedToken') + const spy_credentialsRepository_create = vi.spyOn(credentialsRepository, 'create') + const spy_credentialsRepository_findPasswordCredentialsByUserId = vi.spyOn(credentialsRepository, 'findPasswordCredentialsByUserId') + + it('should resolve with no current credential for user', async () => { + await expect(service.updatePassword('3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', '111')).resolves.not.toThrow() + }) + it('should generate a hashed token', async () => { + expect(spy_tokensService_createHashToken).toBeCalledTimes(1) + }) + it('should call find password credentials by user id', async () => { + expect(spy_credentialsRepository_findPasswordCredentialsByUserId).toBeCalledTimes(1) + }) + it('should create a new credential when user has no credential', async () => { + expect(spy_credentialsRepository_create).toHaveBeenCalledTimes(1) + }) + }) +}) diff --git a/src/routes/(app)/(protected)/collections/[cuid]/+page.server.ts b/src/routes/(app)/(protected)/collections/[cuid]/+page.server.ts index c394fa6..488fbb1 100644 --- a/src/routes/(app)/(protected)/collections/[cuid]/+page.server.ts +++ b/src/routes/(app)/(protected)/collections/[cuid]/+page.server.ts @@ -1,13 +1,12 @@ import { notSignedInMessage } from '$lib/flashMessages.js' +import { collection_items, collections, gamesTable } from '$lib/server/api/databases/tables' import { db } from '$lib/server/api/packages/drizzle' -import { userNotAuthenticated } from '$lib/server/auth-utils' import { modifyListGameSchema } from '$lib/validations/zod-schemas' -import { type Actions, error, fail } from '@sveltejs/kit' +import { type Actions, error } from '@sveltejs/kit' import { and, eq } from 'drizzle-orm' import { redirect } from 'sveltekit-flash-message/server' import { zod } from 'sveltekit-superforms/adapters' import { superValidate } from 'sveltekit-superforms/server' -import { collection_items, collections, gamesTable } from '../../../../../lib/server/api/databases/tables' export async function load(event) { const { params, locals } = event diff --git a/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte b/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte index b840239..450233c 100644 --- a/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte +++ b/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte @@ -3,10 +3,10 @@ import Game from '$components/Game.svelte' import type { UICollection } from '$lib/types' -export let data +const { data } = $props() +const { items = [] } = data console.log(`Page data: ${JSON.stringify(data)}`) let collection: UICollection = data?.collection ?? {} -let items = data?.items || [] console.log('items', items) // async function handleNextPageEvent(event: CustomEvent) { diff --git a/src/routes/(app)/(protected)/settings/security/change/password/+page.svelte b/src/routes/(app)/(protected)/settings/security/change/password/+page.svelte index fbc8215..e2f8c0f 100644 --- a/src/routes/(app)/(protected)/settings/security/change/password/+page.svelte +++ b/src/routes/(app)/(protected)/settings/security/change/password/+page.svelte @@ -53,7 +53,7 @@ const { form: formData, enhance } = form aria-label={`${hiddenCurrentPassword ? 'Show' : 'Hide'} Current Password}`} onPressedChange={() => (hiddenCurrentPassword = !hiddenCurrentPassword)} > - {#if hiddenCurrentPassword}{:else}{/if} + {#if hiddenCurrentPassword}{:else}{/if} @@ -73,7 +73,7 @@ const { form: formData, enhance } = form aria-label={`${hiddenPassword ? 'Show' : 'Hide'} Password}`} onPressedChange={() => (hiddenPassword = !hiddenPassword)} > - {#if hiddenPassword}{:else}{/if} + {#if hiddenPassword}{:else}{/if} @@ -93,7 +93,7 @@ const { form: formData, enhance } = form aria-label={`${hiddenConfirmPassword ? 'Show' : 'Hide'} Confirm Password}`} onPressedChange={() => (hiddenConfirmPassword = !hiddenConfirmPassword)} > - {#if hiddenConfirmPassword}{:else}{/if} + {#if hiddenConfirmPassword}{:else}{/if} diff --git a/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.server.ts b/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.server.ts index 4d6577a..1a45df9 100644 --- a/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.server.ts +++ b/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.server.ts @@ -102,7 +102,7 @@ export const actions: Actions = { const { error: verifyPasswordError } = await locals.api.me.verify.password .$post({ - json: { password: addTwoFactorForm.data.current_password }, + json: { password: addTwoFactorForm.data.password }, }) .then(locals.parseApiResponse) @@ -144,7 +144,7 @@ export const actions: Actions = { } const { error: verifyPasswordError } = await locals.api.me.verify.password .$post({ - json: { password: removeTwoFactorForm.data.current_password }, + json: { password: removeTwoFactorForm.data.password }, }) .then(locals.parseApiResponse) diff --git a/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.svelte b/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.svelte index b52ba0b..47672d4 100644 --- a/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.svelte +++ b/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.svelte @@ -42,7 +42,7 @@ const { form: removeTwoFactorFormData, enhance: removeTwoFactorEnhance } = remov Current Password - + Please enter your current password. @@ -64,7 +64,7 @@ const { form: removeTwoFactorFormData, enhance: removeTwoFactorEnhance } = remov Enter Password - + Please enter your current password. diff --git a/src/routes/(app)/(protected)/settings/security/mfa/totp/schemas.ts b/src/routes/(app)/(protected)/settings/security/mfa/totp/schemas.ts index fd14c28..6e05a49 100644 --- a/src/routes/(app)/(protected)/settings/security/mfa/totp/schemas.ts +++ b/src/routes/(app)/(protected)/settings/security/mfa/totp/schemas.ts @@ -1,14 +1,14 @@ import { z } from 'zod' export const addTwoFactorSchema = z.object({ - current_password: z.string({ required_error: 'Current Password is required' }), + password: z.string({ required_error: 'Current Password is required' }), two_factor_code: z.string({ required_error: 'Two Factor Code is required' }).trim(), }) export type AddTwoFactorSchema = typeof addTwoFactorSchema export const removeTwoFactorSchema = addTwoFactorSchema.pick({ - current_password: true, + password: true, }) export type RemoveTwoFactorSchema = typeof removeTwoFactorSchema diff --git a/src/routes/(app)/(protected)/wishlists/+page.svelte b/src/routes/(app)/(protected)/wishlists/+page.svelte index a65577f..ace0846 100644 --- a/src/routes/(app)/(protected)/wishlists/+page.svelte +++ b/src/routes/(app)/(protected)/wishlists/+page.svelte @@ -1,26 +1,28 @@ Your Wishlists | Bored Game -

Your wishlistsTable

+
+

Your wishlistsTable

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

You have no wishlistsTable

- {:else} - {#each wishlists as wishlist} -
-

{wishlist.name}

-

Created at: {new Date(wishlist.created_at).toLocaleString()}

-
- {/each} - {/if} +
+
+ {#if wishlists.length === 0} +

You have no wishlistsTable

+ {:else} + {#each wishlists as wishlist} +
+

{wishlist.name}

+

Created at: {new Date(wishlist.created_at).toLocaleString()}

+
+ {/each} + {/if} +
diff --git a/src/routes/(app)/(protected)/wishlists/[cuid]/+page.svelte b/src/routes/(app)/(protected)/wishlists/[cuid]/+page.svelte index 4eb0cca..784cbd7 100644 --- a/src/routes/(app)/(protected)/wishlists/[cuid]/+page.svelte +++ b/src/routes/(app)/(protected)/wishlists/[cuid]/+page.svelte @@ -1,35 +1,44 @@ {`Your Wishlist | Bored Game`} -

Your wishlist

+
+

Your wishlist

-
- {#if items.length > 0} - {#each items as item (item.id)} - - {/each} - {:else} -

Sorry no gamesTable found!

- {/if} +
+ {#if items.length > 0} + {#each items as item (item.id)} + + {/each} + {:else} +

Sorry no games found!

+ {/if} +
diff --git a/vite.config.ts b/vite.config.ts index 9ccc126..c484cfd 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -16,7 +16,8 @@ export default defineConfig({ sveltekit() ], test: { - include: ['src/**/*.{test,spec}.{js,ts}'] + include: ['src/**/*.{test,spec}.{js,ts}'], + mockReset: true, }, css: { devSourcemap: true, From b1527e7782f7b9fa575b6048118bd9106d599f49 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Fri, 13 Sep 2024 17:21:22 -0700 Subject: [PATCH 09/29] Fixing all the tests to pass --- src/lib/server/api/databases/seeds/roles.ts | 2 +- .../api/databases/tables/roles.table.ts | 7 + src/lib/server/api/services/iam.service.ts | 4 +- src/lib/server/api/tests/iam.service.test.ts | 115 ++++++---- .../server/api/tests/tokens.service.test.ts | 32 ++- .../api/tests/user_roles.service.test.ts | 105 +++++---- .../server/api/tests/users.service.test.ts | 211 +++++++----------- 7 files changed, 227 insertions(+), 249 deletions(-) diff --git a/src/lib/server/api/databases/seeds/roles.ts b/src/lib/server/api/databases/seeds/roles.ts index 35cefcd..a299a94 100644 --- a/src/lib/server/api/databases/seeds/roles.ts +++ b/src/lib/server/api/databases/seeds/roles.ts @@ -1,5 +1,5 @@ import * as schema from '$lib/server/api/databases/tables' -import { type db } from '$lib/server/api/packages/drizzle' +import type { db } from '$lib/server/api/packages/drizzle' import roles from './data/roles.json' export default async function seed(db: db) { diff --git a/src/lib/server/api/databases/tables/roles.table.ts b/src/lib/server/api/databases/tables/roles.table.ts index 1dfcfc2..e9f036f 100644 --- a/src/lib/server/api/databases/tables/roles.table.ts +++ b/src/lib/server/api/databases/tables/roles.table.ts @@ -4,6 +4,13 @@ import { pgTable, text, uuid } from 'drizzle-orm/pg-core' import { timestamps } from '../../common/utils/table' import { user_roles } from './userRoles.table' +export enum RoleName { + ADMIN = 'admin', + EDITOR = 'editor', + MODERATOR = 'moderator', + USER = 'user', +} + export const rolesTable = pgTable('roles', { id: uuid('id').primaryKey().defaultRandom(), cuid: text('cuid') diff --git a/src/lib/server/api/services/iam.service.ts b/src/lib/server/api/services/iam.service.ts index a70e8c3..7d93a5f 100644 --- a/src/lib/server/api/services/iam.service.ts +++ b/src/lib/server/api/services/iam.service.ts @@ -44,13 +44,13 @@ export class IamService { } const existingUserForNewUsername = await this.usersService.findOneByUsername(data.username) - if (existingUserForNewUsername && existingUserForNewUsername.id !== userId) { + if (existingUserForNewUsername && existingUserForNewUsername.id !== user.id) { return { error: 'Username already in use', } } - return this.usersService.updateUser(userId, { + return this.usersService.updateUser(user.id, { first_name: data.firstName, last_name: data.lastName, username: data.username !== user.username ? data.username : user.username, diff --git a/src/lib/server/api/tests/iam.service.test.ts b/src/lib/server/api/tests/iam.service.test.ts index 96d3174..40b0bae 100644 --- a/src/lib/server/api/tests/iam.service.test.ts +++ b/src/lib/server/api/tests/iam.service.test.ts @@ -2,6 +2,7 @@ import 'reflect-metadata' import { IamService } from '$lib/server/api/services/iam.service' import { LuciaService } from '$lib/server/api/services/lucia.service' import { UsersService } from '$lib/server/api/services/users.service' +import { faker } from '@faker-js/faker' import { container } from 'tsyringe' import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' @@ -25,60 +26,36 @@ describe('IamService', () => { vi.resetAllMocks() }) + const timeStampDate = new Date() + const dbUser = { + id: faker.string.uuid(), + cuid: 'ciglo1j8q0000t9j4xq8d6p5e', + first_name: faker.person.firstName(), + last_name: faker.person.lastName(), + email: faker.internet.email(), + username: faker.internet.userName(), + verified: false, + receive_email: false, + mfa_enabled: false, + theme: 'system', + createdAt: timeStampDate, + updatedAt: timeStampDate, + } + describe('Update Profile', () => { - it('should resolve', async () => { - const timeStampDate = new Date() - userService.findOneById = vi.fn().mockResolvedValueOnce({ - id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - cuid: 'ciglo1j8q0000t9j4xq8d6p5e', - first_name: 'test', - last_name: 'test', - email: 'test@example.com', - username: 'test', - verified: false, - receive_email: false, - mfa_enabled: false, - theme: 'system', - createdAt: timeStampDate, - updatedAt: timeStampDate, - }) + it('should update user', async () => { + userService.findOneById = vi.fn().mockResolvedValueOnce(dbUser) userService.findOneByUsername = vi.fn().mockResolvedValue(undefined) - userService.updateUser = vi.fn().mockResolvedValue({ - id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - cuid: 'ciglo1j8q0000t9j4xq8d6p5e', - first_name: 'test', - last_name: 'test', - email: 'test@example.com', - username: 'test', - verified: false, - receive_email: false, - mfa_enabled: false, - theme: 'system', - createdAt: timeStampDate, - updatedAt: timeStampDate, - }) + userService.updateUser = vi.fn().mockResolvedValue(dbUser) const spy_userService_findOneById = vi.spyOn(userService, 'findOneById') const spy_userService_findOneByUsername = vi.spyOn(userService, 'findOneByUsername') const spy_userService_updateUser = vi.spyOn(userService, 'updateUser') await expect( - service.updateProfile('3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', { - username: 'test', + service.updateProfile(faker.string.uuid(), { + username: faker.internet.userName(), }), - ).resolves.toEqual({ - id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - cuid: 'ciglo1j8q0000t9j4xq8d6p5e', - first_name: 'test', - last_name: 'test', - email: 'test@example.com', - username: 'test', - verified: false, - receive_email: false, - mfa_enabled: false, - theme: 'system', - createdAt: timeStampDate, - updatedAt: timeStampDate, - }) + ).resolves.toEqual(dbUser) expect(spy_userService_findOneById).toBeCalledTimes(1) expect(spy_userService_findOneByUsername).toBeCalledTimes(1) expect(spy_userService_updateUser).toBeCalledTimes(1) @@ -91,8 +68,8 @@ describe('IamService', () => { const spy_userService_findOneByUsername = vi.spyOn(userService, 'findOneByUsername') const spy_userService_updateUser = vi.spyOn(userService, 'updateUser') await expect( - service.updateProfile('3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', { - username: 'test', + service.updateProfile(faker.string.uuid(), { + username: faker.internet.userName(), }), ).resolves.toEqual({ error: 'User not found', @@ -101,5 +78,47 @@ describe('IamService', () => { expect(spy_userService_findOneByUsername).toBeCalledTimes(0) expect(spy_userService_updateUser).toBeCalledTimes(0) }) + + it('should error on duplicate username', async () => { + userService.findOneById = vi.fn().mockResolvedValueOnce(dbUser) + userService.findOneByUsername = vi.fn().mockResolvedValue({ + id: faker.string.uuid(), + }) + userService.updateUser = vi.fn().mockResolvedValue(dbUser) + + const spy_userService_findOneById = vi.spyOn(userService, 'findOneById') + const spy_userService_findOneByUsername = vi.spyOn(userService, 'findOneByUsername') + const spy_userService_updateUser = vi.spyOn(userService, 'updateUser') + await expect( + service.updateProfile(faker.string.uuid(), { + username: faker.internet.userName(), + }), + ).resolves.toEqual({ + error: 'Username already in use', + }) + expect(spy_userService_findOneById).toBeCalledTimes(1) + expect(spy_userService_findOneByUsername).toBeCalledTimes(1) + expect(spy_userService_updateUser).toBeCalledTimes(0) + }) + }) + + it('should not error if the user id of new username is the current user id', async () => { + userService.findOneById = vi.fn().mockResolvedValueOnce(dbUser) + userService.findOneByUsername = vi.fn().mockResolvedValue({ + id: dbUser.id, + }) + userService.updateUser = vi.fn().mockResolvedValue(dbUser) + + const spy_userService_findOneById = vi.spyOn(userService, 'findOneById') + const spy_userService_findOneByUsername = vi.spyOn(userService, 'findOneByUsername') + const spy_userService_updateUser = vi.spyOn(userService, 'updateUser') + await expect( + service.updateProfile(dbUser.id, { + username: dbUser.id, + }), + ).resolves.toEqual(dbUser) + expect(spy_userService_findOneById).toBeCalledTimes(1) + expect(spy_userService_findOneByUsername).toBeCalledTimes(1) + expect(spy_userService_updateUser).toBeCalledTimes(1) }) }) diff --git a/src/lib/server/api/tests/tokens.service.test.ts b/src/lib/server/api/tests/tokens.service.test.ts index ad0aa3b..cff2574 100644 --- a/src/lib/server/api/tests/tokens.service.test.ts +++ b/src/lib/server/api/tests/tokens.service.test.ts @@ -1,7 +1,7 @@ import 'reflect-metadata' import { Argon2id } from 'oslo/password' import { container } from 'tsyringe' -import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' +import { afterAll, beforeAll, describe, expect, expectTypeOf, it, vi } from 'vitest' import { HashingService } from '../services/hashing.service' import { TokensService } from '../services/tokens.service' @@ -18,30 +18,28 @@ describe('TokensService', () => { }) describe('Generate Token', () => { - const hashedPassword = new Argon2id().hash('111') - - hashingService.hash = vi.fn().mockResolvedValue(hashedPassword) - hashingService.verify = vi.fn().mockResolvedValue(true) - - const spy_hashingService_hash = vi.spyOn(hashingService, 'hash') - const spy_hashingService_verify = vi.spyOn(hashingService, 'verify') - it('should resolve', async () => { - expect(service.createHashedToken('111')).resolves.string + const hashedPassword = await new Argon2id().hash('111') + hashingService.hash = vi.fn().mockResolvedValue(hashedPassword) + const spy_hashingService_hash = vi.spyOn(hashingService, 'hash') + const spy_hashingService_verify = vi.spyOn(hashingService, 'verify') + await expectTypeOf(service.createHashedToken('111')).resolves.toBeString() + expect(spy_hashingService_hash).toBeCalledTimes(1) + expect(spy_hashingService_verify).toBeCalledTimes(0) }) it('should generate a token that is verifiable', async () => { + hashingService.hash = vi.fn().mockResolvedValue(await new Argon2id().hash('111')) + hashingService.verify = vi.fn().mockResolvedValue(true) + const spy_hashingService_hash = vi.spyOn(hashingService, 'hash') + const spy_hashingService_verify = vi.spyOn(hashingService, 'verify') const token = await service.createHashedToken('111') + expect(token).not.toBeNaN() expect(token).not.toBeUndefined() expect(token).not.toBeNull() const verifiable = await service.verifyHashedToken(token, '111') expect(verifiable).toBeTruthy() - }) - - it('should generate a hashed token', async () => { - expect(spy_hashingService_hash).toHaveBeenCalledTimes(2) - }) - it('should verify a hashed token', async () => { - expect(spy_hashingService_verify).toHaveBeenCalledTimes(1) + expect(spy_hashingService_hash).toBeCalledTimes(1) + expect(spy_hashingService_verify).toBeCalledTimes(1) }) }) }) diff --git a/src/lib/server/api/tests/user_roles.service.test.ts b/src/lib/server/api/tests/user_roles.service.test.ts index dfd47d2..89cde2a 100644 --- a/src/lib/server/api/tests/user_roles.service.test.ts +++ b/src/lib/server/api/tests/user_roles.service.test.ts @@ -1,62 +1,75 @@ -import 'reflect-metadata'; -import { container } from 'tsyringe'; -import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; -import { UserRolesService } from '../services/user_roles.service'; -import { UserRolesRepository } from '../repositories/user_roles.repository'; -import { RolesService } from '../services/roles.service'; +import 'reflect-metadata' +import { RoleName } from '$lib/server/api/databases/tables' +import { faker } from '@faker-js/faker' +import { container } from 'tsyringe' +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' +import { UserRolesRepository } from '../repositories/user_roles.repository' +import { RolesService } from '../services/roles.service' +import { UserRolesService } from '../services/user_roles.service' describe('UserRolesService', () => { - let service: UserRolesService; - const userRolesRepository = vi.mocked(UserRolesRepository.prototype); - const rolesService = vi.mocked(RolesService.prototype); + let service: UserRolesService + const userRolesRepository = vi.mocked(UserRolesRepository.prototype) + const rolesService = vi.mocked(RolesService.prototype) beforeAll(() => { service = container .register(UserRolesRepository, { useValue: userRolesRepository }) .register(RolesService, { useValue: rolesService }) - .resolve(UserRolesService); - }); + .resolve(UserRolesService) + }) afterAll(() => { vi.resetAllMocks() - }); + }) + + const timeStampDate = new Date() + const roleUUID = faker.string.uuid() + const userUUID = faker.string.uuid() + const dbRole = { + id: roleUUID, + cuid: 'ciglo1j8q0000t9j4xq8d6p5e', + name: RoleName.ADMIN, + createdAt: timeStampDate, + updatedAt: timeStampDate, + } + + const dbUserRole = { + id: faker.string.uuid(), + cuid: 'ciglo1j8q0000t9j4xq8d6p5e', + role_id: roleUUID, + user_id: userUUID, + primary: true, + createdAt: timeStampDate, + updatedAt: timeStampDate, + } describe('Create User Role', () => { - rolesService.findOneByNameOrThrow = vi.fn().mockResolvedValue({ - id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - cuid: 'ciglo1j8q0000t9j4xq8d6p5e', - name: 'user', - createdAt: new Date(), - updatedAt: new Date() - } satisfies Awaited>); - - userRolesRepository.create = vi.fn().mockResolvedValue({ - id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - cuid: 'ciglo1j8q0000t9j4xq8d6p5e', - user_id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8fff', - role_id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - primary: true, - createdAt: new Date(), - updatedAt: new Date() - } satisfies Awaited>); - - const spy_rolesService_findOneByNameOrThrow = vi.spyOn(rolesService, 'findOneByNameOrThrow'); - const spy_userRolesRepository_create = vi.spyOn(userRolesRepository, 'create'); - it('should resolve', async () => { - await expect(service.addRoleToUser('3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8fff', 'user', true)).resolves.not.toThrowError(); - }) - it('should call rolesService.findOneByNameOrThrow', async () => { - expect(spy_rolesService_findOneByNameOrThrow).toBeCalledWith('user'); - expect(spy_rolesService_findOneByNameOrThrow).toBeCalledTimes(1); - }) - it('should call userRolesRepository.create', async () => { + rolesService.findOneByNameOrThrow = vi.fn().mockResolvedValue(dbRole satisfies Awaited>) + + userRolesRepository.create = vi.fn().mockResolvedValue(dbUserRole satisfies Awaited>) + + const spy_rolesService_findOneByNameOrThrow = vi.spyOn(rolesService, 'findOneByNameOrThrow') + const spy_userRolesRepository_create = vi.spyOn(userRolesRepository, 'create') + + await expect(service.addRoleToUser(userUUID, RoleName.ADMIN, true)).resolves.not.toThrowError() + expect(spy_rolesService_findOneByNameOrThrow).toBeCalledWith(RoleName.ADMIN) + expect(spy_rolesService_findOneByNameOrThrow).toBeCalledTimes(1) expect(spy_userRolesRepository_create).toBeCalledWith({ - user_id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8fff', - role_id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - primary: true - }); - expect(spy_userRolesRepository_create).toBeCalledTimes(1); + user_id: userUUID, + role_id: dbRole.id, + primary: true, + }) + expect(spy_userRolesRepository_create).toBeCalledTimes(1) + }) + it('should error on no role found', async () => { + rolesService.findOneByNameOrThrow = vi.fn().mockResolvedValue(undefined) + + const spy_rolesService_findOneByNameOrThrow = vi.spyOn(rolesService, 'findOneByNameOrThrow') + await expect(service.addRoleToUser(userUUID, RoleName.ADMIN, true)).rejects.toThrowError(`Role with name ${RoleName.ADMIN} not found`) + expect(spy_rolesService_findOneByNameOrThrow).toBeCalledWith(RoleName.ADMIN) + expect(spy_rolesService_findOneByNameOrThrow).toBeCalledTimes(1) }) }) -}); \ No newline at end of file +}) diff --git a/src/lib/server/api/tests/users.service.test.ts b/src/lib/server/api/tests/users.service.test.ts index ec551a2..ca916e2 100644 --- a/src/lib/server/api/tests/users.service.test.ts +++ b/src/lib/server/api/tests/users.service.test.ts @@ -1,8 +1,9 @@ import 'reflect-metadata' import { CredentialsType } from '$lib/server/api/databases/tables' +import { faker } from '@faker-js/faker' import { Argon2id } from 'oslo/password' import { container } from 'tsyringe' -import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' import { CredentialsRepository } from '../repositories/credentials.repository' import { UsersRepository } from '../repositories/users.repository' import { CollectionsService } from '../services/collections.service' @@ -35,154 +36,94 @@ describe('UsersService', () => { vi.resetAllMocks() }) + const timeStampDate = new Date() + const dbUser = { + id: faker.string.uuid(), + cuid: 'ciglo1j8q0000t9j4xq8d6p5e', + first_name: faker.person.firstName(), + last_name: faker.person.lastName(), + email: faker.internet.email(), + username: faker.internet.userName(), + verified: false, + receive_email: false, + mfa_enabled: false, + theme: 'system', + createdAt: timeStampDate, + updatedAt: timeStampDate, + } + const dbCredentials = { + id: faker.string.uuid(), + user_id: dbUser.id, + type: CredentialsType.PASSWORD, + secret_data: 'hashedPassword', + createdAt: timeStampDate, + updatedAt: timeStampDate, + } + describe('Create User', () => { - const date = new Date() - - const hashedPassword = new Argon2id().hash('111') - tokensService.createHashedToken = vi.fn().mockResolvedValue(hashedPassword) - - usersRepository.create = vi.fn().mockResolvedValue({ - id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - cuid: 'ciglo1j8q0000t9j4xq8d6p5e', - first_name: 'test', - last_name: 'test', - email: 'test@example.com', - username: 'test', - verified: false, - receive_email: false, - mfa_enabled: false, - theme: 'system', - createdAt: date, - updatedAt: date, - } satisfies Awaited>) - - credentialsRepository.create = vi.fn().mockResolvedValue({ - id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - user_id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - type: CredentialsType.PASSWORD, - secret_data: hashedPassword, - }) satisfies Awaited> - - userRolesService.addRoleToUser = vi.fn().mockResolvedValue(undefined) - - wishlistsService.createEmptyNoName = vi.fn().mockResolvedValue(undefined) - - collectionsService.createEmptyNoName = vi.fn().mockResolvedValue(undefined) - - const spy_tokensService_createHashToken = vi.spyOn(tokensService, 'createHashedToken') - const spy_usersRepository_create = vi.spyOn(usersRepository, 'create') - const spy_credentialsRepository_create = vi.spyOn(credentialsRepository, 'create') - const spy_userRolesService_addRoleToUser = vi.spyOn(userRolesService, 'addRoleToUser') - const spy_wishlistsService_createEmptyNoName = vi.spyOn(wishlistsService, 'createEmptyNoName') - const spy_collectionsService_createEmptyNoName = vi.spyOn(collectionsService, 'createEmptyNoName') - it('should resolve', async () => { + const hashedPassword = new Argon2id().hash('111') + tokensService.createHashedToken = vi.fn().mockResolvedValue(hashedPassword) + usersRepository.create = vi.fn().mockResolvedValue(dbUser satisfies Awaited>) + credentialsRepository.create = vi.fn().mockResolvedValue(dbCredentials satisfies Awaited>) + userRolesService.addRoleToUser = vi.fn().mockResolvedValue(undefined) + wishlistsService.createEmptyNoName = vi.fn().mockResolvedValue(undefined) + collectionsService.createEmptyNoName = vi.fn().mockResolvedValue(undefined) + + const spy_tokensService_createHashToken = vi.spyOn(tokensService, 'createHashedToken') + const spy_usersRepository_create = vi.spyOn(usersRepository, 'create') + const spy_credentialsRepository_create = vi.spyOn(credentialsRepository, 'create') + const spy_userRolesService_addRoleToUser = vi.spyOn(userRolesService, 'addRoleToUser') + const spy_wishlistsService_createEmptyNoName = vi.spyOn(wishlistsService, 'createEmptyNoName') + const spy_collectionsService_createEmptyNoName = vi.spyOn(collectionsService, 'createEmptyNoName') await expect( service.create({ - firstName: 'test', - lastName: 'test', - email: 'test@example.com', - username: 'test', - password: '111', - confirm_password: '111', + firstName: faker.person.firstName(), + lastName: faker.person.lastName(), + email: faker.internet.email(), + username: faker.internet.userName(), + password: faker.string.alphanumeric(10), + confirm_password: faker.string.alphanumeric(10), }), - ).resolves.toEqual({ - id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - cuid: 'ciglo1j8q0000t9j4xq8d6p5e', - first_name: 'test', - last_name: 'test', - email: 'test@example.com', - username: 'test', - verified: false, - receive_email: false, - mfa_enabled: false, - theme: 'system', - createdAt: date, - updatedAt: date, - }) - }) - // it('should generate a hashed token', async () => { - // expect(spy_tokensService_createHashToken).toBeCalledTimes(1) - // }) - // it('should create a new user', async () => { - // expect(spy_usersRepository_create).toBeCalledTimes(1) - // }) - // it('should create a new credential', async () => { - // expect(spy_credentialsRepository_create).toBeCalledTimes(1) - // }) - // it('should add role to user', async () => { - // expect(spy_userRolesService_addRoleToUser).toBeCalledTimes(1) - // }) - // it('should create a new wishlist', async () => { - // expect(spy_wishlistsService_createEmptyNoName).toBeCalledTimes(1) - // }) - // it('should create a new collection', async () => { - // expect(spy_collectionsService_createEmptyNoName).toBeCalledTimes(1) - // }) - }) - describe('Update User Password Exiting Credentials', () => { - const hashedPassword = new Argon2id().hash('111') - tokensService.createHashedToken = vi.fn().mockResolvedValue(hashedPassword) satisfies Awaited> - credentialsRepository.update = vi.fn().mockResolvedValue({ - id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - user_id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - type: 'PASSWORD', - secret_data: hashedPassword, - }) satisfies Awaited> - credentialsRepository.findPasswordCredentialsByUserId = vi.fn().mockResolvedValue({ - id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - user_id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - type: 'PASSWORD', - secret_data: hashedPassword, - }) satisfies Awaited> - - const spy_tokensService_createHashToken = vi.spyOn(tokensService, 'createHashedToken') - const spy_credentialsRepository_findPasswordCredentialsByUserId = vi.spyOn(credentialsRepository, 'findPasswordCredentialsByUserId') - const spy_credentialsRepository_update = vi.spyOn(credentialsRepository, 'update') - - it('should resolve', async () => { - await expect(service.updatePassword('3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', '111')).resolves.toBeUndefined() - }) - console.log(spy_tokensService_createHashToken.mock.calls) - it('should generate a hashed token', async () => { + ).resolves.toEqual(dbUser) expect(spy_tokensService_createHashToken).toBeCalledTimes(1) + expect(spy_usersRepository_create).toBeCalledTimes(1) + expect(spy_credentialsRepository_create).toBeCalledTimes(1) + expect(spy_userRolesService_addRoleToUser).toBeCalledTimes(1) + expect(spy_wishlistsService_createEmptyNoName).toBeCalledTimes(1) + expect(spy_collectionsService_createEmptyNoName).toBeCalledTimes(1) }) - console.log(spy_credentialsRepository_findPasswordCredentialsByUserId.mock.calls) - it('should call find password credentials by user id', async () => { + }) + describe('Update User', () => { + it('should resolve Password Exiting Credentials', async () => { + const hashedPassword = new Argon2id().hash('111') + tokensService.createHashedToken = vi.fn().mockResolvedValue(hashedPassword) + credentialsRepository.update = vi.fn().mockResolvedValue(dbCredentials satisfies Awaited>) + credentialsRepository.findPasswordCredentialsByUserId = vi + .fn() + .mockResolvedValue(dbCredentials satisfies Awaited>) + + const spy_tokensService_createHashToken = vi.spyOn(tokensService, 'createHashedToken') + const spy_credentialsRepository_findPasswordCredentialsByUserId = vi.spyOn(credentialsRepository, 'findPasswordCredentialsByUserId') + const spy_credentialsRepository_update = vi.spyOn(credentialsRepository, 'update') + await expect(service.updatePassword(dbUser.id, faker.string.alphanumeric(10))).resolves.toBeUndefined() + expect(spy_tokensService_createHashToken).toBeCalledTimes(1) expect(spy_credentialsRepository_findPasswordCredentialsByUserId).toBeCalledTimes(1) - }) - console.log(spy_credentialsRepository_update.mock.calls) - it('should update the credential when user has credential', async () => { expect(spy_credentialsRepository_update).toBeCalledTimes(1) }) - }) - describe('Update User Password No Existing Credentials', () => { - const hashedPassword = new Argon2id().hash('111') - tokensService.createHashedToken = vi.fn().mockResolvedValue(hashedPassword) satisfies Awaited> - credentialsRepository.findPasswordCredentialsByUserId = vi.fn().mockResolvedValue(null) satisfies Awaited< - ReturnType - > - credentialsRepository.create = vi.fn().mockResolvedValue({ - id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - user_id: '3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', - type: 'PASSWORD', - secret_data: hashedPassword, - }) satisfies Awaited> + it('Should Create User Password No Existing Credentials', async () => { + const hashedPassword = new Argon2id().hash('111') + tokensService.createHashedToken = vi.fn().mockResolvedValue(hashedPassword) + credentialsRepository.findPasswordCredentialsByUserId = vi.fn().mockResolvedValue(null) + credentialsRepository.create = vi.fn().mockResolvedValue(dbCredentials satisfies Awaited>) - const spy_tokensService_createHashToken = vi.spyOn(tokensService, 'createHashedToken') - const spy_credentialsRepository_create = vi.spyOn(credentialsRepository, 'create') - const spy_credentialsRepository_findPasswordCredentialsByUserId = vi.spyOn(credentialsRepository, 'findPasswordCredentialsByUserId') + const spy_tokensService_createHashToken = vi.spyOn(tokensService, 'createHashedToken') + const spy_credentialsRepository_create = vi.spyOn(credentialsRepository, 'create') + const spy_credentialsRepository_findPasswordCredentialsByUserId = vi.spyOn(credentialsRepository, 'findPasswordCredentialsByUserId') - it('should resolve with no current credential for user', async () => { - await expect(service.updatePassword('3e0e9f0f-0a0b-4f0b-8f0b-0a0b4f0b8f0b', '111')).resolves.not.toThrow() - }) - it('should generate a hashed token', async () => { + await expect(service.updatePassword(dbUser.id, faker.string.alphanumeric(10))).resolves.not.toThrow() expect(spy_tokensService_createHashToken).toBeCalledTimes(1) - }) - it('should call find password credentials by user id', async () => { expect(spy_credentialsRepository_findPasswordCredentialsByUserId).toBeCalledTimes(1) - }) - it('should create a new credential when user has no credential', async () => { expect(spy_credentialsRepository_create).toHaveBeenCalledTimes(1) }) }) From fbf4d08b07197a3bcbf5bfb6ba9a1c5fef3828f2 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Mon, 16 Sep 2024 09:07:22 -0700 Subject: [PATCH 10/29] Adding OAuth for GitHub. --- .env.example | 4 + package.json | 16 +- pnpm-lock.yaml | 752 ++++++++++-------- src/lib/server/api/common/env.ts | 2 + .../api/controllers/collection.controller.ts | 5 + .../api/controllers/oauth.controller.ts | 55 ++ .../api/databases/tables/collections.table.ts | 4 +- src/lib/server/api/index.ts | 1 + .../repositories/collections.repository.ts | 19 +- .../federated_identity.repository.ts | 25 + .../api/services/collections.service.ts | 4 + src/lib/server/api/services/oauth.service.ts | 54 ++ src/lib/server/auth.ts | 4 + .../(protected)/collections/+page.server.ts | 20 +- .../(protected)/collections/+page.svelte | 26 +- .../(auth)/auth/callback/github/+server.ts | 21 + src/routes/(auth)/login/github/+server.ts | 18 + 17 files changed, 645 insertions(+), 385 deletions(-) create mode 100644 src/lib/server/api/controllers/oauth.controller.ts create mode 100644 src/lib/server/api/repositories/federated_identity.repository.ts create mode 100644 src/lib/server/api/services/oauth.service.ts create mode 100644 src/lib/server/auth.ts create mode 100644 src/routes/(auth)/auth/callback/github/+server.ts create mode 100644 src/routes/(auth)/login/github/+server.ts diff --git a/.env.example b/.env.example index 7b3b671..527dae2 100644 --- a/.env.example +++ b/.env.example @@ -18,6 +18,10 @@ ADMIN_PASSWORD= TWO_FACTOR_TIMEOUT=300000 +# OAuth +GITHUB_CLIENT_ID="" +GITHUB_CLIENT_SECRET="" + # Public PUBLIC_SITE_NAME='Bored Game' diff --git a/package.json b/package.json index e04cff2..92afa67 100644 --- a/package.json +++ b/package.json @@ -27,16 +27,17 @@ "@faker-js/faker": "^8.4.1", "@melt-ui/pp": "^0.3.2", "@melt-ui/svelte": "^0.83.0", - "@playwright/test": "^1.47.0", + "@playwright/test": "^1.47.1", "@sveltejs/adapter-auto": "^3.2.4", - "@sveltejs/enhanced-img": "^0.3.4", - "@sveltejs/kit": "^2.5.26", + "@sveltejs/enhanced-img": "^0.3.7", + "@sveltejs/kit": "^2.5.27", "@sveltejs/vite-plugin-svelte": "^3.1.2", "@types/cookie": "^0.6.0", "@types/node": "^20.16.5", - "@types/pg": "^8.11.9", + "@types/pg": "^8.11.10", "@typescript-eslint/eslint-plugin": "^7.18.0", "@typescript-eslint/parser": "^7.18.0", + "arctic": "^1.9.2", "autoprefixer": "^10.4.20", "drizzle-kit": "^0.23.2", "eslint": "^8.57.0", @@ -47,7 +48,7 @@ "lucia": "3.2.0", "lucide-svelte": "^0.408.0", "nodemailer": "^6.9.15", - "postcss": "^8.4.45", + "postcss": "^8.4.47", "postcss-import": "^16.1.0", "postcss-load-config": "^5.1.0", "postcss-preset-env": "^9.6.0", @@ -64,13 +65,13 @@ "svelte-sequential-preprocessor": "^2.0.1", "sveltekit-flash-message": "^2.4.4", "sveltekit-rate-limiter": "^0.5.2", - "sveltekit-superforms": "^2.17.0", + "sveltekit-superforms": "^2.18.0", "tailwindcss": "^3.4.11", "ts-node": "^10.9.2", "tslib": "^2.7.0", "tsx": "^4.19.1", "typescript": "^5.6.2", - "vite": "^5.4.4", + "vite": "^5.4.5", "vitest": "^1.6.0", "zod": "^3.23.8" }, @@ -92,7 +93,6 @@ "@sveltejs/adapter-vercel": "^5.4.3", "@types/feather-icons": "^4.29.4", "@vercel/og": "^0.5.20", - "arctic": "^1.9.2", "bits-ui": "^0.21.13", "boardgamegeekclient": "^1.9.1", "bullmq": "^5.13.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1bcf7f5..3368666 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,7 +31,7 @@ importers: version: 3.5.5 '@lucia-auth/adapter-drizzle': specifier: ^1.1.0 - version: 1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4))(lucia@3.2.0) + version: 1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.12.0)(postgres@3.4.4))(lucia@3.2.0) '@lukeed/uuid': specifier: ^2.0.1 version: 2.0.1 @@ -46,19 +46,16 @@ importers: version: 2.6.2 '@sveltejs/adapter-node': specifier: ^5.2.2 - version: 5.2.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))) + version: 5.2.2(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))) '@sveltejs/adapter-vercel': specifier: ^5.4.3 - version: 5.4.3(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))) + version: 5.4.3(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))) '@types/feather-icons': specifier: ^4.29.4 version: 4.29.4 '@vercel/og': specifier: ^0.5.20 version: 0.5.20 - arctic: - specifier: ^1.9.2 - version: 1.9.2 bits-ui: specifier: ^0.21.13 version: 0.21.13(svelte@5.0.0-next.175) @@ -85,16 +82,16 @@ importers: version: 11.0.6 drizzle-orm: specifier: ^0.32.2 - version: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4) + version: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.12.0)(postgres@3.4.4) drizzle-zod: specifier: ^0.5.1 - version: 0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4))(zod@3.23.8) + version: 0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.12.0)(postgres@3.4.4))(zod@3.23.8) feather-icons: specifier: ^4.29.2 version: 4.29.2 formsnap: specifier: ^1.0.1 - version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)) + version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.18.0(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)) handlebars: specifier: ^4.7.8 version: 4.7.8 @@ -181,20 +178,20 @@ importers: specifier: ^0.83.0 version: 0.83.0(svelte@5.0.0-next.175) '@playwright/test': - specifier: ^1.47.0 - version: 1.47.0 + specifier: ^1.47.1 + version: 1.47.1 '@sveltejs/adapter-auto': specifier: ^3.2.4 - version: 3.2.4(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))) + version: 3.2.4(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))) '@sveltejs/enhanced-img': - specifier: ^0.3.4 - version: 0.3.4(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + specifier: ^0.3.7 + version: 0.3.7(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) '@sveltejs/kit': - specifier: ^2.5.26 - version: 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + specifier: ^2.5.27 + version: 2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) '@sveltejs/vite-plugin-svelte': specifier: ^3.1.2 - version: 3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + version: 3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) '@types/cookie': specifier: ^0.6.0 version: 0.6.0 @@ -202,17 +199,20 @@ importers: specifier: ^20.16.5 version: 20.16.5 '@types/pg': - specifier: ^8.11.9 - version: 8.11.9 + specifier: ^8.11.10 + version: 8.11.10 '@typescript-eslint/eslint-plugin': specifier: ^7.18.0 version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0)(typescript@5.6.2) '@typescript-eslint/parser': specifier: ^7.18.0 version: 7.18.0(eslint@8.57.0)(typescript@5.6.2) + arctic: + specifier: ^1.9.2 + version: 1.9.2 autoprefixer: specifier: ^10.4.20 - version: 10.4.20(postcss@8.4.45) + version: 10.4.20(postcss@8.4.47) drizzle-kit: specifier: ^0.23.2 version: 0.23.2 @@ -241,17 +241,17 @@ importers: specifier: ^6.9.15 version: 6.9.15 postcss: - specifier: ^8.4.45 - version: 8.4.45 + specifier: ^8.4.47 + version: 8.4.47 postcss-import: specifier: ^16.1.0 - version: 16.1.0(postcss@8.4.45) + version: 16.1.0(postcss@8.4.47) postcss-load-config: specifier: ^5.1.0 - version: 5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1) + version: 5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1) postcss-preset-env: specifier: ^9.6.0 - version: 9.6.0(postcss@8.4.45) + version: 9.6.0(postcss@8.4.47) prettier: specifier: ^3.3.3 version: 3.3.3 @@ -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.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175) + version: 3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.78.0)(svelte@5.0.0-next.175) svelte-headless-table: specifier: ^0.18.2 version: 0.18.2(svelte@5.0.0-next.175) @@ -281,19 +281,19 @@ importers: version: 3.1.4(svelte@5.0.0-next.175)(typescript@5.6.2) svelte-preprocess: specifier: ^6.0.2 - version: 6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2) + version: 6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2) svelte-sequential-preprocessor: specifier: ^2.0.1 version: 2.0.1 sveltekit-flash-message: specifier: ^2.4.4 - version: 2.4.4(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175) + version: 2.4.4(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175) sveltekit-rate-limiter: specifier: ^0.5.2 - version: 0.5.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))) + version: 0.5.2(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))) sveltekit-superforms: - specifier: ^2.17.0 - version: 2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175) + specifier: ^2.18.0 + version: 2.18.0(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) tailwindcss: specifier: ^3.4.11 version: 3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) @@ -310,8 +310,8 @@ importers: specifier: ^5.6.2 version: 5.6.2 vite: - specifier: ^5.4.4 - version: 5.4.4(@types/node@20.16.5)(sass@1.78.0) + specifier: ^5.4.5 + version: 5.4.5(@types/node@20.16.5)(sass@1.78.0) vitest: specifier: ^1.6.0 version: 1.6.0(@types/node@20.16.5)(sass@1.78.0) @@ -1706,8 +1706,8 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@playwright/test@1.47.0': - resolution: {integrity: sha512-SgAdlSwYVpToI4e/IH19IHHWvoijAYH5hu2MWSXptRypLSnzj51PcGD+rsOXFayde4P9ZLi+loXVwArg6IUkCA==} + '@playwright/test@1.47.1': + resolution: {integrity: sha512-dbWpcNQZ5nj16m+A5UNScYx7HX5trIy7g4phrcitn+Nk83S32EBX/CLU4hiF4RGKX/yRc93AAqtfaXB7JWBd4Q==} engines: {node: '>=18'} hasBin: true @@ -1956,14 +1956,14 @@ packages: peerDependencies: '@sveltejs/kit': ^2.4.0 - '@sveltejs/enhanced-img@0.3.4': - resolution: {integrity: sha512-eX+ob5uWr0bTLMKeG9nhhM84aR88hqiLiyEfWZPX7ijhk/wlmYSUX9nOiaVHh2ct1U+Ju9Hhb90Copw+ZNOB8w==} + '@sveltejs/enhanced-img@0.3.7': + resolution: {integrity: sha512-Rb692ralH4Vs8bx52b403Xs2ZmZJ3XctYiXGNXLay9ex1G56jD31jqPFnwoWKyUqiD9JTi6CxVp/1Xy2Dus86Q==} peerDependencies: svelte: ^4.0.0 || ^5.0.0-next.0 vite: '>= 5.0.0' - '@sveltejs/kit@2.5.26': - resolution: {integrity: sha512-8l1JTIM2L+bS8ebq1E+nGjv/YSKSnD9Q19bYIUkc41vaEG2JjVUx6ikvPIJv2hkQAuqJLzoPrXlKk4KcyWOv3Q==} + '@sveltejs/kit@2.5.27': + resolution: {integrity: sha512-CcbRTzl+65oWljAASL6UlxM4x3NWwd0fjq5fQOfP243vs50myFQ8lil0fr3Im6HeeQqYUCtnv8HjO8REWVPjTw==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -2019,12 +2019,12 @@ packages: '@types/node@20.16.5': resolution: {integrity: sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==} + '@types/pg@8.11.10': + resolution: {integrity: sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==} + '@types/pg@8.11.6': resolution: {integrity: sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ==} - '@types/pg@8.11.9': - resolution: {integrity: sha512-M4mYeJZRBD9lCBCGa72F44uKSV9eJrAFfjlPJagdA6pgIr2OPJULFB7nqnZzOdqXG0qzHlgtZKzTdIgbmHitSg==} - '@types/pug@2.0.10': resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==} @@ -2034,6 +2034,22 @@ packages: '@types/validator@13.12.1': resolution: {integrity: sha512-w0URwf7BQb0rD/EuiG12KP0bailHKHP5YVviJG9zw3ykAokL0TuxU2TUqMB7EwZ59bDHYdeTIvjI5m0S7qHfOA==} + '@typeschema/class-validator@0.2.0': + resolution: {integrity: sha512-zq0qeflVu1Z6D0ttkqAWZMtxJeNEQ70yo/025sV0jujiOOgQx38JXrky77nSWWPp2E1KIMtgkToQbkzkXyW5yg==} + peerDependencies: + class-validator: ^0.14.1 + peerDependenciesMeta: + class-validator: + optional: true + + '@typeschema/core@0.14.0': + resolution: {integrity: sha512-Ia6PtZHcL3KqsAWXjMi5xIyZ7XMH4aSnOQes8mfMLx+wGFGtGRNlwe6Y7cYvX+WfNK67OL0/HSe9t8QDygV0/w==} + peerDependencies: + '@types/json-schema': ^7.0.15 + peerDependenciesMeta: + '@types/json-schema': + optional: true + '@typescript-eslint/eslint-plugin@7.18.0': resolution: {integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==} engines: {node: ^18.18.0 || >=20.0.0} @@ -2351,6 +2367,9 @@ packages: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} + class-validator@0.14.1: + resolution: {integrity: sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==} + class-variance-authority@0.7.0: resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==} @@ -3219,6 +3238,9 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + libphonenumber-js@1.11.8: + resolution: {integrity: sha512-0fv/YKpJBAgXKy0kaS3fnqoUVN8901vUYAKIGD/MWZaDfhJt1nZjPL3ZzdZBt/G8G8Hw2J1xOIrXWdNHFHPAvg==} + lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} @@ -3673,13 +3695,13 @@ packages: pkg-types@1.2.0: resolution: {integrity: sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==} - playwright-core@1.47.0: - resolution: {integrity: sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg==} + playwright-core@1.47.1: + resolution: {integrity: sha512-i1iyJdLftqtt51mEk6AhYFaAJCDx0xQ/O5NU8EKaWFgMjItPVma542Nh/Aq8aLCjIJSzjaiEQGW/nyqLkGF1OQ==} engines: {node: '>=18'} hasBin: true - playwright@1.47.0: - resolution: {integrity: sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww==} + playwright@1.47.1: + resolution: {integrity: sha512-SUEKi6947IqYbKxRiqnbUobVZY4bF1uu+ZnZNJX9DfU1tlf2UhWfvVjLf01pQx9URsOr18bFVUKXmanYWhbfkw==} engines: {node: '>=18'} hasBin: true @@ -3922,8 +3944,8 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.4.45: - resolution: {integrity: sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==} + postcss@8.4.47: + resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} engines: {node: ^10 || ^12 || >=14} postgres-array@2.0.0: @@ -4211,6 +4233,10 @@ packages: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -4453,8 +4479,8 @@ packages: peerDependencies: '@sveltejs/kit': 1.x || 2.x - sveltekit-superforms@2.17.0: - resolution: {integrity: sha512-QrX8pkcmE0XoeVU42zMhsah4FoDrgtPc/4cZEr38rDlgU+DE0xNc5J0E7z1456sUJNbFjaB0+HZwwAkX0vYqaA==} + sveltekit-superforms@2.18.0: + resolution: {integrity: sha512-INx2EwWk82WcUdG5iEMtcJ+NLvBpYOdiHDRa68Q9p9W+YRAN3mxwiqj5gpfVrvBPlGfFZypeAze54pBZ/wlspw==} peerDependencies: '@sveltejs/kit': 1.x || 2.x svelte: 3.x || 4.x || >=5.0.0-next.51 @@ -4679,8 +4705,8 @@ packages: engines: {node: ^18.0.0 || >=20.0.0} hasBin: true - vite@5.4.4: - resolution: {integrity: sha512-RHFCkULitycHVTtelJ6jQLd+KSAAzOgEYorV32R2q++M6COBjKJR6BxqClwp5sf0XaBDjVMuJ9wnNfyAJwjMkA==} + vite@5.4.5: + resolution: {integrity: sha512-pXqR0qtb2bTwLkev4SE3r4abCNioP3GkjvIDLlzziPpXtHgiJIjuKl+1GN6ESOT3wMjG3JTeARopj2SwYaHTOA==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -4939,201 +4965,201 @@ snapshots: '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-cascade-layers@4.0.6(postcss@8.4.45)': + '@csstools/postcss-cascade-layers@4.0.6(postcss@8.4.47)': dependencies: '@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.1.2) - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - '@csstools/postcss-color-function@3.0.19(postcss@8.4.45)': + '@csstools/postcss-color-function@3.0.19(postcss@8.4.47)': dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-color-mix-function@2.0.19(postcss@8.4.45)': + '@csstools/postcss-color-mix-function@2.0.19(postcss@8.4.47)': dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-content-alt-text@1.0.0(postcss@8.4.45)': + '@csstools/postcss-content-alt-text@1.0.0(postcss@8.4.47)': dependencies: '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-exponential-functions@1.0.9(postcss@8.4.45)': + '@csstools/postcss-exponential-functions@1.0.9(postcss@8.4.47)': dependencies: '@csstools/css-calc': 1.2.4(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-font-format-keywords@3.0.2(postcss@8.4.45)': + '@csstools/postcss-font-format-keywords@3.0.2(postcss@8.4.47)': dependencies: - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 postcss-value-parser: 4.2.0 - '@csstools/postcss-gamut-mapping@1.0.11(postcss@8.4.45)': + '@csstools/postcss-gamut-mapping@1.0.11(postcss@8.4.47)': dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-gradients-interpolation-method@4.0.20(postcss@8.4.45)': + '@csstools/postcss-gradients-interpolation-method@4.0.20(postcss@8.4.47)': dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-hwb-function@3.0.18(postcss@8.4.45)': + '@csstools/postcss-hwb-function@3.0.18(postcss@8.4.47)': dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-ic-unit@3.0.7(postcss@8.4.45)': + '@csstools/postcss-ic-unit@3.0.7(postcss@8.4.47)': dependencies: - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 postcss-value-parser: 4.2.0 - '@csstools/postcss-initial@1.0.1(postcss@8.4.45)': + '@csstools/postcss-initial@1.0.1(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-is-pseudo-class@4.0.8(postcss@8.4.45)': + '@csstools/postcss-is-pseudo-class@4.0.8(postcss@8.4.47)': dependencies: '@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.1.2) - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - '@csstools/postcss-light-dark-function@1.0.8(postcss@8.4.45)': + '@csstools/postcss-light-dark-function@1.0.8(postcss@8.4.47)': dependencies: '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-logical-float-and-clear@2.0.1(postcss@8.4.45)': + '@csstools/postcss-logical-float-and-clear@2.0.1(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-logical-overflow@1.0.1(postcss@8.4.45)': + '@csstools/postcss-logical-overflow@1.0.1(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-logical-overscroll-behavior@1.0.1(postcss@8.4.45)': + '@csstools/postcss-logical-overscroll-behavior@1.0.1(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-logical-resize@2.0.1(postcss@8.4.45)': + '@csstools/postcss-logical-resize@2.0.1(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - '@csstools/postcss-logical-viewport-units@2.0.11(postcss@8.4.45)': + '@csstools/postcss-logical-viewport-units@2.0.11(postcss@8.4.47)': dependencies: '@csstools/css-tokenizer': 2.4.1 - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-media-minmax@1.1.8(postcss@8.4.45)': + '@csstools/postcss-media-minmax@1.1.8(postcss@8.4.47)': dependencies: '@csstools/css-calc': 1.2.4(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 '@csstools/media-query-list-parser': 2.1.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-media-queries-aspect-ratio-number-values@2.0.11(postcss@8.4.45)': + '@csstools/postcss-media-queries-aspect-ratio-number-values@2.0.11(postcss@8.4.47)': dependencies: '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 '@csstools/media-query-list-parser': 2.1.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-nested-calc@3.0.2(postcss@8.4.45)': + '@csstools/postcss-nested-calc@3.0.2(postcss@8.4.47)': dependencies: - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 postcss-value-parser: 4.2.0 - '@csstools/postcss-normalize-display-values@3.0.2(postcss@8.4.45)': + '@csstools/postcss-normalize-display-values@3.0.2(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - '@csstools/postcss-oklab-function@3.0.19(postcss@8.4.45)': + '@csstools/postcss-oklab-function@3.0.19(postcss@8.4.47)': dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-progressive-custom-properties@3.3.0(postcss@8.4.45)': + '@csstools/postcss-progressive-custom-properties@3.3.0(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - '@csstools/postcss-relative-color-syntax@2.0.19(postcss@8.4.45)': + '@csstools/postcss-relative-color-syntax@2.0.19(postcss@8.4.47)': dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - '@csstools/postcss-scope-pseudo-class@3.0.1(postcss@8.4.45)': + '@csstools/postcss-scope-pseudo-class@3.0.1(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - '@csstools/postcss-stepped-value-functions@3.0.10(postcss@8.4.45)': + '@csstools/postcss-stepped-value-functions@3.0.10(postcss@8.4.47)': dependencies: '@csstools/css-calc': 1.2.4(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-text-decoration-shorthand@3.0.7(postcss@8.4.45)': + '@csstools/postcss-text-decoration-shorthand@3.0.7(postcss@8.4.47)': dependencies: '@csstools/color-helpers': 4.2.1 - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - '@csstools/postcss-trigonometric-functions@3.0.10(postcss@8.4.45)': + '@csstools/postcss-trigonometric-functions@3.0.10(postcss@8.4.47)': dependencies: '@csstools/css-calc': 1.2.4(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - postcss: 8.4.45 + postcss: 8.4.47 - '@csstools/postcss-unset-value@3.0.1(postcss@8.4.45)': + '@csstools/postcss-unset-value@3.0.1(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 '@csstools/selector-resolve-nested@1.1.0(postcss-selector-parser@6.1.2)': dependencies: @@ -5143,9 +5169,9 @@ snapshots: dependencies: postcss-selector-parser: 6.1.2 - '@csstools/utilities@1.0.0(postcss@8.4.45)': + '@csstools/utilities@1.0.0(postcss@8.4.47)': dependencies: - postcss: 8.4.45 + postcss: 8.4.47 '@drizzle-team/brocli@0.8.2': {} @@ -5664,9 +5690,9 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@lucia-auth/adapter-drizzle@1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4))(lucia@3.2.0)': + '@lucia-auth/adapter-drizzle@1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.12.0)(postgres@3.4.4))(lucia@3.2.0)': dependencies: - drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4) + drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.12.0)(postgres@3.4.4) lucia: 3.2.0 '@lukeed/csprng@1.1.0': {} @@ -5888,9 +5914,9 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@playwright/test@1.47.0': + '@playwright/test@1.47.1': dependencies: - playwright: 1.47.0 + playwright: 1.47.1 '@polka/url@1.0.0-next.25': {} @@ -6063,41 +6089,41 @@ snapshots: '@sodaru/yup-to-json-schema@2.0.1': optional: true - '@sveltejs/adapter-auto@3.2.4(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))': + '@sveltejs/adapter-auto@3.2.4(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))': dependencies: - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) import-meta-resolve: 4.1.0 - '@sveltejs/adapter-node@5.2.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))': + '@sveltejs/adapter-node@5.2.2(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))': dependencies: '@rollup/plugin-commonjs': 26.0.1(rollup@4.21.2) '@rollup/plugin-json': 6.1.0(rollup@4.21.2) '@rollup/plugin-node-resolve': 15.2.3(rollup@4.21.2) - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) rollup: 4.21.2 - '@sveltejs/adapter-vercel@5.4.3(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))': + '@sveltejs/adapter-vercel@5.4.3(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))': dependencies: - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) '@vercel/nft': 0.27.4 esbuild: 0.21.5 transitivePeerDependencies: - encoding - supports-color - '@sveltejs/enhanced-img@0.3.4(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))': + '@sveltejs/enhanced-img@0.3.7(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))': dependencies: magic-string: 0.30.11 svelte: 5.0.0-next.175 svelte-parse-markup: 0.1.5(svelte@5.0.0-next.175) - vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.5(@types/node@20.16.5)(sass@1.78.0) vite-imagetools: 7.0.4(rollup@4.21.2) transitivePeerDependencies: - rollup - '@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))': + '@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.0.0 @@ -6111,28 +6137,28 @@ snapshots: sirv: 2.0.4 svelte: 5.0.0-next.175 tiny-glob: 0.2.9 - vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.5(@types/node@20.16.5)(sass@1.78.0) - '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))': + '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) debug: 4.3.6 svelte: 5.0.0-next.175 - vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.5(@types/node@20.16.5)(sass@1.78.0) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))': + '@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) debug: 4.3.6 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.11 svelte: 5.0.0-next.175 svelte-hmr: 0.16.0(svelte@5.0.0-next.175) - vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) - vitefu: 0.2.5(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + vite: 5.4.5(@types/node@20.16.5)(sass@1.78.0) + vitefu: 0.2.5(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) transitivePeerDependencies: - supports-color @@ -6166,13 +6192,13 @@ snapshots: dependencies: undici-types: 6.19.8 - '@types/pg@8.11.6': + '@types/pg@8.11.10': dependencies: '@types/node': 20.16.5 pg-protocol: 1.6.1 pg-types: 4.0.2 - '@types/pg@8.11.9': + '@types/pg@8.11.6': dependencies: '@types/node': 20.16.5 pg-protocol: 1.6.1 @@ -6185,6 +6211,20 @@ snapshots: '@types/validator@13.12.1': optional: true + '@typeschema/class-validator@0.2.0(@types/json-schema@7.0.15)(class-validator@0.14.1)': + dependencies: + '@typeschema/core': 0.14.0(@types/json-schema@7.0.15) + optionalDependencies: + class-validator: 0.14.1 + transitivePeerDependencies: + - '@types/json-schema' + optional: true + + '@typeschema/core@0.14.0(@types/json-schema@7.0.15)': + optionalDependencies: + '@types/json-schema': 7.0.15 + optional: true + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0)(typescript@5.6.2)': dependencies: '@eslint-community/regexpp': 4.11.0 @@ -6428,14 +6468,14 @@ snapshots: async-sema@3.1.1: {} - autoprefixer@10.4.20(postcss@8.4.45): + autoprefixer@10.4.20(postcss@8.4.47): dependencies: browserslist: 4.23.3 caniuse-lite: 1.0.30001655 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.1.0 - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 axobject-query@4.1.0: {} @@ -6578,6 +6618,13 @@ snapshots: chownr@2.0.0: {} + class-validator@0.14.1: + dependencies: + '@types/validator': 13.12.1 + libphonenumber-js: 1.11.8 + validator: 13.12.0 + optional: true + class-variance-authority@0.7.0: dependencies: clsx: 2.0.0 @@ -6658,25 +6705,25 @@ snapshots: css-background-parser@0.1.0: {} - css-blank-pseudo@6.0.2(postcss@8.4.45): + css-blank-pseudo@6.0.2(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 css-box-shadow@1.0.0-3: {} css-color-keywords@1.0.0: {} - css-has-pseudo@6.0.5(postcss@8.4.45): + css-has-pseudo@6.0.5(postcss@8.4.47): dependencies: '@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.1.2) - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 postcss-value-parser: 4.2.0 - css-prefers-color-scheme@9.0.1(postcss@8.4.45): + css-prefers-color-scheme@9.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 css-to-react-native@3.2.0: dependencies: @@ -6687,7 +6734,7 @@ snapshots: css-tree@2.3.1: dependencies: mdn-data: 2.0.30 - source-map-js: 1.2.0 + source-map-js: 1.2.1 cssdb@8.1.0: {} @@ -6769,16 +6816,16 @@ snapshots: transitivePeerDependencies: - supports-color - drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4): + drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.12.0)(postgres@3.4.4): optionalDependencies: '@neondatabase/serverless': 0.9.5 - '@types/pg': 8.11.9 + '@types/pg': 8.11.10 pg: 8.12.0 postgres: 3.4.4 - drizzle-zod@0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4))(zod@3.23.8): + drizzle-zod@0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.12.0)(postgres@3.4.4))(zod@3.23.8): dependencies: - drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.9)(pg@8.12.0)(postgres@3.4.4) + drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.12.0)(postgres@3.4.4) zod: 3.23.8 eastasianwidth@0.2.0: {} @@ -6945,9 +6992,9 @@ snapshots: eslint-compat-utils: 0.5.1(eslint@8.57.0) esutils: 2.0.3 known-css-properties: 0.30.0 - postcss: 8.4.45 - postcss-load-config: 3.1.4(postcss@8.4.45)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) - postcss-safe-parser: 6.0.0(postcss@8.4.45) + postcss: 8.4.47 + postcss-load-config: 3.1.4(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + postcss-safe-parser: 6.0.0(postcss@8.4.47) postcss-selector-parser: 6.1.2 semver: 7.6.3 svelte-eslint-parser: 0.41.0(svelte@5.0.0-next.175) @@ -7170,11 +7217,11 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)): + formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.18.0(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)): dependencies: nanoid: 5.0.7 svelte: 5.0.0-next.175 - sveltekit-superforms: 2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175) + sveltekit-superforms: 2.18.0(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) forwarded@0.2.0: {} @@ -7488,6 +7535,9 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + libphonenumber-js@1.11.8: + optional: true + lilconfig@2.1.0: {} lilconfig@3.1.2: {} @@ -7884,281 +7934,281 @@ snapshots: mlly: 1.7.1 pathe: 1.1.2 - playwright-core@1.47.0: {} + playwright-core@1.47.1: {} - playwright@1.47.0: + playwright@1.47.1: dependencies: - playwright-core: 1.47.0 + playwright-core: 1.47.1 optionalDependencies: fsevents: 2.3.2 pngjs@5.0.0: {} - postcss-attribute-case-insensitive@6.0.3(postcss@8.4.45): + postcss-attribute-case-insensitive@6.0.3(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - postcss-clamp@4.1.0(postcss@8.4.45): + postcss-clamp@4.1.0(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-color-functional-notation@6.0.14(postcss@8.4.45): + postcss-color-functional-notation@6.0.14(postcss@8.4.47): dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - postcss-color-hex-alpha@9.0.4(postcss@8.4.45): + postcss-color-hex-alpha@9.0.4(postcss@8.4.47): dependencies: - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-color-rebeccapurple@9.0.3(postcss@8.4.45): + postcss-color-rebeccapurple@9.0.3(postcss@8.4.47): dependencies: - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-custom-media@10.0.8(postcss@8.4.45): + postcss-custom-media@10.0.8(postcss@8.4.47): dependencies: '@csstools/cascade-layer-name-parser': 1.0.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 '@csstools/media-query-list-parser': 2.1.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) - postcss: 8.4.45 + postcss: 8.4.47 - postcss-custom-properties@13.3.12(postcss@8.4.45): + postcss-custom-properties@13.3.12(postcss@8.4.47): dependencies: '@csstools/cascade-layer-name-parser': 1.0.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-custom-selectors@7.1.12(postcss@8.4.45): + postcss-custom-selectors@7.1.12(postcss@8.4.47): dependencies: '@csstools/cascade-layer-name-parser': 1.0.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - postcss-dir-pseudo-class@8.0.1(postcss@8.4.45): + postcss-dir-pseudo-class@8.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - postcss-double-position-gradients@5.0.7(postcss@8.4.45): + postcss-double-position-gradients@5.0.7(postcss@8.4.47): dependencies: - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-focus-visible@9.0.1(postcss@8.4.45): + postcss-focus-visible@9.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - postcss-focus-within@8.0.1(postcss@8.4.45): + postcss-focus-within@8.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - postcss-font-variant@5.0.0(postcss@8.4.45): + postcss-font-variant@5.0.0(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - postcss-gap-properties@5.0.1(postcss@8.4.45): + postcss-gap-properties@5.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - postcss-image-set-function@6.0.3(postcss@8.4.45): + postcss-image-set-function@6.0.3(postcss@8.4.47): dependencies: - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-import@15.1.0(postcss@8.4.45): + postcss-import@15.1.0(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.8 - postcss-import@16.1.0(postcss@8.4.45): + postcss-import@16.1.0(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.8 - postcss-js@4.0.1(postcss@8.4.45): + postcss-js@4.0.1(postcss@8.4.47): dependencies: camelcase-css: 2.0.1 - postcss: 8.4.45 + postcss: 8.4.47 - postcss-lab-function@6.0.19(postcss@8.4.45): + postcss-lab-function@6.0.19(postcss@8.4.47): dependencies: '@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': 2.4.1 - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/utilities': 1.0.0(postcss@8.4.45) - postcss: 8.4.45 + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/utilities': 1.0.0(postcss@8.4.47) + postcss: 8.4.47 - postcss-load-config@3.1.4(postcss@8.4.45)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): + postcss-load-config@3.1.4(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): dependencies: lilconfig: 2.1.0 yaml: 1.10.2 optionalDependencies: - postcss: 8.4.45 + postcss: 8.4.47 ts-node: 10.9.2(@types/node@20.16.5)(typescript@5.6.2) - postcss-load-config@4.0.2(postcss@8.4.45)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): + postcss-load-config@4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): dependencies: lilconfig: 3.1.2 yaml: 2.5.1 optionalDependencies: - postcss: 8.4.45 + postcss: 8.4.47 ts-node: 10.9.2(@types/node@20.16.5)(typescript@5.6.2) - postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1): + postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1): dependencies: lilconfig: 3.1.2 yaml: 2.5.1 optionalDependencies: jiti: 1.21.6 - postcss: 8.4.45 + postcss: 8.4.47 tsx: 4.19.1 - postcss-logical@7.0.1(postcss@8.4.45): + postcss-logical@7.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-nested@6.2.0(postcss@8.4.45): + postcss-nested@6.2.0(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - postcss-nesting@12.1.5(postcss@8.4.45): + postcss-nesting@12.1.5(postcss@8.4.47): dependencies: '@csstools/selector-resolve-nested': 1.1.0(postcss-selector-parser@6.1.2) '@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.1.2) - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - postcss-opacity-percentage@2.0.0(postcss@8.4.45): + postcss-opacity-percentage@2.0.0(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - postcss-overflow-shorthand@5.0.1(postcss@8.4.45): + postcss-overflow-shorthand@5.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-page-break@3.0.4(postcss@8.4.45): + postcss-page-break@3.0.4(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - postcss-place@9.0.1(postcss@8.4.45): + postcss-place@9.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - postcss-preset-env@9.6.0(postcss@8.4.45): + postcss-preset-env@9.6.0(postcss@8.4.47): dependencies: - '@csstools/postcss-cascade-layers': 4.0.6(postcss@8.4.45) - '@csstools/postcss-color-function': 3.0.19(postcss@8.4.45) - '@csstools/postcss-color-mix-function': 2.0.19(postcss@8.4.45) - '@csstools/postcss-content-alt-text': 1.0.0(postcss@8.4.45) - '@csstools/postcss-exponential-functions': 1.0.9(postcss@8.4.45) - '@csstools/postcss-font-format-keywords': 3.0.2(postcss@8.4.45) - '@csstools/postcss-gamut-mapping': 1.0.11(postcss@8.4.45) - '@csstools/postcss-gradients-interpolation-method': 4.0.20(postcss@8.4.45) - '@csstools/postcss-hwb-function': 3.0.18(postcss@8.4.45) - '@csstools/postcss-ic-unit': 3.0.7(postcss@8.4.45) - '@csstools/postcss-initial': 1.0.1(postcss@8.4.45) - '@csstools/postcss-is-pseudo-class': 4.0.8(postcss@8.4.45) - '@csstools/postcss-light-dark-function': 1.0.8(postcss@8.4.45) - '@csstools/postcss-logical-float-and-clear': 2.0.1(postcss@8.4.45) - '@csstools/postcss-logical-overflow': 1.0.1(postcss@8.4.45) - '@csstools/postcss-logical-overscroll-behavior': 1.0.1(postcss@8.4.45) - '@csstools/postcss-logical-resize': 2.0.1(postcss@8.4.45) - '@csstools/postcss-logical-viewport-units': 2.0.11(postcss@8.4.45) - '@csstools/postcss-media-minmax': 1.1.8(postcss@8.4.45) - '@csstools/postcss-media-queries-aspect-ratio-number-values': 2.0.11(postcss@8.4.45) - '@csstools/postcss-nested-calc': 3.0.2(postcss@8.4.45) - '@csstools/postcss-normalize-display-values': 3.0.2(postcss@8.4.45) - '@csstools/postcss-oklab-function': 3.0.19(postcss@8.4.45) - '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.45) - '@csstools/postcss-relative-color-syntax': 2.0.19(postcss@8.4.45) - '@csstools/postcss-scope-pseudo-class': 3.0.1(postcss@8.4.45) - '@csstools/postcss-stepped-value-functions': 3.0.10(postcss@8.4.45) - '@csstools/postcss-text-decoration-shorthand': 3.0.7(postcss@8.4.45) - '@csstools/postcss-trigonometric-functions': 3.0.10(postcss@8.4.45) - '@csstools/postcss-unset-value': 3.0.1(postcss@8.4.45) - autoprefixer: 10.4.20(postcss@8.4.45) + '@csstools/postcss-cascade-layers': 4.0.6(postcss@8.4.47) + '@csstools/postcss-color-function': 3.0.19(postcss@8.4.47) + '@csstools/postcss-color-mix-function': 2.0.19(postcss@8.4.47) + '@csstools/postcss-content-alt-text': 1.0.0(postcss@8.4.47) + '@csstools/postcss-exponential-functions': 1.0.9(postcss@8.4.47) + '@csstools/postcss-font-format-keywords': 3.0.2(postcss@8.4.47) + '@csstools/postcss-gamut-mapping': 1.0.11(postcss@8.4.47) + '@csstools/postcss-gradients-interpolation-method': 4.0.20(postcss@8.4.47) + '@csstools/postcss-hwb-function': 3.0.18(postcss@8.4.47) + '@csstools/postcss-ic-unit': 3.0.7(postcss@8.4.47) + '@csstools/postcss-initial': 1.0.1(postcss@8.4.47) + '@csstools/postcss-is-pseudo-class': 4.0.8(postcss@8.4.47) + '@csstools/postcss-light-dark-function': 1.0.8(postcss@8.4.47) + '@csstools/postcss-logical-float-and-clear': 2.0.1(postcss@8.4.47) + '@csstools/postcss-logical-overflow': 1.0.1(postcss@8.4.47) + '@csstools/postcss-logical-overscroll-behavior': 1.0.1(postcss@8.4.47) + '@csstools/postcss-logical-resize': 2.0.1(postcss@8.4.47) + '@csstools/postcss-logical-viewport-units': 2.0.11(postcss@8.4.47) + '@csstools/postcss-media-minmax': 1.1.8(postcss@8.4.47) + '@csstools/postcss-media-queries-aspect-ratio-number-values': 2.0.11(postcss@8.4.47) + '@csstools/postcss-nested-calc': 3.0.2(postcss@8.4.47) + '@csstools/postcss-normalize-display-values': 3.0.2(postcss@8.4.47) + '@csstools/postcss-oklab-function': 3.0.19(postcss@8.4.47) + '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.47) + '@csstools/postcss-relative-color-syntax': 2.0.19(postcss@8.4.47) + '@csstools/postcss-scope-pseudo-class': 3.0.1(postcss@8.4.47) + '@csstools/postcss-stepped-value-functions': 3.0.10(postcss@8.4.47) + '@csstools/postcss-text-decoration-shorthand': 3.0.7(postcss@8.4.47) + '@csstools/postcss-trigonometric-functions': 3.0.10(postcss@8.4.47) + '@csstools/postcss-unset-value': 3.0.1(postcss@8.4.47) + autoprefixer: 10.4.20(postcss@8.4.47) browserslist: 4.23.3 - css-blank-pseudo: 6.0.2(postcss@8.4.45) - css-has-pseudo: 6.0.5(postcss@8.4.45) - css-prefers-color-scheme: 9.0.1(postcss@8.4.45) + css-blank-pseudo: 6.0.2(postcss@8.4.47) + css-has-pseudo: 6.0.5(postcss@8.4.47) + css-prefers-color-scheme: 9.0.1(postcss@8.4.47) cssdb: 8.1.0 - postcss: 8.4.45 - postcss-attribute-case-insensitive: 6.0.3(postcss@8.4.45) - postcss-clamp: 4.1.0(postcss@8.4.45) - postcss-color-functional-notation: 6.0.14(postcss@8.4.45) - postcss-color-hex-alpha: 9.0.4(postcss@8.4.45) - postcss-color-rebeccapurple: 9.0.3(postcss@8.4.45) - postcss-custom-media: 10.0.8(postcss@8.4.45) - postcss-custom-properties: 13.3.12(postcss@8.4.45) - postcss-custom-selectors: 7.1.12(postcss@8.4.45) - postcss-dir-pseudo-class: 8.0.1(postcss@8.4.45) - postcss-double-position-gradients: 5.0.7(postcss@8.4.45) - postcss-focus-visible: 9.0.1(postcss@8.4.45) - postcss-focus-within: 8.0.1(postcss@8.4.45) - postcss-font-variant: 5.0.0(postcss@8.4.45) - postcss-gap-properties: 5.0.1(postcss@8.4.45) - postcss-image-set-function: 6.0.3(postcss@8.4.45) - postcss-lab-function: 6.0.19(postcss@8.4.45) - postcss-logical: 7.0.1(postcss@8.4.45) - postcss-nesting: 12.1.5(postcss@8.4.45) - postcss-opacity-percentage: 2.0.0(postcss@8.4.45) - postcss-overflow-shorthand: 5.0.1(postcss@8.4.45) - postcss-page-break: 3.0.4(postcss@8.4.45) - postcss-place: 9.0.1(postcss@8.4.45) - postcss-pseudo-class-any-link: 9.0.2(postcss@8.4.45) - postcss-replace-overflow-wrap: 4.0.0(postcss@8.4.45) - postcss-selector-not: 7.0.2(postcss@8.4.45) + postcss: 8.4.47 + postcss-attribute-case-insensitive: 6.0.3(postcss@8.4.47) + postcss-clamp: 4.1.0(postcss@8.4.47) + postcss-color-functional-notation: 6.0.14(postcss@8.4.47) + postcss-color-hex-alpha: 9.0.4(postcss@8.4.47) + postcss-color-rebeccapurple: 9.0.3(postcss@8.4.47) + postcss-custom-media: 10.0.8(postcss@8.4.47) + postcss-custom-properties: 13.3.12(postcss@8.4.47) + postcss-custom-selectors: 7.1.12(postcss@8.4.47) + postcss-dir-pseudo-class: 8.0.1(postcss@8.4.47) + postcss-double-position-gradients: 5.0.7(postcss@8.4.47) + postcss-focus-visible: 9.0.1(postcss@8.4.47) + postcss-focus-within: 8.0.1(postcss@8.4.47) + postcss-font-variant: 5.0.0(postcss@8.4.47) + postcss-gap-properties: 5.0.1(postcss@8.4.47) + postcss-image-set-function: 6.0.3(postcss@8.4.47) + postcss-lab-function: 6.0.19(postcss@8.4.47) + postcss-logical: 7.0.1(postcss@8.4.47) + postcss-nesting: 12.1.5(postcss@8.4.47) + postcss-opacity-percentage: 2.0.0(postcss@8.4.47) + postcss-overflow-shorthand: 5.0.1(postcss@8.4.47) + postcss-page-break: 3.0.4(postcss@8.4.47) + postcss-place: 9.0.1(postcss@8.4.47) + postcss-pseudo-class-any-link: 9.0.2(postcss@8.4.47) + postcss-replace-overflow-wrap: 4.0.0(postcss@8.4.47) + postcss-selector-not: 7.0.2(postcss@8.4.47) - postcss-pseudo-class-any-link@9.0.2(postcss@8.4.45): + postcss-pseudo-class-any-link@9.0.2(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 - postcss-replace-overflow-wrap@4.0.0(postcss@8.4.45): + postcss-replace-overflow-wrap@4.0.0(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - postcss-safe-parser@6.0.0(postcss@8.4.45): + postcss-safe-parser@6.0.0(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - postcss-scss@4.0.9(postcss@8.4.45): + postcss-scss@4.0.9(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 - postcss-selector-not@7.0.2(postcss@8.4.45): + postcss-selector-not@7.0.2(postcss@8.4.47): dependencies: - postcss: 8.4.45 + postcss: 8.4.47 postcss-selector-parser: 6.1.2 postcss-selector-parser@6.1.2: @@ -8168,11 +8218,11 @@ snapshots: postcss-value-parser@4.2.0: {} - postcss@8.4.45: + postcss@8.4.47: dependencies: nanoid: 3.3.7 picocolors: 1.1.0 - source-map-js: 1.2.0 + source-map-js: 1.2.1 postgres-array@2.0.0: {} @@ -8502,6 +8552,8 @@ snapshots: source-map-js@1.2.0: {} + source-map-js@1.2.1: {} + source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 @@ -8578,14 +8630,14 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-check@3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175): + svelte-check@3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.78.0)(svelte@5.0.0-next.175): dependencies: '@jridgewell/trace-mapping': 0.3.25 chokidar: 3.6.0 picocolors: 1.1.0 sade: 1.8.1 svelte: 5.0.0-next.175 - svelte-preprocess: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2) + svelte-preprocess: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2) typescript: 5.6.2 transitivePeerDependencies: - '@babel/core' @@ -8603,8 +8655,8 @@ snapshots: eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 espree: 9.6.1 - postcss: 8.4.45 - postcss-scss: 4.0.9(postcss@8.4.45) + postcss: 8.4.47 + postcss-scss: 4.0.9(postcss@8.4.47) optionalDependencies: svelte: 5.0.0-next.175 @@ -8641,7 +8693,7 @@ snapshots: dependencies: svelte: 5.0.0-next.175 - svelte-preprocess@5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2): + svelte-preprocess@5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2): dependencies: '@types/pug': 2.0.10 detect-indent: 6.1.0 @@ -8650,17 +8702,17 @@ snapshots: strip-indent: 3.0.0 svelte: 5.0.0-next.175 optionalDependencies: - postcss: 8.4.45 - postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1) + postcss: 8.4.47 + postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1) sass: 1.78.0 typescript: 5.6.2 - svelte-preprocess@6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1))(postcss@8.4.45)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2): + svelte-preprocess@6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2): dependencies: svelte: 5.0.0-next.175 optionalDependencies: - postcss: 8.4.45 - postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.45)(tsx@4.19.1) + postcss: 8.4.47 + postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1) sass: 1.78.0 typescript: 5.6.2 @@ -8715,19 +8767,19 @@ snapshots: magic-string: 0.30.11 zimmerframe: 1.1.2 - sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175): + sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) svelte: 5.0.0-next.175 - sveltekit-rate-limiter@0.5.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0))): + sveltekit-rate-limiter@0.5.2(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))): dependencies: '@isaacs/ttlcache': 1.4.1 - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) - sveltekit-superforms@2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175): + sveltekit-superforms@2.18.0(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) devalue: 5.0.0 just-clone: 6.2.0 memoize-weak: 1.0.2 @@ -8738,8 +8790,10 @@ snapshots: '@gcornut/valibot-json-schema': 0.31.0 '@sinclair/typebox': 0.32.35 '@sodaru/yup-to-json-schema': 2.0.1 + '@typeschema/class-validator': 0.2.0(@types/json-schema@7.0.15)(class-validator@0.14.1) '@vinejs/vine': 1.8.0 arktype: 2.0.0-beta.0 + class-validator: 0.14.1 joi: 17.13.3 json-schema-to-ts: 3.1.1 superstruct: 2.0.2 @@ -8747,6 +8801,8 @@ snapshots: yup: 1.4.0 zod: 3.23.8 zod-to-json-schema: 3.23.3(zod@3.23.8) + transitivePeerDependencies: + - '@types/json-schema' tabbable@6.2.0: {} @@ -8777,11 +8833,11 @@ snapshots: normalize-path: 3.0.0 object-hash: 3.0.0 picocolors: 1.1.0 - postcss: 8.4.45 - postcss-import: 15.1.0(postcss@8.4.45) - postcss-js: 4.0.1(postcss@8.4.45) - postcss-load-config: 4.0.2(postcss@8.4.45)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) - postcss-nested: 6.2.0(postcss@8.4.45) + postcss: 8.4.47 + postcss-import: 15.1.0(postcss@8.4.47) + postcss-js: 4.0.1(postcss@8.4.47) + postcss-load-config: 4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + postcss-nested: 6.2.0(postcss@8.4.47) postcss-selector-parser: 6.1.2 resolve: 1.22.8 sucrase: 3.35.0 @@ -8964,7 +9020,7 @@ snapshots: debug: 4.3.6 pathe: 1.1.2 picocolors: 1.1.0 - vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.5(@types/node@20.16.5)(sass@1.78.0) transitivePeerDependencies: - '@types/node' - less @@ -8976,19 +9032,19 @@ snapshots: - supports-color - terser - vite@5.4.4(@types/node@20.16.5)(sass@1.78.0): + vite@5.4.5(@types/node@20.16.5)(sass@1.78.0): dependencies: esbuild: 0.21.5 - postcss: 8.4.45 + postcss: 8.4.47 rollup: 4.21.2 optionalDependencies: '@types/node': 20.16.5 fsevents: 2.3.3 sass: 1.78.0 - vitefu@0.2.5(vite@5.4.4(@types/node@20.16.5)(sass@1.78.0)): + vitefu@0.2.5(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)): optionalDependencies: - vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.5(@types/node@20.16.5)(sass@1.78.0) vitest@1.6.0(@types/node@20.16.5)(sass@1.78.0): dependencies: @@ -9009,7 +9065,7 @@ snapshots: strip-literal: 2.1.0 tinybench: 2.9.0 tinypool: 0.8.4 - vite: 5.4.4(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.5(@types/node@20.16.5)(sass@1.78.0) vite-node: 1.6.0(@types/node@20.16.5)(sass@1.78.0) why-is-node-running: 2.3.0 optionalDependencies: diff --git a/src/lib/server/api/common/env.ts b/src/lib/server/api/common/env.ts index 17796e8..95b35c4 100644 --- a/src/lib/server/api/common/env.ts +++ b/src/lib/server/api/common/env.ts @@ -17,6 +17,8 @@ const EnvSchema = z.object({ DATABASE_DB: z.string(), DB_MIGRATING: stringBoolean, DB_SEEDING: stringBoolean, + GITHUB_CLIENT_ID: z.string(), + GITHUB_CLIENT_SECRET: z.string(), NODE_ENV: z.string().default('development'), ORIGIN: z.string(), PUBLIC_SITE_NAME: z.string(), diff --git a/src/lib/server/api/controllers/collection.controller.ts b/src/lib/server/api/controllers/collection.controller.ts index 86dfcc5..5cc94cd 100644 --- a/src/lib/server/api/controllers/collection.controller.ts +++ b/src/lib/server/api/controllers/collection.controller.ts @@ -18,6 +18,11 @@ export class CollectionController extends Controller { console.log('collections service', collections) return c.json({ collections }) }) + .get('/count', requireAuth, async (c) => { + const user = c.var.user + const collections = await this.collectionsService.findAllByUserIdWithDetails(user.id) + return c.json({ collections }) + }) .get('/:cuid', requireAuth, async (c) => { const cuid = c.req.param('cuid') const collection = await this.collectionsService.findOneByCuid(cuid) diff --git a/src/lib/server/api/controllers/oauth.controller.ts b/src/lib/server/api/controllers/oauth.controller.ts new file mode 100644 index 0000000..4b1bcb4 --- /dev/null +++ b/src/lib/server/api/controllers/oauth.controller.ts @@ -0,0 +1,55 @@ +import 'reflect-metadata' +import { Controller } from '$lib/server/api/common/types/controller' +import { LuciaService } from '$lib/server/api/services/lucia.service' +import { OAuthService } from '$lib/server/api/services/oauth.service' +import { github } from '$lib/server/auth' +import { OAuth2RequestError } from 'arctic' +import { getCookie } from 'hono/cookie' +import { inject, injectable } from 'tsyringe' + +@injectable() +export class OAuthController extends Controller { + constructor( + @inject(LuciaService) private luciaService: LuciaService, + @inject(OAuthService) private readonly oauthService: OAuthService) { + super() + } + + routes() { + return this.controller + .get('/github', async (c) => { + try { + const code = c.req.query('code')?.toString() ?? null + const state = c.req.query('state')?.toString() ?? null + const storedState = getCookie(c).github_oauth_state ?? null + + if (!code || !state || !storedState || state !== storedState) { + return c.body(null, 400) + } + + const tokens = await github.validateAuthorizationCode(code) + const githubUserResponse = await fetch("https://api.github.com/user", { + headers: { + Authorization: `Bearer ${tokens.accessToken}` + } + }); + const githubUser: GitHubUser = await githubUserResponse.json(); + + const token = await this.oauthService.handleOAuthUser(githubUser.id, githubUser.login, 'github') + return c.json({ token }) + } catch (error) { + // the specific error message depends on the provider + if (error instanceof OAuth2RequestError) { + // invalid code + return c.body(null, 400) + } + return c.body(null, 500) + } + }) + } +} + +interface GitHubUser { + id: number; + login: string; +} \ No newline at end of file diff --git a/src/lib/server/api/databases/tables/collections.table.ts b/src/lib/server/api/databases/tables/collections.table.ts index 715bf4d..4b483df 100644 --- a/src/lib/server/api/databases/tables/collections.table.ts +++ b/src/lib/server/api/databases/tables/collections.table.ts @@ -3,6 +3,7 @@ import { type InferSelectModel, relations } from 'drizzle-orm' import { pgTable, text, uuid } from 'drizzle-orm/pg-core' import { timestamps } from '../../common/utils/table' import { usersTable } from './users.table' +import { collection_items } from './collectionItems.table' export const collections = pgTable('collections', { id: uuid('id').primaryKey().defaultRandom(), @@ -16,11 +17,12 @@ export const collections = pgTable('collections', { ...timestamps, }) -export const collection_relations = relations(collections, ({ one }) => ({ +export const collection_relations = relations(collections, ({ one, many }) => ({ user: one(usersTable, { fields: [collections.user_id], references: [usersTable.id], }), + collection_items: many(collection_items), })) export type Collections = InferSelectModel diff --git a/src/lib/server/api/index.ts b/src/lib/server/api/index.ts index 8dd5adb..f39f32a 100644 --- a/src/lib/server/api/index.ts +++ b/src/lib/server/api/index.ts @@ -44,6 +44,7 @@ const routes = app .route('/me', container.resolve(IamController).routes()) .route('/user', container.resolve(UserController).routes()) .route('/login', container.resolve(LoginController).routes()) + .route('/oauth', container.resolve(OAuthController).routes()) .route('/signup', container.resolve(SignupController).routes()) .route('/wishlists', container.resolve(WishlistController).routes()) .route('/collections', container.resolve(CollectionController).routes()) diff --git a/src/lib/server/api/repositories/collections.repository.ts b/src/lib/server/api/repositories/collections.repository.ts index c6f097b..bea63ed 100644 --- a/src/lib/server/api/repositories/collections.repository.ts +++ b/src/lib/server/api/repositories/collections.repository.ts @@ -2,7 +2,7 @@ import { takeFirstOrThrow } from '$lib/server/api/common/utils/repository' import { DrizzleService } from '$lib/server/api/services/drizzle.service' import { type InferInsertModel, eq } from 'drizzle-orm' import { inject, injectable } from 'tsyringe' -import { collections } from '../databases/tables' +import { collection_items, collections } from '../databases/tables' export type CreateCollection = InferInsertModel export type UpdateCollection = Partial @@ -51,6 +51,23 @@ export class CollectionsRepository { }) } + async findAllByUserIdWithDetails(userId: string, db = this.drizzle.db) { + return db.query.collections.findMany({ + where: eq(collections.user_id, userId), + columns: { + cuid: true, + name: true, + }, + with: { + collection_items: { + columns: { + cuid: true + } + }, + } + }) + } + async create(data: CreateCollection, db = this.drizzle.db) { return db.insert(collections).values(data).returning().then(takeFirstOrThrow) } diff --git a/src/lib/server/api/repositories/federated_identity.repository.ts b/src/lib/server/api/repositories/federated_identity.repository.ts new file mode 100644 index 0000000..a67009e --- /dev/null +++ b/src/lib/server/api/repositories/federated_identity.repository.ts @@ -0,0 +1,25 @@ +import { inject, injectable } from "tsyringe"; +import { DrizzleService } from "../services/drizzle.service"; +import { and, eq, type InferInsertModel } from "drizzle-orm"; +import { federatedIdentityTable } from "../databases/tables"; +import { takeFirstOrThrow } from "../common/utils/repository"; + +export type CreateFederatedIdentity = InferInsertModel + +@injectable() +export class FederatedIdentityRepository { + + constructor( + @inject(DrizzleService) private readonly drizzle: DrizzleService + ) { } + + async findOneByUserIdAndProvider(userId: string, provider: string) { + return this.drizzle.db.query.federatedIdentityTable.findFirst({ + where: and(eq(federatedIdentityTable.user_id, userId), eq(federatedIdentityTable.identity_provider, provider)) + }) + } + + async create(data: CreateFederatedIdentity, db = this.drizzle.db) { + return db.insert(federatedIdentityTable).values(data).returning().then(takeFirstOrThrow) + } +} \ No newline at end of file diff --git a/src/lib/server/api/services/collections.service.ts b/src/lib/server/api/services/collections.service.ts index 4e0a009..107ccdf 100644 --- a/src/lib/server/api/services/collections.service.ts +++ b/src/lib/server/api/services/collections.service.ts @@ -16,6 +16,10 @@ export class CollectionsService { return this.collectionsRepository.findAllByUserId(userId); } + async findAllByUserIdWithDetails(userId: string) { + return this.collectionsRepository.findAllByUserIdWithDetails(userId); + } + async findOneById(id: string) { return this.collectionsRepository.findOneById(id); } diff --git a/src/lib/server/api/services/oauth.service.ts b/src/lib/server/api/services/oauth.service.ts new file mode 100644 index 0000000..4432792 --- /dev/null +++ b/src/lib/server/api/services/oauth.service.ts @@ -0,0 +1,54 @@ +import { github } from "$lib/server/auth"; +import { db } from "$lib/server/db"; +import { lucia } from "$lib/server/lucia"; +import type { RequestEvent } from "@sveltejs/kit"; +import { OAuth2RequestError } from "arctic"; +import { generateIdFromEntropySize } from "lucia"; +import { inject, injectable } from "tsyringe"; +import { UsersService } from "./users.service"; +import { FederatedIdentityRepository } from "../repositories/federated_identity.repository"; + +@inejectable() +export class OAuthService { + constructor( + @inject(FederatedIdentityRepository) private readonly federatedIdentityRepository: FederatedIdentityRepository, + @inject(UsersService) private readonly usersService: UsersService + ) {} + + async handleOAuthUser(oauthUserId: number, oauthUsername: string, oauthProvider: string) { + const existingUser = await this.federatedIdentityRepository.findOneByUserIdAndProvider(`${oauthUserId}`, oauthProvider) + + if (existingUser) { + return existingUser.id + } else { + const userId = generateIdFromEntropySize(10); // 16 characters long + + const user = await this.drizzleService.db.transaction(async (trx) => { + const user = await this.usersService.create({ + id: userId, + username: oauthUsername + }, trx); + + await this.federatedIdentityRepository.create({ + identity_provider: oauthProvider, + user_id: userId, + identity_id: `${oauthUserId}` + }, trx); + return user; + }) + + const session = await lucia.createSession(userId, {}); + const sessionCookie = lucia.createSessionCookie(session.id); + event.cookies.set(sessionCookie.name, sessionCookie.value, { + path: ".", + ...sessionCookie.attributes + }); + } + return new Response(null, { + status: 302, + headers: { + Location: "/" + } + }); + } +} \ No newline at end of file diff --git a/src/lib/server/auth.ts b/src/lib/server/auth.ts new file mode 100644 index 0000000..bf0d9aa --- /dev/null +++ b/src/lib/server/auth.ts @@ -0,0 +1,4 @@ +import env from "$lib/server/api/common/env"; +import { GitHub } from "arctic"; + +export const github = new GitHub(env.GITHUB_CLIENT_ID, env.GITHUB_CLIENT_SECRET); diff --git a/src/routes/(app)/(protected)/collections/+page.server.ts b/src/routes/(app)/(protected)/collections/+page.server.ts index 7dc3e2e..881f050 100644 --- a/src/routes/(app)/(protected)/collections/+page.server.ts +++ b/src/routes/(app)/(protected)/collections/+page.server.ts @@ -1,13 +1,12 @@ import { notSignedInMessage } from '$lib/flashMessages' +import { collection_items, collections, gamesTable } from '$lib/server/api/databases/tables' import { db } from '$lib/server/api/packages/drizzle' -import { userNotAuthenticated } from '$lib/server/auth-utils' import { modifyListGameSchema } from '$lib/validations/zod-schemas' import { type Actions, error, fail } from '@sveltejs/kit' import { and, eq } from 'drizzle-orm' import { redirect } from 'sveltekit-flash-message/server' import { zod } from 'sveltekit-superforms/adapters' import { superValidate } from 'sveltekit-superforms/server' -import { collection_items, collections, gamesTable } from '../../../../lib/server/api/databases/tables' export async function load(event) { const { locals } = event @@ -18,23 +17,10 @@ export async function load(event) { } try { - const userCollections = await db.query.collections.findMany({ - columns: { - cuid: true, - name: true, - created_at: true, - }, - where: eq(collections.user_id, authedUser.id), - }) - console.log('collections', userCollections) - - if (userCollections?.length === 0) { - console.log('Collection was not found') - return fail(404, {}) - } + const { data, error } = await locals.api.collections.$get().then(locals.parseApiResponse) return { - collections: userCollections, + collections: data?.collections || [], } } catch (e) { console.error(e) diff --git a/src/routes/(app)/(protected)/collections/+page.svelte b/src/routes/(app)/(protected)/collections/+page.svelte index 81f993f..6d600b9 100644 --- a/src/routes/(app)/(protected)/collections/+page.svelte +++ b/src/routes/(app)/(protected)/collections/+page.svelte @@ -1,24 +1,34 @@ Your Collections | Bored Game +

Your Collections

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

You have no collections

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

Number of items:

+

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

+
+
+ {/each} {/if}
@@ -30,10 +40,6 @@ width: 100%; } - .collections { - margin: 2rem 0; - } - .collection-list { display: grid; grid-template-columns: repeat(3, minmax(200px, 1fr)); diff --git a/src/routes/(auth)/auth/callback/github/+server.ts b/src/routes/(auth)/auth/callback/github/+server.ts new file mode 100644 index 0000000..c58847d --- /dev/null +++ b/src/routes/(auth)/auth/callback/github/+server.ts @@ -0,0 +1,21 @@ +import { github } from "$lib/server/auth"; +import { OAuth2RequestError } from "arctic"; +import { generateIdFromEntropySize } from "lucia"; + +import type { RequestEvent } from "@sveltejs/kit"; + +export async function GET(event: RequestEvent): Promise { + const code = event.url.searchParams.get('code') + const state = event.url.searchParams.get('state') + const { data, error } = await locals.api.oauth.$get({ + params: { + code, + state + } + }) +} + +interface GitHubUser { + id: number; + login: string; +} \ No newline at end of file diff --git a/src/routes/(auth)/login/github/+server.ts b/src/routes/(auth)/login/github/+server.ts new file mode 100644 index 0000000..a93f2f8 --- /dev/null +++ b/src/routes/(auth)/login/github/+server.ts @@ -0,0 +1,18 @@ +import { github } from '$lib/server/auth' +import { redirect } from '@sveltejs/kit' +import { generateState } from 'arctic' + +export async function GET(event) { + const state = generateState(); + const url = await github.createAuthorizationURL(state) + + event.cookies.set('github_state', state, { + path: '/', + secure: import.meta.env.PROD, + httpOnly: true, + maxAge: 60 * 10, + sameSite: 'lax' + }); + + redirect(302, url.toString()) +} \ No newline at end of file From a0b01e5adebad55156bea962431af40fdea434eb Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Tue, 17 Sep 2024 17:32:26 -0700 Subject: [PATCH 11/29] Fixing OAuth flows, passing code and state correctly to hono, and signing in with GitHub. --- .../api/controllers/oauth.controller.ts | 85 ++++++++++------- src/lib/server/api/index.ts | 1 + .../repositories/collections.repository.ts | 8 +- .../repositories/credentials.repository.ts | 2 +- .../federated_identity.repository.ts | 25 ++--- .../api/repositories/roles.repository.ts | 10 +- .../api/repositories/user_roles.repository.ts | 4 +- .../api/services/collections.service.ts | 47 ++++++---- src/lib/server/api/services/oauth.service.ts | 60 ++++-------- .../server/api/services/user_roles.service.ts | 48 ++++++---- src/lib/server/api/services/users.service.ts | 91 ++++++++++++++----- .../server/api/services/wishlists.service.ts | 43 +++++---- .../(auth)/auth/callback/github/+server.ts | 42 +++++---- src/routes/(auth)/login/+page.server.ts | 3 + src/routes/(auth)/login/+page.svelte | 69 +++++++------- src/routes/(auth)/login/github/+server.ts | 14 +-- 16 files changed, 319 insertions(+), 233 deletions(-) diff --git a/src/lib/server/api/controllers/oauth.controller.ts b/src/lib/server/api/controllers/oauth.controller.ts index 4b1bcb4..570f42b 100644 --- a/src/lib/server/api/controllers/oauth.controller.ts +++ b/src/lib/server/api/controllers/oauth.controller.ts @@ -4,52 +4,73 @@ import { LuciaService } from '$lib/server/api/services/lucia.service' import { OAuthService } from '$lib/server/api/services/oauth.service' import { github } from '$lib/server/auth' import { OAuth2RequestError } from 'arctic' -import { getCookie } from 'hono/cookie' +import { getCookie, setCookie } from 'hono/cookie' +import { TimeSpan } from 'oslo' import { inject, injectable } from 'tsyringe' @injectable() export class OAuthController extends Controller { constructor( @inject(LuciaService) private luciaService: LuciaService, - @inject(OAuthService) private readonly oauthService: OAuthService) { + @inject(OAuthService) private oauthService: OAuthService, + ) { super() } routes() { - return this.controller - .get('/github', async (c) => { - try { - const code = c.req.query('code')?.toString() ?? null - const state = c.req.query('state')?.toString() ?? null - const storedState = getCookie(c).github_oauth_state ?? null + return this.controller.get('/github', async (c) => { + try { + const code = c.req.query('code')?.toString() ?? null + const state = c.req.query('state')?.toString() ?? null + const storedState = getCookie(c).github_oauth_state ?? null - if (!code || !state || !storedState || state !== storedState) { - return c.body(null, 400) - } + console.log('code', code, 'state', state, 'storedState', storedState) - const tokens = await github.validateAuthorizationCode(code) - const githubUserResponse = await fetch("https://api.github.com/user", { - headers: { - Authorization: `Bearer ${tokens.accessToken}` - } - }); - const githubUser: GitHubUser = await githubUserResponse.json(); - - const token = await this.oauthService.handleOAuthUser(githubUser.id, githubUser.login, 'github') - return c.json({ token }) - } catch (error) { - // the specific error message depends on the provider - if (error instanceof OAuth2RequestError) { - // invalid code - return c.body(null, 400) - } - return c.body(null, 500) + if (!code || !state || !storedState || state !== storedState) { + return c.body(null, 400) } - }) + + const tokens = await github.validateAuthorizationCode(code) + const githubUserResponse = await fetch('https://api.github.com/user', { + headers: { + Authorization: `Bearer ${tokens.accessToken}`, + }, + }) + const githubUser: GitHubUser = await githubUserResponse.json() + + const userId = await this.oauthService.handleOAuthUser(githubUser.id, githubUser.login, 'github') + + const session = await this.luciaService.lucia.createSession(userId, {}) + const sessionCookie = this.luciaService.lucia.createSessionCookie(session.id) + + setCookie(c, sessionCookie.name, sessionCookie.value, { + path: sessionCookie.attributes.path, + maxAge: + sessionCookie?.attributes?.maxAge && sessionCookie?.attributes?.maxAge < new TimeSpan(365, 'd').seconds() + ? sessionCookie.attributes.maxAge + : new TimeSpan(2, 'w').seconds(), + domain: sessionCookie.attributes.domain, + sameSite: sessionCookie.attributes.sameSite as any, + secure: sessionCookie.attributes.secure, + httpOnly: sessionCookie.attributes.httpOnly, + expires: sessionCookie.attributes.expires, + }) + + return c.json({ message: 'ok' }) + } catch (error) { + console.error(error) + // the specific error message depends on the provider + if (error instanceof OAuth2RequestError) { + // invalid code + return c.body(null, 400) + } + return c.body(null, 500) + } + }) } } interface GitHubUser { - id: number; - login: string; -} \ No newline at end of file + id: number + login: string +} diff --git a/src/lib/server/api/index.ts b/src/lib/server/api/index.ts index f39f32a..3106d86 100644 --- a/src/lib/server/api/index.ts +++ b/src/lib/server/api/index.ts @@ -1,6 +1,7 @@ import 'reflect-metadata' import { CollectionController } from '$lib/server/api/controllers/collection.controller' import { MfaController } from '$lib/server/api/controllers/mfa.controller' +import { OAuthController } from '$lib/server/api/controllers/oauth.controller' import { SignupController } from '$lib/server/api/controllers/signup.controller' import { UserController } from '$lib/server/api/controllers/user.controller' import { WishlistController } from '$lib/server/api/controllers/wishlist.controller' diff --git a/src/lib/server/api/repositories/collections.repository.ts b/src/lib/server/api/repositories/collections.repository.ts index bea63ed..c351714 100644 --- a/src/lib/server/api/repositories/collections.repository.ts +++ b/src/lib/server/api/repositories/collections.repository.ts @@ -2,7 +2,7 @@ import { takeFirstOrThrow } from '$lib/server/api/common/utils/repository' import { DrizzleService } from '$lib/server/api/services/drizzle.service' import { type InferInsertModel, eq } from 'drizzle-orm' import { inject, injectable } from 'tsyringe' -import { collection_items, collections } from '../databases/tables' +import { collections } from '../databases/tables' export type CreateCollection = InferInsertModel export type UpdateCollection = Partial @@ -61,10 +61,10 @@ export class CollectionsRepository { with: { collection_items: { columns: { - cuid: true - } + cuid: true, + }, }, - } + }, }) } diff --git a/src/lib/server/api/repositories/credentials.repository.ts b/src/lib/server/api/repositories/credentials.repository.ts index 0671a40..bdd8de5 100644 --- a/src/lib/server/api/repositories/credentials.repository.ts +++ b/src/lib/server/api/repositories/credentials.repository.ts @@ -44,7 +44,7 @@ export class CredentialsRepository { } async findOneByIdOrThrow(id: string, db = this.drizzle.db) { - const credentials = await this.findOneById(id) + const credentials = await this.findOneById(id, db) if (!credentials) throw Error('Credentials not found') return credentials } diff --git a/src/lib/server/api/repositories/federated_identity.repository.ts b/src/lib/server/api/repositories/federated_identity.repository.ts index a67009e..2180590 100644 --- a/src/lib/server/api/repositories/federated_identity.repository.ts +++ b/src/lib/server/api/repositories/federated_identity.repository.ts @@ -1,25 +1,28 @@ -import { inject, injectable } from "tsyringe"; -import { DrizzleService } from "../services/drizzle.service"; -import { and, eq, type InferInsertModel } from "drizzle-orm"; -import { federatedIdentityTable } from "../databases/tables"; -import { takeFirstOrThrow } from "../common/utils/repository"; +import { type InferInsertModel, and, eq } from 'drizzle-orm' +import { inject, injectable } from 'tsyringe' +import { takeFirstOrThrow } from '../common/utils/repository' +import { federatedIdentityTable } from '../databases/tables' +import { DrizzleService } from '../services/drizzle.service' export type CreateFederatedIdentity = InferInsertModel @injectable() export class FederatedIdentityRepository { - - constructor( - @inject(DrizzleService) private readonly drizzle: DrizzleService - ) { } + constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} async findOneByUserIdAndProvider(userId: string, provider: string) { return this.drizzle.db.query.federatedIdentityTable.findFirst({ - where: and(eq(federatedIdentityTable.user_id, userId), eq(federatedIdentityTable.identity_provider, provider)) + where: and(eq(federatedIdentityTable.user_id, userId), eq(federatedIdentityTable.identity_provider, provider)), + }) + } + + async findOneByFederatedUserIdAndProvider(federatedUserId: string, provider: string) { + return this.drizzle.db.query.federatedIdentityTable.findFirst({ + where: and(eq(federatedIdentityTable.federated_user_id, federatedUserId), eq(federatedIdentityTable.identity_provider, provider)), }) } async create(data: CreateFederatedIdentity, db = this.drizzle.db) { return db.insert(federatedIdentityTable).values(data).returning().then(takeFirstOrThrow) } -} \ No newline at end of file +} diff --git a/src/lib/server/api/repositories/roles.repository.ts b/src/lib/server/api/repositories/roles.repository.ts index 2750d5c..4d9f283 100644 --- a/src/lib/server/api/repositories/roles.repository.ts +++ b/src/lib/server/api/repositories/roles.repository.ts @@ -28,29 +28,29 @@ export class RolesRepository { constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) {} async findOneById(id: string, db = this.drizzle.db) { - return db.query.roles.findFirst({ + return db.query.rolesTable.findFirst({ where: eq(rolesTable.id, id), }) } async findOneByIdOrThrow(id: string, db = this.drizzle.db) { - const role = await this.findOneById(id) + const role = await this.findOneById(id, db) if (!role) throw Error('Role not found') return role } async findAll(db = this.drizzle.db) { - return db.query.roles.findMany() + return db.query.rolesTable.findMany() } async findOneByName(name: string, db = this.drizzle.db) { - return db.query.roles.findFirst({ + return db.query.rolesTable.findFirst({ where: eq(rolesTable.name, name), }) } async findOneByNameOrThrow(name: string, db = this.drizzle.db) { - const role = await this.findOneByName(name) + const role = await this.findOneByName(name, db) if (!role) throw Error('Role not found') return role } diff --git a/src/lib/server/api/repositories/user_roles.repository.ts b/src/lib/server/api/repositories/user_roles.repository.ts index 737bc0c..ef95b74 100644 --- a/src/lib/server/api/repositories/user_roles.repository.ts +++ b/src/lib/server/api/repositories/user_roles.repository.ts @@ -33,8 +33,8 @@ export class UserRolesRepository { }) } - async findOneByIdOrThrow(id: string) { - const userRole = await this.findOneById(id) + async findOneByIdOrThrow(id: string, db = this.drizzle.db) { + const userRole = await this.findOneById(id, db) if (!userRole) throw Error('User not found') return userRole } diff --git a/src/lib/server/api/services/collections.service.ts b/src/lib/server/api/services/collections.service.ts index 107ccdf..ccdbcbc 100644 --- a/src/lib/server/api/services/collections.service.ts +++ b/src/lib/server/api/services/collections.service.ts @@ -1,41 +1,50 @@ -import { inject, injectable } from "tsyringe"; -import { generateRandomAnimalName } from "$lib/utils/randomDataUtil"; -import { CollectionsRepository } from "../repositories/collections.repository"; +import type { db } from '$lib/server/api/packages/drizzle' +import { generateRandomAnimalName } from '$lib/utils/randomDataUtil' +import { inject, injectable } from 'tsyringe' +import { CollectionsRepository } from '../repositories/collections.repository' @injectable() export class CollectionsService { - constructor( - @inject(CollectionsRepository) private readonly collectionsRepository: CollectionsRepository - ) { } + constructor(@inject(CollectionsRepository) private readonly collectionsRepository: CollectionsRepository) {} async findOneByUserId(userId: string) { - return this.collectionsRepository.findOneByUserId(userId); + return this.collectionsRepository.findOneByUserId(userId) } async findAllByUserId(userId: string) { - return this.collectionsRepository.findAllByUserId(userId); + return this.collectionsRepository.findAllByUserId(userId) } async findAllByUserIdWithDetails(userId: string) { - return this.collectionsRepository.findAllByUserIdWithDetails(userId); + return this.collectionsRepository.findAllByUserIdWithDetails(userId) } async findOneById(id: string) { - return this.collectionsRepository.findOneById(id); + return this.collectionsRepository.findOneById(id) } async findOneByCuid(cuid: string) { - return this.collectionsRepository.findOneByCuid(cuid); + return this.collectionsRepository.findOneByCuid(cuid) } - async createEmptyNoName(userId: string) { - return this.createEmpty(userId, null); + async createEmptyNoName(userId: string, trx: Parameters[0]>[0] | null = null) { + return this.createEmpty(userId, null, trx) } - async createEmpty(userId: string, name: string | null) { - return this.collectionsRepository.create({ - user_id: userId, - name: name ?? generateRandomAnimalName(), - }); + async createEmpty(userId: string, name: string | null, trx: Parameters[0]>[0] | null = null) { + if (!trx) { + return this.collectionsRepository.create({ + user_id: userId, + name: name ?? generateRandomAnimalName(), + }) + } + + return this.collectionsRepository.create( + { + user_id: userId, + name: name ?? generateRandomAnimalName(), + }, + trx, + ) } -} \ No newline at end of file +} diff --git a/src/lib/server/api/services/oauth.service.ts b/src/lib/server/api/services/oauth.service.ts index 4432792..0e62baa 100644 --- a/src/lib/server/api/services/oauth.service.ts +++ b/src/lib/server/api/services/oauth.service.ts @@ -1,54 +1,26 @@ -import { github } from "$lib/server/auth"; -import { db } from "$lib/server/db"; -import { lucia } from "$lib/server/lucia"; -import type { RequestEvent } from "@sveltejs/kit"; -import { OAuth2RequestError } from "arctic"; -import { generateIdFromEntropySize } from "lucia"; -import { inject, injectable } from "tsyringe"; -import { UsersService } from "./users.service"; -import { FederatedIdentityRepository } from "../repositories/federated_identity.repository"; +import { inject, injectable } from 'tsyringe' +import { FederatedIdentityRepository } from '../repositories/federated_identity.repository' +import { UsersService } from './users.service' -@inejectable() +@injectable() export class OAuthService { constructor( @inject(FederatedIdentityRepository) private readonly federatedIdentityRepository: FederatedIdentityRepository, - @inject(UsersService) private readonly usersService: UsersService + @inject(UsersService) private readonly usersService: UsersService, ) {} async handleOAuthUser(oauthUserId: number, oauthUsername: string, oauthProvider: string) { - const existingUser = await this.federatedIdentityRepository.findOneByUserIdAndProvider(`${oauthUserId}`, oauthProvider) + const federatedUser = await this.federatedIdentityRepository.findOneByFederatedUserIdAndProvider(`${oauthUserId}`, oauthProvider) - if (existingUser) { - return existingUser.id - } else { - const userId = generateIdFromEntropySize(10); // 16 characters long - - const user = await this.drizzleService.db.transaction(async (trx) => { - const user = await this.usersService.create({ - id: userId, - username: oauthUsername - }, trx); - - await this.federatedIdentityRepository.create({ - identity_provider: oauthProvider, - user_id: userId, - identity_id: `${oauthUserId}` - }, trx); - return user; - }) - - const session = await lucia.createSession(userId, {}); - const sessionCookie = lucia.createSessionCookie(session.id); - event.cookies.set(sessionCookie.name, sessionCookie.value, { - path: ".", - ...sessionCookie.attributes - }); + if (federatedUser) { + return federatedUser.user_id } - return new Response(null, { - status: 302, - headers: { - Location: "/" - } - }); + + const user = await this.usersService.createOAuthUser(oauthUserId, oauthUsername, oauthProvider) + + if (!user) { + throw new Error('Failed to create user') + } + return user.id } -} \ No newline at end of file +} diff --git a/src/lib/server/api/services/user_roles.service.ts b/src/lib/server/api/services/user_roles.service.ts index 04ad1d0..ea80eff 100644 --- a/src/lib/server/api/services/user_roles.service.ts +++ b/src/lib/server/api/services/user_roles.service.ts @@ -1,39 +1,51 @@ -import {inject, injectable} from "tsyringe"; -import {type CreateUserRole, UserRolesRepository} from "$lib/server/api/repositories/user_roles.repository"; -import {RolesService} from "$lib/server/api/services/roles.service"; +import type { db } from '$lib/server/api/packages/drizzle' +import { type CreateUserRole, UserRolesRepository } from '$lib/server/api/repositories/user_roles.repository' +import { RolesService } from '$lib/server/api/services/roles.service' +import { inject, injectable } from 'tsyringe' @injectable() export class UserRolesService { constructor( - @inject(UserRolesRepository) private readonly userRolesRepository: UserRolesRepository, - @inject(RolesService) private readonly rolesService: RolesService - ) { } + @inject(UserRolesRepository) private readonly userRolesRepository: UserRolesRepository, + @inject(RolesService) private readonly rolesService: RolesService, + ) {} async findOneById(id: string) { - return this.userRolesRepository.findOneById(id); + return this.userRolesRepository.findOneById(id) } async findAllByUserId(userId: string) { - return this.userRolesRepository.findAllByUserId(userId); + return this.userRolesRepository.findAllByUserId(userId) } async create(data: CreateUserRole) { - return this.userRolesRepository.create(data); + return this.userRolesRepository.create(data) } - async addRoleToUser(userId: string, roleName: string, primary = false) { + async addRoleToUser(userId: string, roleName: string, primary = false, trx: Parameters[0]>[0] | null = null) { // Find the role by its name - const role = await this.rolesService.findOneByNameOrThrow(roleName); + const role = await this.rolesService.findOneByNameOrThrow(roleName) if (!role || !role.id) { - throw new Error(`Role with name ${roleName} not found`); + throw new Error(`Role with name ${roleName} not found`) + } + + if (!trx) { + return this.userRolesRepository.create({ + user_id: userId, + role_id: role.id, + primary, + }) } // Create a UserRole entry linking the user and the role - return this.userRolesRepository.create({ - user_id: userId, - role_id: role.id, - primary, - }); + return this.userRolesRepository.create( + { + user_id: userId, + role_id: role.id, + primary, + }, + trx, + ) } -} \ No newline at end of file +} diff --git a/src/lib/server/api/services/users.service.ts b/src/lib/server/api/services/users.service.ts index f067809..008a41a 100644 --- a/src/lib/server/api/services/users.service.ts +++ b/src/lib/server/api/services/users.service.ts @@ -1,11 +1,14 @@ import type { SignupUsernameEmailDto } from '$lib/server/api/dtos/signup-username-email.dto' import { CredentialsRepository } from '$lib/server/api/repositories/credentials.repository' +import { FederatedIdentityRepository } from '$lib/server/api/repositories/federated_identity.repository' +import { WishlistsRepository } from '$lib/server/api/repositories/wishlists.repository' import { TokensService } from '$lib/server/api/services/tokens.service' import { UserRolesService } from '$lib/server/api/services/user_roles.service' import { inject, injectable } from 'tsyringe' import { CredentialsType } from '../databases/tables' import { type UpdateUser, UsersRepository } from '../repositories/users.repository' import { CollectionsService } from './collections.service' +import { DrizzleService } from './drizzle.service' import { WishlistsService } from './wishlists.service' @injectable() @@ -13,9 +16,12 @@ export class UsersService { constructor( @inject(CollectionsService) private readonly collectionsService: CollectionsService, @inject(CredentialsRepository) private readonly credentialsRepository: CredentialsRepository, + @inject(DrizzleService) private readonly drizzleService: DrizzleService, + @inject(FederatedIdentityRepository) private readonly federatedIdentityRepository: FederatedIdentityRepository, @inject(TokensService) private readonly tokenService: TokensService, @inject(UsersRepository) private readonly usersRepository: UsersRepository, @inject(UserRolesService) private readonly userRolesService: UserRolesService, + @inject(WishlistsRepository) private readonly wishlistsRepository: WishlistsRepository, @inject(WishlistsService) private readonly wishlistsService: WishlistsService, ) {} @@ -23,34 +29,71 @@ export class UsersService { const { firstName, lastName, email, username, password } = data const hashedPassword = await this.tokenService.createHashedToken(password) - const user = await this.usersRepository.create({ - first_name: firstName, - last_name: lastName, - email, - username, + return await this.drizzleService.db.transaction(async (trx) => { + const createdUser = await this.usersRepository.create( + { + first_name: firstName, + last_name: lastName, + email, + username, + }, + trx, + ) + + if (!createdUser) { + return null + } + + const credentials = await this.credentialsRepository.create( + { + user_id: createdUser.id, + type: CredentialsType.PASSWORD, + secret_data: hashedPassword, + }, + trx, + ) + + if (!credentials) { + await this.usersRepository.delete(createdUser.id) + return null + } + + await this.userRolesService.addRoleToUser(createdUser.id, 'user', true, trx) + + await this.wishlistsService.createEmptyNoName(createdUser.id, trx) + await this.collectionsService.createEmptyNoName(createdUser.id, trx) }) + } - if (!user) { - return null - } + async createOAuthUser(oauthUserId: number, oauthUsername: string, oauthProvider: string) { + return await this.drizzleService.db.transaction(async (trx) => { + const createdUser = await this.usersRepository.create( + { + username: oauthUsername, + }, + trx, + ) - const credentials = await this.credentialsRepository.create({ - user_id: user.id, - type: CredentialsType.PASSWORD, - secret_data: hashedPassword, + if (!createdUser) { + return null + } + + await this.federatedIdentityRepository.create( + { + identity_provider: oauthProvider, + user_id: createdUser.id, + federated_user_id: `${oauthUserId}`, + federated_username: oauthUsername, + }, + trx, + ) + + await this.userRolesService.addRoleToUser(createdUser.id, 'user', true, trx) + + await this.wishlistsService.createEmptyNoName(createdUser.id, trx) + await this.collectionsService.createEmptyNoName(createdUser.id, trx) + return createdUser }) - - if (!credentials) { - await this.usersRepository.delete(user.id) - return null - } - - await this.userRolesService.addRoleToUser(user.id, 'user', true) - - await this.wishlistsService.createEmptyNoName(user.id) - await this.collectionsService.createEmptyNoName(user.id) - - return user } async updateUser(userId: string, data: UpdateUser) { diff --git a/src/lib/server/api/services/wishlists.service.ts b/src/lib/server/api/services/wishlists.service.ts index f7326a1..b06b174 100644 --- a/src/lib/server/api/services/wishlists.service.ts +++ b/src/lib/server/api/services/wishlists.service.ts @@ -1,34 +1,41 @@ -import { inject, injectable } from "tsyringe"; -import { WishlistsRepository } from "../repositories/wishlists.repository"; -import { generateRandomAnimalName } from "$lib/utils/randomDataUtil"; +import type { db } from '$lib/server/api/packages/drizzle' +import { generateRandomAnimalName } from '$lib/utils/randomDataUtil' +import { inject, injectable } from 'tsyringe' +import { WishlistsRepository } from '../repositories/wishlists.repository' @injectable() export class WishlistsService { - - constructor( - @inject(WishlistsRepository) private readonly wishlistsRepository: WishlistsRepository - ) { } + constructor(@inject(WishlistsRepository) private readonly wishlistsRepository: WishlistsRepository) {} async findAllByUserId(userId: string) { - return this.wishlistsRepository.findAllByUserId(userId); + return this.wishlistsRepository.findAllByUserId(userId) } async findOneById(id: string) { - return this.wishlistsRepository.findOneById(id); + return this.wishlistsRepository.findOneById(id) } async findOneByCuid(cuid: string) { - return this.wishlistsRepository.findOneByCuid(cuid); + return this.wishlistsRepository.findOneByCuid(cuid) } - async createEmptyNoName(userId: string) { - return this.createEmpty(userId, null); + async createEmptyNoName(userId: string, trx: Parameters[0]>[0] | null = null) { + return this.createEmpty(userId, null, trx) } - async createEmpty(userId: string, name: string | null) { - return this.wishlistsRepository.create({ - user_id: userId, - name: name ?? generateRandomAnimalName(), - }); + async createEmpty(userId: string, name: string | null, trx: Parameters[0]>[0] | null = null) { + if (!trx) { + return this.wishlistsRepository.create({ + user_id: userId, + name: name ?? generateRandomAnimalName(), + }) + } + return this.wishlistsRepository.create( + { + user_id: userId, + name: name ?? generateRandomAnimalName(), + }, + trx, + ) } -} \ No newline at end of file +} diff --git a/src/routes/(auth)/auth/callback/github/+server.ts b/src/routes/(auth)/auth/callback/github/+server.ts index c58847d..f4c0f73 100644 --- a/src/routes/(auth)/auth/callback/github/+server.ts +++ b/src/routes/(auth)/auth/callback/github/+server.ts @@ -1,21 +1,31 @@ -import { github } from "$lib/server/auth"; -import { OAuth2RequestError } from "arctic"; -import { generateIdFromEntropySize } from "lucia"; - -import type { RequestEvent } from "@sveltejs/kit"; +import { StatusCodes } from '$lib/constants/status-codes' +import type { RequestEvent } from '@sveltejs/kit' +import { redirect } from 'sveltekit-flash-message/server' export async function GET(event: RequestEvent): Promise { - const code = event.url.searchParams.get('code') - const state = event.url.searchParams.get('state') - const { data, error } = await locals.api.oauth.$get({ - params: { - code, - state - } - }) + const { locals, url } = event + const code = url.searchParams.get('code') + const state = url.searchParams.get('state') + console.log('code', code, 'state', state) + + const { data, error } = await locals.api.oauth.github.$get({ query: { code, state } }).then(locals.parseApiResponse) + + if (error) { + return new Response(JSON.stringify(error), { + status: 400, + }) + } + + if (!data) { + return new Response(JSON.stringify({ message: 'Invalid request' }), { + status: 400, + }) + } + + redirect(StatusCodes.TEMPORARY_REDIRECT, '/') } interface GitHubUser { - id: number; - login: string; -} \ No newline at end of file + id: number + login: string +} diff --git a/src/routes/(auth)/login/+page.server.ts b/src/routes/(auth)/login/+page.server.ts index a2b90e9..a08e5d1 100644 --- a/src/routes/(auth)/login/+page.server.ts +++ b/src/routes/(auth)/login/+page.server.ts @@ -1,3 +1,4 @@ +import { StatusCodes } from '$lib/constants/status-codes' import { signinUsernameDto } from '$lib/dtos/signin-username.dto' import { type Actions, fail } from '@sveltejs/kit' import { redirect } from 'sveltekit-flash-message/server' @@ -136,6 +137,8 @@ export const actions: Actions = { form.data.username = '' form.data.password = '' + redirect(StatusCodes.TEMPORARY_REDIRECT, '/') + // if ( // twoFactorDetails?.enabled && // twoFactorDetails?.secret !== null && diff --git a/src/routes/(auth)/login/+page.svelte b/src/routes/(auth)/login/+page.svelte index 195f233..090ac27 100644 --- a/src/routes/(auth)/login/+page.svelte +++ b/src/routes/(auth)/login/+page.svelte @@ -1,41 +1,41 @@ @@ -63,6 +63,9 @@
+

Sign in

+Sign in with GitHub + {#snippet usernamePasswordForm()} diff --git a/src/routes/(auth)/login/github/+server.ts b/src/routes/(auth)/login/github/+server.ts index a93f2f8..d9e5c33 100644 --- a/src/routes/(auth)/login/github/+server.ts +++ b/src/routes/(auth)/login/github/+server.ts @@ -2,17 +2,19 @@ import { github } from '$lib/server/auth' import { redirect } from '@sveltejs/kit' import { generateState } from 'arctic' -export async function GET(event) { - const state = generateState(); +import type { RequestEvent } from '@sveltejs/kit' + +export async function GET(event: RequestEvent): Promise { + const state = generateState() const url = await github.createAuthorizationURL(state) - event.cookies.set('github_state', state, { + event.cookies.set('github_oauth_state', state, { path: '/', secure: import.meta.env.PROD, httpOnly: true, maxAge: 60 * 10, - sameSite: 'lax' - }); + sameSite: 'lax', + }) redirect(302, url.toString()) -} \ No newline at end of file +} From 0e33a85e3796d83db1c6f531e97b0dfea4ca2e66 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Tue, 17 Sep 2024 22:13:07 -0700 Subject: [PATCH 12/29] Design sign in with GitHub. --- package.json | 26 +- pnpm-lock.yaml | 383 ++++++++++++++------------- src/routes/(auth)/login/+page.svelte | 14 +- 3 files changed, 224 insertions(+), 199 deletions(-) diff --git a/package.json b/package.json index 92afa67..55ba0af 100644 --- a/package.json +++ b/package.json @@ -28,9 +28,9 @@ "@melt-ui/pp": "^0.3.2", "@melt-ui/svelte": "^0.83.0", "@playwright/test": "^1.47.1", - "@sveltejs/adapter-auto": "^3.2.4", - "@sveltejs/enhanced-img": "^0.3.7", - "@sveltejs/kit": "^2.5.27", + "@sveltejs/adapter-auto": "^3.2.5", + "@sveltejs/enhanced-img": "^0.3.8", + "@sveltejs/kit": "^2.5.28", "@sveltejs/vite-plugin-svelte": "^3.1.2", "@types/cookie": "^0.6.0", "@types/node": "^20.16.5", @@ -40,7 +40,7 @@ "arctic": "^1.9.2", "autoprefixer": "^10.4.20", "drizzle-kit": "^0.23.2", - "eslint": "^8.57.0", + "eslint": "^8.57.1", "eslint-config-prettier": "^9.1.0", "eslint-plugin-svelte": "2.36.0-next.13", "just-clone": "^6.2.0", @@ -54,7 +54,7 @@ "postcss-preset-env": "^9.6.0", "prettier": "^3.3.3", "prettier-plugin-svelte": "^3.2.6", - "sass": "^1.78.0", + "sass": "^1.79.1", "satori": "^0.10.14", "satori-html": "^0.3.2", "svelte": "5.0.0-next.175", @@ -65,13 +65,13 @@ "svelte-sequential-preprocessor": "^2.0.1", "sveltekit-flash-message": "^2.4.4", "sveltekit-rate-limiter": "^0.5.2", - "sveltekit-superforms": "^2.18.0", - "tailwindcss": "^3.4.11", + "sveltekit-superforms": "^2.18.1", + "tailwindcss": "^3.4.12", "ts-node": "^10.9.2", "tslib": "^2.7.0", "tsx": "^4.19.1", "typescript": "^5.6.2", - "vite": "^5.4.5", + "vite": "^5.4.6", "vitest": "^1.6.0", "zod": "^3.23.8" }, @@ -89,13 +89,13 @@ "@neondatabase/serverless": "^0.9.5", "@paralleldrive/cuid2": "^2.2.2", "@resvg/resvg-js": "^2.6.2", - "@sveltejs/adapter-node": "^5.2.2", - "@sveltejs/adapter-vercel": "^5.4.3", + "@sveltejs/adapter-node": "^5.2.3", + "@sveltejs/adapter-vercel": "^5.4.4", "@types/feather-icons": "^4.29.4", "@vercel/og": "^0.5.20", "bits-ui": "^0.21.13", "boardgamegeekclient": "^1.9.1", - "bullmq": "^5.13.0", + "bullmq": "^5.13.1", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "cookie": "^0.6.0", @@ -106,7 +106,7 @@ "feather-icons": "^4.29.2", "formsnap": "^1.0.1", "handlebars": "^4.7.8", - "hono": "^4.6.1", + "hono": "^4.6.2", "hono-rate-limiter": "^0.4.0", "html-entities": "^2.5.2", "iconify-icon": "^2.1.0", @@ -116,7 +116,7 @@ "loader": "^2.1.1", "open-props": "^1.7.6", "oslo": "^1.2.1", - "pg": "^8.12.0", + "pg": "^8.13.0", "postgres": "^3.4.4", "qrcode": "^1.5.4", "radix-svelte": "^0.9.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3368666..84f41fe 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,13 +13,13 @@ importers: version: 5.1.0 '@hono/swagger-ui': specifier: ^0.4.1 - version: 0.4.1(hono@4.6.1) + version: 0.4.1(hono@4.6.2) '@hono/zod-openapi': specifier: ^0.15.3 - version: 0.15.3(hono@4.6.1)(zod@3.23.8) + version: 0.15.3(hono@4.6.2)(zod@3.23.8) '@hono/zod-validator': specifier: ^0.2.2 - version: 0.2.2(hono@4.6.1)(zod@3.23.8) + version: 0.2.2(hono@4.6.2)(zod@3.23.8) '@iconify-icons/line-md': specifier: ^1.2.30 version: 1.2.30 @@ -31,7 +31,7 @@ importers: version: 3.5.5 '@lucia-auth/adapter-drizzle': specifier: ^1.1.0 - version: 1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.12.0)(postgres@3.4.4))(lucia@3.2.0) + version: 1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4))(lucia@3.2.0) '@lukeed/uuid': specifier: ^2.0.1 version: 2.0.1 @@ -45,11 +45,11 @@ importers: specifier: ^2.6.2 version: 2.6.2 '@sveltejs/adapter-node': - specifier: ^5.2.2 - version: 5.2.2(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))) + specifier: ^5.2.3 + version: 5.2.3(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))) '@sveltejs/adapter-vercel': - specifier: ^5.4.3 - version: 5.4.3(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))) + specifier: ^5.4.4 + version: 5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))) '@types/feather-icons': specifier: ^4.29.4 version: 4.29.4 @@ -63,8 +63,8 @@ importers: specifier: ^1.9.1 version: 1.9.1 bullmq: - specifier: ^5.13.0 - version: 5.13.0 + specifier: ^5.13.1 + version: 5.13.1 class-variance-authority: specifier: ^0.7.0 version: 0.7.0 @@ -82,25 +82,25 @@ importers: version: 11.0.6 drizzle-orm: specifier: ^0.32.2 - version: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.12.0)(postgres@3.4.4) + version: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4) drizzle-zod: specifier: ^0.5.1 - version: 0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.12.0)(postgres@3.4.4))(zod@3.23.8) + version: 0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4))(zod@3.23.8) feather-icons: specifier: ^4.29.2 version: 4.29.2 formsnap: specifier: ^1.0.1 - version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.18.0(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)) + version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.18.1(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)) handlebars: specifier: ^4.7.8 version: 4.7.8 hono: - specifier: ^4.6.1 - version: 4.6.1 + specifier: ^4.6.2 + version: 4.6.2 hono-rate-limiter: specifier: ^0.4.0 - version: 0.4.0(hono@4.6.1) + version: 0.4.0(hono@4.6.2) html-entities: specifier: ^2.5.2 version: 2.5.2 @@ -126,8 +126,8 @@ importers: specifier: ^1.2.1 version: 1.2.1 pg: - specifier: ^8.12.0 - version: 8.12.0 + specifier: ^8.13.0 + version: 8.13.0 postgres: specifier: ^3.4.4 version: 3.4.4 @@ -154,10 +154,10 @@ importers: version: 2.5.2 tailwind-variants: specifier: ^0.2.1 - version: 0.2.1(tailwindcss@3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))) + version: 0.2.1(tailwindcss@3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))) tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))) + version: 1.0.7(tailwindcss@3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))) tsyringe: specifier: ^4.8.0 version: 4.8.0 @@ -181,17 +181,17 @@ importers: specifier: ^1.47.1 version: 1.47.1 '@sveltejs/adapter-auto': - specifier: ^3.2.4 - version: 3.2.4(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))) + specifier: ^3.2.5 + version: 3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))) '@sveltejs/enhanced-img': - specifier: ^0.3.7 - version: 0.3.7(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) + specifier: ^0.3.8 + version: 0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) '@sveltejs/kit': - specifier: ^2.5.27 - version: 2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) + specifier: ^2.5.28 + version: 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) '@sveltejs/vite-plugin-svelte': specifier: ^3.1.2 - version: 3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) + version: 3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) '@types/cookie': specifier: ^0.6.0 version: 0.6.0 @@ -203,10 +203,10 @@ importers: version: 8.11.10 '@typescript-eslint/eslint-plugin': specifier: ^7.18.0 - version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0)(typescript@5.6.2) + version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2) '@typescript-eslint/parser': specifier: ^7.18.0 - version: 7.18.0(eslint@8.57.0)(typescript@5.6.2) + version: 7.18.0(eslint@8.57.1)(typescript@5.6.2) arctic: specifier: ^1.9.2 version: 1.9.2 @@ -217,14 +217,14 @@ importers: specifier: ^0.23.2 version: 0.23.2 eslint: - specifier: ^8.57.0 - version: 8.57.0 + specifier: ^8.57.1 + version: 8.57.1 eslint-config-prettier: specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.0) + version: 9.1.0(eslint@8.57.1) eslint-plugin-svelte: specifier: 2.36.0-next.13 - version: 2.36.0-next.13(eslint@8.57.0)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + version: 2.36.0-next.13(eslint@8.57.1)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) just-clone: specifier: ^6.2.0 version: 6.2.0 @@ -259,8 +259,8 @@ importers: specifier: ^3.2.6 version: 3.2.6(prettier@3.3.3)(svelte@5.0.0-next.175) sass: - specifier: ^1.78.0 - version: 1.78.0 + specifier: ^1.79.1 + version: 1.79.1 satori: specifier: ^0.10.14 version: 0.10.14 @@ -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.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.78.0)(svelte@5.0.0-next.175) + version: 3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175) svelte-headless-table: specifier: ^0.18.2 version: 0.18.2(svelte@5.0.0-next.175) @@ -281,22 +281,22 @@ importers: version: 3.1.4(svelte@5.0.0-next.175)(typescript@5.6.2) svelte-preprocess: specifier: ^6.0.2 - version: 6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2) + version: 6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175)(typescript@5.6.2) svelte-sequential-preprocessor: specifier: ^2.0.1 version: 2.0.1 sveltekit-flash-message: specifier: ^2.4.4 - version: 2.4.4(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175) + version: 2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175) sveltekit-rate-limiter: specifier: ^0.5.2 - version: 0.5.2(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))) + version: 0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))) sveltekit-superforms: - specifier: ^2.18.0 - version: 2.18.0(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) + specifier: ^2.18.1 + version: 2.18.1(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) tailwindcss: - specifier: ^3.4.11 - version: 3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + specifier: ^3.4.12 + version: 3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@20.16.5)(typescript@5.6.2) @@ -310,11 +310,11 @@ importers: specifier: ^5.6.2 version: 5.6.2 vite: - specifier: ^5.4.5 - version: 5.4.5(@types/node@20.16.5)(sass@1.78.0) + specifier: ^5.4.6 + version: 5.4.6(@types/node@20.16.5)(sass@1.79.1) vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@20.16.5)(sass@1.78.0) + version: 1.6.0(@types/node@20.16.5)(sass@1.79.1) zod: specifier: ^3.23.8 version: 3.23.8 @@ -1225,8 +1225,8 @@ packages: resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@eslint/js@8.57.0': - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} + '@eslint/js@8.57.1': + resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} '@exodus/schemasafe@1.3.0': @@ -1276,8 +1276,8 @@ packages: hono: '>=3.9.0' zod: ^3.19.1 - '@humanwhocodes/config-array@0.11.14': - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + '@humanwhocodes/config-array@0.13.0': + resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} deprecated: Use @eslint/config-array instead @@ -1941,29 +1941,29 @@ packages: '@sodaru/yup-to-json-schema@2.0.1': resolution: {integrity: sha512-lWb0Wiz8KZ9ip/dY1eUqt7fhTPmL24p6Hmv5Fd9pzlzAdw/YNcWZr+tiCT4oZ4Zyxzi9+1X4zv82o7jYvcFxYA==} - '@sveltejs/adapter-auto@3.2.4': - resolution: {integrity: sha512-a64AKYbfTUrVwU0xslzv1Jf3M8bj0IwhptaXmhgIkjXspBXhD0od9JiItQHchijpLMGdEDcYBlvqySkEawv6mQ==} + '@sveltejs/adapter-auto@3.2.5': + resolution: {integrity: sha512-27LR+uKccZ62lgq4N/hvyU2G+hTP9fxWEAfnZcl70HnyfAjMSsGk1z/SjAPXNCD1mVJIE7IFu3TQ8cQ/UH3c0A==} peerDependencies: '@sveltejs/kit': ^2.0.0 - '@sveltejs/adapter-node@5.2.2': - resolution: {integrity: sha512-BCX4zP0cf86TXpmvLQTnnT/tp7P12UMezf+5LwljP1MJC1fFzn9XOXpAHQCyP+pyHGy2K7p5gY0LyLcZFAL02w==} + '@sveltejs/adapter-node@5.2.3': + resolution: {integrity: sha512-0KNrTc9NiEhB1vyVL0HiqZaW2P5JWNJgTYT5PnUZCLO9Oydx8G+6PNtJPJ/NNPyeGrn+6LwR5L8GNRvA4b5Bpw==} peerDependencies: '@sveltejs/kit': ^2.4.0 - '@sveltejs/adapter-vercel@5.4.3': - resolution: {integrity: sha512-srZBkMpeaa7lflO1ZGdKTW3jWHscE9rdAkyxgRlVMVyugjcPOZ3dcpEfpoM4wtVCbpEOdHniWqQR9yL+zs4ybA==} + '@sveltejs/adapter-vercel@5.4.4': + resolution: {integrity: sha512-KORoxxqB2H5DrxpCHc9Yfijcgvmoaaz6G6eKHEg9fRlTsujJkxN26C0x4YlcgxqDU4dLIi1wfSLHpuZD0E4Irg==} peerDependencies: '@sveltejs/kit': ^2.4.0 - '@sveltejs/enhanced-img@0.3.7': - resolution: {integrity: sha512-Rb692ralH4Vs8bx52b403Xs2ZmZJ3XctYiXGNXLay9ex1G56jD31jqPFnwoWKyUqiD9JTi6CxVp/1Xy2Dus86Q==} + '@sveltejs/enhanced-img@0.3.8': + resolution: {integrity: sha512-n66u46ZeqHltiTm0BEjWptYmCrCY0EltEEvakmC7d5o5ZejDbOvOWm914mebbRKaP2Bezv65TNCod/wqvw/0KA==} peerDependencies: svelte: ^4.0.0 || ^5.0.0-next.0 vite: '>= 5.0.0' - '@sveltejs/kit@2.5.27': - resolution: {integrity: sha512-CcbRTzl+65oWljAASL6UlxM4x3NWwd0fjq5fQOfP243vs50myFQ8lil0fr3Im6HeeQqYUCtnv8HjO8REWVPjTw==} + '@sveltejs/kit@2.5.28': + resolution: {integrity: sha512-/O7pvFGBsQPcFa9UrW8eUC5uHTOXLsUp3SN0dY6YmRAL9nfPSrJsSJk//j5vMpinSshzUjteAFcfQTU+04Ka1w==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -2311,8 +2311,8 @@ packages: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} - bullmq@5.13.0: - resolution: {integrity: sha512-rE7v3jMZZGsEhfMhLZwADwuHdqJPTTGHBM8C+SpxF9GzyZ+7pvC80EP5bOZJPPRzbmyhvIPJCVd0bchUZiQF+w==} + bullmq@5.13.1: + resolution: {integrity: sha512-9Ss2GzV+VVA2Q/+qUxQ7zxAwfLWBwc7DIUNboq0EdXGRf2Ia+Qi7BwT51rnxglu4b/0SRsSElevRT8IZc7HvtQ==} bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} @@ -2363,6 +2363,10 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + chokidar@4.0.0: + resolution: {integrity: sha512-mxIojEAQcuEvT/lyXq+jf/3cO/KoA6z4CeNDGGevTybECPOMFCnQy3OPahluUkbqgPNGw5Bi78UC7Po6Lhy+NA==} + engines: {node: '>= 14.16.0'} + chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} @@ -2806,8 +2810,8 @@ packages: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} + eslint@8.57.1: + resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true @@ -3062,9 +3066,9 @@ packages: peerDependencies: hono: ^4.1.1 - hono@4.6.1: - resolution: {integrity: sha512-6NGwvttY1+HAFii08VYiEKI6ETPAFbpLntpm2M/MogEsAFWdZV74UNT+2M4bmqX90cIQhjlpBSP+tO+CfB0uww==} - engines: {node: '>=16.0.0'} + hono@4.6.2: + resolution: {integrity: sha512-v+39817TgAhetmHUEli8O0uHDmxp2Up3DnhS4oUZXOl5IQ9np9tYtldd42e5zgdLVS0wsOoXQNZ6mx+BGmEvCA==} + engines: {node: '>=16.9.0'} html-entities@2.5.2: resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} @@ -3638,8 +3642,8 @@ packages: pg-cloudflare@1.1.1: resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==} - pg-connection-string@2.6.4: - resolution: {integrity: sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==} + pg-connection-string@2.7.0: + resolution: {integrity: sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==} pg-int8@1.0.1: resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} @@ -3649,14 +3653,17 @@ packages: resolution: {integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==} engines: {node: '>=4'} - pg-pool@3.6.2: - resolution: {integrity: sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==} + pg-pool@3.7.0: + resolution: {integrity: sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g==} peerDependencies: pg: '>=8.0' pg-protocol@1.6.1: resolution: {integrity: sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==} + pg-protocol@1.7.0: + resolution: {integrity: sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==} + pg-types@2.2.0: resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} engines: {node: '>=4'} @@ -3665,8 +3672,8 @@ packages: resolution: {integrity: sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==} engines: {node: '>=10'} - pg@8.12.0: - resolution: {integrity: sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ==} + pg@8.13.0: + resolution: {integrity: sha512-34wkUTh3SxTClfoHB3pQ7bIMvw9dpFU1audQQeZG837fmHfHpr14n/AELVDoOYVDW2h5RDWU78tFjkD+erSBsw==} engines: {node: '>= 8.0.0'} peerDependencies: pg-native: '>=3.0.1' @@ -4063,6 +4070,10 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + readdirp@4.0.1: + resolution: {integrity: sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==} + engines: {node: '>= 14.16.0'} + redis-errors@1.2.0: resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} engines: {node: '>=4'} @@ -4137,8 +4148,8 @@ packages: sander@0.5.1: resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==} - sass@1.78.0: - resolution: {integrity: sha512-AaIqGSrjo5lA2Yg7RvFZrlXDBCp3nV4XP73GrLGvdRWWwk+8H3l0SDvq/5bA4eF+0RFPLuWUk3E+P1U/YqnpsQ==} + sass@1.79.1: + resolution: {integrity: sha512-+mA7svoNKeL0DiJqZGeR/ZGUu8he4I8o3jyUcOFyo4eBJrwNgIMmAEwCMo/N2Y3wdjOBcRzoNxZIOtrtMX8EXg==} engines: {node: '>=14.0.0'} hasBin: true @@ -4479,8 +4490,8 @@ packages: peerDependencies: '@sveltejs/kit': 1.x || 2.x - sveltekit-superforms@2.18.0: - resolution: {integrity: sha512-INx2EwWk82WcUdG5iEMtcJ+NLvBpYOdiHDRa68Q9p9W+YRAN3mxwiqj5gpfVrvBPlGfFZypeAze54pBZ/wlspw==} + sveltekit-superforms@2.18.1: + resolution: {integrity: sha512-bdWXlWfvG0AauTj8KGZ00dZGix4jxzGM5ywXFZuodJjwGyEpnfNbui4n1KX5KdIqsVoTU1cKrxt0gZnuJivJsw==} peerDependencies: '@sveltejs/kit': 1.x || 2.x svelte: 3.x || 4.x || >=5.0.0-next.51 @@ -4502,8 +4513,8 @@ packages: peerDependencies: tailwindcss: '>=3.0.0 || insiders' - tailwindcss@3.4.11: - resolution: {integrity: sha512-qhEuBcLemjSJk5ajccN9xJFtM/h0AVCPaA6C92jNP+M2J8kX+eMJHI7R2HFKUvvAsMpcfLILMCFYSeDwpMmlUg==} + tailwindcss@3.4.12: + resolution: {integrity: sha512-Htf/gHj2+soPb9UayUNci/Ja3d8pTmu9ONTfh4QY8r3MATTZOzmv6UYWF7ZwikEIC8okpfqmGqrmDehua8mF8w==} engines: {node: '>=14.0.0'} hasBin: true @@ -4705,8 +4716,8 @@ packages: engines: {node: ^18.0.0 || >=20.0.0} hasBin: true - vite@5.4.5: - resolution: {integrity: sha512-pXqR0qtb2bTwLkev4SE3r4abCNioP3GkjvIDLlzziPpXtHgiJIjuKl+1GN6ESOT3wMjG3JTeARopj2SwYaHTOA==} + vite@5.4.6: + resolution: {integrity: sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -5476,9 +5487,9 @@ snapshots: '@esbuild/win32-x64@0.23.1': optional: true - '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.1)': dependencies: - eslint: 8.57.0 + eslint: 8.57.1 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.11.0': {} @@ -5497,7 +5508,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@8.57.0': {} + '@eslint/js@8.57.1': {} '@exodus/schemasafe@1.3.0': optional: true @@ -5534,23 +5545,23 @@ snapshots: '@hapi/hoek': 9.3.0 optional: true - '@hono/swagger-ui@0.4.1(hono@4.6.1)': + '@hono/swagger-ui@0.4.1(hono@4.6.2)': dependencies: - hono: 4.6.1 + hono: 4.6.2 - '@hono/zod-openapi@0.15.3(hono@4.6.1)(zod@3.23.8)': + '@hono/zod-openapi@0.15.3(hono@4.6.2)(zod@3.23.8)': dependencies: '@asteasolutions/zod-to-openapi': 7.1.1(zod@3.23.8) - '@hono/zod-validator': 0.2.2(hono@4.6.1)(zod@3.23.8) - hono: 4.6.1 + '@hono/zod-validator': 0.2.2(hono@4.6.2)(zod@3.23.8) + hono: 4.6.2 zod: 3.23.8 - '@hono/zod-validator@0.2.2(hono@4.6.1)(zod@3.23.8)': + '@hono/zod-validator@0.2.2(hono@4.6.2)(zod@3.23.8)': dependencies: - hono: 4.6.1 + hono: 4.6.2 zod: 3.23.8 - '@humanwhocodes/config-array@0.11.14': + '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 debug: 4.3.6 @@ -5690,9 +5701,9 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@lucia-auth/adapter-drizzle@1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.12.0)(postgres@3.4.4))(lucia@3.2.0)': + '@lucia-auth/adapter-drizzle@1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4))(lucia@3.2.0)': dependencies: - drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.12.0)(postgres@3.4.4) + drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4) lucia: 3.2.0 '@lukeed/csprng@1.1.0': {} @@ -6089,41 +6100,41 @@ snapshots: '@sodaru/yup-to-json-schema@2.0.1': optional: true - '@sveltejs/adapter-auto@3.2.4(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))': + '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))': dependencies: - '@sveltejs/kit': 2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) import-meta-resolve: 4.1.0 - '@sveltejs/adapter-node@5.2.2(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))': + '@sveltejs/adapter-node@5.2.3(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))': dependencies: '@rollup/plugin-commonjs': 26.0.1(rollup@4.21.2) '@rollup/plugin-json': 6.1.0(rollup@4.21.2) '@rollup/plugin-node-resolve': 15.2.3(rollup@4.21.2) - '@sveltejs/kit': 2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) rollup: 4.21.2 - '@sveltejs/adapter-vercel@5.4.3(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))': + '@sveltejs/adapter-vercel@5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))': dependencies: - '@sveltejs/kit': 2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) '@vercel/nft': 0.27.4 esbuild: 0.21.5 transitivePeerDependencies: - encoding - supports-color - '@sveltejs/enhanced-img@0.3.7(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))': + '@sveltejs/enhanced-img@0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))': dependencies: magic-string: 0.30.11 svelte: 5.0.0-next.175 svelte-parse-markup: 0.1.5(svelte@5.0.0-next.175) - vite: 5.4.5(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.6(@types/node@20.16.5)(sass@1.79.1) vite-imagetools: 7.0.4(rollup@4.21.2) transitivePeerDependencies: - rollup - '@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))': + '@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.0.0 @@ -6137,28 +6148,28 @@ snapshots: sirv: 2.0.4 svelte: 5.0.0-next.175 tiny-glob: 0.2.9 - vite: 5.4.5(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.6(@types/node@20.16.5)(sass@1.79.1) - '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))': + '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) debug: 4.3.6 svelte: 5.0.0-next.175 - vite: 5.4.5(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.6(@types/node@20.16.5)(sass@1.79.1) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))': + '@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) debug: 4.3.6 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.11 svelte: 5.0.0-next.175 svelte-hmr: 0.16.0(svelte@5.0.0-next.175) - vite: 5.4.5(@types/node@20.16.5)(sass@1.78.0) - vitefu: 0.2.5(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) + vite: 5.4.6(@types/node@20.16.5)(sass@1.79.1) + vitefu: 0.2.5(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) transitivePeerDependencies: - supports-color @@ -6225,15 +6236,15 @@ snapshots: '@types/json-schema': 7.0.15 optional: true - '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0)(typescript@5.6.2)': + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2)': dependencies: '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 7.18.0(eslint@8.57.0)(typescript@5.6.2) + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.6.2) '@typescript-eslint/scope-manager': 7.18.0 - '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.0)(typescript@5.6.2) - '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.6.2) + '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.1)(typescript@5.6.2) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.6.2) '@typescript-eslint/visitor-keys': 7.18.0 - eslint: 8.57.0 + eslint: 8.57.1 graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -6243,14 +6254,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.6.2)': + '@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2)': dependencies: '@typescript-eslint/scope-manager': 7.18.0 '@typescript-eslint/types': 7.18.0 '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.2) '@typescript-eslint/visitor-keys': 7.18.0 debug: 4.3.6 - eslint: 8.57.0 + eslint: 8.57.1 optionalDependencies: typescript: 5.6.2 transitivePeerDependencies: @@ -6261,12 +6272,12 @@ snapshots: '@typescript-eslint/types': 7.18.0 '@typescript-eslint/visitor-keys': 7.18.0 - '@typescript-eslint/type-utils@7.18.0(eslint@8.57.0)(typescript@5.6.2)': + '@typescript-eslint/type-utils@7.18.0(eslint@8.57.1)(typescript@5.6.2)': dependencies: '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.2) - '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.6.2) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.1)(typescript@5.6.2) debug: 4.3.6 - eslint: 8.57.0 + eslint: 8.57.1 ts-api-utils: 1.3.0(typescript@5.6.2) optionalDependencies: typescript: 5.6.2 @@ -6290,13 +6301,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@7.18.0(eslint@8.57.0)(typescript@5.6.2)': + '@typescript-eslint/utils@7.18.0(eslint@8.57.1)(typescript@5.6.2)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) '@typescript-eslint/scope-manager': 7.18.0 '@typescript-eslint/types': 7.18.0 '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.2) - eslint: 8.57.0 + eslint: 8.57.1 transitivePeerDependencies: - supports-color - typescript @@ -6548,7 +6559,7 @@ snapshots: builtin-modules@3.3.0: {} - bullmq@5.13.0: + bullmq@5.13.1: dependencies: cron-parser: 4.9.0 ioredis: 5.4.1 @@ -6616,6 +6627,10 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + chokidar@4.0.0: + dependencies: + readdirp: 4.0.1 + chownr@2.0.0: {} class-validator@0.14.1: @@ -6816,16 +6831,16 @@ snapshots: transitivePeerDependencies: - supports-color - drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.12.0)(postgres@3.4.4): + drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4): optionalDependencies: '@neondatabase/serverless': 0.9.5 '@types/pg': 8.11.10 - pg: 8.12.0 + pg: 8.13.0 postgres: 3.4.4 - drizzle-zod@0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.12.0)(postgres@3.4.4))(zod@3.23.8): + drizzle-zod@0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4))(zod@3.23.8): dependencies: - drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.12.0)(postgres@3.4.4) + drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4) zod: 3.23.8 eastasianwidth@0.2.0: {} @@ -6974,22 +6989,22 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-compat-utils@0.5.1(eslint@8.57.0): + eslint-compat-utils@0.5.1(eslint@8.57.1): dependencies: - eslint: 8.57.0 + eslint: 8.57.1 semver: 7.6.3 - eslint-config-prettier@9.1.0(eslint@8.57.0): + eslint-config-prettier@9.1.0(eslint@8.57.1): dependencies: - eslint: 8.57.0 + eslint: 8.57.1 - eslint-plugin-svelte@2.36.0-next.13(eslint@8.57.0)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): + eslint-plugin-svelte@2.36.0-next.13(eslint@8.57.1)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) '@jridgewell/sourcemap-codec': 1.5.0 debug: 4.3.6 - eslint: 8.57.0 - eslint-compat-utils: 0.5.1(eslint@8.57.0) + eslint: 8.57.1 + eslint-compat-utils: 0.5.1(eslint@8.57.1) esutils: 2.0.3 known-css-properties: 0.30.0 postcss: 8.4.47 @@ -7011,13 +7026,13 @@ snapshots: eslint-visitor-keys@3.4.3: {} - eslint@8.57.0: + eslint@8.57.1: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) '@eslint-community/regexpp': 4.11.0 '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 + '@eslint/js': 8.57.1 + '@humanwhocodes/config-array': 0.13.0 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 '@ungap/structured-clone': 1.2.0 @@ -7217,11 +7232,11 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.18.0(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)): + formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.18.1(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)): dependencies: nanoid: 5.0.7 svelte: 5.0.0-next.175 - sveltekit-superforms: 2.18.0(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) + sveltekit-superforms: 2.18.1(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) forwarded@0.2.0: {} @@ -7354,11 +7369,11 @@ snapshots: hex-rgb@4.3.0: {} - hono-rate-limiter@0.4.0(hono@4.6.1): + hono-rate-limiter@0.4.0(hono@4.6.2): dependencies: - hono: 4.6.1 + hono: 4.6.2 - hono@4.6.1: {} + hono@4.6.2: {} html-entities@2.5.2: {} @@ -7876,18 +7891,20 @@ snapshots: pg-cloudflare@1.1.1: optional: true - pg-connection-string@2.6.4: {} + pg-connection-string@2.7.0: {} pg-int8@1.0.1: {} pg-numeric@1.0.2: {} - pg-pool@3.6.2(pg@8.12.0): + pg-pool@3.7.0(pg@8.13.0): dependencies: - pg: 8.12.0 + pg: 8.13.0 pg-protocol@1.6.1: {} + pg-protocol@1.7.0: {} + pg-types@2.2.0: dependencies: pg-int8: 1.0.1 @@ -7906,11 +7923,11 @@ snapshots: postgres-interval: 3.0.0 postgres-range: 1.1.4 - pg@8.12.0: + pg@8.13.0: dependencies: - pg-connection-string: 2.6.4 - pg-pool: 3.6.2(pg@8.12.0) - pg-protocol: 1.6.1 + pg-connection-string: 2.7.0 + pg-pool: 3.7.0(pg@8.13.0) + pg-protocol: 1.7.0 pg-types: 2.2.0 pgpass: 1.0.5 optionalDependencies: @@ -8320,6 +8337,8 @@ snapshots: dependencies: picomatch: 2.3.1 + readdirp@4.0.1: {} + redis-errors@1.2.0: {} redis-parser@3.0.0: @@ -8400,9 +8419,9 @@ snapshots: mkdirp: 0.5.6 rimraf: 2.7.1 - sass@1.78.0: + sass@1.79.1: dependencies: - chokidar: 3.6.0 + chokidar: 4.0.0 immutable: 4.3.7 source-map-js: 1.2.0 @@ -8630,14 +8649,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.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.78.0)(svelte@5.0.0-next.175): + svelte-check@3.8.6(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175): dependencies: '@jridgewell/trace-mapping': 0.3.25 chokidar: 3.6.0 picocolors: 1.1.0 sade: 1.8.1 svelte: 5.0.0-next.175 - svelte-preprocess: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2) + svelte-preprocess: 5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175)(typescript@5.6.2) typescript: 5.6.2 transitivePeerDependencies: - '@babel/core' @@ -8693,7 +8712,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.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2): + svelte-preprocess@5.1.4(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175)(typescript@5.6.2): dependencies: '@types/pug': 2.0.10 detect-indent: 6.1.0 @@ -8704,16 +8723,16 @@ snapshots: optionalDependencies: postcss: 8.4.47 postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1) - sass: 1.78.0 + sass: 1.79.1 typescript: 5.6.2 - svelte-preprocess@6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.78.0)(svelte@5.0.0-next.175)(typescript@5.6.2): + svelte-preprocess@6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175)(typescript@5.6.2): dependencies: svelte: 5.0.0-next.175 optionalDependencies: postcss: 8.4.47 postcss-load-config: 5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1) - sass: 1.78.0 + sass: 1.79.1 typescript: 5.6.2 svelte-render@2.0.1(svelte@5.0.0-next.175): @@ -8767,19 +8786,19 @@ snapshots: magic-string: 0.30.11 zimmerframe: 1.1.2 - sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175): + sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) svelte: 5.0.0-next.175 - sveltekit-rate-limiter@0.5.2(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0))): + sveltekit-rate-limiter@0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))): dependencies: '@isaacs/ttlcache': 1.4.1 - '@sveltejs/kit': 2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) - sveltekit-superforms@2.18.0(@sveltejs/kit@2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): + sveltekit-superforms@2.18.1(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.27(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)))(svelte@5.0.0-next.175)(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) devalue: 5.0.0 just-clone: 6.2.0 memoize-weak: 1.0.2 @@ -8808,16 +8827,16 @@ snapshots: tailwind-merge@2.5.2: {} - tailwind-variants@0.2.1(tailwindcss@3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))): + tailwind-variants@0.2.1(tailwindcss@3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))): dependencies: tailwind-merge: 2.5.2 - tailwindcss: 3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + tailwindcss: 3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) - tailwindcss-animate@1.0.7(tailwindcss@3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))): + tailwindcss-animate@1.0.7(tailwindcss@3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))): dependencies: - tailwindcss: 3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + tailwindcss: 3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) - tailwindcss@3.4.11(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): + tailwindcss@3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -9014,13 +9033,13 @@ snapshots: transitivePeerDependencies: - rollup - vite-node@1.6.0(@types/node@20.16.5)(sass@1.78.0): + vite-node@1.6.0(@types/node@20.16.5)(sass@1.79.1): dependencies: cac: 6.7.14 debug: 4.3.6 pathe: 1.1.2 picocolors: 1.1.0 - vite: 5.4.5(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.6(@types/node@20.16.5)(sass@1.79.1) transitivePeerDependencies: - '@types/node' - less @@ -9032,7 +9051,7 @@ snapshots: - supports-color - terser - vite@5.4.5(@types/node@20.16.5)(sass@1.78.0): + vite@5.4.6(@types/node@20.16.5)(sass@1.79.1): dependencies: esbuild: 0.21.5 postcss: 8.4.47 @@ -9040,13 +9059,13 @@ snapshots: optionalDependencies: '@types/node': 20.16.5 fsevents: 2.3.3 - sass: 1.78.0 + sass: 1.79.1 - vitefu@0.2.5(vite@5.4.5(@types/node@20.16.5)(sass@1.78.0)): + vitefu@0.2.5(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)): optionalDependencies: - vite: 5.4.5(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.6(@types/node@20.16.5)(sass@1.79.1) - vitest@1.6.0(@types/node@20.16.5)(sass@1.78.0): + vitest@1.6.0(@types/node@20.16.5)(sass@1.79.1): dependencies: '@vitest/expect': 1.6.0 '@vitest/runner': 1.6.0 @@ -9065,8 +9084,8 @@ snapshots: strip-literal: 2.1.0 tinybench: 2.9.0 tinypool: 0.8.4 - vite: 5.4.5(@types/node@20.16.5)(sass@1.78.0) - vite-node: 1.6.0(@types/node@20.16.5)(sass@1.78.0) + vite: 5.4.6(@types/node@20.16.5)(sass@1.79.1) + vite-node: 1.6.0(@types/node@20.16.5)(sass@1.79.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 20.16.5 diff --git a/src/routes/(auth)/login/+page.svelte b/src/routes/(auth)/login/+page.svelte index 090ac27..3cfe70c 100644 --- a/src/routes/(auth)/login/+page.svelte +++ b/src/routes/(auth)/login/+page.svelte @@ -12,6 +12,7 @@ import { AlertCircle } from 'lucide-svelte' import * as flashModule from 'sveltekit-flash-message/client' import { zodClient } from 'sveltekit-superforms/adapters' import { superForm } from 'sveltekit-superforms/client' +import { Github } from 'lucide-svelte' let { data } = $props() @@ -47,8 +48,10 @@ const { form: loginForm, enhance } = superLoginForm Log into your account - + {@render usernamePasswordForm()} + or sign in with + {@render oAuthButtons()}

By clicking continue, you agree to our @@ -63,9 +66,6 @@ const { form: loginForm, enhance } = superLoginForm

-

Sign in

-
Sign in with GitHub - {#snippet usernamePasswordForm()} @@ -89,5 +89,11 @@ const { form: loginForm, enhance } = superLoginForm {/snippet} +{#snippet oAuthButtons()} +
+ +
+{/snippet} + \ No newline at end of file From dd4bbb01dcff649b0ab5a24c0c1023b5c94aaa6b Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Tue, 17 Sep 2024 22:58:24 -0700 Subject: [PATCH 13/29] Remove sass --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 55ba0af..59cf53a 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,6 @@ "postcss-preset-env": "^9.6.0", "prettier": "^3.3.3", "prettier-plugin-svelte": "^3.2.6", - "sass": "^1.79.1", "satori": "^0.10.14", "satori-html": "^0.3.2", "svelte": "5.0.0-next.175", From 7477c4417435f74509393b08c7947ec3229fa77b Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Tue, 17 Sep 2024 22:59:05 -0700 Subject: [PATCH 14/29] Remove sass, lock updated --- pnpm-lock.yaml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 84f41fe..c3c844e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -258,9 +258,6 @@ importers: prettier-plugin-svelte: specifier: ^3.2.6 version: 3.2.6(prettier@3.3.3)(svelte@5.0.0-next.175) - sass: - specifier: ^1.79.1 - version: 1.79.1 satori: specifier: ^0.10.14 version: 0.10.14 @@ -6630,6 +6627,7 @@ snapshots: chokidar@4.0.0: dependencies: readdirp: 4.0.1 + optional: true chownr@2.0.0: {} @@ -7406,7 +7404,8 @@ snapshots: imagetools-core@7.0.1: {} - immutable@4.3.7: {} + immutable@4.3.7: + optional: true import-fresh@3.3.0: dependencies: @@ -8337,7 +8336,8 @@ snapshots: dependencies: picomatch: 2.3.1 - readdirp@4.0.1: {} + readdirp@4.0.1: + optional: true redis-errors@1.2.0: {} @@ -8424,6 +8424,7 @@ snapshots: chokidar: 4.0.0 immutable: 4.3.7 source-map-js: 1.2.0 + optional: true satori-html@0.3.2: dependencies: @@ -8569,7 +8570,8 @@ snapshots: minimist: 1.2.8 sander: 0.5.1 - source-map-js@1.2.0: {} + source-map-js@1.2.0: + optional: true source-map-js@1.2.1: {} From 9b50e0fb48d27c4831999f310063f1068982ed0d Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Thu, 19 Sep 2024 16:55:03 -0700 Subject: [PATCH 15/29] Adding more OAuth provider scaffolding and using svgs for icons. --- package.json | 1 + pnpm-lock.yaml | 18 +++++++++-------- .../collections/[cuid]/+page.svelte | 2 +- .../settings/profile/+page.server.ts | 8 -------- src/routes/(auth)/login/+page.svelte | 10 ++++++++-- src/routes/(auth)/login/apple/+server.ts | 20 +++++++++++++++++++ src/routes/(auth)/login/google/+server.ts | 20 +++++++++++++++++++ src/routes/(auth)/login/spotify/+server.ts | 20 +++++++++++++++++++ src/routes/(auth)/login/tidal/+server.ts | 20 +++++++++++++++++++ 9 files changed, 100 insertions(+), 19 deletions(-) create mode 100644 src/routes/(auth)/login/apple/+server.ts create mode 100644 src/routes/(auth)/login/google/+server.ts create mode 100644 src/routes/(auth)/login/spotify/+server.ts create mode 100644 src/routes/(auth)/login/tidal/+server.ts diff --git a/package.json b/package.json index 59cf53a..9423b10 100644 --- a/package.json +++ b/package.json @@ -121,6 +121,7 @@ "radix-svelte": "^0.9.0", "rate-limit-redis": "^4.2.0", "reflect-metadata": "^0.2.2", + "simple-icons": "^13.10.0", "svelte-french-toast": "^1.2.0", "svelte-lazy-loader": "^1.0.0", "tailwind-merge": "^2.5.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c3c844e..daff87b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -143,6 +143,9 @@ importers: reflect-metadata: specifier: ^0.2.2 version: 0.2.2 + simple-icons: + specifier: ^13.10.0 + version: 13.10.0 svelte-french-toast: specifier: ^1.2.0 version: 1.2.0(svelte@5.0.0-next.175) @@ -4222,6 +4225,10 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-icons@13.10.0: + resolution: {integrity: sha512-akHZxjNvq4nLlLsKxDot7A+ZYXgjhAP4GwvWEItHeKiquuWXoI8xGGfP+hzGLbTmbmi2teYmHMS45PIOFy6EFA==} + engines: {node: '>=0.12.18'} + simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} @@ -4237,10 +4244,6 @@ packages: resolution: {integrity: sha512-o7npfeJE6wi6J9l0/5LKshFzZ2rMatRiCDwYeDQaOzqdzRJwALhX7mk/A/ecg6wjMu7wdZbmXfD2S/vpOg0bdQ==} hasBin: true - source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} - engines: {node: '>=0.10.0'} - source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -8423,7 +8426,7 @@ snapshots: dependencies: chokidar: 4.0.0 immutable: 4.3.7 - source-map-js: 1.2.0 + source-map-js: 1.2.1 optional: true satori-html@0.3.2: @@ -8551,6 +8554,8 @@ snapshots: signal-exit@4.1.0: {} + simple-icons@13.10.0: {} + simple-swizzle@0.2.2: dependencies: is-arrayish: 0.3.2 @@ -8570,9 +8575,6 @@ snapshots: minimist: 1.2.8 sander: 0.5.1 - source-map-js@1.2.0: - optional: true - source-map-js@1.2.1: {} source-map-support@0.5.21: diff --git a/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte b/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte index 450233c..70a1054 100644 --- a/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte +++ b/src/routes/(app)/(protected)/collections/[cuid]/+page.svelte @@ -40,7 +40,7 @@ console.log('items', items)
{#if items.length === 0} -

No gamesTable in your collection

+

No games in your collection

{:else} {#each items as game (game.game_id)} diff --git a/src/routes/(app)/(protected)/settings/profile/+page.server.ts b/src/routes/(app)/(protected)/settings/profile/+page.server.ts index 77cab00..1841c32 100644 --- a/src/routes/(app)/(protected)/settings/profile/+page.server.ts +++ b/src/routes/(app)/(protected)/settings/profile/+page.server.ts @@ -18,14 +18,6 @@ export const load: PageServerLoad = async (event) => { throw redirect(302, '/login', notSignedInMessage, event) } - console.log('authedUser', authedUser) - // if (userNotAuthenticated(user, session)) { - // redirect(302, '/login', notSignedInMessage, event); - // } - // const dbUser = await db.query.usersTable.findFirst({ - // where: eq(usersTable.id, user!.id!), - // }); - const profileForm = await superValidate(zod(updateProfileSchema), { defaults: { firstName: authedUser?.firstName ?? '', diff --git a/src/routes/(auth)/login/+page.svelte b/src/routes/(auth)/login/+page.svelte index 3cfe70c..8d6ecaf 100644 --- a/src/routes/(auth)/login/+page.svelte +++ b/src/routes/(auth)/login/+page.svelte @@ -9,10 +9,10 @@ import { boredState } from '$lib/stores/boredState.js' import { receive, send } from '$lib/utils/pageCrossfade' import { signInSchema } from '$lib/validations/auth' import { AlertCircle } from 'lucide-svelte' +import { siApple, siGithub, siGoogle } from 'simple-icons' import * as flashModule from 'sveltekit-flash-message/client' import { zodClient } from 'sveltekit-superforms/adapters' import { superForm } from 'sveltekit-superforms/client' -import { Github } from 'lucide-svelte' let { data } = $props() @@ -91,9 +91,15 @@ const { form: loginForm, enhance } = superLoginForm {#snippet oAuthButtons()}
- + + +
{/snippet} \ No newline at end of file diff --git a/src/routes/(auth)/login/apple/+server.ts b/src/routes/(auth)/login/apple/+server.ts new file mode 100644 index 0000000..d9e5c33 --- /dev/null +++ b/src/routes/(auth)/login/apple/+server.ts @@ -0,0 +1,20 @@ +import { github } from '$lib/server/auth' +import { redirect } from '@sveltejs/kit' +import { generateState } from 'arctic' + +import type { RequestEvent } from '@sveltejs/kit' + +export async function GET(event: RequestEvent): Promise { + const state = generateState() + const url = await github.createAuthorizationURL(state) + + event.cookies.set('github_oauth_state', state, { + path: '/', + secure: import.meta.env.PROD, + httpOnly: true, + maxAge: 60 * 10, + sameSite: 'lax', + }) + + redirect(302, url.toString()) +} diff --git a/src/routes/(auth)/login/google/+server.ts b/src/routes/(auth)/login/google/+server.ts new file mode 100644 index 0000000..d9e5c33 --- /dev/null +++ b/src/routes/(auth)/login/google/+server.ts @@ -0,0 +1,20 @@ +import { github } from '$lib/server/auth' +import { redirect } from '@sveltejs/kit' +import { generateState } from 'arctic' + +import type { RequestEvent } from '@sveltejs/kit' + +export async function GET(event: RequestEvent): Promise { + const state = generateState() + const url = await github.createAuthorizationURL(state) + + event.cookies.set('github_oauth_state', state, { + path: '/', + secure: import.meta.env.PROD, + httpOnly: true, + maxAge: 60 * 10, + sameSite: 'lax', + }) + + redirect(302, url.toString()) +} diff --git a/src/routes/(auth)/login/spotify/+server.ts b/src/routes/(auth)/login/spotify/+server.ts new file mode 100644 index 0000000..d9e5c33 --- /dev/null +++ b/src/routes/(auth)/login/spotify/+server.ts @@ -0,0 +1,20 @@ +import { github } from '$lib/server/auth' +import { redirect } from '@sveltejs/kit' +import { generateState } from 'arctic' + +import type { RequestEvent } from '@sveltejs/kit' + +export async function GET(event: RequestEvent): Promise { + const state = generateState() + const url = await github.createAuthorizationURL(state) + + event.cookies.set('github_oauth_state', state, { + path: '/', + secure: import.meta.env.PROD, + httpOnly: true, + maxAge: 60 * 10, + sameSite: 'lax', + }) + + redirect(302, url.toString()) +} diff --git a/src/routes/(auth)/login/tidal/+server.ts b/src/routes/(auth)/login/tidal/+server.ts new file mode 100644 index 0000000..d9e5c33 --- /dev/null +++ b/src/routes/(auth)/login/tidal/+server.ts @@ -0,0 +1,20 @@ +import { github } from '$lib/server/auth' +import { redirect } from '@sveltejs/kit' +import { generateState } from 'arctic' + +import type { RequestEvent } from '@sveltejs/kit' + +export async function GET(event: RequestEvent): Promise { + const state = generateState() + const url = await github.createAuthorizationURL(state) + + event.cookies.set('github_oauth_state', state, { + path: '/', + secure: import.meta.env.PROD, + httpOnly: true, + maxAge: 60 * 10, + sameSite: 'lax', + }) + + redirect(302, url.toString()) +} From cb271d377e05ad0723d151a8923495b48ce6abea Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Thu, 19 Sep 2024 18:06:54 -0700 Subject: [PATCH 16/29] Adding license and starting google oauth. --- .env.example | 2 + LICENSE | 21 +++ package.json | 5 +- src/lib/server/api/common/env.ts | 2 + .../api/controllers/oauth.controller.ts | 140 +++++++++++++----- src/lib/server/auth.ts | 4 +- src/routes/(app)/privacy/+page.svelte | 2 +- .../(auth)/auth/callback/github/+server.ts | 5 - .../(auth)/auth/callback/google/+server.ts | 26 ++++ src/routes/(auth)/login/google/+server.ts | 19 ++- 10 files changed, 172 insertions(+), 54 deletions(-) create mode 100644 LICENSE create mode 100644 src/routes/(auth)/auth/callback/google/+server.ts diff --git a/.env.example b/.env.example index 527dae2..a539bcd 100644 --- a/.env.example +++ b/.env.example @@ -21,6 +21,8 @@ TWO_FACTOR_TIMEOUT=300000 # OAuth GITHUB_CLIENT_ID="" GITHUB_CLIENT_SECRET="" +GOOGLE_CLIENT_ID="" +GOOGLE_CLIENT_SECRET="" # Public diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2af8905 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License Copyright (c) 2024 Bradley Shellnut + +Permission is hereby granted, +free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice +(including the next paragraph) shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO +EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/package.json b/package.json index 9423b10..8caf66b 100644 --- a/package.json +++ b/package.json @@ -129,5 +129,6 @@ "tailwindcss-animate": "^1.0.7", "tsyringe": "^4.8.0", "zod-to-json-schema": "^3.23.3" - } -} + }, + "license": "MIT" +} \ No newline at end of file diff --git a/src/lib/server/api/common/env.ts b/src/lib/server/api/common/env.ts index 95b35c4..5dd1157 100644 --- a/src/lib/server/api/common/env.ts +++ b/src/lib/server/api/common/env.ts @@ -19,6 +19,8 @@ const EnvSchema = z.object({ DB_SEEDING: stringBoolean, GITHUB_CLIENT_ID: z.string(), GITHUB_CLIENT_SECRET: z.string(), + GOOGLE_CLIENT_ID: z.string(), + GOOGLE_CLIENT_SECRET: z.string(), NODE_ENV: z.string().default('development'), ORIGIN: z.string(), PUBLIC_SITE_NAME: z.string(), diff --git a/src/lib/server/api/controllers/oauth.controller.ts b/src/lib/server/api/controllers/oauth.controller.ts index 570f42b..4a7b44e 100644 --- a/src/lib/server/api/controllers/oauth.controller.ts +++ b/src/lib/server/api/controllers/oauth.controller.ts @@ -2,7 +2,7 @@ import 'reflect-metadata' import { Controller } from '$lib/server/api/common/types/controller' import { LuciaService } from '$lib/server/api/services/lucia.service' import { OAuthService } from '$lib/server/api/services/oauth.service' -import { github } from '$lib/server/auth' +import { github, google } from '$lib/server/auth' import { OAuth2RequestError } from 'arctic' import { getCookie, setCookie } from 'hono/cookie' import { TimeSpan } from 'oslo' @@ -18,55 +18,108 @@ export class OAuthController extends Controller { } routes() { - return this.controller.get('/github', async (c) => { - try { - const code = c.req.query('code')?.toString() ?? null - const state = c.req.query('state')?.toString() ?? null - const storedState = getCookie(c).github_oauth_state ?? null + return this.controller + .get('/github', async (c) => { + try { + const code = c.req.query('code')?.toString() ?? null + const state = c.req.query('state')?.toString() ?? null + const storedState = getCookie(c).github_oauth_state ?? null - console.log('code', code, 'state', state, 'storedState', storedState) + console.log('code', code, 'state', state, 'storedState', storedState) - if (!code || !state || !storedState || state !== storedState) { - return c.body(null, 400) + if (!code || !state || !storedState || state !== storedState) { + return c.body(null, 400) + } + + const tokens = await github.validateAuthorizationCode(code) + const githubUserResponse = await fetch('https://api.github.com/user', { + headers: { + Authorization: `Bearer ${tokens.accessToken}`, + }, + }) + const githubUser: GitHubUser = await githubUserResponse.json() + + const userId = await this.oauthService.handleOAuthUser(githubUser.id, githubUser.login, 'github') + + const session = await this.luciaService.lucia.createSession(userId, {}) + const sessionCookie = this.luciaService.lucia.createSessionCookie(session.id) + + setCookie(c, sessionCookie.name, sessionCookie.value, { + path: sessionCookie.attributes.path, + maxAge: + sessionCookie?.attributes?.maxAge && sessionCookie?.attributes?.maxAge < new TimeSpan(365, 'd').seconds() + ? sessionCookie.attributes.maxAge + : new TimeSpan(2, 'w').seconds(), + domain: sessionCookie.attributes.domain, + sameSite: sessionCookie.attributes.sameSite as any, + secure: sessionCookie.attributes.secure, + httpOnly: sessionCookie.attributes.httpOnly, + expires: sessionCookie.attributes.expires, + }) + + return c.json({ message: 'ok' }) + } catch (error) { + console.error(error) + // the specific error message depends on the provider + if (error instanceof OAuth2RequestError) { + // invalid code + return c.body(null, 400) + } + return c.body(null, 500) } + }) + .get('/google', async (c) => { + try { + const code = c.req.query('code')?.toString() ?? null + const state = c.req.query('state')?.toString() ?? null + const storedState = getCookie(c).google_oauth_state ?? null + const storedCodeVerifier = getCookie(c).google_oauth_code_verifier ?? null - const tokens = await github.validateAuthorizationCode(code) - const githubUserResponse = await fetch('https://api.github.com/user', { - headers: { - Authorization: `Bearer ${tokens.accessToken}`, - }, - }) - const githubUser: GitHubUser = await githubUserResponse.json() + console.log('code', code, 'state', state, 'storedState', storedState) - const userId = await this.oauthService.handleOAuthUser(githubUser.id, githubUser.login, 'github') + if (!code || !storedState || !storedCodeVerifier || state !== storedState) { + return c.body(null, 400) + } - const session = await this.luciaService.lucia.createSession(userId, {}) - const sessionCookie = this.luciaService.lucia.createSessionCookie(session.id) + const tokens = await google.validateAuthorizationCode(code, storedCodeVerifier) + console.log('tokens', tokens) + const googleUserResponse = await fetch('https://www.googleapis.com/oauth2/v3/userinfo', { + headers: { + Authorization: `Bearer ${tokens.accessToken}`, + }, + }) + console.log('googleUserResponse', googleUserResponse) + const googleUser: GoogleUser = await googleUserResponse.json() - setCookie(c, sessionCookie.name, sessionCookie.value, { - path: sessionCookie.attributes.path, - maxAge: - sessionCookie?.attributes?.maxAge && sessionCookie?.attributes?.maxAge < new TimeSpan(365, 'd').seconds() - ? sessionCookie.attributes.maxAge - : new TimeSpan(2, 'w').seconds(), - domain: sessionCookie.attributes.domain, - sameSite: sessionCookie.attributes.sameSite as any, - secure: sessionCookie.attributes.secure, - httpOnly: sessionCookie.attributes.httpOnly, - expires: sessionCookie.attributes.expires, - }) + const userId = await this.oauthService.handleOAuthUser(googleUser.id, googleUser.login, 'github') - return c.json({ message: 'ok' }) - } catch (error) { - console.error(error) - // the specific error message depends on the provider - if (error instanceof OAuth2RequestError) { - // invalid code - return c.body(null, 400) + const session = await this.luciaService.lucia.createSession(userId, {}) + const sessionCookie = this.luciaService.lucia.createSessionCookie(session.id) + + setCookie(c, sessionCookie.name, sessionCookie.value, { + path: sessionCookie.attributes.path, + maxAge: + sessionCookie?.attributes?.maxAge && sessionCookie?.attributes?.maxAge < new TimeSpan(365, 'd').seconds() + ? sessionCookie.attributes.maxAge + : new TimeSpan(2, 'w').seconds(), + domain: sessionCookie.attributes.domain, + sameSite: sessionCookie.attributes.sameSite as any, + secure: sessionCookie.attributes.secure, + httpOnly: sessionCookie.attributes.httpOnly, + expires: sessionCookie.attributes.expires, + }) + + return c.json({ message: 'ok' }) + } catch (error) { + console.error(error) + // the specific error message depends on the provider + if (error instanceof OAuth2RequestError) { + // invalid code + return c.body(null, 400) + } + return c.body(null, 500) } - return c.body(null, 500) - } - }) + }) } } @@ -74,3 +127,8 @@ interface GitHubUser { id: number login: string } + +interface GoogleUser { + id: number + login: string +} diff --git a/src/lib/server/auth.ts b/src/lib/server/auth.ts index bf0d9aa..e06aa3e 100644 --- a/src/lib/server/auth.ts +++ b/src/lib/server/auth.ts @@ -1,4 +1,6 @@ import env from "$lib/server/api/common/env"; -import { GitHub } from "arctic"; +import { GitHub, Google } from "arctic"; export const github = new GitHub(env.GITHUB_CLIENT_ID, env.GITHUB_CLIENT_SECRET); + +export const google = new Google(env.GOOGLE_CLIENT_ID, env.GOOGLE_CLIENT_SECRET, `${env.ORIGIN}/auth/callback/google`); \ No newline at end of file diff --git a/src/routes/(app)/privacy/+page.svelte b/src/routes/(app)/privacy/+page.svelte index 97bcf66..4711f47 100644 --- a/src/routes/(app)/privacy/+page.svelte +++ b/src/routes/(app)/privacy/+page.svelte @@ -1,5 +1,5 @@

Privacy Policy

-

Last Updated: September 13th, 2023

+

Last Updated: September 19th, 2024

At Bored Game, we respect your privacy and are committed to protecting your personal information. We collect only the personal information that is necessary for us to provide our services to you. diff --git a/src/routes/(auth)/auth/callback/github/+server.ts b/src/routes/(auth)/auth/callback/github/+server.ts index f4c0f73..5453600 100644 --- a/src/routes/(auth)/auth/callback/github/+server.ts +++ b/src/routes/(auth)/auth/callback/github/+server.ts @@ -24,8 +24,3 @@ export async function GET(event: RequestEvent): Promise { redirect(StatusCodes.TEMPORARY_REDIRECT, '/') } - -interface GitHubUser { - id: number - login: string -} diff --git a/src/routes/(auth)/auth/callback/google/+server.ts b/src/routes/(auth)/auth/callback/google/+server.ts new file mode 100644 index 0000000..5bc0ad4 --- /dev/null +++ b/src/routes/(auth)/auth/callback/google/+server.ts @@ -0,0 +1,26 @@ +import { StatusCodes } from '$lib/constants/status-codes' +import type { RequestEvent } from '@sveltejs/kit' +import { redirect } from 'sveltekit-flash-message/server' + +export async function GET(event: RequestEvent): Promise { + const { locals, url } = event + const code = url.searchParams.get('code') + const state = url.searchParams.get('state') + console.log('code', code, 'state', state) + + const { data, error } = await locals.api.oauth.google.$get({ query: { code, state } }).then(locals.parseApiResponse) + + if (error) { + return new Response(JSON.stringify(error), { + status: 400, + }) + } + + if (!data) { + return new Response(JSON.stringify({ message: 'Invalid request' }), { + status: 400, + }) + } + + redirect(StatusCodes.TEMPORARY_REDIRECT, '/') +} diff --git a/src/routes/(auth)/login/google/+server.ts b/src/routes/(auth)/login/google/+server.ts index d9e5c33..3c2ce04 100644 --- a/src/routes/(auth)/login/google/+server.ts +++ b/src/routes/(auth)/login/google/+server.ts @@ -1,14 +1,25 @@ -import { github } from '$lib/server/auth' +import { google } from '$lib/server/auth' import { redirect } from '@sveltejs/kit' -import { generateState } from 'arctic' +import { generateCodeVerifier, generateState } from 'arctic' import type { RequestEvent } from '@sveltejs/kit' +// Google Login export async function GET(event: RequestEvent): Promise { const state = generateState() - const url = await github.createAuthorizationURL(state) + const codeVerifier = generateCodeVerifier(); - event.cookies.set('github_oauth_state', state, { + const url = await google.createAuthorizationURL(state, codeVerifier) + + event.cookies.set('google_oauth_state', state, { + path: '/', + secure: import.meta.env.PROD, + httpOnly: true, + maxAge: 60 * 10, + sameSite: 'lax', + }) + + event.cookies.set('google_oauth_code_verifier', codeVerifier, { path: '/', secure: import.meta.env.PROD, httpOnly: true, From 3aa1c77947cbae7b05880778764b087a8a27a8bc Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Fri, 20 Sep 2024 17:25:51 -0700 Subject: [PATCH 17/29] Add picture and email verified columns to the user, migrations, fixing OAuth with Google, creating types for OAuth --- drizzle.config.ts | 2 +- package.json | 12 +- pnpm-lock.yaml | 174 +- src/lib/server/api/common/types/oauth-user.ts | 9 + .../api/controllers/oauth.controller.ts | 38 +- .../migrations/0001_pink_the_enforcers.sql | 2 + .../migrations/meta/0001_snapshot.json | 1876 +++++++++++++++++ .../databases/migrations/meta/_journal.json | 7 + .../api/databases/tables/users.table.ts | 2 + src/lib/server/api/services/oauth.service.ts | 7 +- src/lib/server/api/services/users.service.ts | 20 +- src/routes/(auth)/login/google/+server.ts | 4 +- 12 files changed, 2037 insertions(+), 116 deletions(-) create mode 100644 src/lib/server/api/common/types/oauth-user.ts create mode 100644 src/lib/server/api/databases/migrations/0001_pink_the_enforcers.sql create mode 100644 src/lib/server/api/databases/migrations/meta/0001_snapshot.json diff --git a/drizzle.config.ts b/drizzle.config.ts index b90a261..e9ec449 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -1,5 +1,5 @@ import 'dotenv/config' -import env from '$lib/server/api/common/env' +import env from './src/lib/server/api/common/env' import { defineConfig } from 'drizzle-kit' export default defineConfig({ diff --git a/package.json b/package.json index 8caf66b..fc21126 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "@faker-js/faker": "^8.4.1", "@melt-ui/pp": "^0.3.2", "@melt-ui/svelte": "^0.83.0", - "@playwright/test": "^1.47.1", + "@playwright/test": "^1.47.2", "@sveltejs/adapter-auto": "^3.2.5", "@sveltejs/enhanced-img": "^0.3.8", "@sveltejs/kit": "^2.5.28", @@ -64,13 +64,13 @@ "svelte-sequential-preprocessor": "^2.0.1", "sveltekit-flash-message": "^2.4.4", "sveltekit-rate-limiter": "^0.5.2", - "sveltekit-superforms": "^2.18.1", + "sveltekit-superforms": "^2.19.0", "tailwindcss": "^3.4.12", "ts-node": "^10.9.2", "tslib": "^2.7.0", "tsx": "^4.19.1", "typescript": "^5.6.2", - "vite": "^5.4.6", + "vite": "^5.4.7", "vitest": "^1.6.0", "zod": "^3.23.8" }, @@ -88,13 +88,13 @@ "@neondatabase/serverless": "^0.9.5", "@paralleldrive/cuid2": "^2.2.2", "@resvg/resvg-js": "^2.6.2", - "@sveltejs/adapter-node": "^5.2.3", + "@sveltejs/adapter-node": "^5.2.4", "@sveltejs/adapter-vercel": "^5.4.4", "@types/feather-icons": "^4.29.4", "@vercel/og": "^0.5.20", - "bits-ui": "^0.21.13", + "bits-ui": "^0.21.15", "boardgamegeekclient": "^1.9.1", - "bullmq": "^5.13.1", + "bullmq": "^5.13.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "cookie": "^0.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index daff87b..5861e10 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,11 +45,11 @@ importers: specifier: ^2.6.2 version: 2.6.2 '@sveltejs/adapter-node': - specifier: ^5.2.3 - version: 5.2.3(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))) + specifier: ^5.2.4 + version: 5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) '@sveltejs/adapter-vercel': specifier: ^5.4.4 - version: 5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))) + version: 5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) '@types/feather-icons': specifier: ^4.29.4 version: 4.29.4 @@ -57,14 +57,14 @@ importers: specifier: ^0.5.20 version: 0.5.20 bits-ui: - specifier: ^0.21.13 - version: 0.21.13(svelte@5.0.0-next.175) + specifier: ^0.21.15 + version: 0.21.15(svelte@5.0.0-next.175) boardgamegeekclient: specifier: ^1.9.1 version: 1.9.1 bullmq: - specifier: ^5.13.1 - version: 5.13.1 + specifier: ^5.13.2 + version: 5.13.2 class-variance-authority: specifier: ^0.7.0 version: 0.7.0 @@ -91,7 +91,7 @@ importers: version: 4.29.2 formsnap: specifier: ^1.0.1 - version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.18.1(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)) + version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)) handlebars: specifier: ^4.7.8 version: 4.7.8 @@ -181,20 +181,20 @@ importers: specifier: ^0.83.0 version: 0.83.0(svelte@5.0.0-next.175) '@playwright/test': - specifier: ^1.47.1 - version: 1.47.1 + specifier: ^1.47.2 + version: 1.47.2 '@sveltejs/adapter-auto': specifier: ^3.2.5 - version: 3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))) + version: 3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) '@sveltejs/enhanced-img': specifier: ^0.3.8 - version: 0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) + version: 0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@sveltejs/kit': specifier: ^2.5.28 - version: 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) + version: 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@sveltejs/vite-plugin-svelte': specifier: ^3.1.2 - version: 3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) + version: 3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@types/cookie': specifier: ^0.6.0 version: 0.6.0 @@ -287,13 +287,13 @@ importers: version: 2.0.1 sveltekit-flash-message: specifier: ^2.4.4 - version: 2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175) + version: 2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175) sveltekit-rate-limiter: specifier: ^0.5.2 - version: 0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))) + version: 0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) sveltekit-superforms: - specifier: ^2.18.1 - version: 2.18.1(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) + specifier: ^2.19.0 + version: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) tailwindcss: specifier: ^3.4.12 version: 3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) @@ -310,8 +310,8 @@ importers: specifier: ^5.6.2 version: 5.6.2 vite: - specifier: ^5.4.6 - version: 5.4.6(@types/node@20.16.5)(sass@1.79.1) + specifier: ^5.4.7 + version: 5.4.7(@types/node@20.16.5)(sass@1.79.1) vitest: specifier: ^1.6.0 version: 1.6.0(@types/node@20.16.5)(sass@1.79.1) @@ -329,11 +329,11 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@ark/schema@0.2.0': - resolution: {integrity: sha512-IkNWCSHdjaoemMXpps4uFHEAQzwJPbTAS8K2vcQpk90sa+eNBuPSVyB/81/Qyl1VYW0iX3ceGC5NL/OznQv1jg==} + '@ark/schema@0.10.0': + resolution: {integrity: sha512-zpfXwWLOzj9aUK+dXQ6aleJAOgle4/WrHDop5CMX2M88dFQ85NdH8O0v0pvMAQnfFcaQAZ/nVDYLlBJsFc09XA==} - '@ark/util@0.1.0': - resolution: {integrity: sha512-qCLYICQoCy3kEKDVwirQp8qvxhY7NJd8BhhoHaj1l3wCFAk9NUbcDsxAkPStZEMdPI/d7NcbGJe8SWZuRG2twQ==} + '@ark/util@0.10.0': + resolution: {integrity: sha512-uK+9VU5doGMYOoOZVE+XaSs1vYACoaEJdrDkuBx26S4X7y3ChyKsPnIg/9pIw2vUySph1GkAXbvBnfVE2GmXgQ==} '@asteasolutions/zod-to-openapi@7.1.1': resolution: {integrity: sha512-lF0d1gAc0lYLO9/BAGivwTwE2Sh9h6CHuDcbk5KnGBfIuAsAkDC+Fdat4dkQY3CS/zUWKHRmFEma0B7X132Ymw==} @@ -1706,8 +1706,8 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@playwright/test@1.47.1': - resolution: {integrity: sha512-dbWpcNQZ5nj16m+A5UNScYx7HX5trIy7g4phrcitn+Nk83S32EBX/CLU4hiF4RGKX/yRc93AAqtfaXB7JWBd4Q==} + '@playwright/test@1.47.2': + resolution: {integrity: sha512-jTXRsoSPONAs8Za9QEQdyjFn+0ZQFjCiIztAIF6bi1HqhBzG9Ma7g1WotyiGqFSBRZjIEqMdT8RUlbk1QVhzCQ==} engines: {node: '>=18'} hasBin: true @@ -1946,8 +1946,8 @@ packages: peerDependencies: '@sveltejs/kit': ^2.0.0 - '@sveltejs/adapter-node@5.2.3': - resolution: {integrity: sha512-0KNrTc9NiEhB1vyVL0HiqZaW2P5JWNJgTYT5PnUZCLO9Oydx8G+6PNtJPJ/NNPyeGrn+6LwR5L8GNRvA4b5Bpw==} + '@sveltejs/adapter-node@5.2.4': + resolution: {integrity: sha512-L9Kngx1ce2SMCbyGBbRaJovl5lzdwH650SzOa50txAAssMfWLj2f8yPsA2eCX8EhT6AxD4RHLNrVa5W8VUYz8w==} peerDependencies: '@sveltejs/kit': ^2.4.0 @@ -2231,8 +2231,8 @@ packages: aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - arktype@2.0.0-beta.0: - resolution: {integrity: sha512-fE3ssMiXjr/bLqFPzlDhRlXngdyHQreu7p7i8+dtcY1CA+f8WrVUcue6JxywhnqEJXPG4HOcIwQcC+q4VfeUMQ==} + arktype@2.0.0-rc.8: + resolution: {integrity: sha512-ByrqjptsavUCUL9ptts6BUL2LCNkVZyniOdaBw76dlBQ6gYIhYSeycuuj4gRFwcAafszOnAPD2fAqHK7bbo/Zw==} array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} @@ -2272,8 +2272,8 @@ packages: bindings@1.5.0: resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} - bits-ui@0.21.13: - resolution: {integrity: sha512-7nmOh6Ig7ND4DXZHv1FhNsY9yUGrad0+mf3tc4YN//3MgnJT1LnHtk4HZAKgmxCOe7txSX7/39LtYHbkrXokAQ==} + bits-ui@0.21.15: + resolution: {integrity: sha512-+m5WSpJnFdCcNdXSTIVC1WYBozipO03qRh03GFWgrdxoHiolCfwW71EYG4LPCWYPG6KcTZV0Cj6iHSiZ7cdKdg==} peerDependencies: svelte: ^4.0.0 || ^5.0.0-next.118 @@ -2311,8 +2311,8 @@ packages: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} - bullmq@5.13.1: - resolution: {integrity: sha512-9Ss2GzV+VVA2Q/+qUxQ7zxAwfLWBwc7DIUNboq0EdXGRf2Ia+Qi7BwT51rnxglu4b/0SRsSElevRT8IZc7HvtQ==} + bullmq@5.13.2: + resolution: {integrity: sha512-McGE8k3mrCvdUHdU0sHkTKDS1xr4pff+hbEKBY51wk5S6Za0gkuejYA620VQTo3Zz37E/NVWMgumwiXPQ3yZcA==} bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} @@ -3702,13 +3702,13 @@ packages: pkg-types@1.2.0: resolution: {integrity: sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==} - playwright-core@1.47.1: - resolution: {integrity: sha512-i1iyJdLftqtt51mEk6AhYFaAJCDx0xQ/O5NU8EKaWFgMjItPVma542Nh/Aq8aLCjIJSzjaiEQGW/nyqLkGF1OQ==} + playwright-core@1.47.2: + resolution: {integrity: sha512-3JvMfF+9LJfe16l7AbSmU555PaTl2tPyQsVInqm3id16pdDfvZ8TTZ/pyzmkbDrZTQefyzU7AIHlZqQnxpqHVQ==} engines: {node: '>=18'} hasBin: true - playwright@1.47.1: - resolution: {integrity: sha512-SUEKi6947IqYbKxRiqnbUobVZY4bF1uu+ZnZNJX9DfU1tlf2UhWfvVjLf01pQx9URsOr18bFVUKXmanYWhbfkw==} + playwright@1.47.2: + resolution: {integrity: sha512-nx1cLMmQWqmA3UsnjaaokyoUpdVaaDhJhMoxX2qj3McpjnsqFHs516QAKYhqHAgOP+oCFTEOCOAaD1RgD/RQfA==} engines: {node: '>=18'} hasBin: true @@ -4490,8 +4490,8 @@ packages: peerDependencies: '@sveltejs/kit': 1.x || 2.x - sveltekit-superforms@2.18.1: - resolution: {integrity: sha512-bdWXlWfvG0AauTj8KGZ00dZGix4jxzGM5ywXFZuodJjwGyEpnfNbui4n1KX5KdIqsVoTU1cKrxt0gZnuJivJsw==} + sveltekit-superforms@2.19.0: + resolution: {integrity: sha512-WJmdYf8WpuDkl6zxdRP72R+wDefx1OhIQYKdsIQqNkFntNq0/BUrkMdUr1i7d/FbX0gS1A9GRflCx3WiYQlAXg==} peerDependencies: '@sveltejs/kit': 1.x || 2.x svelte: 3.x || 4.x || >=5.0.0-next.51 @@ -4716,8 +4716,8 @@ packages: engines: {node: ^18.0.0 || >=20.0.0} hasBin: true - vite@5.4.6: - resolution: {integrity: sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==} + vite@5.4.7: + resolution: {integrity: sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -4889,12 +4889,12 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@ark/schema@0.2.0': + '@ark/schema@0.10.0': dependencies: - '@ark/util': 0.1.0 + '@ark/util': 0.10.0 optional: true - '@ark/util@0.1.0': + '@ark/util@0.10.0': optional: true '@asteasolutions/zod-to-openapi@7.1.1(zod@3.23.8)': @@ -5925,9 +5925,9 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@playwright/test@1.47.1': + '@playwright/test@1.47.2': dependencies: - playwright: 1.47.1 + playwright: 1.47.2 '@polka/url@1.0.0-next.25': {} @@ -6100,41 +6100,41 @@ snapshots: '@sodaru/yup-to-json-schema@2.0.1': optional: true - '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))': + '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) import-meta-resolve: 4.1.0 - '@sveltejs/adapter-node@5.2.3(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))': + '@sveltejs/adapter-node@5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': dependencies: '@rollup/plugin-commonjs': 26.0.1(rollup@4.21.2) '@rollup/plugin-json': 6.1.0(rollup@4.21.2) '@rollup/plugin-node-resolve': 15.2.3(rollup@4.21.2) - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) rollup: 4.21.2 - '@sveltejs/adapter-vercel@5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))': + '@sveltejs/adapter-vercel@5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@vercel/nft': 0.27.4 esbuild: 0.21.5 transitivePeerDependencies: - encoding - supports-color - '@sveltejs/enhanced-img@0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/enhanced-img@0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: magic-string: 0.30.11 svelte: 5.0.0-next.175 svelte-parse-markup: 0.1.5(svelte@5.0.0-next.175) - vite: 5.4.6(@types/node@20.16.5)(sass@1.79.1) + vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) vite-imagetools: 7.0.4(rollup@4.21.2) transitivePeerDependencies: - rollup - '@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.0.0 @@ -6148,28 +6148,28 @@ snapshots: sirv: 2.0.4 svelte: 5.0.0-next.175 tiny-glob: 0.2.9 - vite: 5.4.6(@types/node@20.16.5)(sass@1.79.1) + vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) - '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) debug: 4.3.6 svelte: 5.0.0-next.175 - vite: 5.4.6(@types/node@20.16.5)(sass@1.79.1) + vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) debug: 4.3.6 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.11 svelte: 5.0.0-next.175 svelte-hmr: 0.16.0(svelte@5.0.0-next.175) - vite: 5.4.6(@types/node@20.16.5)(sass@1.79.1) - vitefu: 0.2.5(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) + vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) + vitefu: 0.2.5(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) transitivePeerDependencies: - supports-color @@ -6465,10 +6465,10 @@ snapshots: dependencies: dequal: 2.0.3 - arktype@2.0.0-beta.0: + arktype@2.0.0-rc.8: dependencies: - '@ark/schema': 0.2.0 - '@ark/util': 0.1.0 + '@ark/schema': 0.10.0 + '@ark/util': 0.10.0 optional: true array-flatten@1.1.1: {} @@ -6501,7 +6501,7 @@ snapshots: dependencies: file-uri-to-path: 1.0.0 - bits-ui@0.21.13(svelte@5.0.0-next.175): + bits-ui@0.21.15(svelte@5.0.0-next.175): dependencies: '@internationalized/date': 3.5.5 '@melt-ui/svelte': 0.76.2(svelte@5.0.0-next.175) @@ -6559,7 +6559,7 @@ snapshots: builtin-modules@3.3.0: {} - bullmq@5.13.1: + bullmq@5.13.2: dependencies: cron-parser: 4.9.0 ioredis: 5.4.1 @@ -7233,11 +7233,11 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.18.1(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)): + formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)): dependencies: nanoid: 5.0.7 svelte: 5.0.0-next.175 - sveltekit-superforms: 2.18.1(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) + sveltekit-superforms: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) forwarded@0.2.0: {} @@ -7953,11 +7953,11 @@ snapshots: mlly: 1.7.1 pathe: 1.1.2 - playwright-core@1.47.1: {} + playwright-core@1.47.2: {} - playwright@1.47.1: + playwright@1.47.2: dependencies: - playwright-core: 1.47.1 + playwright-core: 1.47.2 optionalDependencies: fsevents: 2.3.2 @@ -8790,19 +8790,19 @@ snapshots: magic-string: 0.30.11 zimmerframe: 1.1.2 - sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175): + sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) svelte: 5.0.0-next.175 - sveltekit-rate-limiter@0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1))): + sveltekit-rate-limiter@0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))): dependencies: '@isaacs/ttlcache': 1.4.1 - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) - sveltekit-superforms@2.18.1(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): + sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) devalue: 5.0.0 just-clone: 6.2.0 memoize-weak: 1.0.2 @@ -8815,7 +8815,7 @@ snapshots: '@sodaru/yup-to-json-schema': 2.0.1 '@typeschema/class-validator': 0.2.0(@types/json-schema@7.0.15)(class-validator@0.14.1) '@vinejs/vine': 1.8.0 - arktype: 2.0.0-beta.0 + arktype: 2.0.0-rc.8 class-validator: 0.14.1 joi: 17.13.3 json-schema-to-ts: 3.1.1 @@ -9043,7 +9043,7 @@ snapshots: debug: 4.3.6 pathe: 1.1.2 picocolors: 1.1.0 - vite: 5.4.6(@types/node@20.16.5)(sass@1.79.1) + vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) transitivePeerDependencies: - '@types/node' - less @@ -9055,7 +9055,7 @@ snapshots: - supports-color - terser - vite@5.4.6(@types/node@20.16.5)(sass@1.79.1): + vite@5.4.7(@types/node@20.16.5)(sass@1.79.1): dependencies: esbuild: 0.21.5 postcss: 8.4.47 @@ -9065,9 +9065,9 @@ snapshots: fsevents: 2.3.3 sass: 1.79.1 - vitefu@0.2.5(vite@5.4.6(@types/node@20.16.5)(sass@1.79.1)): + vitefu@0.2.5(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)): optionalDependencies: - vite: 5.4.6(@types/node@20.16.5)(sass@1.79.1) + vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) vitest@1.6.0(@types/node@20.16.5)(sass@1.79.1): dependencies: @@ -9088,7 +9088,7 @@ snapshots: strip-literal: 2.1.0 tinybench: 2.9.0 tinypool: 0.8.4 - vite: 5.4.6(@types/node@20.16.5)(sass@1.79.1) + vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) vite-node: 1.6.0(@types/node@20.16.5)(sass@1.79.1) why-is-node-running: 2.3.0 optionalDependencies: diff --git a/src/lib/server/api/common/types/oauth-user.ts b/src/lib/server/api/common/types/oauth-user.ts new file mode 100644 index 0000000..9d14b0c --- /dev/null +++ b/src/lib/server/api/common/types/oauth-user.ts @@ -0,0 +1,9 @@ +export type OAuthUser = { + sub: string; + given_name?: string; + family_name?: string; + picture?: string; + username: string; + email?: string; + email_verified?: boolean; +} \ No newline at end of file diff --git a/src/lib/server/api/controllers/oauth.controller.ts b/src/lib/server/api/controllers/oauth.controller.ts index 4a7b44e..ab8edb0 100644 --- a/src/lib/server/api/controllers/oauth.controller.ts +++ b/src/lib/server/api/controllers/oauth.controller.ts @@ -7,6 +7,7 @@ import { OAuth2RequestError } from 'arctic' import { getCookie, setCookie } from 'hono/cookie' import { TimeSpan } from 'oslo' import { inject, injectable } from 'tsyringe' +import type {OAuthUser} from "$lib/server/api/common/types/oauth-user"; @injectable() export class OAuthController extends Controller { @@ -25,8 +26,6 @@ export class OAuthController extends Controller { const state = c.req.query('state')?.toString() ?? null const storedState = getCookie(c).github_oauth_state ?? null - console.log('code', code, 'state', state, 'storedState', storedState) - if (!code || !state || !storedState || state !== storedState) { return c.body(null, 400) } @@ -39,7 +38,13 @@ export class OAuthController extends Controller { }) const githubUser: GitHubUser = await githubUserResponse.json() - const userId = await this.oauthService.handleOAuthUser(githubUser.id, githubUser.login, 'github') + const oAuthUser: OAuthUser = { + sub: `${githubUser.id}`, + username: githubUser.login, + email: null + } + + const userId = await this.oauthService.handleOAuthUser(oAuthUser, 'github') const session = await this.luciaService.lucia.createSession(userId, {}) const sessionCookie = this.luciaService.lucia.createSessionCookie(session.id) @@ -75,23 +80,29 @@ export class OAuthController extends Controller { const storedState = getCookie(c).google_oauth_state ?? null const storedCodeVerifier = getCookie(c).google_oauth_code_verifier ?? null - console.log('code', code, 'state', state, 'storedState', storedState) - if (!code || !storedState || !storedCodeVerifier || state !== storedState) { return c.body(null, 400) } const tokens = await google.validateAuthorizationCode(code, storedCodeVerifier) - console.log('tokens', tokens) - const googleUserResponse = await fetch('https://www.googleapis.com/oauth2/v3/userinfo', { + const googleUserResponse = await fetch("https://openidconnect.googleapis.com/v1/userinfo", { headers: { Authorization: `Bearer ${tokens.accessToken}`, }, }) - console.log('googleUserResponse', googleUserResponse) const googleUser: GoogleUser = await googleUserResponse.json() - const userId = await this.oauthService.handleOAuthUser(googleUser.id, googleUser.login, 'github') + const oAuthUser: OAuthUser = { + sub: googleUser.sub, + given_name: googleUser.given_name, + family_name: googleUser.family_name, + picture: googleUser.picture, + username: googleUser.email, + email: googleUser.email, + email_verified: googleUser.email_verified, + } + + const userId = await this.oauthService.handleOAuthUser(oAuthUser, 'google') const session = await this.luciaService.lucia.createSession(userId, {}) const sessionCookie = this.luciaService.lucia.createSessionCookie(session.id) @@ -129,6 +140,11 @@ interface GitHubUser { } interface GoogleUser { - id: number - login: string + sub: string + name: string + given_name: string + family_name: string + picture: string + email: string + email_verified: boolean } diff --git a/src/lib/server/api/databases/migrations/0001_pink_the_enforcers.sql b/src/lib/server/api/databases/migrations/0001_pink_the_enforcers.sql new file mode 100644 index 0000000..1135b5e --- /dev/null +++ b/src/lib/server/api/databases/migrations/0001_pink_the_enforcers.sql @@ -0,0 +1,2 @@ +ALTER TABLE "users" ADD COLUMN "email_verified" boolean DEFAULT false;--> statement-breakpoint +ALTER TABLE "users" ADD COLUMN "picture" text; \ No newline at end of file diff --git a/src/lib/server/api/databases/migrations/meta/0001_snapshot.json b/src/lib/server/api/databases/migrations/meta/0001_snapshot.json new file mode 100644 index 0000000..ae9ae5b --- /dev/null +++ b/src/lib/server/api/databases/migrations/meta/0001_snapshot.json @@ -0,0 +1,1876 @@ +{ + "id": "e1230cae-67ce-4669-885a-3d3fe4462f9e", + "prevId": "4760134e-48bb-47db-b431-56903dad6e24", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.categories": { + "name": "categories", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "categories_cuid_unique": { + "name": "categories_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.categories_to_external_ids": { + "name": "categories_to_external_ids", + "schema": "", + "columns": { + "category_id": { + "name": "category_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "categories_to_external_ids_category_id_categories_id_fk": { + "name": "categories_to_external_ids_category_id_categories_id_fk", + "tableFrom": "categories_to_external_ids", + "tableTo": "categories", + "columnsFrom": [ + "category_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "categories_to_external_ids_external_id_external_ids_id_fk": { + "name": "categories_to_external_ids_external_id_external_ids_id_fk", + "tableFrom": "categories_to_external_ids", + "tableTo": "external_ids", + "columnsFrom": [ + "external_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "categories_to_external_ids_category_id_external_id_pk": { + "name": "categories_to_external_ids_category_id_external_id_pk", + "columns": [ + "category_id", + "external_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.categories_to_games": { + "name": "categories_to_games", + "schema": "", + "columns": { + "category_id": { + "name": "category_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "categories_to_games_category_id_categories_id_fk": { + "name": "categories_to_games_category_id_categories_id_fk", + "tableFrom": "categories_to_games", + "tableTo": "categories", + "columnsFrom": [ + "category_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "categories_to_games_game_id_games_id_fk": { + "name": "categories_to_games_game_id_games_id_fk", + "tableFrom": "categories_to_games", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "categories_to_games_category_id_game_id_pk": { + "name": "categories_to_games_category_id_game_id_pk", + "columns": [ + "category_id", + "game_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.collection_items": { + "name": "collection_items", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "collection_id": { + "name": "collection_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "times_played": { + "name": "times_played", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "collection_items_collection_id_collections_id_fk": { + "name": "collection_items_collection_id_collections_id_fk", + "tableFrom": "collection_items", + "tableTo": "collections", + "columnsFrom": [ + "collection_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "collection_items_game_id_games_id_fk": { + "name": "collection_items_game_id_games_id_fk", + "tableFrom": "collection_items", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "collection_items_cuid_unique": { + "name": "collection_items_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.collections": { + "name": "collections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'My Collection'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "collections_user_id_users_id_fk": { + "name": "collections_user_id_users_id_fk", + "tableFrom": "collections", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "collections_cuid_unique": { + "name": "collections_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.credentials": { + "name": "credentials", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'password'" + }, + "secret_data": { + "name": "secret_data", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "credentials_user_id_users_id_fk": { + "name": "credentials_user_id_users_id_fk", + "tableFrom": "credentials", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.expansions": { + "name": "expansions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "base_game_id": { + "name": "base_game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "expansions_base_game_id_games_id_fk": { + "name": "expansions_base_game_id_games_id_fk", + "tableFrom": "expansions", + "tableTo": "games", + "columnsFrom": [ + "base_game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "expansions_game_id_games_id_fk": { + "name": "expansions_game_id_games_id_fk", + "tableFrom": "expansions", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "expansions_cuid_unique": { + "name": "expansions_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.external_ids": { + "name": "external_ids", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "external_id_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "external_ids_cuid_unique": { + "name": "external_ids_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.federated_identity": { + "name": "federated_identity", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "identity_provider": { + "name": "identity_provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "federated_user_id": { + "name": "federated_user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "federated_username": { + "name": "federated_username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "federated_identity_user_id_users_id_fk": { + "name": "federated_identity_user_id_users_id_fk", + "tableFrom": "federated_identity", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.games": { + "name": "games", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "year_published": { + "name": "year_published", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "min_players": { + "name": "min_players", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "max_players": { + "name": "max_players", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "playtime": { + "name": "playtime", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "min_playtime": { + "name": "min_playtime", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "max_playtime": { + "name": "max_playtime", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "min_age": { + "name": "min_age", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "image_url": { + "name": "image_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "thumb_url": { + "name": "thumb_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_sync_at": { + "name": "last_sync_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "search_index": { + "name": "search_index", + "columns": [ + { + "expression": "(\n\t\t\t\tsetweight(to_tsvector('english', \"name\"), 'A') ||\n setweight(to_tsvector('english', \"slug\"), 'B')\n )", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "gin", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "games_cuid_unique": { + "name": "games_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.games_to_external_ids": { + "name": "games_to_external_ids", + "schema": "", + "columns": { + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "games_to_external_ids_game_id_games_id_fk": { + "name": "games_to_external_ids_game_id_games_id_fk", + "tableFrom": "games_to_external_ids", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "games_to_external_ids_external_id_external_ids_id_fk": { + "name": "games_to_external_ids_external_id_external_ids_id_fk", + "tableFrom": "games_to_external_ids", + "tableTo": "external_ids", + "columnsFrom": [ + "external_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "games_to_external_ids_game_id_external_id_pk": { + "name": "games_to_external_ids_game_id_external_id_pk", + "columns": [ + "game_id", + "external_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.mechanics": { + "name": "mechanics", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "mechanics_cuid_unique": { + "name": "mechanics_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.mechanics_to_external_ids": { + "name": "mechanics_to_external_ids", + "schema": "", + "columns": { + "mechanic_id": { + "name": "mechanic_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "mechanics_to_external_ids_mechanic_id_mechanics_id_fk": { + "name": "mechanics_to_external_ids_mechanic_id_mechanics_id_fk", + "tableFrom": "mechanics_to_external_ids", + "tableTo": "mechanics", + "columnsFrom": [ + "mechanic_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "mechanics_to_external_ids_external_id_external_ids_id_fk": { + "name": "mechanics_to_external_ids_external_id_external_ids_id_fk", + "tableFrom": "mechanics_to_external_ids", + "tableTo": "external_ids", + "columnsFrom": [ + "external_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "mechanics_to_external_ids_mechanic_id_external_id_pk": { + "name": "mechanics_to_external_ids_mechanic_id_external_id_pk", + "columns": [ + "mechanic_id", + "external_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.mechanics_to_games": { + "name": "mechanics_to_games", + "schema": "", + "columns": { + "mechanic_id": { + "name": "mechanic_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "mechanics_to_games_mechanic_id_mechanics_id_fk": { + "name": "mechanics_to_games_mechanic_id_mechanics_id_fk", + "tableFrom": "mechanics_to_games", + "tableTo": "mechanics", + "columnsFrom": [ + "mechanic_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "mechanics_to_games_game_id_games_id_fk": { + "name": "mechanics_to_games_game_id_games_id_fk", + "tableFrom": "mechanics_to_games", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "mechanics_to_games_mechanic_id_game_id_pk": { + "name": "mechanics_to_games_mechanic_id_game_id_pk", + "columns": [ + "mechanic_id", + "game_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.password_reset_tokens": { + "name": "password_reset_tokens", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "password_reset_tokens_user_id_users_id_fk": { + "name": "password_reset_tokens_user_id_users_id_fk", + "tableFrom": "password_reset_tokens", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.publishers": { + "name": "publishers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "publishers_cuid_unique": { + "name": "publishers_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.publishers_to_external_ids": { + "name": "publishers_to_external_ids", + "schema": "", + "columns": { + "publisher_id": { + "name": "publisher_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "publishers_to_external_ids_publisher_id_publishers_id_fk": { + "name": "publishers_to_external_ids_publisher_id_publishers_id_fk", + "tableFrom": "publishers_to_external_ids", + "tableTo": "publishers", + "columnsFrom": [ + "publisher_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "publishers_to_external_ids_external_id_external_ids_id_fk": { + "name": "publishers_to_external_ids_external_id_external_ids_id_fk", + "tableFrom": "publishers_to_external_ids", + "tableTo": "external_ids", + "columnsFrom": [ + "external_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "publishers_to_external_ids_publisher_id_external_id_pk": { + "name": "publishers_to_external_ids_publisher_id_external_id_pk", + "columns": [ + "publisher_id", + "external_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.publishers_to_games": { + "name": "publishers_to_games", + "schema": "", + "columns": { + "publisher_id": { + "name": "publisher_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "publishers_to_games_publisher_id_publishers_id_fk": { + "name": "publishers_to_games_publisher_id_publishers_id_fk", + "tableFrom": "publishers_to_games", + "tableTo": "publishers", + "columnsFrom": [ + "publisher_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + }, + "publishers_to_games_game_id_games_id_fk": { + "name": "publishers_to_games_game_id_games_id_fk", + "tableFrom": "publishers_to_games", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "restrict", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "publishers_to_games_publisher_id_game_id_pk": { + "name": "publishers_to_games_publisher_id_game_id_pk", + "columns": [ + "publisher_id", + "game_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.recovery_codes": { + "name": "recovery_codes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "used": { + "name": "used", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "recovery_codes_user_id_users_id_fk": { + "name": "recovery_codes_user_id_users_id_fk", + "tableFrom": "recovery_codes", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.roles": { + "name": "roles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "roles_cuid_unique": { + "name": "roles_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + }, + "roles_name_unique": { + "name": "roles_name_unique", + "nullsNotDistinct": false, + "columns": [ + "name" + ] + } + } + }, + "public.sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "ip_country": { + "name": "ip_country", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "two_factor_auth_enabled": { + "name": "two_factor_auth_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "is_two_factor_authenticated": { + "name": "is_two_factor_authenticated", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.two_factor": { + "name": "two_factor", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret": { + "name": "secret", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "initiated_time": { + "name": "initiated_time", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "two_factor_user_id_users_id_fk": { + "name": "two_factor_user_id_users_id_fk", + "tableFrom": "two_factor", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "two_factor_cuid_unique": { + "name": "two_factor_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + }, + "two_factor_user_id_unique": { + "name": "two_factor_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + } + } + }, + "public.user_roles": { + "name": "user_roles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "primary": { + "name": "primary", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_roles_user_id_users_id_fk": { + "name": "user_roles_user_id_users_id_fk", + "tableFrom": "user_roles", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_roles_role_id_roles_id_fk": { + "name": "user_roles_role_id_roles_id_fk", + "tableFrom": "user_roles", + "tableTo": "roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_roles_cuid_unique": { + "name": "user_roles_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "verified": { + "name": "verified", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "receive_email": { + "name": "receive_email", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "picture": { + "name": "picture", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "mfa_enabled": { + "name": "mfa_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "theme": { + "name": "theme", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'system'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_cuid_unique": { + "name": "users_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + }, + "users_username_unique": { + "name": "users_username_unique", + "nullsNotDistinct": false, + "columns": [ + "username" + ] + }, + "users_email_unique": { + "name": "users_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + } + }, + "public.wishlist_items": { + "name": "wishlist_items", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "wishlist_id": { + "name": "wishlist_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "game_id": { + "name": "game_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "wishlist_items_wishlist_id_wishlists_id_fk": { + "name": "wishlist_items_wishlist_id_wishlists_id_fk", + "tableFrom": "wishlist_items", + "tableTo": "wishlists", + "columnsFrom": [ + "wishlist_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "wishlist_items_game_id_games_id_fk": { + "name": "wishlist_items_game_id_games_id_fk", + "tableFrom": "wishlist_items", + "tableTo": "games", + "columnsFrom": [ + "game_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "wishlist_items_cuid_unique": { + "name": "wishlist_items_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + }, + "public.wishlists": { + "name": "wishlists", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "cuid": { + "name": "cuid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'My Wishlist'" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "wishlists_user_id_users_id_fk": { + "name": "wishlists_user_id_users_id_fk", + "tableFrom": "wishlists", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "wishlists_cuid_unique": { + "name": "wishlists_cuid_unique", + "nullsNotDistinct": false, + "columns": [ + "cuid" + ] + } + } + } + }, + "enums": { + "public.external_id_type": { + "name": "external_id_type", + "schema": "public", + "values": [ + "game", + "category", + "mechanic", + "publisher", + "designer", + "artist" + ] + } + }, + "schemas": {}, + "sequences": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/src/lib/server/api/databases/migrations/meta/_journal.json b/src/lib/server/api/databases/migrations/meta/_journal.json index 1f88a00..6022f03 100644 --- a/src/lib/server/api/databases/migrations/meta/_journal.json +++ b/src/lib/server/api/databases/migrations/meta/_journal.json @@ -8,6 +8,13 @@ "when": 1725489682980, "tag": "0000_volatile_warhawk", "breakpoints": true + }, + { + "idx": 1, + "version": "7", + "when": 1726877846811, + "tag": "0001_pink_the_enforcers", + "breakpoints": true } ] } \ No newline at end of file diff --git a/src/lib/server/api/databases/tables/users.table.ts b/src/lib/server/api/databases/tables/users.table.ts index 2836dba..c244bbd 100644 --- a/src/lib/server/api/databases/tables/users.table.ts +++ b/src/lib/server/api/databases/tables/users.table.ts @@ -15,6 +15,8 @@ export const usersTable = pgTable('users', { last_name: text('last_name'), verified: boolean('verified').default(false), receive_email: boolean('receive_email').default(false), + email_verified: boolean('email_verified').default(false), + picture: text('picture'), mfa_enabled: boolean('mfa_enabled').notNull().default(false), theme: text('theme').default('system'), ...timestamps, diff --git a/src/lib/server/api/services/oauth.service.ts b/src/lib/server/api/services/oauth.service.ts index 0e62baa..8dae4f9 100644 --- a/src/lib/server/api/services/oauth.service.ts +++ b/src/lib/server/api/services/oauth.service.ts @@ -1,6 +1,7 @@ import { inject, injectable } from 'tsyringe' import { FederatedIdentityRepository } from '../repositories/federated_identity.repository' import { UsersService } from './users.service' +import type {OAuthUser} from "$lib/server/api/common/types/oauth-user"; @injectable() export class OAuthService { @@ -9,14 +10,14 @@ export class OAuthService { @inject(UsersService) private readonly usersService: UsersService, ) {} - async handleOAuthUser(oauthUserId: number, oauthUsername: string, oauthProvider: string) { - const federatedUser = await this.federatedIdentityRepository.findOneByFederatedUserIdAndProvider(`${oauthUserId}`, oauthProvider) + async handleOAuthUser(oAuthUser: OAuthUser, oauthProvider: string) { + const federatedUser = await this.federatedIdentityRepository.findOneByFederatedUserIdAndProvider(oAuthUser.sub, oauthProvider) if (federatedUser) { return federatedUser.user_id } - const user = await this.usersService.createOAuthUser(oauthUserId, oauthUsername, oauthProvider) + const user = await this.usersService.createOAuthUser(oAuthUser, oauthProvider) if (!user) { throw new Error('Failed to create user') diff --git a/src/lib/server/api/services/users.service.ts b/src/lib/server/api/services/users.service.ts index 008a41a..8298793 100644 --- a/src/lib/server/api/services/users.service.ts +++ b/src/lib/server/api/services/users.service.ts @@ -5,11 +5,12 @@ import { WishlistsRepository } from '$lib/server/api/repositories/wishlists.repo import { TokensService } from '$lib/server/api/services/tokens.service' import { UserRolesService } from '$lib/server/api/services/user_roles.service' import { inject, injectable } from 'tsyringe' -import { CredentialsType } from '../databases/tables' +import {CredentialsType, RoleName} from '../databases/tables' import { type UpdateUser, UsersRepository } from '../repositories/users.repository' import { CollectionsService } from './collections.service' import { DrizzleService } from './drizzle.service' import { WishlistsService } from './wishlists.service' +import type {OAuthUser} from "$lib/server/api/common/types/oauth-user"; @injectable() export class UsersService { @@ -58,18 +59,23 @@ export class UsersService { return null } - await this.userRolesService.addRoleToUser(createdUser.id, 'user', true, trx) + await this.userRolesService.addRoleToUser(createdUser.id, RoleName.USER, true, trx) await this.wishlistsService.createEmptyNoName(createdUser.id, trx) await this.collectionsService.createEmptyNoName(createdUser.id, trx) }) } - async createOAuthUser(oauthUserId: number, oauthUsername: string, oauthProvider: string) { + async createOAuthUser(oAuthUser: OAuthUser, oauthProvider: string) { return await this.drizzleService.db.transaction(async (trx) => { const createdUser = await this.usersRepository.create( { - username: oauthUsername, + username: oAuthUser.username || oAuthUser.username, + email: oAuthUser.email || null, + first_name: oAuthUser.given_name || null, + last_name: oAuthUser.family_name || null, + picture: oAuthUser.picture || null, + email_verified: oAuthUser.email_verified || false, }, trx, ) @@ -82,13 +88,13 @@ export class UsersService { { identity_provider: oauthProvider, user_id: createdUser.id, - federated_user_id: `${oauthUserId}`, - federated_username: oauthUsername, + federated_user_id: oAuthUser.sub, + federated_username: oAuthUser.email || oAuthUser.username, }, trx, ) - await this.userRolesService.addRoleToUser(createdUser.id, 'user', true, trx) + await this.userRolesService.addRoleToUser(createdUser.id, RoleName.USER, true, trx) await this.wishlistsService.createEmptyNoName(createdUser.id, trx) await this.collectionsService.createEmptyNoName(createdUser.id, trx) diff --git a/src/routes/(auth)/login/google/+server.ts b/src/routes/(auth)/login/google/+server.ts index 3c2ce04..98da6dd 100644 --- a/src/routes/(auth)/login/google/+server.ts +++ b/src/routes/(auth)/login/google/+server.ts @@ -9,7 +9,9 @@ export async function GET(event: RequestEvent): Promise { const state = generateState() const codeVerifier = generateCodeVerifier(); - const url = await google.createAuthorizationURL(state, codeVerifier) + const url = await google.createAuthorizationURL(state, codeVerifier, { + scopes: ["profile", "email", "openid"] + }) event.cookies.set('google_oauth_state', state, { path: '/', From 03b6bdbcf34a77c6bfcead4a3aea959707cd5fa6 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Sat, 21 Sep 2024 09:37:21 -0700 Subject: [PATCH 18/29] Fixing types and using provider type. --- src/lib/server/api/common/types/{oauth-user.ts => oauth.ts} | 4 +++- src/lib/server/api/controllers/oauth.controller.ts | 4 ++-- src/lib/server/api/services/oauth.service.ts | 4 ++-- src/lib/server/api/services/users.service.ts | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) rename src/lib/server/api/common/types/{oauth-user.ts => oauth.ts} (73%) diff --git a/src/lib/server/api/common/types/oauth-user.ts b/src/lib/server/api/common/types/oauth.ts similarity index 73% rename from src/lib/server/api/common/types/oauth-user.ts rename to src/lib/server/api/common/types/oauth.ts index 9d14b0c..60e8bbd 100644 --- a/src/lib/server/api/common/types/oauth-user.ts +++ b/src/lib/server/api/common/types/oauth.ts @@ -6,4 +6,6 @@ export type OAuthUser = { username: string; email?: string; email_verified?: boolean; -} \ No newline at end of file +} + +export type OAuthProviders = 'github' | 'google' | 'apple' \ No newline at end of file diff --git a/src/lib/server/api/controllers/oauth.controller.ts b/src/lib/server/api/controllers/oauth.controller.ts index ab8edb0..6a542d0 100644 --- a/src/lib/server/api/controllers/oauth.controller.ts +++ b/src/lib/server/api/controllers/oauth.controller.ts @@ -7,7 +7,7 @@ import { OAuth2RequestError } from 'arctic' import { getCookie, setCookie } from 'hono/cookie' import { TimeSpan } from 'oslo' import { inject, injectable } from 'tsyringe' -import type {OAuthUser} from "$lib/server/api/common/types/oauth-user"; +import type {OAuthUser} from "$lib/server/api/common/types/oauth"; @injectable() export class OAuthController extends Controller { @@ -41,7 +41,7 @@ export class OAuthController extends Controller { const oAuthUser: OAuthUser = { sub: `${githubUser.id}`, username: githubUser.login, - email: null + email: undefined } const userId = await this.oauthService.handleOAuthUser(oAuthUser, 'github') diff --git a/src/lib/server/api/services/oauth.service.ts b/src/lib/server/api/services/oauth.service.ts index 8dae4f9..ef563c6 100644 --- a/src/lib/server/api/services/oauth.service.ts +++ b/src/lib/server/api/services/oauth.service.ts @@ -1,7 +1,7 @@ import { inject, injectable } from 'tsyringe' import { FederatedIdentityRepository } from '../repositories/federated_identity.repository' import { UsersService } from './users.service' -import type {OAuthUser} from "$lib/server/api/common/types/oauth-user"; +import type {OAuthUser, OAuthProviders} from "$lib/server/api/common/types/oauth"; @injectable() export class OAuthService { @@ -10,7 +10,7 @@ export class OAuthService { @inject(UsersService) private readonly usersService: UsersService, ) {} - async handleOAuthUser(oAuthUser: OAuthUser, oauthProvider: string) { + async handleOAuthUser(oAuthUser: OAuthUser, oauthProvider: OAuthProviders) { const federatedUser = await this.federatedIdentityRepository.findOneByFederatedUserIdAndProvider(oAuthUser.sub, oauthProvider) if (federatedUser) { diff --git a/src/lib/server/api/services/users.service.ts b/src/lib/server/api/services/users.service.ts index 8298793..172908f 100644 --- a/src/lib/server/api/services/users.service.ts +++ b/src/lib/server/api/services/users.service.ts @@ -10,7 +10,7 @@ import { type UpdateUser, UsersRepository } from '../repositories/users.reposito import { CollectionsService } from './collections.service' import { DrizzleService } from './drizzle.service' import { WishlistsService } from './wishlists.service' -import type {OAuthUser} from "$lib/server/api/common/types/oauth-user"; +import type {OAuthUser} from "$lib/server/api/common/types/oauth"; @injectable() export class UsersService { From e4ac3ee7f0cadd68e1335713d755b13273626582 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Sat, 21 Sep 2024 09:38:30 -0700 Subject: [PATCH 19/29] Removing simple icons dependency --- package.json | 1 - pnpm-lock.yaml | 9 --------- src/routes/(auth)/login/+page.svelte | 1 - 3 files changed, 11 deletions(-) diff --git a/package.json b/package.json index fc21126..c56b854 100644 --- a/package.json +++ b/package.json @@ -121,7 +121,6 @@ "radix-svelte": "^0.9.0", "rate-limit-redis": "^4.2.0", "reflect-metadata": "^0.2.2", - "simple-icons": "^13.10.0", "svelte-french-toast": "^1.2.0", "svelte-lazy-loader": "^1.0.0", "tailwind-merge": "^2.5.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5861e10..b13a638 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -143,9 +143,6 @@ importers: reflect-metadata: specifier: ^0.2.2 version: 0.2.2 - simple-icons: - specifier: ^13.10.0 - version: 13.10.0 svelte-french-toast: specifier: ^1.2.0 version: 1.2.0(svelte@5.0.0-next.175) @@ -4225,10 +4222,6 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - simple-icons@13.10.0: - resolution: {integrity: sha512-akHZxjNvq4nLlLsKxDot7A+ZYXgjhAP4GwvWEItHeKiquuWXoI8xGGfP+hzGLbTmbmi2teYmHMS45PIOFy6EFA==} - engines: {node: '>=0.12.18'} - simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} @@ -8554,8 +8547,6 @@ snapshots: signal-exit@4.1.0: {} - simple-icons@13.10.0: {} - simple-swizzle@0.2.2: dependencies: is-arrayish: 0.3.2 diff --git a/src/routes/(auth)/login/+page.svelte b/src/routes/(auth)/login/+page.svelte index 8d6ecaf..662bab1 100644 --- a/src/routes/(auth)/login/+page.svelte +++ b/src/routes/(auth)/login/+page.svelte @@ -9,7 +9,6 @@ import { boredState } from '$lib/stores/boredState.js' import { receive, send } from '$lib/utils/pageCrossfade' import { signInSchema } from '$lib/validations/auth' import { AlertCircle } from 'lucide-svelte' -import { siApple, siGithub, siGoogle } from 'simple-icons' import * as flashModule from 'sveltekit-flash-message/client' import { zodClient } from 'sveltekit-superforms/adapters' import { superForm } from 'sveltekit-superforms/client' From a45d782910f68c922162754a8ad741d6596a92a8 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Sun, 22 Sep 2024 14:45:24 -0700 Subject: [PATCH 20/29] Remove OG image generation from Satori for now. --- package.json | 6 +- pnpm-lock.yaml | 265 +++--------------- src/lib/renderImage.ts | 45 --- .../(app)/(protected)/admin/+layout.svelte | 2 +- src/routes/og/+server.ts | 28 -- 5 files changed, 45 insertions(+), 301 deletions(-) delete mode 100644 src/lib/renderImage.ts delete mode 100644 src/routes/og/+server.ts diff --git a/package.json b/package.json index c56b854..9f8db5a 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "@sveltejs/adapter-auto": "^3.2.5", "@sveltejs/enhanced-img": "^0.3.8", "@sveltejs/kit": "^2.5.28", - "@sveltejs/vite-plugin-svelte": "^3.1.2", + "@sveltejs/vite-plugin-svelte": "4.0.0-next.7", "@types/cookie": "^0.6.0", "@types/node": "^20.16.5", "@types/pg": "^8.11.10", @@ -45,7 +45,6 @@ "eslint-plugin-svelte": "2.36.0-next.13", "just-clone": "^6.2.0", "just-debounce-it": "^3.2.0", - "lucia": "3.2.0", "lucide-svelte": "^0.408.0", "nodemailer": "^6.9.15", "postcss": "^8.4.47", @@ -54,8 +53,6 @@ "postcss-preset-env": "^9.6.0", "prettier": "^3.3.3", "prettier-plugin-svelte": "^3.2.6", - "satori": "^0.10.14", - "satori-html": "^0.3.2", "svelte": "5.0.0-next.175", "svelte-check": "^3.8.6", "svelte-headless-table": "^0.18.2", @@ -87,7 +84,6 @@ "@lukeed/uuid": "^2.0.1", "@neondatabase/serverless": "^0.9.5", "@paralleldrive/cuid2": "^2.2.2", - "@resvg/resvg-js": "^2.6.2", "@sveltejs/adapter-node": "^5.2.4", "@sveltejs/adapter-vercel": "^5.4.4", "@types/feather-icons": "^4.29.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b13a638..16e4045 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,15 +41,12 @@ importers: '@paralleldrive/cuid2': specifier: ^2.2.2 version: 2.2.2 - '@resvg/resvg-js': - specifier: ^2.6.2 - version: 2.6.2 '@sveltejs/adapter-node': specifier: ^5.2.4 - version: 5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) + version: 5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) '@sveltejs/adapter-vercel': specifier: ^5.4.4 - version: 5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) + version: 5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) '@types/feather-icons': specifier: ^4.29.4 version: 4.29.4 @@ -91,7 +88,7 @@ importers: version: 4.29.2 formsnap: specifier: ^1.0.1 - version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)) + version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)) handlebars: specifier: ^4.7.8 version: 4.7.8 @@ -182,16 +179,16 @@ importers: version: 1.47.2 '@sveltejs/adapter-auto': specifier: ^3.2.5 - version: 3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) + version: 3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) '@sveltejs/enhanced-img': specifier: ^0.3.8 version: 0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@sveltejs/kit': specifier: ^2.5.28 - version: 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + version: 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@sveltejs/vite-plugin-svelte': - specifier: ^3.1.2 - version: 3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + specifier: 4.0.0-next.7 + version: 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@types/cookie': specifier: ^0.6.0 version: 0.6.0 @@ -231,9 +228,6 @@ importers: just-debounce-it: specifier: ^3.2.0 version: 3.2.0 - lucia: - specifier: 3.2.0 - version: 3.2.0 lucide-svelte: specifier: ^0.408.0 version: 0.408.0(svelte@5.0.0-next.175) @@ -258,12 +252,6 @@ importers: prettier-plugin-svelte: specifier: ^3.2.6 version: 3.2.6(prettier@3.3.3)(svelte@5.0.0-next.175) - satori: - specifier: ^0.10.14 - version: 0.10.14 - satori-html: - specifier: ^0.3.2 - version: 0.3.2 svelte: specifier: 5.0.0-next.175 version: 5.0.0-next.175 @@ -284,13 +272,13 @@ importers: version: 2.0.1 sveltekit-flash-message: specifier: ^2.4.4 - version: 2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175) + version: 2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175) sveltekit-rate-limiter: specifier: ^0.5.2 - version: 0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) + version: 0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) sveltekit-superforms: specifier: ^2.19.0 - version: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) + version: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) tailwindcss: specifier: ^3.4.12 version: 3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) @@ -1715,82 +1703,6 @@ packages: resolution: {integrity: sha512-xhhEcEvhQC8mP5oOr5hbE4CmUgmw/IPV1jhpGg2xSkzoFrt9i8YVqBQt9744EFesi5F7pBheWozg63RUBM/5JA==} engines: {node: '>=18.16.0'} - '@resvg/resvg-js-android-arm-eabi@2.6.2': - resolution: {integrity: sha512-FrJibrAk6v29eabIPgcTUMPXiEz8ssrAk7TXxsiZzww9UTQ1Z5KAbFJs+Z0Ez+VZTYgnE5IQJqBcoSiMebtPHA==} - engines: {node: '>= 10'} - cpu: [arm] - os: [android] - - '@resvg/resvg-js-android-arm64@2.6.2': - resolution: {integrity: sha512-VcOKezEhm2VqzXpcIJoITuvUS/fcjIw5NA/w3tjzWyzmvoCdd+QXIqy3FBGulWdClvp4g+IfUemigrkLThSjAQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [android] - - '@resvg/resvg-js-darwin-arm64@2.6.2': - resolution: {integrity: sha512-nmok2LnAd6nLUKI16aEB9ydMC6Lidiiq2m1nEBDR1LaaP7FGs4AJ90qDraxX+CWlVuRlvNjyYJTNv8qFjtL9+A==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - - '@resvg/resvg-js-darwin-x64@2.6.2': - resolution: {integrity: sha512-GInyZLjgWDfsVT6+SHxQVRwNzV0AuA1uqGsOAW+0th56J7Nh6bHHKXHBWzUrihxMetcFDmQMAX1tZ1fZDYSRsw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - - '@resvg/resvg-js-linux-arm-gnueabihf@2.6.2': - resolution: {integrity: sha512-YIV3u/R9zJbpqTTNwTZM5/ocWetDKGsro0SWp70eGEM9eV2MerWyBRZnQIgzU3YBnSBQ1RcxRZvY/UxwESfZIw==} - engines: {node: '>= 10'} - cpu: [arm] - os: [linux] - - '@resvg/resvg-js-linux-arm64-gnu@2.6.2': - resolution: {integrity: sha512-zc2BlJSim7YR4FZDQ8OUoJg5holYzdiYMeobb9pJuGDidGL9KZUv7SbiD4E8oZogtYY42UZEap7dqkkYuA91pg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@resvg/resvg-js-linux-arm64-musl@2.6.2': - resolution: {integrity: sha512-3h3dLPWNgSsD4lQBJPb4f+kvdOSJHa5PjTYVsWHxLUzH4IFTJUAnmuWpw4KqyQ3NA5QCyhw4TWgxk3jRkQxEKg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@resvg/resvg-js-linux-x64-gnu@2.6.2': - resolution: {integrity: sha512-IVUe+ckIerA7xMZ50duAZzwf1U7khQe2E0QpUxu5MBJNao5RqC0zwV/Zm965vw6D3gGFUl7j4m+oJjubBVoftw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@resvg/resvg-js-linux-x64-musl@2.6.2': - resolution: {integrity: sha512-UOf83vqTzoYQO9SZ0fPl2ZIFtNIz/Rr/y+7X8XRX1ZnBYsQ/tTb+cj9TE+KHOdmlTFBxhYzVkP2lRByCzqi4jQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@resvg/resvg-js-win32-arm64-msvc@2.6.2': - resolution: {integrity: sha512-7C/RSgCa+7vqZ7qAbItfiaAWhyRSoD4l4BQAbVDqRRsRgY+S+hgS3in0Rxr7IorKUpGE69X48q6/nOAuTJQxeQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - - '@resvg/resvg-js-win32-ia32-msvc@2.6.2': - resolution: {integrity: sha512-har4aPAlvjnLcil40AC77YDIk6loMawuJwFINEM7n0pZviwMkMvjb2W5ZirsNOZY4aDbo5tLx0wNMREp5Brk+w==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - - '@resvg/resvg-js-win32-x64-msvc@2.6.2': - resolution: {integrity: sha512-ZXtYhtUr5SSaBrUDq7DiyjOFJqBVL/dOBN7N/qmi/pO0IgiWW/f/ue3nbvu9joWE5aAKDoIzy/CxsY0suwGosQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - - '@resvg/resvg-js@2.6.2': - resolution: {integrity: sha512-xBaJish5OeGmniDj9cW5PRa/PtmuVU3ziqrbr5xJj901ZDN4TosrVaNZpEiLZAxdfnhAe7uQ7QFWfjPe9d9K2Q==} - engines: {node: '>= 10'} - '@resvg/resvg-wasm@2.6.0': resolution: {integrity: sha512-iDkBM6Ivex8nULtBu8cX670/lfsGxq8U1cuqE+qS9xFpPQP1enPdVm/33Kq3+B+bAldA+AHNZnCgpmlHo/fZrQ==} engines: {node: '>= 10'} @@ -1968,19 +1880,19 @@ packages: svelte: ^4.0.0 || ^5.0.0-next.0 vite: ^5.0.3 - '@sveltejs/vite-plugin-svelte-inspector@2.1.0': - resolution: {integrity: sha512-9QX28IymvBlSCqsCll5t0kQVxipsfhFFL+L2t3nTWfXnddYwxBuAEtTtlaVQpRz9c37BhJjltSeY4AJSC03SSg==} - engines: {node: ^18.0.0 || >=20} + '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.3': + resolution: {integrity: sha512-kuGJ2CZ5lAw3gKF8Kw0AfKtUJWbwdlDHY14K413B0MCyrzvQvsKTorwmwZcky0+QqY6RnVIZ/5FttB9bQmkLXg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22} peerDependencies: - '@sveltejs/vite-plugin-svelte': ^3.0.0 - svelte: ^4.0.0 || ^5.0.0-next.0 + '@sveltejs/vite-plugin-svelte': ^4.0.0-next.0||^4.0.0 + svelte: ^5.0.0-next.96 || ^5.0.0 vite: ^5.0.0 - '@sveltejs/vite-plugin-svelte@3.1.2': - resolution: {integrity: sha512-Txsm1tJvtiYeLUVRNqxZGKR/mI+CzuIQuc2gn+YCs9rMTowpNZ2Nqt53JdL8KF9bLhAf2ruR/dr9eZCwdTriRA==} - engines: {node: ^18.0.0 || >=20} + '@sveltejs/vite-plugin-svelte@4.0.0-next.7': + resolution: {integrity: sha512-yMUnAqquoayvBDztk1rWUgdtvjv7YcHgopCAB7sWl9SQht8U/7lqwTlJU0ZTAY09pFFRe6bbakd7YoiyyIvJiA==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22} peerDependencies: - svelte: ^4.0.0 || ^5.0.0-next.0 + svelte: ^5.0.0-next.96 || ^5.0.0 vite: ^5.0.0 '@swc/helpers@0.5.13': @@ -4150,13 +4062,6 @@ packages: engines: {node: '>=14.0.0'} hasBin: true - satori-html@0.3.2: - resolution: {integrity: sha512-wjTh14iqADFKDK80e51/98MplTGfxz2RmIzh0GqShlf4a67+BooLywF17TvJPD6phO0Hxm7Mf1N5LtRYvdkYRA==} - - satori@0.10.14: - resolution: {integrity: sha512-abovcqmwl97WKioxpkfuMeZmndB1TuDFY/R+FymrZyiGP+pMYomvgSzVPnbNMWHHESOPosVHGL352oFbdAnJcA==} - engines: {node: '>=16'} - satori@0.10.9: resolution: {integrity: sha512-XU9EELUEZuioT4acLIpCXxHcFzrsC8muvg0MY28d+TlqwxbkTzBmWbw+3+hnCzXT7YZ0Qm8k3eXktDaEu+qmEw==} engines: {node: '>=16'} @@ -4347,12 +4252,6 @@ packages: peerDependencies: svelte: ^4.0.0 - svelte-hmr@0.16.0: - resolution: {integrity: sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==} - engines: {node: ^12.20 || ^14.13.1 || >= 16} - peerDependencies: - svelte: ^3.19.0 || ^4.0.0 - svelte-keyed@2.0.0: resolution: {integrity: sha512-7TeEn+QbJC2OJrHiuM0T8vMBkms3DNpTE+Ir+NtnVBnBMA78aL4f1ft9t0Hn/pBbD/TnIXi4YfjFRAgtN+DZ5g==} peerDependencies: @@ -4647,9 +4546,6 @@ packages: engines: {node: '>=0.8.0'} hasBin: true - ultrahtml@1.5.3: - resolution: {integrity: sha512-GykOvZwgDWZlTQMtp5jrD4BVL+gNn2NVlVafjcFUJ7taY20tqYdwdoWBFy6GBJsNTZe1GkGPkSl5knQAjtgceg==} - undici-types@6.19.8: resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} @@ -4740,8 +4636,8 @@ packages: terser: optional: true - vitefu@0.2.5: - resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} + vitefu@1.0.2: + resolution: {integrity: sha512-0/iAvbXyM3RiPPJ4lyD4w6Mjgtf4ejTK6TPvTNG3H32PLwuT0N/ZjJLiXug7ETE/LWtTeHw9WRv7uX/tIKYyKg==} peerDependencies: vite: ^3.0.0 || ^4.0.0 || ^5.0.0 peerDependenciesMeta: @@ -5927,57 +5823,6 @@ snapshots: '@poppinss/macroable@1.0.2': optional: true - '@resvg/resvg-js-android-arm-eabi@2.6.2': - optional: true - - '@resvg/resvg-js-android-arm64@2.6.2': - optional: true - - '@resvg/resvg-js-darwin-arm64@2.6.2': - optional: true - - '@resvg/resvg-js-darwin-x64@2.6.2': - optional: true - - '@resvg/resvg-js-linux-arm-gnueabihf@2.6.2': - optional: true - - '@resvg/resvg-js-linux-arm64-gnu@2.6.2': - optional: true - - '@resvg/resvg-js-linux-arm64-musl@2.6.2': - optional: true - - '@resvg/resvg-js-linux-x64-gnu@2.6.2': - optional: true - - '@resvg/resvg-js-linux-x64-musl@2.6.2': - optional: true - - '@resvg/resvg-js-win32-arm64-msvc@2.6.2': - optional: true - - '@resvg/resvg-js-win32-ia32-msvc@2.6.2': - optional: true - - '@resvg/resvg-js-win32-x64-msvc@2.6.2': - optional: true - - '@resvg/resvg-js@2.6.2': - optionalDependencies: - '@resvg/resvg-js-android-arm-eabi': 2.6.2 - '@resvg/resvg-js-android-arm64': 2.6.2 - '@resvg/resvg-js-darwin-arm64': 2.6.2 - '@resvg/resvg-js-darwin-x64': 2.6.2 - '@resvg/resvg-js-linux-arm-gnueabihf': 2.6.2 - '@resvg/resvg-js-linux-arm64-gnu': 2.6.2 - '@resvg/resvg-js-linux-arm64-musl': 2.6.2 - '@resvg/resvg-js-linux-x64-gnu': 2.6.2 - '@resvg/resvg-js-linux-x64-musl': 2.6.2 - '@resvg/resvg-js-win32-arm64-msvc': 2.6.2 - '@resvg/resvg-js-win32-ia32-msvc': 2.6.2 - '@resvg/resvg-js-win32-x64-msvc': 2.6.2 - '@resvg/resvg-wasm@2.6.0': {} '@rollup/plugin-commonjs@26.0.1(rollup@4.21.2)': @@ -6093,22 +5938,22 @@ snapshots: '@sodaru/yup-to-json-schema@2.0.1': optional: true - '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': + '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) import-meta-resolve: 4.1.0 - '@sveltejs/adapter-node@5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': + '@sveltejs/adapter-node@5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': dependencies: '@rollup/plugin-commonjs': 26.0.1(rollup@4.21.2) '@rollup/plugin-json': 6.1.0(rollup@4.21.2) '@rollup/plugin-node-resolve': 15.2.3(rollup@4.21.2) - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) rollup: 4.21.2 - '@sveltejs/adapter-vercel@5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': + '@sveltejs/adapter-vercel@5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@vercel/nft': 0.27.4 esbuild: 0.21.5 transitivePeerDependencies: @@ -6125,9 +5970,9 @@ snapshots: transitivePeerDependencies: - rollup - '@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.0.0 @@ -6143,26 +5988,25 @@ snapshots: tiny-glob: 0.2.9 vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) - '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) debug: 4.3.6 svelte: 5.0.0-next.175 vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte-inspector': 3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) debug: 4.3.6 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.11 svelte: 5.0.0-next.175 - svelte-hmr: 0.16.0(svelte@5.0.0-next.175) vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) - vitefu: 0.2.5(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + vitefu: 1.0.2(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) transitivePeerDependencies: - supports-color @@ -7226,11 +7070,11 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)): + formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)): dependencies: nanoid: 5.0.7 svelte: 5.0.0-next.175 - sveltekit-superforms: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) + sveltekit-superforms: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) forwarded@0.2.0: {} @@ -8422,23 +8266,6 @@ snapshots: source-map-js: 1.2.1 optional: true - satori-html@0.3.2: - dependencies: - ultrahtml: 1.5.3 - - satori@0.10.14: - dependencies: - '@shuding/opentype.js': 1.4.0-beta.0 - css-background-parser: 0.1.0 - css-box-shadow: 1.0.0-3 - css-to-react-native: 3.2.0 - emoji-regex: 10.4.0 - escape-html: 1.0.3 - linebreak: 1.1.0 - parse-css-color: 0.2.1 - postcss-value-parser: 4.2.0 - yoga-wasm-web: 0.3.3 - satori@0.10.9: dependencies: '@shuding/opentype.js': 1.4.0-beta.0 @@ -8686,10 +8513,6 @@ snapshots: svelte-render: 2.0.1(svelte@5.0.0-next.175) svelte-subscribe: 2.0.1(svelte@5.0.0-next.175) - svelte-hmr@0.16.0(svelte@5.0.0-next.175): - dependencies: - svelte: 5.0.0-next.175 - svelte-keyed@2.0.0(svelte@5.0.0-next.175): dependencies: svelte: 5.0.0-next.175 @@ -8781,19 +8604,19 @@ snapshots: magic-string: 0.30.11 zimmerframe: 1.1.2 - sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175): + sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) svelte: 5.0.0-next.175 - sveltekit-rate-limiter@0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))): + sveltekit-rate-limiter@0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))): dependencies: '@isaacs/ttlcache': 1.4.1 - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) - sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): + sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) devalue: 5.0.0 just-clone: 6.2.0 memoize-weak: 1.0.2 @@ -8978,8 +8801,6 @@ snapshots: uglify-js@3.19.3: optional: true - ultrahtml@1.5.3: {} - undici-types@6.19.8: {} unfetch@4.2.0: {} @@ -9056,7 +8877,7 @@ snapshots: fsevents: 2.3.3 sass: 1.79.1 - vitefu@0.2.5(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)): + vitefu@1.0.2(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)): optionalDependencies: vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) diff --git a/src/lib/renderImage.ts b/src/lib/renderImage.ts deleted file mode 100644 index eaa0f09..0000000 --- a/src/lib/renderImage.ts +++ /dev/null @@ -1,45 +0,0 @@ -import satori from 'satori'; -import { Resvg } from '@resvg/resvg-js'; -import { html as toReactNode } from 'satori-html'; -import { dev } from '$app/environment'; -import { read } from '$app/server'; - -// we use a Vite plugin to turn this import into the result of fs.readFileSync during build -import firaSansSemiBold from '$lib/fonts/FiraSans-Bold.ttf'; - -const fontData = read(firaSansSemiBold).arrayBuffer(); - -export async function componentToPng(component, - props: Record, - height: number, width: number) { - const result = component.render(props); - const markup = toReactNode(`${result.html}`); - - const svg = await satori(markup, { - fonts: [ - { - name: 'Fira Sans', - data: await fontData, - style: 'normal' - } - ], - height: +height, - width: +width - }); - - const resvg = new Resvg(svg, { - fitTo: { - mode: 'width', - value: +width - } - }); - - const image = resvg.render(); - - return new Response(image.asPng(), { - headers: { - 'content-type': 'image/png', - 'cache-control': dev ? 'no-cache, no-store' : 'public, immutable, no-transform, max-age=86400' - } - }); -} \ No newline at end of file diff --git a/src/routes/(app)/(protected)/admin/+layout.svelte b/src/routes/(app)/(protected)/admin/+layout.svelte index 370488e..35f8d53 100644 --- a/src/routes/(app)/(protected)/admin/+layout.svelte +++ b/src/routes/(app)/(protected)/admin/+layout.svelte @@ -39,7 +39,7 @@

Do the admin stuff

- +{@render children()} diff --git a/src/routes/og/+server.ts b/src/routes/og/+server.ts deleted file mode 100644 index 2eafec8..0000000 --- a/src/routes/og/+server.ts +++ /dev/null @@ -1,28 +0,0 @@ -import SocialImageCard from '$components/socialImageCard.svelte'; -import { componentToPng } from '$lib/renderImage.js'; - -const height = 630; -const width = 1200; - -/** @type {import('./$types').RequestHandler} */ -export async function GET({ url }) { - try { - const faviconImageLocation = 'images/bored-game.png'; - const image = `${new URL(url.origin).href}${faviconImageLocation}`; - const header = url.searchParams.get('header') ?? undefined; - const page = url.searchParams.get('page') ?? undefined; - const content = url.searchParams.get('content') ?? ''; - - return componentToPng(SocialImageCard, { - header, - page, - content, - image, - width: `${width}`, - height: `${height}`, - url: new URL(url.origin).href - }, height, width); - } catch (e) { - console.error(e); - } -}; From 216847b0fd3fa735600046a89e5a795083b8123d Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Sun, 22 Sep 2024 20:11:45 -0700 Subject: [PATCH 21/29] Trying older packages for build. --- package.json | 21 ++-- pnpm-lock.yaml | 254 ++++++++++++------------------------------------- 2 files changed, 73 insertions(+), 202 deletions(-) diff --git a/package.json b/package.json index 9f8db5a..12495c8 100644 --- a/package.json +++ b/package.json @@ -27,11 +27,11 @@ "@faker-js/faker": "^8.4.1", "@melt-ui/pp": "^0.3.2", "@melt-ui/svelte": "^0.83.0", - "@playwright/test": "^1.47.2", + "@playwright/test": "^1.47.1", "@sveltejs/adapter-auto": "^3.2.5", "@sveltejs/enhanced-img": "^0.3.8", "@sveltejs/kit": "^2.5.28", - "@sveltejs/vite-plugin-svelte": "4.0.0-next.7", + "@sveltejs/vite-plugin-svelte": "^3.1.2", "@types/cookie": "^0.6.0", "@types/node": "^20.16.5", "@types/pg": "^8.11.10", @@ -45,6 +45,7 @@ "eslint-plugin-svelte": "2.36.0-next.13", "just-clone": "^6.2.0", "just-debounce-it": "^3.2.0", + "lucia": "3.2.0", "lucide-svelte": "^0.408.0", "nodemailer": "^6.9.15", "postcss": "^8.4.47", @@ -61,13 +62,13 @@ "svelte-sequential-preprocessor": "^2.0.1", "sveltekit-flash-message": "^2.4.4", "sveltekit-rate-limiter": "^0.5.2", - "sveltekit-superforms": "^2.19.0", + "sveltekit-superforms": "^2.18.1", "tailwindcss": "^3.4.12", "ts-node": "^10.9.2", "tslib": "^2.7.0", "tsx": "^4.19.1", "typescript": "^5.6.2", - "vite": "^5.4.7", + "vite": "^5.4.6", "vitest": "^1.6.0", "zod": "^3.23.8" }, @@ -84,13 +85,12 @@ "@lukeed/uuid": "^2.0.1", "@neondatabase/serverless": "^0.9.5", "@paralleldrive/cuid2": "^2.2.2", - "@sveltejs/adapter-node": "^5.2.4", + "@sveltejs/adapter-node": "^5.2.3", "@sveltejs/adapter-vercel": "^5.4.4", "@types/feather-icons": "^4.29.4", - "@vercel/og": "^0.5.20", - "bits-ui": "^0.21.15", + "bits-ui": "^0.21.13", "boardgamegeekclient": "^1.9.1", - "bullmq": "^5.13.2", + "bullmq": "^5.13.1", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "cookie": "^0.6.0", @@ -124,6 +124,5 @@ "tailwindcss-animate": "^1.0.7", "tsyringe": "^4.8.0", "zod-to-json-schema": "^3.23.3" - }, - "license": "MIT" -} \ No newline at end of file + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 16e4045..86433c9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -42,25 +42,22 @@ importers: specifier: ^2.2.2 version: 2.2.2 '@sveltejs/adapter-node': - specifier: ^5.2.4 - version: 5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) + specifier: ^5.2.3 + version: 5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) '@sveltejs/adapter-vercel': specifier: ^5.4.4 - version: 5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) + version: 5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) '@types/feather-icons': specifier: ^4.29.4 version: 4.29.4 - '@vercel/og': - specifier: ^0.5.20 - version: 0.5.20 bits-ui: - specifier: ^0.21.15 + specifier: ^0.21.13 version: 0.21.15(svelte@5.0.0-next.175) boardgamegeekclient: specifier: ^1.9.1 version: 1.9.1 bullmq: - specifier: ^5.13.2 + specifier: ^5.13.1 version: 5.13.2 class-variance-authority: specifier: ^0.7.0 @@ -88,7 +85,7 @@ importers: version: 4.29.2 formsnap: specifier: ^1.0.1 - version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)) + version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)) handlebars: specifier: ^4.7.8 version: 4.7.8 @@ -175,20 +172,20 @@ importers: specifier: ^0.83.0 version: 0.83.0(svelte@5.0.0-next.175) '@playwright/test': - specifier: ^1.47.2 + specifier: ^1.47.1 version: 1.47.2 '@sveltejs/adapter-auto': specifier: ^3.2.5 - version: 3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) + version: 3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) '@sveltejs/enhanced-img': specifier: ^0.3.8 version: 0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@sveltejs/kit': specifier: ^2.5.28 - version: 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + version: 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@sveltejs/vite-plugin-svelte': - specifier: 4.0.0-next.7 - version: 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + specifier: ^3.1.2 + version: 3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@types/cookie': specifier: ^0.6.0 version: 0.6.0 @@ -228,6 +225,9 @@ importers: just-debounce-it: specifier: ^3.2.0 version: 3.2.0 + lucia: + specifier: 3.2.0 + version: 3.2.0 lucide-svelte: specifier: ^0.408.0 version: 0.408.0(svelte@5.0.0-next.175) @@ -272,13 +272,13 @@ importers: version: 2.0.1 sveltekit-flash-message: specifier: ^2.4.4 - version: 2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175) + version: 2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175) sveltekit-rate-limiter: specifier: ^0.5.2 - version: 0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) + version: 0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) sveltekit-superforms: - specifier: ^2.19.0 - version: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) + specifier: ^2.18.1 + version: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) tailwindcss: specifier: ^3.4.12 version: 3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) @@ -295,7 +295,7 @@ importers: specifier: ^5.6.2 version: 5.6.2 vite: - specifier: ^5.4.7 + specifier: ^5.4.6 version: 5.4.7(@types/node@20.16.5)(sass@1.79.1) vitest: specifier: ^1.6.0 @@ -1703,10 +1703,6 @@ packages: resolution: {integrity: sha512-xhhEcEvhQC8mP5oOr5hbE4CmUgmw/IPV1jhpGg2xSkzoFrt9i8YVqBQt9744EFesi5F7pBheWozg63RUBM/5JA==} engines: {node: '>=18.16.0'} - '@resvg/resvg-wasm@2.6.0': - resolution: {integrity: sha512-iDkBM6Ivex8nULtBu8cX670/lfsGxq8U1cuqE+qS9xFpPQP1enPdVm/33Kq3+B+bAldA+AHNZnCgpmlHo/fZrQ==} - engines: {node: '>= 10'} - '@rollup/plugin-commonjs@26.0.1': resolution: {integrity: sha512-UnsKoZK6/aGIH6AdkptXhNvhaqftcjq3zZdT+LY5Ftms6JR06nADcDsYp5hTU9E2lbJUEOhdlY5J4DNTneM+jQ==} engines: {node: '>=16.0.0 || 14 >= 14.17'} @@ -1827,11 +1823,6 @@ packages: cpu: [x64] os: [win32] - '@shuding/opentype.js@1.4.0-beta.0': - resolution: {integrity: sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==} - engines: {node: '>= 8.0.0'} - hasBin: true - '@sideway/address@4.1.5': resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} @@ -1880,19 +1871,19 @@ packages: svelte: ^4.0.0 || ^5.0.0-next.0 vite: ^5.0.3 - '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.3': - resolution: {integrity: sha512-kuGJ2CZ5lAw3gKF8Kw0AfKtUJWbwdlDHY14K413B0MCyrzvQvsKTorwmwZcky0+QqY6RnVIZ/5FttB9bQmkLXg==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22} + '@sveltejs/vite-plugin-svelte-inspector@2.1.0': + resolution: {integrity: sha512-9QX28IymvBlSCqsCll5t0kQVxipsfhFFL+L2t3nTWfXnddYwxBuAEtTtlaVQpRz9c37BhJjltSeY4AJSC03SSg==} + engines: {node: ^18.0.0 || >=20} peerDependencies: - '@sveltejs/vite-plugin-svelte': ^4.0.0-next.0||^4.0.0 - svelte: ^5.0.0-next.96 || ^5.0.0 + '@sveltejs/vite-plugin-svelte': ^3.0.0 + svelte: ^4.0.0 || ^5.0.0-next.0 vite: ^5.0.0 - '@sveltejs/vite-plugin-svelte@4.0.0-next.7': - resolution: {integrity: sha512-yMUnAqquoayvBDztk1rWUgdtvjv7YcHgopCAB7sWl9SQht8U/7lqwTlJU0ZTAY09pFFRe6bbakd7YoiyyIvJiA==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22} + '@sveltejs/vite-plugin-svelte@3.1.2': + resolution: {integrity: sha512-Txsm1tJvtiYeLUVRNqxZGKR/mI+CzuIQuc2gn+YCs9rMTowpNZ2Nqt53JdL8KF9bLhAf2ruR/dr9eZCwdTriRA==} + engines: {node: ^18.0.0 || >=20} peerDependencies: - svelte: ^5.0.0-next.96 || ^5.0.0 + svelte: ^4.0.0 || ^5.0.0-next.0 vite: ^5.0.0 '@swc/helpers@0.5.13': @@ -2025,10 +2016,6 @@ packages: engines: {node: '>=16'} hasBin: true - '@vercel/og@0.5.20': - resolution: {integrity: sha512-zi+ZXSx/peXA+1lq7s/5Vzmm/TTfTSf/5P1qNYnh42+7X+pZmahWoXt0i7SWiq3WagfsNUNA4hUDapDiHRoXqA==} - engines: {node: '>=16'} - '@vinejs/compiler@2.5.0': resolution: {integrity: sha512-hg4ekaB5Y2zh+IWzBiC/WCDWrIfpVnKu/ubUvelKlidc/VbulsexoFRw5kJGHZenPVI5YzNnDeTdYSALkTV7jQ==} engines: {node: '>=18.0.0'} @@ -2170,10 +2157,6 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - base64-js@0.0.8: - resolution: {integrity: sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==} - engines: {node: '>= 0.4'} - binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -2251,9 +2234,6 @@ packages: resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} engines: {node: '>=16'} - camelize@1.0.1: - resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} - caniuse-lite@1.0.30001655: resolution: {integrity: sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==} @@ -2370,22 +2350,12 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} - css-background-parser@0.1.0: - resolution: {integrity: sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA==} - css-blank-pseudo@6.0.2: resolution: {integrity: sha512-J/6m+lsqpKPqWHOifAFtKFeGLOzw3jR92rxQcwRUfA/eTuZzKfKlxOmYDx2+tqOPQAueNvBiY8WhAeHu5qNmTg==} engines: {node: ^14 || ^16 || >=18} peerDependencies: postcss: ^8.4 - css-box-shadow@1.0.0-3: - resolution: {integrity: sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg==} - - css-color-keywords@1.0.0: - resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==} - engines: {node: '>=4'} - css-has-pseudo@6.0.5: resolution: {integrity: sha512-ZTv6RlvJJZKp32jPYnAJVhowDCrRrHUTAxsYSuUPBEDJjzws6neMnzkRblxtgmv1RgcV5dhH2gn7E3wA9Wt6lw==} engines: {node: ^14 || ^16 || >=18} @@ -2398,9 +2368,6 @@ packages: peerDependencies: postcss: ^8.4 - css-to-react-native@3.2.0: - resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==} - css-tree@2.3.1: resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} @@ -2623,9 +2590,6 @@ packages: electron-to-chromium@1.5.13: resolution: {integrity: sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==} - emoji-regex@10.4.0: - resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} - emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2797,9 +2761,6 @@ packages: feather-icons@4.29.2: resolution: {integrity: sha512-0TaCFTnBTVCz6U+baY2UJNKne5ifGh7sMG4ZC2LoBWCZdIyPa+y6UiR4lEYGws1JOFWdee8KAsAIvu0VcXqiqA==} - fflate@0.7.4: - resolution: {integrity: sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==} - file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -2966,10 +2927,6 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} - hex-rgb@4.3.0: - resolution: {integrity: sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw==} - engines: {node: '>=6'} - hono-rate-limiter@0.4.0: resolution: {integrity: sha512-7RWU2HZvxPtfBrvjXKDiQ3F6ZH8k49JhxVkHquUz5UZKjauj5PrP29MvISykThtfpy4mGG6kqxFBHW1ed9wwnA==} peerDependencies: @@ -3162,9 +3119,6 @@ packages: resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} engines: {node: '>=14'} - linebreak@1.1.0: - resolution: {integrity: sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==} - lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -3495,16 +3449,10 @@ packages: package-json-from-dist@1.0.0: resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} - pako@0.2.9: - resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} - parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} - parse-css-color@0.2.1: - resolution: {integrity: sha512-bwS/GGIFV3b6KS4uwpzCFj4w297Yl3uqnSgIPsoQkx7GMLROXfMnWvxfNkL0oh8HVhZA4hvJoEoEIqonfJ3BWg==} - parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -4062,10 +4010,6 @@ packages: engines: {node: '>=14.0.0'} hasBin: true - satori@0.10.9: - resolution: {integrity: sha512-XU9EELUEZuioT4acLIpCXxHcFzrsC8muvg0MY28d+TlqwxbkTzBmWbw+3+hnCzXT7YZ0Qm8k3eXktDaEu+qmEw==} - engines: {node: '>=16'} - schema-dts@1.1.2: resolution: {integrity: sha512-MpNwH0dZJHinVxk9bT8XUdjKTxMYrA5bLtrrGmFA6PTLwlOKnhi67XoRd6/ty+Djt6ZC0slR57qFhZDNMI6DhQ==} peerDependencies: @@ -4178,9 +4122,6 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} - string.prototype.codepointat@0.2.1: - resolution: {integrity: sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==} - string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -4252,6 +4193,12 @@ packages: peerDependencies: svelte: ^4.0.0 + svelte-hmr@0.16.0: + resolution: {integrity: sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==} + engines: {node: ^12.20 || ^14.13.1 || >= 16} + peerDependencies: + svelte: ^3.19.0 || ^4.0.0 + svelte-keyed@2.0.0: resolution: {integrity: sha512-7TeEn+QbJC2OJrHiuM0T8vMBkms3DNpTE+Ir+NtnVBnBMA78aL4f1ft9t0Hn/pBbD/TnIXi4YfjFRAgtN+DZ5g==} peerDependencies: @@ -4430,9 +4377,6 @@ packages: tiny-glob@0.2.9: resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} - tiny-inflate@1.0.3: - resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} - tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -4552,9 +4496,6 @@ packages: unfetch@4.2.0: resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==} - unicode-trie@2.0.0: - resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==} - unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} @@ -4636,8 +4577,8 @@ packages: terser: optional: true - vitefu@1.0.2: - resolution: {integrity: sha512-0/iAvbXyM3RiPPJ4lyD4w6Mjgtf4ejTK6TPvTNG3H32PLwuT0N/ZjJLiXug7ETE/LWtTeHw9WRv7uX/tIKYyKg==} + vitefu@0.2.5: + resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} peerDependencies: vite: ^3.0.0 || ^4.0.0 || ^5.0.0 peerDependenciesMeta: @@ -4752,9 +4693,6 @@ packages: resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} engines: {node: '>=12.20'} - yoga-wasm-web@0.3.3: - resolution: {integrity: sha512-N+d4UJSJbt/R3wqY7Coqs5pcV0aUj2j9IaQ3rNj9bVCLld8tTGKRa2USARjnvZJWVx1NDmQev8EknoczaOQDOA==} - yup@1.4.0: resolution: {integrity: sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==} @@ -5823,8 +5761,6 @@ snapshots: '@poppinss/macroable@1.0.2': optional: true - '@resvg/resvg-wasm@2.6.0': {} - '@rollup/plugin-commonjs@26.0.1(rollup@4.21.2)': dependencies: '@rollup/pluginutils': 5.1.0(rollup@4.21.2) @@ -5914,11 +5850,6 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.21.2': optional: true - '@shuding/opentype.js@1.4.0-beta.0': - dependencies: - fflate: 0.7.4 - string.prototype.codepointat: 0.2.1 - '@sideway/address@4.1.5': dependencies: '@hapi/hoek': 9.3.0 @@ -5938,22 +5869,22 @@ snapshots: '@sodaru/yup-to-json-schema@2.0.1': optional: true - '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': + '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) import-meta-resolve: 4.1.0 - '@sveltejs/adapter-node@5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': + '@sveltejs/adapter-node@5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': dependencies: '@rollup/plugin-commonjs': 26.0.1(rollup@4.21.2) '@rollup/plugin-json': 6.1.0(rollup@4.21.2) '@rollup/plugin-node-resolve': 15.2.3(rollup@4.21.2) - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) rollup: 4.21.2 - '@sveltejs/adapter-vercel@5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': + '@sveltejs/adapter-vercel@5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@vercel/nft': 0.27.4 esbuild: 0.21.5 transitivePeerDependencies: @@ -5970,9 +5901,9 @@ snapshots: transitivePeerDependencies: - rollup - '@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.0.0 @@ -5988,25 +5919,26 @@ snapshots: tiny-glob: 0.2.9 vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) - '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) debug: 4.3.6 svelte: 5.0.0-next.175 vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) debug: 4.3.6 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.11 svelte: 5.0.0-next.175 + svelte-hmr: 0.16.0(svelte@5.0.0-next.175) vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) - vitefu: 1.0.2(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + vitefu: 0.2.5(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) transitivePeerDependencies: - supports-color @@ -6174,12 +6106,6 @@ snapshots: - encoding - supports-color - '@vercel/og@0.5.20': - dependencies: - '@resvg/resvg-wasm': 2.6.0 - satori: 0.10.9 - yoga-wasm-web: 0.3.3 - '@vinejs/compiler@2.5.0': optional: true @@ -6330,8 +6256,6 @@ snapshots: balanced-match@1.0.2: {} - base64-js@0.0.8: {} - binary-extensions@2.3.0: {} bindings@1.5.0: @@ -6429,8 +6353,6 @@ snapshots: camelcase@8.0.0: optional: true - camelize@1.0.1: {} - caniuse-lite@1.0.30001655: {} chai@4.5.0: @@ -6556,17 +6478,11 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - css-background-parser@0.1.0: {} - css-blank-pseudo@6.0.2(postcss@8.4.47): dependencies: postcss: 8.4.47 postcss-selector-parser: 6.1.2 - css-box-shadow@1.0.0-3: {} - - css-color-keywords@1.0.0: {} - css-has-pseudo@6.0.5(postcss@8.4.47): dependencies: '@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.1.2) @@ -6578,12 +6494,6 @@ snapshots: dependencies: postcss: 8.4.47 - css-to-react-native@3.2.0: - dependencies: - camelize: 1.0.1 - css-color-keywords: 1.0.0 - postcss-value-parser: 4.2.0 - css-tree@2.3.1: dependencies: mdn-data: 2.0.30 @@ -6687,8 +6597,6 @@ snapshots: electron-to-chromium@1.5.13: {} - emoji-regex@10.4.0: {} - emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -7019,8 +6927,6 @@ snapshots: classnames: 2.5.1 core-js: 3.38.1 - fflate@0.7.4: {} - file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 @@ -7070,11 +6976,11 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)): + formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)): dependencies: nanoid: 5.0.7 svelte: 5.0.0-next.175 - sveltekit-superforms: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) + sveltekit-superforms: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) forwarded@0.2.0: {} @@ -7205,8 +7111,6 @@ snapshots: dependencies: function-bind: 1.1.2 - hex-rgb@4.3.0: {} - hono-rate-limiter@0.4.0(hono@4.6.2): dependencies: hono: 4.6.2 @@ -7396,11 +7300,6 @@ snapshots: lilconfig@3.1.2: {} - linebreak@1.1.0: - dependencies: - base64-js: 0.0.8 - unicode-trie: 2.0.0 - lines-and-columns@1.2.4: {} loader@2.1.1: {} @@ -7685,17 +7584,10 @@ snapshots: package-json-from-dist@1.0.0: {} - pako@0.2.9: {} - parent-module@1.0.1: dependencies: callsites: 3.1.0 - parse-css-color@0.2.1: - dependencies: - color-name: 1.1.4 - hex-rgb: 4.3.0 - parseurl@1.3.3: {} path-exists@4.0.0: {} @@ -8266,19 +8158,6 @@ snapshots: source-map-js: 1.2.1 optional: true - satori@0.10.9: - dependencies: - '@shuding/opentype.js': 1.4.0-beta.0 - css-background-parser: 0.1.0 - css-box-shadow: 1.0.0-3 - css-to-react-native: 3.2.0 - emoji-regex: 10.4.0 - escape-html: 1.0.3 - linebreak: 1.1.0 - parse-css-color: 0.2.1 - postcss-value-parser: 4.2.0 - yoga-wasm-web: 0.3.3 - schema-dts@1.1.2(typescript@5.6.2): dependencies: typescript: 5.6.2 @@ -8424,8 +8303,6 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.0 - string.prototype.codepointat@0.2.1: {} - string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 @@ -8513,6 +8390,10 @@ snapshots: svelte-render: 2.0.1(svelte@5.0.0-next.175) svelte-subscribe: 2.0.1(svelte@5.0.0-next.175) + svelte-hmr@0.16.0(svelte@5.0.0-next.175): + dependencies: + svelte: 5.0.0-next.175 + svelte-keyed@2.0.0(svelte@5.0.0-next.175): dependencies: svelte: 5.0.0-next.175 @@ -8604,19 +8485,19 @@ snapshots: magic-string: 0.30.11 zimmerframe: 1.1.2 - sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175): + sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) svelte: 5.0.0-next.175 - sveltekit-rate-limiter@0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))): + sveltekit-rate-limiter@0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))): dependencies: '@isaacs/ttlcache': 1.4.1 - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) - sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): + sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) devalue: 5.0.0 just-clone: 6.2.0 memoize-weak: 1.0.2 @@ -8708,8 +8589,6 @@ snapshots: globalyzer: 0.1.0 globrex: 0.1.2 - tiny-inflate@1.0.3: {} - tinybench@2.9.0: {} tinypool@0.8.4: {} @@ -8805,11 +8684,6 @@ snapshots: unfetch@4.2.0: {} - unicode-trie@2.0.0: - dependencies: - pako: 0.2.9 - tiny-inflate: 1.0.3 - unpipe@1.0.0: {} update-browserslist-db@1.1.0(browserslist@4.23.3): @@ -8877,7 +8751,7 @@ snapshots: fsevents: 2.3.3 sass: 1.79.1 - vitefu@1.0.2(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)): + vitefu@0.2.5(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)): optionalDependencies: vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) @@ -8996,8 +8870,6 @@ snapshots: yocto-queue@1.1.1: {} - yoga-wasm-web@0.3.3: {} - yup@1.4.0: dependencies: property-expr: 2.0.6 From 21c0a33c52e1b6dfea13fcb60ac4d635df26f7db Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Mon, 23 Sep 2024 09:50:01 -0700 Subject: [PATCH 22/29] Adding newer oslo dependencies and argon2 in regular dependencies. --- .vscode/settings.json | 8 +- package.json | 9 +- pnpm-lock.yaml | 310 ++++++++++++++++-- src/lib/server/api/services/totp.service.ts | 8 +- .../security/change/password/+page.server.ts | 5 - .../security/mfa/totp/+page.server.ts | 13 +- src/routes/(app)/privacy/+page.server.ts | 2 +- src/routes/(app)/terms/+page.server.ts | 2 +- src/routes/(auth)/totp/+page.server.ts | 1 - 9 files changed, 319 insertions(+), 39 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 82fd2e1..dfc4497 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,9 @@ { - "cSpell.words": ["iconify", "kickstarter", "lucide", "msrp", "pcss"] + "cSpell.words": [ + "iconify", + "kickstarter", + "lucide", + "msrp", + "pcss" + ] } diff --git a/package.json b/package.json index 12495c8..43ea474 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "@types/cookie": "^0.6.0", "@types/node": "^20.16.5", "@types/pg": "^8.11.10", + "@types/qrcode": "^1.5.5", "@typescript-eslint/eslint-plugin": "^7.18.0", "@typescript-eslint/parser": "^7.18.0", "arctic": "^1.9.2", @@ -61,7 +62,6 @@ "svelte-preprocess": "^6.0.2", "svelte-sequential-preprocessor": "^2.0.1", "sveltekit-flash-message": "^2.4.4", - "sveltekit-rate-limiter": "^0.5.2", "sveltekit-superforms": "^2.18.1", "tailwindcss": "^3.4.12", "ts-node": "^10.9.2", @@ -84,6 +84,13 @@ "@lucia-auth/adapter-drizzle": "^1.1.0", "@lukeed/uuid": "^2.0.1", "@neondatabase/serverless": "^0.9.5", + "@node-rs/argon2": "^1.8.3", + "@oslojs/crypto": "^1.0.1", + "@oslojs/encoding": "^1.0.0", + "@oslojs/jwt": "^0.2.0", + "@oslojs/oauth2": "^0.5.0", + "@oslojs/otp": "^1.0.0", + "@oslojs/webauthn": "^1.0.0", "@paralleldrive/cuid2": "^2.2.2", "@sveltejs/adapter-node": "^5.2.3", "@sveltejs/adapter-vercel": "^5.4.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 86433c9..3828c27 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,6 +38,27 @@ importers: '@neondatabase/serverless': specifier: ^0.9.5 version: 0.9.5 + '@node-rs/argon2': + specifier: ^1.8.3 + version: 1.8.3 + '@oslojs/crypto': + specifier: ^1.0.1 + version: 1.0.1 + '@oslojs/encoding': + specifier: ^1.0.0 + version: 1.0.0 + '@oslojs/jwt': + specifier: ^0.2.0 + version: 0.2.0 + '@oslojs/oauth2': + specifier: ^0.5.0 + version: 0.5.0 + '@oslojs/otp': + specifier: ^1.0.0 + version: 1.0.0 + '@oslojs/webauthn': + specifier: ^1.0.0 + version: 1.0.0 '@paralleldrive/cuid2': specifier: ^2.2.2 version: 2.2.2 @@ -195,6 +216,9 @@ importers: '@types/pg': specifier: ^8.11.10 version: 8.11.10 + '@types/qrcode': + specifier: ^1.5.5 + version: 1.5.5 '@typescript-eslint/eslint-plugin': specifier: ^7.18.0 version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2) @@ -273,9 +297,6 @@ importers: sveltekit-flash-message: specifier: ^2.4.4 version: 2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175) - sveltekit-rate-limiter: - specifier: ^0.5.2 - version: 0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) sveltekit-superforms: specifier: ^2.18.1 version: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) @@ -632,12 +653,18 @@ packages: '@emnapi/core@0.45.0': resolution: {integrity: sha512-DPWjcUDQkCeEM4VnljEOEcXdAD7pp8zSZsgOujk/LGIwCXWbXJngin+MO4zbH429lzeC3WbYLGjE2MaUOwzpyw==} + '@emnapi/core@1.2.0': + resolution: {integrity: sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w==} + '@emnapi/runtime@0.45.0': resolution: {integrity: sha512-Txumi3td7J4A/xTTwlssKieHKTGl3j4A1tglBx72auZ49YK7ePY6XZricgIg9mnZT4xPfA+UPCUdnhRuEFDL+w==} '@emnapi/runtime@1.2.0': resolution: {integrity: sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==} + '@emnapi/wasi-threads@1.0.1': + resolution: {integrity: sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==} + '@esbuild-kit/core-utils@3.3.2': resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} @@ -1398,10 +1425,6 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} - '@isaacs/ttlcache@1.4.1': - resolution: {integrity: sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==} - engines: {node: '>=12'} - '@jest/schemas@29.6.3': resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1491,6 +1514,9 @@ packages: cpu: [x64] os: [win32] + '@napi-rs/wasm-runtime@0.2.4': + resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==} + '@neondatabase/serverless@0.9.5': resolution: {integrity: sha512-siFas6gItqv6wD/pZnvdu34wEqgG3nSE6zWZdq5j2DEsa+VvX8i/5HXJOo06qrw5axPXn+lGCxeR+NLaSPIXug==} @@ -1504,87 +1530,174 @@ packages: cpu: [arm] os: [android] + '@node-rs/argon2-android-arm-eabi@1.8.3': + resolution: {integrity: sha512-JFZPlNM0A8Og+Tncb8UZsQrhEMlbHBXPsT3hRoKImzVmTmq28Os0ucFWow0AACp2coLHBSydXH3Dh0lZup3rWw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [android] + '@node-rs/argon2-android-arm64@1.7.0': resolution: {integrity: sha512-s9j/G30xKUx8WU50WIhF0fIl1EdhBGq0RQ06lEhZ0Gi0ap8lhqbE2Bn5h3/G2D1k0Dx+yjeVVNmt/xOQIRG38A==} engines: {node: '>= 10'} cpu: [arm64] os: [android] + '@node-rs/argon2-android-arm64@1.8.3': + resolution: {integrity: sha512-zaf8P3T92caeW2xnMA7P1QvRA4pIt/04oilYP44XlTCtMye//vwXDMeK53sl7dvYiJKnzAWDRx41k8vZvpZazg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + '@node-rs/argon2-darwin-arm64@1.7.0': resolution: {integrity: sha512-ZIz4L6HGOB9U1kW23g+m7anGNuTZ0RuTw0vNp3o+2DWpb8u8rODq6A8tH4JRL79S+Co/Nq608m9uackN2pe0Rw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] + '@node-rs/argon2-darwin-arm64@1.8.3': + resolution: {integrity: sha512-DV/IbmLGdNXBtXb5o2UI5ba6kvqXqPAJgmMOTUCuHeBSp992GlLHdfU4rzGu0dNrxudBnunNZv+crd0YdEQSUA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + '@node-rs/argon2-darwin-x64@1.7.0': resolution: {integrity: sha512-5oi/pxqVhODW/pj1+3zElMTn/YukQeywPHHYDbcAW3KsojFjKySfhcJMd1DjKTc+CHQI+4lOxZzSUzK7mI14Hw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] + '@node-rs/argon2-darwin-x64@1.8.3': + resolution: {integrity: sha512-YMjmBGFZhLfYjfQ2gll9A+BZu/zAMV7lWZIbKxb7ZgEofILQwuGmExjDtY3Jplido/6leCEdpmlk2oIsME00LA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + '@node-rs/argon2-freebsd-x64@1.7.0': resolution: {integrity: sha512-Ify08683hA4QVXYoIm5SUWOY5DPIT/CMB0CQT+IdxQAg/F+qp342+lUkeAtD5bvStQuCx/dFO3bnnzoe2clMhA==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] + '@node-rs/argon2-freebsd-x64@1.8.3': + resolution: {integrity: sha512-Hq3Rj5Yb2RolTG/luRPnv+XiGCbi5nAK25Pc8ou/tVapwX+iktEm/NXbxc5zsMxraYVkCvfdwBjweC5O+KqCGw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + '@node-rs/argon2-linux-arm-gnueabihf@1.7.0': resolution: {integrity: sha512-7DjDZ1h5AUHAtRNjD19RnQatbhL+uuxBASuuXIBu4/w6Dx8n7YPxwTP4MXfsvuRgKuMWiOb/Ub/HJ3kXVCXRkg==} engines: {node: '>= 10'} cpu: [arm] os: [linux] + '@node-rs/argon2-linux-arm-gnueabihf@1.8.3': + resolution: {integrity: sha512-x49l8RgzKoG0/V0IXa5rrEl1TcJEc936ctlYFvqcunSOyowZ6kiWtrp1qrbOR8gbaNILl11KTF52vF6+h8UlEQ==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + '@node-rs/argon2-linux-arm64-gnu@1.7.0': resolution: {integrity: sha512-nJDoMP4Y3YcqGswE4DvP080w6O24RmnFEDnL0emdI8Nou17kNYBzP2546Nasx9GCyLzRcYQwZOUjrtUuQ+od2g==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + '@node-rs/argon2-linux-arm64-gnu@1.8.3': + resolution: {integrity: sha512-gJesam/qA63reGkb9qJ2TjFSLBtY41zQh2oei7nfnYsmVQPuHHWItJxEa1Bm21SPW53gZex4jFJbDIgj0+PxIw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + '@node-rs/argon2-linux-arm64-musl@1.7.0': resolution: {integrity: sha512-BKWS8iVconhE3jrb9mj6t1J9vwUqQPpzCbUKxfTGJfc+kNL58F1SXHBoe2cDYGnHrFEHTY0YochzXoAfm4Dm/A==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + '@node-rs/argon2-linux-arm64-musl@1.8.3': + resolution: {integrity: sha512-7O6kQdSKzB4Tjx/EBa8zKIxnmLkQE8VdJgPm6Ksrpn+ueo0mx2xf76fIDnbbTCtm3UbB+y+FkTo2wLA7tOqIKg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + '@node-rs/argon2-linux-x64-gnu@1.7.0': resolution: {integrity: sha512-EmgqZOlf4Jurk/szW1iTsVISx25bKksVC5uttJDUloTgsAgIGReCpUUO1R24pBhu9ESJa47iv8NSf3yAfGv6jQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + '@node-rs/argon2-linux-x64-gnu@1.8.3': + resolution: {integrity: sha512-OBH+EFG7BGjFyldaao2H2gSCLmjtrrwf420B1L+lFn7JLW9UAjsIPFKAcWsYwPa/PwYzIge9Y7SGcpqlsSEX0w==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + '@node-rs/argon2-linux-x64-musl@1.7.0': resolution: {integrity: sha512-/o1efYCYIxjfuoRYyBTi2Iy+1iFfhqHCvvVsnjNSgO1xWiWrX0Rrt/xXW5Zsl7vS2Y+yu8PL8KFWRzZhaVxfKA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + '@node-rs/argon2-linux-x64-musl@1.8.3': + resolution: {integrity: sha512-bDbMuyekIxZaN7NaX+gHVkOyABB8bcMEJYeRPW1vCXKHj3brJns1wiUFSxqeUXreupifNVJlQfPt1Y5B/vFXgQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + '@node-rs/argon2-wasm32-wasi@1.7.0': resolution: {integrity: sha512-Evmk9VcxqnuwQftfAfYEr6YZYSPLzmKUsbFIMep5nTt9PT4XYRFAERj7wNYp+rOcBenF3X4xoB+LhwcOMTNE5w==} engines: {node: '>=14.0.0'} cpu: [wasm32] + '@node-rs/argon2-wasm32-wasi@1.8.3': + resolution: {integrity: sha512-NBf2cMCDbNKMzp13Pog8ZPmI0M9U4Ak5b95EUjkp17kdKZFds12dwW67EMnj7Zy+pRqby2QLECaWebDYfNENTg==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + '@node-rs/argon2-win32-arm64-msvc@1.7.0': resolution: {integrity: sha512-qgsU7T004COWWpSA0tppDqDxbPLgg8FaU09krIJ7FBl71Sz8SFO40h7fDIjfbTT5w7u6mcaINMQ5bSHu75PCaA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] + '@node-rs/argon2-win32-arm64-msvc@1.8.3': + resolution: {integrity: sha512-AHpPo7UbdW5WWjwreVpgFSY0o1RY4A7cUFaqDXZB2OqEuyrhMxBdZct9PX7PQKI18D85pLsODnR+gvVuTwJ6rQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + '@node-rs/argon2-win32-ia32-msvc@1.7.0': resolution: {integrity: sha512-JGafwWYQ/HpZ3XSwP4adQ6W41pRvhcdXvpzIWtKvX+17+xEXAe2nmGWM6s27pVkg1iV2ZtoYLRDkOUoGqZkCcg==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] + '@node-rs/argon2-win32-ia32-msvc@1.8.3': + resolution: {integrity: sha512-bqzn2rcQkEwCINefhm69ttBVVkgHJb/V03DdBKsPFtiX6H47axXKz62d1imi26zFXhOEYxhKbu3js03GobJOLw==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + '@node-rs/argon2-win32-x64-msvc@1.7.0': resolution: {integrity: sha512-9oq4ShyFakw8AG3mRls0AoCpxBFcimYx7+jvXeAf2OqKNO+mSA6eZ9z7KQeVCi0+SOEUYxMGf5UiGiDb9R6+9Q==} engines: {node: '>= 10'} cpu: [x64] os: [win32] + '@node-rs/argon2-win32-x64-msvc@1.8.3': + resolution: {integrity: sha512-ILlrRThdbp5xNR5gwYM2ic1n/vG5rJ8dQZ+YMRqksl+lnTJ/6FDe5BOyIhiPtiDwlCiCtUA+1NxpDB9KlUCAIA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + '@node-rs/argon2@1.7.0': resolution: {integrity: sha512-zfULc+/tmcWcxn+nHkbyY8vP3+MpEqKORbszt4UkpqZgBgDAAIYvuDN/zukfTgdmo6tmJKKVfzigZOPk4LlIog==} engines: {node: '>= 10'} + '@node-rs/argon2@1.8.3': + resolution: {integrity: sha512-sf/QAEI59hsMEEE2J8vO4hKrXrv4Oplte3KI2N4MhMDYpytH0drkVfErmHBfWFZxxIEK03fX1WsBNswS2nIZKg==} + engines: {node: '>= 10'} + '@node-rs/bcrypt-android-arm-eabi@1.9.0': resolution: {integrity: sha512-nOCFISGtnodGHNiLrG0WYLWr81qQzZKYfmwHc7muUeq+KY0sQXyHOwZk9OuNQAWv/lnntmtbwkwT0QNEmOyLvA==} engines: {node: '>= 10'} @@ -1684,6 +1797,39 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@oslojs/asn1@1.0.0': + resolution: {integrity: sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA==} + + '@oslojs/binary@1.0.0': + resolution: {integrity: sha512-9RCU6OwXU6p67H4NODbuxv2S3eenuQ4/WFLrsq+K/k682xrznH5EVWA7N4VFk9VYVcbFtKqur5YQQZc0ySGhsQ==} + + '@oslojs/cbor@1.0.0': + resolution: {integrity: sha512-AY6Lknexs7n2xp8Cgey95c+975VG7XOk4UEdRdNFxHmDDbuf47OC/LAVRsl14DeTLwo8W6xr3HLFwUFmKcndTQ==} + + '@oslojs/crypto@1.0.0': + resolution: {integrity: sha512-dVz8TkkgYdr3tlwxHd7SCYGxoN7ynwHLA0nei/Aq9C+ERU0BK+U8+/3soEzBUxUNKYBf42351DyJUZ2REla50w==} + + '@oslojs/crypto@1.0.1': + resolution: {integrity: sha512-7n08G8nWjAr/Yu3vu9zzrd0L9XnrJfpMioQcvCMxBIiF5orECHe5/3J0jmXRVvgfqMm/+4oxlQ+Sq39COYLcNQ==} + + '@oslojs/encoding@0.4.1': + resolution: {integrity: sha512-hkjo6MuIK/kQR5CrGNdAPZhS01ZCXuWDRJ187zh6qqF2+yMHZpD9fAYpX8q2bOO6Ryhl3XpCT6kUX76N8hhm4Q==} + + '@oslojs/encoding@1.0.0': + resolution: {integrity: sha512-dyIB0SdZgMm5BhGwdSp8rMxEFIopLKxDG1vxIBaiogyom6ZqH2aXPb6DEC2WzOOWKdPSq1cxdNeRx2wAn1Z+ZQ==} + + '@oslojs/jwt@0.2.0': + resolution: {integrity: sha512-bLE7BtHrURedCn4Mco3ma9L4Y1GR2SMBuIvjWr7rmQ4/W/4Jy70TIAgZ+0nIlk0xHz1vNP8x8DCns45Sb2XRbg==} + + '@oslojs/oauth2@0.5.0': + resolution: {integrity: sha512-t70+e4EgnzTbU4MrUWXzqWN2A6RJrlSSvwwuBv6E0Ap6/nsIXrjsdRWeTcSvvXTcC6fi0YdWaqEWLipcEm2Cgw==} + + '@oslojs/otp@1.0.0': + resolution: {integrity: sha512-w/vZfoVsFCCcmsmsXVsIMoWbvr1IZmQ9BsDZwdePSpe8rFKMD1Knd+05iJr415adXkFVyu0tYxgrLPYMynNtXQ==} + + '@oslojs/webauthn@1.0.0': + resolution: {integrity: sha512-2ZRpbt3msNURwvjmavzq9vrNlxUnWFBGMYqbC1kO3fYBLskL7r4DiLJT1wbtLoI+hclFwjhl48YhRFBl6RWg1A==} + '@paralleldrive/cuid2@2.2.2': resolution: {integrity: sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==} @@ -1904,6 +2050,9 @@ packages: '@tybys/wasm-util@0.8.3': resolution: {integrity: sha512-Z96T/L6dUFFxgFJ+pQtkPpne9q7i6kIPYCFnQBHSgSPV9idTsKfIhCss0h5iM9irweZCatkrdeP8yi5uM1eX6Q==} + '@tybys/wasm-util@0.9.0': + resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} + '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} @@ -1928,6 +2077,9 @@ packages: '@types/pug@2.0.10': resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==} + '@types/qrcode@1.5.5': + resolution: {integrity: sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==} + '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -4324,11 +4476,6 @@ packages: '@sveltejs/kit': 1.x || 2.x svelte: 3.x || 4.x || >=5.0.0-next.51 - sveltekit-rate-limiter@0.5.2: - resolution: {integrity: sha512-7CELKmTffNjj0i/RUxT9SKYFA9IO/tQabjgT39clOlkKvlcGozNy8nqoIx+24amWfqEqC/WXYMEIek04PiFdyA==} - peerDependencies: - '@sveltejs/kit': 1.x || 2.x - sveltekit-superforms@2.19.0: resolution: {integrity: sha512-WJmdYf8WpuDkl6zxdRP72R+wDefx1OhIQYKdsIQqNkFntNq0/BUrkMdUr1i7d/FbX0gS1A9GRflCx3WiYQlAXg==} peerDependencies: @@ -5018,6 +5165,12 @@ snapshots: tslib: 2.7.0 optional: true + '@emnapi/core@1.2.0': + dependencies: + '@emnapi/wasi-threads': 1.0.1 + tslib: 2.7.0 + optional: true + '@emnapi/runtime@0.45.0': dependencies: tslib: 2.7.0 @@ -5028,6 +5181,11 @@ snapshots: tslib: 2.7.0 optional: true + '@emnapi/wasi-threads@1.0.1': + dependencies: + tslib: 2.7.0 + optional: true + '@esbuild-kit/core-utils@3.3.2': dependencies: esbuild: 0.18.20 @@ -5500,8 +5658,6 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 - '@isaacs/ttlcache@1.4.1': {} - '@jest/schemas@29.6.3': dependencies: '@sinclair/typebox': 0.27.8 @@ -5599,6 +5755,13 @@ snapshots: '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': optional: true + '@napi-rs/wasm-runtime@0.2.4': + dependencies: + '@emnapi/core': 1.2.0 + '@emnapi/runtime': 1.2.0 + '@tybys/wasm-util': 0.9.0 + optional: true + '@neondatabase/serverless@0.9.5': dependencies: '@types/pg': 8.11.6 @@ -5608,33 +5771,63 @@ snapshots: '@node-rs/argon2-android-arm-eabi@1.7.0': optional: true + '@node-rs/argon2-android-arm-eabi@1.8.3': + optional: true + '@node-rs/argon2-android-arm64@1.7.0': optional: true + '@node-rs/argon2-android-arm64@1.8.3': + optional: true + '@node-rs/argon2-darwin-arm64@1.7.0': optional: true + '@node-rs/argon2-darwin-arm64@1.8.3': + optional: true + '@node-rs/argon2-darwin-x64@1.7.0': optional: true + '@node-rs/argon2-darwin-x64@1.8.3': + optional: true + '@node-rs/argon2-freebsd-x64@1.7.0': optional: true + '@node-rs/argon2-freebsd-x64@1.8.3': + optional: true + '@node-rs/argon2-linux-arm-gnueabihf@1.7.0': optional: true + '@node-rs/argon2-linux-arm-gnueabihf@1.8.3': + optional: true + '@node-rs/argon2-linux-arm64-gnu@1.7.0': optional: true + '@node-rs/argon2-linux-arm64-gnu@1.8.3': + optional: true + '@node-rs/argon2-linux-arm64-musl@1.7.0': optional: true + '@node-rs/argon2-linux-arm64-musl@1.8.3': + optional: true + '@node-rs/argon2-linux-x64-gnu@1.7.0': optional: true + '@node-rs/argon2-linux-x64-gnu@1.8.3': + optional: true + '@node-rs/argon2-linux-x64-musl@1.7.0': optional: true + '@node-rs/argon2-linux-x64-musl@1.8.3': + optional: true + '@node-rs/argon2-wasm32-wasi@1.7.0': dependencies: '@emnapi/core': 0.45.0 @@ -5643,15 +5836,29 @@ snapshots: memfs-browser: 3.5.10302 optional: true + '@node-rs/argon2-wasm32-wasi@1.8.3': + dependencies: + '@napi-rs/wasm-runtime': 0.2.4 + optional: true + '@node-rs/argon2-win32-arm64-msvc@1.7.0': optional: true + '@node-rs/argon2-win32-arm64-msvc@1.8.3': + optional: true + '@node-rs/argon2-win32-ia32-msvc@1.7.0': optional: true + '@node-rs/argon2-win32-ia32-msvc@1.8.3': + optional: true + '@node-rs/argon2-win32-x64-msvc@1.7.0': optional: true + '@node-rs/argon2-win32-x64-msvc@1.8.3': + optional: true + '@node-rs/argon2@1.7.0': optionalDependencies: '@node-rs/argon2-android-arm-eabi': 1.7.0 @@ -5669,6 +5876,23 @@ snapshots: '@node-rs/argon2-win32-ia32-msvc': 1.7.0 '@node-rs/argon2-win32-x64-msvc': 1.7.0 + '@node-rs/argon2@1.8.3': + optionalDependencies: + '@node-rs/argon2-android-arm-eabi': 1.8.3 + '@node-rs/argon2-android-arm64': 1.8.3 + '@node-rs/argon2-darwin-arm64': 1.8.3 + '@node-rs/argon2-darwin-x64': 1.8.3 + '@node-rs/argon2-freebsd-x64': 1.8.3 + '@node-rs/argon2-linux-arm-gnueabihf': 1.8.3 + '@node-rs/argon2-linux-arm64-gnu': 1.8.3 + '@node-rs/argon2-linux-arm64-musl': 1.8.3 + '@node-rs/argon2-linux-x64-gnu': 1.8.3 + '@node-rs/argon2-linux-x64-musl': 1.8.3 + '@node-rs/argon2-wasm32-wasi': 1.8.3 + '@node-rs/argon2-win32-arm64-msvc': 1.8.3 + '@node-rs/argon2-win32-ia32-msvc': 1.8.3 + '@node-rs/argon2-win32-x64-msvc': 1.8.3 + '@node-rs/bcrypt-android-arm-eabi@1.9.0': optional: true @@ -5745,6 +5969,50 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 + '@oslojs/asn1@1.0.0': + dependencies: + '@oslojs/binary': 1.0.0 + + '@oslojs/binary@1.0.0': {} + + '@oslojs/cbor@1.0.0': + dependencies: + '@oslojs/binary': 1.0.0 + + '@oslojs/crypto@1.0.0': + dependencies: + '@oslojs/asn1': 1.0.0 + '@oslojs/binary': 1.0.0 + + '@oslojs/crypto@1.0.1': + dependencies: + '@oslojs/asn1': 1.0.0 + '@oslojs/binary': 1.0.0 + + '@oslojs/encoding@0.4.1': {} + + '@oslojs/encoding@1.0.0': {} + + '@oslojs/jwt@0.2.0': + dependencies: + '@oslojs/encoding': 0.4.1 + + '@oslojs/oauth2@0.5.0': {} + + '@oslojs/otp@1.0.0': + dependencies: + '@oslojs/binary': 1.0.0 + '@oslojs/crypto': 1.0.0 + '@oslojs/encoding': 1.0.0 + + '@oslojs/webauthn@1.0.0': + dependencies: + '@oslojs/asn1': 1.0.0 + '@oslojs/binary': 1.0.0 + '@oslojs/cbor': 1.0.0 + '@oslojs/crypto': 1.0.0 + '@oslojs/encoding': 1.0.0 + '@paralleldrive/cuid2@2.2.2': dependencies: '@noble/hashes': 1.5.0 @@ -5959,6 +6227,11 @@ snapshots: tslib: 2.7.0 optional: true + '@tybys/wasm-util@0.9.0': + dependencies: + tslib: 2.7.0 + optional: true + '@types/cookie@0.6.0': {} '@types/estree@1.0.5': {} @@ -5986,6 +6259,10 @@ snapshots: '@types/pug@2.0.10': {} + '@types/qrcode@1.5.5': + dependencies: + '@types/node': 20.16.5 + '@types/resolve@1.20.2': {} '@types/validator@13.12.1': @@ -8490,11 +8767,6 @@ snapshots: '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) svelte: 5.0.0-next.175 - sveltekit-rate-limiter@0.5.2(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))): - dependencies: - '@isaacs/ttlcache': 1.4.1 - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) - sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): dependencies: '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) diff --git a/src/lib/server/api/services/totp.service.ts b/src/lib/server/api/services/totp.service.ts index b8c5fbf..ac0253c 100644 --- a/src/lib/server/api/services/totp.service.ts +++ b/src/lib/server/api/services/totp.service.ts @@ -1,7 +1,7 @@ import { CredentialsRepository } from '$lib/server/api/repositories/credentials.repository' import { HMAC } from 'oslo/crypto' -import { decodeHex, encodeHex } from 'oslo/encoding' -import { TOTPController } from 'oslo/otp' +import { decodeHex, encodeHexLowerCase } from '@oslojs/encoding' +import { verifyTOTP } from '@oslojs/otp' import { inject, injectable } from 'tsyringe' import type { CredentialsType } from '../databases/tables' @@ -27,7 +27,7 @@ export class TotpService { try { return await this.credentialsRepository.create({ user_id: userId, - secret_data: encodeHex(twoFactorSecret), + secret_data: encodeHexLowerCase(twoFactorSecret), type: 'totp', }) } catch (e) { @@ -49,6 +49,6 @@ export class TotpService { if (!credential) { throw new Error('TOTP credential not found') } - return await new TOTPController().verify(code, decodeHex(credential.secret_data)) + return await verifyTOTP(decodeHex(credential.secret_data), 30, 6, code) } } diff --git a/src/routes/(app)/(protected)/settings/security/change/password/+page.server.ts b/src/routes/(app)/(protected)/settings/security/change/password/+page.server.ts index 300b45d..30bd840 100644 --- a/src/routes/(app)/(protected)/settings/security/change/password/+page.server.ts +++ b/src/routes/(app)/(protected)/settings/security/change/password/+page.server.ts @@ -1,10 +1,5 @@ import { notSignedInMessage } from '$lib/flashMessages' -import { usersTable } from '$lib/server/api/databases/tables' -import { db } from '$lib/server/api/packages/drizzle' import { type Actions, fail } from '@sveltejs/kit' -import { eq } from 'drizzle-orm' -import type { Cookie } from 'lucia' -import { Argon2id } from 'oslo/password' import { redirect } from 'sveltekit-flash-message/server' import { zod } from 'sveltekit-superforms/adapters' import { setError, superValidate } from 'sveltekit-superforms/server' diff --git a/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.server.ts b/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.server.ts index 1a45df9..91f2ec4 100644 --- a/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.server.ts +++ b/src/routes/(app)/(protected)/settings/security/mfa/totp/+page.server.ts @@ -2,8 +2,8 @@ import { notSignedInMessage } from '$lib/flashMessages' import env from '$lib/server/api/common/env' import { type Actions, fail } from '@sveltejs/kit' import kebabCase from 'just-kebab-case' -import { base32, decodeHex } from 'oslo/encoding' -import { createTOTPKeyURI } from 'oslo/otp' +import { encodeBase32, decodeHex } from '@oslojs/encoding' +import { createTOTPKeyURI } from '@oslojs/otp' import QRCode from 'qrcode' import { redirect } from 'sveltekit-flash-message/server' import { zod } from 'sveltekit-superforms/adapters' @@ -63,10 +63,11 @@ export const load: PageServerLoad = async (event) => { }) } const decodedHexSecret = decodeHex(createdTotpCredentials.secret_data) - const secret = base32.encode(new Uint8Array(decodedHexSecret), { - includePadding: false, - }) - const totpUri = createTOTPKeyURI(issuer, accountName, decodedHexSecret) + const secret = encodeBase32(new TextEncoder().encode(decodedHexSecret)) + const intervalInSeconds = 30 + const digits = 6 + + const totpUri = createTOTPKeyURI(issuer, accountName, decodedHexSecret, intervalInSeconds, digits) addTwoFactorForm.data = { current_password: '', diff --git a/src/routes/(app)/privacy/+page.server.ts b/src/routes/(app)/privacy/+page.server.ts index 10cfeb3..189f71e 100644 --- a/src/routes/(app)/privacy/+page.server.ts +++ b/src/routes/(app)/privacy/+page.server.ts @@ -1 +1 @@ -// export const prerender = true; \ No newline at end of file +export const prerender = true; diff --git a/src/routes/(app)/terms/+page.server.ts b/src/routes/(app)/terms/+page.server.ts index 4973a60..189f71e 100644 --- a/src/routes/(app)/terms/+page.server.ts +++ b/src/routes/(app)/terms/+page.server.ts @@ -1 +1 @@ -// export const prerender = true; +export const prerender = true; diff --git a/src/routes/(auth)/totp/+page.server.ts b/src/routes/(auth)/totp/+page.server.ts index 9b05025..a4f79dd 100644 --- a/src/routes/(auth)/totp/+page.server.ts +++ b/src/routes/(auth)/totp/+page.server.ts @@ -7,7 +7,6 @@ import { type Actions, fail } from '@sveltejs/kit' import { and, eq } from 'drizzle-orm' import { Argon2id } from 'oslo/password' import { redirect } from 'sveltekit-flash-message/server' -import { RateLimiter } from 'sveltekit-rate-limiter/server' import { zod } from 'sveltekit-superforms/adapters' import { superValidate } from 'sveltekit-superforms/server' import type { PageServerLoad, RequestEvent } from './$types' From 54bc9c3faa94d4ba9aa1e8d7caa7f46c4a9b43dd Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Tue, 24 Sep 2024 17:13:11 -0700 Subject: [PATCH 23/29] Using scrypt instead of Argon2 given it is a pure JS implementation and noders-argon2 rust implementation has issues on Vite/Vercel/etc. --- package.json | 2 +- pnpm-lock.yaml | 91 ++++++++----------- src/lib/server/api/databases/seeds/users.ts | 9 +- src/lib/server/api/mockTest.ts | 10 -- .../server/api/services/drizzle.service.ts | 2 +- .../server/api/services/hashing.service.ts | 75 +++++++++------ .../api/services/recovery-codes.service.ts | 9 +- .../server/api/tests/tokens.service.test.ts | 5 +- .../server/api/tests/users.service.test.ts | 34 ++++++- src/routes/(auth)/totp/+page.server.ts | 39 ++++---- 10 files changed, 150 insertions(+), 126 deletions(-) delete mode 100644 src/lib/server/api/mockTest.ts diff --git a/package.json b/package.json index 43ea474..bc46b96 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "@sveltejs/adapter-auto": "^3.2.5", "@sveltejs/enhanced-img": "^0.3.8", "@sveltejs/kit": "^2.5.28", - "@sveltejs/vite-plugin-svelte": "^3.1.2", + "@sveltejs/vite-plugin-svelte": "4.0.0-next.7", "@types/cookie": "^0.6.0", "@types/node": "^20.16.5", "@types/pg": "^8.11.10", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3828c27..ee6151a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -64,10 +64,10 @@ importers: version: 2.2.2 '@sveltejs/adapter-node': specifier: ^5.2.3 - version: 5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) + version: 5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) '@sveltejs/adapter-vercel': specifier: ^5.4.4 - version: 5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) + version: 5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) '@types/feather-icons': specifier: ^4.29.4 version: 4.29.4 @@ -106,7 +106,7 @@ importers: version: 4.29.2 formsnap: specifier: ^1.0.1 - version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)) + version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)) handlebars: specifier: ^4.7.8 version: 4.7.8 @@ -197,16 +197,16 @@ importers: version: 1.47.2 '@sveltejs/adapter-auto': specifier: ^3.2.5 - version: 3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) + version: 3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) '@sveltejs/enhanced-img': specifier: ^0.3.8 version: 0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@sveltejs/kit': specifier: ^2.5.28 - version: 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + version: 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@sveltejs/vite-plugin-svelte': - specifier: ^3.1.2 - version: 3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + specifier: 4.0.0-next.7 + version: 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@types/cookie': specifier: ^0.6.0 version: 0.6.0 @@ -296,10 +296,10 @@ importers: version: 2.0.1 sveltekit-flash-message: specifier: ^2.4.4 - version: 2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175) + version: 2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175) sveltekit-superforms: specifier: ^2.18.1 - version: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) + version: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) tailwindcss: specifier: ^3.4.12 version: 3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) @@ -2017,19 +2017,19 @@ packages: svelte: ^4.0.0 || ^5.0.0-next.0 vite: ^5.0.3 - '@sveltejs/vite-plugin-svelte-inspector@2.1.0': - resolution: {integrity: sha512-9QX28IymvBlSCqsCll5t0kQVxipsfhFFL+L2t3nTWfXnddYwxBuAEtTtlaVQpRz9c37BhJjltSeY4AJSC03SSg==} - engines: {node: ^18.0.0 || >=20} + '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.3': + resolution: {integrity: sha512-kuGJ2CZ5lAw3gKF8Kw0AfKtUJWbwdlDHY14K413B0MCyrzvQvsKTorwmwZcky0+QqY6RnVIZ/5FttB9bQmkLXg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22} peerDependencies: - '@sveltejs/vite-plugin-svelte': ^3.0.0 - svelte: ^4.0.0 || ^5.0.0-next.0 + '@sveltejs/vite-plugin-svelte': ^4.0.0-next.0||^4.0.0 + svelte: ^5.0.0-next.96 || ^5.0.0 vite: ^5.0.0 - '@sveltejs/vite-plugin-svelte@3.1.2': - resolution: {integrity: sha512-Txsm1tJvtiYeLUVRNqxZGKR/mI+CzuIQuc2gn+YCs9rMTowpNZ2Nqt53JdL8KF9bLhAf2ruR/dr9eZCwdTriRA==} - engines: {node: ^18.0.0 || >=20} + '@sveltejs/vite-plugin-svelte@4.0.0-next.7': + resolution: {integrity: sha512-yMUnAqquoayvBDztk1rWUgdtvjv7YcHgopCAB7sWl9SQht8U/7lqwTlJU0ZTAY09pFFRe6bbakd7YoiyyIvJiA==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22} peerDependencies: - svelte: ^4.0.0 || ^5.0.0-next.0 + svelte: ^5.0.0-next.96 || ^5.0.0 vite: ^5.0.0 '@swc/helpers@0.5.13': @@ -4345,12 +4345,6 @@ packages: peerDependencies: svelte: ^4.0.0 - svelte-hmr@0.16.0: - resolution: {integrity: sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==} - engines: {node: ^12.20 || ^14.13.1 || >= 16} - peerDependencies: - svelte: ^3.19.0 || ^4.0.0 - svelte-keyed@2.0.0: resolution: {integrity: sha512-7TeEn+QbJC2OJrHiuM0T8vMBkms3DNpTE+Ir+NtnVBnBMA78aL4f1ft9t0Hn/pBbD/TnIXi4YfjFRAgtN+DZ5g==} peerDependencies: @@ -4724,8 +4718,8 @@ packages: terser: optional: true - vitefu@0.2.5: - resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} + vitefu@1.0.2: + resolution: {integrity: sha512-0/iAvbXyM3RiPPJ4lyD4w6Mjgtf4ejTK6TPvTNG3H32PLwuT0N/ZjJLiXug7ETE/LWtTeHw9WRv7uX/tIKYyKg==} peerDependencies: vite: ^3.0.0 || ^4.0.0 || ^5.0.0 peerDependenciesMeta: @@ -6137,22 +6131,22 @@ snapshots: '@sodaru/yup-to-json-schema@2.0.1': optional: true - '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': + '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) import-meta-resolve: 4.1.0 - '@sveltejs/adapter-node@5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': + '@sveltejs/adapter-node@5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': dependencies: '@rollup/plugin-commonjs': 26.0.1(rollup@4.21.2) '@rollup/plugin-json': 6.1.0(rollup@4.21.2) '@rollup/plugin-node-resolve': 15.2.3(rollup@4.21.2) - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) rollup: 4.21.2 - '@sveltejs/adapter-vercel@5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': + '@sveltejs/adapter-vercel@5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@vercel/nft': 0.27.4 esbuild: 0.21.5 transitivePeerDependencies: @@ -6169,9 +6163,9 @@ snapshots: transitivePeerDependencies: - rollup - '@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.0.0 @@ -6187,26 +6181,25 @@ snapshots: tiny-glob: 0.2.9 vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) - '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) debug: 4.3.6 svelte: 5.0.0-next.175 vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte-inspector': 3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) debug: 4.3.6 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.11 svelte: 5.0.0-next.175 - svelte-hmr: 0.16.0(svelte@5.0.0-next.175) vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) - vitefu: 0.2.5(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + vitefu: 1.0.2(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) transitivePeerDependencies: - supports-color @@ -7253,11 +7246,11 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)): + formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)): dependencies: nanoid: 5.0.7 svelte: 5.0.0-next.175 - sveltekit-superforms: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) + sveltekit-superforms: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) forwarded@0.2.0: {} @@ -8667,10 +8660,6 @@ snapshots: svelte-render: 2.0.1(svelte@5.0.0-next.175) svelte-subscribe: 2.0.1(svelte@5.0.0-next.175) - svelte-hmr@0.16.0(svelte@5.0.0-next.175): - dependencies: - svelte: 5.0.0-next.175 - svelte-keyed@2.0.0(svelte@5.0.0-next.175): dependencies: svelte: 5.0.0-next.175 @@ -8762,14 +8751,14 @@ snapshots: magic-string: 0.30.11 zimmerframe: 1.1.2 - sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175): + sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) svelte: 5.0.0-next.175 - sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): + sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) devalue: 5.0.0 just-clone: 6.2.0 memoize-weak: 1.0.2 @@ -9023,7 +9012,7 @@ snapshots: fsevents: 2.3.3 sass: 1.79.1 - vitefu@0.2.5(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)): + vitefu@1.0.2(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)): optionalDependencies: vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) diff --git a/src/lib/server/api/databases/seeds/users.ts b/src/lib/server/api/databases/seeds/users.ts index a4d22c8..49f2942 100644 --- a/src/lib/server/api/databases/seeds/users.ts +++ b/src/lib/server/api/databases/seeds/users.ts @@ -1,9 +1,8 @@ import * as schema from '$lib/server/api/databases/tables' import type { db } from '$lib/server/api/packages/drizzle' import { eq } from 'drizzle-orm' -import { Argon2id } from 'oslo/password' -import { config } from '../../common/config' import users from './data/users.json' +import { HashingService } from '../../services/hashing.service' type JsonRole = { name: string @@ -11,6 +10,7 @@ type JsonRole = { } export default async function seed(db: db) { + const hashingService = new HashingService() const adminRole = await db.select().from(schema.rolesTable).where(eq(schema.rolesTable.name, 'admin')) const userRole = await db.select().from(schema.rolesTable).where(eq(schema.rolesTable.name, 'user')) @@ -32,7 +32,7 @@ export default async function seed(db: db) { await db.insert(schema.credentialsTable).values({ user_id: adminUser[0].id, type: schema.CredentialsType.PASSWORD, - secret_data: await new Argon2id().hash(`${process.env.ADMIN_PASSWORD}`), + secret_data: await hashingService.hash(`${process.env.ADMIN_PASSWORD}`), }) await db.insert(schema.collections).values({ user_id: adminUser[0].id }).onConflictDoNothing() @@ -60,6 +60,7 @@ export default async function seed(db: db) { .onConflictDoNothing() console.log('Admin user given user role.') + const hasingService = new HashingService() await Promise.all( users.map(async (user) => { const [insertedUser] = await db @@ -71,7 +72,7 @@ export default async function seed(db: db) { await db.insert(schema.credentialsTable).values({ user_id: insertedUser?.id, type: schema.CredentialsType.PASSWORD, - secret_data: await new Argon2id().hash(user.password), + secret_data: await hasingService.hash(user.password), }) await db.insert(schema.collections).values({ user_id: insertedUser?.id }) await db.insert(schema.wishlistsTable).values({ user_id: insertedUser?.id }) diff --git a/src/lib/server/api/mockTest.ts b/src/lib/server/api/mockTest.ts deleted file mode 100644 index a475662..0000000 --- a/src/lib/server/api/mockTest.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Argon2id } from "oslo/password"; - -export async function hash(value: string) { - const argon2 = new Argon2id() - return argon2.hash(value); -} - -export function verify(hashedValue: string, value: string) { - return new Argon2id().verify(hashedValue, value); -} diff --git a/src/lib/server/api/services/drizzle.service.ts b/src/lib/server/api/services/drizzle.service.ts index 8e7a098..bbcb008 100644 --- a/src/lib/server/api/services/drizzle.service.ts +++ b/src/lib/server/api/services/drizzle.service.ts @@ -7,7 +7,7 @@ import { type Disposable, injectable } from 'tsyringe' @injectable() export class DrizzleService implements Disposable { protected readonly pool: pg.Pool - readonly db: NodePgDatabase + db: NodePgDatabase readonly schema: typeof schema = schema constructor() { diff --git a/src/lib/server/api/services/hashing.service.ts b/src/lib/server/api/services/hashing.service.ts index 5a03f4e..5cd526d 100644 --- a/src/lib/server/api/services/hashing.service.ts +++ b/src/lib/server/api/services/hashing.service.ts @@ -1,34 +1,51 @@ -import { injectable } from "tsyringe"; -import { Argon2id } from "oslo/password"; +import { scrypt } from 'node:crypto' +import { decodeHex, encodeHexLowerCase } from '@oslojs/encoding' +import { constantTimeEqual } from '@oslojs/crypto/subtle' +import { injectable } from 'tsyringe' -/* ---------------------------------- Note ---------------------------------- */ -/* -Reference: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#argon2id - -I use Scrpt as the hashing algorithm due to its higher compatability -with vite's build system and it uses less memory than Argon2id. - -You can use Argon2id or any other hashing algorithm you prefer. -*/ -/* -------------------------------------------------------------------------- */ -/* -With Argon2id, you get the following error at times when vite optimizes its dependencies at times, - -Error: Build failed with 2 errors: -node_modules/.pnpm/@node-rs+argon2@1.7.0/node_modules/@node-rs/argon2/index.js:159:36: ERROR: No loader is configured for ".node" files: node_module -*/ -/* -------------------------------------------------------------------------- */ -// If you don't use a hasher from oslo, which are preconfigured with recommended parameters from OWASP, -// ensure that you configure them properly. @injectable() export class HashingService { - private readonly hasher = new Argon2id(); + private N: number + private r: number + private p: number + private dkLen: number - async hash(data: string) { - return this.hasher.hash(data); - } + constructor() { + this.N = 16384 + this.r = 16 + this.p = 1 + this.dkLen = 64 + } + async hash(password: string) { + const salt = encodeHexLowerCase(crypto.getRandomValues(new Uint8Array(16))) + const key = await this.generateKey(password, salt) + return `${salt}:${encodeHexLowerCase(key)}` + } - async verify(hash: string, data: string) { - return this.hasher.verify(hash, data) - } -} \ No newline at end of file + async verify(hash: string, password: string) { + const [salt, key] = hash.split(':') + const targetKey = await this.generateKey(password, salt) + return constantTimeEqual(targetKey, decodeHex(key)) + } + + async generateKey(password: string, salt: string): Promise { + return await new Promise((resolve, reject) => { + scrypt( + password.normalize('NFKC'), + salt, + this.dkLen, + { + N: this.N, + p: this.p, + r: this.r, + // errors when 128 * N * r > `maxmem` (approximately) + maxmem: 128 * this.N * this.r * 2, + }, + (err, buff) => { + if (err) return reject(err) + return resolve(buff) + }, + ) + }) + } +} diff --git a/src/lib/server/api/services/recovery-codes.service.ts b/src/lib/server/api/services/recovery-codes.service.ts index e96f7dc..75d6d6b 100644 --- a/src/lib/server/api/services/recovery-codes.service.ts +++ b/src/lib/server/api/services/recovery-codes.service.ts @@ -1,12 +1,15 @@ import 'reflect-metadata' import { RecoveryCodesRepository } from '$lib/server/api/repositories/recovery-codes.repository' import { alphabet, generateRandomString } from 'oslo/crypto' -import { Argon2id } from 'oslo/password' import { inject, injectable } from 'tsyringe' +import { HashingService } from './hashing.service' @injectable() export class RecoveryCodesService { - constructor(@inject(RecoveryCodesRepository) private readonly recoveryCodesRepository: RecoveryCodesRepository) {} + constructor( + @inject(HashingService) private readonly hashingService: HashingService, + @inject(RecoveryCodesRepository) private readonly recoveryCodesRepository: RecoveryCodesRepository + ) {} async findAllRecoveryCodesByUserId(userId: string) { return this.recoveryCodesRepository.findAllByUserId(userId) @@ -16,7 +19,7 @@ export class RecoveryCodesService { const createdRecoveryCodes = Array.from({ length: 5 }, () => generateRandomString(10, alphabet('A-Z', '0-9'))) if (createdRecoveryCodes && userId) { for (const code of createdRecoveryCodes) { - const hashedCode = await new Argon2id().hash(code) + const hashedCode = await this.hashingService.hash(code) console.log('Inserting recovery code', code, hashedCode) await this.recoveryCodesRepository.create({ userId, code: hashedCode }) } diff --git a/src/lib/server/api/tests/tokens.service.test.ts b/src/lib/server/api/tests/tokens.service.test.ts index cff2574..7ecdddf 100644 --- a/src/lib/server/api/tests/tokens.service.test.ts +++ b/src/lib/server/api/tests/tokens.service.test.ts @@ -1,5 +1,4 @@ import 'reflect-metadata' -import { Argon2id } from 'oslo/password' import { container } from 'tsyringe' import { afterAll, beforeAll, describe, expect, expectTypeOf, it, vi } from 'vitest' import { HashingService } from '../services/hashing.service' @@ -19,7 +18,7 @@ describe('TokensService', () => { describe('Generate Token', () => { it('should resolve', async () => { - const hashedPassword = await new Argon2id().hash('111') + const hashedPassword = 'testhash' hashingService.hash = vi.fn().mockResolvedValue(hashedPassword) const spy_hashingService_hash = vi.spyOn(hashingService, 'hash') const spy_hashingService_verify = vi.spyOn(hashingService, 'verify') @@ -28,7 +27,7 @@ describe('TokensService', () => { expect(spy_hashingService_verify).toBeCalledTimes(0) }) it('should generate a token that is verifiable', async () => { - hashingService.hash = vi.fn().mockResolvedValue(await new Argon2id().hash('111')) + hashingService.hash = vi.fn().mockResolvedValue('testhash') hashingService.verify = vi.fn().mockResolvedValue(true) const spy_hashingService_hash = vi.spyOn(hashingService, 'hash') const spy_hashingService_verify = vi.spyOn(hashingService, 'verify') diff --git a/src/lib/server/api/tests/users.service.test.ts b/src/lib/server/api/tests/users.service.test.ts index ca916e2..8757df8 100644 --- a/src/lib/server/api/tests/users.service.test.ts +++ b/src/lib/server/api/tests/users.service.test.ts @@ -1,12 +1,12 @@ import 'reflect-metadata' import { CredentialsType } from '$lib/server/api/databases/tables' import { faker } from '@faker-js/faker' -import { Argon2id } from 'oslo/password' import { container } from 'tsyringe' import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' import { CredentialsRepository } from '../repositories/credentials.repository' import { UsersRepository } from '../repositories/users.repository' import { CollectionsService } from '../services/collections.service' +import { DrizzleService } from '../services/drizzle.service' import { TokensService } from '../services/tokens.service' import { UserRolesService } from '../services/user_roles.service' import { UsersService } from '../services/users.service' @@ -15,21 +15,44 @@ import { WishlistsService } from '../services/wishlists.service' describe('UsersService', () => { let service: UsersService const credentialsRepository = vi.mocked(CredentialsRepository.prototype) + const drizzleService = vi.mocked(DrizzleService.prototype, { deep: true }) const tokensService = vi.mocked(TokensService.prototype) const usersRepository = vi.mocked(UsersRepository.prototype) const userRolesService = vi.mocked(UserRolesService.prototype) const wishlistsService = vi.mocked(WishlistsService.prototype) const collectionsService = vi.mocked(CollectionsService.prototype) + // Mocking the dependencies + vi.mock('pg', () => ({ + Pool: vi.fn().mockImplementation(() => ({ + connect: vi.fn(), + end: vi.fn(), + })), + })) + + vi.mock('drizzle-orm/node-postgres', () => ({ + drizzle: vi.fn().mockImplementation(() => ({ + transaction: vi.fn().mockImplementation((callback) => callback()), + // Add other methods you need to mock + })), + })) + beforeAll(() => { service = container .register(CredentialsRepository, { useValue: credentialsRepository }) + .register(DrizzleService, { useValue: drizzleService }) .register(TokensService, { useValue: tokensService }) .register(UsersRepository, { useValue: usersRepository }) .register(UserRolesService, { useValue: userRolesService }) .register(WishlistsService, { useValue: wishlistsService }) .register(CollectionsService, { useValue: collectionsService }) .resolve(UsersService) + + drizzleService.db = { + transaction: vi.fn().mockImplementation(async (callback) => { + return await callback() + }), + } as any }) afterAll(() => { @@ -62,8 +85,11 @@ describe('UsersService', () => { describe('Create User', () => { it('should resolve', async () => { - const hashedPassword = new Argon2id().hash('111') + const hashedPassword = 'testhash' tokensService.createHashedToken = vi.fn().mockResolvedValue(hashedPassword) + // drizzleService.db = { + // transaction: vi.fn().mockResolvedValue(dbUser satisfies Awaited>), + // } usersRepository.create = vi.fn().mockResolvedValue(dbUser satisfies Awaited>) credentialsRepository.create = vi.fn().mockResolvedValue(dbCredentials satisfies Awaited>) userRolesService.addRoleToUser = vi.fn().mockResolvedValue(undefined) @@ -96,7 +122,7 @@ describe('UsersService', () => { }) describe('Update User', () => { it('should resolve Password Exiting Credentials', async () => { - const hashedPassword = new Argon2id().hash('111') + const hashedPassword = 'testhash' tokensService.createHashedToken = vi.fn().mockResolvedValue(hashedPassword) credentialsRepository.update = vi.fn().mockResolvedValue(dbCredentials satisfies Awaited>) credentialsRepository.findPasswordCredentialsByUserId = vi @@ -112,7 +138,7 @@ describe('UsersService', () => { expect(spy_credentialsRepository_update).toBeCalledTimes(1) }) it('Should Create User Password No Existing Credentials', async () => { - const hashedPassword = new Argon2id().hash('111') + const hashedPassword = 'testhash' tokensService.createHashedToken = vi.fn().mockResolvedValue(hashedPassword) credentialsRepository.findPasswordCredentialsByUserId = vi.fn().mockResolvedValue(null) credentialsRepository.create = vi.fn().mockResolvedValue(dbCredentials satisfies Awaited>) diff --git a/src/routes/(auth)/totp/+page.server.ts b/src/routes/(auth)/totp/+page.server.ts index a4f79dd..cfba820 100644 --- a/src/routes/(auth)/totp/+page.server.ts +++ b/src/routes/(auth)/totp/+page.server.ts @@ -4,8 +4,7 @@ import { twoFactorTable, usersTable } from '$lib/server/api/databases/tables' import { db } from '$lib/server/api/packages/drizzle' import { recoveryCodeSchema, totpSchema } from '$lib/validations/auth' import { type Actions, fail } from '@sveltejs/kit' -import { and, eq } from 'drizzle-orm' -import { Argon2id } from 'oslo/password' +import { eq } from 'drizzle-orm' import { redirect } from 'sveltekit-flash-message/server' import { zod } from 'sveltekit-superforms/adapters' import { superValidate } from 'sveltekit-superforms/server' @@ -268,21 +267,21 @@ function totpTimeElapsed(initiatedTime: Date) { return false } -async function checkRecoveryCode(recoveryCode: string, userId: string) { - const userRecoveryCodes = await db.query.recoveryCodesTable.findMany({ - where: and(eq(recoveryCodesTable.used, false), eq(recoveryCodesTable.userId, userId)), - }) - for (const code of userRecoveryCodes) { - const validRecoveryCode = await new Argon2id().verify(code.code, recoveryCode) - if (validRecoveryCode) { - await db - .update(recoveryCodesTable) - .set({ - used: true, - }) - .where(eq(recoveryCodesTable.id, code.id)) - return true - } - } - return false -} +// async function checkRecoveryCode(recoveryCode: string, userId: string) { +// const userRecoveryCodes = await db.query.recoveryCodesTable.findMany({ +// where: and(eq(recoveryCodesTable.used, false), eq(recoveryCodesTable.userId, userId)), +// }) +// for (const code of userRecoveryCodes) { +// const validRecoveryCode = await new Argon2id().verify(code.code, recoveryCode) +// if (validRecoveryCode) { +// await db +// .update(recoveryCodesTable) +// .set({ +// used: true, +// }) +// .where(eq(recoveryCodesTable.id, code.id)) +// return true +// } +// } +// return false +// } From 0ddfacb3a76c48a4346896367f042045149118ed Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Thu, 26 Sep 2024 14:02:08 -0700 Subject: [PATCH 24/29] Adding pg-native to the dependencies. --- package.json | 1 + pnpm-lock.yaml | 70 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 57 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index bc46b96..334c4ce 100644 --- a/package.json +++ b/package.json @@ -119,6 +119,7 @@ "open-props": "^1.7.6", "oslo": "^1.2.1", "pg": "^8.13.0", + "pg-native": "^3.2.0", "postgres": "^3.4.4", "qrcode": "^1.5.4", "radix-svelte": "^0.9.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ee6151a..19c1dbd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,7 +31,7 @@ importers: version: 3.5.5 '@lucia-auth/adapter-drizzle': specifier: ^1.1.0 - version: 1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4))(lucia@3.2.0) + version: 1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0(pg-native@3.2.0))(postgres@3.4.4))(lucia@3.2.0) '@lukeed/uuid': specifier: ^2.0.1 version: 2.0.1 @@ -97,10 +97,10 @@ importers: version: 11.0.6 drizzle-orm: specifier: ^0.32.2 - version: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4) + version: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0(pg-native@3.2.0))(postgres@3.4.4) drizzle-zod: specifier: ^0.5.1 - version: 0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4))(zod@3.23.8) + version: 0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0(pg-native@3.2.0))(postgres@3.4.4))(zod@3.23.8) feather-icons: specifier: ^4.29.2 version: 4.29.2 @@ -142,7 +142,10 @@ importers: version: 1.2.1 pg: specifier: ^8.13.0 - version: 8.13.0 + version: 8.13.0(pg-native@3.2.0) + pg-native: + specifier: ^3.2.0 + version: 3.2.0 postgres: specifier: ^3.4.4 version: 3.4.4 @@ -3263,6 +3266,9 @@ packages: libphonenumber-js@1.11.8: resolution: {integrity: sha512-0fv/YKpJBAgXKy0kaS3fnqoUVN8901vUYAKIGD/MWZaDfhJt1nZjPL3ZzdZBt/G8G8Hw2J1xOIrXWdNHFHPAvg==} + libpq@1.8.13: + resolution: {integrity: sha512-t1wpnGVgwRIFSKoe4RFUllAFj953kNMcdXhGvFJwI0r6lJQqgSwTeiIciaCinjOmHk0HnFeWQSMC6Uw2591G4A==} + lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} @@ -3460,6 +3466,9 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + nan@2.19.0: + resolution: {integrity: sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==} + nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -3658,6 +3667,9 @@ packages: resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} engines: {node: '>=4.0.0'} + pg-native@3.2.0: + resolution: {integrity: sha512-9q9I6RmT285DiRc0xkYb8e+bwOIIbnfVLddnzzXW35K1sZc74dR+symo2oeuzSW/sDQ8n24gWAvlGWK/GDJ3+Q==} + pg-numeric@1.0.2: resolution: {integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==} engines: {node: '>=4'} @@ -3673,6 +3685,9 @@ packages: pg-protocol@1.7.0: resolution: {integrity: sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==} + pg-types@1.13.0: + resolution: {integrity: sha512-lfKli0Gkl/+za/+b6lzENajczwZHc7D5kiUCZfgm914jipD2kIOIvEkAhZ8GrW3/TUoP9w8FHjwpPObBye5KQQ==} + pg-types@2.2.0: resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} engines: {node: '>=4'} @@ -3964,6 +3979,10 @@ packages: resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} engines: {node: ^10 || ^12 || >=14} + postgres-array@1.0.3: + resolution: {integrity: sha512-5wClXrAP0+78mcsNX3/ithQ5exKvCyK5lr5NEEEeGwwM6NJdQgzIJBVxLvRW+huFpX92F2QnZ5CcokH0VhK2qQ==} + engines: {node: '>=0.10.0'} + postgres-array@2.0.0: resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} engines: {node: '>=4'} @@ -5678,9 +5697,9 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@lucia-auth/adapter-drizzle@1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4))(lucia@3.2.0)': + '@lucia-auth/adapter-drizzle@1.1.0(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0(pg-native@3.2.0))(postgres@3.4.4))(lucia@3.2.0)': dependencies: - drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4) + drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0(pg-native@3.2.0))(postgres@3.4.4) lucia: 3.2.0 '@lukeed/csprng@1.1.0': {} @@ -6849,16 +6868,16 @@ snapshots: transitivePeerDependencies: - supports-color - drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4): + drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0(pg-native@3.2.0))(postgres@3.4.4): optionalDependencies: '@neondatabase/serverless': 0.9.5 '@types/pg': 8.11.10 - pg: 8.13.0 + pg: 8.13.0(pg-native@3.2.0) postgres: 3.4.4 - drizzle-zod@0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4))(zod@3.23.8): + drizzle-zod@0.5.1(drizzle-orm@0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0(pg-native@3.2.0))(postgres@3.4.4))(zod@3.23.8): dependencies: - drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0)(postgres@3.4.4) + drizzle-orm: 0.32.2(@neondatabase/serverless@0.9.5)(@types/pg@8.11.10)(pg@8.13.0(pg-native@3.2.0))(postgres@3.4.4) zod: 3.23.8 eastasianwidth@0.2.0: {} @@ -7566,6 +7585,11 @@ snapshots: libphonenumber-js@1.11.8: optional: true + libpq@1.8.13: + dependencies: + bindings: 1.5.0 + nan: 2.19.0 + lilconfig@2.1.0: {} lilconfig@3.1.2: {} @@ -7736,6 +7760,8 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 + nan@2.19.0: {} + nanoid@3.3.7: {} nanoid@5.0.7: {} @@ -7896,16 +7922,29 @@ snapshots: pg-int8@1.0.1: {} + pg-native@3.2.0: + dependencies: + libpq: 1.8.13 + pg-types: 1.13.0 + pg-numeric@1.0.2: {} - pg-pool@3.7.0(pg@8.13.0): + pg-pool@3.7.0(pg@8.13.0(pg-native@3.2.0)): dependencies: - pg: 8.13.0 + pg: 8.13.0(pg-native@3.2.0) pg-protocol@1.6.1: {} pg-protocol@1.7.0: {} + pg-types@1.13.0: + dependencies: + pg-int8: 1.0.1 + postgres-array: 1.0.3 + postgres-bytea: 1.0.0 + postgres-date: 1.0.7 + postgres-interval: 1.2.0 + pg-types@2.2.0: dependencies: pg-int8: 1.0.1 @@ -7924,15 +7963,16 @@ snapshots: postgres-interval: 3.0.0 postgres-range: 1.1.4 - pg@8.13.0: + pg@8.13.0(pg-native@3.2.0): dependencies: pg-connection-string: 2.7.0 - pg-pool: 3.7.0(pg@8.13.0) + pg-pool: 3.7.0(pg@8.13.0(pg-native@3.2.0)) pg-protocol: 1.7.0 pg-types: 2.2.0 pgpass: 1.0.5 optionalDependencies: pg-cloudflare: 1.1.1 + pg-native: 3.2.0 pgpass@1.0.5: dependencies: @@ -8242,6 +8282,8 @@ snapshots: picocolors: 1.1.0 source-map-js: 1.2.1 + postgres-array@1.0.3: {} + postgres-array@2.0.0: {} postgres-array@3.0.2: {} From fc1a0731a62099a29f5cfa25dc00b314152271da Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Thu, 26 Sep 2024 14:09:50 -0700 Subject: [PATCH 25/29] Changing to adapter node --- package.json | 1 - pnpm-lock.yaml | 12 +++++++----- svelte.config.js | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 334c4ce..bc46b96 100644 --- a/package.json +++ b/package.json @@ -119,7 +119,6 @@ "open-props": "^1.7.6", "oslo": "^1.2.1", "pg": "^8.13.0", - "pg-native": "^3.2.0", "postgres": "^3.4.4", "qrcode": "^1.5.4", "radix-svelte": "^0.9.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 19c1dbd..746f0fc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -143,9 +143,6 @@ importers: pg: specifier: ^8.13.0 version: 8.13.0(pg-native@3.2.0) - pg-native: - specifier: ^3.2.0 - version: 3.2.0 postgres: specifier: ^3.4.4 version: 3.4.4 @@ -7589,6 +7586,7 @@ snapshots: dependencies: bindings: 1.5.0 nan: 2.19.0 + optional: true lilconfig@2.1.0: {} @@ -7760,7 +7758,8 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - nan@2.19.0: {} + nan@2.19.0: + optional: true nanoid@3.3.7: {} @@ -7926,6 +7925,7 @@ snapshots: dependencies: libpq: 1.8.13 pg-types: 1.13.0 + optional: true pg-numeric@1.0.2: {} @@ -7944,6 +7944,7 @@ snapshots: postgres-bytea: 1.0.0 postgres-date: 1.0.7 postgres-interval: 1.2.0 + optional: true pg-types@2.2.0: dependencies: @@ -8282,7 +8283,8 @@ snapshots: picocolors: 1.1.0 source-map-js: 1.2.1 - postgres-array@1.0.3: {} + postgres-array@1.0.3: + optional: true postgres-array@2.0.0: {} diff --git a/svelte.config.js b/svelte.config.js index 71dd300..1b81ef1 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -1,6 +1,6 @@ import 'reflect-metadata' import { preprocessMeltUI } from '@melt-ui/pp' -import adapter from '@sveltejs/adapter-vercel' +import adapter from '@sveltejs/adapter-node' import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' import sequence from 'svelte-sequential-preprocessor' From 66c876002ee864ac38061730f10d9f9cd0234787 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Thu, 26 Sep 2024 18:44:05 -0700 Subject: [PATCH 26/29] Removing apple from oauth list and updating dependencies. --- package.json | 18 +- pnpm-lock.yaml | 322 +++++++++++++---------- src/routes/(auth)/login/+page.svelte | 1 - src/routes/(auth)/login/apple/+server.ts | 20 -- 4 files changed, 185 insertions(+), 176 deletions(-) delete mode 100644 src/routes/(auth)/login/apple/+server.ts diff --git a/package.json b/package.json index bc46b96..f0a6755 100644 --- a/package.json +++ b/package.json @@ -30,10 +30,10 @@ "@playwright/test": "^1.47.1", "@sveltejs/adapter-auto": "^3.2.5", "@sveltejs/enhanced-img": "^0.3.8", - "@sveltejs/kit": "^2.5.28", + "@sveltejs/kit": "^2.6.0", "@sveltejs/vite-plugin-svelte": "4.0.0-next.7", "@types/cookie": "^0.6.0", - "@types/node": "^20.16.5", + "@types/node": "^20.16.9", "@types/pg": "^8.11.10", "@types/qrcode": "^1.5.5", "@typescript-eslint/eslint-plugin": "^7.18.0", @@ -54,21 +54,21 @@ "postcss-load-config": "^5.1.0", "postcss-preset-env": "^9.6.0", "prettier": "^3.3.3", - "prettier-plugin-svelte": "^3.2.6", + "prettier-plugin-svelte": "^3.2.7", "svelte": "5.0.0-next.175", "svelte-check": "^3.8.6", "svelte-headless-table": "^0.18.2", "svelte-meta-tags": "^3.1.4", - "svelte-preprocess": "^6.0.2", + "svelte-preprocess": "^6.0.3", "svelte-sequential-preprocessor": "^2.0.1", "sveltekit-flash-message": "^2.4.4", "sveltekit-superforms": "^2.18.1", - "tailwindcss": "^3.4.12", + "tailwindcss": "^3.4.13", "ts-node": "^10.9.2", "tslib": "^2.7.0", "tsx": "^4.19.1", "typescript": "^5.6.2", - "vite": "^5.4.6", + "vite": "^5.4.8", "vitest": "^1.6.0", "zod": "^3.23.8" }, @@ -86,13 +86,13 @@ "@neondatabase/serverless": "^0.9.5", "@node-rs/argon2": "^1.8.3", "@oslojs/crypto": "^1.0.1", - "@oslojs/encoding": "^1.0.0", + "@oslojs/encoding": "^1.1.0", "@oslojs/jwt": "^0.2.0", "@oslojs/oauth2": "^0.5.0", "@oslojs/otp": "^1.0.0", "@oslojs/webauthn": "^1.0.0", "@paralleldrive/cuid2": "^2.2.2", - "@sveltejs/adapter-node": "^5.2.3", + "@sveltejs/adapter-node": "^5.2.5", "@sveltejs/adapter-vercel": "^5.4.4", "@types/feather-icons": "^4.29.4", "bits-ui": "^0.21.13", @@ -108,7 +108,7 @@ "feather-icons": "^4.29.2", "formsnap": "^1.0.1", "handlebars": "^4.7.8", - "hono": "^4.6.2", + "hono": "^4.6.3", "hono-rate-limiter": "^0.4.0", "html-entities": "^2.5.2", "iconify-icon": "^2.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 746f0fc..de85c4f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,13 +13,13 @@ importers: version: 5.1.0 '@hono/swagger-ui': specifier: ^0.4.1 - version: 0.4.1(hono@4.6.2) + version: 0.4.1(hono@4.6.3) '@hono/zod-openapi': specifier: ^0.15.3 - version: 0.15.3(hono@4.6.2)(zod@3.23.8) + version: 0.15.3(hono@4.6.3)(zod@3.23.8) '@hono/zod-validator': specifier: ^0.2.2 - version: 0.2.2(hono@4.6.2)(zod@3.23.8) + version: 0.2.2(hono@4.6.3)(zod@3.23.8) '@iconify-icons/line-md': specifier: ^1.2.30 version: 1.2.30 @@ -45,8 +45,8 @@ importers: specifier: ^1.0.1 version: 1.0.1 '@oslojs/encoding': - specifier: ^1.0.0 - version: 1.0.0 + specifier: ^1.1.0 + version: 1.1.0 '@oslojs/jwt': specifier: ^0.2.0 version: 0.2.0 @@ -63,11 +63,11 @@ importers: specifier: ^2.2.2 version: 2.2.2 '@sveltejs/adapter-node': - specifier: ^5.2.3 - version: 5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) + specifier: ^5.2.5 + version: 5.2.5(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1))) '@sveltejs/adapter-vercel': specifier: ^5.4.4 - version: 5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) + version: 5.4.4(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1))) '@types/feather-icons': specifier: ^4.29.4 version: 4.29.4 @@ -106,16 +106,16 @@ importers: version: 4.29.2 formsnap: specifier: ^1.0.1 - version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)) + version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)) handlebars: specifier: ^4.7.8 version: 4.7.8 hono: - specifier: ^4.6.2 - version: 4.6.2 + specifier: ^4.6.3 + version: 4.6.3 hono-rate-limiter: specifier: ^0.4.0 - version: 0.4.0(hono@4.6.2) + version: 0.4.0(hono@4.6.3) html-entities: specifier: ^2.5.2 version: 2.5.2 @@ -169,10 +169,10 @@ importers: version: 2.5.2 tailwind-variants: specifier: ^0.2.1 - version: 0.2.1(tailwindcss@3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))) + version: 0.2.1(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2))) tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))) + version: 1.0.7(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2))) tsyringe: specifier: ^4.8.0 version: 4.8.0 @@ -197,22 +197,22 @@ importers: version: 1.47.2 '@sveltejs/adapter-auto': specifier: ^3.2.5 - version: 3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))) + version: 3.2.5(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1))) '@sveltejs/enhanced-img': specifier: ^0.3.8 - version: 0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + version: 0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) '@sveltejs/kit': - specifier: ^2.5.28 - version: 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + specifier: ^2.6.0 + version: 2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) '@sveltejs/vite-plugin-svelte': specifier: 4.0.0-next.7 - version: 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + version: 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) '@types/cookie': specifier: ^0.6.0 version: 0.6.0 '@types/node': - specifier: ^20.16.5 - version: 20.16.5 + specifier: ^20.16.9 + version: 20.16.9 '@types/pg': specifier: ^8.11.10 version: 8.11.10 @@ -242,7 +242,7 @@ importers: version: 9.1.0(eslint@8.57.1) eslint-plugin-svelte: specifier: 2.36.0-next.13 - version: 2.36.0-next.13(eslint@8.57.1)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + version: 2.36.0-next.13(eslint@8.57.1)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)) just-clone: specifier: ^6.2.0 version: 6.2.0 @@ -274,8 +274,8 @@ importers: specifier: ^3.3.3 version: 3.3.3 prettier-plugin-svelte: - specifier: ^3.2.6 - version: 3.2.6(prettier@3.3.3)(svelte@5.0.0-next.175) + specifier: ^3.2.7 + version: 3.2.7(prettier@3.3.3)(svelte@5.0.0-next.175) svelte: specifier: 5.0.0-next.175 version: 5.0.0-next.175 @@ -289,23 +289,23 @@ importers: specifier: ^3.1.4 version: 3.1.4(svelte@5.0.0-next.175)(typescript@5.6.2) svelte-preprocess: - specifier: ^6.0.2 - version: 6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175)(typescript@5.6.2) + specifier: ^6.0.3 + version: 6.0.3(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175)(typescript@5.6.2) svelte-sequential-preprocessor: specifier: ^2.0.1 version: 2.0.1 sveltekit-flash-message: specifier: ^2.4.4 - version: 2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175) + version: 2.4.4(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175) sveltekit-superforms: specifier: ^2.18.1 - version: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) + version: 2.19.0(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) tailwindcss: - specifier: ^3.4.12 - version: 3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + specifier: ^3.4.13 + version: 3.4.13(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)) ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.16.5)(typescript@5.6.2) + version: 10.9.2(@types/node@20.16.9)(typescript@5.6.2) tslib: specifier: ^2.7.0 version: 2.7.0 @@ -316,11 +316,11 @@ importers: specifier: ^5.6.2 version: 5.6.2 vite: - specifier: ^5.4.6 - version: 5.4.7(@types/node@20.16.5)(sass@1.79.1) + specifier: ^5.4.8 + version: 5.4.8(@types/node@20.16.9)(sass@1.79.1) vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@20.16.5)(sass@1.79.1) + version: 1.6.0(@types/node@20.16.9)(sass@1.79.1) zod: specifier: ^3.23.8 version: 3.23.8 @@ -1818,6 +1818,9 @@ packages: '@oslojs/encoding@1.0.0': resolution: {integrity: sha512-dyIB0SdZgMm5BhGwdSp8rMxEFIopLKxDG1vxIBaiogyom6ZqH2aXPb6DEC2WzOOWKdPSq1cxdNeRx2wAn1Z+ZQ==} + '@oslojs/encoding@1.1.0': + resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} + '@oslojs/jwt@0.2.0': resolution: {integrity: sha512-bLE7BtHrURedCn4Mco3ma9L4Y1GR2SMBuIvjWr7rmQ4/W/4Jy70TIAgZ+0nIlk0xHz1vNP8x8DCns45Sb2XRbg==} @@ -1849,8 +1852,8 @@ packages: resolution: {integrity: sha512-xhhEcEvhQC8mP5oOr5hbE4CmUgmw/IPV1jhpGg2xSkzoFrt9i8YVqBQt9744EFesi5F7pBheWozg63RUBM/5JA==} engines: {node: '>=18.16.0'} - '@rollup/plugin-commonjs@26.0.1': - resolution: {integrity: sha512-UnsKoZK6/aGIH6AdkptXhNvhaqftcjq3zZdT+LY5Ftms6JR06nADcDsYp5hTU9E2lbJUEOhdlY5J4DNTneM+jQ==} + '@rollup/plugin-commonjs@28.0.0': + resolution: {integrity: sha512-BJcu+a+Mpq476DMXG+hevgPSl56bkUoi88dKT8t3RyUp8kGuOh+2bU8Gs7zXDlu+fyZggnJ+iOBGrb/O1SorYg==} engines: {node: '>=16.0.0 || 14 >= 14.17'} peerDependencies: rollup: ^2.68.0||^3.0.0||^4.0.0 @@ -1867,8 +1870,8 @@ packages: rollup: optional: true - '@rollup/plugin-node-resolve@15.2.3': - resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==} + '@rollup/plugin-node-resolve@15.3.0': + resolution: {integrity: sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==} engines: {node: '>=14.0.0'} peerDependencies: rollup: ^2.78.0||^3.0.0||^4.0.0 @@ -1889,6 +1892,15 @@ packages: rollup: optional: true + '@rollup/pluginutils@5.1.2': + resolution: {integrity: sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + '@rollup/rollup-android-arm-eabi@4.21.2': resolution: {integrity: sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg==} cpu: [arm] @@ -1992,8 +2004,8 @@ packages: peerDependencies: '@sveltejs/kit': ^2.0.0 - '@sveltejs/adapter-node@5.2.4': - resolution: {integrity: sha512-L9Kngx1ce2SMCbyGBbRaJovl5lzdwH650SzOa50txAAssMfWLj2f8yPsA2eCX8EhT6AxD4RHLNrVa5W8VUYz8w==} + '@sveltejs/adapter-node@5.2.5': + resolution: {integrity: sha512-FVeysFqeIlKFpDF1Oj38gby34f6uA9FuXnV330Z0RHmSyOR9JzJs70/nFKy1Ue3fWtf7S0RemOrP66Vr9Jcmew==} peerDependencies: '@sveltejs/kit': ^2.4.0 @@ -2008,8 +2020,8 @@ packages: svelte: ^4.0.0 || ^5.0.0-next.0 vite: '>= 5.0.0' - '@sveltejs/kit@2.5.28': - resolution: {integrity: sha512-/O7pvFGBsQPcFa9UrW8eUC5uHTOXLsUp3SN0dY6YmRAL9nfPSrJsSJk//j5vMpinSshzUjteAFcfQTU+04Ka1w==} + '@sveltejs/kit@2.6.0': + resolution: {integrity: sha512-oG8cCAopDQavdN+RbzanNpfyUWsTbZ2Nt1zNioBm8thXLo1/8VtwP/KvlJW2HgrdN235NI4IL5bSZjTEXKuifQ==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -2059,14 +2071,17 @@ packages: '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@types/feather-icons@4.29.4': resolution: {integrity: sha512-cvwI455PWx/gJ33XDTIZOdauRy+XCxZggkOT/tAQYZLdySPFATD4RnDC9mxOnCIEaK9kwPm3zZigkAsMkhXb5w==} '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@20.16.5': - resolution: {integrity: sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==} + '@types/node@20.16.9': + resolution: {integrity: sha512-rkvIVJxsOfBejxK7I0FO5sa2WxFmJCzoDwcd88+fq/CUfynNywTo/1/T6hyFz22CyztsnLS9nVlHOnTI36RH5w==} '@types/pg@8.11.10': resolution: {integrity: sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==} @@ -2351,10 +2366,6 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - builtin-modules@3.3.0: - resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} - engines: {node: '>=6'} - bullmq@5.13.2: resolution: {integrity: sha512-McGE8k3mrCvdUHdU0sHkTKDS1xr4pff+hbEKBY51wk5S6Za0gkuejYA620VQTo3Zz37E/NVWMgumwiXPQ3yZcA==} @@ -2404,8 +2415,8 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} - chokidar@4.0.0: - resolution: {integrity: sha512-mxIojEAQcuEvT/lyXq+jf/3cO/KoA6z4CeNDGGevTybECPOMFCnQy3OPahluUkbqgPNGw5Bi78UC7Po6Lhy+NA==} + chokidar@4.0.1: + resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} engines: {node: '>= 14.16.0'} chownr@2.0.0: @@ -2601,6 +2612,9 @@ packages: devalue@5.0.0: resolution: {integrity: sha512-gO+/OMXF7488D+u3ue+G7Y4AA3ZmUnB3eHJXmBTgNHvr4ZNzl36A0ZtG+XCRNYCkYx/bFmw4qtkoFLa+wSrwAA==} + devalue@5.1.1: + resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==} + didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} @@ -2910,6 +2924,14 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + fdir@6.3.0: + resolution: {integrity: sha512-QOnuT+BOtivR77wYvCWHfGt9s4Pz1VIMbD463vegT5MLqNXy8rYFT/lPVEqf/bhYeT6qmqrNHhsX+rWwe3rOCQ==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + feather-icons@4.29.2: resolution: {integrity: sha512-0TaCFTnBTVCz6U+baY2UJNKne5ifGh7sMG4ZC2LoBWCZdIyPa+y6UiR4lEYGws1JOFWdee8KAsAIvu0VcXqiqA==} @@ -3084,8 +3106,8 @@ packages: peerDependencies: hono: ^4.1.1 - hono@4.6.2: - resolution: {integrity: sha512-v+39817TgAhetmHUEli8O0uHDmxp2Up3DnhS4oUZXOl5IQ9np9tYtldd42e5zgdLVS0wsOoXQNZ6mx+BGmEvCA==} + hono@4.6.3: + resolution: {integrity: sha512-0LeEuBNFeSHGqZ9sNVVgZjB1V5fmhkBSB0hZrpqStSMLOWgfLy0dHOvrjbJh0H2khsjet6rbHfWTHY0kpYThKQ==} engines: {node: '>=16.9.0'} html-entities@2.5.2: @@ -3154,10 +3176,6 @@ packages: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} - is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} - is-core-module@2.15.1: resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} engines: {node: '>= 0.4'} @@ -4023,8 +4041,8 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier-plugin-svelte@3.2.6: - resolution: {integrity: sha512-Y1XWLw7vXUQQZmgv1JAEiLcErqUniAF2wO7QJsw8BVMvpLET2dI5WpEIEJx1r11iHVdSMzQxivyfrH9On9t2IQ==} + prettier-plugin-svelte@3.2.7: + resolution: {integrity: sha512-/Dswx/ea0lV34If1eDcG3nulQ63YNr5KPDfMsjbdtpSWOxKKJ7nAc2qlVuYwEvCr4raIuredNoR7K4JCkmTGaQ==} peerDependencies: prettier: ^3.0.0 svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0 @@ -4416,8 +4434,8 @@ packages: typescript: optional: true - svelte-preprocess@6.0.2: - resolution: {integrity: sha512-OvDTLfaOkkhjprbDKO0SOCkjNYuHy16dbD4SpqbIi6QiabOMHxRT4km5/dzbFFkmW1L0E2INF3MFltG2pgOyKQ==} + svelte-preprocess@6.0.3: + resolution: {integrity: sha512-PLG2k05qHdhmRG7zR/dyo5qKvakhm8IJ+hD2eFRQmMLHp7X3eJnjeupUtvuRpbNiF31RjVw45W+abDwHEmP5OA==} engines: {node: '>= 18.0.0'} peerDependencies: '@babel/core': ^7.10.2 @@ -4509,8 +4527,8 @@ packages: peerDependencies: tailwindcss: '>=3.0.0 || insiders' - tailwindcss@3.4.12: - resolution: {integrity: sha512-Htf/gHj2+soPb9UayUNci/Ja3d8pTmu9ONTfh4QY8r3MATTZOzmv6UYWF7ZwikEIC8okpfqmGqrmDehua8mF8w==} + tailwindcss@3.4.13: + resolution: {integrity: sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==} engines: {node: '>=14.0.0'} hasBin: true @@ -4703,8 +4721,8 @@ packages: engines: {node: ^18.0.0 || >=20.0.0} hasBin: true - vite@5.4.7: - resolution: {integrity: sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==} + vite@5.4.8: + resolution: {integrity: sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -5540,20 +5558,20 @@ snapshots: '@hapi/hoek': 9.3.0 optional: true - '@hono/swagger-ui@0.4.1(hono@4.6.2)': + '@hono/swagger-ui@0.4.1(hono@4.6.3)': dependencies: - hono: 4.6.2 + hono: 4.6.3 - '@hono/zod-openapi@0.15.3(hono@4.6.2)(zod@3.23.8)': + '@hono/zod-openapi@0.15.3(hono@4.6.3)(zod@3.23.8)': dependencies: '@asteasolutions/zod-to-openapi': 7.1.1(zod@3.23.8) - '@hono/zod-validator': 0.2.2(hono@4.6.2)(zod@3.23.8) - hono: 4.6.2 + '@hono/zod-validator': 0.2.2(hono@4.6.3)(zod@3.23.8) + hono: 4.6.3 zod: 3.23.8 - '@hono/zod-validator@0.2.2(hono@4.6.2)(zod@3.23.8)': + '@hono/zod-validator@0.2.2(hono@4.6.3)(zod@3.23.8)': dependencies: - hono: 4.6.2 + hono: 4.6.3 zod: 3.23.8 '@humanwhocodes/config-array@0.13.0': @@ -6003,6 +6021,8 @@ snapshots: '@oslojs/encoding@1.0.0': {} + '@oslojs/encoding@1.1.0': {} + '@oslojs/jwt@0.2.0': dependencies: '@oslojs/encoding': 0.4.1 @@ -6039,14 +6059,15 @@ snapshots: '@poppinss/macroable@1.0.2': optional: true - '@rollup/plugin-commonjs@26.0.1(rollup@4.21.2)': + '@rollup/plugin-commonjs@28.0.0(rollup@4.21.2)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.21.2) + '@rollup/pluginutils': 5.1.2(rollup@4.21.2) commondir: 1.0.1 estree-walker: 2.0.2 - glob: 10.4.5 + fdir: 6.3.0(picomatch@2.3.1) is-reference: 1.2.1 magic-string: 0.30.11 + picomatch: 2.3.1 optionalDependencies: rollup: 4.21.2 @@ -6056,12 +6077,11 @@ snapshots: optionalDependencies: rollup: 4.21.2 - '@rollup/plugin-node-resolve@15.2.3(rollup@4.21.2)': + '@rollup/plugin-node-resolve@15.3.0(rollup@4.21.2)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.21.2) + '@rollup/pluginutils': 5.1.2(rollup@4.21.2) '@types/resolve': 1.20.2 deepmerge: 4.3.1 - is-builtin-module: 3.2.1 is-module: 1.0.0 resolve: 1.22.8 optionalDependencies: @@ -6080,6 +6100,14 @@ snapshots: optionalDependencies: rollup: 4.21.2 + '@rollup/pluginutils@5.1.2(rollup@4.21.2)': + dependencies: + '@types/estree': 1.0.6 + estree-walker: 2.0.2 + picomatch: 2.3.1 + optionalDependencies: + rollup: 4.21.2 + '@rollup/rollup-android-arm-eabi@4.21.2': optional: true @@ -6147,44 +6175,44 @@ snapshots: '@sodaru/yup-to-json-schema@2.0.1': optional: true - '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': + '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))': dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) import-meta-resolve: 4.1.0 - '@sveltejs/adapter-node@5.2.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': + '@sveltejs/adapter-node@5.2.5(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))': dependencies: - '@rollup/plugin-commonjs': 26.0.1(rollup@4.21.2) + '@rollup/plugin-commonjs': 28.0.0(rollup@4.21.2) '@rollup/plugin-json': 6.1.0(rollup@4.21.2) - '@rollup/plugin-node-resolve': 15.2.3(rollup@4.21.2) - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@rollup/plugin-node-resolve': 15.3.0(rollup@4.21.2) + '@sveltejs/kit': 2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) rollup: 4.21.2 - '@sveltejs/adapter-vercel@5.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))': + '@sveltejs/adapter-vercel@5.4.4(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))': dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) '@vercel/nft': 0.27.4 esbuild: 0.21.5 transitivePeerDependencies: - encoding - supports-color - '@sveltejs/enhanced-img@0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/enhanced-img@0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1))': dependencies: magic-string: 0.30.11 svelte: 5.0.0-next.175 svelte-parse-markup: 0.1.5(svelte@5.0.0-next.175) - vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) + vite: 5.4.8(@types/node@20.16.9)(sass@1.79.1) vite-imagetools: 7.0.4(rollup@4.21.2) transitivePeerDependencies: - rollup - '@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) '@types/cookie': 0.6.0 cookie: 0.6.0 - devalue: 5.0.0 + devalue: 5.1.1 esm-env: 1.0.0 import-meta-resolve: 4.1.0 kleur: 4.1.5 @@ -6195,27 +6223,27 @@ snapshots: sirv: 2.0.4 svelte: 5.0.0-next.175 tiny-glob: 0.2.9 - vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) + vite: 5.4.8(@types/node@20.16.9)(sass@1.79.1) - '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) debug: 4.3.6 svelte: 5.0.0-next.175 - vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) + vite: 5.4.8(@types/node@20.16.9)(sass@1.79.1) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1))': + '@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte-inspector': 3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) debug: 4.3.6 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.11 svelte: 5.0.0-next.175 - vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) - vitefu: 1.0.2(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + vite: 5.4.8(@types/node@20.16.9)(sass@1.79.1) + vitefu: 1.0.2(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) transitivePeerDependencies: - supports-color @@ -6245,24 +6273,26 @@ snapshots: '@types/estree@1.0.5': {} + '@types/estree@1.0.6': {} + '@types/feather-icons@4.29.4': {} '@types/json-schema@7.0.15': optional: true - '@types/node@20.16.5': + '@types/node@20.16.9': dependencies: undici-types: 6.19.8 '@types/pg@8.11.10': dependencies: - '@types/node': 20.16.5 + '@types/node': 20.16.9 pg-protocol: 1.6.1 pg-types: 4.0.2 '@types/pg@8.11.6': dependencies: - '@types/node': 20.16.5 + '@types/node': 20.16.9 pg-protocol: 1.6.1 pg-types: 4.0.2 @@ -6270,7 +6300,7 @@ snapshots: '@types/qrcode@1.5.5': dependencies: - '@types/node': 20.16.5 + '@types/node': 20.16.9 '@types/resolve@1.20.2': {} @@ -6604,8 +6634,6 @@ snapshots: buffer-from@1.1.2: {} - builtin-modules@3.3.0: {} - bullmq@5.13.2: dependencies: cron-parser: 4.9.0 @@ -6672,7 +6700,7 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - chokidar@4.0.0: + chokidar@4.0.1: dependencies: readdirp: 4.0.1 optional: true @@ -6832,6 +6860,8 @@ snapshots: devalue@5.0.0: {} + devalue@5.1.1: {} + didyoumean@1.2.2: {} diff-sequences@29.6.3: {} @@ -7030,7 +7060,7 @@ snapshots: dependencies: eslint: 8.57.1 - eslint-plugin-svelte@2.36.0-next.13(eslint@8.57.1)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): + eslint-plugin-svelte@2.36.0-next.13(eslint@8.57.1)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)): dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) '@jridgewell/sourcemap-codec': 1.5.0 @@ -7040,7 +7070,7 @@ snapshots: esutils: 2.0.3 known-css-properties: 0.30.0 postcss: 8.4.47 - postcss-load-config: 3.1.4(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + postcss-load-config: 3.1.4(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)) postcss-safe-parser: 6.0.0(postcss@8.4.47) postcss-selector-parser: 6.1.2 semver: 7.6.3 @@ -7208,6 +7238,10 @@ snapshots: dependencies: reusify: 1.0.4 + fdir@6.3.0(picomatch@2.3.1): + optionalDependencies: + picomatch: 2.3.1 + feather-icons@4.29.2: dependencies: classnames: 2.5.1 @@ -7262,11 +7296,11 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)): + formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)): dependencies: nanoid: 5.0.7 svelte: 5.0.0-next.175 - sveltekit-superforms: 2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) + sveltekit-superforms: 2.19.0(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) forwarded@0.2.0: {} @@ -7397,11 +7431,11 @@ snapshots: dependencies: function-bind: 1.1.2 - hono-rate-limiter@0.4.0(hono@4.6.2): + hono-rate-limiter@0.4.0(hono@4.6.3): dependencies: - hono: 4.6.2 + hono: 4.6.3 - hono@4.6.2: {} + hono@4.6.3: {} html-entities@2.5.2: {} @@ -7475,10 +7509,6 @@ snapshots: dependencies: binary-extensions: 2.3.0 - is-builtin-module@3.2.1: - dependencies: - builtin-modules: 3.3.0 - is-core-module@2.15.1: dependencies: hasown: 2.0.2 @@ -7499,7 +7529,7 @@ snapshots: is-reference@1.2.1: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 is-reference@3.0.2: dependencies: @@ -8123,21 +8153,21 @@ snapshots: '@csstools/utilities': 1.0.0(postcss@8.4.47) postcss: 8.4.47 - postcss-load-config@3.1.4(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): + postcss-load-config@3.1.4(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)): dependencies: lilconfig: 2.1.0 yaml: 1.10.2 optionalDependencies: postcss: 8.4.47 - ts-node: 10.9.2(@types/node@20.16.5)(typescript@5.6.2) + ts-node: 10.9.2(@types/node@20.16.9)(typescript@5.6.2) - postcss-load-config@4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): + postcss-load-config@4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)): dependencies: lilconfig: 3.1.2 yaml: 2.5.1 optionalDependencies: postcss: 8.4.47 - ts-node: 10.9.2(@types/node@20.16.5)(typescript@5.6.2) + ts-node: 10.9.2(@types/node@20.16.9)(typescript@5.6.2) postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1): dependencies: @@ -8312,7 +8342,7 @@ snapshots: prelude-ls@1.2.1: {} - prettier-plugin-svelte@3.2.6(prettier@3.3.3)(svelte@5.0.0-next.175): + prettier-plugin-svelte@3.2.7(prettier@3.3.3)(svelte@5.0.0-next.175): dependencies: prettier: 3.3.3 svelte: 5.0.0-next.175 @@ -8467,7 +8497,7 @@ snapshots: sass@1.79.1: dependencies: - chokidar: 4.0.0 + chokidar: 4.0.1 immutable: 4.3.7 source-map-js: 1.2.1 optional: true @@ -8735,7 +8765,7 @@ snapshots: sass: 1.79.1 typescript: 5.6.2 - svelte-preprocess@6.0.2(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175)(typescript@5.6.2): + svelte-preprocess@6.0.3(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175)(typescript@5.6.2): dependencies: svelte: 5.0.0-next.175 optionalDependencies: @@ -8795,14 +8825,14 @@ snapshots: magic-string: 0.30.11 zimmerframe: 1.1.2 - sveltekit-flash-message@2.4.4(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175): + sveltekit-flash-message@2.4.4(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) svelte: 5.0.0-next.175 - sveltekit-superforms@2.19.0(@sveltejs/kit@2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): + sveltekit-superforms@2.19.0(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.5.28(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)) + '@sveltejs/kit': 2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) devalue: 5.0.0 just-clone: 6.2.0 memoize-weak: 1.0.2 @@ -8831,16 +8861,16 @@ snapshots: tailwind-merge@2.5.2: {} - tailwind-variants@0.2.1(tailwindcss@3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))): + tailwind-variants@0.2.1(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2))): dependencies: tailwind-merge: 2.5.2 - tailwindcss: 3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + tailwindcss: 3.4.13(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)) - tailwindcss-animate@1.0.7(tailwindcss@3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2))): + tailwindcss-animate@1.0.7(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2))): dependencies: - tailwindcss: 3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + tailwindcss: 3.4.13(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)) - tailwindcss@3.4.12(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)): + tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -8859,7 +8889,7 @@ snapshots: postcss: 8.4.47 postcss-import: 15.1.0(postcss@8.4.47) postcss-js: 4.0.1(postcss@8.4.47) - postcss-load-config: 4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2)) + postcss-load-config: 4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)) postcss-nested: 6.2.0(postcss@8.4.47) postcss-selector-parser: 6.1.2 resolve: 1.22.8 @@ -8924,14 +8954,14 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-node@10.9.2(@types/node@20.16.5)(typescript@5.6.2): + ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.16.5 + '@types/node': 20.16.9 acorn: 8.12.1 acorn-walk: 8.3.3 arg: 4.1.3 @@ -9028,13 +9058,13 @@ snapshots: transitivePeerDependencies: - rollup - vite-node@1.6.0(@types/node@20.16.5)(sass@1.79.1): + vite-node@1.6.0(@types/node@20.16.9)(sass@1.79.1): dependencies: cac: 6.7.14 debug: 4.3.6 pathe: 1.1.2 picocolors: 1.1.0 - vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) + vite: 5.4.8(@types/node@20.16.9)(sass@1.79.1) transitivePeerDependencies: - '@types/node' - less @@ -9046,21 +9076,21 @@ snapshots: - supports-color - terser - vite@5.4.7(@types/node@20.16.5)(sass@1.79.1): + vite@5.4.8(@types/node@20.16.9)(sass@1.79.1): dependencies: esbuild: 0.21.5 postcss: 8.4.47 rollup: 4.21.2 optionalDependencies: - '@types/node': 20.16.5 + '@types/node': 20.16.9 fsevents: 2.3.3 sass: 1.79.1 - vitefu@1.0.2(vite@5.4.7(@types/node@20.16.5)(sass@1.79.1)): + vitefu@1.0.2(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)): optionalDependencies: - vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) + vite: 5.4.8(@types/node@20.16.9)(sass@1.79.1) - vitest@1.6.0(@types/node@20.16.5)(sass@1.79.1): + vitest@1.6.0(@types/node@20.16.9)(sass@1.79.1): dependencies: '@vitest/expect': 1.6.0 '@vitest/runner': 1.6.0 @@ -9079,11 +9109,11 @@ snapshots: strip-literal: 2.1.0 tinybench: 2.9.0 tinypool: 0.8.4 - vite: 5.4.7(@types/node@20.16.5)(sass@1.79.1) - vite-node: 1.6.0(@types/node@20.16.5)(sass@1.79.1) + vite: 5.4.8(@types/node@20.16.9)(sass@1.79.1) + vite-node: 1.6.0(@types/node@20.16.9)(sass@1.79.1) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 20.16.5 + '@types/node': 20.16.9 transitivePeerDependencies: - less - lightningcss diff --git a/src/routes/(auth)/login/+page.svelte b/src/routes/(auth)/login/+page.svelte index 662bab1..96fdd94 100644 --- a/src/routes/(auth)/login/+page.svelte +++ b/src/routes/(auth)/login/+page.svelte @@ -91,7 +91,6 @@ const { form: loginForm, enhance } = superLoginForm {#snippet oAuthButtons()}
-
{/snippet} diff --git a/src/routes/(auth)/login/apple/+server.ts b/src/routes/(auth)/login/apple/+server.ts deleted file mode 100644 index d9e5c33..0000000 --- a/src/routes/(auth)/login/apple/+server.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { github } from '$lib/server/auth' -import { redirect } from '@sveltejs/kit' -import { generateState } from 'arctic' - -import type { RequestEvent } from '@sveltejs/kit' - -export async function GET(event: RequestEvent): Promise { - const state = generateState() - const url = await github.createAuthorizationURL(state) - - event.cookies.set('github_oauth_state', state, { - path: '/', - secure: import.meta.env.PROD, - httpOnly: true, - maxAge: 60 * 10, - sameSite: 'lax', - }) - - redirect(302, url.toString()) -} From 590dea70b560f7270ad6991ede1ed6deb77de698 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Sun, 29 Sep 2024 16:13:08 -0700 Subject: [PATCH 27/29] Fix merge conflict on drizzle config. --- drizzle.config.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drizzle.config.ts b/drizzle.config.ts index 117e93e..f5f2c7e 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -5,11 +5,7 @@ import { defineConfig } from 'drizzle-kit' export default defineConfig({ dialect: 'postgresql', out: './src/lib/server/api/databases/migrations', -<<<<<<< HEAD - schema: './src/lib/server/api/databases/tables/*.table.ts', -======= schema: './src/lib/server/api/databases/tables/index.ts', ->>>>>>> 5849219833a6b9a99ec24a960962c4c537e93748 dbCredentials: { host: env.DATABASE_HOST || 'localhost', port: Number(env.DATABASE_PORT) || 5432, From bd87b89d11b9e46bd5bfef9daa6166a356826117 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Sun, 29 Sep 2024 19:51:24 -0700 Subject: [PATCH 28/29] Fix relations so Drizzle Studio can render. --- .../api/databases/tables/gamesToExternalIds.table.ts | 12 ++++++++++++ .../databases/tables/mechanicsToExternalIds.table.ts | 12 ++++++++++++ .../server/api/databases/tables/publishers.table.ts | 4 ++-- .../tables/publishersToExternalIds.table.ts | 12 ++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/lib/server/api/databases/tables/gamesToExternalIds.table.ts b/src/lib/server/api/databases/tables/gamesToExternalIds.table.ts index 8b19da3..3d56ccc 100644 --- a/src/lib/server/api/databases/tables/gamesToExternalIds.table.ts +++ b/src/lib/server/api/databases/tables/gamesToExternalIds.table.ts @@ -1,6 +1,7 @@ import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core' import { gamesTable } from '././games.table' import { externalIdsTable } from './externalIds.table' +import { relations } from 'drizzle-orm' export const gamesToExternalIdsTable = pgTable( 'games_to_external_ids', @@ -20,3 +21,14 @@ export const gamesToExternalIdsTable = pgTable( } }, ) + +export const gamesToExternalIdsRelations = relations(gamesToExternalIdsTable, ({ one }) => ({ + game: one(gamesTable, { + fields: [gamesToExternalIdsTable.gameId], + references: [gamesTable.id], + }), + externalId: one(externalIdsTable, { + fields: [gamesToExternalIdsTable.externalId], + references: [externalIdsTable.id], + }), +})) \ No newline at end of file diff --git a/src/lib/server/api/databases/tables/mechanicsToExternalIds.table.ts b/src/lib/server/api/databases/tables/mechanicsToExternalIds.table.ts index bb28cac..840e062 100644 --- a/src/lib/server/api/databases/tables/mechanicsToExternalIds.table.ts +++ b/src/lib/server/api/databases/tables/mechanicsToExternalIds.table.ts @@ -1,6 +1,7 @@ import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core' import { externalIdsTable } from './externalIds.table' import { mechanicsTable } from './mechanics.table' +import { relations } from 'drizzle-orm' export const mechanicsToExternalIdsTable = pgTable( 'mechanics_to_external_ids', @@ -20,3 +21,14 @@ export const mechanicsToExternalIdsTable = pgTable( } }, ) + +export const mechanicsToExternalIdsRelations = relations(mechanicsToExternalIdsTable, ({ one }) => ({ + mechanic: one(mechanicsTable, { + fields: [mechanicsToExternalIdsTable.mechanicId], + references: [mechanicsTable.id], + }), + externalId: one(externalIdsTable, { + fields: [mechanicsToExternalIdsTable.externalId], + references: [externalIdsTable.id], + }), +})) diff --git a/src/lib/server/api/databases/tables/publishers.table.ts b/src/lib/server/api/databases/tables/publishers.table.ts index 8102539..fd909b6 100644 --- a/src/lib/server/api/databases/tables/publishers.table.ts +++ b/src/lib/server/api/databases/tables/publishers.table.ts @@ -18,6 +18,6 @@ export const publishersTable = pgTable('publishers', { export type Publishers = InferSelectModel export const publishers_relations = relations(publishersTable, ({ many }) => ({ - publishers_to_games: many(publishers_to_games), + publishersToGames: many(publishers_to_games), publishersToExternalIds: many(publishersToExternalIdsTable), -})) +})) \ No newline at end of file diff --git a/src/lib/server/api/databases/tables/publishersToExternalIds.table.ts b/src/lib/server/api/databases/tables/publishersToExternalIds.table.ts index d16786b..2249d2f 100644 --- a/src/lib/server/api/databases/tables/publishersToExternalIds.table.ts +++ b/src/lib/server/api/databases/tables/publishersToExternalIds.table.ts @@ -1,6 +1,7 @@ import { pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core' import { externalIdsTable } from './externalIds.table' import { publishersTable } from './publishers.table' +import { relations } from 'drizzle-orm' export const publishersToExternalIdsTable = pgTable( 'publishers_to_external_ids', @@ -20,3 +21,14 @@ export const publishersToExternalIdsTable = pgTable( } }, ) + +export const publishersToExternalIdsRelations = relations(publishersToExternalIdsTable, ({ one }) => ({ + publisher: one(publishersTable, { + fields: [publishersToExternalIdsTable.publisherId], + references: [publishersTable.id], + }), + externalId: one(externalIdsTable, { + fields: [publishersToExternalIdsTable.externalId], + references: [externalIdsTable.id], + }), +})) From 728f9dbbba972abd050e958641d2224456e1a517 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Mon, 30 Sep 2024 09:52:40 -0700 Subject: [PATCH 29/29] Updating depenencies and fixing imports for seeds --- package.json | 8 +- pnpm-lock.yaml | 177 ++++++++++---------- src/lib/server/api/databases/seeds/roles.ts | 4 +- src/lib/server/api/databases/seeds/users.ts | 6 +- 4 files changed, 95 insertions(+), 100 deletions(-) diff --git a/package.json b/package.json index f0a6755..dc6a12c 100644 --- a/package.json +++ b/package.json @@ -30,10 +30,10 @@ "@playwright/test": "^1.47.1", "@sveltejs/adapter-auto": "^3.2.5", "@sveltejs/enhanced-img": "^0.3.8", - "@sveltejs/kit": "^2.6.0", + "@sveltejs/kit": "^2.6.1", "@sveltejs/vite-plugin-svelte": "4.0.0-next.7", "@types/cookie": "^0.6.0", - "@types/node": "^20.16.9", + "@types/node": "^20.16.10", "@types/pg": "^8.11.10", "@types/qrcode": "^1.5.5", "@typescript-eslint/eslint-plugin": "^7.18.0", @@ -60,7 +60,7 @@ "svelte-headless-table": "^0.18.2", "svelte-meta-tags": "^3.1.4", "svelte-preprocess": "^6.0.3", - "svelte-sequential-preprocessor": "^2.0.1", + "svelte-sequential-preprocessor": "^2.0.2", "sveltekit-flash-message": "^2.4.4", "sveltekit-superforms": "^2.18.1", "tailwindcss": "^3.4.13", @@ -97,7 +97,7 @@ "@types/feather-icons": "^4.29.4", "bits-ui": "^0.21.13", "boardgamegeekclient": "^1.9.1", - "bullmq": "^5.13.1", + "bullmq": "^5.14.0", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "cookie": "^0.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index de85c4f..453dea3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -64,10 +64,10 @@ importers: version: 2.2.2 '@sveltejs/adapter-node': specifier: ^5.2.5 - version: 5.2.5(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1))) + version: 5.2.5(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1))) '@sveltejs/adapter-vercel': specifier: ^5.4.4 - version: 5.4.4(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1))) + version: 5.4.4(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1))) '@types/feather-icons': specifier: ^4.29.4 version: 4.29.4 @@ -78,8 +78,8 @@ importers: specifier: ^1.9.1 version: 1.9.1 bullmq: - specifier: ^5.13.1 - version: 5.13.2 + specifier: ^5.14.0 + version: 5.14.0 class-variance-authority: specifier: ^0.7.0 version: 0.7.0 @@ -106,7 +106,7 @@ importers: version: 4.29.2 formsnap: specifier: ^1.0.1 - version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)) + version: 1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)) handlebars: specifier: ^4.7.8 version: 4.7.8 @@ -169,10 +169,10 @@ importers: version: 2.5.2 tailwind-variants: specifier: ^0.2.1 - version: 0.2.1(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2))) + version: 0.2.1(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))) tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2))) + version: 1.0.7(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))) tsyringe: specifier: ^4.8.0 version: 4.8.0 @@ -197,22 +197,22 @@ importers: version: 1.47.2 '@sveltejs/adapter-auto': specifier: ^3.2.5 - version: 3.2.5(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1))) + version: 3.2.5(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1))) '@sveltejs/enhanced-img': specifier: ^0.3.8 - version: 0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) + version: 0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)) '@sveltejs/kit': - specifier: ^2.6.0 - version: 2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) + specifier: ^2.6.1 + version: 2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)) '@sveltejs/vite-plugin-svelte': specifier: 4.0.0-next.7 - version: 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) + version: 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)) '@types/cookie': specifier: ^0.6.0 version: 0.6.0 '@types/node': - specifier: ^20.16.9 - version: 20.16.9 + specifier: ^20.16.10 + version: 20.16.10 '@types/pg': specifier: ^8.11.10 version: 8.11.10 @@ -242,7 +242,7 @@ importers: version: 9.1.0(eslint@8.57.1) eslint-plugin-svelte: specifier: 2.36.0-next.13 - version: 2.36.0-next.13(eslint@8.57.1)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)) + version: 2.36.0-next.13(eslint@8.57.1)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2)) just-clone: specifier: ^6.2.0 version: 6.2.0 @@ -292,20 +292,20 @@ importers: specifier: ^6.0.3 version: 6.0.3(postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1))(postcss@8.4.47)(sass@1.79.1)(svelte@5.0.0-next.175)(typescript@5.6.2) svelte-sequential-preprocessor: - specifier: ^2.0.1 - version: 2.0.1 + specifier: ^2.0.2 + version: 2.0.2 sveltekit-flash-message: specifier: ^2.4.4 - version: 2.4.4(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175) + version: 2.4.4(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175) sveltekit-superforms: specifier: ^2.18.1 - version: 2.19.0(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) + version: 2.19.0(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) tailwindcss: specifier: ^3.4.13 - version: 3.4.13(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)) + version: 3.4.13(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2)) ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.16.9)(typescript@5.6.2) + version: 10.9.2(@types/node@20.16.10)(typescript@5.6.2) tslib: specifier: ^2.7.0 version: 2.7.0 @@ -317,10 +317,10 @@ importers: version: 5.6.2 vite: specifier: ^5.4.8 - version: 5.4.8(@types/node@20.16.9)(sass@1.79.1) + version: 5.4.8(@types/node@20.16.10)(sass@1.79.1) vitest: specifier: ^1.6.0 - version: 1.6.0(@types/node@20.16.9)(sass@1.79.1) + version: 1.6.0(@types/node@20.16.10)(sass@1.79.1) zod: specifier: ^3.23.8 version: 3.23.8 @@ -2020,8 +2020,8 @@ packages: svelte: ^4.0.0 || ^5.0.0-next.0 vite: '>= 5.0.0' - '@sveltejs/kit@2.6.0': - resolution: {integrity: sha512-oG8cCAopDQavdN+RbzanNpfyUWsTbZ2Nt1zNioBm8thXLo1/8VtwP/KvlJW2HgrdN235NI4IL5bSZjTEXKuifQ==} + '@sveltejs/kit@2.6.1': + resolution: {integrity: sha512-QFlch3GPGZYidYhdRAub0fONw8UTguPICFHUSPxNkA/jdlU1p6C6yqq19J1QWdxIHS2El/ycDCGrHb3EAiMNqg==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -2080,8 +2080,8 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@20.16.9': - resolution: {integrity: sha512-rkvIVJxsOfBejxK7I0FO5sa2WxFmJCzoDwcd88+fq/CUfynNywTo/1/T6hyFz22CyztsnLS9nVlHOnTI36RH5w==} + '@types/node@20.16.10': + resolution: {integrity: sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==} '@types/pg@8.11.10': resolution: {integrity: sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==} @@ -2366,8 +2366,8 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - bullmq@5.13.2: - resolution: {integrity: sha512-McGE8k3mrCvdUHdU0sHkTKDS1xr4pff+hbEKBY51wk5S6Za0gkuejYA620VQTo3Zz37E/NVWMgumwiXPQ3yZcA==} + bullmq@5.14.0: + resolution: {integrity: sha512-qxZHtRuGEp0oHM1aNokuZ4gA0xr6vcZQPe1OLuQoDTuhaEXB4faxApUoo85v/PHnzrniAAqNT9kqD+UBbmECDQ==} bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} @@ -4476,8 +4476,8 @@ packages: peerDependencies: svelte: ^4.0.0 - svelte-sequential-preprocessor@2.0.1: - resolution: {integrity: sha512-N5JqlBni6BzElxmuFrOPxOJnjsxh1cFDACLEVKs8OHBcx8ZNRO1p5SxuQex1m3qbLzAC8G99EHeWcxGkjyKjLQ==} + svelte-sequential-preprocessor@2.0.2: + resolution: {integrity: sha512-DIFm0kSNscVxtBmKkBiygAHB5otoqN1aVmJ3t57jZhJfCB7Np/lUSoTtSrvPFjmlBbMeOsb1VQ06cut1+rBYOg==} engines: {node: '>=16'} svelte-subscribe@2.0.1: @@ -4617,9 +4617,6 @@ packages: tslib@2.4.0: resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} - tslib@2.6.3: - resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} - tslib@2.7.0: resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} @@ -6175,41 +6172,41 @@ snapshots: '@sodaru/yup-to-json-schema@2.0.1': optional: true - '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))': + '@sveltejs/adapter-auto@3.2.5(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))': dependencies: - '@sveltejs/kit': 2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) + '@sveltejs/kit': 2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)) import-meta-resolve: 4.1.0 - '@sveltejs/adapter-node@5.2.5(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))': + '@sveltejs/adapter-node@5.2.5(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))': dependencies: '@rollup/plugin-commonjs': 28.0.0(rollup@4.21.2) '@rollup/plugin-json': 6.1.0(rollup@4.21.2) '@rollup/plugin-node-resolve': 15.3.0(rollup@4.21.2) - '@sveltejs/kit': 2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) + '@sveltejs/kit': 2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)) rollup: 4.21.2 - '@sveltejs/adapter-vercel@5.4.4(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))': + '@sveltejs/adapter-vercel@5.4.4(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))': dependencies: - '@sveltejs/kit': 2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) + '@sveltejs/kit': 2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)) '@vercel/nft': 0.27.4 esbuild: 0.21.5 transitivePeerDependencies: - encoding - supports-color - '@sveltejs/enhanced-img@0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1))': + '@sveltejs/enhanced-img@0.3.8(rollup@4.21.2)(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1))': dependencies: magic-string: 0.30.11 svelte: 5.0.0-next.175 svelte-parse-markup: 0.1.5(svelte@5.0.0-next.175) - vite: 5.4.8(@types/node@20.16.9)(sass@1.79.1) + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.1) vite-imagetools: 7.0.4(rollup@4.21.2) transitivePeerDependencies: - rollup - '@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1))': + '@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.1.1 @@ -6223,27 +6220,27 @@ snapshots: sirv: 2.0.4 svelte: 5.0.0-next.175 tiny-glob: 0.2.9 - vite: 5.4.8(@types/node@20.16.9)(sass@1.79.1) + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.1) - '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1))': + '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)) debug: 4.3.6 svelte: 5.0.0-next.175 - vite: 5.4.8(@types/node@20.16.9)(sass@1.79.1) + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.1) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1))': + '@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) + '@sveltejs/vite-plugin-svelte-inspector': 3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)) debug: 4.3.6 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.11 svelte: 5.0.0-next.175 - vite: 5.4.8(@types/node@20.16.9)(sass@1.79.1) - vitefu: 1.0.2(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.1) + vitefu: 1.0.2(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)) transitivePeerDependencies: - supports-color @@ -6280,19 +6277,19 @@ snapshots: '@types/json-schema@7.0.15': optional: true - '@types/node@20.16.9': + '@types/node@20.16.10': dependencies: undici-types: 6.19.8 '@types/pg@8.11.10': dependencies: - '@types/node': 20.16.9 + '@types/node': 20.16.10 pg-protocol: 1.6.1 pg-types: 4.0.2 '@types/pg@8.11.6': dependencies: - '@types/node': 20.16.9 + '@types/node': 20.16.10 pg-protocol: 1.6.1 pg-types: 4.0.2 @@ -6300,7 +6297,7 @@ snapshots: '@types/qrcode@1.5.5': dependencies: - '@types/node': 20.16.9 + '@types/node': 20.16.10 '@types/resolve@1.20.2': {} @@ -6634,7 +6631,7 @@ snapshots: buffer-from@1.1.2: {} - bullmq@5.13.2: + bullmq@5.14.0: dependencies: cron-parser: 4.9.0 ioredis: 5.4.1 @@ -7060,7 +7057,7 @@ snapshots: dependencies: eslint: 8.57.1 - eslint-plugin-svelte@2.36.0-next.13(eslint@8.57.1)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)): + eslint-plugin-svelte@2.36.0-next.13(eslint@8.57.1)(svelte@5.0.0-next.175)(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2)): dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) '@jridgewell/sourcemap-codec': 1.5.0 @@ -7070,7 +7067,7 @@ snapshots: esutils: 2.0.3 known-css-properties: 0.30.0 postcss: 8.4.47 - postcss-load-config: 3.1.4(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)) + postcss-load-config: 3.1.4(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2)) postcss-safe-parser: 6.0.0(postcss@8.4.47) postcss-selector-parser: 6.1.2 semver: 7.6.3 @@ -7296,11 +7293,11 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)): + formsnap@1.0.1(svelte@5.0.0-next.175)(sveltekit-superforms@2.19.0(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175)): dependencies: nanoid: 5.0.7 svelte: 5.0.0-next.175 - sveltekit-superforms: 2.19.0(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) + sveltekit-superforms: 2.19.0(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175) forwarded@0.2.0: {} @@ -8153,21 +8150,21 @@ snapshots: '@csstools/utilities': 1.0.0(postcss@8.4.47) postcss: 8.4.47 - postcss-load-config@3.1.4(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)): + postcss-load-config@3.1.4(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2)): dependencies: lilconfig: 2.1.0 yaml: 1.10.2 optionalDependencies: postcss: 8.4.47 - ts-node: 10.9.2(@types/node@20.16.9)(typescript@5.6.2) + ts-node: 10.9.2(@types/node@20.16.10)(typescript@5.6.2) - postcss-load-config@4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)): + postcss-load-config@4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2)): dependencies: lilconfig: 3.1.2 yaml: 2.5.1 optionalDependencies: postcss: 8.4.47 - ts-node: 10.9.2(@types/node@20.16.9)(typescript@5.6.2) + ts-node: 10.9.2(@types/node@20.16.10)(typescript@5.6.2) postcss-load-config@5.1.0(jiti@1.21.6)(postcss@8.4.47)(tsx@4.19.1): dependencies: @@ -8779,10 +8776,10 @@ snapshots: svelte: 5.0.0-next.175 svelte-subscribe: 2.0.1(svelte@5.0.0-next.175) - svelte-sequential-preprocessor@2.0.1: + svelte-sequential-preprocessor@2.0.2: dependencies: svelte: 4.2.19 - tslib: 2.6.3 + tslib: 2.7.0 svelte-subscribe@2.0.1(svelte@5.0.0-next.175): dependencies: @@ -8825,14 +8822,14 @@ snapshots: magic-string: 0.30.11 zimmerframe: 1.1.2 - sveltekit-flash-message@2.4.4(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175): + sveltekit-flash-message@2.4.4(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) + '@sveltejs/kit': 2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)) svelte: 5.0.0-next.175 - sveltekit-superforms@2.19.0(@sveltejs/kit@2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): + sveltekit-superforms@2.19.0(@sveltejs/kit@2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(@types/json-schema@7.0.15)(svelte@5.0.0-next.175): dependencies: - '@sveltejs/kit': 2.6.0(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)) + '@sveltejs/kit': 2.6.1(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)))(svelte@5.0.0-next.175)(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)) devalue: 5.0.0 just-clone: 6.2.0 memoize-weak: 1.0.2 @@ -8861,16 +8858,16 @@ snapshots: tailwind-merge@2.5.2: {} - tailwind-variants@0.2.1(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2))): + tailwind-variants@0.2.1(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))): dependencies: tailwind-merge: 2.5.2 - tailwindcss: 3.4.13(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)) + tailwindcss: 3.4.13(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2)) - tailwindcss-animate@1.0.7(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2))): + tailwindcss-animate@1.0.7(tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2))): dependencies: - tailwindcss: 3.4.13(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)) + tailwindcss: 3.4.13(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2)) - tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)): + tailwindcss@3.4.13(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -8889,7 +8886,7 @@ snapshots: postcss: 8.4.47 postcss-import: 15.1.0(postcss@8.4.47) postcss-js: 4.0.1(postcss@8.4.47) - postcss-load-config: 4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2)) + postcss-load-config: 4.0.2(postcss@8.4.47)(ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2)) postcss-nested: 6.2.0(postcss@8.4.47) postcss-selector-parser: 6.1.2 resolve: 1.22.8 @@ -8954,14 +8951,14 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-node@10.9.2(@types/node@20.16.9)(typescript@5.6.2): + ts-node@10.9.2(@types/node@20.16.10)(typescript@5.6.2): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.16.9 + '@types/node': 20.16.10 acorn: 8.12.1 acorn-walk: 8.3.3 arg: 4.1.3 @@ -8977,8 +8974,6 @@ snapshots: tslib@2.4.0: optional: true - tslib@2.6.3: {} - tslib@2.7.0: {} tsx@4.19.1: @@ -9058,13 +9053,13 @@ snapshots: transitivePeerDependencies: - rollup - vite-node@1.6.0(@types/node@20.16.9)(sass@1.79.1): + vite-node@1.6.0(@types/node@20.16.10)(sass@1.79.1): dependencies: cac: 6.7.14 debug: 4.3.6 pathe: 1.1.2 picocolors: 1.1.0 - vite: 5.4.8(@types/node@20.16.9)(sass@1.79.1) + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.1) transitivePeerDependencies: - '@types/node' - less @@ -9076,21 +9071,21 @@ snapshots: - supports-color - terser - vite@5.4.8(@types/node@20.16.9)(sass@1.79.1): + vite@5.4.8(@types/node@20.16.10)(sass@1.79.1): dependencies: esbuild: 0.21.5 postcss: 8.4.47 rollup: 4.21.2 optionalDependencies: - '@types/node': 20.16.9 + '@types/node': 20.16.10 fsevents: 2.3.3 sass: 1.79.1 - vitefu@1.0.2(vite@5.4.8(@types/node@20.16.9)(sass@1.79.1)): + vitefu@1.0.2(vite@5.4.8(@types/node@20.16.10)(sass@1.79.1)): optionalDependencies: - vite: 5.4.8(@types/node@20.16.9)(sass@1.79.1) + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.1) - vitest@1.6.0(@types/node@20.16.9)(sass@1.79.1): + vitest@1.6.0(@types/node@20.16.10)(sass@1.79.1): dependencies: '@vitest/expect': 1.6.0 '@vitest/runner': 1.6.0 @@ -9109,11 +9104,11 @@ snapshots: strip-literal: 2.1.0 tinybench: 2.9.0 tinypool: 0.8.4 - vite: 5.4.8(@types/node@20.16.9)(sass@1.79.1) - vite-node: 1.6.0(@types/node@20.16.9)(sass@1.79.1) + vite: 5.4.8(@types/node@20.16.10)(sass@1.79.1) + vite-node: 1.6.0(@types/node@20.16.10)(sass@1.79.1) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 20.16.9 + '@types/node': 20.16.10 transitivePeerDependencies: - less - lightningcss diff --git a/src/lib/server/api/databases/seeds/roles.ts b/src/lib/server/api/databases/seeds/roles.ts index a299a94..1d5b0e7 100644 --- a/src/lib/server/api/databases/seeds/roles.ts +++ b/src/lib/server/api/databases/seeds/roles.ts @@ -1,5 +1,5 @@ -import * as schema from '$lib/server/api/databases/tables' -import type { db } from '$lib/server/api/packages/drizzle' +import type { db } from '../../packages/drizzle' +import * as schema from '../tables' import roles from './data/roles.json' export default async function seed(db: db) { diff --git a/src/lib/server/api/databases/seeds/users.ts b/src/lib/server/api/databases/seeds/users.ts index 49f2942..ee039f2 100644 --- a/src/lib/server/api/databases/seeds/users.ts +++ b/src/lib/server/api/databases/seeds/users.ts @@ -1,8 +1,8 @@ -import * as schema from '$lib/server/api/databases/tables' -import type { db } from '$lib/server/api/packages/drizzle' import { eq } from 'drizzle-orm' -import users from './data/users.json' +import type { db } from '../../packages/drizzle' import { HashingService } from '../../services/hashing.service' +import * as schema from '../tables' +import users from './data/users.json' type JsonRole = { name: string