mirror of
https://github.com/BradNut/boredgame
synced 2025-09-08 17:40:22 +00:00
Fixing all the root imports, installing and adding logging based on auth example.
This commit is contained in:
parent
f35bddc27b
commit
16aad6696d
33 changed files with 707 additions and 353 deletions
10
package.json
10
package.json
|
|
@ -17,14 +17,14 @@
|
|||
"seed": "ts-node --esm prisma/seed.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.34.1",
|
||||
"@playwright/test": "^1.34.3",
|
||||
"@rgossiaux/svelte-headlessui": "1.0.2",
|
||||
"@rgossiaux/svelte-heroicons": "^0.1.2",
|
||||
"@sveltejs/adapter-auto": "^1.0.3",
|
||||
"@sveltejs/adapter-vercel": "^1.0.6",
|
||||
"@sveltejs/kit": "^1.18.0",
|
||||
"@sveltejs/kit": "^1.19.0",
|
||||
"@types/cookie": "^0.5.1",
|
||||
"@types/node": "^18.16.14",
|
||||
"@types/node": "^18.16.16",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.7",
|
||||
"@typescript-eslint/parser": "^5.59.7",
|
||||
"autoprefixer": "^10.4.14",
|
||||
|
|
@ -52,12 +52,13 @@
|
|||
"ts-node": "^10.9.1",
|
||||
"tslib": "^2.5.2",
|
||||
"typescript": "^4.9.5",
|
||||
"vite": "^4.3.8",
|
||||
"vite": "^4.3.9",
|
||||
"vitest": "^0.25.3",
|
||||
"zod": "^3.21.4"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@axiomhq/axiom-node": "^0.12.0",
|
||||
"@fontsource/fira-mono": "^4.5.10",
|
||||
"@iconify-icons/line-md": "^1.2.22",
|
||||
"@iconify-icons/mdi": "^1.2.46",
|
||||
|
|
@ -76,6 +77,7 @@
|
|||
"open-props": "^1.5.8",
|
||||
"svelte-lazy": "^1.2.1",
|
||||
"svelte-lazy-loader": "^1.0.0",
|
||||
"sveltekit-flash-message": "^0.11.3",
|
||||
"zod-to-json-schema": "^3.21.1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
333
pnpm-lock.yaml
333
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
|
@ -55,4 +55,99 @@ model AuthKey {
|
|||
enum Role {
|
||||
USER
|
||||
ADMIN
|
||||
}
|
||||
}
|
||||
|
||||
model Game {
|
||||
id String @id
|
||||
name String
|
||||
description String?
|
||||
yearPublished Int?
|
||||
minPlayers Int?
|
||||
maxPlayers Int?
|
||||
minPlaytime Int?
|
||||
maxPlaytime Int?
|
||||
minAge Int?
|
||||
imageUrl String?
|
||||
thumbUrl String?
|
||||
url String?
|
||||
rulesUrl String?
|
||||
weightAmount Float?
|
||||
weightUnits String?
|
||||
bggId String?
|
||||
bggUrl String?
|
||||
primaryPublisher Publisher?
|
||||
categories Category[]
|
||||
mechanics Mechanic[]
|
||||
designers Designer[]
|
||||
publishers Publisher[]
|
||||
artists Artist[]
|
||||
names String[] @db.Array
|
||||
expansions Expansion[]
|
||||
|
||||
@@index([game_id])
|
||||
@@map("games")
|
||||
}
|
||||
|
||||
model Publisher {
|
||||
id String @id
|
||||
name String
|
||||
games Game[] @relation(references: [id], fields: [game_id])
|
||||
primaryPublisher Game[] @relation("PrimaryPublisher")
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@map("publishers")
|
||||
}
|
||||
|
||||
model Category {
|
||||
id String @id
|
||||
name String
|
||||
slug String
|
||||
games Game[] @relation("GameCategories")
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@map("categories")
|
||||
}
|
||||
|
||||
model Mechanic {
|
||||
id String @id
|
||||
name String
|
||||
games Game[] @relation("GameMechanics")
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@map("mechanics")
|
||||
}
|
||||
|
||||
model Designer {
|
||||
id String @id
|
||||
name String
|
||||
games Game[] @relation("GameDesigners")
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@map("designers")
|
||||
}
|
||||
|
||||
model Artist {
|
||||
id String @id
|
||||
name String
|
||||
games Game[] @relation("GameArtists")
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@map("artists")
|
||||
}
|
||||
|
||||
model Expansion {
|
||||
id String @id
|
||||
name String
|
||||
yearPublished Int?
|
||||
baseGame Game? @relation("Expansions", fields: [baseGameId], references: [id])
|
||||
baseGameId String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@map("expansions")
|
||||
}
|
||||
|
|
|
|||
13
src/app.d.ts
vendored
13
src/app.d.ts
vendored
|
|
@ -4,9 +4,22 @@
|
|||
// src/app.d.ts
|
||||
declare global {
|
||||
namespace App {
|
||||
interface PageData {
|
||||
flash?: { type: 'success' | 'error'; message: string };
|
||||
}
|
||||
interface Locals {
|
||||
auth: import('lucia-auth').AuthRequest;
|
||||
user: Lucia.UserAttributes;
|
||||
startTimer: number;
|
||||
error: string;
|
||||
errorId: string;
|
||||
errorStackTrace: string;
|
||||
message: unknown;
|
||||
track: unknown;
|
||||
}
|
||||
interface Error {
|
||||
code?: string;
|
||||
errorId?: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,33 @@
|
|||
import { redirect, type Handle } from '@sveltejs/kit';
|
||||
import type { HandleServerError } from '@sveltejs/kit';
|
||||
import { auth } from '$lib/server/lucia';
|
||||
import log from '$lib/server/log';
|
||||
import { dev } from '$app/environment';
|
||||
|
||||
export const handleError: HandleServerError = async ({ error, event }) => {
|
||||
const errorId = crypto.randomUUID();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
event.locals.error = error?.toString() || undefined;
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
event.locals.errorStackTrace = error?.stack || undefined;
|
||||
event.locals.errorId = errorId;
|
||||
if (!dev) {
|
||||
log(500, event);
|
||||
}
|
||||
|
||||
return {
|
||||
message: 'An unexpected error occurred.',
|
||||
errorId
|
||||
};
|
||||
};
|
||||
|
||||
export const handle: Handle = async ({ event, resolve }) => {
|
||||
const startTimer = Date.now();
|
||||
event.locals.startTimer = startTimer;
|
||||
|
||||
event.locals.auth = auth.handleRequest(event);
|
||||
console.log(JSON.stringify(event));
|
||||
if (event.locals?.auth) {
|
||||
|
|
@ -13,5 +39,9 @@ export const handle: Handle = async ({ event, resolve }) => {
|
|||
}
|
||||
}
|
||||
|
||||
return await resolve(event);
|
||||
const response = await resolve(event);
|
||||
if (!dev) {
|
||||
log(response.status, event);
|
||||
}
|
||||
return response;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
DialogOverlay,
|
||||
DialogTitle
|
||||
} from '@rgossiaux/svelte-headlessui';
|
||||
import { boredState } from '$root/lib/stores/boredState';
|
||||
import { collectionStore } from '$root/lib/stores/collectionStore';
|
||||
import { boredState } from '$lib/stores/boredState';
|
||||
import { collectionStore } from '$lib/stores/collectionStore';
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
function clearCollection() {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { browser } from '$app/environment';
|
||||
import { boredState } from '$root/lib/stores/boredState';
|
||||
import { wishlistStore } from '$root/lib/stores/wishlistStore';
|
||||
import { boredState } from '$lib/stores/boredState';
|
||||
import { wishlistStore } from '$lib/stores/wishlistStore';
|
||||
import DefaultDialog from './DefaultDialog.svelte';
|
||||
|
||||
function clearWishlist() {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
DialogOverlay,
|
||||
DialogTitle
|
||||
} from '@rgossiaux/svelte-headlessui';
|
||||
import { boredState } from '$root/lib/stores/boredState';
|
||||
import { boredState } from '$lib/stores/boredState';
|
||||
|
||||
export let title: string;
|
||||
export let description: string;
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
DialogOverlay,
|
||||
DialogTitle
|
||||
} from '@rgossiaux/svelte-headlessui';
|
||||
import { boredState } from '$root/lib/stores/boredState';
|
||||
import { collectionStore } from '$root/lib/stores/collectionStore';
|
||||
import { removeFromCollection } from '$root/lib/util/manipulateCollection';
|
||||
import { boredState } from '$lib/stores/boredState';
|
||||
import { collectionStore } from '$lib/stores/collectionStore';
|
||||
import { removeFromCollection } from '$lib/util/manipulateCollection';
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
function removeGame() {
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
DialogOverlay,
|
||||
DialogTitle
|
||||
} from '@rgossiaux/svelte-headlessui';
|
||||
import { boredState } from '$root/lib/stores/boredState';
|
||||
import { wishlistStore } from '$root/lib/stores/wishlistStore';
|
||||
import { removeFromWishlist } from '$root/lib/util/manipulateWishlist';
|
||||
import { boredState } from '$lib/stores/boredState';
|
||||
import { wishlistStore } from '$lib/stores/wishlistStore';
|
||||
import { removeFromWishlist } from '$lib/util/manipulateWishlist';
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
function removeGame() {
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
import Button from '$lib/components/button/index.svelte';
|
||||
import type { GameType, SavedGameType } from '$lib/types';
|
||||
import { collectionStore } from '$lib/stores/collectionStore';
|
||||
import { wishlistStore } from '$root/lib/stores/wishlistStore';
|
||||
import { wishlistStore } from '$lib/stores/wishlistStore';
|
||||
import { addToCollection, removeFromCollection } from '$lib/util/manipulateCollection';
|
||||
import { addToWishlist } from '$lib/util/manipulateWishlist';
|
||||
import { browser } from '$app/environment';
|
||||
import { binarySearchOnStore } from '$root/lib/util/binarySearchOnStore';
|
||||
import { convertToSavedGame } from '$root/lib/util/gameMapper';
|
||||
import { binarySearchOnStore } from '$lib/util/binarySearchOnStore';
|
||||
import { convertToSavedGame } from '$lib/util/gameMapper';
|
||||
|
||||
export let game: GameType | SavedGameType;
|
||||
export let detailed: boolean = false;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { browser } from '$app/environment';
|
||||
import { boredState } from '$root/lib/stores/boredState';
|
||||
import { collectionStore } from '$root/lib/stores/collectionStore';
|
||||
import { ToastType } from '$root/lib/types';
|
||||
import { boredState } from '$lib/stores/boredState';
|
||||
import { collectionStore } from '$lib/stores/collectionStore';
|
||||
import { ToastType } from '$lib/types';
|
||||
import { SaveIcon, ShareIcon, TrashIcon } from '@rgossiaux/svelte-heroicons/outline';
|
||||
import ClearCollectionDialog from '../dialog/ClearCollectionDialog.svelte';
|
||||
import { toast } from '../toast/toast';
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { browser } from '$app/environment';
|
||||
import { boredState } from '$root/lib/stores/boredState';
|
||||
import { wishlistStore } from '$root/lib/stores/wishlistStore';
|
||||
import { ToastType } from '$root/lib/types';
|
||||
import { boredState } from '$lib/stores/boredState';
|
||||
import { wishlistStore } from '$lib/stores/wishlistStore';
|
||||
import { ToastType } from '$lib/types';
|
||||
import { SaveIcon, ShareIcon, TrashIcon } from '@rgossiaux/svelte-heroicons/outline';
|
||||
import ClearWishlistDialog from '../dialog/ClearWishlistDialog.svelte';
|
||||
import { toast } from '../toast/toast';
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
import { collectionStore } from '$lib/stores/collectionStore';
|
||||
import { toast } from '$lib/components/toast/toast';
|
||||
import { ToastType, type SavedGameType } from '$lib/types';
|
||||
import { mapSavedGameToGame } from '$root/lib/util/gameMapper';
|
||||
import { mapSavedGameToGame } from '$lib/util/gameMapper';
|
||||
|
||||
async function getRandomCollectionGame() {
|
||||
if ($collectionStore.length > 0) {
|
||||
|
|
|
|||
|
|
@ -21,15 +21,15 @@
|
|||
cancel();
|
||||
}
|
||||
},
|
||||
onUpdated: ({ form }) => {
|
||||
if ($gameStore.length <= 0) {
|
||||
toast.send('No results found 😿', {
|
||||
duration: 3000,
|
||||
type: ToastType.ERROR,
|
||||
dismissible: true
|
||||
});
|
||||
}
|
||||
}
|
||||
// onUpdated: ({ form }) => {
|
||||
// if ($gameStore.length <= 0) {
|
||||
// toast.send('No results found 😿', {
|
||||
// duration: 3000,
|
||||
// type: ToastType.ERROR,
|
||||
// dismissible: true
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
});
|
||||
|
||||
let submitting = $boredState?.loading;
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@
|
|||
import { boredState } from '$lib/stores/boredState';
|
||||
import AdvancedSearch from '$lib/components/search/advancedSearch/index.svelte';
|
||||
import { xl, md, sm } from '$lib/stores/mediaQueryStore';
|
||||
import { gameStore } from '$root/lib/stores/gameSearchStore';
|
||||
import { gameStore } from '$lib/stores/gameSearchStore';
|
||||
import { toast } from '../../toast/toast';
|
||||
import Pagination from '$lib/components/pagination/index.svelte';
|
||||
import Game from '$lib/components/game/index.svelte';
|
||||
import { ToastType, type GameType, type SavedGameType } from '$root/lib/types';
|
||||
import { ToastType, type GameType, type SavedGameType } from '$lib/types';
|
||||
import SkeletonPlaceholder from '../../SkeletonPlaceholder.svelte';
|
||||
import RemoveCollectionDialog from '../../dialog/RemoveCollectionDialog.svelte';
|
||||
import RemoveWishlistDialog from '../../dialog/RemoveWishlistDialog.svelte';
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { dev } from '$app/environment';
|
||||
export const BASE_URL = dev ? 'http://localhost:5173' : 'https://boredgame.vercel.app';
|
||||
export const APP_NAME = 'Bored Game';
|
||||
export const DOMAIN = 'boredgame.vercel.app';
|
||||
|
|
|
|||
70
src/lib/server/log.ts
Normal file
70
src/lib/server/log.ts
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import { Client } from '@axiomhq/axiom-node';
|
||||
import { AXIOM_TOKEN, AXIOM_ORG_ID, AXIOM_DATASET } from '$env/static/private';
|
||||
import getAllUrlParams from '$lib/util/getAllUrlParams';
|
||||
import parseTrack from '$lib/util/parseTrack';
|
||||
import parseMessage from '$lib/util/parseMessage';
|
||||
import { DOMAIN } from '$lib/config/constants';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
export default async function log(statusCode: number, event) {
|
||||
try {
|
||||
let level = 'info';
|
||||
if (statusCode >= 400) {
|
||||
level = 'error';
|
||||
}
|
||||
const error = event?.locals?.error || undefined;
|
||||
const errorId = event?.locals?.errorId || undefined;
|
||||
const errorStackTrace = event?.locals?.errorStackTrace || undefined;
|
||||
let urlParams = {};
|
||||
if (event?.url?.search) {
|
||||
urlParams = await getAllUrlParams(event?.url?.search);
|
||||
}
|
||||
let messageEvents = {};
|
||||
if (event?.locals?.message) {
|
||||
messageEvents = await parseMessage(event?.locals?.message);
|
||||
}
|
||||
let trackEvents = {};
|
||||
if (event?.locals?.track) {
|
||||
trackEvents = await parseTrack(event?.locals?.track);
|
||||
}
|
||||
|
||||
let referer = event.request.headers.get('referer');
|
||||
if (referer) {
|
||||
const refererUrl = await new URL(referer);
|
||||
const refererHostname = refererUrl.hostname;
|
||||
if (refererHostname === 'localhost' || refererHostname === DOMAIN) {
|
||||
referer = refererUrl.pathname;
|
||||
}
|
||||
} else {
|
||||
referer = undefined;
|
||||
}
|
||||
const logData: object = {
|
||||
level: level,
|
||||
method: event.request.method,
|
||||
path: event.url.pathname,
|
||||
status: statusCode,
|
||||
timeInMs: Date.now() - event?.locals?.startTimer,
|
||||
user: event?.locals?.user?.email,
|
||||
userId: event?.locals?.user?.userId,
|
||||
referer: referer,
|
||||
error: error,
|
||||
errorId: errorId,
|
||||
errorStackTrace: errorStackTrace,
|
||||
...urlParams,
|
||||
...messageEvents,
|
||||
...trackEvents
|
||||
};
|
||||
console.log('log: ', JSON.stringify(logData));
|
||||
if (!AXIOM_TOKEN || !AXIOM_ORG_ID || !AXIOM_DATASET) {
|
||||
return;
|
||||
}
|
||||
const client = new Client({
|
||||
token: AXIOM_TOKEN,
|
||||
orgId: AXIOM_ORG_ID
|
||||
});
|
||||
await client.ingestEvents(AXIOM_DATASET, [logData]);
|
||||
} catch (err) {
|
||||
throw new Error(`Error Logger: ${JSON.stringify(err)}`);
|
||||
}
|
||||
}
|
||||
11
src/lib/util/getAllUrlParams.ts
Normal file
11
src/lib/util/getAllUrlParams.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
export default async function getAllUrlParams(url: string): Promise<object> {
|
||||
let paramsObj = {};
|
||||
try {
|
||||
url = url?.slice(1); // remove leading ?
|
||||
if (!url) return {}; // if no params return
|
||||
paramsObj = await Object.fromEntries(await new URLSearchParams(url));
|
||||
} catch (error) {
|
||||
console.log('error: ', error);
|
||||
}
|
||||
return paramsObj;
|
||||
}
|
||||
15
src/lib/util/parseMessage.ts
Normal file
15
src/lib/util/parseMessage.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
export default async function parseMessage(message: unknown): Promise<object> {
|
||||
let messageObj = {};
|
||||
try {
|
||||
if (message) {
|
||||
if (typeof message === 'string') {
|
||||
messageObj = { message: message };
|
||||
} else {
|
||||
messageObj = message;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('error: ', error);
|
||||
}
|
||||
return messageObj;
|
||||
}
|
||||
15
src/lib/util/parseTrack.ts
Normal file
15
src/lib/util/parseTrack.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
export default async function parseTrack(track: unknown): Promise<object> {
|
||||
let trackObj = {};
|
||||
try {
|
||||
if (track) {
|
||||
if (typeof track === 'string') {
|
||||
trackObj = { track: track };
|
||||
} else {
|
||||
trackObj = track;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('error: ', error);
|
||||
}
|
||||
return trackObj;
|
||||
}
|
||||
|
|
@ -1,4 +1,20 @@
|
|||
<h1>The page you requested doesn't exist! 🤷♂️</h1>
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{#if $page.status === 404}
|
||||
<h1>The page you requested doesn't exist! 🤷♂️</h1>
|
||||
<h3 class="mt-6"><a href="/">Go Home</a></h3>
|
||||
{:else}
|
||||
<h1 class="h1">Unexpected Error</h1>
|
||||
<h3 class="mt-6">We're investigating the issue.</h3>
|
||||
{/if}
|
||||
|
||||
{#if $page.error?.errorId}
|
||||
<p class="mt-6">Error ID: {$page.error.errorId}</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
import Portal from '$lib/Portal.svelte';
|
||||
import { boredState } from '$lib/stores/boredState';
|
||||
import { collectionStore } from '$lib/stores/collectionStore';
|
||||
import { wishlistStore } from '$root/lib/stores/wishlistStore';
|
||||
import { wishlistStore } from '$lib/stores/wishlistStore';
|
||||
import { gameStore } from '$lib/stores/gameSearchStore';
|
||||
import { toast } from '$lib/components/toast/toast';
|
||||
import Toast from '$lib/components/toast/Toast.svelte';
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ import { search_schema } from '$lib/zodValidation';
|
|||
|
||||
export const load = async ({ fetch, url }) => {
|
||||
const formData = Object.fromEntries(url?.searchParams);
|
||||
console.log('formData', formData);
|
||||
formData.name = formData?.q;
|
||||
const form = await superValidate(formData, search_schema);
|
||||
console.log('form', form);
|
||||
return { form };
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@ export const load = async (event) => {
|
|||
if (session) {
|
||||
throw redirect(302, '/');
|
||||
}
|
||||
const form = await superValidate(event, signInSchema);
|
||||
return {
|
||||
form
|
||||
};
|
||||
// const form = await superValidate(event, signInSchema);
|
||||
// return {
|
||||
// form
|
||||
// };
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
|
|
@ -24,6 +24,7 @@ export const actions = {
|
|||
const form = await superValidate(event, signInSchema);
|
||||
|
||||
if (!form.valid) {
|
||||
form.data.password = '';
|
||||
return fail(400, {
|
||||
form
|
||||
});
|
||||
|
|
@ -31,16 +32,17 @@ export const actions = {
|
|||
|
||||
// Adding user to the db
|
||||
try {
|
||||
console.log('sign in user');
|
||||
const key = await auth.useKey('username', form.data.username, form.data.password);
|
||||
const session = await auth.createSession(key.userId);
|
||||
event.locals.auth.setSession(session);
|
||||
} catch (e) {
|
||||
// TODO: need to return error message to the client
|
||||
console.error(e);
|
||||
form.data.password = '';
|
||||
return setError(form, null, 'The username or password is incorrect.');
|
||||
}
|
||||
|
||||
form.data.username = '';
|
||||
form.data.password = '';
|
||||
return { form };
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
const { form, errors, enhance, delayed } = superForm(data.form, {
|
||||
taintedMessage: null,
|
||||
validators: signInSchema,
|
||||
validationMethod: 'oninput',
|
||||
delayMs: 0,
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { userSchema } from '$root/lib/config/zod-schemas.js';
|
||||
import { userSchema } from '$lib/config/zod-schemas.js';
|
||||
import { superForm } from 'sveltekit-superforms/client';
|
||||
|
||||
export let data;
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
import { tick, onDestroy } from 'svelte';
|
||||
import Game from '$lib/components/game/index.svelte';
|
||||
import { collectionStore } from '$lib/stores/collectionStore';
|
||||
import type { GameType, SavedGameType } from '$root/lib/types';
|
||||
import { boredState } from '$root/lib/stores/boredState';
|
||||
import Pagination from '$root/lib/components/pagination/index.svelte';
|
||||
import RemoveCollectionDialog from '$root/lib/components/dialog/RemoveCollectionDialog.svelte';
|
||||
import RemoveWishlistDialog from '$root/lib/components/dialog/RemoveWishlistDialog.svelte';
|
||||
import { createSearchStore, searchHandler } from '$root/lib/stores/search';
|
||||
import type { GameType, SavedGameType } from '$lib/types';
|
||||
import { boredState } from '$lib/stores/boredState';
|
||||
import Pagination from '$lib/components/pagination/index.svelte';
|
||||
import RemoveCollectionDialog from '$lib/components/dialog/RemoveCollectionDialog.svelte';
|
||||
import RemoveWishlistDialog from '$lib/components/dialog/RemoveWishlistDialog.svelte';
|
||||
import { createSearchStore, searchHandler } from '$lib/stores/search';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
export let data: PageData;
|
||||
|
|
|
|||
|
|
@ -15,16 +15,16 @@
|
|||
import { collectionStore } from '$lib/stores/collectionStore';
|
||||
import { wishlistStore } from '$lib/stores/wishlistStore';
|
||||
import Button from '$lib/components/button/index.svelte';
|
||||
import RemoveCollectionDialog from '$root/lib/components/dialog/RemoveCollectionDialog.svelte';
|
||||
import RemoveCollectionDialog from '$lib/components/dialog/RemoveCollectionDialog.svelte';
|
||||
import { addToCollection } from '$lib/util/manipulateCollection';
|
||||
import type { PageData } from './$types';
|
||||
import { boredState } from '$root/lib/stores/boredState';
|
||||
import { boredState } from '$lib/stores/boredState';
|
||||
import { browser } from '$app/environment';
|
||||
import LinkWithIcon from '$root/lib/components/LinkWithIcon.svelte';
|
||||
import { addToWishlist } from '$root/lib/util/manipulateWishlist';
|
||||
import RemoveWishlistDialog from '$root/lib/components/dialog/RemoveWishlistDialog.svelte';
|
||||
import { binarySearchOnStore } from '$root/lib/util/binarySearchOnStore';
|
||||
import { convertToSavedGame } from '$root/lib/util/gameMapper';
|
||||
import LinkWithIcon from '$lib/components/LinkWithIcon.svelte';
|
||||
import { addToWishlist } from '$lib/util/manipulateWishlist';
|
||||
import RemoveWishlistDialog from '$lib/components/dialog/RemoveWishlistDialog.svelte';
|
||||
import { binarySearchOnStore } from '$lib/util/binarySearchOnStore';
|
||||
import { convertToSavedGame } from '$lib/util/gameMapper';
|
||||
|
||||
$: existsInCollection = $collectionStore.find((item: SavedGameType) => item.id === game.id);
|
||||
$: existsInWishlist = $wishlistStore.find((item: SavedGameType) => item.id === game.id);
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
import { tick, onDestroy } from 'svelte';
|
||||
import Game from '$lib/components/game/index.svelte';
|
||||
import { wishlistStore } from '$lib/stores/wishlistStore';
|
||||
import type { GameType, SavedGameType } from '$root/lib/types';
|
||||
import { boredState } from '$root/lib/stores/boredState';
|
||||
import Pagination from '$root/lib/components/pagination/index.svelte';
|
||||
import RemoveWishlistDialog from '$root/lib/components/dialog/RemoveWishlistDialog.svelte';
|
||||
import RemoveCollectionDialog from '$root/lib/components/dialog/RemoveCollectionDialog.svelte';
|
||||
import { createSearchStore, searchHandler } from '$root/lib/stores/search';
|
||||
import type { GameType, SavedGameType } from '$lib/types';
|
||||
import { boredState } from '$lib/stores/boredState';
|
||||
import Pagination from '$lib/components/pagination/index.svelte';
|
||||
import RemoveWishlistDialog from '$lib/components/dialog/RemoveWishlistDialog.svelte';
|
||||
import RemoveCollectionDialog from '$lib/components/dialog/RemoveCollectionDialog.svelte';
|
||||
import { createSearchStore, searchHandler } from '$lib/stores/search';
|
||||
|
||||
let gameToRemove: GameType | SavedGameType;
|
||||
let pageSize = 10;
|
||||
|
|
|
|||
|
|
@ -1,181 +1,181 @@
|
|||
import { invalid, type RequestEvent } from '@sveltejs/kit';
|
||||
import { BOARD_GAME_ATLAS_CLIENT_ID } from '$env/static/private';
|
||||
import type { GameType, SearchQuery } from "$root/lib/types";
|
||||
import { mapAPIGameToBoredGame } from "$root/lib/util/gameMapper";
|
||||
import type { GameType, SearchQuery } from '$lib/types';
|
||||
import { mapAPIGameToBoredGame } from '$lib/util/gameMapper';
|
||||
|
||||
interface Actions {
|
||||
[key: string]: any // Action
|
||||
[key: string]: any; // Action
|
||||
}
|
||||
|
||||
export const Games: Actions = {
|
||||
search: async ({ request, locals }: RequestEvent): Promise<any> => {
|
||||
console.log("In search action specific")
|
||||
// Do things in here
|
||||
const form = await request.formData();
|
||||
console.log('action form', form);
|
||||
const queryParams: SearchQuery = {
|
||||
order_by: 'rank',
|
||||
ascending: false,
|
||||
limit: 10,
|
||||
skip: 0,
|
||||
client_id: BOARD_GAME_ATLAS_CLIENT_ID,
|
||||
fuzzy_match: true,
|
||||
name: ''
|
||||
};
|
||||
search: async ({ request, locals }: RequestEvent): Promise<any> => {
|
||||
console.log('In search action specific');
|
||||
// Do things in here
|
||||
const form = await request.formData();
|
||||
console.log('action form', form);
|
||||
const queryParams: SearchQuery = {
|
||||
order_by: 'rank',
|
||||
ascending: false,
|
||||
limit: 10,
|
||||
skip: 0,
|
||||
client_id: BOARD_GAME_ATLAS_CLIENT_ID,
|
||||
fuzzy_match: true,
|
||||
name: ''
|
||||
};
|
||||
|
||||
const name = form.has('name') ? form.get('name') : await request?.text();
|
||||
console.log('name', name);
|
||||
if (name) {
|
||||
queryParams.name = `${name}`;
|
||||
}
|
||||
const name = form.has('name') ? form.get('name') : await request?.text();
|
||||
console.log('name', name);
|
||||
if (name) {
|
||||
queryParams.name = `${name}`;
|
||||
}
|
||||
|
||||
const newQueryParams: Record<string, string> = {};
|
||||
for (const key in queryParams) {
|
||||
console.log('key', key);
|
||||
console.log('queryParams[key]', queryParams[key]);
|
||||
newQueryParams[key] = `${queryParams[key]}`;
|
||||
}
|
||||
const newQueryParams: Record<string, string> = {};
|
||||
for (const key in queryParams) {
|
||||
console.log('key', key);
|
||||
console.log('queryParams[key]', queryParams[key]);
|
||||
newQueryParams[key] = `${queryParams[key]}`;
|
||||
}
|
||||
|
||||
const urlQueryParams = new URLSearchParams(newQueryParams);
|
||||
console.log('urlQueryParams', urlQueryParams);
|
||||
const urlQueryParams = new URLSearchParams(newQueryParams);
|
||||
console.log('urlQueryParams', urlQueryParams);
|
||||
|
||||
try {
|
||||
throw new Error("test error");
|
||||
// const url = `https://api.boardgameatlas.com/api/search${urlQueryParams ? `?${urlQueryParams}` : ''
|
||||
// }`;
|
||||
// const response = await fetch(url, {
|
||||
// method: 'get',
|
||||
// headers: {
|
||||
// 'content-type': 'application/json'
|
||||
// }
|
||||
// });
|
||||
// console.log('board game response', response);
|
||||
// if (response.status !== 200) {
|
||||
// console.log('Status not 200', response.status)
|
||||
// invalid(response.status, {});
|
||||
// }
|
||||
try {
|
||||
throw new Error('test error');
|
||||
// const url = `https://api.boardgameatlas.com/api/search${urlQueryParams ? `?${urlQueryParams}` : ''
|
||||
// }`;
|
||||
// const response = await fetch(url, {
|
||||
// method: 'get',
|
||||
// headers: {
|
||||
// 'content-type': 'application/json'
|
||||
// }
|
||||
// });
|
||||
// console.log('board game response', response);
|
||||
// if (response.status !== 200) {
|
||||
// console.log('Status not 200', response.status)
|
||||
// invalid(response.status, {});
|
||||
// }
|
||||
|
||||
// if (response.status === 200) {
|
||||
// const gameResponse = await response.json();
|
||||
// console.log('gameResponse', gameResponse);
|
||||
// const gameList = gameResponse?.games;
|
||||
// const totalCount = gameResponse?.count;
|
||||
// console.log('totalCount', totalCount);
|
||||
// const games: GameType[] = [];
|
||||
// gameList.forEach((game) => {
|
||||
// games.push(mapAPIGameToBoredGame(game));
|
||||
// });
|
||||
// if (response.status === 200) {
|
||||
// const gameResponse = await response.json();
|
||||
// console.log('gameResponse', gameResponse);
|
||||
// const gameList = gameResponse?.games;
|
||||
// const totalCount = gameResponse?.count;
|
||||
// console.log('totalCount', totalCount);
|
||||
// const games: GameType[] = [];
|
||||
// gameList.forEach((game) => {
|
||||
// games.push(mapAPIGameToBoredGame(game));
|
||||
// });
|
||||
|
||||
// console.log('returning from search')
|
||||
// console.log('returning from search')
|
||||
|
||||
// return {
|
||||
// games,
|
||||
// totalCount: games.length
|
||||
// };
|
||||
// }
|
||||
// return {
|
||||
// games,
|
||||
// totalCount: games.length
|
||||
// };
|
||||
// }
|
||||
|
||||
// return {
|
||||
// games: [],
|
||||
// totalCount: 0
|
||||
// };
|
||||
} catch (e) {
|
||||
console.log(`Error searching board games ${e}`);
|
||||
return invalid(400, { reason: 'Exception' })
|
||||
}
|
||||
}
|
||||
// return {
|
||||
// games: [],
|
||||
// totalCount: 0
|
||||
// };
|
||||
} catch (e) {
|
||||
console.log(`Error searching board games ${e}`);
|
||||
return invalid(400, { reason: 'Exception' });
|
||||
}
|
||||
}
|
||||
|
||||
// const id = form.get('id');
|
||||
// const ids = form.get('ids');
|
||||
// const minAge = form.get('minAge');
|
||||
// const minPlayers = form.get('minPlayers');
|
||||
// const maxPlayers = form.get('maxPlayers');
|
||||
// const exactMinAge = form.get('exactMinAge') || false;
|
||||
// const exactMinPlayers = form.get('exactMinPlayers') || false;
|
||||
// const exactMaxPlayers = form.get('exactMaxPlayers') || false;
|
||||
// const random = form.get('random') === 'on' || false;
|
||||
// const id = form.get('id');
|
||||
// const ids = form.get('ids');
|
||||
// const minAge = form.get('minAge');
|
||||
// const minPlayers = form.get('minPlayers');
|
||||
// const maxPlayers = form.get('maxPlayers');
|
||||
// const exactMinAge = form.get('exactMinAge') || false;
|
||||
// const exactMinPlayers = form.get('exactMinPlayers') || false;
|
||||
// const exactMaxPlayers = form.get('exactMaxPlayers') || false;
|
||||
// const random = form.get('random') === 'on' || false;
|
||||
|
||||
// if (minAge) {
|
||||
// if (exactMinAge) {
|
||||
// queryParams.min_age = +minAge;
|
||||
// } else {
|
||||
// queryParams.gt_min_age = +minAge === 1 ? 0 : +minAge - 1;
|
||||
// }
|
||||
// }
|
||||
// if (minAge) {
|
||||
// if (exactMinAge) {
|
||||
// queryParams.min_age = +minAge;
|
||||
// } else {
|
||||
// queryParams.gt_min_age = +minAge === 1 ? 0 : +minAge - 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (minPlayers) {
|
||||
// if (exactMinPlayers) {
|
||||
// queryParams.min_players = +minPlayers;
|
||||
// } else {
|
||||
// queryParams.gt_min_players = +minPlayers === 1 ? 0 : +minPlayers - 1;
|
||||
// }
|
||||
// }
|
||||
// if (minPlayers) {
|
||||
// if (exactMinPlayers) {
|
||||
// queryParams.min_players = +minPlayers;
|
||||
// } else {
|
||||
// queryParams.gt_min_players = +minPlayers === 1 ? 0 : +minPlayers - 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (maxPlayers) {
|
||||
// if (exactMaxPlayers) {
|
||||
// queryParams.max_players = +maxPlayers;
|
||||
// } else {
|
||||
// queryParams.lt_max_players = +maxPlayers + 1;
|
||||
// }
|
||||
// }
|
||||
// if (maxPlayers) {
|
||||
// if (exactMaxPlayers) {
|
||||
// queryParams.max_players = +maxPlayers;
|
||||
// } else {
|
||||
// queryParams.lt_max_players = +maxPlayers + 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (id) {
|
||||
// queryParams.ids = new Array(`${id}`);
|
||||
// }
|
||||
// if (id) {
|
||||
// queryParams.ids = new Array(`${id}`);
|
||||
// }
|
||||
|
||||
// if (ids) {
|
||||
// // TODO: Pass in ids array from localstorage / game store
|
||||
// queryParams.ids = new Array(ids);
|
||||
// }
|
||||
// if (ids) {
|
||||
// // TODO: Pass in ids array from localstorage / game store
|
||||
// queryParams.ids = new Array(ids);
|
||||
// }
|
||||
|
||||
// queryParams.random = random;
|
||||
// console.log('queryParams', queryParams);
|
||||
// queryParams.random = random;
|
||||
// console.log('queryParams', queryParams);
|
||||
|
||||
// const newQueryParams: Record<string, string> = {};
|
||||
// for (const key in queryParams) {
|
||||
// newQueryParams[key] = `${queryParams[key as keyof typeof queryParams]}`;
|
||||
// }
|
||||
// const newQueryParams: Record<string, string> = {};
|
||||
// for (const key in queryParams) {
|
||||
// newQueryParams[key] = `${queryParams[key as keyof typeof queryParams]}`;
|
||||
// }
|
||||
|
||||
// const urlQueryParams = new URLSearchParams(newQueryParams);
|
||||
// const urlQueryParams = new URLSearchParams(newQueryParams);
|
||||
|
||||
// const url = `https://api.boardgameatlas.com/api/search${urlQueryParams ? `?${urlQueryParams}` : ''
|
||||
// }`;
|
||||
// const response = await fetch(url, {
|
||||
// method: 'get',
|
||||
// headers: {
|
||||
// 'content-type': 'application/json'
|
||||
// }
|
||||
// });
|
||||
// console.log('response status', response.status);
|
||||
// console.log('board game response action', response);
|
||||
// if (response.status === 404) {
|
||||
// // user hasn't created a todo list.
|
||||
// // start with an empty array
|
||||
// return {
|
||||
// success: true,
|
||||
// games: [],
|
||||
// totalCount: 0
|
||||
// };
|
||||
// }
|
||||
// const url = `https://api.boardgameatlas.com/api/search${urlQueryParams ? `?${urlQueryParams}` : ''
|
||||
// }`;
|
||||
// const response = await fetch(url, {
|
||||
// method: 'get',
|
||||
// headers: {
|
||||
// 'content-type': 'application/json'
|
||||
// }
|
||||
// });
|
||||
// console.log('response status', response.status);
|
||||
// console.log('board game response action', response);
|
||||
// if (response.status === 404) {
|
||||
// // user hasn't created a todo list.
|
||||
// // start with an empty array
|
||||
// return {
|
||||
// success: true,
|
||||
// games: [],
|
||||
// totalCount: 0
|
||||
// };
|
||||
// }
|
||||
|
||||
// if (response.status === 200) {
|
||||
// const gameResponse = await response.json();
|
||||
// console.log('gameResponse', gameResponse);
|
||||
// const gameList = gameResponse?.games;
|
||||
// const games: GameType[] = [];
|
||||
// gameList.forEach((game: GameType) => {
|
||||
// games.push(mapAPIGameToBoredGame(game));
|
||||
// });
|
||||
// console.log('action games', games);
|
||||
// return {
|
||||
// games,
|
||||
// totalCount: games.length
|
||||
// };
|
||||
// }
|
||||
// if (response.status === 200) {
|
||||
// const gameResponse = await response.json();
|
||||
// console.log('gameResponse', gameResponse);
|
||||
// const gameList = gameResponse?.games;
|
||||
// const games: GameType[] = [];
|
||||
// gameList.forEach((game: GameType) => {
|
||||
// games.push(mapAPIGameToBoredGame(game));
|
||||
// });
|
||||
// console.log('action games', games);
|
||||
// return {
|
||||
// games,
|
||||
// totalCount: games.length
|
||||
// };
|
||||
// }
|
||||
|
||||
// return { success: false };
|
||||
// }
|
||||
// create: async function create({ request, locals }): Promise<any> {
|
||||
// const data = await getFormDataObject<any>(request);
|
||||
// return data;
|
||||
// }
|
||||
}
|
||||
// return { success: false };
|
||||
// }
|
||||
// create: async function create({ request, locals }): Promise<any> {
|
||||
// const data = await getFormDataObject<any>(request);
|
||||
// return data;
|
||||
// }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
@import 'reset.pcss';
|
||||
@import 'global.pcss';
|
||||
@import '$root/styles/theme.pcss';
|
||||
@import 'theme.pcss';
|
||||
|
|
|
|||
|
|
@ -14,20 +14,16 @@ const config = {
|
|||
postcss: true
|
||||
})
|
||||
],
|
||||
vitePlugin: {
|
||||
inspector: true,
|
||||
},
|
||||
kit: {
|
||||
adapter: adapter(),
|
||||
alias: {
|
||||
$root: './src',
|
||||
$lib: './src/lib',
|
||||
$styles: './src/styles',
|
||||
}
|
||||
},
|
||||
vitePlugin: {
|
||||
experimental: {
|
||||
inspector: {
|
||||
toggleKeyCombo: 'control-alt-shift'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
|
|||
Loading…
Reference in a new issue