diff --git a/engine/src/auth/middleware.rs b/engine/src/auth/middleware.rs index 76574b6..5c144d0 100644 --- a/engine/src/auth/middleware.rs +++ b/engine/src/auth/middleware.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use poem::{web::Data, Error, FromRequest, Request, RequestBody, Result}; +use reqwest::StatusCode; use uuid::Uuid; use crate::state::AppState; @@ -33,7 +34,11 @@ impl<'a> FromRequest<'a> for AuthToken { // Check if active session exists with token let session = SessionState::get_by_id(token, &state.database) .await - .unwrap(); + .unwrap() + .ok_or(Error::from_string( + "Session not found, token valid but no session exists", + StatusCode::UNAUTHORIZED, + ))?; Ok(AuthToken::Active(ActiveUser { session })) } diff --git a/engine/src/auth/session.rs b/engine/src/auth/session.rs index 57d7623..6c27f39 100644 --- a/engine/src/auth/session.rs +++ b/engine/src/auth/session.rs @@ -35,12 +35,12 @@ impl SessionState { Ok(session) } - pub async fn get_by_id(id: Uuid, database: &Database) -> Result { + pub async fn get_by_id(id: Uuid, database: &Database) -> Result, sqlx::Error> { let session = sqlx::query_as::<_, SessionState>( "SELECT * FROM sessions WHERE id = $1 AND valid = TRUE", ) .bind(id) - .fetch_one(&database.pool) + .fetch_optional(&database.pool) .await?; Ok(session) diff --git a/web/package.json b/web/package.json index 13ac029..e7e0355 100644 --- a/web/package.json +++ b/web/package.json @@ -2,7 +2,7 @@ "name": "web", "version": "1.0.0", "description": "", - "main": "index.js", + "type": "module", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "vite", @@ -13,6 +13,7 @@ "author": "", "license": "GPL-3", "dependencies": { + "@tanstack/react-router": "^1.45.14", "@vitejs/plugin-react": "^4.3.1", "autoprefixer": "^10.4.19", "postcss": "^8.4.38", @@ -24,6 +25,8 @@ "zustand": "^4.5.4" }, "devDependencies": { + "@tanstack/router-devtools": "^1.45.14", + "@tanstack/router-plugin": "^1.45.13", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@types/url-search-params": "^1.1.2", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index f9efbc5..7851b80 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -5,6 +5,9 @@ settings: excludeLinksFromLockfile: false dependencies: + '@tanstack/react-router': + specifier: ^1.45.14 + version: 1.45.14(react-dom@18.3.1)(react@18.3.1) '@vitejs/plugin-react': specifier: ^4.3.1 version: 4.3.1(vite@5.2.10) @@ -34,6 +37,12 @@ dependencies: version: 4.5.4(@types/react@18.3.3)(react@18.3.1) devDependencies: + '@tanstack/router-devtools': + specifier: ^1.45.14 + version: 1.45.14(@tanstack/react-router@1.45.14)(csstype@3.1.3)(react-dom@18.3.1)(react@18.3.1) + '@tanstack/router-plugin': + specifier: ^1.45.13 + version: 1.45.13(vite@5.2.10) '@types/react': specifier: ^18.3.3 version: 18.3.3 @@ -69,7 +78,6 @@ packages: dependencies: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - dev: false /@babel/code-frame@7.24.7: resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} @@ -81,7 +89,6 @@ packages: /@babel/compat-data@7.25.0: resolution: {integrity: sha512-P4fwKI2mjEb3ZU5cnMJzvRsRKGBUcs8jvxIoRmr6ufAY9Xk2Bz7JubRTTivkw55c7WQJfTECeqYVa+HZ0FzREg==} engines: {node: '>=6.9.0'} - dev: false /@babel/core@7.24.9: resolution: {integrity: sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==} @@ -104,7 +111,6 @@ packages: semver: 6.3.1 transitivePeerDependencies: - supports-color - dev: false /@babel/generator@7.25.0: resolution: {integrity: sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==} @@ -114,7 +120,6 @@ packages: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 jsesc: 2.5.2 - dev: false /@babel/helper-compilation-targets@7.24.8: resolution: {integrity: sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==} @@ -125,7 +130,6 @@ packages: browserslist: 4.23.2 lru-cache: 5.1.1 semver: 6.3.1 - dev: false /@babel/helper-module-imports@7.24.7: resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} @@ -135,7 +139,6 @@ packages: '@babel/types': 7.25.0 transitivePeerDependencies: - supports-color - dev: false /@babel/helper-module-transforms@7.25.0(@babel/core@7.24.9): resolution: {integrity: sha512-bIkOa2ZJYn7FHnepzr5iX9Kmz8FjIz4UKzJ9zhX3dnYuVW0xul9RuR3skBfoLu+FPTQw90EHW9rJsSZhyLQ3fQ==} @@ -150,12 +153,10 @@ packages: '@babel/traverse': 7.25.1 transitivePeerDependencies: - supports-color - dev: false /@babel/helper-plugin-utils@7.24.8: resolution: {integrity: sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==} engines: {node: '>=6.9.0'} - dev: false /@babel/helper-simple-access@7.24.7: resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} @@ -165,12 +166,10 @@ packages: '@babel/types': 7.25.0 transitivePeerDependencies: - supports-color - dev: false /@babel/helper-string-parser@7.24.8: resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} engines: {node: '>=6.9.0'} - dev: false /@babel/helper-validator-identifier@7.24.7: resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} @@ -179,7 +178,6 @@ packages: /@babel/helper-validator-option@7.24.8: resolution: {integrity: sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==} engines: {node: '>=6.9.0'} - dev: false /@babel/helpers@7.25.0: resolution: {integrity: sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==} @@ -187,7 +185,6 @@ packages: dependencies: '@babel/template': 7.25.0 '@babel/types': 7.25.0 - dev: false /@babel/highlight@7.24.7: resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} @@ -204,7 +201,26 @@ packages: hasBin: true dependencies: '@babel/types': 7.25.0 - dev: false + + /@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.24.9): + resolution: {integrity: sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.9 + '@babel/helper-plugin-utils': 7.24.8 + dev: true + + /@babel/plugin-syntax-typescript@7.24.7(@babel/core@7.24.9): + resolution: {integrity: sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.9 + '@babel/helper-plugin-utils': 7.24.8 + dev: true /@babel/plugin-transform-react-jsx-self@7.24.7(@babel/core@7.24.9): resolution: {integrity: sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==} @@ -233,7 +249,6 @@ packages: '@babel/code-frame': 7.24.7 '@babel/parser': 7.25.0 '@babel/types': 7.25.0 - dev: false /@babel/traverse@7.25.1: resolution: {integrity: sha512-LrHHoWq08ZpmmFqBAzN+hUdWwy5zt7FGa/hVwMcOqW6OVtwqaoD5utfuGYU87JYxdZgLUvktAsn37j/sYR9siA==} @@ -248,7 +263,6 @@ packages: globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: false /@babel/types@7.25.0: resolution: {integrity: sha512-LcnxQSsd9aXOIgmmSpvZ/1yo46ra2ESYyqLcryaBZOghxy5qqOBjvCWP5JfkI8yl9rlxRgdLTTMCQQRcN2hdCg==} @@ -257,7 +271,6 @@ packages: '@babel/helper-string-parser': 7.24.8 '@babel/helper-validator-identifier': 7.24.7 to-fast-properties: 2.0.0 - dev: false /@esbuild/aix-ppc64@0.20.2: resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} @@ -265,7 +278,6 @@ packages: cpu: [ppc64] os: [aix] requiresBuild: true - dev: false optional: true /@esbuild/android-arm64@0.20.2: @@ -274,7 +286,6 @@ packages: cpu: [arm64] os: [android] requiresBuild: true - dev: false optional: true /@esbuild/android-arm@0.20.2: @@ -283,7 +294,6 @@ packages: cpu: [arm] os: [android] requiresBuild: true - dev: false optional: true /@esbuild/android-x64@0.20.2: @@ -292,7 +302,6 @@ packages: cpu: [x64] os: [android] requiresBuild: true - dev: false optional: true /@esbuild/darwin-arm64@0.20.2: @@ -301,7 +310,6 @@ packages: cpu: [arm64] os: [darwin] requiresBuild: true - dev: false optional: true /@esbuild/darwin-x64@0.20.2: @@ -310,7 +318,6 @@ packages: cpu: [x64] os: [darwin] requiresBuild: true - dev: false optional: true /@esbuild/freebsd-arm64@0.20.2: @@ -319,7 +326,6 @@ packages: cpu: [arm64] os: [freebsd] requiresBuild: true - dev: false optional: true /@esbuild/freebsd-x64@0.20.2: @@ -328,7 +334,6 @@ packages: cpu: [x64] os: [freebsd] requiresBuild: true - dev: false optional: true /@esbuild/linux-arm64@0.20.2: @@ -337,7 +342,6 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-arm@0.20.2: @@ -346,7 +350,6 @@ packages: cpu: [arm] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-ia32@0.20.2: @@ -355,7 +358,6 @@ packages: cpu: [ia32] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-loong64@0.20.2: @@ -364,7 +366,6 @@ packages: cpu: [loong64] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-mips64el@0.20.2: @@ -373,7 +374,6 @@ packages: cpu: [mips64el] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-ppc64@0.20.2: @@ -382,7 +382,6 @@ packages: cpu: [ppc64] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-riscv64@0.20.2: @@ -391,7 +390,6 @@ packages: cpu: [riscv64] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-s390x@0.20.2: @@ -400,7 +398,6 @@ packages: cpu: [s390x] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-x64@0.20.2: @@ -409,7 +406,6 @@ packages: cpu: [x64] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/netbsd-x64@0.20.2: @@ -418,7 +414,6 @@ packages: cpu: [x64] os: [netbsd] requiresBuild: true - dev: false optional: true /@esbuild/openbsd-x64@0.20.2: @@ -427,7 +422,6 @@ packages: cpu: [x64] os: [openbsd] requiresBuild: true - dev: false optional: true /@esbuild/sunos-x64@0.20.2: @@ -436,7 +430,6 @@ packages: cpu: [x64] os: [sunos] requiresBuild: true - dev: false optional: true /@esbuild/win32-arm64@0.20.2: @@ -445,7 +438,6 @@ packages: cpu: [arm64] os: [win32] requiresBuild: true - dev: false optional: true /@esbuild/win32-ia32@0.20.2: @@ -454,7 +446,6 @@ packages: cpu: [ia32] os: [win32] requiresBuild: true - dev: false optional: true /@esbuild/win32-x64@0.20.2: @@ -463,7 +454,6 @@ packages: cpu: [x64] os: [win32] requiresBuild: true - dev: false optional: true /@eslint-community/eslint-utils@4.4.0(eslint@9.8.0): @@ -548,28 +538,23 @@ packages: '@jridgewell/set-array': 1.2.1 '@jridgewell/sourcemap-codec': 1.4.15 '@jridgewell/trace-mapping': 0.3.25 - dev: false /@jridgewell/resolve-uri@3.1.2: resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - dev: false /@jridgewell/set-array@1.2.1: resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} - dev: false /@jridgewell/sourcemap-codec@1.4.15: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: false /@jridgewell/trace-mapping@0.3.25: resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - dev: false /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -601,7 +586,6 @@ packages: cpu: [arm] os: [android] requiresBuild: true - dev: false optional: true /@rollup/rollup-android-arm64@4.16.4: @@ -609,7 +593,6 @@ packages: cpu: [arm64] os: [android] requiresBuild: true - dev: false optional: true /@rollup/rollup-darwin-arm64@4.16.4: @@ -617,7 +600,6 @@ packages: cpu: [arm64] os: [darwin] requiresBuild: true - dev: false optional: true /@rollup/rollup-darwin-x64@4.16.4: @@ -625,7 +607,6 @@ packages: cpu: [x64] os: [darwin] requiresBuild: true - dev: false optional: true /@rollup/rollup-linux-arm-gnueabihf@4.16.4: @@ -633,7 +614,6 @@ packages: cpu: [arm] os: [linux] requiresBuild: true - dev: false optional: true /@rollup/rollup-linux-arm-musleabihf@4.16.4: @@ -641,7 +621,6 @@ packages: cpu: [arm] os: [linux] requiresBuild: true - dev: false optional: true /@rollup/rollup-linux-arm64-gnu@4.16.4: @@ -649,7 +628,6 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true - dev: false optional: true /@rollup/rollup-linux-arm64-musl@4.16.4: @@ -657,7 +635,6 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true - dev: false optional: true /@rollup/rollup-linux-powerpc64le-gnu@4.16.4: @@ -665,7 +642,6 @@ packages: cpu: [ppc64] os: [linux] requiresBuild: true - dev: false optional: true /@rollup/rollup-linux-riscv64-gnu@4.16.4: @@ -673,7 +649,6 @@ packages: cpu: [riscv64] os: [linux] requiresBuild: true - dev: false optional: true /@rollup/rollup-linux-s390x-gnu@4.16.4: @@ -681,7 +656,6 @@ packages: cpu: [s390x] os: [linux] requiresBuild: true - dev: false optional: true /@rollup/rollup-linux-x64-gnu@4.16.4: @@ -689,7 +663,6 @@ packages: cpu: [x64] os: [linux] requiresBuild: true - dev: false optional: true /@rollup/rollup-linux-x64-musl@4.16.4: @@ -697,7 +670,6 @@ packages: cpu: [x64] os: [linux] requiresBuild: true - dev: false optional: true /@rollup/rollup-win32-arm64-msvc@4.16.4: @@ -705,7 +677,6 @@ packages: cpu: [arm64] os: [win32] requiresBuild: true - dev: false optional: true /@rollup/rollup-win32-ia32-msvc@4.16.4: @@ -713,7 +684,6 @@ packages: cpu: [ia32] os: [win32] requiresBuild: true - dev: false optional: true /@rollup/rollup-win32-x64-msvc@4.16.4: @@ -721,9 +691,102 @@ packages: cpu: [x64] os: [win32] requiresBuild: true - dev: false optional: true + /@tanstack/history@1.45.3: + resolution: {integrity: sha512-n4XXInV9irIq0obRvINIkESkGk280Q+xkIIbswmM0z9nAu2wsIRZNvlmPrtYh6bgNWtItOWWoihFUjLTW8g6Jg==} + engines: {node: '>=12'} + + /@tanstack/react-router@1.45.14(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-eGSOaZI2urexpkoJb+SzOAnoZ61IuMzCzBziU6HD9b6lnySXQ2Z4LFGcHx2+BK5rzkGXtkfOoGLtQ2SE6lFTdA==} + engines: {node: '>=12'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + dependencies: + '@tanstack/history': 1.45.3 + '@tanstack/react-store': 0.5.5(react-dom@18.3.1)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + + /@tanstack/react-store@0.5.5(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-1orYXGatBqXCYKuroFwV8Ll/6aDa5E3pU6RR4h7RvRk7TmxF1+zLCsWALZaeijXkySNMGmvawSbUXRypivg2XA==} + peerDependencies: + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + dependencies: + '@tanstack/store': 0.5.5 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + use-sync-external-store: 1.2.2(react@18.3.1) + + /@tanstack/router-devtools@1.45.14(@tanstack/react-router@1.45.14)(csstype@3.1.3)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-BZ/TiN47uV9DFeULYvXSzKKgQU6ezmWmEfPaQsx35KWSLC4awOOo+A7AVDITURBxgZ+vB1vqGkGbLp7d34mGIQ==} + engines: {node: '>=12'} + peerDependencies: + '@tanstack/react-router': ^1.45.14 + react: '>=18' + react-dom: '>=18' + dependencies: + '@tanstack/react-router': 1.45.14(react-dom@18.3.1)(react@18.3.1) + clsx: 2.1.1 + goober: 2.1.14(csstype@3.1.3) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + transitivePeerDependencies: + - csstype + dev: true + + /@tanstack/router-generator@1.45.7: + resolution: {integrity: sha512-5B756YXpZO0/yr7ahsxXoBOCpqroLx/D3l6X9qPlZaP0FVHVmTR6ZKGRX6zzuAxns/VO+sxnQso4AYLdDyZ9GA==} + engines: {node: '>=12'} + dependencies: + prettier: 3.3.3 + zod: 3.23.8 + dev: true + + /@tanstack/router-plugin@1.45.13(vite@5.2.10): + resolution: {integrity: sha512-7IWdtIDC5jjhD6IZ5c/s11xNwvKDom/p6ZOO78FxeeA0FIaSx+3AQD7/iVhzfiRfepqGmecLn9a1KfNTFGQI/A==} + engines: {node: '>=12'} + peerDependencies: + '@rsbuild/core': '>=0.7.9' + vite: '>=5.0.13' + webpack: '>=5.92.0' + peerDependenciesMeta: + '@rsbuild/core': + optional: true + vite: + optional: true + webpack: + optional: true + dependencies: + '@babel/core': 7.24.9 + '@babel/generator': 7.25.0 + '@babel/parser': 7.25.0 + '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.24.9) + '@babel/plugin-syntax-typescript': 7.24.7(@babel/core@7.24.9) + '@babel/template': 7.25.0 + '@babel/traverse': 7.25.1 + '@babel/types': 7.25.0 + '@tanstack/router-generator': 1.45.7 + '@types/babel__core': 7.20.5 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.6 + babel-dead-code-elimination: 1.0.6 + chokidar: 3.6.0 + unplugin: 1.12.0 + vite: 5.2.10 + zod: 3.23.8 + transitivePeerDependencies: + - supports-color + dev: true + + /@tanstack/store@0.5.5: + resolution: {integrity: sha512-EOSrgdDAJExbvRZEQ/Xhh9iZchXpMN+ga1Bnk8Nmygzs8TfiE6hbzThF+Pr2G19uHL6+DTDTHhJ8VQiOd7l4tA==} + /@types/babel__core@7.20.5: resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} dependencies: @@ -732,30 +795,25 @@ packages: '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.20.6 - dev: false /@types/babel__generator@7.6.8: resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} dependencies: '@babel/types': 7.25.0 - dev: false /@types/babel__template@7.4.4: resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} dependencies: '@babel/parser': 7.25.0 '@babel/types': 7.25.0 - dev: false /@types/babel__traverse@7.20.6: resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} dependencies: '@babel/types': 7.25.0 - dev: false /@types/estree@1.0.5: resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - dev: false /@types/normalize-package-data@2.4.4: resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -981,7 +1039,6 @@ packages: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 - dev: false /arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -1094,13 +1151,23 @@ packages: deep-equal: 2.2.3 dev: true + /babel-dead-code-elimination@1.0.6: + resolution: {integrity: sha512-JxFi9qyRJpN0LjEbbjbN8g0ux71Qppn9R8Qe3k6QzHg2CaKsbUQtbn307LQGiDLGjV6JCtEFqfxzVig9MyDCHQ==} + dependencies: + '@babel/core': 7.24.9 + '@babel/parser': 7.25.0 + '@babel/traverse': 7.25.1 + '@babel/types': 7.25.0 + transitivePeerDependencies: + - supports-color + dev: true + /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} /binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} - dev: false /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -1140,7 +1207,6 @@ packages: electron-to-chromium: 1.5.2 node-releases: 2.0.14 update-browserslist-db: 1.1.0(browserslist@4.23.2) - dev: false /builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} @@ -1174,7 +1240,6 @@ packages: /caniuse-lite@1.0.30001643: resolution: {integrity: sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==} - dev: false /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -1205,7 +1270,6 @@ packages: readdirp: 3.6.0 optionalDependencies: fsevents: 2.3.3 - dev: false /ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} @@ -1223,6 +1287,11 @@ packages: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} dev: false + /clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + dev: true + /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -1251,7 +1320,6 @@ packages: /convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: false /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} @@ -1383,7 +1451,6 @@ packages: /electron-to-chromium@1.5.2: resolution: {integrity: sha512-kc4r3U3V3WLaaZqThjYz/Y6z8tJe+7K0bbjUVo3i+LWIypVdMx5nXCkwRe6SWbY6ILqLdc1rKcKmr3HoH7wjSQ==} - dev: false /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1556,12 +1623,10 @@ packages: '@esbuild/win32-arm64': 0.20.2 '@esbuild/win32-ia32': 0.20.2 '@esbuild/win32-x64': 0.20.2 - dev: false /escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} - dev: false /escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} @@ -1914,7 +1979,6 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true - dev: false optional: true /function-bind@1.1.2: @@ -1937,7 +2001,6 @@ packages: /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} - dev: false /get-intrinsic@1.2.4: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} @@ -1986,7 +2049,6 @@ packages: /globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} - dev: false /globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} @@ -2013,6 +2075,14 @@ packages: slash: 3.0.0 dev: true + /goober@2.1.14(csstype@3.1.3): + resolution: {integrity: sha512-4UpC0NdGyAFqLNPnhCT2iHpza2q+RAY3GV85a/mRPdzyPQMsj0KmMMuetdIkzWRbJ+Hgau1EZztq8ImmiMGhsg==} + peerDependencies: + csstype: ^3.0.10 + dependencies: + csstype: 3.1.3 + dev: true + /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: @@ -2135,7 +2205,6 @@ packages: engines: {node: '>=8'} dependencies: binary-extensions: 2.3.0 - dev: false /is-boolean-object@1.1.2: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} @@ -2335,7 +2404,6 @@ packages: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} hasBin: true - dev: false /json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} @@ -2357,7 +2425,6 @@ packages: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true - dev: false /jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} @@ -2434,7 +2501,6 @@ packages: hasBin: true dependencies: js-tokens: 4.0.0 - dev: false /lru-cache@10.2.1: resolution: {integrity: sha512-tS24spDe/zXhWbNPErCHs/AGOzbKGHT+ybSBqmdLm8WZ1xXLWvH8Qn71QPAlqVhd0qUTWjy+Kl9JmISgDdEjsA==} @@ -2445,7 +2511,6 @@ packages: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} dependencies: yallist: 3.1.1 - dev: false /merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} @@ -2495,7 +2560,6 @@ packages: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - dev: false /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -2503,7 +2567,6 @@ packages: /node-releases@2.0.14: resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - dev: false /normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} @@ -2517,7 +2580,6 @@ packages: /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} - dev: false /normalize-range@0.1.2: resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} @@ -2673,7 +2735,6 @@ packages: /picocolors@1.0.1: resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} - dev: false /picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -2767,7 +2828,6 @@ packages: nanoid: 3.3.7 picocolors: 1.0.0 source-map-js: 1.2.0 - dev: false /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} @@ -2787,6 +2847,12 @@ packages: hasBin: true dev: true + /prettier@3.3.3: + resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} + engines: {node: '>=14'} + hasBin: true + dev: true + /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -2803,7 +2869,6 @@ packages: loose-envify: 1.4.0 react: 18.3.1 scheduler: 0.23.2 - dev: false /react-refresh@0.14.2: resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} @@ -2815,7 +2880,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: loose-envify: 1.4.0 - dev: false /read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} @@ -2847,7 +2911,6 @@ packages: engines: {node: '>=8.10.0'} dependencies: picomatch: 2.3.1 - dev: false /reflect.getprototypeof@1.0.6: resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} @@ -2918,7 +2981,6 @@ packages: '@rollup/rollup-win32-ia32-msvc': 4.16.4 '@rollup/rollup-win32-x64-msvc': 4.16.4 fsevents: 2.3.3 - dev: false /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -2954,7 +3016,6 @@ packages: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} dependencies: loose-envify: 1.4.0 - dev: false /semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} @@ -2964,7 +3025,6 @@ packages: /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - dev: false /semver@7.6.3: resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} @@ -3027,7 +3087,6 @@ packages: /source-map-js@1.2.0: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} - dev: false /spdx-correct@3.2.0: resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} @@ -3224,10 +3283,15 @@ packages: any-promise: 1.3.0 dev: false + /tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + + /tiny-warning@1.0.3: + resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} - dev: false /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} @@ -3338,6 +3402,16 @@ packages: which-boxed-primitive: 1.0.2 dev: true + /unplugin@1.12.0: + resolution: {integrity: sha512-KeczzHl2sATPQUx1gzo+EnUkmN4VmGBYRRVOZSGvGITE9rGHRDGqft6ONceP3vgXcyJ2XjX5axG5jMWUwNCYLw==} + engines: {node: '>=14.0.0'} + dependencies: + acorn: 8.12.1 + chokidar: 3.6.0 + webpack-sources: 3.2.3 + webpack-virtual-modules: 0.6.2 + dev: true + /update-browserslist-db@1.0.13(browserslist@4.23.0): resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} hasBin: true @@ -3358,7 +3432,6 @@ packages: browserslist: 4.23.2 escalade: 3.1.2 picocolors: 1.0.1 - dev: false /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -3380,7 +3453,6 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: react: 18.3.1 - dev: false /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -3426,7 +3498,15 @@ packages: rollup: 4.16.4 optionalDependencies: fsevents: 2.3.3 - dev: false + + /webpack-sources@3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} + engines: {node: '>=10.13.0'} + dev: true + + /webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + dev: true /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} @@ -3509,7 +3589,6 @@ packages: /yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: false /yaml@2.4.1: resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==} @@ -3522,6 +3601,10 @@ packages: engines: {node: '>=10'} dev: true + /zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + dev: true + /zustand@4.5.4(@types/react@18.3.3)(react@18.3.1): resolution: {integrity: sha512-/BPMyLKJPtFEvVL0E9E9BTUM63MNyhPGlvxk1XjrfWTUlV+BR8jufjsovHzrtR6YNcBEcL7cMHovL1n9xHawEg==} engines: {node: '>=12.7.0'} diff --git a/web/postcss.config.js b/web/postcss.config.js index 811990a..3a99d35 100644 --- a/web/postcss.config.js +++ b/web/postcss.config.js @@ -1,6 +1,13 @@ -module.exports = { - plugins: [ - require("tailwindcss"), - require("autoprefixer"), - ], +// module.exports = { +// plugins: [ +// require("tailwindcss"), +// require("autoprefixer"), +// ], +// }; + +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, }; diff --git a/web/src/api/core.ts b/web/src/api/core.ts index 44e9563..17f92fd 100644 --- a/web/src/api/core.ts +++ b/web/src/api/core.ts @@ -1,19 +1,31 @@ import useSWR from "swr"; +import { useAuth } from "./auth"; const BASE_URL = "http://localhost:3000" -export const useHttp = (url: string, token: string | null) => useSWR(token && url, async (): Promise => { - const headers = new Headers(); +export const useHttp = (url: string) => { + const { token, clearAuthToken } = useAuth(); - headers.append("Authorization", "Bearer " + token); + return useSWR(token && url, async (): Promise => { + const headers = new Headers(); - try { - const response = await fetch(BASE_URL + url, { headers }); - const data = await response.json() as K; + headers.append("Authorization", "Bearer " + token); - return data as K; - } catch (error) { - console.error(error); - return null; - } -}); + try { + const response = await fetch(BASE_URL + url, { headers }); + + if (response.status === 401) { + console.log("Token expired, clearing token"); + clearAuthToken(); + return null; + } + + const data = await response.json() as K; + + return data as K; + } catch (error) { + console.error(error); + return null; + } + }); +}; diff --git a/web/src/api/me.ts b/web/src/api/me.ts index 43b639b..5c79e8c 100644 --- a/web/src/api/me.ts +++ b/web/src/api/me.ts @@ -1,5 +1,3 @@ -import useSWR from "swr"; -import { useAuth } from "./auth"; import { useHttp } from "./core"; export type ApiMeResponse = { @@ -30,4 +28,4 @@ export type ApiMeResponse = { "nickname": any } -export const useApiMe = (token: string | null) => useHttp("/me", token); +export const useApiMe = () => useHttp("/me"); diff --git a/web/src/api/temp_all.ts b/web/src/api/temp_all.ts index 8136e85..9a2fb07 100644 --- a/web/src/api/temp_all.ts +++ b/web/src/api/temp_all.ts @@ -1,8 +1,7 @@ -import useSWR from "swr"; import { useHttp } from "./core"; type PropertiesResponse = { id: number, }; -export const useTempAll = (token: string | null) => useHttp("/api/properties", token); +export const useTempAll = () => useHttp("/api/properties"); diff --git a/web/src/components/Navbar.tsx b/web/src/components/Navbar.tsx index 5421684..fd6947b 100644 --- a/web/src/components/Navbar.tsx +++ b/web/src/components/Navbar.tsx @@ -1,16 +1,15 @@ -import useSWR from "swr"; -import { apiMe, useApiMe } from "../api/me"; +import { useApiMe } from "../api/me"; import { useAuth } from "../api/auth"; const LOGIN_URL = "http://localhost:3000/login"; export const Navbar = () => { const { token, clearAuthToken } = useAuth(); - const { data: meData, isLoading: isVerifyingAuth } = useApiMe(token); - + const { data: meData, isLoading: isVerifyingAuth } = useApiMe(); + const login_here_url = LOGIN_URL + "?redirect=" + encodeURIComponent(window.location.href); - console.log({meData}); + console.log({ meData }); return (
diff --git a/web/src/index.tsx b/web/src/index.tsx index 02b9f59..92e386e 100644 --- a/web/src/index.tsx +++ b/web/src/index.tsx @@ -1,10 +1,23 @@ import React from 'react' import ReactDOM from 'react-dom/client' -import {App} from './App.tsx' +import { RouterProvider, createRouter } from '@tanstack/react-router' import './index.css' +// Import the generated route tree +import { routeTree } from './routeTree.gen' + +// Create a new router instance +const router = createRouter({ routeTree }) + +// Register the router instance for type safety +declare module '@tanstack/react-router' { + interface Register { + router: typeof router + } +} + ReactDOM.createRoot(document.getElementById('root')!).render( - + , -) +); diff --git a/web/src/routeTree.gen.ts b/web/src/routeTree.gen.ts new file mode 100644 index 0000000..0edc01b --- /dev/null +++ b/web/src/routeTree.gen.ts @@ -0,0 +1,82 @@ +/* prettier-ignore-start */ + +/* eslint-disable */ + +// @ts-nocheck + +// noinspection JSUnusedGlobalSymbols + +// This file is auto-generated by TanStack Router + +import { createFileRoute } from '@tanstack/react-router' + +// Import Routes + +import { Route as rootRoute } from './routes/__root' + +// Create Virtual Routes + +const AboutLazyImport = createFileRoute('/about')() +const IndexLazyImport = createFileRoute('/')() + +// Create/Update Routes + +const AboutLazyRoute = AboutLazyImport.update({ + path: '/about', + getParentRoute: () => rootRoute, +} as any).lazy(() => import('./routes/about.lazy').then((d) => d.Route)) + +const IndexLazyRoute = IndexLazyImport.update({ + path: '/', + getParentRoute: () => rootRoute, +} as any).lazy(() => import('./routes/index.lazy').then((d) => d.Route)) + +// Populate the FileRoutesByPath interface + +declare module '@tanstack/react-router' { + interface FileRoutesByPath { + '/': { + id: '/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof IndexLazyImport + parentRoute: typeof rootRoute + } + '/about': { + id: '/about' + path: '/about' + fullPath: '/about' + preLoaderRoute: typeof AboutLazyImport + parentRoute: typeof rootRoute + } + } +} + +// Create and export the route tree + +export const routeTree = rootRoute.addChildren({ + IndexLazyRoute, + AboutLazyRoute, +}) + +/* prettier-ignore-end */ + +/* ROUTE_MANIFEST_START +{ + "routes": { + "__root__": { + "filePath": "__root.tsx", + "children": [ + "/", + "/about" + ] + }, + "/": { + "filePath": "index.lazy.tsx" + }, + "/about": { + "filePath": "about.lazy.tsx" + } + } +} +ROUTE_MANIFEST_END */ diff --git a/web/src/routes/__root.tsx b/web/src/routes/__root.tsx new file mode 100644 index 0000000..bd1e45b --- /dev/null +++ b/web/src/routes/__root.tsx @@ -0,0 +1,20 @@ +import { createRootRoute, Link, Outlet } from '@tanstack/react-router' +import { TanStackRouterDevtools } from '@tanstack/router-devtools' + +export const Route = createRootRoute({ + component: () => ( + <> +
+ + Home + {' '} + + About + +
+
+ + + + ), +}) diff --git a/web/src/routes/about.lazy.tsx b/web/src/routes/about.lazy.tsx new file mode 100644 index 0000000..71eaf17 --- /dev/null +++ b/web/src/routes/about.lazy.tsx @@ -0,0 +1,9 @@ +import { createLazyFileRoute } from '@tanstack/react-router' + +export const Route = createLazyFileRoute('/about')({ + component: About, +}) + +function About() { + return
Hello from About!
+} diff --git a/web/src/routes/index.lazy.tsx b/web/src/routes/index.lazy.tsx new file mode 100644 index 0000000..c0c7415 --- /dev/null +++ b/web/src/routes/index.lazy.tsx @@ -0,0 +1,13 @@ +import { createLazyFileRoute } from '@tanstack/react-router' + +export const Route = createLazyFileRoute('/')({ + component: Index, +}) + +function Index() { + return ( +
+

Welcome Home!

+
+ ) +} diff --git a/web/tsconfig.json b/web/tsconfig.json index 2daf07f..e3a862c 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -11,9 +11,9 @@ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ /* Language and Environment */ - "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - "jsx": "preserve", /* Specify what JSX code is generated. */ + "target": "es2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + "lib": ["ES2020", "DOM", "DOM.Iterable"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + "jsx": "react-jsx", /* Specify what JSX code is generated. */ // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ @@ -21,13 +21,13 @@ // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ /* Modules */ - "module": "commonjs", /* Specify what module code is generated. */ + "module": "ESNext", /* Specify what module code is generated. */ // "rootDir": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + "moduleResolution": "Bundler", /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ @@ -39,7 +39,7 @@ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ + "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ @@ -57,7 +57,7 @@ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ // "outDir": "./", /* Specify an output folder for all emitted files. */ // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ + "noEmit": true, /* Disable emitting files from a compilation. */ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ @@ -72,7 +72,7 @@ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ diff --git a/web/vite.config.ts b/web/vite.config.ts index 92babc1..cc1a400 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -1,7 +1,8 @@ import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' +import { TanStackRouterVite } from '@tanstack/router-plugin/vite'; // https://vitejs.dev/config/ export default defineConfig({ - plugins: [react()], -}) + plugins: [TanStackRouterVite(), react()], +});