diff --git a/.eslintrc.cjs b/.eslintrc.cjs index ebc1958..4b29a01 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,30 +1,30 @@ module.exports = { - root: true, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:svelte/recommended', - 'prettier' - ], - parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint'], - parserOptions: { - sourceType: 'module', - ecmaVersion: 2020, - extraFileExtensions: ['.svelte'] - }, - env: { - browser: true, - es2017: true, - node: true - }, - overrides: [ - { - files: ['*.svelte'], - parser: 'svelte-eslint-parser', - parserOptions: { - parser: '@typescript-eslint/parser' - } - } - ] + root: true, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:svelte/recommended', + 'prettier' + ], + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint'], + parserOptions: { + sourceType: 'module', + ecmaVersion: 2020, + extraFileExtensions: ['.svelte'] + }, + env: { + browser: true, + es2017: true, + node: true + }, + overrides: [ + { + files: ['*.svelte'], + parser: 'svelte-eslint-parser', + parserOptions: { + parser: '@typescript-eslint/parser' + } + } + ] }; diff --git a/.prettierrc b/.prettierrc index 9573023..0580f3e 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,8 +1,8 @@ { - "useTabs": true, - "singleQuote": true, - "trailingComma": "none", - "printWidth": 100, - "plugins": ["prettier-plugin-svelte"], - "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] + "useTabs": false, + "singleQuote": true, + "trailingComma": "none", + "printWidth": 100, + "plugins": ["prettier-plugin-svelte"], + "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] } diff --git a/package.json b/package.json index aef9d17..0f0bc19 100644 --- a/package.json +++ b/package.json @@ -1,33 +1,41 @@ { - "name": "larsen", - "version": "0.0.1", - "private": true, - "scripts": { - "dev": "vite dev", - "build": "vite build", - "preview": "vite preview", - "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", - "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", - "test": "vitest", - "lint": "prettier --check . && eslint .", - "format": "prettier --write ." - }, - "devDependencies": { - "@sveltejs/adapter-auto": "^2.0.0", - "@sveltejs/kit": "^1.27.4", - "@typescript-eslint/eslint-plugin": "^6.0.0", - "@typescript-eslint/parser": "^6.0.0", - "eslint": "^8.28.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-svelte": "^2.30.0", - "prettier": "^3.0.0", - "prettier-plugin-svelte": "^3.0.0", - "svelte": "^4.0.5", - "svelte-check": "^3.6.0", - "tslib": "^2.4.1", - "typescript": "^5.0.0", - "vite": "^4.4.2", - "vitest": "^0.34.0" - }, - "type": "module" + "name": "larsen", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "test": "vitest", + "lint": "prettier --check . && eslint .", + "format": "prettier --write ." + }, + "devDependencies": { + "@sveltejs/adapter-auto": "^2.0.0", + "@sveltejs/kit": "^1.27.4", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "eslint": "^8.28.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-svelte": "^2.30.0", + "prettier": "^3.0.0", + "prettier-plugin-svelte": "^3.0.0", + "prisma": "^5.6.0", + "svelte": "^4.0.5", + "svelte-check": "^3.6.0", + "tslib": "^2.4.1", + "typescript": "^5.0.0", + "vite": "^4.4.2", + "vitest": "^0.34.0" + }, + "type": "module", + "dependencies": { + "@aws-sdk/client-s3": "^3.454.0", + "@lucia-auth/adapter-prisma": "^3.0.2", + "@picocss/pico": "^1.5.10", + "@prisma/client": "5.6.0", + "lucia": "^2.7.4" + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a34d4ef..41c57b3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,23 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +dependencies: + '@aws-sdk/client-s3': + specifier: ^3.454.0 + version: 3.454.0 + '@lucia-auth/adapter-prisma': + specifier: ^3.0.2 + version: 3.0.2(@prisma/client@5.6.0)(lucia@2.7.4) + '@picocss/pico': + specifier: ^1.5.10 + version: 1.5.10 + '@prisma/client': + specifier: 5.6.0 + version: 5.6.0(prisma@5.6.0) + lucia: + specifier: ^2.7.4 + version: 2.7.4 + devDependencies: '@sveltejs/adapter-auto': specifier: ^2.0.0 @@ -32,6 +49,9 @@ devDependencies: prettier-plugin-svelte: specifier: ^3.0.0 version: 3.1.0(prettier@3.1.0)(svelte@4.2.5) + prisma: + specifier: ^5.6.0 + version: 5.6.0 svelte: specifier: ^4.0.5 version: 4.2.5 @@ -66,6 +86,588 @@ packages: '@jridgewell/trace-mapping': 0.3.20 dev: true + /@aws-crypto/crc32@3.0.0: + resolution: {integrity: sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==} + dependencies: + '@aws-crypto/util': 3.0.0 + '@aws-sdk/types': 3.451.0 + tslib: 1.14.1 + dev: false + + /@aws-crypto/crc32c@3.0.0: + resolution: {integrity: sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==} + dependencies: + '@aws-crypto/util': 3.0.0 + '@aws-sdk/types': 3.451.0 + tslib: 1.14.1 + dev: false + + /@aws-crypto/ie11-detection@3.0.0: + resolution: {integrity: sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==} + dependencies: + tslib: 1.14.1 + dev: false + + /@aws-crypto/sha1-browser@3.0.0: + resolution: {integrity: sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==} + dependencies: + '@aws-crypto/ie11-detection': 3.0.0 + '@aws-crypto/supports-web-crypto': 3.0.0 + '@aws-crypto/util': 3.0.0 + '@aws-sdk/types': 3.451.0 + '@aws-sdk/util-locate-window': 3.310.0 + '@aws-sdk/util-utf8-browser': 3.259.0 + tslib: 1.14.1 + dev: false + + /@aws-crypto/sha256-browser@3.0.0: + resolution: {integrity: sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==} + dependencies: + '@aws-crypto/ie11-detection': 3.0.0 + '@aws-crypto/sha256-js': 3.0.0 + '@aws-crypto/supports-web-crypto': 3.0.0 + '@aws-crypto/util': 3.0.0 + '@aws-sdk/types': 3.451.0 + '@aws-sdk/util-locate-window': 3.310.0 + '@aws-sdk/util-utf8-browser': 3.259.0 + tslib: 1.14.1 + dev: false + + /@aws-crypto/sha256-js@3.0.0: + resolution: {integrity: sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==} + dependencies: + '@aws-crypto/util': 3.0.0 + '@aws-sdk/types': 3.451.0 + tslib: 1.14.1 + dev: false + + /@aws-crypto/supports-web-crypto@3.0.0: + resolution: {integrity: sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==} + dependencies: + tslib: 1.14.1 + dev: false + + /@aws-crypto/util@3.0.0: + resolution: {integrity: sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==} + dependencies: + '@aws-sdk/types': 3.451.0 + '@aws-sdk/util-utf8-browser': 3.259.0 + tslib: 1.14.1 + dev: false + + /@aws-sdk/client-s3@3.454.0: + resolution: {integrity: sha512-vBx4iB1c4mEz+twMnl6angC1/IpnmXaT8L6Kl9uNiurFsb6N4tCyrJ24kECdsOSTM7ePXvE1fKst8zAh6MW5ZA==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-crypto/sha1-browser': 3.0.0 + '@aws-crypto/sha256-browser': 3.0.0 + '@aws-crypto/sha256-js': 3.0.0 + '@aws-sdk/client-sts': 3.454.0 + '@aws-sdk/core': 3.451.0 + '@aws-sdk/credential-provider-node': 3.451.0 + '@aws-sdk/middleware-bucket-endpoint': 3.451.0 + '@aws-sdk/middleware-expect-continue': 3.451.0 + '@aws-sdk/middleware-flexible-checksums': 3.451.0 + '@aws-sdk/middleware-host-header': 3.451.0 + '@aws-sdk/middleware-location-constraint': 3.451.0 + '@aws-sdk/middleware-logger': 3.451.0 + '@aws-sdk/middleware-recursion-detection': 3.451.0 + '@aws-sdk/middleware-sdk-s3': 3.451.0 + '@aws-sdk/middleware-signing': 3.451.0 + '@aws-sdk/middleware-ssec': 3.451.0 + '@aws-sdk/middleware-user-agent': 3.451.0 + '@aws-sdk/region-config-resolver': 3.451.0 + '@aws-sdk/signature-v4-multi-region': 3.451.0 + '@aws-sdk/types': 3.451.0 + '@aws-sdk/util-endpoints': 3.451.0 + '@aws-sdk/util-user-agent-browser': 3.451.0 + '@aws-sdk/util-user-agent-node': 3.451.0 + '@aws-sdk/xml-builder': 3.310.0 + '@smithy/config-resolver': 2.0.18 + '@smithy/eventstream-serde-browser': 2.0.13 + '@smithy/eventstream-serde-config-resolver': 2.0.13 + '@smithy/eventstream-serde-node': 2.0.13 + '@smithy/fetch-http-handler': 2.2.6 + '@smithy/hash-blob-browser': 2.0.14 + '@smithy/hash-node': 2.0.15 + '@smithy/hash-stream-node': 2.0.15 + '@smithy/invalid-dependency': 2.0.13 + '@smithy/md5-js': 2.0.15 + '@smithy/middleware-content-length': 2.0.15 + '@smithy/middleware-endpoint': 2.2.0 + '@smithy/middleware-retry': 2.0.20 + '@smithy/middleware-serde': 2.0.13 + '@smithy/middleware-stack': 2.0.7 + '@smithy/node-config-provider': 2.1.5 + '@smithy/node-http-handler': 2.1.9 + '@smithy/protocol-http': 3.0.9 + '@smithy/smithy-client': 2.1.15 + '@smithy/types': 2.5.0 + '@smithy/url-parser': 2.0.13 + '@smithy/util-base64': 2.0.1 + '@smithy/util-body-length-browser': 2.0.0 + '@smithy/util-body-length-node': 2.1.0 + '@smithy/util-defaults-mode-browser': 2.0.19 + '@smithy/util-defaults-mode-node': 2.0.25 + '@smithy/util-endpoints': 1.0.4 + '@smithy/util-retry': 2.0.6 + '@smithy/util-stream': 2.0.20 + '@smithy/util-utf8': 2.0.2 + '@smithy/util-waiter': 2.0.13 + fast-xml-parser: 4.2.5 + tslib: 2.6.2 + transitivePeerDependencies: + - aws-crt + dev: false + + /@aws-sdk/client-sso@3.451.0: + resolution: {integrity: sha512-KkYSke3Pdv3MfVH/5fT528+MKjMyPKlcLcd4zQb0x6/7Bl7EHrPh1JZYjzPLHelb+UY5X0qN8+cb8iSu1eiwIQ==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-crypto/sha256-browser': 3.0.0 + '@aws-crypto/sha256-js': 3.0.0 + '@aws-sdk/core': 3.451.0 + '@aws-sdk/middleware-host-header': 3.451.0 + '@aws-sdk/middleware-logger': 3.451.0 + '@aws-sdk/middleware-recursion-detection': 3.451.0 + '@aws-sdk/middleware-user-agent': 3.451.0 + '@aws-sdk/region-config-resolver': 3.451.0 + '@aws-sdk/types': 3.451.0 + '@aws-sdk/util-endpoints': 3.451.0 + '@aws-sdk/util-user-agent-browser': 3.451.0 + '@aws-sdk/util-user-agent-node': 3.451.0 + '@smithy/config-resolver': 2.0.18 + '@smithy/fetch-http-handler': 2.2.6 + '@smithy/hash-node': 2.0.15 + '@smithy/invalid-dependency': 2.0.13 + '@smithy/middleware-content-length': 2.0.15 + '@smithy/middleware-endpoint': 2.2.0 + '@smithy/middleware-retry': 2.0.20 + '@smithy/middleware-serde': 2.0.13 + '@smithy/middleware-stack': 2.0.7 + '@smithy/node-config-provider': 2.1.5 + '@smithy/node-http-handler': 2.1.9 + '@smithy/protocol-http': 3.0.9 + '@smithy/smithy-client': 2.1.15 + '@smithy/types': 2.5.0 + '@smithy/url-parser': 2.0.13 + '@smithy/util-base64': 2.0.1 + '@smithy/util-body-length-browser': 2.0.0 + '@smithy/util-body-length-node': 2.1.0 + '@smithy/util-defaults-mode-browser': 2.0.19 + '@smithy/util-defaults-mode-node': 2.0.25 + '@smithy/util-endpoints': 1.0.4 + '@smithy/util-retry': 2.0.6 + '@smithy/util-utf8': 2.0.2 + tslib: 2.6.2 + transitivePeerDependencies: + - aws-crt + dev: false + + /@aws-sdk/client-sts@3.454.0: + resolution: {integrity: sha512-0fDvr8WeB6IYO8BUCzcivWmahgGl/zDbaYfakzGnt4mrl5ztYaXE875WI6b7+oFcKMRvN+KLvwu5TtyFuNY+GQ==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-crypto/sha256-browser': 3.0.0 + '@aws-crypto/sha256-js': 3.0.0 + '@aws-sdk/core': 3.451.0 + '@aws-sdk/credential-provider-node': 3.451.0 + '@aws-sdk/middleware-host-header': 3.451.0 + '@aws-sdk/middleware-logger': 3.451.0 + '@aws-sdk/middleware-recursion-detection': 3.451.0 + '@aws-sdk/middleware-sdk-sts': 3.451.0 + '@aws-sdk/middleware-signing': 3.451.0 + '@aws-sdk/middleware-user-agent': 3.451.0 + '@aws-sdk/region-config-resolver': 3.451.0 + '@aws-sdk/types': 3.451.0 + '@aws-sdk/util-endpoints': 3.451.0 + '@aws-sdk/util-user-agent-browser': 3.451.0 + '@aws-sdk/util-user-agent-node': 3.451.0 + '@smithy/config-resolver': 2.0.18 + '@smithy/fetch-http-handler': 2.2.6 + '@smithy/hash-node': 2.0.15 + '@smithy/invalid-dependency': 2.0.13 + '@smithy/middleware-content-length': 2.0.15 + '@smithy/middleware-endpoint': 2.2.0 + '@smithy/middleware-retry': 2.0.20 + '@smithy/middleware-serde': 2.0.13 + '@smithy/middleware-stack': 2.0.7 + '@smithy/node-config-provider': 2.1.5 + '@smithy/node-http-handler': 2.1.9 + '@smithy/protocol-http': 3.0.9 + '@smithy/smithy-client': 2.1.15 + '@smithy/types': 2.5.0 + '@smithy/url-parser': 2.0.13 + '@smithy/util-base64': 2.0.1 + '@smithy/util-body-length-browser': 2.0.0 + '@smithy/util-body-length-node': 2.1.0 + '@smithy/util-defaults-mode-browser': 2.0.19 + '@smithy/util-defaults-mode-node': 2.0.25 + '@smithy/util-endpoints': 1.0.4 + '@smithy/util-retry': 2.0.6 + '@smithy/util-utf8': 2.0.2 + fast-xml-parser: 4.2.5 + tslib: 2.6.2 + transitivePeerDependencies: + - aws-crt + dev: false + + /@aws-sdk/core@3.451.0: + resolution: {integrity: sha512-SamWW2zHEf1ZKe3j1w0Piauryl8BQIlej0TBS18A4ACzhjhWXhCs13bO1S88LvPR5mBFXok3XOT6zPOnKDFktw==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/smithy-client': 2.1.15 + tslib: 2.6.2 + dev: false + + /@aws-sdk/credential-provider-env@3.451.0: + resolution: {integrity: sha512-9dAav7DcRgaF7xCJEQR5ER9ErXxnu/tdnVJ+UPmb1NPeIZdESv1A3lxFDEq1Fs8c4/lzAj9BpshGyJVIZwZDKg==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/types': 3.451.0 + '@smithy/property-provider': 2.0.14 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/credential-provider-ini@3.451.0: + resolution: {integrity: sha512-TySt64Ci5/ZbqFw1F9Z0FIGvYx5JSC9e6gqDnizIYd8eMnn8wFRUscRrD7pIHKfrhvVKN5h0GdYovmMO/FMCBw==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/credential-provider-env': 3.451.0 + '@aws-sdk/credential-provider-process': 3.451.0 + '@aws-sdk/credential-provider-sso': 3.451.0 + '@aws-sdk/credential-provider-web-identity': 3.451.0 + '@aws-sdk/types': 3.451.0 + '@smithy/credential-provider-imds': 2.1.1 + '@smithy/property-provider': 2.0.14 + '@smithy/shared-ini-file-loader': 2.2.4 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + transitivePeerDependencies: + - aws-crt + dev: false + + /@aws-sdk/credential-provider-node@3.451.0: + resolution: {integrity: sha512-AEwM1WPyxUdKrKyUsKyFqqRFGU70e4qlDyrtBxJnSU9NRLZI8tfEZ67bN7fHSxBUBODgDXpMSlSvJiBLh5/3pw==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/credential-provider-env': 3.451.0 + '@aws-sdk/credential-provider-ini': 3.451.0 + '@aws-sdk/credential-provider-process': 3.451.0 + '@aws-sdk/credential-provider-sso': 3.451.0 + '@aws-sdk/credential-provider-web-identity': 3.451.0 + '@aws-sdk/types': 3.451.0 + '@smithy/credential-provider-imds': 2.1.1 + '@smithy/property-provider': 2.0.14 + '@smithy/shared-ini-file-loader': 2.2.4 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + transitivePeerDependencies: + - aws-crt + dev: false + + /@aws-sdk/credential-provider-process@3.451.0: + resolution: {integrity: sha512-HQywSdKeD5PErcLLnZfSyCJO+6T+ZyzF+Lm/QgscSC+CbSUSIPi//s15qhBRVely/3KBV6AywxwNH+5eYgt4lQ==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/types': 3.451.0 + '@smithy/property-provider': 2.0.14 + '@smithy/shared-ini-file-loader': 2.2.4 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/credential-provider-sso@3.451.0: + resolution: {integrity: sha512-Usm/N51+unOt8ID4HnQzxIjUJDrkAQ1vyTOC0gSEEJ7h64NSSPGD5yhN7il5WcErtRd3EEtT1a8/GTC5TdBctg==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/client-sso': 3.451.0 + '@aws-sdk/token-providers': 3.451.0 + '@aws-sdk/types': 3.451.0 + '@smithy/property-provider': 2.0.14 + '@smithy/shared-ini-file-loader': 2.2.4 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + transitivePeerDependencies: + - aws-crt + dev: false + + /@aws-sdk/credential-provider-web-identity@3.451.0: + resolution: {integrity: sha512-Xtg3Qw65EfDjWNG7o2xD6sEmumPfsy3WDGjk2phEzVg8s7hcZGxf5wYwe6UY7RJvlEKrU0rFA+AMn6Hfj5oOzg==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/types': 3.451.0 + '@smithy/property-provider': 2.0.14 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/middleware-bucket-endpoint@3.451.0: + resolution: {integrity: sha512-KWyZ1JGnYz2QbHuJtYTP1BVnMOfVopR8rP8dTinVb/JR5HfAYz4imICJlJUbOYRjN7wpA3PrRI8dNRjrSBjWJg==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/types': 3.451.0 + '@aws-sdk/util-arn-parser': 3.310.0 + '@smithy/node-config-provider': 2.1.5 + '@smithy/protocol-http': 3.0.9 + '@smithy/types': 2.5.0 + '@smithy/util-config-provider': 2.0.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/middleware-expect-continue@3.451.0: + resolution: {integrity: sha512-vwG8o2Uk6biLDlOZnqXemsO4dS2HvrprUdxyouwu6hlzLFskg8nL122butn19JqXJKgcVLuSSLzT+xwqBWy2Rg==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/types': 3.451.0 + '@smithy/protocol-http': 3.0.9 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/middleware-flexible-checksums@3.451.0: + resolution: {integrity: sha512-eOkpcC2zgAvqs1w7Yp5nsk9LBIj6qLU5kaZuZEBOiFbNKIrTnPo6dQuhgvDcKHD6Y5W/cUjSBiFMs/ROb5aoug==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-crypto/crc32': 3.0.0 + '@aws-crypto/crc32c': 3.0.0 + '@aws-sdk/types': 3.451.0 + '@smithy/is-array-buffer': 2.0.0 + '@smithy/protocol-http': 3.0.9 + '@smithy/types': 2.5.0 + '@smithy/util-utf8': 2.0.2 + tslib: 2.6.2 + dev: false + + /@aws-sdk/middleware-host-header@3.451.0: + resolution: {integrity: sha512-j8a5jAfhWmsK99i2k8oR8zzQgXrsJtgrLxc3js6U+525mcZytoiDndkWTmD5fjJ1byU1U2E5TaPq+QJeDip05Q==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/types': 3.451.0 + '@smithy/protocol-http': 3.0.9 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/middleware-location-constraint@3.451.0: + resolution: {integrity: sha512-R4U2G7mybP0BMiQBJWTcB47g49F4PSXTiCsvMDp5WOEhpWvGQuO1ZIhTxCl5s5lgTSne063Os8W6KSdK2yG2TQ==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/types': 3.451.0 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/middleware-logger@3.451.0: + resolution: {integrity: sha512-0kHrYEyVeB2QBfP6TfbI240aRtatLZtcErJbhpiNUb+CQPgEL3crIjgVE8yYiJumZ7f0jyjo8HLPkwD1/2APaw==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/types': 3.451.0 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/middleware-recursion-detection@3.451.0: + resolution: {integrity: sha512-J6jL6gJ7orjHGM70KDRcCP7so/J2SnkN4vZ9YRLTeeZY6zvBuHDjX8GCIgSqPn/nXFXckZO8XSnA7u6+3TAT0w==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/types': 3.451.0 + '@smithy/protocol-http': 3.0.9 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/middleware-sdk-s3@3.451.0: + resolution: {integrity: sha512-XF4Cw8HrYUwGLKOqKtWs6ss1WXoxvQUcgGLACGSqn9a0p51446NiS5671x7qJUsfBuygdKlIKcOc8pPr9a+5Ow==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/types': 3.451.0 + '@aws-sdk/util-arn-parser': 3.310.0 + '@smithy/protocol-http': 3.0.9 + '@smithy/smithy-client': 2.1.15 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/middleware-sdk-sts@3.451.0: + resolution: {integrity: sha512-UJ6UfVUEgp0KIztxpAeelPXI5MLj9wUtUCqYeIMP7C1ZhoEMNm3G39VLkGN43dNhBf1LqjsV9jkKMZbVfYXuwg==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/middleware-signing': 3.451.0 + '@aws-sdk/types': 3.451.0 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/middleware-signing@3.451.0: + resolution: {integrity: sha512-s5ZlcIoLNg1Huj4Qp06iKniE8nJt/Pj1B/fjhWc6cCPCM7XJYUCejCnRh6C5ZJoBEYodjuwZBejPc1Wh3j+znA==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/types': 3.451.0 + '@smithy/property-provider': 2.0.14 + '@smithy/protocol-http': 3.0.9 + '@smithy/signature-v4': 2.0.15 + '@smithy/types': 2.5.0 + '@smithy/util-middleware': 2.0.6 + tslib: 2.6.2 + dev: false + + /@aws-sdk/middleware-ssec@3.451.0: + resolution: {integrity: sha512-hDkeBUiRsvuDbvsPha0/uJHE680WDzjAOoE6ZnLBoWsw7ry+Bw1ULMj0sCmpBVrQ7Gpivi/6zbezhClVmt3ITw==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/types': 3.451.0 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/middleware-user-agent@3.451.0: + resolution: {integrity: sha512-8NM/0JiKLNvT9wtAQVl1DFW0cEO7OvZyLSUBLNLTHqyvOZxKaZ8YFk7d8PL6l76LeUKRxq4NMxfZQlUIRe0eSA==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/types': 3.451.0 + '@aws-sdk/util-endpoints': 3.451.0 + '@smithy/protocol-http': 3.0.9 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/region-config-resolver@3.451.0: + resolution: {integrity: sha512-3iMf4OwzrFb4tAAmoROXaiORUk2FvSejnHIw/XHvf/jjR4EqGGF95NZP/n/MeFZMizJWVssrwS412GmoEyoqhg==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/node-config-provider': 2.1.5 + '@smithy/types': 2.5.0 + '@smithy/util-config-provider': 2.0.0 + '@smithy/util-middleware': 2.0.6 + tslib: 2.6.2 + dev: false + + /@aws-sdk/signature-v4-multi-region@3.451.0: + resolution: {integrity: sha512-qQKY7/txeNUTLyRL3WxUWEwaZ5sf76EIZgu9kLaR96cAYSxwQi/qQB3ijbfD6u7sJIA8aROMxeYK0VmRsQg0CA==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/types': 3.451.0 + '@smithy/protocol-http': 3.0.9 + '@smithy/signature-v4': 2.0.15 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/token-providers@3.451.0: + resolution: {integrity: sha512-ij1L5iUbn6CwxVOT1PG4NFjsrsKN9c4N1YEM0lkl6DwmaNOscjLKGSNyj9M118vSWsOs1ZDbTwtj++h0O/BWrQ==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-crypto/sha256-browser': 3.0.0 + '@aws-crypto/sha256-js': 3.0.0 + '@aws-sdk/middleware-host-header': 3.451.0 + '@aws-sdk/middleware-logger': 3.451.0 + '@aws-sdk/middleware-recursion-detection': 3.451.0 + '@aws-sdk/middleware-user-agent': 3.451.0 + '@aws-sdk/region-config-resolver': 3.451.0 + '@aws-sdk/types': 3.451.0 + '@aws-sdk/util-endpoints': 3.451.0 + '@aws-sdk/util-user-agent-browser': 3.451.0 + '@aws-sdk/util-user-agent-node': 3.451.0 + '@smithy/config-resolver': 2.0.18 + '@smithy/fetch-http-handler': 2.2.6 + '@smithy/hash-node': 2.0.15 + '@smithy/invalid-dependency': 2.0.13 + '@smithy/middleware-content-length': 2.0.15 + '@smithy/middleware-endpoint': 2.2.0 + '@smithy/middleware-retry': 2.0.20 + '@smithy/middleware-serde': 2.0.13 + '@smithy/middleware-stack': 2.0.7 + '@smithy/node-config-provider': 2.1.5 + '@smithy/node-http-handler': 2.1.9 + '@smithy/property-provider': 2.0.14 + '@smithy/protocol-http': 3.0.9 + '@smithy/shared-ini-file-loader': 2.2.4 + '@smithy/smithy-client': 2.1.15 + '@smithy/types': 2.5.0 + '@smithy/url-parser': 2.0.13 + '@smithy/util-base64': 2.0.1 + '@smithy/util-body-length-browser': 2.0.0 + '@smithy/util-body-length-node': 2.1.0 + '@smithy/util-defaults-mode-browser': 2.0.19 + '@smithy/util-defaults-mode-node': 2.0.25 + '@smithy/util-endpoints': 1.0.4 + '@smithy/util-retry': 2.0.6 + '@smithy/util-utf8': 2.0.2 + tslib: 2.6.2 + transitivePeerDependencies: + - aws-crt + dev: false + + /@aws-sdk/types@3.451.0: + resolution: {integrity: sha512-rhK+qeYwCIs+laJfWCcrYEjay2FR/9VABZJ2NRM89jV/fKqGVQR52E5DQqrI+oEIL5JHMhhnr4N4fyECMS35lw==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/util-arn-parser@3.310.0: + resolution: {integrity: sha512-jL8509owp/xB9+Or0pvn3Fe+b94qfklc2yPowZZIFAkFcCSIdkIglz18cPDWnYAcy9JGewpMS1COXKIUhZkJsA==} + engines: {node: '>=14.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + + /@aws-sdk/util-endpoints@3.451.0: + resolution: {integrity: sha512-giqLGBTnRIcKkDqwU7+GQhKbtJ5Ku35cjGQIfMyOga6pwTBUbaK0xW1Sdd8sBQ1GhApscnChzI9o/R9x0368vw==} + engines: {node: '>=14.0.0'} + dependencies: + '@aws-sdk/types': 3.451.0 + '@smithy/util-endpoints': 1.0.4 + tslib: 2.6.2 + dev: false + + /@aws-sdk/util-locate-window@3.310.0: + resolution: {integrity: sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==} + engines: {node: '>=14.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + + /@aws-sdk/util-user-agent-browser@3.451.0: + resolution: {integrity: sha512-Ws5mG3J0TQifH7OTcMrCTexo7HeSAc3cBgjfhS/ofzPUzVCtsyg0G7I6T7wl7vJJETix2Kst2cpOsxygPgPD9w==} + dependencies: + '@aws-sdk/types': 3.451.0 + '@smithy/types': 2.5.0 + bowser: 2.11.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/util-user-agent-node@3.451.0: + resolution: {integrity: sha512-TBzm6P+ql4mkGFAjPlO1CI+w3yUT+NulaiALjl/jNX/nnUp6HsJsVxJf4nVFQTG5KRV0iqMypcs7I3KIhH+LmA==} + engines: {node: '>=14.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + dependencies: + '@aws-sdk/types': 3.451.0 + '@smithy/node-config-provider': 2.1.5 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@aws-sdk/util-utf8-browser@3.259.0: + resolution: {integrity: sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==} + dependencies: + tslib: 2.6.2 + dev: false + + /@aws-sdk/xml-builder@3.310.0: + resolution: {integrity: sha512-TqELu4mOuSIKQCqj63fGVs86Yh+vBx5nHRpWKNUNhB2nPTpfbziTs5c1X358be3peVWA4wPxW7Nt53KIg1tnNw==} + engines: {node: '>=14.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + /@esbuild/android-arm64@0.18.20: resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} engines: {node: '>=12'} @@ -363,6 +965,16 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /@lucia-auth/adapter-prisma@3.0.2(@prisma/client@5.6.0)(lucia@2.7.4): + resolution: {integrity: sha512-EyJWZene1/zasPwPctv8wwNErZt5mwwm5JATbhg+kXr3R8pbC7lJfVzDTAeeFClVH5k/FywRcsBl3JkPaNIcow==} + peerDependencies: + '@prisma/client': ^4.2.0 || ^5.0.0 + lucia: ^2.0.0 + dependencies: + '@prisma/client': 5.6.0(prisma@5.6.0) + lucia: 2.7.4 + dev: false + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -384,14 +996,478 @@ packages: fastq: 1.15.0 dev: true + /@picocss/pico@1.5.10: + resolution: {integrity: sha512-+LafMsrwPxXQMk6sI///TmSInCwwZmq+K7SikyL3N/4GhhwzyPC+TQLUEqmrLyjluR+uIpFFcqjty30Rtr6GxQ==} + dev: false + /@polka/url@1.0.0-next.23: resolution: {integrity: sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==} dev: true + /@prisma/client@5.6.0(prisma@5.6.0): + resolution: {integrity: sha512-mUDefQFa1wWqk4+JhKPYq8BdVoFk9NFMBXUI8jAkBfQTtgx8WPx02U2HB/XbAz3GSUJpeJOKJQtNvaAIDs6sug==} + engines: {node: '>=16.13'} + requiresBuild: true + peerDependencies: + prisma: '*' + peerDependenciesMeta: + prisma: + optional: true + dependencies: + '@prisma/engines-version': 5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee + prisma: 5.6.0 + dev: false + + /@prisma/engines-version@5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee: + resolution: {integrity: sha512-UoFgbV1awGL/3wXuUK3GDaX2SolqczeeJ5b4FVec9tzeGbSWJboPSbT0psSrmgYAKiKnkOPFSLlH6+b+IyOwAw==} + dev: false + + /@prisma/engines@5.6.0: + resolution: {integrity: sha512-Mt2q+GNJpU2vFn6kif24oRSBQv1KOkYaterQsi0k2/lA+dLvhRX6Lm26gon6PYHwUM8/h8KRgXIUMU0PCLB6bw==} + requiresBuild: true + /@sinclair/typebox@0.27.8: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true + /@smithy/abort-controller@2.0.13: + resolution: {integrity: sha512-eeOPD+GF9BzF/Mjy3PICLePx4l0f3rG/nQegQHRLTloN5p1lSJJNZsyn+FzDnW8P2AduragZqJdtKNCxXozB1Q==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/chunked-blob-reader-native@2.0.1: + resolution: {integrity: sha512-N2oCZRglhWKm7iMBu7S6wDzXirjAofi7tAd26cxmgibRYOBS4D3hGfmkwCpHdASZzwZDD8rluh0Rcqw1JeZDRw==} + dependencies: + '@smithy/util-base64': 2.0.1 + tslib: 2.6.2 + dev: false + + /@smithy/chunked-blob-reader@2.0.0: + resolution: {integrity: sha512-k+J4GHJsMSAIQPChGBrjEmGS+WbPonCXesoqP9fynIqjn7rdOThdH8FAeCmokP9mxTYKQAKoHCLPzNlm6gh7Wg==} + dependencies: + tslib: 2.6.2 + dev: false + + /@smithy/config-resolver@2.0.18: + resolution: {integrity: sha512-761sJSgNbvsqcsKW6/WZbrZr4H+0Vp/QKKqwyrxCPwD8BsiPEXNHyYnqNgaeK9xRWYswjon0Uxbpe3DWQo0j/g==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/node-config-provider': 2.1.5 + '@smithy/types': 2.5.0 + '@smithy/util-config-provider': 2.0.0 + '@smithy/util-middleware': 2.0.6 + tslib: 2.6.2 + dev: false + + /@smithy/credential-provider-imds@2.1.1: + resolution: {integrity: sha512-gw5G3FjWC6sNz8zpOJgPpH5HGKrpoVFQpToNAwLwJVyI/LJ2jDJRjSKEsM6XI25aRpYjMSE/Qptxx305gN1vHw==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/node-config-provider': 2.1.5 + '@smithy/property-provider': 2.0.14 + '@smithy/types': 2.5.0 + '@smithy/url-parser': 2.0.13 + tslib: 2.6.2 + dev: false + + /@smithy/eventstream-codec@2.0.13: + resolution: {integrity: sha512-CExbelIYp+DxAHG8RIs0l9QL7ElqhG4ym9BNoSpkPa4ptBQfzJdep3LbOSVJIE2VUdBAeObdeL6EDB3Jo85n3g==} + dependencies: + '@aws-crypto/crc32': 3.0.0 + '@smithy/types': 2.5.0 + '@smithy/util-hex-encoding': 2.0.0 + tslib: 2.6.2 + dev: false + + /@smithy/eventstream-serde-browser@2.0.13: + resolution: {integrity: sha512-OJ/2g/VxkzA+mYZxV102oX3CsiE+igTSmqq/ir3oEVG2kSIdRC00ryttj/lmL14W06ExNi0ysmfLxQkL8XrAZQ==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/eventstream-serde-universal': 2.0.13 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/eventstream-serde-config-resolver@2.0.13: + resolution: {integrity: sha512-2BI1CbnYuEvAYoWSeWJtPNygbIKiWeSLxCmDLnyM6wQV32Of7VptiQlaFXPxXp4zqn/rs3ocZ/T29rxE4s4Gsg==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/eventstream-serde-node@2.0.13: + resolution: {integrity: sha512-7NbFwPafb924elFxCBDvm48jy/DeSrpFbFQN0uN2ThuY5HrEeubikS0t7WMva4Z4EnRoivpbuT0scb9vUIJKoA==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/eventstream-serde-universal': 2.0.13 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/eventstream-serde-universal@2.0.13: + resolution: {integrity: sha512-j0yFd5UfftM+ia9dxLRbheJDCkCZBHpcEzCsPO8BxVOTbdcX/auVJCv6ov/yvpCKsf4Hv3mOqi0Is1YogM2g3Q==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/eventstream-codec': 2.0.13 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/fetch-http-handler@2.2.6: + resolution: {integrity: sha512-PStY3XO1Ksjwn3wMKye5U6m6zxXpXrXZYqLy/IeCbh3nM9QB3Jgw/B0PUSLUWKdXg4U8qgEu300e3ZoBvZLsDg==} + dependencies: + '@smithy/protocol-http': 3.0.9 + '@smithy/querystring-builder': 2.0.13 + '@smithy/types': 2.5.0 + '@smithy/util-base64': 2.0.1 + tslib: 2.6.2 + dev: false + + /@smithy/hash-blob-browser@2.0.14: + resolution: {integrity: sha512-yWdghyPJIEqLYsaE7YVgd3YhM7jN4Pv6eJQvTomnMsz5K2qRBlpjUx3T9fKlElp1qdeQ7DNc3sAat4i9CUBO7Q==} + dependencies: + '@smithy/chunked-blob-reader': 2.0.0 + '@smithy/chunked-blob-reader-native': 2.0.1 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/hash-node@2.0.15: + resolution: {integrity: sha512-t/qjEJZu/G46A22PAk1k/IiJZT4ncRkG5GOCNWN9HPPy5rCcSZUbh7gwp7CGKgJJ7ATMMg+0Td7i9o1lQTwOfQ==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/types': 2.5.0 + '@smithy/util-buffer-from': 2.0.0 + '@smithy/util-utf8': 2.0.2 + tslib: 2.6.2 + dev: false + + /@smithy/hash-stream-node@2.0.15: + resolution: {integrity: sha512-ZZ6kC/pHt5Dc2goXIIyC8uA7A4GUMSzdCynAabnZ3CSSaV6ctP8mlvVkqjPph0O3XzHlx/80gdLrNqi1GDPUsA==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/types': 2.5.0 + '@smithy/util-utf8': 2.0.2 + tslib: 2.6.2 + dev: false + + /@smithy/invalid-dependency@2.0.13: + resolution: {integrity: sha512-XsGYhVhvEikX1Yz0kyIoLssJf2Rs6E0U2w2YuKdT4jSra5A/g8V2oLROC1s56NldbgnpesTYB2z55KCHHbKyjw==} + dependencies: + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/is-array-buffer@2.0.0: + resolution: {integrity: sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==} + engines: {node: '>=14.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + + /@smithy/md5-js@2.0.15: + resolution: {integrity: sha512-pAZaokib56XvhU0t/R9vAcr3L3bMhIakhF25X7EMSQ7LAURiLfce/tgON8I3x/dIbnZUyeRi8f2cx2azu6ATew==} + dependencies: + '@smithy/types': 2.5.0 + '@smithy/util-utf8': 2.0.2 + tslib: 2.6.2 + dev: false + + /@smithy/middleware-content-length@2.0.15: + resolution: {integrity: sha512-xH4kRBw01gJgWiU+/mNTrnyFXeozpZHw39gLb3JKGsFDVmSrJZ8/tRqu27tU/ki1gKkxr2wApu+dEYjI3QwV1Q==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/protocol-http': 3.0.9 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/middleware-endpoint@2.2.0: + resolution: {integrity: sha512-tddRmaig5URk2106PVMiNX6mc5BnKIKajHHDxb7K0J5MLdcuQluHMGnjkv18iY9s9O0tF+gAcPd/pDXA5L9DZw==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/middleware-serde': 2.0.13 + '@smithy/node-config-provider': 2.1.5 + '@smithy/shared-ini-file-loader': 2.2.4 + '@smithy/types': 2.5.0 + '@smithy/url-parser': 2.0.13 + '@smithy/util-middleware': 2.0.6 + tslib: 2.6.2 + dev: false + + /@smithy/middleware-retry@2.0.20: + resolution: {integrity: sha512-X2yrF/SHDk2WDd8LflRNS955rlzQ9daz9UWSp15wW8KtzoTXg3bhHM78HbK1cjr48/FWERSJKh9AvRUUGlIawg==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/node-config-provider': 2.1.5 + '@smithy/protocol-http': 3.0.9 + '@smithy/service-error-classification': 2.0.6 + '@smithy/types': 2.5.0 + '@smithy/util-middleware': 2.0.6 + '@smithy/util-retry': 2.0.6 + tslib: 2.6.2 + uuid: 8.3.2 + dev: false + + /@smithy/middleware-serde@2.0.13: + resolution: {integrity: sha512-tBGbeXw+XsE6pPr4UaXOh+UIcXARZeiA8bKJWxk2IjJcD1icVLhBSUQH9myCIZLNNzJIH36SDjUX8Wqk4xJCJg==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/middleware-stack@2.0.7: + resolution: {integrity: sha512-L1KLAAWkXbGx1t2jjCI/mDJ2dDNq+rp4/ifr/HcC6FHngxho5O7A5bQLpKHGlkfATH6fUnOEx0VICEVFA4sUzw==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/node-config-provider@2.1.5: + resolution: {integrity: sha512-3Omb5/h4tOCuKRx4p4pkYTvEYRCYoKk52bOYbKUyz/G/8gERbagsN8jFm4FjQubkrcIqQEghTpQaUw6uk+0edw==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/property-provider': 2.0.14 + '@smithy/shared-ini-file-loader': 2.2.4 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/node-http-handler@2.1.9: + resolution: {integrity: sha512-+K0q3SlNcocmo9OZj+fz67gY4lwhOCvIJxVbo/xH+hfWObvaxrMTx7JEzzXcluK0thnnLz++K3Qe7Z/8MDUreA==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/abort-controller': 2.0.13 + '@smithy/protocol-http': 3.0.9 + '@smithy/querystring-builder': 2.0.13 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/property-provider@2.0.14: + resolution: {integrity: sha512-k3D2qp9o6imTrLaXRj6GdLYEJr1sXqS99nLhzq8fYmJjSVOeMg/G+1KVAAc7Oxpu71rlZ2f8SSZxcSxkevuR0A==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/protocol-http@3.0.9: + resolution: {integrity: sha512-U1wl+FhYu4/BC+rjwh1lg2gcJChQhytiNQSggREgQ9G2FzmoK9sACBZvx7thyWMvRyHQTE22mO2d5UM8gMKDBg==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/querystring-builder@2.0.13: + resolution: {integrity: sha512-JhXKwp3JtsFUe96XLHy/nUPEbaXqn6r7xE4sNaH8bxEyytE5q1fwt0ew/Ke6+vIC7gP87HCHgQpJHg1X1jN2Fw==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/types': 2.5.0 + '@smithy/util-uri-escape': 2.0.0 + tslib: 2.6.2 + dev: false + + /@smithy/querystring-parser@2.0.13: + resolution: {integrity: sha512-TEiT6o8CPZVxJ44Rly/rrsATTQsE+b/nyBVzsYn2sa75xAaZcurNxsFd8z1haoUysONiyex24JMHoJY6iCfLdA==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/service-error-classification@2.0.6: + resolution: {integrity: sha512-fCQ36frtYra2fqY2/DV8+3/z2d0VB/1D1hXbjRcM5wkxTToxq6xHbIY/NGGY6v4carskMyG8FHACxgxturJ9Pg==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/types': 2.5.0 + dev: false + + /@smithy/shared-ini-file-loader@2.2.4: + resolution: {integrity: sha512-9dRknGgvYlRIsoTcmMJXuoR/3ekhGwhRq4un3ns2/byre4Ql5hyUN4iS0x8eITohjU90YOnUCsbRwZRvCkbRfw==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/signature-v4@2.0.15: + resolution: {integrity: sha512-SRTEJSEhQYVlBKIIdZ9SZpqW+KFqxqcNnEcBX+8xkDdWx+DItme9VcCDkdN32yTIrICC+irUufnUdV7mmHPjoA==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/eventstream-codec': 2.0.13 + '@smithy/is-array-buffer': 2.0.0 + '@smithy/types': 2.5.0 + '@smithy/util-hex-encoding': 2.0.0 + '@smithy/util-middleware': 2.0.6 + '@smithy/util-uri-escape': 2.0.0 + '@smithy/util-utf8': 2.0.2 + tslib: 2.6.2 + dev: false + + /@smithy/smithy-client@2.1.15: + resolution: {integrity: sha512-rngZcQu7Jvs9UbHihK1EI67RMPuzkc3CJmu4MBgB7D7yBnMGuFR86tq5rqHfL2gAkNnMelBN/8kzQVvZjNKefQ==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/middleware-stack': 2.0.7 + '@smithy/types': 2.5.0 + '@smithy/util-stream': 2.0.20 + tslib: 2.6.2 + dev: false + + /@smithy/types@2.5.0: + resolution: {integrity: sha512-/a31lYofrMBkJb3BuPlYJTMKDj0hUmKUP6JFZQu6YVuQVoAjubiY0A52U9S0Uysd33n/djexCUSNJ+G9bf3/aA==} + engines: {node: '>=14.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + + /@smithy/url-parser@2.0.13: + resolution: {integrity: sha512-okWx2P/d9jcTsZWTVNnRMpFOE7fMkzloSFyM53fA7nLKJQObxM2T4JlZ5KitKKuXq7pxon9J6SF2kCwtdflIrA==} + dependencies: + '@smithy/querystring-parser': 2.0.13 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/util-base64@2.0.1: + resolution: {integrity: sha512-DlI6XFYDMsIVN+GH9JtcRp3j02JEVuWIn/QOZisVzpIAprdsxGveFed0bjbMRCqmIFe8uetn5rxzNrBtIGrPIQ==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/util-buffer-from': 2.0.0 + tslib: 2.6.2 + dev: false + + /@smithy/util-body-length-browser@2.0.0: + resolution: {integrity: sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==} + dependencies: + tslib: 2.6.2 + dev: false + + /@smithy/util-body-length-node@2.1.0: + resolution: {integrity: sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==} + engines: {node: '>=14.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + + /@smithy/util-buffer-from@2.0.0: + resolution: {integrity: sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/is-array-buffer': 2.0.0 + tslib: 2.6.2 + dev: false + + /@smithy/util-config-provider@2.0.0: + resolution: {integrity: sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==} + engines: {node: '>=14.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + + /@smithy/util-defaults-mode-browser@2.0.19: + resolution: {integrity: sha512-VHP8xdFR7/orpiABJwgoTB0t8Zhhwpf93gXhNfUBiwAE9O0rvsv7LwpQYjgvbOUDDO8JfIYQB2GYJNkqqGWsXw==} + engines: {node: '>= 10.0.0'} + dependencies: + '@smithy/property-provider': 2.0.14 + '@smithy/smithy-client': 2.1.15 + '@smithy/types': 2.5.0 + bowser: 2.11.0 + tslib: 2.6.2 + dev: false + + /@smithy/util-defaults-mode-node@2.0.25: + resolution: {integrity: sha512-jkmep6/JyWmn2ADw9VULDeGbugR4N/FJCKOt+gYyVswmN1BJOfzF2umaYxQ1HhQDvna3kzm1Dbo1qIfBW4iuHA==} + engines: {node: '>= 10.0.0'} + dependencies: + '@smithy/config-resolver': 2.0.18 + '@smithy/credential-provider-imds': 2.1.1 + '@smithy/node-config-provider': 2.1.5 + '@smithy/property-provider': 2.0.14 + '@smithy/smithy-client': 2.1.15 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/util-endpoints@1.0.4: + resolution: {integrity: sha512-FPry8j1xye5yzrdnf4xKUXVnkQErxdN7bUIaqC0OFoGsv2NfD9b2UUMuZSSt+pr9a8XWAqj0HoyVNUfPiZ/PvQ==} + engines: {node: '>= 14.0.0'} + dependencies: + '@smithy/node-config-provider': 2.1.5 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/util-hex-encoding@2.0.0: + resolution: {integrity: sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==} + engines: {node: '>=14.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + + /@smithy/util-middleware@2.0.6: + resolution: {integrity: sha512-7W4uuwBvSLgKoLC1x4LfeArCVcbuHdtVaC4g30kKsD1erfICyQ45+tFhhs/dZNeQg+w392fhunCm/+oCcb6BSA==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/util-retry@2.0.6: + resolution: {integrity: sha512-PSO41FofOBmyhPQJwBQJ6mVlaD7Sp9Uff9aBbnfBJ9eqXOE/obrqQjn0PNdkfdvViiPXl49BINfnGcFtSP4kYw==} + engines: {node: '>= 14.0.0'} + dependencies: + '@smithy/service-error-classification': 2.0.6 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + + /@smithy/util-stream@2.0.20: + resolution: {integrity: sha512-tT8VASuD8jJu0yjHEMTCPt1o5E3FVzgdsxK6FQLAjXKqVv5V8InCnc0EOsYrijgspbfDqdAJg7r0o2sySfcHVg==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/fetch-http-handler': 2.2.6 + '@smithy/node-http-handler': 2.1.9 + '@smithy/types': 2.5.0 + '@smithy/util-base64': 2.0.1 + '@smithy/util-buffer-from': 2.0.0 + '@smithy/util-hex-encoding': 2.0.0 + '@smithy/util-utf8': 2.0.2 + tslib: 2.6.2 + dev: false + + /@smithy/util-uri-escape@2.0.0: + resolution: {integrity: sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==} + engines: {node: '>=14.0.0'} + dependencies: + tslib: 2.6.2 + dev: false + + /@smithy/util-utf8@2.0.2: + resolution: {integrity: sha512-qOiVORSPm6Ce4/Yu6hbSgNHABLP2VMv8QOC3tTDNHHlWY19pPyc++fBTbZPtx6egPXi4HQxKDnMxVxpbtX2GoA==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/util-buffer-from': 2.0.0 + tslib: 2.6.2 + dev: false + + /@smithy/util-waiter@2.0.13: + resolution: {integrity: sha512-YovIQatiuM7giEsRFotqJa2i3EbU2EE3PgtpXgtLgpx5rXiZMAwPxXYDFVFhuO0lbqvc/Zx4n+ZIisXOHPSqyg==} + engines: {node: '>=14.0.0'} + dependencies: + '@smithy/abort-controller': 2.0.13 + '@smithy/types': 2.5.0 + tslib: 2.6.2 + dev: false + /@sveltejs/adapter-auto@2.1.1(@sveltejs/kit@1.27.6): resolution: {integrity: sha512-nzi6x/7/3Axh5VKQ8Eed3pYxastxoa06Y/bFhWb7h3Nu+nGRVxKAy3+hBJgmPCwWScy8n0TsstZjSVKfyrIHkg==} peerDependencies: @@ -761,6 +1837,10 @@ packages: engines: {node: '>=8'} dev: true + /bowser@2.11.0: + resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} + dev: false + /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -1157,6 +2237,13 @@ packages: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} dev: true + /fast-xml-parser@4.2.5: + resolution: {integrity: sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==} + hasBin: true + dependencies: + strnum: 1.0.5 + dev: false + /fastq@1.15.0: resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} dependencies: @@ -1435,6 +2522,10 @@ packages: yallist: 4.0.0 dev: true + /lucia@2.7.4: + resolution: {integrity: sha512-do6Aah5kX2DUl7N0CvELWV1/b+qZGF0AUmUrkthYeNfXfgx4RAkWi4BkAlgGDBB/0c1WApb18mUD1pA5qTaWmw==} + dev: false + /magic-string@0.27.0: resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} engines: {node: '>=12'} @@ -1707,6 +2798,14 @@ packages: react-is: 18.2.0 dev: true + /prisma@5.6.0: + resolution: {integrity: sha512-EEaccku4ZGshdr2cthYHhf7iyvCcXqwJDvnoQRAJg5ge2Tzpv0e2BaMCp+CbbDUwoVTzwgOap9Zp+d4jFa2O9A==} + engines: {node: '>=16.13'} + hasBin: true + requiresBuild: true + dependencies: + '@prisma/engines': 5.6.0 + /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -1871,6 +2970,10 @@ packages: acorn: 8.11.2 dev: true + /strnum@1.0.5: + resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + dev: false + /supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -2044,9 +3147,12 @@ packages: typescript: 5.2.2 dev: true + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: false + /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - dev: true /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} @@ -2096,6 +3202,11 @@ packages: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: true + /uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + dev: false + /vite-node@0.34.6(@types/node@20.9.2): resolution: {integrity: sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==} engines: {node: '>=v14.18.0'} diff --git a/prisma/dev.db b/prisma/dev.db new file mode 100644 index 0000000..80cc27a Binary files /dev/null and b/prisma/dev.db differ diff --git a/prisma/schema.prisma b/prisma/schema.prisma new file mode 100644 index 0000000..d46d1cf --- /dev/null +++ b/prisma/schema.prisma @@ -0,0 +1,62 @@ +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "sqlite" + url = env("DATABASE_URL") +} + +model User { + id String @id @unique + username String @unique + tracks Track[] + comments Comment[] + + auth_session Session[] + key Key[] +} + +// Auth Stuff +model Session { + id String @id @unique + user_id String + active_expires BigInt + idle_expires BigInt + user User @relation(references: [id], fields: [user_id], onDelete: Cascade) + + @@index([user_id]) +} + +model Key { + id String @id @unique + hashed_password String? + user_id String + user User @relation(references: [id], fields: [user_id], onDelete: Cascade) + + @@index([user_id]) +} + +// Application stuff +model Track { + id Int @id @default(autoincrement()) + title String + versions TrackVersion[] + producer User @relation(fields: [producerId], references: [id], onDelete: Cascade) + producerId String +} + +model TrackVersion { + id Int @id @default(autoincrement()) + track Track @relation(fields: [trackId], references: [id], onDelete: Cascade) + trackId Int + comments Comment[] +} + +model Comment { + id Int @id @default(autoincrement()) + author User @relation(fields: [authorId], references: [id]) + authorId String + trackVersion TrackVersion @relation(fields: [trackVersionId], references: [id], onDelete: Cascade) + trackVersionId Int +} diff --git a/src/app.css b/src/app.css new file mode 100644 index 0000000..4c81113 --- /dev/null +++ b/src/app.css @@ -0,0 +1,37 @@ +/* Teal Light scheme (Default) */ +/* Can be forced with data-theme="light" */ +[data-theme='light'], +:root:not([data-theme='dark']) { + --primary: #00897b; + --primary-hover: #00796b; + --primary-focus: rgba(0, 137, 123, 0.125); + --primary-inverse: #fff; +} + +/* Teal Dark scheme (Auto) */ +/* Automatically enabled if user has Dark mode enabled */ +@media only screen and (prefers-color-scheme: dark) { + :root:not([data-theme]) { + --primary: #00897b; + --primary-hover: #009688; + --primary-focus: rgba(0, 137, 123, 0.25); + --primary-inverse: #fff; + } +} + +/* Teal Dark scheme (Forced) */ +/* Enabled if forced with data-theme="dark" */ +[data-theme='dark'] { + --primary: #00897b; + --primary-hover: #009688; + --primary-focus: rgba(0, 137, 123, 0.25); + --primary-inverse: #fff; +} + +/* Teal (Common styles) */ +:root { + --form-element-active-border-color: var(--primary); + --form-element-focus-color: var(--primary-focus); + --switch-color: var(--primary-inverse); + --switch-checked-background-color: var(--primary); +} diff --git a/src/app.d.ts b/src/app.d.ts index f59b884..c075c65 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -1,12 +1,30 @@ // See https://kit.svelte.dev/docs/types#app + +import type { PrismaClient } from '@prisma/client'; +import type { Auth, AuthRequest } from 'lucia'; + // for information about these interfaces declare global { - namespace App { - // interface Error {} - // interface Locals {} - // interface PageData {} - // interface Platform {} - } + namespace App { + // interface Error {} + interface Locals { + database: PrismaClient; + auth: Auth; + objectStorage: ObjectStorage; + + authReq: AuthRequest; + } + // interface PageData {} + // interface Platform {} + } + + namespace Lucia { + type Auth = import('$lib/server/lucia').Auth; + type DatabaseUserAttributes = { + username: string; + }; + type DatabaseSessionAttributes = {}; + } } export {}; diff --git a/src/app.html b/src/app.html index 77a5ff5..84ffad1 100644 --- a/src/app.html +++ b/src/app.html @@ -1,12 +1,12 @@ - - - - - %sveltekit.head% - - -
%sveltekit.body%
- + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ diff --git a/src/hooks.server.ts b/src/hooks.server.ts new file mode 100644 index 0000000..abfb510 --- /dev/null +++ b/src/hooks.server.ts @@ -0,0 +1,17 @@ +import type { Handle } from '@sveltejs/kit'; + +import { S3_STORAGE_URL } from '$env/static/private'; + +import { auth } from '$lib/server/lucia'; +import { ObjectStorageS3 } from '$lib/server/storage/s3'; + +const s3Client = new ObjectStorageS3(S3_STORAGE_URL); + +export const handle: Handle = async ({ event, resolve }) => { + event.locals.auth = auth; + event.locals.objectStorage = s3Client; + + event.locals.authReq = auth.handleRequest(event); + + return await resolve(event); +}; diff --git a/src/index.test.ts b/src/index.test.ts index e07cbbd..964d287 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect } from 'vitest'; describe('sum test', () => { - it('adds 1 + 2 to equal 3', () => { - expect(1 + 2).toBe(3); - }); + it('adds 1 + 2 to equal 3', () => { + expect(1 + 2).toBe(3); + }); }); diff --git a/src/lib/server/lucia.ts b/src/lib/server/lucia.ts new file mode 100644 index 0000000..cf4eedd --- /dev/null +++ b/src/lib/server/lucia.ts @@ -0,0 +1,19 @@ +import { lucia } from 'lucia'; +import { sveltekit } from 'lucia/middleware'; +import { dev } from '$app/environment'; +import { prisma } from '@lucia-auth/adapter-prisma'; +import { PrismaClient } from '@prisma/client'; + +const client = new PrismaClient(); + +export const auth = lucia({ + env: dev ? 'DEV' : 'PROD', + middleware: sveltekit(), + adapter: prisma(client), + + getUserAttributes: (data) => { + return { + username: data.username + }; + } +}); diff --git a/src/lib/server/s3.ts b/src/lib/server/s3.ts new file mode 100644 index 0000000..92e9a1f --- /dev/null +++ b/src/lib/server/s3.ts @@ -0,0 +1,20 @@ +import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3'; + +const client = new S3Client(); + +const uploadObject = async (obj: Buffer) => { + const command = new PutObjectCommand({ + Bucket: 'test-bucket', + Key: 'hello-s3.txt', + Body: obj + }); + + try { + await client.send(command); + return null; + } catch (err) { + return err; + } +}; + +export { uploadObject }; diff --git a/src/lib/server/storage/index.ts b/src/lib/server/storage/index.ts new file mode 100644 index 0000000..6e5e732 --- /dev/null +++ b/src/lib/server/storage/index.ts @@ -0,0 +1,3 @@ +interface ObjectStorage { + putObject: (obj: Buffer) => Promise; +} diff --git a/src/lib/server/storage/s3.ts b/src/lib/server/storage/s3.ts new file mode 100644 index 0000000..dc33902 --- /dev/null +++ b/src/lib/server/storage/s3.ts @@ -0,0 +1,29 @@ +import { PutObjectCommand, S3Client, S3ServiceException } from '@aws-sdk/client-s3'; + +class ObjectStorageS3 implements ObjectStorage { + client: S3Client; + + constructor(url: string) { + this.client = new S3Client({ + endpoint: url + }); + } + + putObject = async (obj: Buffer) => { + const command = new PutObjectCommand({ + Bucket: 'test-bucket', + Key: 'hello-s3.txt', + Body: obj + }); + + try { + await this.client.send(command); + } catch (err) { + return err as S3ServiceException; + } + + return null; + }; +} + +export { ObjectStorageS3 }; diff --git a/src/lib/validators.ts b/src/lib/validators.ts new file mode 100644 index 0000000..abec529 --- /dev/null +++ b/src/lib/validators.ts @@ -0,0 +1,6 @@ +const validatePassword = (password: string) => { + const passwordRe = /^.{8,255}$/; + return passwordRe.test(password); +}; + +export { validatePassword }; diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts new file mode 100644 index 0000000..8f4534c --- /dev/null +++ b/src/routes/+layout.server.ts @@ -0,0 +1,7 @@ +import type { LayoutServerLoad } from './$types'; + +export const load: LayoutServerLoad = async ({ locals: { authReq } }) => { + return { + isLoggedIn: authReq.validate() + }; +}; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte new file mode 100644 index 0000000..df150ba --- /dev/null +++ b/src/routes/+layout.svelte @@ -0,0 +1,31 @@ + + + + + + + + +
+ +
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 5982b0a..3b64160 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,2 +1,5 @@ -

Welcome to SvelteKit

-

Visit kit.svelte.dev to read the documentation

+ + Larsen + + +

Your Tracks

diff --git a/src/routes/login/+page.server.ts b/src/routes/login/+page.server.ts new file mode 100644 index 0000000..7941c35 --- /dev/null +++ b/src/routes/login/+page.server.ts @@ -0,0 +1,54 @@ +import { validatePassword } from '$lib/validators'; +import { LuciaError } from 'lucia'; +import type { Actions, PageServerLoad } from './$types'; + +import { fail, redirect } from '@sveltejs/kit'; + +export const load: PageServerLoad = async ({ locals: { authReq } }) => { + const session = await authReq.validate(); + if (session) throw redirect(302, '/'); + return {}; +}; + +export const actions: Actions = { + default: async ({ request, locals: { auth, authReq } }) => { + const formData = await request.formData(); + + const username = formData.get('username') as string; + const password = formData.get('password') as string; + + if (!validatePassword(password)) { + return fail(400, { + message: 'Password has an invalid length; must be between 8 and 255 characters.' + }); + } + + try { + const key = await auth.useKey('username', username.toLowerCase(), password); + + const session = await auth.createSession({ + userId: key.userId, + attributes: {} + }); + + authReq.setSession(session); + } catch (err) { + // Auth errors + if ( + err instanceof LuciaError && + (err.message === 'AUTH_INVALID_KEY_ID' || err.message === 'AUTH_INVALID_PASSWORD') + ) { + return fail(400, { + message: 'Incorrect username or password' + }); + } + + // Bad errors + return fail(500, { + message: 'Internal server error; please try again later.' + }); + } + + throw redirect(302, '/'); + } +}; diff --git a/src/routes/login/+page.svelte b/src/routes/login/+page.svelte new file mode 100644 index 0000000..e4ed558 --- /dev/null +++ b/src/routes/login/+page.svelte @@ -0,0 +1,85 @@ + + + + Login | Larsen + + +
+
+
+

Login

+ {#if form} +

{form?.message}

+ {:else} +

Username and password, please

+ {/if} +
+ +
+ + +
+ +
+ + +

+ Don't have an account? Sign Up Now +

+
+
+
+
+ + diff --git a/src/routes/signup/+page.server.ts b/src/routes/signup/+page.server.ts new file mode 100644 index 0000000..5d31232 --- /dev/null +++ b/src/routes/signup/+page.server.ts @@ -0,0 +1,60 @@ +import type { Actions, PageServerLoad } from './$types'; + +import { fail, redirect } from '@sveltejs/kit'; +import { validatePassword } from '$lib/validators'; +import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library'; + +export const load: PageServerLoad = async ({ locals: { authReq } }) => { + const session = await authReq.validate(); + if (session) throw redirect(302, '/'); + return {}; +}; + +export const actions: Actions = { + default: async ({ request, locals: { auth, authReq } }) => { + const formData = await request.formData(); + + const username = formData.get('username') as string; + const password = formData.get('password') as string; + + if (!validatePassword(password)) { + return fail(400, { + message: 'Password has an invalid length; must be between 8 and 255 characters.' + }); + } + + // Create user and set session + try { + const user = await auth.createUser({ + key: { + providerId: 'username', + providerUserId: username.toLowerCase(), + password + }, + attributes: { + username + } + }); + + const session = await auth.createSession({ + userId: user.userId, + attributes: {} + }); + + authReq.setSession(session); + } catch (err) { + if (err instanceof PrismaClientKnownRequestError && err.code === 'P2002') { + return fail(400, { + message: 'User already exists.' + }); + } + + console.log(err); + return fail(500, { + message: 'Internal server error, please try again later.' + }); + } + + throw redirect(302, '/'); + } +}; diff --git a/src/routes/signup/+page.svelte b/src/routes/signup/+page.svelte new file mode 100644 index 0000000..f0e485d --- /dev/null +++ b/src/routes/signup/+page.svelte @@ -0,0 +1,105 @@ + + + + Sign Up | Larsen + + +
+
+
+

Sign Up

+ {#if form} +

{form?.message}

+ {:else} +

Give me your soul.

+ {/if} +
+ +
+ + + + No silly requirements. Just 8 characters. + +
+ +
+ + +

+ Already have an account? Login Now +

+
+
+
+
+ + diff --git a/src/routes/upload/+page.svelte b/src/routes/upload/+page.svelte new file mode 100644 index 0000000..5bf31f0 --- /dev/null +++ b/src/routes/upload/+page.svelte @@ -0,0 +1,33 @@ + + + + Upload | Larsen + + +
+
+
+

Upload a New Track

+ {#if form} +

{form?.message}

+ {:else} +

Some good tunes.

+ {/if} +
+ + + + + + +
+
diff --git a/svelte.config.js b/svelte.config.js index 1cf26a0..ecaf275 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -3,16 +3,16 @@ import { vitePreprocess } from '@sveltejs/kit/vite'; /** @type {import('@sveltejs/kit').Config} */ const config = { - // Consult https://kit.svelte.dev/docs/integrations#preprocessors - // for more information about preprocessors - preprocess: vitePreprocess(), + // Consult https://kit.svelte.dev/docs/integrations#preprocessors + // for more information about preprocessors + preprocess: vitePreprocess(), - kit: { - // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. - // If your environment is not supported or you settled on a specific environment, switch out the adapter. - // See https://kit.svelte.dev/docs/adapters for more information about adapters. - adapter: adapter() - } + kit: { + // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. + // If your environment is not supported or you settled on a specific environment, switch out the adapter. + // See https://kit.svelte.dev/docs/adapters for more information about adapters. + adapter: adapter() + } }; export default config; diff --git a/tsconfig.json b/tsconfig.json index 82081ab..34aadc0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,18 +1,18 @@ { - "extends": "./.svelte-kit/tsconfig.json", - "compilerOptions": { - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "moduleResolution": "bundler" - } - // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias - // - // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes - // from the referenced tsconfig.json - TypeScript does not merge them in + "extends": "./.svelte-kit/tsconfig.json", + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "moduleResolution": "bundler" + } + // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias + // + // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes + // from the referenced tsconfig.json - TypeScript does not merge them in } diff --git a/vite.config.ts b/vite.config.ts index 37b6a84..0131ff9 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -2,8 +2,8 @@ import { sveltekit } from '@sveltejs/kit/vite'; import { defineConfig } from 'vitest/config'; export default defineConfig({ - plugins: [sveltekit()], - test: { - include: ['src/**/*.{test,spec}.{js,ts}'] - } + plugins: [sveltekit()], + test: { + include: ['src/**/*.{test,spec}.{js,ts}'] + } });