From 7d334f9cb701c28b85dbe60e8319234d1f3440c6 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Tue, 17 Oct 2023 22:28:53 +1300 Subject: [PATCH] Big changes. Added Sentry at least for now for error tracking to get this up. Moved prisma client generation to the server hooks and passing in locals. Refactor to use prisma in locals. Creating expansions and linking while displaying on Game page. --- .gitignore | 5 +- package.json | 1 + pnpm-lock.yaml | 504 +++++++++++++++++- prisma/schema.prisma | 6 +- src/app.d.ts | 4 + src/hooks.client.ts | 23 + src/hooks.server.ts | 55 +- .../components/search/textSearch/index.svelte | 20 +- src/lib/config/prisma.ts | 5 - src/lib/prisma.ts | 4 - src/lib/server/log.ts | 70 --- src/lib/server/lucia.ts | 6 +- src/lib/types.ts | 15 - src/lib/utils/dbUtils.ts | 94 ++-- src/lib/utils/gameMapper.ts | 3 +- .../(protected)/collection/+page.server.ts | 26 +- .../(app)/(protected)/list/+layout.server.ts | 7 +- .../(protected)/list/[id]/+page.server.ts | 12 +- .../(app)/(protected)/profile/+page.server.ts | 2 +- .../(protected)/wishlist/+page.server.ts | 19 +- src/routes/(app)/game/[id]/+page.server.ts | 63 ++- src/routes/(app)/game/[id]/+page.svelte | 30 +- src/routes/(app)/search/+page.server.ts | 22 +- src/routes/(auth)/login/+page.server.ts | 8 +- src/routes/(auth)/sign-up/+page.server.ts | 9 +- .../api/collection/[id]/search/+server.ts | 6 +- src/routes/api/game/search/+server.ts | 61 ++- .../api/wishlist/[id]/search/+server.ts | 6 +- src/server/roles.ts | 6 +- src/server/users.ts | 9 +- vite.config.ts | 15 +- 31 files changed, 787 insertions(+), 329 deletions(-) create mode 100644 src/hooks.client.ts delete mode 100644 src/lib/config/prisma.ts delete mode 100644 src/lib/prisma.ts delete mode 100644 src/lib/server/log.ts diff --git a/.gitignore b/.gitignore index c26e17f..77f68f1 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,7 @@ node_modules .vercel .output .idea -.fleet \ No newline at end of file +.fleet + +# Sentry Config File +.sentryclirc diff --git a/package.json b/package.json index d0dd53b..64f2821 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,7 @@ "@melt-ui/svelte": "^0.50.1", "@paralleldrive/cuid2": "^2.2.2", "@prisma/client": "^5.4.2", + "@sentry/sveltekit": "^7.74.0", "@types/feather-icons": "^4.29.1", "@vercel/og": "^0.5.13", "bits-ui": "^0.0.27", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6635e02..c4308f9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,9 @@ dependencies: '@prisma/client': specifier: ^5.4.2 version: 5.4.2(prisma@5.4.2) + '@sentry/sveltekit': + specifier: ^7.74.0 + version: 7.74.0(@sveltejs/kit@1.25.2)(svelte@4.2.1) '@types/feather-icons': specifier: ^4.29.1 version: 4.29.1 @@ -258,6 +261,24 @@ packages: - debug dev: false + /@babel/helper-string-parser@7.22.5: + resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/parser@7.23.0: + resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.23.0 + dev: false + /@babel/runtime@7.23.2: resolution: {integrity: sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==} engines: {node: '>=6.9.0'} @@ -265,6 +286,15 @@ packages: regenerator-runtime: 0.14.0 dev: false + /@babel/types@7.23.0: + resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.22.5 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + dev: false + /@colors/colors@1.6.0: resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} engines: {node: '>=0.1.90'} @@ -1472,6 +1502,173 @@ packages: estree-walker: 2.0.2 picomatch: 2.3.1 + /@sentry-internal/tracing@7.74.0: + resolution: {integrity: sha512-JK6IRGgdtZjswGfaGIHNWIThffhOHzVIIaGmglui+VFIzOsOqePjoxaDV0MEvzafxXZD7eWqGE5RGuZ0n6HFVg==} + engines: {node: '>=8'} + dependencies: + '@sentry/core': 7.74.0 + '@sentry/types': 7.74.0 + '@sentry/utils': 7.74.0 + tslib: 2.6.1 + dev: false + + /@sentry/browser@7.74.0: + resolution: {integrity: sha512-Njr8216Z1dFUcl6NqBOk20dssK9SjoVddY74Xq+Q4p3NfXBG3lkMcACXor7SFoJRZXq8CZWGS13Cc5KwViRw4g==} + engines: {node: '>=8'} + dependencies: + '@sentry-internal/tracing': 7.74.0 + '@sentry/core': 7.74.0 + '@sentry/replay': 7.74.0 + '@sentry/types': 7.74.0 + '@sentry/utils': 7.74.0 + tslib: 2.6.1 + dev: false + + /@sentry/bundler-plugin-core@0.6.1: + resolution: {integrity: sha512-EecCJKp9ERM7J93DNDJTvkY78UiD/IfOjBdXWnaUVE0n619O7LfMVjwlXzxRJKl2x05dBE3lDraILLDGxCf6fg==} + engines: {node: '>= 10'} + dependencies: + '@sentry/cli': 2.21.2 + '@sentry/node': 7.74.0 + '@sentry/tracing': 7.74.0 + find-up: 5.0.0 + glob: 9.3.2 + magic-string: 0.27.0 + unplugin: 1.0.1 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /@sentry/cli@2.21.2: + resolution: {integrity: sha512-X1nye89zl+QV3FSuQDGItfM51tW9PQ7ce0TtV/12DgGgTVEgnVp5uvO3wX5XauHvulQzRPzwUL3ZK+yS5bAwCw==} + engines: {node: '>= 10'} + hasBin: true + requiresBuild: true + dependencies: + https-proxy-agent: 5.0.1 + node-fetch: 2.6.7 + progress: 2.0.3 + proxy-from-env: 1.1.0 + which: 2.0.2 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /@sentry/core@7.74.0: + resolution: {integrity: sha512-83NRuqn7nDZkSVBN5yJQqcpXDG4yMYiB7TkYUKrGTzBpRy6KUOrkCdybuKk0oraTIGiGSe5WEwCFySiNgR9FzA==} + engines: {node: '>=8'} + dependencies: + '@sentry/types': 7.74.0 + '@sentry/utils': 7.74.0 + tslib: 2.6.1 + dev: false + + /@sentry/integrations@7.74.0: + resolution: {integrity: sha512-O4UyxiV5wzXSDnEd9Z/SIt/5M12URWNtIJPPJjowlllzw8X9e3zBcnXmjMOLZ+mZWjQmRDjOoz3lPPQ17f7fvw==} + engines: {node: '>=8'} + dependencies: + '@sentry/core': 7.74.0 + '@sentry/types': 7.74.0 + '@sentry/utils': 7.74.0 + localforage: 1.10.0 + tslib: 2.6.1 + dev: false + + /@sentry/node@7.74.0: + resolution: {integrity: sha512-uBmW2/z0cz/WFIG74ZF7lSipO0XNzMf9yrdqnZXnGDYsUZE4I4QiqDN0hNi6fkTgf9MYRC8uFem2OkAvyPJ74Q==} + engines: {node: '>=8'} + dependencies: + '@sentry-internal/tracing': 7.74.0 + '@sentry/core': 7.74.0 + '@sentry/types': 7.74.0 + '@sentry/utils': 7.74.0 + cookie: 0.5.0 + https-proxy-agent: 5.0.1 + lru_map: 0.3.3 + tslib: 2.6.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@sentry/replay@7.74.0: + resolution: {integrity: sha512-GoYa3cHTTFVI/J1cnZ0i4X128mf/JljaswO3PWNTe2k3lSHq/LM5aV0keClRvwM0W8hlix8oOTT06nnenOUmmw==} + engines: {node: '>=12'} + dependencies: + '@sentry/core': 7.74.0 + '@sentry/types': 7.74.0 + '@sentry/utils': 7.74.0 + dev: false + + /@sentry/svelte@7.74.0(svelte@4.2.1): + resolution: {integrity: sha512-dIbNOGs6wOp7QrRjDvYtuNDWeQjXRSWBWJWQVxHLpnzLoWW6isj1Iyrbm9po38CBGdmv5jcQz69Lf5GFRckgFw==} + engines: {node: '>=8'} + peerDependencies: + svelte: 3.x || 4.x + dependencies: + '@sentry/browser': 7.74.0 + '@sentry/types': 7.74.0 + '@sentry/utils': 7.74.0 + magic-string: 0.30.0 + svelte: 4.2.1 + tslib: 2.6.1 + dev: false + + /@sentry/sveltekit@7.74.0(@sveltejs/kit@1.25.2)(svelte@4.2.1): + resolution: {integrity: sha512-Ijdc/5lcvpwL0owkCkZP36YzcU32Fc8/38PrqU1rXsNglBB1KyZ0zAbsCevN+Y9sv5BLVGut8uIsJ7Fc0j6iFQ==} + engines: {node: '>=16'} + peerDependencies: + '@sveltejs/kit': 1.x + dependencies: + '@sentry-internal/tracing': 7.74.0 + '@sentry/core': 7.74.0 + '@sentry/integrations': 7.74.0 + '@sentry/node': 7.74.0 + '@sentry/svelte': 7.74.0(svelte@4.2.1) + '@sentry/types': 7.74.0 + '@sentry/utils': 7.74.0 + '@sentry/vite-plugin': 0.6.1 + '@sveltejs/kit': 1.25.2(svelte@4.2.1)(vite@4.4.9) + magicast: 0.2.8 + sorcery: 0.11.0 + transitivePeerDependencies: + - encoding + - supports-color + - svelte + dev: false + + /@sentry/tracing@7.74.0: + resolution: {integrity: sha512-rSFJADhh3J3zmkzJ1EXCOwS3h7F6o/lSKu7CWZSZ6k5kBvbCJ5AXvGQadhPdWPJMMcPFzCJaOyTKEPcwL4tbCw==} + engines: {node: '>=8'} + dependencies: + '@sentry-internal/tracing': 7.74.0 + dev: false + + /@sentry/types@7.74.0: + resolution: {integrity: sha512-rI5eIRbUycWjn6s6o3yAjjWtIvYSxZDdnKv5je2EZINfLKcMPj1dkl6wQd2F4y7gLfD/N6Y0wZYIXC3DUdJQQg==} + engines: {node: '>=8'} + dev: false + + /@sentry/utils@7.74.0: + resolution: {integrity: sha512-k3np8nuTPtx5KDODPtULfFln4UXdE56MZCcF19Jv6Ljxf+YN/Ady1+0Oi3e0XoSvFpWNyWnglauT7M65qCE6kg==} + engines: {node: '>=8'} + dependencies: + '@sentry/types': 7.74.0 + tslib: 2.6.1 + dev: false + + /@sentry/vite-plugin@0.6.1: + resolution: {integrity: sha512-qkvKaSOcNhNWcdxRXLSs+8cF3ey0XIRmEzTl8U7sTTcZwuOMHsJB+HsYij6aTGaqsKfP8w1ozVt9szBAiL4//w==} + engines: {node: '>= 10'} + dependencies: + '@sentry/bundler-plugin-core': 0.6.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + /@shuding/opentype.js@1.4.0-beta.0: resolution: {integrity: sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==} engines: {node: '>= 8.0.0'} @@ -1920,10 +2117,27 @@ packages: engines: {node: '>=8'} dev: true + /assert@2.1.0: + resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} + dependencies: + call-bind: 1.0.2 + is-nan: 1.3.2 + object-is: 1.1.5 + object.assign: 4.1.4 + util: 0.12.5 + dev: false + /assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} dev: true + /ast-types@0.16.1: + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + engines: {node: '>=4'} + dependencies: + tslib: 2.6.1 + dev: false + /async-sema@3.1.1: resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==} @@ -1947,6 +2161,11 @@ packages: postcss-value-parser: 4.2.0 dev: true + /available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: false + /axios-retry@3.8.0: resolution: {integrity: sha512-CfIsQyWNc5/AE7x/UEReRUadiBmQeoBpSEC+4QyGLJMswTsP1tz0GW2YYPnE7w9+ESMef5zOgLDFpHynNyEZ1w==} dependencies: @@ -2024,6 +2243,12 @@ packages: balanced-match: 1.0.2 concat-map: 0.0.1 + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: false + /braces@3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} @@ -2054,7 +2279,6 @@ packages: /buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - dev: true /busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} @@ -2062,6 +2286,13 @@ packages: dependencies: streamsearch: 1.1.0 + /call-bind@1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.2.1 + dev: false + /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -2287,6 +2518,24 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} + /define-data-property@1.1.1: + resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + gopd: 1.0.1 + has-property-descriptors: 1.0.0 + dev: false + + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + has-property-descriptors: 1.0.0 + object-keys: 1.1.1 + dev: false + /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -2347,7 +2596,6 @@ packages: /es6-promise@3.3.1: resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} - dev: true /esbuild@0.16.8: resolution: {integrity: sha512-RKxRaLYAI5b/IVJ5k8jK3bO2G7cch2ZIZFbfKHbBzpwsWt9+VChcBEndNISBBZ5c3WwekFfkfl11/2QfIGHgDw==} @@ -2537,6 +2785,12 @@ packages: eslint-visitor-keys: 3.4.3 dev: true + /esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: false + /esquery@1.5.0: resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} engines: {node: '>=0.10'} @@ -2655,7 +2909,6 @@ packages: dependencies: locate-path: 6.0.0 path-exists: 4.0.0 - dev: true /flat-cache@3.0.4: resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} @@ -2690,6 +2943,12 @@ packages: optional: true dev: false + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: false + /form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} @@ -2760,6 +3019,15 @@ packages: resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} dev: true + /get-intrinsic@1.2.1: + resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-proto: 1.0.1 + has-symbols: 1.0.3 + dev: false + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -2792,6 +3060,16 @@ packages: once: 1.4.0 path-is-absolute: 1.0.1 + /glob@9.3.2: + resolution: {integrity: sha512-BTv/JhKXFEHsErMte/AnfiSv8yYOLLiyH2lTg8vn02O21zWFgHPTfxtgn1QRe7NRgggUhC8hacR2Re94svHqeA==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + fs.realpath: 1.0.0 + minimatch: 7.4.6 + minipass: 4.2.8 + path-scurry: 1.10.1 + dev: false + /globals@13.19.0: resolution: {integrity: sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==} engines: {node: '>=8'} @@ -2817,6 +3095,12 @@ packages: /globrex@0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.1 + dev: false + /graceful-fs@4.2.10: resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} @@ -2829,6 +3113,29 @@ packages: engines: {node: '>=8'} dev: true + /has-property-descriptors@1.0.0: + resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + dependencies: + get-intrinsic: 1.2.1 + dev: false + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + dev: false + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: false + + /has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: false + /has-unicode@2.0.1: resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} @@ -2871,6 +3178,10 @@ packages: engines: {node: '>= 4'} dev: true + /immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + dev: false + /immutable@4.1.0: resolution: {integrity: sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==} @@ -2900,12 +3211,25 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + /is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: false + /is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} dependencies: binary-extensions: 2.2.0 + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: false + /is-core-module@2.12.1: resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==} dependencies: @@ -2919,12 +3243,27 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + /is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: false + /is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} dependencies: is-extglob: 2.1.1 + /is-nan@1.3.2: + resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + dev: false + /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -2944,9 +3283,15 @@ packages: engines: {node: '>=10'} dev: false + /is-typed-array@1.1.12: + resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.11 + dev: false + /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true /isomorphic-unfetch@3.1.0: resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==} @@ -3017,6 +3362,12 @@ packages: type-check: 0.4.0 dev: true + /lie@3.1.1: + resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==} + dependencies: + immediate: 3.0.6 + dev: false + /lilconfig@2.0.6: resolution: {integrity: sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==} engines: {node: '>=10'} @@ -3043,6 +3394,12 @@ packages: engines: {node: '>=14'} dev: true + /localforage@1.10.0: + resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==} + dependencies: + lie: 3.1.1 + dev: false + /locate-character@3.0.0: resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} @@ -3051,7 +3408,6 @@ packages: engines: {node: '>=10'} dependencies: p-locate: 5.0.0 - dev: true /lodash.clone@4.5.0: resolution: {integrity: sha512-GhrVeweiTD6uTmmn5hV/lzgCQhccwReIVRLHp7LT4SopOjqEZ5BbX8b5WWEtAKasjmy8hR7ZPwsYlxRCku5odg==} @@ -3083,12 +3439,21 @@ packages: get-func-name: 2.0.0 dev: true + /lru-cache@10.0.1: + resolution: {integrity: sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==} + engines: {node: 14 || >=16.14} + dev: false + /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} dependencies: yallist: 4.0.0 + /lru_map@0.3.3: + resolution: {integrity: sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==} + dev: false + /lucia@2.7.1: resolution: {integrity: sha512-EHDTajS1YWA7Q37jd29Far1l4nfZgsWLp4hDQeaQhVpJd2WKQqA3626kJYmOj1CTweVMkE54xFi5JIph+agZkQ==} dev: false @@ -3106,7 +3471,6 @@ packages: engines: {node: '>=12'} dependencies: '@jridgewell/sourcemap-codec': 1.4.15 - dev: true /magic-string@0.30.0: resolution: {integrity: sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==} @@ -3114,6 +3478,14 @@ packages: dependencies: '@jridgewell/sourcemap-codec': 1.4.15 + /magicast@0.2.8: + resolution: {integrity: sha512-zEnqeb3E6TfMKYXGyHv3utbuHNixr04o3/gVGviSzVQkbFiU46VZUd+Ea/1npKfvEsEWxBYuIksKzoztTDPg0A==} + dependencies: + '@babel/parser': 7.23.0 + '@babel/types': 7.23.0 + recast: 0.23.4 + dev: false + /make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -3169,9 +3541,15 @@ packages: dependencies: brace-expansion: 1.1.11 + /minimatch@7.4.6: + resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: false + /minimist@1.2.7: resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} - dev: true /minipass@3.3.6: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} @@ -3185,6 +3563,16 @@ packages: dependencies: yallist: 4.0.0 + /minipass@4.2.8: + resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} + engines: {node: '>=8'} + dev: false + + /minipass@7.0.4: + resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} + engines: {node: '>=16 || 14 >=14.17'} + dev: false + /minizlib@2.1.2: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} @@ -3197,7 +3585,6 @@ packages: hasBin: true dependencies: minimist: 1.2.7 - dev: true /mkdirp@1.0.4: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} @@ -3291,6 +3678,29 @@ packages: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} + /object-is@1.1.5: + resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + dev: false + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: false + + /object.assign@4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: false + /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: @@ -3317,14 +3727,12 @@ packages: engines: {node: '>=10'} dependencies: yocto-queue: 0.1.0 - dev: true /p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} dependencies: p-limit: 3.1.0 - dev: true /pako@0.2.9: resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} @@ -3345,7 +3753,6 @@ packages: /path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - dev: true /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} @@ -3359,6 +3766,14 @@ packages: /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + /path-scurry@1.10.1: + resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + lru-cache: 10.0.1 + minipass: 7.0.4 + dev: false + /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -3855,6 +4270,11 @@ packages: dependencies: '@prisma/engines': 5.4.2 + /progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + dev: false + /proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} dev: false @@ -3897,6 +4317,17 @@ packages: dependencies: picomatch: 2.3.1 + /recast@0.23.4: + resolution: {integrity: sha512-qtEDqIZGVcSZCHniWwZWbRy79Dc6Wp3kT/UmDA2RJKBPg7+7k51aQBZirHmUGn5uvHf2rg8DkjizrN26k61ATw==} + engines: {node: '>= 4'} + dependencies: + assert: 2.1.0 + ast-types: 0.16.1 + esprima: 4.0.1 + source-map: 0.6.1 + tslib: 2.6.1 + dev: false + /reflect-metadata@0.1.13: resolution: {integrity: sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==} dev: false @@ -3939,7 +4370,6 @@ packages: hasBin: true dependencies: glob: 7.2.3 - dev: true /rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} @@ -3980,7 +4410,6 @@ packages: graceful-fs: 4.2.10 mkdirp: 0.5.6 rimraf: 2.7.1 - dev: true /sass@1.65.1: resolution: {integrity: sha512-9DINwtHmA41SEd36eVPQ9BJKpn7eKDQmUHmpI0y5Zv2Rcorrh0zS+cFrt050hdNbmmCNKTW3hV5mWfuegNRsEA==} @@ -4098,7 +4527,6 @@ packages: buffer-crc32: 0.2.13 minimist: 1.2.7 sander: 0.5.1 - dev: true /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} @@ -4107,7 +4535,6 @@ packages: /source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - dev: true /streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} @@ -4466,6 +4893,11 @@ packages: engines: {node: '>=14.0.0'} dev: true + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: false + /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -4529,7 +4961,6 @@ packages: /tslib@2.6.1: resolution: {integrity: sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==} - dev: true /tsutils@3.21.0(typescript@5.1.6): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} @@ -4589,6 +5020,15 @@ packages: '@types/unist': 3.0.0 dev: false + /unplugin@1.0.1: + resolution: {integrity: sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==} + dependencies: + acorn: 8.10.0 + chokidar: 3.5.3 + webpack-sources: 3.2.3 + webpack-virtual-modules: 0.5.0 + dev: false + /update-browserslist-db@1.0.11(browserslist@4.21.10): resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==} hasBin: true @@ -4620,6 +5060,16 @@ packages: /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + /util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + dependencies: + inherits: 2.0.4 + is-arguments: 1.1.1 + is-generator-function: 1.0.10 + is-typed-array: 1.1.12 + which-typed-array: 1.1.11 + dev: false + /v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} @@ -4726,19 +5176,38 @@ packages: /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + /webpack-sources@3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} + engines: {node: '>=10.13.0'} + dev: false + + /webpack-virtual-modules@0.5.0: + resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} + dev: false + /whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 + /which-typed-array@1.1.11: + resolution: {integrity: sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: false + /which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true dependencies: isexe: 2.0.0 - dev: true /wide-align@1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} @@ -4776,7 +5245,6 @@ packages: /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - dev: true /yoga-wasm-web@0.3.3: resolution: {integrity: sha512-N+d4UJSJbt/R3wqY7Coqs5pcV0aUj2j9IaQ3rNj9bVCLld8tTGKRa2USARjnvZJWVx1NDmQev8EknoczaOQDOA==} diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 994cc1e..61a1f11 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -175,7 +175,8 @@ model Game { publishers Publisher[] artists Artist[] names GameName[] - expansions Expansion[] + expansions Expansion[] @relation("BaseToExpansion") + expansion_of Expansion[] @relation("ExpansionToBase") collection_items CollectionItem[] wishlist_items WishlistItem[] list_items ListItem[] @@ -269,8 +270,9 @@ model Artist { model Expansion { id String @id @default(cuid()) - base_game Game @relation(fields: [base_game_id], references: [id]) + base_game Game @relation(name: "BaseToExpansion", fields: [base_game_id], references: [id]) base_game_id String + game Game @relation(name: "ExpansionToBase", fields: [game_id], references: [id]) game_id String created_at DateTime @default(now()) @db.Timestamp(6) updated_at DateTime @updatedAt @db.Timestamp(6) diff --git a/src/app.d.ts b/src/app.d.ts index df527f0..bcbeb53 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -22,6 +22,10 @@ declare global { errorStackTrace: string; message: unknown; track: unknown; + session: { + ip: string, + country: string + } } interface Error { code?: string; diff --git a/src/hooks.client.ts b/src/hooks.client.ts new file mode 100644 index 0000000..f3e3411 --- /dev/null +++ b/src/hooks.client.ts @@ -0,0 +1,23 @@ +import { dev } from '$app/environment'; +import { handleErrorWithSentry, Replay } from '@sentry/sveltekit'; +import * as Sentry from '@sentry/sveltekit'; + +Sentry.init({ + dsn: 'https://742e43279df93a3c4a4a78c12eb1f879@o4506057768632320.ingest.sentry.io/4506057770401792', + tracesSampleRate: 1.0, + + // This sets the sample rate to be 10%. You may want this to be 100% while + // in development and sample at a lower rate in production + replaysSessionSampleRate: 0.1, + + // If the entire session is not sampled, use the below sample rate to sample + // sessions when an error occurs. + replaysOnErrorSampleRate: 1.0, + + // If you don't want to use Session Replay, just remove the line below: + integrations: [new Replay()], + environment: dev ? 'development' : 'production' +}); + +// If you have a custom error handler, pass it to `handleErrorWithSentry` +export const handleError = handleErrorWithSentry(); diff --git a/src/hooks.server.ts b/src/hooks.server.ts index aad9f13..54f28de 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -1,34 +1,19 @@ +import * as Sentry from '@sentry/sveltekit'; import { sequence } from '@sveltejs/kit/hooks'; -import { type HandleServerError, type Handle } from '@sveltejs/kit'; -import { dev } from '$app/environment'; +import { PrismaClient } from '@prisma/client'; +import type { Handle } 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(); +Sentry.init({ + dsn: 'https://742e43279df93a3c4a4a78c12eb1f879@o4506057768632320.ingest.sentry.io/4506057770401792', + tracesSampleRate: 1, + environment: dev ? 'development' : 'production' +}); - // 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 prismaClient: Handle = async function ({ event, resolve }) { -// event.locals.prisma = prisma; -// const response = await resolve(event); -// return response; -// }; +// * START UP +// RUNS ONCE ON FILE LOAD +export const prisma_client = new PrismaClient(); export const authentication: Handle = async function ({ event, resolve }) { const startTimer = Date.now(); @@ -52,8 +37,22 @@ export const authentication: Handle = async function ({ event, resolve }) { console.log('auth empty'); } + return await resolve(event); +}; + +// This hook is used to pass our prisma instance to each action, load, and endpoint +export const prisma: Handle = async function ({ event, resolve }) { + const ip = event.request.headers.get('x-forwarded-for') as string; + const country = event.request.headers.get('x-vercel-ip-country') as string; + event.locals.prisma = prisma_client; + event.locals.session = { + ...event.locals.session, + ip, + country + }; const response = await resolve(event); return response; }; -export const handle = sequence(authentication); +export const handle = sequence(sequence(Sentry.sentryHandle(), authentication, prisma)); +export const handleError = Sentry.handleErrorWithSentry(); \ No newline at end of file diff --git a/src/lib/components/search/textSearch/index.svelte b/src/lib/components/search/textSearch/index.svelte index 3dbdfe2..f0ed086 100644 --- a/src/lib/components/search/textSearch/index.svelte +++ b/src/lib/components/search/textSearch/index.svelte @@ -85,20 +85,20 @@ {#if showButton} diff --git a/src/lib/config/prisma.ts b/src/lib/config/prisma.ts deleted file mode 100644 index 4e54f7a..0000000 --- a/src/lib/config/prisma.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { PrismaClient } from '@prisma/client'; - -const prisma = new PrismaClient(); - -export default prisma; diff --git a/src/lib/prisma.ts b/src/lib/prisma.ts deleted file mode 100644 index 736f146..0000000 --- a/src/lib/prisma.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { PrismaClient } from '@prisma/client'; - -const prisma = new PrismaClient(); -export default prisma; diff --git a/src/lib/server/log.ts b/src/lib/server/log.ts deleted file mode 100644 index 1a3e92e..0000000 --- a/src/lib/server/log.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { Client } from '@axiomhq/axiom-node'; -import { AXIOM_TOKEN, AXIOM_ORG_ID, AXIOM_DATASET } from '$env/static/private'; -import getAllUrlParams from '$lib/utils/getAllUrlParams'; -import parseTrack from '$lib/utils/parseTrack'; -import parseMessage from '$lib/utils/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)}`); - } -} diff --git a/src/lib/server/lucia.ts b/src/lib/server/lucia.ts index 7be939d..f81e10f 100644 --- a/src/lib/server/lucia.ts +++ b/src/lib/server/lucia.ts @@ -2,15 +2,13 @@ import { lucia } from 'lucia'; import { sveltekit } from 'lucia/middleware'; import { prisma } from '@lucia-auth/adapter-prisma'; -import { PrismaClient } from '@prisma/client'; import { dev } from '$app/environment'; - -const client = new PrismaClient(); +import { PrismaClient } from '@prisma/client'; export const auth = lucia({ - adapter: prisma(client), env: dev ? 'DEV' : 'PROD', middleware: sveltekit(), + adapter: prisma(new PrismaClient()), getUserAttributes: (databaseUser) => { return { username: databaseUser.username, diff --git a/src/lib/types.ts b/src/lib/types.ts index 86caf89..3339c07 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -1,22 +1,7 @@ -import { Prisma } from '@prisma/client'; import type { SvelteComponent } from 'svelte'; export type Message = { status: 'error' | 'success' | 'warning' | 'info'; text: string }; -export const gameInclude = Prisma.validator()({ - game: { - select: { - id: true, - name: true, - thumb_url: true - } - } -}); - -export type CollectionItemWithGame = Prisma.CollectionItemGetPayload<{ - include: typeof gameInclude; -}>; - export type Dialog = { isOpen: boolean; content?: typeof SvelteComponent; diff --git a/src/lib/utils/dbUtils.ts b/src/lib/utils/dbUtils.ts index 6fa7eaa..c9e9230 100644 --- a/src/lib/utils/dbUtils.ts +++ b/src/lib/utils/dbUtils.ts @@ -1,13 +1,11 @@ import type { Game } from '@prisma/client'; import kebabCase from 'just-kebab-case'; import type { BggLinkDto } from 'boardgamegeekclient/dist/esm/dto/concrete/subdto'; -import prisma from '$lib/prisma'; -import type { GameType } from '$lib/types'; import { mapAPIGameToBoredGame } from './gameMapper'; -export async function createArtist(externalArtist: BggLinkDto) { +export async function createArtist(locals: App.Locals, externalArtist: BggLinkDto) { try { - let dbArtist = await prisma.artist.findFirst({ + let dbArtist = await locals.prisma.artist.findFirst({ where: { external_id: externalArtist.id }, @@ -19,10 +17,11 @@ export async function createArtist(externalArtist: BggLinkDto) { } }); if (dbArtist) { + console.log('Artist already exists', dbArtist.name); return dbArtist; } console.log('Creating artist', JSON.stringify(externalArtist, null, 2)); - let artist = await prisma.artist.create({ + let artist = await locals.prisma.artist.create({ data: { name: externalArtist.value, external_id: externalArtist.id, @@ -44,9 +43,9 @@ export async function createArtist(externalArtist: BggLinkDto) { } } -export async function createDesigner(externalDesigner: BggLinkDto) { +export async function createDesigner(locals: App.Locals, externalDesigner: BggLinkDto) { try { - let dbDesigner = await prisma.designer.findFirst({ + let dbDesigner = await locals.prisma.designer.findFirst({ where: { external_id: externalDesigner.id }, @@ -58,10 +57,11 @@ export async function createDesigner(externalDesigner: BggLinkDto) { } }); if (dbDesigner) { + console.log('Designer already exists', dbDesigner.name); return dbDesigner; } console.log('Creating designer', JSON.stringify(externalDesigner, null, 2)); - let designer = await prisma.designer.create({ + let designer = await locals.prisma.designer.create({ data: { name: externalDesigner.value, external_id: externalDesigner.id, @@ -83,9 +83,9 @@ export async function createDesigner(externalDesigner: BggLinkDto) { } } -export async function createPublisher(externalPublisher: BggLinkDto) { +export async function createPublisher(locals: App.Locals, externalPublisher: BggLinkDto) { try { - let dbPublisher = await prisma.publisher.findFirst({ + let dbPublisher = await locals.prisma.publisher.findFirst({ where: { external_id: externalPublisher.id }, @@ -97,10 +97,11 @@ export async function createPublisher(externalPublisher: BggLinkDto) { } }); if (dbPublisher) { + console.log('Publisher already exists', dbPublisher.name); return dbPublisher; } console.log('Creating publisher', JSON.stringify(externalPublisher, null, 2)); - let publisher = await prisma.publisher.create({ + let publisher = await locals.prisma.publisher.create({ data: { name: externalPublisher.value, external_id: externalPublisher.id, @@ -122,9 +123,9 @@ export async function createPublisher(externalPublisher: BggLinkDto) { } } -export async function createCategory(externalCategory: BggLinkDto) { +export async function createCategory(locals: App.Locals, externalCategory: BggLinkDto) { try { - let dbCategory = await prisma.category.findFirst({ + let dbCategory = await locals.prisma.category.findFirst({ where: { external_id: externalCategory.id }, @@ -136,10 +137,11 @@ export async function createCategory(externalCategory: BggLinkDto) { } }); if (dbCategory) { + console.log('Category already exists', dbCategory.name); return dbCategory; } console.log('Creating category', JSON.stringify(externalCategory, null, 2)); - let category = await prisma.category.create({ + let category = await locals.prisma.category.create({ data: { name: externalCategory.value, external_id: externalCategory.id, @@ -162,9 +164,9 @@ export async function createCategory(externalCategory: BggLinkDto) { } } -export async function createMechanic(externalMechanic: BggLinkDto) { +export async function createMechanic(locals: App.Locals, externalMechanic: BggLinkDto) { try { - let dbMechanic = await prisma.mechanic.findFirst({ + let dbMechanic = await locals.prisma.mechanic.findFirst({ where: { external_id: externalMechanic.id }, @@ -176,10 +178,11 @@ export async function createMechanic(externalMechanic: BggLinkDto) { } }); if (dbMechanic) { + console.log('Mechanic already exists', dbMechanic.name); return dbMechanic; } console.log('Creating mechanic', JSON.stringify(externalMechanic, null, 2)); - let mechanic = await prisma.mechanic.upsert({ + let mechanic = await locals.prisma.mechanic.upsert({ where: { external_id: externalMechanic.id }, @@ -204,13 +207,14 @@ export async function createMechanic(externalMechanic: BggLinkDto) { } export async function createExpansion( + locals: App.Locals, game: Game, externalExpansion: BggLinkDto, gameIsExpansion: boolean, eventFetch: Function ) { try { - let dbExpansionGame = await prisma.game.findUnique({ + let dbExpansionGame = await locals.prisma.game.findUnique({ where: { external_id: externalExpansion.id } @@ -224,7 +228,7 @@ export async function createExpansion( const externalGame = await externalGameResponse.json(); console.log('externalGame', externalGame); let boredGame = mapAPIGameToBoredGame(externalGame); - dbExpansionGame = await createOrUpdateGameMinimal(boredGame); + dbExpansionGame = await createOrUpdateGameMinimal(locals, boredGame); } else { throw new Error( `${gameIsExpansion ? 'Base game' : 'Expansion game'} not found and failed to create.` @@ -240,7 +244,7 @@ export async function createExpansion( 'External expansion is expansion. Looking for base game', JSON.stringify(game, null, 2) ); - dbExpansion = await prisma.expansion.findFirst({ + dbExpansion = await locals.prisma.expansion.findFirst({ where: { game_id: dbExpansionGame.id }, @@ -257,7 +261,7 @@ export async function createExpansion( 'External Expansion is base game. Looking for expansion', JSON.stringify(game, null, 2) ); - dbExpansion = await prisma.expansion.findFirst({ + dbExpansion = await locals.prisma.expansion.findFirst({ where: { base_game_id: dbExpansionGame.id }, @@ -277,7 +281,7 @@ export async function createExpansion( } console.log(`Creating expansion. baseGameId: ${baseGameId}, gameId: ${gameId}`); - let expansion = await prisma.expansion.create({ + let expansion = await locals.prisma.expansion.create({ data: { base_game_id: baseGameId, game_id: gameId @@ -286,6 +290,36 @@ export async function createExpansion( console.log('Created expansion', JSON.stringify(expansion, null, 2)); + if (gameIsExpansion) { + console.log('Connecting current game to expansion'); + await locals.prisma.game.update({ + where: { + id: gameId + }, + data: { + expansions: { + connect: { + id: expansion.id + } + } + } + }); + } else { + console.log('Connecting current game to base game'); + await locals.prisma.game.update({ + where: { + external_id: baseGameId + }, + data: { + expansions: { + connect: { + id: expansion.id + } + } + } + }); + } + return expansion; } catch (e) { console.error(e); @@ -293,10 +327,10 @@ export async function createExpansion( } } -export async function createOrUpdateGameMinimal(game: GameType) { +export async function createOrUpdateGameMinimal(locals: App.Locals, game: Game) { console.log('Creating or updating minimal game data', JSON.stringify(game, null, 2)); const externalUrl = `https://boardgamegeek.com/boardgame/${game.external_id}`; - return await prisma.game.upsert({ + return await locals.prisma.game.upsert({ where: { external_id: game.external_id }, @@ -333,18 +367,18 @@ export async function createOrUpdateGameMinimal(game: GameType) { }); } -export async function createOrUpdateGame(game: GameType) { +export async function createOrUpdateGame(locals: App.Locals, game: Game) { console.log('Creating or updating game', JSON.stringify(game, null, 2)); const categoryIds = game.categories; const mechanicIds = game.mechanics; const publisherIds = game.publishers; const designerIds = game.designers; const artistIds = game.artists; - const expansionIds = game.expansions; + // const expansionIds = game.expansions; const externalUrl = `https://boardgamegeek.com/boardgame/${game.external_id}`; console.log('categoryIds', categoryIds); console.log('mechanicIds', mechanicIds); - return await prisma.game.upsert({ + return await locals.prisma.game.upsert({ include: { mechanics: true, publishers: true, @@ -384,9 +418,6 @@ export async function createOrUpdateGame(game: GameType) { }, artists: { connect: artistIds - }, - expansions: { - connect: expansionIds } }, update: { @@ -418,9 +449,6 @@ export async function createOrUpdateGame(game: GameType) { }, artists: { connect: artistIds - }, - expansions: { - connect: expansionIds } } }); diff --git a/src/lib/utils/gameMapper.ts b/src/lib/utils/gameMapper.ts index a55d8f8..d21f7dd 100644 --- a/src/lib/utils/gameMapper.ts +++ b/src/lib/utils/gameMapper.ts @@ -1,4 +1,5 @@ import type { GameType, SavedGameType } from '$lib/types'; +import type { Game } from '@prisma/client'; import kebabCase from 'just-kebab-case'; export function convertToSavedGame(game: GameType | SavedGameType): SavedGameType { @@ -42,7 +43,7 @@ export function mapSavedGameToGame(game: SavedGameType): GameType { }; } -export function mapAPIGameToBoredGame(game: GameType): GameType { +export function mapAPIGameToBoredGame(game: GameType): Game { // TODO: Fix types return { external_id: game.external_id, diff --git a/src/routes/(app)/(protected)/collection/+page.server.ts b/src/routes/(app)/(protected)/collection/+page.server.ts index 1df21d5..ea84678 100644 --- a/src/routes/(app)/(protected)/collection/+page.server.ts +++ b/src/routes/(app)/(protected)/collection/+page.server.ts @@ -1,9 +1,7 @@ import { error, fail, redirect } from '@sveltejs/kit'; -import { setError, superValidate } from 'sveltekit-superforms/server'; +import { superValidate } from 'sveltekit-superforms/server'; import type { PageServerLoad } from '../../$types.js'; -import prisma from '$lib/prisma'; import { modifyListGameSchema, type ListGame } from '$lib/config/zod-schemas.js'; -import type { CollectionItemWithGame } from '$lib/types.js'; import { search_schema } from '$lib/zodValidation.js'; export const load: PageServerLoad = async ({ fetch, url, locals }) => { @@ -29,7 +27,7 @@ export const load: PageServerLoad = async ({ fetch, url, locals }) => { const listManageForm = await superValidate(modifyListGameSchema); try { - let collection = await prisma.collection.findUnique({ + let collection = await locals.prisma.collection.findUnique({ where: { user_id: session.user.userId } @@ -39,14 +37,14 @@ export const load: PageServerLoad = async ({ fetch, url, locals }) => { if (!collection) { console.log('Collection was not found'); return fail(404, {}); - // collection = await prisma.collection.create({ + // collection = await locals.prisma.collection.create({ // data: { // user_id: session.userId // } // }); } - let collection_items: CollectionItemWithGame[] = await prisma.collectionItem.findMany({ + let collection_items = await locals.prisma.collectionItem.findMany({ where: { collection_id: collection.id }, @@ -110,14 +108,14 @@ export const actions = { throw redirect(302, '/login'); } - let game = await prisma.game.findUnique({ + let game = await locals.prisma.game.findUnique({ where: { id: form.data.id } }); if (!game) { - // game = await prisma.game.create({ + // game = await locals.prisma.game.create({ // data: { // name: form.name // } @@ -127,7 +125,7 @@ export const actions = { } if (game) { - const collection = await prisma.collection.findUnique({ + const collection = await locals.prisma.collection.findUnique({ where: { user_id: session.user.userId } @@ -138,7 +136,7 @@ export const actions = { return error(404, 'Wishlist not found'); } - await prisma.collectionItem.create({ + await locals.prisma.collectionItem.create({ data: { game_id: game.id, collection_id: collection.id, @@ -182,14 +180,14 @@ export const actions = { throw redirect(302, '/login'); } - let game = await prisma.game.findUnique({ + let game = await locals.prisma.game.findUnique({ where: { id: form.data.id } }); if (!game) { - // game = await prisma.game.create({ + // game = await locals.prisma.game.create({ // data: { // name: form.name // } @@ -199,7 +197,7 @@ export const actions = { } if (game) { - const collection = await prisma.collection.findUnique({ + const collection = await locals.prisma.collection.findUnique({ where: { user_id: session.user.userId } @@ -210,7 +208,7 @@ export const actions = { return error(404, 'Wishlist not found'); } - await prisma.collectionItem.delete({ + await locals.prisma.collectionItem.delete({ where: { collection_id: collection.id, game_id: game.id diff --git a/src/routes/(app)/(protected)/list/+layout.server.ts b/src/routes/(app)/(protected)/list/+layout.server.ts index 451cb00..e94fe5d 100644 --- a/src/routes/(app)/(protected)/list/+layout.server.ts +++ b/src/routes/(app)/(protected)/list/+layout.server.ts @@ -1,21 +1,20 @@ -import prisma from '$lib/prisma'; import { redirect } from '@sveltejs/kit'; -export async function load({ params, locals }) { +export async function load({ locals }) { const session = await locals.auth.validate(); if (!session) { throw redirect(302, '/login'); } try { - let wishlists = await prisma.wishlist.findMany({ + let wishlists = await locals.prisma.wishlist.findMany({ where: { user_id: session.userId } }); if (wishlists.length === 0) { - const wishlist = await prisma.wishlist.create({ + const wishlist = await locals.prisma.wishlist.create({ data: { user_id: session.userId } diff --git a/src/routes/(app)/(protected)/list/[id]/+page.server.ts b/src/routes/(app)/(protected)/list/[id]/+page.server.ts index 6492bdc..87da5b0 100644 --- a/src/routes/(app)/(protected)/list/[id]/+page.server.ts +++ b/src/routes/(app)/(protected)/list/[id]/+page.server.ts @@ -1,7 +1,5 @@ import { fail, redirect } from '@sveltejs/kit'; import { superValidate } from 'sveltekit-superforms/server'; -import prisma from '$lib/prisma'; -import { list_game_request_schema } from '$lib/zodValidation'; export async function load({ params, locals }) { const session = await locals.auth.validate(); @@ -10,7 +8,7 @@ export async function load({ params, locals }) { } try { - let wishlist = await prisma.wishlist.findUnique({ + let wishlist = await locals.prisma.wishlist.findUnique({ where: { id: params.id, AND: { @@ -52,14 +50,14 @@ export const actions = { throw redirect(302, '/login'); } - let game = await prisma.game.findUnique({ + let game = await locals.prisma.game.findUnique({ where: { id: form.id } }); if (!game) { - // game = await prisma.game.create({ + // game = await locals.prisma.game.create({ // data: { // name: form.name // } @@ -69,7 +67,7 @@ export const actions = { }); } - const wishlist = await prisma.wishlist.findUnique({ + const wishlist = await locals.prisma.wishlist.findUnique({ where: { id: params.id } @@ -85,7 +83,7 @@ export const actions = { throw redirect(302, '/404'); } - const wishlistItem = await prisma.wishlistItem.create({ + const wishlistItem = await locals.prisma.wishlistItem.create({ data: { game_id: game.id, wishlist_id: wishlist.id diff --git a/src/routes/(app)/(protected)/profile/+page.server.ts b/src/routes/(app)/(protected)/profile/+page.server.ts index 157818c..290d72c 100644 --- a/src/routes/(app)/(protected)/profile/+page.server.ts +++ b/src/routes/(app)/(protected)/profile/+page.server.ts @@ -61,7 +61,7 @@ export const actions = { if (user.email !== form.data.email) { // auth.update - // await prisma.key.update({ + // await locals.prisma.key.update({ // where: { // id: 'emailpassword:' + user.email // }, diff --git a/src/routes/(app)/(protected)/wishlist/+page.server.ts b/src/routes/(app)/(protected)/wishlist/+page.server.ts index e8e1931..2cacc82 100644 --- a/src/routes/(app)/(protected)/wishlist/+page.server.ts +++ b/src/routes/(app)/(protected)/wishlist/+page.server.ts @@ -1,6 +1,5 @@ import { error, redirect } from '@sveltejs/kit'; import { superValidate } from 'sveltekit-superforms/server'; -import prisma from '$lib/prisma'; import { modifyListGameSchema } from '$lib/config/zod-schemas.js'; export async function load({ params, locals }) { @@ -12,7 +11,7 @@ export async function load({ params, locals }) { console.log('Wishlist load User id', session.user); try { - let wishlist = await prisma.wishlist.findUnique({ + let wishlist = await locals.prisma.wishlist.findUnique({ where: { user_id: session?.user?.userId }, @@ -58,14 +57,14 @@ export const actions = { throw redirect(302, '/login'); } - let game = await prisma.game.findUnique({ + let game = await locals.prisma.game.findUnique({ where: { id: form.data.id } }); if (!game) { - // game = await prisma.game.create({ + // game = await locals.prisma.game.create({ // data: { // name: form.name // } @@ -75,7 +74,7 @@ export const actions = { } if (game) { - const wishlist = await prisma.wishlist.findUnique({ + const wishlist = await locals.prisma.wishlist.findUnique({ where: { user_id: session.user.userId } @@ -86,7 +85,7 @@ export const actions = { return error(404, 'Wishlist not found'); } - await prisma.wishlistItem.create({ + await locals.prisma.wishlistItem.create({ data: { game_id: game.id, wishlist_id: wishlist.id @@ -129,14 +128,14 @@ export const actions = { throw redirect(302, '/login'); } - let game = await prisma.game.findUnique({ + let game = await locals.prisma.game.findUnique({ where: { id: form.data.id } }); if (!game) { - // game = await prisma.game.create({ + // game = await locals.prisma.game.create({ // data: { // name: form.name // } @@ -146,7 +145,7 @@ export const actions = { } if (game) { - const wishlist = await prisma.wishlist.findUnique({ + const wishlist = await locals.prisma.wishlist.findUnique({ where: { user_id: session.user.userId } @@ -157,7 +156,7 @@ export const actions = { return error(404, 'Wishlist not found'); } - await prisma.wishlistItem.delete({ + await locals.prisma.wishlistItem.delete({ where: { wishlist_id: wishlist.id, game_id: game.id diff --git a/src/routes/(app)/game/[id]/+page.server.ts b/src/routes/(app)/game/[id]/+page.server.ts index e672812..8d6f745 100644 --- a/src/routes/(app)/game/[id]/+page.server.ts +++ b/src/routes/(app)/game/[id]/+page.server.ts @@ -1,5 +1,4 @@ import { error } from '@sveltejs/kit'; -import prisma from '$lib/prisma'; import { createArtist, createCategory, @@ -12,11 +11,11 @@ import { import { mapAPIGameToBoredGame } from '$lib/utils/gameMapper.js'; import type { Game } from '@prisma/client'; -export const load = async ({ params, setHeaders, locals, fetch }) => { +export const load = async ({ params, locals, fetch }) => { try { const { user } = locals; const { id } = params; - const game = await prisma.game.findUnique({ + const game = await locals.prisma.game.findUnique({ where: { id }, @@ -28,7 +27,22 @@ export const load = async ({ params, setHeaders, locals, fetch }) => { categories: true, expansions: { include: { - base_game: true + game: { + select: { + id: true, + name: true + } + } + } + }, + expansion_of: { + include: { + base_game: { + select: { + id: true, + name: true + } + } } } } @@ -44,13 +58,13 @@ export const load = async ({ params, setHeaders, locals, fetch }) => { game.last_sync_at === null || currentDate.getDate() - game.last_sync_at.getDate() > 7 * 24 * 60 * 60 * 1000 ) { - await syncGameAndConnectedData(game, fetch); + await syncGameAndConnectedData(locals, game, fetch); } let wishlist; let collection; if (user) { - wishlist = await prisma.wishlist.findUnique({ + wishlist = await locals.prisma.wishlist.findUnique({ where: { user_id: user.userId }, @@ -63,7 +77,7 @@ export const load = async ({ params, setHeaders, locals, fetch }) => { } }); - collection = await prisma.collection.findUnique({ + collection = await locals.prisma.collection.findUnique({ where: { user_id: user.userId }, @@ -94,7 +108,7 @@ export const load = async ({ params, setHeaders, locals, fetch }) => { throw error(404, 'not found'); }; -async function syncGameAndConnectedData(game: Game, eventFetch: Function) { +async function syncGameAndConnectedData(locals: App.Locals, game: Game, eventFetch: Function) { console.log( `Retrieving full external game details for external id: ${game.external_id} with name ${game.name}` ); @@ -107,50 +121,35 @@ async function syncGameAndConnectedData(game: Game, eventFetch: Function) { let artists = []; let designers = []; let publishers = []; - let expansions = []; for (const externalCategory of externalGame.categories) { - const category = await createCategory(externalCategory); + const category = await createCategory(locals, externalCategory); categories.push({ id: category.id }); } for (const externalMechanic of externalGame.mechanics) { - const mechanic = await createMechanic(externalMechanic); + const mechanic = await createMechanic(locals, externalMechanic); mechanics.push({ id: mechanic.id }); } for (const externalArtist of externalGame.artists) { - const artist = await createArtist(externalArtist); + const artist = await createArtist(locals, externalArtist); artists.push({ id: artist.id }); } for (const externalDesigner of externalGame.designers) { - const designer = await createDesigner(externalDesigner); + const designer = await createDesigner(locals, externalDesigner); designers.push({ id: designer.id }); } for (const externalPublisher of externalGame.publishers) { - const publisher = await createPublisher(externalPublisher); + const publisher = await createPublisher(locals, externalPublisher); publishers.push({ id: publisher.id }); } for (const externalExpansion of externalGame.expansions) { - let expansion; console.log('Inbound?', externalExpansion.inbound); if (externalExpansion?.inbound === true) { - expansion = await createExpansion(game, externalExpansion, false, eventFetch); - await prisma.game.update({ - where: { - external_id: externalExpansion.id - }, - data: { - expansions: { - connect: { - id: expansion.id - } - } - } - }) + createExpansion(locals, game, externalExpansion, false, eventFetch); } else { - expansion = await createExpansion(game, externalExpansion, true, eventFetch); - expansions.push({ id: expansion.id }); + createExpansion(locals, game, externalExpansion, true, eventFetch); } } @@ -161,7 +160,7 @@ async function syncGameAndConnectedData(game: Game, eventFetch: Function) { boredGame.designers = designers; boredGame.artists = artists; boredGame.publishers = publishers; - boredGame.expansions = expansions; - return createOrUpdateGame(boredGame); + // boredGame.expansions = expansions; + return createOrUpdateGame(locals, boredGame); } } diff --git a/src/routes/(app)/game/[id]/+page.svelte b/src/routes/(app)/game/[id]/+page.svelte index 63361b6..7e47477 100644 --- a/src/routes/(app)/game/[id]/+page.svelte +++ b/src/routes/(app)/game/[id]/+page.svelte @@ -79,12 +79,6 @@ {mechanic.name} {/each} -
-

Expansions

- {#each game?.expansions as expansions} - {expansions?.base_game?.name} - {/each} -
{@html game?.description}
@@ -98,6 +92,30 @@ {/if} +
+

Expansion Of

+ +
+
+

Expansions

+ +