From af078e7ba2c8d7760603467670bf3917ce810013 Mon Sep 17 00:00:00 2001 From: Face <69168154+face-hh@users.noreply.github.com> Date: Thu, 22 May 2025 13:17:11 +0300 Subject: [PATCH] auth & sidebar --- website/bun.lock | 147 +++---- .../drizzle/0000_wonderful_mephistopheles.sql | 62 +++ website/drizzle/0001_sleepy_queen_noir.sql | 2 + website/drizzle/meta/0000_snapshot.json | 321 ++++++++++++++ website/drizzle/meta/0001_snapshot.json | 321 ++++++++++++++ website/drizzle/meta/_journal.json | 20 + website/package-lock.json | 397 +++++++++++++++++- website/package.json | 5 +- website/src/app.css | 103 +++-- website/src/hooks.server.ts | 10 + website/src/lib/auth-client.ts | 12 + website/src/lib/auth.ts | 56 +++ .../src/lib/components/self/AppSidebar.svelte | 140 ++++++ .../self/SignInConfirmDialog.svelte | 48 +++ .../components/ui/dialog/dialog-close.svelte | 7 + .../ui/dialog/dialog-content.svelte | 39 ++ .../ui/dialog/dialog-description.svelte | 17 + .../components/ui/dialog/dialog-footer.svelte | 20 + .../components/ui/dialog/dialog-header.svelte | 20 + .../ui/dialog/dialog-overlay.svelte | 20 + .../components/ui/dialog/dialog-title.svelte | 17 + .../ui/dialog/dialog-trigger.svelte | 7 + website/src/lib/components/ui/dialog/index.ts | 37 ++ website/src/lib/components/ui/input/index.ts | 7 + .../src/lib/components/ui/input/input.svelte | 51 +++ .../src/lib/components/ui/separator/index.ts | 7 + .../components/ui/separator/separator.svelte | 20 + website/src/lib/components/ui/sheet/index.ts | 36 ++ .../components/ui/sheet/sheet-close.svelte | 7 + .../components/ui/sheet/sheet-content.svelte | 58 +++ .../ui/sheet/sheet-description.svelte | 17 + .../components/ui/sheet/sheet-footer.svelte | 20 + .../components/ui/sheet/sheet-header.svelte | 20 + .../components/ui/sheet/sheet-overlay.svelte | 22 + .../components/ui/sheet/sheet-title.svelte | 17 + .../components/ui/sheet/sheet-trigger.svelte | 7 + .../lib/components/ui/sidebar/constants.ts | 6 + .../components/ui/sidebar/context.svelte.ts | 81 ++++ .../src/lib/components/ui/sidebar/index.ts | 75 ++++ .../ui/sidebar/sidebar-content.svelte | 24 ++ .../ui/sidebar/sidebar-footer.svelte | 21 + .../ui/sidebar/sidebar-group-action.svelte | 36 ++ .../ui/sidebar/sidebar-group-content.svelte | 21 + .../ui/sidebar/sidebar-group-label.svelte | 34 ++ .../ui/sidebar/sidebar-group.svelte | 21 + .../ui/sidebar/sidebar-header.svelte | 21 + .../ui/sidebar/sidebar-input.svelte | 21 + .../ui/sidebar/sidebar-inset.svelte | 24 ++ .../ui/sidebar/sidebar-menu-action.svelte | 43 ++ .../ui/sidebar/sidebar-menu-badge.svelte | 29 ++ .../ui/sidebar/sidebar-menu-button.svelte | 103 +++++ .../ui/sidebar/sidebar-menu-item.svelte | 21 + .../ui/sidebar/sidebar-menu-skeleton.svelte | 36 ++ .../ui/sidebar/sidebar-menu-sub-button.svelte | 43 ++ .../ui/sidebar/sidebar-menu-sub-item.svelte | 21 + .../ui/sidebar/sidebar-menu-sub.svelte | 25 ++ .../components/ui/sidebar/sidebar-menu.svelte | 21 + .../ui/sidebar/sidebar-provider.svelte | 53 +++ .../components/ui/sidebar/sidebar-rail.svelte | 36 ++ .../ui/sidebar/sidebar-separator.svelte | 19 + .../ui/sidebar/sidebar-trigger.svelte | 35 ++ .../lib/components/ui/sidebar/sidebar.svelte | 104 +++++ .../src/lib/components/ui/skeleton/index.ts | 7 + .../components/ui/skeleton/skeleton.svelte | 17 + .../src/lib/components/ui/tooltip/index.ts | 21 + .../ui/tooltip/tooltip-content.svelte | 47 +++ .../ui/tooltip/tooltip-trigger.svelte | 7 + website/src/lib/hooks/is-mobile.svelte.ts | 9 + website/src/lib/server/db/index.ts | 16 +- website/src/lib/server/db/schema.ts | 52 ++- website/src/lib/stores/user-data.ts | 13 + website/src/routes/+layout.server.ts | 22 + website/src/routes/+layout.svelte | 93 +++- website/static/placeholder_logo.png | Bin 0 -> 20832 bytes 74 files changed, 3262 insertions(+), 133 deletions(-) create mode 100644 website/drizzle/0000_wonderful_mephistopheles.sql create mode 100644 website/drizzle/0001_sleepy_queen_noir.sql create mode 100644 website/drizzle/meta/0000_snapshot.json create mode 100644 website/drizzle/meta/0001_snapshot.json create mode 100644 website/drizzle/meta/_journal.json create mode 100644 website/src/hooks.server.ts create mode 100644 website/src/lib/auth-client.ts create mode 100644 website/src/lib/auth.ts create mode 100644 website/src/lib/components/self/AppSidebar.svelte create mode 100644 website/src/lib/components/self/SignInConfirmDialog.svelte create mode 100644 website/src/lib/components/ui/dialog/dialog-close.svelte create mode 100644 website/src/lib/components/ui/dialog/dialog-content.svelte create mode 100644 website/src/lib/components/ui/dialog/dialog-description.svelte create mode 100644 website/src/lib/components/ui/dialog/dialog-footer.svelte create mode 100644 website/src/lib/components/ui/dialog/dialog-header.svelte create mode 100644 website/src/lib/components/ui/dialog/dialog-overlay.svelte create mode 100644 website/src/lib/components/ui/dialog/dialog-title.svelte create mode 100644 website/src/lib/components/ui/dialog/dialog-trigger.svelte create mode 100644 website/src/lib/components/ui/dialog/index.ts create mode 100644 website/src/lib/components/ui/input/index.ts create mode 100644 website/src/lib/components/ui/input/input.svelte create mode 100644 website/src/lib/components/ui/separator/index.ts create mode 100644 website/src/lib/components/ui/separator/separator.svelte create mode 100644 website/src/lib/components/ui/sheet/index.ts create mode 100644 website/src/lib/components/ui/sheet/sheet-close.svelte create mode 100644 website/src/lib/components/ui/sheet/sheet-content.svelte create mode 100644 website/src/lib/components/ui/sheet/sheet-description.svelte create mode 100644 website/src/lib/components/ui/sheet/sheet-footer.svelte create mode 100644 website/src/lib/components/ui/sheet/sheet-header.svelte create mode 100644 website/src/lib/components/ui/sheet/sheet-overlay.svelte create mode 100644 website/src/lib/components/ui/sheet/sheet-title.svelte create mode 100644 website/src/lib/components/ui/sheet/sheet-trigger.svelte create mode 100644 website/src/lib/components/ui/sidebar/constants.ts create mode 100644 website/src/lib/components/ui/sidebar/context.svelte.ts create mode 100644 website/src/lib/components/ui/sidebar/index.ts create mode 100644 website/src/lib/components/ui/sidebar/sidebar-content.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-footer.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-group-action.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-group-content.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-group-label.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-group.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-header.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-input.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-inset.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-menu-action.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-menu-badge.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-menu-button.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-menu-item.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-menu-sub.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-menu.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-provider.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-rail.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-separator.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar-trigger.svelte create mode 100644 website/src/lib/components/ui/sidebar/sidebar.svelte create mode 100644 website/src/lib/components/ui/skeleton/index.ts create mode 100644 website/src/lib/components/ui/skeleton/skeleton.svelte create mode 100644 website/src/lib/components/ui/tooltip/index.ts create mode 100644 website/src/lib/components/ui/tooltip/tooltip-content.svelte create mode 100644 website/src/lib/components/ui/tooltip/tooltip-trigger.svelte create mode 100644 website/src/lib/hooks/is-mobile.svelte.ts create mode 100644 website/src/lib/stores/user-data.ts create mode 100644 website/src/routes/+layout.server.ts create mode 100644 website/static/placeholder_logo.png diff --git a/website/bun.lock b/website/bun.lock index 6b1a1c3..88ffffe 100644 --- a/website/bun.lock +++ b/website/bun.lock @@ -7,19 +7,22 @@ "@tailwindcss/postcss": "^4.1.7", "@tailwindcss/typography": "^0.5.16", "@visx/scale": "^3.12.0", + "better-auth": "^1.2.8", "drizzle-orm": "^0.33.0", + "lightweight-charts": "^5.0.7", "lucide-svelte": "^0.511.0", "postgres": "^3.4.4", + "svelte-lightweight-charts": "^2.2.0", }, "devDependencies": { - "@lucide/svelte": "^0.511.0", + "@lucide/svelte": "^0.482.0", "@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0", "autoprefixer": "^10.4.20", + "bits-ui": "^1.5.0", "clsx": "^2.1.1", "drizzle-kit": "^0.22.0", - "layerchart": "2.0.0-next.6", "prettier": "^3.3.2", "prettier-plugin-svelte": "^3.2.6", "prettier-plugin-tailwindcss": "^0.6.11", @@ -39,9 +42,9 @@ "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], - "@dagrejs/dagre": ["@dagrejs/dagre@1.1.4", "", { "dependencies": { "@dagrejs/graphlib": "2.2.4" } }, "sha512-QUTc54Cg/wvmlEUxB+uvoPVKFazM1H18kVHBQNmK2NbrDR5ihOCR6CXLnDSZzMcSQKJtabPUWridBOlJM3WkDg=="], + "@better-auth/utils": ["@better-auth/utils@0.2.5", "", { "dependencies": { "typescript": "^5.8.2", "uncrypto": "^0.1.3" } }, "sha512-uI2+/8h/zVsH8RrYdG8eUErbuGBk16rZKQfz8CjxQOyCE6v7BqFYEbFwvOkvl1KbUdxhqOnXp78+uE5h8qVEgQ=="], - "@dagrejs/graphlib": ["@dagrejs/graphlib@2.2.4", "", {}, "sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw=="], + "@better-fetch/fetch": ["@better-fetch/fetch@1.1.18", "", {}, "sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA=="], "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="], @@ -99,6 +102,10 @@ "@floating-ui/utils": ["@floating-ui/utils@0.2.9", "", {}, "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg=="], + "@hexagon/base64": ["@hexagon/base64@1.1.28", "", {}, "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw=="], + + "@internationalized/date": ["@internationalized/date@3.8.1", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-PgVE6B6eIZtzf9Gu5HvJxRK3ufUFz9DhspELuhW/N0GuMGMTLvPQNRkHP2hTuP9lblOk+f+1xi96sPiPXANXAA=="], + "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="], "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], @@ -111,17 +118,23 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], - "@layerstack/svelte-actions": ["@layerstack/svelte-actions@1.0.1-next.2", "", { "dependencies": { "@floating-ui/dom": "^1.7.0", "@layerstack/utils": "1.1.0-next.2", "d3-array": "^3.2.4", "d3-scale": "^4.0.2", "date-fns": "^4.1.0", "lodash-es": "^4.17.21" } }, "sha512-s4iGrFIt+obdHP+Mzre+drCiZttqs5UYSw6CfQs1D2IeqTFkkbvRvYosh47flMi6ElN4psCrCcwn8KntClhMow=="], + "@levischuck/tiny-cbor": ["@levischuck/tiny-cbor@0.2.11", "", {}, "sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow=="], - "@layerstack/svelte-state": ["@layerstack/svelte-state@0.1.0-next.3", "", { "dependencies": { "@layerstack/utils": "1.1.0-next.2" } }, "sha512-SOmu/1RGuBfJ37THo4cbl8Ruiijrhju5+J+w+2/AV2GtUtho51peYI2Zt9rFIwS/L0OtvQwN3oSLcfIuWoxCiQ=="], + "@lucide/svelte": ["@lucide/svelte@0.482.0", "", { "peerDependencies": { "svelte": "^5" } }, "sha512-n2ycHU9cNcleRDwwpEHBJ6pYzVhHIaL3a+9dQa8kns9hB2g05bY+v2p2KP8v0pZwtNhYTHk/F2o2uZ1bVtQGhw=="], - "@layerstack/svelte-stores": ["@layerstack/svelte-stores@1.0.2-next.2", "", { "dependencies": { "@layerstack/utils": "1.1.0-next.2", "d3-array": "^3.2.4", "date-fns": "^4.1.0", "immer": "^10.1.1", "lodash-es": "^4.17.21", "zod": "^3.24.3" } }, "sha512-YC1eEwtRAG+1ek+xdkfHCVoUPrhnVbJM+M4xTzoD4JuIf45GTUtwXop9MARYVX2G3ZlUUw1TdbjmHpfbzVLI9g=="], + "@noble/ciphers": ["@noble/ciphers@0.6.0", "", {}, "sha512-mIbq/R9QXk5/cTfESb1OKtyFnk7oc1Om/8onA1158K9/OZUQFDEVy55jVTato+xmp3XX6F6Qh0zz0Nc1AxAlRQ=="], - "@layerstack/tailwind": ["@layerstack/tailwind@2.0.0-next.4", "", { "dependencies": { "@layerstack/utils": "^1.1.0-next.2", "clsx": "^2.1.1", "culori": "^4.0.1", "d3-array": "^3.2.4", "date-fns": "^4.1.0", "lodash-es": "^4.17.21", "tailwind-merge": "^3.2.0", "tailwindcss": "^4.1.5" } }, "sha512-46QUWvMaYGlGmi17vfT2o6mV7/0ZaWi0qJ4vjPKrayBsxn1mVjqX0cbW7EXC6JnmMVYt5CZu0768rWCM4nGCzA=="], + "@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], - "@layerstack/utils": ["@layerstack/utils@1.1.0-next.2", "", { "dependencies": { "d3-array": "^3.2.4", "date-fns": "^4.1.0", "lodash-es": "^4.17.21" } }, "sha512-9Y4TOAE0iIVvnrf1mkft79rF/vTO84bZuc4hjhJB7XguFjy2f00pEfrDjF+IqleWImMFfRu31K2IMM6wRWEBXQ=="], + "@peculiar/asn1-android": ["@peculiar/asn1-android@2.3.16", "", { "dependencies": { "@peculiar/asn1-schema": "^2.3.15", "asn1js": "^3.0.5", "tslib": "^2.8.1" } }, "sha512-a1viIv3bIahXNssrOIkXZIlI2ePpZaNmR30d4aBL99mu2rO+mT9D6zBsp7H6eROWGtmwv0Ionp5olJurIo09dw=="], - "@lucide/svelte": ["@lucide/svelte@0.511.0", "", { "peerDependencies": { "svelte": "^5" } }, "sha512-aLCSPMUJmHlCuLXzXENXa4Z1NV2mN1iAZAFKk4bEbey+/MdsNlu+/DqwVkgW3Yvj6p8y8Vn5xZ2v9CLmPlA6Vw=="], + "@peculiar/asn1-ecc": ["@peculiar/asn1-ecc@2.3.15", "", { "dependencies": { "@peculiar/asn1-schema": "^2.3.15", "@peculiar/asn1-x509": "^2.3.15", "asn1js": "^3.0.5", "tslib": "^2.8.1" } }, "sha512-/HtR91dvgog7z/WhCVdxZJ/jitJuIu8iTqiyWVgRE9Ac5imt2sT/E4obqIVGKQw7PIy+X6i8lVBoT6wC73XUgA=="], + + "@peculiar/asn1-rsa": ["@peculiar/asn1-rsa@2.3.15", "", { "dependencies": { "@peculiar/asn1-schema": "^2.3.15", "@peculiar/asn1-x509": "^2.3.15", "asn1js": "^3.0.5", "tslib": "^2.8.1" } }, "sha512-p6hsanvPhexRtYSOHihLvUUgrJ8y0FtOM97N5UEpC+VifFYyZa0iZ5cXjTkZoDwxJ/TTJ1IJo3HVTB2JJTpXvg=="], + + "@peculiar/asn1-schema": ["@peculiar/asn1-schema@2.3.15", "", { "dependencies": { "asn1js": "^3.0.5", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "sha512-QPeD8UA8axQREpgR5UTAfu2mqQmm97oUqahDtNdBcfj3qAnoXzFdQW+aNf/tD2WVXF8Fhmftxoj0eMIT++gX2w=="], + + "@peculiar/asn1-x509": ["@peculiar/asn1-x509@2.3.15", "", { "dependencies": { "@peculiar/asn1-schema": "^2.3.15", "asn1js": "^3.0.5", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "sha512-0dK5xqTqSLaxv1FHXIcd4Q/BZNuopg+u1l23hT9rOmQ1g4dNtw0g/RnEi+TboB0gOwGtrWn269v27cMgchFIIg=="], "@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="], @@ -165,6 +178,10 @@ "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.41.0", "", { "os": "win32", "cpu": "x64" }, "sha512-h1J+Yzjo/X+0EAvR2kIXJDuTuyT7drc+t2ALY0nIcGPbTatNOf0VWdhEA2Z4AAjv6X1NJV7SYo5oCTYRJhSlVA=="], + "@simplewebauthn/browser": ["@simplewebauthn/browser@13.1.0", "", {}, "sha512-WuHZ/PYvyPJ9nxSzgHtOEjogBhwJfC8xzYkPC+rR/+8chl/ft4ngjiK8kSU5HtRJfczupyOh33b25TjYbvwAcg=="], + + "@simplewebauthn/server": ["@simplewebauthn/server@13.1.1", "", { "dependencies": { "@hexagon/base64": "^1.1.27", "@levischuck/tiny-cbor": "^0.2.2", "@peculiar/asn1-android": "^2.3.10", "@peculiar/asn1-ecc": "^2.3.8", "@peculiar/asn1-rsa": "^2.3.8", "@peculiar/asn1-schema": "^2.3.8", "@peculiar/asn1-x509": "^2.3.8" } }, "sha512-1hsLpRHfSuMB9ee2aAdh0Htza/X3f4djhYISrggqGe3xopNjOcePiSDkDDoPzDYaaMCrbqGP1H2TYU7bgL9PmA=="], + "@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.5", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ=="], "@sveltejs/adapter-auto": ["@sveltejs/adapter-auto@3.3.1", "", { "dependencies": { "import-meta-resolve": "^4.1.0" }, "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-5Sc7WAxYdL6q9j/+D0jJKjGREGlfIevDyHSQ2eNETHcB1TKlQWHcAo8AS8H1QdjNvSXpvOwNjykDUHPEAyGgdQ=="], @@ -175,6 +192,8 @@ "@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@3.0.1", "", { "dependencies": { "debug": "^4.3.7" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^4.0.0-next.0||^4.0.0", "svelte": "^5.0.0-next.96 || ^5.0.0", "vite": "^5.0.0" } }, "sha512-2CKypmj1sM4GE7HjllT7UKmo4Q6L5xFRd7VMGEWhYnZ+wc6AUVU01IBd7yUi6WnFndEwWoMNOd6e8UjoN0nbvQ=="], + "@swc/helpers": ["@swc/helpers@0.5.17", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A=="], + "@tailwindcss/node": ["@tailwindcss/node@4.1.7", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", "tailwindcss": "4.1.7" } }, "sha512-9rsOpdY9idRI2NH6CL4wORFY0+Q6fnx9XP9Ju+iq/0wJwGD5IByIgFmwVbyy4ymuyprj8Qh4ErxMKTUL4uNh3g=="], "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.7", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.7", "@tailwindcss/oxide-darwin-arm64": "4.1.7", "@tailwindcss/oxide-darwin-x64": "4.1.7", "@tailwindcss/oxide-freebsd-x64": "4.1.7", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.7", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.7", "@tailwindcss/oxide-linux-arm64-musl": "4.1.7", "@tailwindcss/oxide-linux-x64-gnu": "4.1.7", "@tailwindcss/oxide-linux-x64-musl": "4.1.7", "@tailwindcss/oxide-wasm32-wasi": "4.1.7", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.7", "@tailwindcss/oxide-win32-x64-msvc": "4.1.7" } }, "sha512-5SF95Ctm9DFiUyjUPnDGkoKItPX/k+xifcQhcqX5RA85m50jw1pT/KzjdvlqxRja45Y52nR4MR9fD1JYd7f8NQ=="], @@ -239,10 +258,18 @@ "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], + "asn1js": ["asn1js@3.0.6", "", { "dependencies": { "pvtsutils": "^1.3.6", "pvutils": "^1.1.3", "tslib": "^2.8.1" } }, "sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA=="], + "autoprefixer": ["autoprefixer@10.4.21", "", { "dependencies": { "browserslist": "^4.24.4", "caniuse-lite": "^1.0.30001702", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ=="], "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], + "better-auth": ["better-auth@1.2.8", "", { "dependencies": { "@better-auth/utils": "0.2.5", "@better-fetch/fetch": "^1.1.18", "@noble/ciphers": "^0.6.0", "@noble/hashes": "^1.6.1", "@simplewebauthn/browser": "^13.0.0", "@simplewebauthn/server": "^13.0.0", "better-call": "^1.0.8", "defu": "^6.1.4", "jose": "^5.9.6", "kysely": "^0.28.1", "nanostores": "^0.11.3", "zod": "^3.24.1" } }, "sha512-y8ry7ZW3/3ZIr82Eo1zUDtMzdoQlFnwNuZ0+b0RxoNZgqmvgTIc/0tCDC7NDJerqSu4UCzer0dvYxBsv3WMIGg=="], + + "better-call": ["better-call@1.0.9", "", { "dependencies": { "@better-fetch/fetch": "^1.1.4", "rou3": "^0.5.1", "set-cookie-parser": "^2.7.1", "uncrypto": "^0.1.3" } }, "sha512-Qfm0gjk0XQz0oI7qvTK1hbqTsBY4xV2hsHAxF8LZfUYl3RaECCIifXuVqtPpZJWvlCCMlQSvkvhhyuApGUba6g=="], + + "bits-ui": ["bits-ui@1.5.3", "", { "dependencies": { "@floating-ui/core": "^1.6.4", "@floating-ui/dom": "^1.6.7", "@internationalized/date": "^3.5.6", "esm-env": "^1.1.2", "runed": "^0.23.2", "svelte-toolbelt": "^0.7.1", "tabbable": "^6.2.0" }, "peerDependencies": { "svelte": "^5.11.0" } }, "sha512-BTZ9/GU11DaEGyQp+AY+sXCMLZO0gbDC5J8l7+Ngj4Vf6hNOwrpMmoh5iuKktA6cphXYolVkUDgBWmkh415I+w=="], + "browserslist": ["browserslist@4.24.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001716", "electron-to-chromium": "^1.5.149", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw=="], "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], @@ -255,68 +282,34 @@ "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], - "commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="], - "cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="], "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], - "culori": ["culori@4.0.1", "", {}, "sha512-LSnjA6HuIUOlkfKVbzi2OlToZE8OjFi667JWN9qNymXVXzGDmvuP60SSgC+e92sd7B7158f7Fy3Mb6rXS5EDPw=="], - - "d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="], + "d3-array": ["d3-array@3.2.1", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-gUY/qeHq/yNqqoCKNq4vtpFLdoCdvyNpWoC/KNjhGbhDuQpAM9sIQQKkXSNpXa9h5KySs/gzm7R88WkUutgwWQ=="], "d3-color": ["d3-color@3.1.0", "", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="], - "d3-delaunay": ["d3-delaunay@6.0.4", "", { "dependencies": { "delaunator": "5" } }, "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A=="], - - "d3-dispatch": ["d3-dispatch@3.0.1", "", {}, "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg=="], - - "d3-dsv": ["d3-dsv@3.0.1", "", { "dependencies": { "commander": "7", "iconv-lite": "0.6", "rw": "1" }, "bin": { "csv2json": "bin/dsv2json.js", "csv2tsv": "bin/dsv2dsv.js", "dsv2dsv": "bin/dsv2dsv.js", "dsv2json": "bin/dsv2json.js", "json2csv": "bin/json2dsv.js", "json2dsv": "bin/json2dsv.js", "json2tsv": "bin/json2dsv.js", "tsv2csv": "bin/dsv2dsv.js", "tsv2json": "bin/dsv2json.js" } }, "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q=="], - - "d3-force": ["d3-force@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-quadtree": "1 - 3", "d3-timer": "1 - 3" } }, "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg=="], + "d3-delaunay": ["d3-delaunay@6.0.2", "", { "dependencies": { "delaunator": "5" } }, "sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ=="], "d3-format": ["d3-format@3.1.0", "", {}, "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA=="], - "d3-geo": ["d3-geo@3.1.1", "", { "dependencies": { "d3-array": "2.5.0 - 3" } }, "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q=="], - - "d3-geo-voronoi": ["d3-geo-voronoi@2.1.0", "", { "dependencies": { "d3-array": "3", "d3-delaunay": "6", "d3-geo": "3", "d3-tricontour": "1" } }, "sha512-kqE4yYuOjPbKdBXG0xztCacPwkVSK2REF1opSNrnqqtXJmNcM++UbwQ8SxvwP6IQTj9RvIjjK4qeiVsEfj0Z2Q=="], - - "d3-hierarchy": ["d3-hierarchy@3.1.2", "", {}, "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA=="], + "d3-geo": ["d3-geo@3.1.0", "", { "dependencies": { "d3-array": "2.5.0 - 3" } }, "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA=="], "d3-interpolate": ["d3-interpolate@3.0.1", "", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="], - "d3-interpolate-path": ["d3-interpolate-path@2.3.0", "", {}, "sha512-tZYtGXxBmbgHsIc9Wms6LS5u4w6KbP8C09a4/ZYc4KLMYYqub57rRBUgpUr2CIarIrJEpdAWWxWQvofgaMpbKQ=="], - - "d3-path": ["d3-path@3.1.0", "", {}, "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="], - - "d3-quadtree": ["d3-quadtree@3.0.1", "", {}, "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw=="], - - "d3-random": ["d3-random@3.0.1", "", {}, "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ=="], - - "d3-sankey": ["d3-sankey@0.12.3", "", { "dependencies": { "d3-array": "1 - 2", "d3-shape": "^1.2.0" } }, "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ=="], - "d3-scale": ["d3-scale@4.0.2", "", { "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" } }, "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="], - "d3-scale-chromatic": ["d3-scale-chromatic@3.1.0", "", { "dependencies": { "d3-color": "1 - 3", "d3-interpolate": "1 - 3" } }, "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ=="], - - "d3-shape": ["d3-shape@3.2.0", "", { "dependencies": { "d3-path": "^3.1.0" } }, "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA=="], - - "d3-tile": ["d3-tile@1.0.0", "", {}, "sha512-79fnTKpPMPDS5xQ0xuS9ir0165NEwwkFpe/DSOmc2Gl9ldYzKKRDWogmTTE8wAJ8NA7PMapNfEcyKhI9Lxdu5Q=="], - "d3-time": ["d3-time@3.1.0", "", { "dependencies": { "d3-array": "2 - 3" } }, "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="], "d3-time-format": ["d3-time-format@4.1.0", "", { "dependencies": { "d3-time": "1 - 3" } }, "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="], - "d3-timer": ["d3-timer@3.0.1", "", {}, "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="], - - "d3-tricontour": ["d3-tricontour@1.0.2", "", { "dependencies": { "d3-delaunay": "6", "d3-scale": "4" } }, "sha512-HIRxHzHagPtUPNabjOlfcyismJYIsc+Xlq4mlsts4e8eAcwyq9Tgk/sYdyhlBpQ0MHwVquc/8j+e29YjXnmxeA=="], - - "date-fns": ["date-fns@4.1.0", "", {}, "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg=="], - "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], + "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], + "delaunator": ["delaunator@5.0.1", "", { "dependencies": { "robust-predicates": "^3.0.2" } }, "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw=="], "detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="], @@ -341,6 +334,8 @@ "esrap": ["esrap@1.4.6", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } }, "sha512-F/D2mADJ9SHY3IwksD4DAXjTt7qt7GWUf3/8RhCNWmC/67tyb55dpimHmy7EplakFaflV0R/PC+fdSPqrRHAQw=="], + "fancy-canvas": ["fancy-canvas@2.1.0", "", {}, "sha512-nifxXJ95JNLFR2NgRV4/MxVP45G9909wJTEKz5fg/TZS20JJZA6hfgRVh/bC9bwl2zBtBNcYPjiBE4njQHVBwQ=="], + "fdir": ["fdir@6.4.4", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg=="], "fraction.js": ["fraction.js@4.3.7", "", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="], @@ -351,21 +346,21 @@ "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], - "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], - - "immer": ["immer@10.1.1", "", {}, "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw=="], - "import-meta-resolve": ["import-meta-resolve@4.1.0", "", {}, "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw=="], + "inline-style-parser": ["inline-style-parser@0.2.4", "", {}, "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q=="], + "internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="], "is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="], "jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="], + "jose": ["jose@5.10.0", "", {}, "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg=="], + "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], - "layerchart": ["layerchart@2.0.0-next.6", "", { "dependencies": { "@dagrejs/dagre": "^1.1.4", "@layerstack/svelte-actions": "1.0.1-next.2", "@layerstack/svelte-state": "0.1.0-next.3", "@layerstack/svelte-stores": "1.0.2-next.2", "@layerstack/tailwind": "2.0.0-next.4", "@layerstack/utils": "1.1.0-next.2", "d3-array": "^3.2.4", "d3-color": "^3.1.0", "d3-delaunay": "^6.0.4", "d3-dsv": "^3.0.1", "d3-force": "^3.0.0", "d3-geo": "^3.1.1", "d3-geo-voronoi": "^2.1.0", "d3-hierarchy": "^3.1.2", "d3-interpolate": "^3.0.1", "d3-interpolate-path": "^2.3.0", "d3-path": "^3.1.0", "d3-quadtree": "^3.0.1", "d3-random": "^3.0.1", "d3-sankey": "^0.12.3", "d3-scale": "^4.0.2", "d3-scale-chromatic": "^3.1.0", "d3-shape": "^3.2.0", "d3-tile": "^1.0.0", "d3-time": "^3.1.0", "date-fns": "^4.1.0", "lodash-es": "^4.17.21", "runed": "^0.27.0" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-QGYhFp3PwZlDzl5b6zNFwFeqROWS0wPyq6ce+9rrETaoRfrmlf3JlJmpLmt9Al8jkwZIQiE9GSQ4phWbW/nTOQ=="], + "kysely": ["kysely@0.28.2", "", {}, "sha512-4YAVLoF0Sf0UTqlhgQMFU9iQECdah7n+13ANkiuVfRvlK+uI0Etbgd7bVP36dKlG+NXWbhGua8vnGt+sdhvT7A=="], "lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="], @@ -389,9 +384,9 @@ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="], - "locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="], + "lightweight-charts": ["lightweight-charts@5.0.7", "", { "dependencies": { "fancy-canvas": "2.1.0" } }, "sha512-A4GqwYKRLhZREJEsSpORNNIWceOy5TS30s/WdAP2apKCDhAcIZDAI76TQHCCSf60oHwM7B92exXdQS9UykjXhw=="], - "lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="], + "locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="], "lodash.castarray": ["lodash.castarray@4.4.0", "", {}, "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q=="], @@ -417,6 +412,8 @@ "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + "nanostores": ["nanostores@0.11.4", "", {}, "sha512-k1oiVNN4hDK8NcNERSZLQiMfRzEGtfnvZvdBvey3SQbgn8Dcrk0h1I6vpxApjb10PFUflZrgJ2WEZyJQ+5v7YQ=="], + "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], "normalize-range": ["normalize-range@0.1.2", "", {}, "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA=="], @@ -439,6 +436,10 @@ "prettier-plugin-tailwindcss": ["prettier-plugin-tailwindcss@0.6.11", "", { "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", "@zackad/prettier-plugin-twig": "*", "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", "prettier-plugin-import-sort": "*", "prettier-plugin-jsdoc": "*", "prettier-plugin-marko": "*", "prettier-plugin-multiline-arrays": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", "prettier-plugin-sort-imports": "*", "prettier-plugin-style-order": "*", "prettier-plugin-svelte": "*" }, "optionalPeers": ["@ianvs/prettier-plugin-sort-imports", "@prettier/plugin-pug", "@shopify/prettier-plugin-liquid", "@trivago/prettier-plugin-sort-imports", "@zackad/prettier-plugin-twig", "prettier-plugin-astro", "prettier-plugin-css-order", "prettier-plugin-import-sort", "prettier-plugin-jsdoc", "prettier-plugin-marko", "prettier-plugin-multiline-arrays", "prettier-plugin-organize-attributes", "prettier-plugin-organize-imports", "prettier-plugin-sort-imports", "prettier-plugin-style-order", "prettier-plugin-svelte"] }, "sha512-YxaYSIvZPAqhrrEpRtonnrXdghZg1irNg4qrjboCXrpybLWVs55cW2N3juhspVJiO0JBvYJT8SYsJpc8OQSnsA=="], + "pvtsutils": ["pvtsutils@1.3.6", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg=="], + + "pvutils": ["pvutils@1.1.3", "", {}, "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ=="], + "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], @@ -447,14 +448,12 @@ "rollup": ["rollup@4.41.0", "", { "dependencies": { "@types/estree": "1.0.7" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.41.0", "@rollup/rollup-android-arm64": "4.41.0", "@rollup/rollup-darwin-arm64": "4.41.0", "@rollup/rollup-darwin-x64": "4.41.0", "@rollup/rollup-freebsd-arm64": "4.41.0", "@rollup/rollup-freebsd-x64": "4.41.0", "@rollup/rollup-linux-arm-gnueabihf": "4.41.0", "@rollup/rollup-linux-arm-musleabihf": "4.41.0", "@rollup/rollup-linux-arm64-gnu": "4.41.0", "@rollup/rollup-linux-arm64-musl": "4.41.0", "@rollup/rollup-linux-loongarch64-gnu": "4.41.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.41.0", "@rollup/rollup-linux-riscv64-gnu": "4.41.0", "@rollup/rollup-linux-riscv64-musl": "4.41.0", "@rollup/rollup-linux-s390x-gnu": "4.41.0", "@rollup/rollup-linux-x64-gnu": "4.41.0", "@rollup/rollup-linux-x64-musl": "4.41.0", "@rollup/rollup-win32-arm64-msvc": "4.41.0", "@rollup/rollup-win32-ia32-msvc": "4.41.0", "@rollup/rollup-win32-x64-msvc": "4.41.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-HqMFpUbWlf/tvcxBFNKnJyzc7Lk+XO3FGc3pbNBLqEbOz0gPLRgcrlS3UF4MfUrVlstOaP/q0kM6GVvi+LrLRg=="], - "runed": ["runed@0.27.0", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-Iwn06Yj7tOnN8UKaSYxY1m7lqig03ZUOlZnZJJ6jDvBgcaxSlrDoWL2v/14yvoE8xFdI9ljdut3DwvzpZbz3/w=="], + "rou3": ["rou3@0.5.1", "", {}, "sha512-OXMmJ3zRk2xeXFGfA3K+EOPHC5u7RDFG7lIOx0X1pdnhUkI8MdVrbV+sNsD80ElpUZ+MRHdyxPnFthq9VHs8uQ=="], - "rw": ["rw@1.3.3", "", {}, "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="], + "runed": ["runed@0.23.4", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-9q8oUiBYeXIDLWNK5DfCWlkL0EW3oGbk845VdKlPeia28l751VpfesaB/+7pI6rnbx1I6rqoZ2fZxptOJLxILA=="], "sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="], - "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], - "set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="], "sirv": ["sirv@3.0.1", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A=="], @@ -465,10 +464,18 @@ "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], + "style-to-object": ["style-to-object@1.0.8", "", { "dependencies": { "inline-style-parser": "0.2.4" } }, "sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g=="], + "svelte": ["svelte@5.32.0", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", "esrap": "^1.4.6", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-2WXcm+mx4D99pb5gvGYiEC6EkPOfzCcgXxcVrxMkAythwzYH5Frr29i3C431U4B8LxXRh9WnFPAz+OzIcFdM7g=="], "svelte-check": ["svelte-check@4.2.1", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "chokidar": "^4.0.1", "fdir": "^6.2.0", "picocolors": "^1.0.0", "sade": "^1.7.4" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": ">=5.0.0" }, "bin": { "svelte-check": "bin/svelte-check" } }, "sha512-e49SU1RStvQhoipkQ/aonDhHnG3qxHSBtNfBRb9pxVXoa+N7qybAo32KgA9wEb2PCYFNaDg7bZCdhLD1vHpdYA=="], + "svelte-lightweight-charts": ["svelte-lightweight-charts@2.2.0", "", { "peerDependencies": { "lightweight-charts": ">=4.0.0", "svelte": ">=3.44.0" } }, "sha512-LXdha4vfLMuOPc0Yyetu+DLSDJkPryGkufUQgpCkfguCscSQUcrLiI9MdqKwQk6Fkm6AZbg8SQ5qDIYxcyC+Dg=="], + + "svelte-toolbelt": ["svelte-toolbelt@0.7.1", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.23.2", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-HcBOcR17Vx9bjaOceUvxkY3nGmbBmCBBbuWLLEWO6jtmWH8f/QoWmbyUfQZrpDINH39en1b8mptfPQT9VKQ1xQ=="], + + "tabbable": ["tabbable@6.2.0", "", {}, "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="], + "tailwind-merge": ["tailwind-merge@3.3.0", "", {}, "sha512-fyW/pEfcQSiigd5SNn0nApUOxx0zB/dm6UDU/rEwc2c3sX2smWUNbapHv+QRqLGVp9GWX3THIa7MUGPo+YkDzQ=="], "tailwind-variants": ["tailwind-variants@0.2.1", "", { "dependencies": { "tailwind-merge": "^2.2.0" }, "peerDependencies": { "tailwindcss": "*" } }, "sha512-2xmhAf4UIc3PijOUcJPA1LP4AbxhpcHuHM2C26xM0k81r0maAO6uoUSHl3APmvHZcY5cZCY/bYuJdfFa4eGoaw=="], @@ -481,10 +488,14 @@ "totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="], + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "tw-animate-css": ["tw-animate-css@1.3.0", "", {}, "sha512-jrJ0XenzS9KVuDThJDvnhalbl4IYiMQ/XvpA0a2FL8KmlK+6CSMviO7ROY/I7z1NnUs5NnDhlM6fXmF40xPxzw=="], "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], + "uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="], + "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="], "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], @@ -513,15 +524,11 @@ "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "@visx/vendor/d3-array": ["d3-array@3.2.1", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-gUY/qeHq/yNqqoCKNq4vtpFLdoCdvyNpWoC/KNjhGbhDuQpAM9sIQQKkXSNpXa9h5KySs/gzm7R88WkUutgwWQ=="], + "d3-geo/d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="], - "@visx/vendor/d3-delaunay": ["d3-delaunay@6.0.2", "", { "dependencies": { "delaunator": "5" } }, "sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ=="], + "d3-scale/d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="], - "@visx/vendor/d3-geo": ["d3-geo@3.1.0", "", { "dependencies": { "d3-array": "2.5.0 - 3" } }, "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA=="], - - "d3-sankey/d3-array": ["d3-array@2.12.1", "", { "dependencies": { "internmap": "^1.0.0" } }, "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ=="], - - "d3-sankey/d3-shape": ["d3-shape@1.3.7", "", { "dependencies": { "d3-path": "1" } }, "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw=="], + "d3-time/d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="], "tailwind-variants/tailwind-merge": ["tailwind-merge@2.6.0", "", {}, "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA=="], @@ -571,12 +578,6 @@ "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="], - "@visx/vendor/d3-geo/d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="], - - "d3-sankey/d3-array/internmap": ["internmap@1.0.1", "", {}, "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw=="], - - "d3-sankey/d3-shape/d3-path": ["d3-path@1.0.9", "", {}, "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="], - "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="], "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="], diff --git a/website/drizzle/0000_wonderful_mephistopheles.sql b/website/drizzle/0000_wonderful_mephistopheles.sql new file mode 100644 index 0000000..6b21c95 --- /dev/null +++ b/website/drizzle/0000_wonderful_mephistopheles.sql @@ -0,0 +1,62 @@ +CREATE TABLE IF NOT EXISTS "account" ( + "id" text PRIMARY KEY NOT NULL, + "account_id" text NOT NULL, + "provider_id" text NOT NULL, + "user_id" text NOT NULL, + "access_token" text, + "refresh_token" text, + "id_token" text, + "access_token_expires_at" timestamp, + "refresh_token_expires_at" timestamp, + "scope" text, + "password" text, + "created_at" timestamp NOT NULL, + "updated_at" timestamp NOT NULL +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "session" ( + "id" text PRIMARY KEY NOT NULL, + "expires_at" timestamp NOT NULL, + "token" text NOT NULL, + "created_at" timestamp NOT NULL, + "updated_at" timestamp NOT NULL, + "ip_address" text, + "user_agent" text, + "user_id" text NOT NULL, + CONSTRAINT "session_token_unique" UNIQUE("token") +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "user" ( + "id" text PRIMARY KEY NOT NULL, + "name" text NOT NULL, + "email" text NOT NULL, + "email_verified" boolean NOT NULL, + "image" text, + "created_at" timestamp NOT NULL, + "updated_at" timestamp NOT NULL, + "is_admin" boolean NOT NULL, + "is_banned" boolean NOT NULL, + "ban_reason" text, + CONSTRAINT "user_email_unique" UNIQUE("email") +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "verification" ( + "id" text PRIMARY KEY NOT NULL, + "identifier" text NOT NULL, + "value" text NOT NULL, + "expires_at" timestamp NOT NULL, + "created_at" timestamp, + "updated_at" timestamp +); +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "session" ADD CONSTRAINT "session_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/website/drizzle/0001_sleepy_queen_noir.sql b/website/drizzle/0001_sleepy_queen_noir.sql new file mode 100644 index 0000000..79afaf3 --- /dev/null +++ b/website/drizzle/0001_sleepy_queen_noir.sql @@ -0,0 +1,2 @@ +ALTER TABLE "user" ALTER COLUMN "is_admin" DROP NOT NULL;--> statement-breakpoint +ALTER TABLE "user" ALTER COLUMN "is_banned" DROP NOT NULL; \ No newline at end of file diff --git a/website/drizzle/meta/0000_snapshot.json b/website/drizzle/meta/0000_snapshot.json new file mode 100644 index 0000000..340e33a --- /dev/null +++ b/website/drizzle/meta/0000_snapshot.json @@ -0,0 +1,321 @@ +{ + "id": "d7c4426d-0ef2-49ad-b93a-54e25e216fc3", + "prevId": "00000000-0000-0000-0000-000000000000", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + } + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "is_banned": { + "name": "is_banned", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "ban_reason": { + "name": "ban_reason", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + } + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/website/drizzle/meta/0001_snapshot.json b/website/drizzle/meta/0001_snapshot.json new file mode 100644 index 0000000..69dbebf --- /dev/null +++ b/website/drizzle/meta/0001_snapshot.json @@ -0,0 +1,321 @@ +{ + "id": "dec93290-a459-4102-b9d8-0095bf72a576", + "prevId": "d7c4426d-0ef2-49ad-b93a-54e25e216fc3", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + } + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "is_banned": { + "name": "is_banned", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "ban_reason": { + "name": "ban_reason", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + } + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/website/drizzle/meta/_journal.json b/website/drizzle/meta/_journal.json new file mode 100644 index 0000000..23fb218 --- /dev/null +++ b/website/drizzle/meta/_journal.json @@ -0,0 +1,20 @@ +{ + "version": "7", + "dialect": "postgresql", + "entries": [ + { + "idx": 0, + "version": "7", + "when": 1747905045049, + "tag": "0000_wonderful_mephistopheles", + "breakpoints": true + }, + { + "idx": 1, + "version": "7", + "when": 1747908527252, + "tag": "0001_sleepy_queen_noir", + "breakpoints": true + } + ] +} \ No newline at end of file diff --git a/website/package-lock.json b/website/package-lock.json index ecad3eb..5bd67f0 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -11,18 +11,21 @@ "@tailwindcss/postcss": "^4.1.7", "@tailwindcss/typography": "^0.5.16", "@visx/scale": "^3.12.0", + "better-auth": "^1.2.8", "drizzle-orm": "^0.33.0", "lightweight-charts": "^5.0.7", "lucide-svelte": "^0.511.0", + "mode-watcher": "^1.0.7", "postgres": "^3.4.4", "svelte-lightweight-charts": "^2.2.0" }, "devDependencies": { - "@lucide/svelte": "^0.511.0", + "@lucide/svelte": "^0.482.0", "@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0", "autoprefixer": "^10.4.20", + "bits-ui": "^1.5.0", "clsx": "^2.1.1", "drizzle-kit": "^0.22.0", "prettier": "^3.3.2", @@ -60,6 +63,20 @@ "node": ">=6.0.0" } }, + "node_modules/@better-auth/utils": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.2.5.tgz", + "integrity": "sha512-uI2+/8h/zVsH8RrYdG8eUErbuGBk16rZKQfz8CjxQOyCE6v7BqFYEbFwvOkvl1KbUdxhqOnXp78+uE5h8qVEgQ==", + "dependencies": { + "typescript": "^5.8.2", + "uncrypto": "^0.1.3" + } + }, + "node_modules/@better-fetch/fetch": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/@better-fetch/fetch/-/fetch-1.1.18.tgz", + "integrity": "sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA==" + }, "node_modules/@esbuild-kit/core-utils": { "version": "3.3.2", "dev": true, @@ -144,6 +161,45 @@ "node": ">=12" } }, + "node_modules/@floating-ui/core": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.0.tgz", + "integrity": "sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==", + "dev": true, + "dependencies": { + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.0.tgz", + "integrity": "sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==", + "dev": true, + "dependencies": { + "@floating-ui/core": "^1.7.0", + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", + "dev": true + }, + "node_modules/@hexagon/base64": { + "version": "1.1.28", + "resolved": "https://registry.npmjs.org/@hexagon/base64/-/base64-1.1.28.tgz", + "integrity": "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==" + }, + "node_modules/@internationalized/date": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.8.1.tgz", + "integrity": "sha512-PgVE6B6eIZtzf9Gu5HvJxRK3ufUFz9DhspELuhW/N0GuMGMTLvPQNRkHP2hTuP9lblOk+f+1xi96sPiPXANXAA==", + "dev": true, + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, "node_modules/@isaacs/fs-minipass": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", @@ -193,15 +249,92 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@levischuck/tiny-cbor": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@levischuck/tiny-cbor/-/tiny-cbor-0.2.11.tgz", + "integrity": "sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==" + }, "node_modules/@lucide/svelte": { - "version": "0.511.0", - "resolved": "https://registry.npmjs.org/@lucide/svelte/-/svelte-0.511.0.tgz", - "integrity": "sha512-aLCSPMUJmHlCuLXzXENXa4Z1NV2mN1iAZAFKk4bEbey+/MdsNlu+/DqwVkgW3Yvj6p8y8Vn5xZ2v9CLmPlA6Vw==", + "version": "0.482.0", + "resolved": "https://registry.npmjs.org/@lucide/svelte/-/svelte-0.482.0.tgz", + "integrity": "sha512-n2ycHU9cNcleRDwwpEHBJ6pYzVhHIaL3a+9dQa8kns9hB2g05bY+v2p2KP8v0pZwtNhYTHk/F2o2uZ1bVtQGhw==", "dev": true, "peerDependencies": { "svelte": "^5" } }, + "node_modules/@noble/ciphers": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.6.0.tgz", + "integrity": "sha512-mIbq/R9QXk5/cTfESb1OKtyFnk7oc1Om/8onA1158K9/OZUQFDEVy55jVTato+xmp3XX6F6Qh0zz0Nc1AxAlRQ==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@peculiar/asn1-android": { + "version": "2.3.16", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-android/-/asn1-android-2.3.16.tgz", + "integrity": "sha512-a1viIv3bIahXNssrOIkXZIlI2ePpZaNmR30d4aBL99mu2rO+mT9D6zBsp7H6eROWGtmwv0Ionp5olJurIo09dw==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.15", + "asn1js": "^3.0.5", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-ecc": { + "version": "2.3.15", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.3.15.tgz", + "integrity": "sha512-/HtR91dvgog7z/WhCVdxZJ/jitJuIu8iTqiyWVgRE9Ac5imt2sT/E4obqIVGKQw7PIy+X6i8lVBoT6wC73XUgA==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.15", + "@peculiar/asn1-x509": "^2.3.15", + "asn1js": "^3.0.5", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-rsa": { + "version": "2.3.15", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.3.15.tgz", + "integrity": "sha512-p6hsanvPhexRtYSOHihLvUUgrJ8y0FtOM97N5UEpC+VifFYyZa0iZ5cXjTkZoDwxJ/TTJ1IJo3HVTB2JJTpXvg==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.15", + "@peculiar/asn1-x509": "^2.3.15", + "asn1js": "^3.0.5", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.3.15", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.15.tgz", + "integrity": "sha512-QPeD8UA8axQREpgR5UTAfu2mqQmm97oUqahDtNdBcfj3qAnoXzFdQW+aNf/tD2WVXF8Fhmftxoj0eMIT++gX2w==", + "dependencies": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-x509": { + "version": "2.3.15", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.3.15.tgz", + "integrity": "sha512-0dK5xqTqSLaxv1FHXIcd4Q/BZNuopg+u1l23hT9rOmQ1g4dNtw0g/RnEi+TboB0gOwGtrWn269v27cMgchFIIg==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.15", + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.6", + "tslib": "^2.8.1" + } + }, "node_modules/@polka/url": { "version": "1.0.0-next.29", "dev": true, @@ -219,6 +352,28 @@ "win32" ] }, + "node_modules/@simplewebauthn/browser": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-13.1.0.tgz", + "integrity": "sha512-WuHZ/PYvyPJ9nxSzgHtOEjogBhwJfC8xzYkPC+rR/+8chl/ft4ngjiK8kSU5HtRJfczupyOh33b25TjYbvwAcg==" + }, + "node_modules/@simplewebauthn/server": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/@simplewebauthn/server/-/server-13.1.1.tgz", + "integrity": "sha512-1hsLpRHfSuMB9ee2aAdh0Htza/X3f4djhYISrggqGe3xopNjOcePiSDkDDoPzDYaaMCrbqGP1H2TYU7bgL9PmA==", + "dependencies": { + "@hexagon/base64": "^1.1.27", + "@levischuck/tiny-cbor": "^0.2.2", + "@peculiar/asn1-android": "^2.3.10", + "@peculiar/asn1-ecc": "^2.3.8", + "@peculiar/asn1-rsa": "^2.3.8", + "@peculiar/asn1-schema": "^2.3.8", + "@peculiar/asn1-x509": "^2.3.8" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@sveltejs/acorn-typescript": { "version": "1.0.5", "license": "MIT", @@ -303,6 +458,15 @@ "vite": "^5.0.0" } }, + "node_modules/@swc/helpers": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", + "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", + "dev": true, + "dependencies": { + "tslib": "^2.8.0" + } + }, "node_modules/@tailwindcss/node": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.7.tgz", @@ -726,6 +890,19 @@ "node": ">= 0.4" } }, + "node_modules/asn1js": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.6.tgz", + "integrity": "sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA==", + "dependencies": { + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.3", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/autoprefixer": { "version": "10.4.21", "dev": true, @@ -769,6 +946,61 @@ "node": ">= 0.4" } }, + "node_modules/better-auth": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/better-auth/-/better-auth-1.2.8.tgz", + "integrity": "sha512-y8ry7ZW3/3ZIr82Eo1zUDtMzdoQlFnwNuZ0+b0RxoNZgqmvgTIc/0tCDC7NDJerqSu4UCzer0dvYxBsv3WMIGg==", + "dependencies": { + "@better-auth/utils": "0.2.5", + "@better-fetch/fetch": "^1.1.18", + "@noble/ciphers": "^0.6.0", + "@noble/hashes": "^1.6.1", + "@simplewebauthn/browser": "^13.0.0", + "@simplewebauthn/server": "^13.0.0", + "better-call": "^1.0.8", + "defu": "^6.1.4", + "jose": "^5.9.6", + "kysely": "^0.28.1", + "nanostores": "^0.11.3", + "zod": "^3.24.1" + } + }, + "node_modules/better-call": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/better-call/-/better-call-1.0.9.tgz", + "integrity": "sha512-Qfm0gjk0XQz0oI7qvTK1hbqTsBY4xV2hsHAxF8LZfUYl3RaECCIifXuVqtPpZJWvlCCMlQSvkvhhyuApGUba6g==", + "dependencies": { + "@better-fetch/fetch": "^1.1.4", + "rou3": "^0.5.1", + "set-cookie-parser": "^2.7.1", + "uncrypto": "^0.1.3" + } + }, + "node_modules/bits-ui": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-1.5.3.tgz", + "integrity": "sha512-BTZ9/GU11DaEGyQp+AY+sXCMLZO0gbDC5J8l7+Ngj4Vf6hNOwrpMmoh5iuKktA6cphXYolVkUDgBWmkh415I+w==", + "dev": true, + "dependencies": { + "@floating-ui/core": "^1.6.4", + "@floating-ui/dom": "^1.6.7", + "@internationalized/date": "^3.5.6", + "esm-env": "^1.1.2", + "runed": "^0.23.2", + "svelte-toolbelt": "^0.7.1", + "tabbable": "^6.2.0" + }, + "engines": { + "node": ">=18", + "pnpm": ">=8.7.0" + }, + "funding": { + "url": "https://github.com/sponsors/huntabyte" + }, + "peerDependencies": { + "svelte": "^5.11.0" + } + }, "node_modules/browserslist": { "version": "4.24.5", "dev": true, @@ -970,6 +1202,11 @@ "node": ">=0.10.0" } }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==" + }, "node_modules/delaunator": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", @@ -1262,6 +1499,11 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/inline-style-parser": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==" + }, "node_modules/internmap": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", @@ -1285,6 +1527,14 @@ "jiti": "lib/jiti-cli.mjs" } }, + "node_modules/jose": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz", + "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/kleur": { "version": "4.1.5", "dev": true, @@ -1293,6 +1543,14 @@ "node": ">=6" } }, + "node_modules/kysely": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.28.2.tgz", + "integrity": "sha512-4YAVLoF0Sf0UTqlhgQMFU9iQECdah7n+13ANkiuVfRvlK+uI0Etbgd7bVP36dKlG+NXWbhGua8vnGt+sdhvT7A==", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/lightningcss": { "version": "1.30.1", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", @@ -1582,6 +1840,33 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/mode-watcher": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/mode-watcher/-/mode-watcher-1.0.7.tgz", + "integrity": "sha512-ZGA7ZGdOvBJeTQkzdBOnXSgTkO6U6iIFWJoyGCTt6oHNg9XP9NBvS26De+V4W2aqI+B0yYXUskFG2VnEo3zyMQ==", + "dependencies": { + "runed": "^0.25.0", + "svelte-toolbelt": "^0.7.1" + }, + "peerDependencies": { + "svelte": "^5.27.0" + } + }, + "node_modules/mode-watcher/node_modules/runed": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/runed/-/runed-0.25.0.tgz", + "integrity": "sha512-7+ma4AG9FT2sWQEA0Egf6mb7PBT2vHyuHail1ie8ropfSjvZGtEAx8YTmUjv/APCsdRRxEVvArNjALk9zFSOrg==", + "funding": [ + "https://github.com/sponsors/huntabyte", + "https://github.com/sponsors/tglide" + ], + "dependencies": { + "esm-env": "^1.0.0" + }, + "peerDependencies": { + "svelte": "^5.7.0" + } + }, "node_modules/mri": { "version": "1.2.0", "dev": true, @@ -1619,6 +1904,20 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/nanostores": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/nanostores/-/nanostores-0.11.4.tgz", + "integrity": "sha512-k1oiVNN4hDK8NcNERSZLQiMfRzEGtfnvZvdBvey3SQbgn8Dcrk0h1I6vpxApjb10PFUflZrgJ2WEZyJQ+5v7YQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, "node_modules/node-releases": { "version": "2.0.19", "dev": true, @@ -1793,6 +2092,22 @@ } } }, + "node_modules/pvtsutils": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", + "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/readdirp": { "version": "4.1.2", "dev": true, @@ -1856,6 +2171,26 @@ "fsevents": "~2.3.2" } }, + "node_modules/rou3": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/rou3/-/rou3-0.5.1.tgz", + "integrity": "sha512-OXMmJ3zRk2xeXFGfA3K+EOPHC5u7RDFG7lIOx0X1pdnhUkI8MdVrbV+sNsD80ElpUZ+MRHdyxPnFthq9VHs8uQ==" + }, + "node_modules/runed": { + "version": "0.23.4", + "resolved": "https://registry.npmjs.org/runed/-/runed-0.23.4.tgz", + "integrity": "sha512-9q8oUiBYeXIDLWNK5DfCWlkL0EW3oGbk845VdKlPeia28l751VpfesaB/+7pI6rnbx1I6rqoZ2fZxptOJLxILA==", + "funding": [ + "https://github.com/sponsors/huntabyte", + "https://github.com/sponsors/tglide" + ], + "dependencies": { + "esm-env": "^1.0.0" + }, + "peerDependencies": { + "svelte": "^5.7.0" + } + }, "node_modules/sade": { "version": "1.8.1", "dev": true, @@ -1869,7 +2204,6 @@ }, "node_modules/set-cookie-parser": { "version": "2.7.1", - "dev": true, "license": "MIT" }, "node_modules/sirv": { @@ -1909,6 +2243,14 @@ "source-map": "^0.6.0" } }, + "node_modules/style-to-object": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz", + "integrity": "sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==", + "dependencies": { + "inline-style-parser": "0.2.4" + } + }, "node_modules/svelte": { "version": "5.32.0", "license": "MIT", @@ -1963,6 +2305,32 @@ "svelte": ">=3.44.0" } }, + "node_modules/svelte-toolbelt": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/svelte-toolbelt/-/svelte-toolbelt-0.7.1.tgz", + "integrity": "sha512-HcBOcR17Vx9bjaOceUvxkY3nGmbBmCBBbuWLLEWO6jtmWH8f/QoWmbyUfQZrpDINH39en1b8mptfPQT9VKQ1xQ==", + "funding": [ + "https://github.com/sponsors/huntabyte" + ], + "dependencies": { + "clsx": "^2.1.1", + "runed": "^0.23.2", + "style-to-object": "^1.0.8" + }, + "engines": { + "node": ">=18", + "pnpm": ">=8.7.0" + }, + "peerDependencies": { + "svelte": "^5.0.0" + } + }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "dev": true + }, "node_modules/tailwind-merge": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.0.tgz", @@ -2036,6 +2404,11 @@ "node": ">=6" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, "node_modules/tw-animate-css": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.3.0.tgz", @@ -2047,7 +2420,6 @@ }, "node_modules/typescript": { "version": "5.8.3", - "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -2057,6 +2429,11 @@ "node": ">=14.17" } }, + "node_modules/uncrypto": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==" + }, "node_modules/update-browserslist-db": { "version": "1.1.3", "dev": true, @@ -2228,6 +2605,14 @@ "node_modules/zimmerframe": { "version": "1.1.2", "license": "MIT" + }, + "node_modules/zod": { + "version": "3.25.20", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.20.tgz", + "integrity": "sha512-z03fqpTMDF1G02VLKUMt6vyACE7rNWkh3gpXVHgPTw28NPtDFRGvcpTtPwn2kMKtQ0idtYJUTxchytmnqYswcw==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/website/package.json b/website/package.json index d2f8497..a184d1a 100644 --- a/website/package.json +++ b/website/package.json @@ -16,11 +16,12 @@ "db:studio": "drizzle-kit studio" }, "devDependencies": { - "@lucide/svelte": "^0.511.0", + "@lucide/svelte": "^0.482.0", "@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0", "autoprefixer": "^10.4.20", + "bits-ui": "^1.5.0", "clsx": "^2.1.1", "drizzle-kit": "^0.22.0", "prettier": "^3.3.2", @@ -39,9 +40,11 @@ "@tailwindcss/postcss": "^4.1.7", "@tailwindcss/typography": "^0.5.16", "@visx/scale": "^3.12.0", + "better-auth": "^1.2.8", "drizzle-orm": "^0.33.0", "lightweight-charts": "^5.0.7", "lucide-svelte": "^0.511.0", + "mode-watcher": "^1.0.7", "postgres": "^3.4.4", "svelte-lightweight-charts": "^2.2.0" } diff --git a/website/src/app.css b/website/src/app.css index 948521d..2c1424f 100644 --- a/website/src/app.css +++ b/website/src/app.css @@ -4,63 +4,75 @@ @custom-variant dark (&:is(.dark *)); +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap'); + :root { - --radius: 0.625rem; + --radius: 0.5rem; --background: oklch(1 0 0); - --foreground: oklch(0.129 0.042 264.695); + --foreground: oklch(0.141 0.005 285.823); --card: oklch(1 0 0); - --card-foreground: oklch(0.129 0.042 264.695); + --card-foreground: oklch(0.141 0.005 285.823); --popover: oklch(1 0 0); - --popover-foreground: oklch(0.129 0.042 264.695); - --primary: oklch(0.208 0.042 265.755); - --primary-foreground: oklch(0.984 0.003 247.858); - --secondary: oklch(0.968 0.007 247.896); - --secondary-foreground: oklch(0.208 0.042 265.755); - --muted: oklch(0.968 0.007 247.896); - --muted-foreground: oklch(0.554 0.046 257.417); - --accent: oklch(0.968 0.007 247.896); - --accent-foreground: oklch(0.208 0.042 265.755); + --popover-foreground: oklch(0.141 0.005 285.823); + --primary: oklch(0.637 0.237 25.331); + --primary-foreground: oklch(0.971 0.013 17.38); + --secondary: oklch(0.967 0.001 286.375); + --secondary-foreground: oklch(0.21 0.006 285.885); + --muted: oklch(0.967 0.001 286.375); + --muted-foreground: oklch(0.552 0.016 285.938); + --accent: oklch(0.967 0.001 286.375); + --accent-foreground: oklch(0.21 0.006 285.885); --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.929 0.013 255.508); - --input: oklch(0.929 0.013 255.508); - --ring: oklch(0.704 0.04 256.788); - --sidebar: oklch(0.984 0.003 247.858); - --sidebar-foreground: oklch(0.129 0.042 264.695); - --sidebar-primary: oklch(0.208 0.042 265.755); - --sidebar-primary-foreground: oklch(0.984 0.003 247.858); - --sidebar-accent: oklch(0.968 0.007 247.896); - --sidebar-accent-foreground: oklch(0.208 0.042 265.755); - --sidebar-border: oklch(0.929 0.013 255.508); - --sidebar-ring: oklch(0.704 0.04 256.788); + --border: oklch(0.92 0.004 286.32); + --input: oklch(0.92 0.004 286.32); + --ring: oklch(0.637 0.237 25.331); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.141 0.005 285.823); + --sidebar-primary: oklch(0.637 0.237 25.331); + --sidebar-primary-foreground: oklch(0.971 0.013 17.38); + --sidebar-accent: oklch(0.967 0.001 286.375); + --sidebar-accent-foreground: oklch(0.21 0.006 285.885); + --sidebar-border: oklch(0.92 0.004 286.32); + --sidebar-ring: oklch(0.637 0.237 25.331); } .dark { - --background: oklch(0.129 0.042 264.695); - --foreground: oklch(0.984 0.003 247.858); - --card: oklch(0.208 0.042 265.755); - --card-foreground: oklch(0.984 0.003 247.858); - --popover: oklch(0.208 0.042 265.755); - --popover-foreground: oklch(0.984 0.003 247.858); - --primary: oklch(0.929 0.013 255.508); - --primary-foreground: oklch(0.208 0.042 265.755); - --secondary: oklch(0.279 0.041 260.031); - --secondary-foreground: oklch(0.984 0.003 247.858); - --muted: oklch(0.279 0.041 260.031); - --muted-foreground: oklch(0.704 0.04 256.788); - --accent: oklch(0.279 0.041 260.031); - --accent-foreground: oklch(0.984 0.003 247.858); + --background: oklch(0.141 0.005 285.823); + --foreground: oklch(0.985 0 0); + --card: oklch(0.21 0.006 285.885); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.21 0.006 285.885); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.637 0.237 25.331); + --primary-foreground: oklch(0.971 0.013 17.38); + --secondary: oklch(0.274 0.006 286.033); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.274 0.006 286.033); + --muted-foreground: oklch(0.705 0.015 286.067); + --accent: oklch(0.274 0.006 286.033); + --accent-foreground: oklch(0.985 0 0); --destructive: oklch(0.704 0.191 22.216); --border: oklch(1 0 0 / 10%); --input: oklch(1 0 0 / 15%); - --ring: oklch(0.551 0.027 264.364); - --sidebar: oklch(0.208 0.042 265.755); - --sidebar-foreground: oklch(0.984 0.003 247.858); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.984 0.003 247.858); - --sidebar-accent: oklch(0.279 0.041 260.031); - --sidebar-accent-foreground: oklch(0.984 0.003 247.858); + --ring: oklch(0.637 0.237 25.331); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.21 0.006 285.885); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.637 0.237 25.331); + --sidebar-primary-foreground: oklch(0.971 0.013 17.38); + --sidebar-accent: oklch(0.274 0.006 286.033); + --sidebar-accent-foreground: oklch(0.985 0 0); --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.551 0.027 264.364); + --sidebar-ring: oklch(0.637 0.237 25.331); } @theme inline { @@ -99,6 +111,7 @@ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-border: var(--sidebar-border); --color-sidebar-ring: var(--sidebar-ring); + --default-font-family: 'Inter', sans-serif; } @layer base { diff --git a/website/src/hooks.server.ts b/website/src/hooks.server.ts new file mode 100644 index 0000000..516bb6c --- /dev/null +++ b/website/src/hooks.server.ts @@ -0,0 +1,10 @@ +import { auth } from "$lib/auth"; +import { svelteKitHandler } from "better-auth/svelte-kit"; + +export async function handle({ event, resolve }) { + // event.setHeaders({ + // 'Cache-Control': 'private, no-cache, no-store, must-revalidate' + // }); + + return svelteKitHandler({ event, resolve, auth }); +} \ No newline at end of file diff --git a/website/src/lib/auth-client.ts b/website/src/lib/auth-client.ts new file mode 100644 index 0000000..1f9f136 --- /dev/null +++ b/website/src/lib/auth-client.ts @@ -0,0 +1,12 @@ +import { createAuthClient } from "better-auth/svelte"; +import { apiKeyClient } from "better-auth/client/plugins"; +import { env } from '$env/dynamic/public'; + +export const client = createAuthClient({ + baseURL: env.PUBLIC_BETTER_AUTH_URL, + plugins: [ + apiKeyClient() + ] +}); + +export const { signIn, signUp, getSession, signOut } = client; \ No newline at end of file diff --git a/website/src/lib/auth.ts b/website/src/lib/auth.ts new file mode 100644 index 0000000..c0b1514 --- /dev/null +++ b/website/src/lib/auth.ts @@ -0,0 +1,56 @@ +import { betterAuth } from "better-auth"; +import { drizzleAdapter } from "better-auth/adapters/drizzle"; +import { apiKey } from "better-auth/plugins"; +import { env } from '$env/dynamic/private'; + +import { db } from "./server/db"; +import { eq } from "drizzle-orm"; + +if (!env.GOOGLE_CLIENT_ID) throw new Error('GOOGLE_CLIENT_ID is not set'); +if (!env.GOOGLE_CLIENT_SECRET) throw new Error('GOOGLE_CLIENT_SECRET is not set'); + +export const auth = betterAuth({ + baseURL: env.PUBLIC_BETTER_AUTH_URL, + secret: env.PRIVATE_BETTER_AUTH_SECRET, + appName: "Rugplay", + + database: drizzleAdapter(db, { + provider: "pg", + }), + socialProviders: { + google: { + clientId: env.GOOGLE_CLIENT_ID, + clientSecret: env.GOOGLE_CLIENT_SECRET, + } + }, + + session: { + cookieCache: { + enabled: true, + maxAge: 60 * 5, // 5 minutes + } + }, + user: { + additionalFields: { + isAdmin: { + type: "boolean", + required: true, + defaultValue: false, + input: false + }, + isBanned: { + type: "boolean", + required: true, + defaultValue: false, + input: false + }, + banReason: { + type: "string", + required: false, + defaultValue: null, + input: false + } + }, + deleteUser: { enabled: true } + }, +}); \ No newline at end of file diff --git a/website/src/lib/components/self/AppSidebar.svelte b/website/src/lib/components/self/AppSidebar.svelte new file mode 100644 index 0000000..ee0bfa9 --- /dev/null +++ b/website/src/lib/components/self/AppSidebar.svelte @@ -0,0 +1,140 @@ + + + + + +
+ twoblade +
+ Rugplay + {#if $USER_DATA?.isAdmin} + | Admin + {/if} +
+
+
+ + + + + + {#each data.navMain as item} + + + {#snippet child({ props }: { props: MenuButtonProps })} + handleNavClick(item.title)} + class={`${props.class}`} + > + + {item.title} + + {/snippet} + + + {/each} + + {#if $USER_DATA?.isAdmin} + {#each data.navAdmin as item} + + + {#snippet child({ props }: { props: MenuButtonProps })} + handleNavClick(item.title)} + class={`${props.class}`} + > + + {item.title} + + {/snippet} + + + {/each} + {/if} + + + + {#snippet child({ props }: { props: MenuButtonProps })} + + {/snippet} + + + + {#if !$USER_DATA} + + + {#snippet child()} + + {/snippet} + + + {/if} + + + + +
diff --git a/website/src/lib/components/self/SignInConfirmDialog.svelte b/website/src/lib/components/self/SignInConfirmDialog.svelte new file mode 100644 index 0000000..7c07a9d --- /dev/null +++ b/website/src/lib/components/self/SignInConfirmDialog.svelte @@ -0,0 +1,48 @@ + + + + + + Sign in to Vyntr + + Choose a service to sign in with. Your account will be created automatically if you don't + have one. + + +
+ + +

+ By continuing, you agree to our + Terms of Service + and + Privacy Policy +

+
+
+
diff --git a/website/src/lib/components/ui/dialog/dialog-close.svelte b/website/src/lib/components/ui/dialog/dialog-close.svelte new file mode 100644 index 0000000..840b2f6 --- /dev/null +++ b/website/src/lib/components/ui/dialog/dialog-close.svelte @@ -0,0 +1,7 @@ + + + diff --git a/website/src/lib/components/ui/dialog/dialog-content.svelte b/website/src/lib/components/ui/dialog/dialog-content.svelte new file mode 100644 index 0000000..06a98f7 --- /dev/null +++ b/website/src/lib/components/ui/dialog/dialog-content.svelte @@ -0,0 +1,39 @@ + + + + + + {@render children?.()} + + + Close + + + diff --git a/website/src/lib/components/ui/dialog/dialog-description.svelte b/website/src/lib/components/ui/dialog/dialog-description.svelte new file mode 100644 index 0000000..3845023 --- /dev/null +++ b/website/src/lib/components/ui/dialog/dialog-description.svelte @@ -0,0 +1,17 @@ + + + diff --git a/website/src/lib/components/ui/dialog/dialog-footer.svelte b/website/src/lib/components/ui/dialog/dialog-footer.svelte new file mode 100644 index 0000000..e7ff446 --- /dev/null +++ b/website/src/lib/components/ui/dialog/dialog-footer.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/website/src/lib/components/ui/dialog/dialog-header.svelte b/website/src/lib/components/ui/dialog/dialog-header.svelte new file mode 100644 index 0000000..fc90cd9 --- /dev/null +++ b/website/src/lib/components/ui/dialog/dialog-header.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/website/src/lib/components/ui/dialog/dialog-overlay.svelte b/website/src/lib/components/ui/dialog/dialog-overlay.svelte new file mode 100644 index 0000000..f81ad83 --- /dev/null +++ b/website/src/lib/components/ui/dialog/dialog-overlay.svelte @@ -0,0 +1,20 @@ + + + diff --git a/website/src/lib/components/ui/dialog/dialog-title.svelte b/website/src/lib/components/ui/dialog/dialog-title.svelte new file mode 100644 index 0000000..067e55e --- /dev/null +++ b/website/src/lib/components/ui/dialog/dialog-title.svelte @@ -0,0 +1,17 @@ + + + diff --git a/website/src/lib/components/ui/dialog/dialog-trigger.svelte b/website/src/lib/components/ui/dialog/dialog-trigger.svelte new file mode 100644 index 0000000..9d1e801 --- /dev/null +++ b/website/src/lib/components/ui/dialog/dialog-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/website/src/lib/components/ui/dialog/index.ts b/website/src/lib/components/ui/dialog/index.ts new file mode 100644 index 0000000..dce1d9d --- /dev/null +++ b/website/src/lib/components/ui/dialog/index.ts @@ -0,0 +1,37 @@ +import { Dialog as DialogPrimitive } from "bits-ui"; + +import Title from "./dialog-title.svelte"; +import Footer from "./dialog-footer.svelte"; +import Header from "./dialog-header.svelte"; +import Overlay from "./dialog-overlay.svelte"; +import Content from "./dialog-content.svelte"; +import Description from "./dialog-description.svelte"; +import Trigger from "./dialog-trigger.svelte"; +import Close from "./dialog-close.svelte"; + +const Root = DialogPrimitive.Root; +const Portal = DialogPrimitive.Portal; + +export { + Root, + Title, + Portal, + Footer, + Header, + Trigger, + Overlay, + Content, + Description, + Close, + // + Root as Dialog, + Title as DialogTitle, + Portal as DialogPortal, + Footer as DialogFooter, + Header as DialogHeader, + Trigger as DialogTrigger, + Overlay as DialogOverlay, + Content as DialogContent, + Description as DialogDescription, + Close as DialogClose, +}; diff --git a/website/src/lib/components/ui/input/index.ts b/website/src/lib/components/ui/input/index.ts new file mode 100644 index 0000000..f47b6d3 --- /dev/null +++ b/website/src/lib/components/ui/input/index.ts @@ -0,0 +1,7 @@ +import Root from "./input.svelte"; + +export { + Root, + // + Root as Input, +}; diff --git a/website/src/lib/components/ui/input/input.svelte b/website/src/lib/components/ui/input/input.svelte new file mode 100644 index 0000000..1eae616 --- /dev/null +++ b/website/src/lib/components/ui/input/input.svelte @@ -0,0 +1,51 @@ + + +{#if type === "file"} + +{:else} + +{/if} diff --git a/website/src/lib/components/ui/separator/index.ts b/website/src/lib/components/ui/separator/index.ts new file mode 100644 index 0000000..82442d2 --- /dev/null +++ b/website/src/lib/components/ui/separator/index.ts @@ -0,0 +1,7 @@ +import Root from "./separator.svelte"; + +export { + Root, + // + Root as Separator, +}; diff --git a/website/src/lib/components/ui/separator/separator.svelte b/website/src/lib/components/ui/separator/separator.svelte new file mode 100644 index 0000000..3648474 --- /dev/null +++ b/website/src/lib/components/ui/separator/separator.svelte @@ -0,0 +1,20 @@ + + + diff --git a/website/src/lib/components/ui/sheet/index.ts b/website/src/lib/components/ui/sheet/index.ts new file mode 100644 index 0000000..01d40c8 --- /dev/null +++ b/website/src/lib/components/ui/sheet/index.ts @@ -0,0 +1,36 @@ +import { Dialog as SheetPrimitive } from "bits-ui"; +import Trigger from "./sheet-trigger.svelte"; +import Close from "./sheet-close.svelte"; +import Overlay from "./sheet-overlay.svelte"; +import Content from "./sheet-content.svelte"; +import Header from "./sheet-header.svelte"; +import Footer from "./sheet-footer.svelte"; +import Title from "./sheet-title.svelte"; +import Description from "./sheet-description.svelte"; + +const Root = SheetPrimitive.Root; +const Portal = SheetPrimitive.Portal; + +export { + Root, + Close, + Trigger, + Portal, + Overlay, + Content, + Header, + Footer, + Title, + Description, + // + Root as Sheet, + Close as SheetClose, + Trigger as SheetTrigger, + Portal as SheetPortal, + Overlay as SheetOverlay, + Content as SheetContent, + Header as SheetHeader, + Footer as SheetFooter, + Title as SheetTitle, + Description as SheetDescription, +}; diff --git a/website/src/lib/components/ui/sheet/sheet-close.svelte b/website/src/lib/components/ui/sheet/sheet-close.svelte new file mode 100644 index 0000000..ae382c1 --- /dev/null +++ b/website/src/lib/components/ui/sheet/sheet-close.svelte @@ -0,0 +1,7 @@ + + + diff --git a/website/src/lib/components/ui/sheet/sheet-content.svelte b/website/src/lib/components/ui/sheet/sheet-content.svelte new file mode 100644 index 0000000..856922e --- /dev/null +++ b/website/src/lib/components/ui/sheet/sheet-content.svelte @@ -0,0 +1,58 @@ + + + + + + + + {@render children?.()} + + + Close + + + diff --git a/website/src/lib/components/ui/sheet/sheet-description.svelte b/website/src/lib/components/ui/sheet/sheet-description.svelte new file mode 100644 index 0000000..333b17a --- /dev/null +++ b/website/src/lib/components/ui/sheet/sheet-description.svelte @@ -0,0 +1,17 @@ + + + diff --git a/website/src/lib/components/ui/sheet/sheet-footer.svelte b/website/src/lib/components/ui/sheet/sheet-footer.svelte new file mode 100644 index 0000000..dd9ed84 --- /dev/null +++ b/website/src/lib/components/ui/sheet/sheet-footer.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/website/src/lib/components/ui/sheet/sheet-header.svelte b/website/src/lib/components/ui/sheet/sheet-header.svelte new file mode 100644 index 0000000..757a6a5 --- /dev/null +++ b/website/src/lib/components/ui/sheet/sheet-header.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/website/src/lib/components/ui/sheet/sheet-overlay.svelte b/website/src/lib/components/ui/sheet/sheet-overlay.svelte new file mode 100644 index 0000000..d1a6177 --- /dev/null +++ b/website/src/lib/components/ui/sheet/sheet-overlay.svelte @@ -0,0 +1,22 @@ + + + diff --git a/website/src/lib/components/ui/sheet/sheet-title.svelte b/website/src/lib/components/ui/sheet/sheet-title.svelte new file mode 100644 index 0000000..9fda327 --- /dev/null +++ b/website/src/lib/components/ui/sheet/sheet-title.svelte @@ -0,0 +1,17 @@ + + + diff --git a/website/src/lib/components/ui/sheet/sheet-trigger.svelte b/website/src/lib/components/ui/sheet/sheet-trigger.svelte new file mode 100644 index 0000000..e266975 --- /dev/null +++ b/website/src/lib/components/ui/sheet/sheet-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/website/src/lib/components/ui/sidebar/constants.ts b/website/src/lib/components/ui/sidebar/constants.ts new file mode 100644 index 0000000..4de4435 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/constants.ts @@ -0,0 +1,6 @@ +export const SIDEBAR_COOKIE_NAME = "sidebar:state"; +export const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7; +export const SIDEBAR_WIDTH = "16rem"; +export const SIDEBAR_WIDTH_MOBILE = "18rem"; +export const SIDEBAR_WIDTH_ICON = "3rem"; +export const SIDEBAR_KEYBOARD_SHORTCUT = "b"; diff --git a/website/src/lib/components/ui/sidebar/context.svelte.ts b/website/src/lib/components/ui/sidebar/context.svelte.ts new file mode 100644 index 0000000..15248ad --- /dev/null +++ b/website/src/lib/components/ui/sidebar/context.svelte.ts @@ -0,0 +1,81 @@ +import { IsMobile } from "$lib/hooks/is-mobile.svelte.js"; +import { getContext, setContext } from "svelte"; +import { SIDEBAR_KEYBOARD_SHORTCUT } from "./constants.js"; + +type Getter = () => T; + +export type SidebarStateProps = { + /** + * A getter function that returns the current open state of the sidebar. + * We use a getter function here to support `bind:open` on the `Sidebar.Provider` + * component. + */ + open: Getter; + + /** + * A function that sets the open state of the sidebar. To support `bind:open`, we need + * a source of truth for changing the open state to ensure it will be synced throughout + * the sub-components and any `bind:` references. + */ + setOpen: (open: boolean) => void; +}; + +class SidebarState { + readonly props: SidebarStateProps; + open = $derived.by(() => this.props.open()); + openMobile = $state(false); + setOpen: SidebarStateProps["setOpen"]; + #isMobile: IsMobile; + state = $derived.by(() => (this.open ? "expanded" : "collapsed")); + + constructor(props: SidebarStateProps) { + this.setOpen = props.setOpen; + this.#isMobile = new IsMobile(); + this.props = props; + } + + // Convenience getter for checking if the sidebar is mobile + // without this, we would need to use `sidebar.isMobile.current` everywhere + get isMobile() { + return this.#isMobile.current; + } + + // Event handler to apply to the `` + handleShortcutKeydown = (e: KeyboardEvent) => { + if (e.key === SIDEBAR_KEYBOARD_SHORTCUT && (e.metaKey || e.ctrlKey)) { + e.preventDefault(); + this.toggle(); + } + }; + + setOpenMobile = (value: boolean) => { + this.openMobile = value; + }; + + toggle = () => { + return this.#isMobile.current + ? (this.openMobile = !this.openMobile) + : this.setOpen(!this.open); + }; +} + +const SYMBOL_KEY = "scn-sidebar"; + +/** + * Instantiates a new `SidebarState` instance and sets it in the context. + * + * @param props The constructor props for the `SidebarState` class. + * @returns The `SidebarState` instance. + */ +export function setSidebar(props: SidebarStateProps): SidebarState { + return setContext(Symbol.for(SYMBOL_KEY), new SidebarState(props)); +} + +/** + * Retrieves the `SidebarState` instance from the context. This is a class instance, + * so you cannot destructure it. + * @returns The `SidebarState` instance. + */ +export function useSidebar(): SidebarState { + return getContext(Symbol.for(SYMBOL_KEY)); +} diff --git a/website/src/lib/components/ui/sidebar/index.ts b/website/src/lib/components/ui/sidebar/index.ts new file mode 100644 index 0000000..318a341 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/index.ts @@ -0,0 +1,75 @@ +import { useSidebar } from "./context.svelte.js"; +import Content from "./sidebar-content.svelte"; +import Footer from "./sidebar-footer.svelte"; +import GroupAction from "./sidebar-group-action.svelte"; +import GroupContent from "./sidebar-group-content.svelte"; +import GroupLabel from "./sidebar-group-label.svelte"; +import Group from "./sidebar-group.svelte"; +import Header from "./sidebar-header.svelte"; +import Input from "./sidebar-input.svelte"; +import Inset from "./sidebar-inset.svelte"; +import MenuAction from "./sidebar-menu-action.svelte"; +import MenuBadge from "./sidebar-menu-badge.svelte"; +import MenuButton from "./sidebar-menu-button.svelte"; +import MenuItem from "./sidebar-menu-item.svelte"; +import MenuSkeleton from "./sidebar-menu-skeleton.svelte"; +import MenuSubButton from "./sidebar-menu-sub-button.svelte"; +import MenuSubItem from "./sidebar-menu-sub-item.svelte"; +import MenuSub from "./sidebar-menu-sub.svelte"; +import Menu from "./sidebar-menu.svelte"; +import Provider from "./sidebar-provider.svelte"; +import Rail from "./sidebar-rail.svelte"; +import Separator from "./sidebar-separator.svelte"; +import Trigger from "./sidebar-trigger.svelte"; +import Root from "./sidebar.svelte"; + +export { + Content, + Footer, + Group, + GroupAction, + GroupContent, + GroupLabel, + Header, + Input, + Inset, + Menu, + MenuAction, + MenuBadge, + MenuButton, + MenuItem, + MenuSkeleton, + MenuSub, + MenuSubButton, + MenuSubItem, + Provider, + Rail, + Root, + Separator, + // + Root as Sidebar, + Content as SidebarContent, + Footer as SidebarFooter, + Group as SidebarGroup, + GroupAction as SidebarGroupAction, + GroupContent as SidebarGroupContent, + GroupLabel as SidebarGroupLabel, + Header as SidebarHeader, + Input as SidebarInput, + Inset as SidebarInset, + Menu as SidebarMenu, + MenuAction as SidebarMenuAction, + MenuBadge as SidebarMenuBadge, + MenuButton as SidebarMenuButton, + MenuItem as SidebarMenuItem, + MenuSkeleton as SidebarMenuSkeleton, + MenuSub as SidebarMenuSub, + MenuSubButton as SidebarMenuSubButton, + MenuSubItem as SidebarMenuSubItem, + Provider as SidebarProvider, + Rail as SidebarRail, + Separator as SidebarSeparator, + Trigger as SidebarTrigger, + Trigger, + useSidebar, +}; diff --git a/website/src/lib/components/ui/sidebar/sidebar-content.svelte b/website/src/lib/components/ui/sidebar/sidebar-content.svelte new file mode 100644 index 0000000..f121800 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-content.svelte @@ -0,0 +1,24 @@ + + +
+ {@render children?.()} +
diff --git a/website/src/lib/components/ui/sidebar/sidebar-footer.svelte b/website/src/lib/components/ui/sidebar/sidebar-footer.svelte new file mode 100644 index 0000000..6259cb9 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-footer.svelte @@ -0,0 +1,21 @@ + + +
+ {@render children?.()} +
diff --git a/website/src/lib/components/ui/sidebar/sidebar-group-action.svelte b/website/src/lib/components/ui/sidebar/sidebar-group-action.svelte new file mode 100644 index 0000000..fb84e4a --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-group-action.svelte @@ -0,0 +1,36 @@ + + +{#if child} + {@render child({ props: mergedProps })} +{:else} + +{/if} diff --git a/website/src/lib/components/ui/sidebar/sidebar-group-content.svelte b/website/src/lib/components/ui/sidebar/sidebar-group-content.svelte new file mode 100644 index 0000000..415255f --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-group-content.svelte @@ -0,0 +1,21 @@ + + +
+ {@render children?.()} +
diff --git a/website/src/lib/components/ui/sidebar/sidebar-group-label.svelte b/website/src/lib/components/ui/sidebar/sidebar-group-label.svelte new file mode 100644 index 0000000..e292945 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-group-label.svelte @@ -0,0 +1,34 @@ + + +{#if child} + {@render child({ props: mergedProps })} +{:else} +
+ {@render children?.()} +
+{/if} diff --git a/website/src/lib/components/ui/sidebar/sidebar-group.svelte b/website/src/lib/components/ui/sidebar/sidebar-group.svelte new file mode 100644 index 0000000..ec18a69 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-group.svelte @@ -0,0 +1,21 @@ + + +
+ {@render children?.()} +
diff --git a/website/src/lib/components/ui/sidebar/sidebar-header.svelte b/website/src/lib/components/ui/sidebar/sidebar-header.svelte new file mode 100644 index 0000000..a1b2db1 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-header.svelte @@ -0,0 +1,21 @@ + + +
+ {@render children?.()} +
diff --git a/website/src/lib/components/ui/sidebar/sidebar-input.svelte b/website/src/lib/components/ui/sidebar/sidebar-input.svelte new file mode 100644 index 0000000..19b3666 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-input.svelte @@ -0,0 +1,21 @@ + + + diff --git a/website/src/lib/components/ui/sidebar/sidebar-inset.svelte b/website/src/lib/components/ui/sidebar/sidebar-inset.svelte new file mode 100644 index 0000000..d862761 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-inset.svelte @@ -0,0 +1,24 @@ + + +
+ {@render children?.()} +
diff --git a/website/src/lib/components/ui/sidebar/sidebar-menu-action.svelte b/website/src/lib/components/ui/sidebar/sidebar-menu-action.svelte new file mode 100644 index 0000000..fa3fb0c --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-menu-action.svelte @@ -0,0 +1,43 @@ + + +{#if child} + {@render child({ props: mergedProps })} +{:else} + +{/if} diff --git a/website/src/lib/components/ui/sidebar/sidebar-menu-badge.svelte b/website/src/lib/components/ui/sidebar/sidebar-menu-badge.svelte new file mode 100644 index 0000000..69e5a3c --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-menu-badge.svelte @@ -0,0 +1,29 @@ + + +
+ {@render children?.()} +
diff --git a/website/src/lib/components/ui/sidebar/sidebar-menu-button.svelte b/website/src/lib/components/ui/sidebar/sidebar-menu-button.svelte new file mode 100644 index 0000000..4bef683 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-menu-button.svelte @@ -0,0 +1,103 @@ + + + + +{#snippet Button({ props }: { props?: Record })} + {@const mergedProps = mergeProps(buttonProps, props)} + {#if child} + {@render child({ props: mergedProps })} + {:else} + + {/if} +{/snippet} + +{#if !tooltipContent} + {@render Button({})} +{:else} + + + {#snippet child({ props })} + {@render Button({ props })} + {/snippet} + + + +{/if} diff --git a/website/src/lib/components/ui/sidebar/sidebar-menu-item.svelte b/website/src/lib/components/ui/sidebar/sidebar-menu-item.svelte new file mode 100644 index 0000000..4db4453 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-menu-item.svelte @@ -0,0 +1,21 @@ + + +
  • + {@render children?.()} +
  • diff --git a/website/src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte b/website/src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte new file mode 100644 index 0000000..cc63b04 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte @@ -0,0 +1,36 @@ + + +
    + {#if showIcon} + + {/if} + + {@render children?.()} +
    diff --git a/website/src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte b/website/src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte new file mode 100644 index 0000000..987f104 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte @@ -0,0 +1,43 @@ + + +{#if child} + {@render child({ props: mergedProps })} +{:else} + + {@render children?.()} + +{/if} diff --git a/website/src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte b/website/src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte new file mode 100644 index 0000000..681d0f1 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte @@ -0,0 +1,21 @@ + + +
  • + {@render children?.()} +
  • diff --git a/website/src/lib/components/ui/sidebar/sidebar-menu-sub.svelte b/website/src/lib/components/ui/sidebar/sidebar-menu-sub.svelte new file mode 100644 index 0000000..8ab1111 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-menu-sub.svelte @@ -0,0 +1,25 @@ + + +
      + {@render children?.()} +
    diff --git a/website/src/lib/components/ui/sidebar/sidebar-menu.svelte b/website/src/lib/components/ui/sidebar/sidebar-menu.svelte new file mode 100644 index 0000000..946ccce --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-menu.svelte @@ -0,0 +1,21 @@ + + +
      + {@render children?.()} +
    diff --git a/website/src/lib/components/ui/sidebar/sidebar-provider.svelte b/website/src/lib/components/ui/sidebar/sidebar-provider.svelte new file mode 100644 index 0000000..5b0d0aa --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-provider.svelte @@ -0,0 +1,53 @@ + + + + + +
    + {@render children?.()} +
    +
    diff --git a/website/src/lib/components/ui/sidebar/sidebar-rail.svelte b/website/src/lib/components/ui/sidebar/sidebar-rail.svelte new file mode 100644 index 0000000..e913d21 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-rail.svelte @@ -0,0 +1,36 @@ + + + diff --git a/website/src/lib/components/ui/sidebar/sidebar-separator.svelte b/website/src/lib/components/ui/sidebar/sidebar-separator.svelte new file mode 100644 index 0000000..18d791b --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-separator.svelte @@ -0,0 +1,19 @@ + + + diff --git a/website/src/lib/components/ui/sidebar/sidebar-trigger.svelte b/website/src/lib/components/ui/sidebar/sidebar-trigger.svelte new file mode 100644 index 0000000..1825182 --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar-trigger.svelte @@ -0,0 +1,35 @@ + + + diff --git a/website/src/lib/components/ui/sidebar/sidebar.svelte b/website/src/lib/components/ui/sidebar/sidebar.svelte new file mode 100644 index 0000000..c8c36df --- /dev/null +++ b/website/src/lib/components/ui/sidebar/sidebar.svelte @@ -0,0 +1,104 @@ + + +{#if collapsible === "none"} +
    + {@render children?.()} +
    +{:else if sidebar.isMobile} + sidebar.openMobile, (v) => sidebar.setOpenMobile(v)} + {...restProps} + > + + + Sidebar + Displays the mobile sidebar. + +
    + {@render children?.()} +
    +
    +
    +{:else} + +{/if} diff --git a/website/src/lib/components/ui/skeleton/index.ts b/website/src/lib/components/ui/skeleton/index.ts new file mode 100644 index 0000000..186db21 --- /dev/null +++ b/website/src/lib/components/ui/skeleton/index.ts @@ -0,0 +1,7 @@ +import Root from "./skeleton.svelte"; + +export { + Root, + // + Root as Skeleton, +}; diff --git a/website/src/lib/components/ui/skeleton/skeleton.svelte b/website/src/lib/components/ui/skeleton/skeleton.svelte new file mode 100644 index 0000000..c7e3d26 --- /dev/null +++ b/website/src/lib/components/ui/skeleton/skeleton.svelte @@ -0,0 +1,17 @@ + + +
    diff --git a/website/src/lib/components/ui/tooltip/index.ts b/website/src/lib/components/ui/tooltip/index.ts new file mode 100644 index 0000000..313a7f0 --- /dev/null +++ b/website/src/lib/components/ui/tooltip/index.ts @@ -0,0 +1,21 @@ +import { Tooltip as TooltipPrimitive } from "bits-ui"; +import Trigger from "./tooltip-trigger.svelte"; +import Content from "./tooltip-content.svelte"; + +const Root = TooltipPrimitive.Root; +const Provider = TooltipPrimitive.Provider; +const Portal = TooltipPrimitive.Portal; + +export { + Root, + Trigger, + Content, + Provider, + Portal, + // + Root as Tooltip, + Content as TooltipContent, + Trigger as TooltipTrigger, + Provider as TooltipProvider, + Portal as TooltipPortal, +}; diff --git a/website/src/lib/components/ui/tooltip/tooltip-content.svelte b/website/src/lib/components/ui/tooltip/tooltip-content.svelte new file mode 100644 index 0000000..a279295 --- /dev/null +++ b/website/src/lib/components/ui/tooltip/tooltip-content.svelte @@ -0,0 +1,47 @@ + + + + + {@render children?.()} + + {#snippet child({ props })} +
    + {/snippet} +
    +
    +
    diff --git a/website/src/lib/components/ui/tooltip/tooltip-trigger.svelte b/website/src/lib/components/ui/tooltip/tooltip-trigger.svelte new file mode 100644 index 0000000..1acdaa4 --- /dev/null +++ b/website/src/lib/components/ui/tooltip/tooltip-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/website/src/lib/hooks/is-mobile.svelte.ts b/website/src/lib/hooks/is-mobile.svelte.ts new file mode 100644 index 0000000..a34b204 --- /dev/null +++ b/website/src/lib/hooks/is-mobile.svelte.ts @@ -0,0 +1,9 @@ +import { MediaQuery } from "svelte/reactivity"; + +const MOBILE_BREAKPOINT = 768; + +export class IsMobile extends MediaQuery { + constructor() { + super(`max-width: ${MOBILE_BREAKPOINT - 1}px`); + } +} diff --git a/website/src/lib/server/db/index.ts b/website/src/lib/server/db/index.ts index 54e3632..623e74d 100644 --- a/website/src/lib/server/db/index.ts +++ b/website/src/lib/server/db/index.ts @@ -1,6 +1,18 @@ import { drizzle } from 'drizzle-orm/postgres-js'; import postgres from 'postgres'; import { env } from '$env/dynamic/private'; +import * as schema from './schema'; + if (!env.DATABASE_URL) throw new Error('DATABASE_URL is not set'); -const client = postgres(env.DATABASE_URL); -export const db = drizzle(client); +/** + * Cache the database connection in development. This avoids creating a new connection on every HMR + * update. + */ +const globalForDb = globalThis as unknown as { + client: postgres.Sql | undefined; +}; + +const client = globalForDb.client ?? postgres(env.DATABASE_URL); +if (env.NODE_ENV !== 'production') globalForDb.client = client; + +export const db = drizzle(client, { schema }); \ No newline at end of file diff --git a/website/src/lib/server/db/schema.ts b/website/src/lib/server/db/schema.ts index aba346f..07e4737 100644 --- a/website/src/lib/server/db/schema.ts +++ b/website/src/lib/server/db/schema.ts @@ -1,6 +1,50 @@ -import { pgTable, serial, text, integer } from 'drizzle-orm/pg-core'; +import { pgTable, text, timestamp, boolean } from "drizzle-orm/pg-core"; -export const user = pgTable('user', { - id: serial('id').primaryKey(), - age: integer('age') +export const user = pgTable("user", { + id: text("id").primaryKey(), + name: text('name').notNull(), + email: text('email').notNull().unique(), + emailVerified: boolean('email_verified').notNull(), + image: text('image'), + createdAt: timestamp('created_at').notNull(), + updatedAt: timestamp('updated_at').notNull(), + isAdmin: boolean('is_admin'), + isBanned: boolean('is_banned'), + banReason: text('ban_reason') +}); + +export const session = pgTable("session", { + id: text("id").primaryKey(), + expiresAt: timestamp('expires_at').notNull(), + token: text('token').notNull().unique(), + createdAt: timestamp('created_at').notNull(), + updatedAt: timestamp('updated_at').notNull(), + ipAddress: text('ip_address'), + userAgent: text('user_agent'), + userId: text('user_id').notNull().references(() => user.id) +}); + +export const account = pgTable("account", { + id: text("id").primaryKey(), + accountId: text('account_id').notNull(), + providerId: text('provider_id').notNull(), + userId: text('user_id').notNull().references(() => user.id), + accessToken: text('access_token'), + refreshToken: text('refresh_token'), + idToken: text('id_token'), + accessTokenExpiresAt: timestamp('access_token_expires_at'), + refreshTokenExpiresAt: timestamp('refresh_token_expires_at'), + scope: text('scope'), + password: text('password'), + createdAt: timestamp('created_at').notNull(), + updatedAt: timestamp('updated_at').notNull() +}); + +export const verification = pgTable("verification", { + id: text("id").primaryKey(), + identifier: text('identifier').notNull(), + value: text('value').notNull(), + expiresAt: timestamp('expires_at').notNull(), + createdAt: timestamp('created_at'), + updatedAt: timestamp('updated_at') }); diff --git a/website/src/lib/stores/user-data.ts b/website/src/lib/stores/user-data.ts new file mode 100644 index 0000000..88c954f --- /dev/null +++ b/website/src/lib/stores/user-data.ts @@ -0,0 +1,13 @@ +import { writable } from 'svelte/store'; + +export type User = { + id: string; + name: string; + email: string; + isAdmin: boolean; + image: string; + isBanned: boolean; + banReason: string | null; +} | null; + +export const USER_DATA = writable(undefined); \ No newline at end of file diff --git a/website/src/routes/+layout.server.ts b/website/src/routes/+layout.server.ts new file mode 100644 index 0000000..2752ac3 --- /dev/null +++ b/website/src/routes/+layout.server.ts @@ -0,0 +1,22 @@ +import { auth } from '$lib/auth'; +import { db } from '$lib/server/db'; +import { eq } from 'drizzle-orm'; +import type { LayoutServerLoad } from './$types'; +import { dev } from '$app/environment'; + +export const load: LayoutServerLoad = async (event) => { + event.setHeaders({ + 'Cache-Control': dev + ? 'no-cache' + : 'private, max-age=30' + }); + + const sessionResponse = await auth.api.getSession({ + headers: event.request.headers + }); + + return { + userSession: sessionResponse?.user || null, + url: event.url.pathname, + }; +}; \ No newline at end of file diff --git a/website/src/routes/+layout.svelte b/website/src/routes/+layout.svelte index 9b776b7..61d1b94 100644 --- a/website/src/routes/+layout.svelte +++ b/website/src/routes/+layout.svelte @@ -1,6 +1,95 @@ -{@render children()} + + + + +
    +
    + + +

    test

    +
    +
    + +
    +
    +
    +
    + {@render children()} +
    +
    +
    +
    +
    +
    diff --git a/website/static/placeholder_logo.png b/website/static/placeholder_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7fff393efbc317209b500197cc749547e67855a6 GIT binary patch literal 20832 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 literal 0 HcmV?d00001