diff --git a/web/package.json b/web/package.json index 99b66c1..8447300 100644 --- a/web/package.json +++ b/web/package.json @@ -14,7 +14,7 @@ "@bufbuild/protobuf": "^2.6.0", "@connectrpc/connect": "^2.0.2", "@connectrpc/connect-web": "^2.0.2", - "@eslint/js": "^9.30.0", + "@eslint/js": "^9.30.1", "@internationalized/date": "^3.8.2", "@lucide/svelte": "^0.515.0", "@sveltejs/adapter-static": "^3.0.8", @@ -22,14 +22,14 @@ "@sveltejs/vite-plugin-svelte": "^5.1.0", "@tailwindcss/vite": "^4.1.11", "@types/eslint": "^9.6.1", - "@types/node": "^22.15.34", + "@types/node": "^22.16.0", "bits-ui": "2.8.10", "clsx": "^2.1.1", - "eslint": "^9.30.0", + "eslint": "^9.30.1", "eslint-config-prettier": "^10.1.5", "eslint-plugin-svelte": "^3.10.1", "formsnap": "^2.0.1", - "globals": "^16.2.0", + "globals": "^16.3.0", "mode-watcher": "^1.1.0", "prettier": "^3.6.2", "prettier-plugin-svelte": "^3.4.0", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 2935aa5..162a3d2 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -25,8 +25,8 @@ importers: specifier: ^2.0.2 version: 2.0.2(@bufbuild/protobuf@2.6.0)(@connectrpc/connect@2.0.2(@bufbuild/protobuf@2.6.0)) '@eslint/js': - specifier: ^9.30.0 - version: 9.30.0 + specifier: ^9.30.1 + version: 9.30.1 '@internationalized/date': specifier: ^3.8.2 version: 3.8.2 @@ -35,22 +35,22 @@ importers: version: 0.515.0(svelte@5.34.9) '@sveltejs/adapter-static': specifier: ^3.0.8 - version: 3.0.8(@sveltejs/kit@2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0))) + version: 3.0.8(@sveltejs/kit@2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0))) '@sveltejs/kit': specifier: ^2.22.2 - version: 2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) + version: 2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) '@sveltejs/vite-plugin-svelte': specifier: ^5.1.0 - version: 5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) + version: 5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) '@tailwindcss/vite': specifier: ^4.1.11 - version: 4.1.11(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) + version: 4.1.11(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) '@types/eslint': specifier: ^9.6.1 version: 9.6.1 '@types/node': - specifier: ^22.15.34 - version: 22.15.34 + specifier: ^22.16.0 + version: 22.16.0 bits-ui: specifier: 2.8.10 version: 2.8.10(@internationalized/date@3.8.2)(svelte@5.34.9) @@ -58,20 +58,20 @@ importers: specifier: ^2.1.1 version: 2.1.1 eslint: - specifier: ^9.30.0 - version: 9.30.0(jiti@2.4.2) + specifier: ^9.30.1 + version: 9.30.1(jiti@2.4.2) eslint-config-prettier: specifier: ^10.1.5 - version: 10.1.5(eslint@9.30.0(jiti@2.4.2)) + version: 10.1.5(eslint@9.30.1(jiti@2.4.2)) eslint-plugin-svelte: specifier: ^3.10.1 - version: 3.10.1(eslint@9.30.0(jiti@2.4.2))(svelte@5.34.9) + version: 3.10.1(eslint@9.30.1(jiti@2.4.2))(svelte@5.34.9) formsnap: specifier: ^2.0.1 - version: 2.0.1(svelte@5.34.9)(sveltekit-superforms@2.27.1(@sveltejs/kit@2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(@types/json-schema@7.0.15)(esbuild@0.25.5)(svelte@5.34.9)(typescript@5.8.3)) + version: 2.0.1(svelte@5.34.9)(sveltekit-superforms@2.27.1(@sveltejs/kit@2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(@types/json-schema@7.0.15)(esbuild@0.25.5)(svelte@5.34.9)(typescript@5.8.3)) globals: - specifier: ^16.2.0 - version: 16.2.0 + specifier: ^16.3.0 + version: 16.3.0 mode-watcher: specifier: ^1.1.0 version: 1.1.0(svelte@5.34.9) @@ -101,7 +101,7 @@ importers: version: 1.0.5(svelte@5.34.9) sveltekit-superforms: specifier: ^2.27.1 - version: 2.27.1(@sveltejs/kit@2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(@types/json-schema@7.0.15)(esbuild@0.25.5)(svelte@5.34.9)(typescript@5.8.3) + version: 2.27.1(@sveltejs/kit@2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(@types/json-schema@7.0.15)(esbuild@0.25.5)(svelte@5.34.9)(typescript@5.8.3) tailwind-merge: specifier: ^3.3.1 version: 3.3.1 @@ -119,10 +119,10 @@ importers: version: 5.8.3 typescript-eslint: specifier: ^8.35.1 - version: 8.35.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3) + version: 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3) vite: specifier: ^6.3.5 - version: 6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) + version: 6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) yaml: specifier: ^2.8.0 version: 2.8.0 @@ -340,8 +340,8 @@ packages: resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.30.0': - resolution: {integrity: sha512-Wzw3wQwPvc9sHM+NjakWTcPx11mbZyiYHuwWa/QfZ7cIRX7WK54PSk7bdyXDaoaopUcMatv1zaQvOAAO8hCdww==} + '@eslint/js@9.30.1': + resolution: {integrity: sha512-zXhuECFlyep42KZUhWjfvsmXGX39W8K8LFb8AWXM9gSV9dQB+MrJGLKvW6Zw0Ggnbpw0VHTtrhFXYe3Gym18jg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.6': @@ -401,18 +401,18 @@ packages: resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} engines: {node: '>=18.0.0'} - '@jridgewell/gen-mapping@0.3.11': - resolution: {integrity: sha512-C512c1ytBTio4MrpWKlJpyFHT6+qfFL8SZ58zBzJ1OOzUEjHeF1BtjY2fH7n4x/g2OV/KiiMLAivOp1DXmiMMw==} + '@jridgewell/gen-mapping@0.3.12': + resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==} '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/sourcemap-codec@1.5.3': - resolution: {integrity: sha512-AiR5uKpFxP3PjO4R19kQGIMwxyRyPuXmKEEy301V1C0+1rVjS94EZQXf1QKZYN8Q0YM+estSPhmx5JwNftv6nw==} + '@jridgewell/sourcemap-codec@1.5.4': + resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==} - '@jridgewell/trace-mapping@0.3.28': - resolution: {integrity: sha512-KNNHHwW3EIp4EDYOvYFGyIFfx36R2dNJYH4knnZlF8T5jdbD5Wx8xmSaQ2gP9URkJ04LGEtlcCtwArKcmFcwKw==} + '@jridgewell/trace-mapping@0.3.29': + resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==} '@lucide/svelte@0.515.0': resolution: {integrity: sha512-CEAyqcZmNBfYzVgaRmK2RFJP5tnbXxekRyDk0XX/eZQRfsJmkDvmQwXNX8C869BgNeryzmrRyjHhUL6g9ZOHNA==} @@ -727,8 +727,8 @@ packages: '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} - '@types/node@22.15.34': - resolution: {integrity: sha512-8Y6E5WUupYy1Dd0II32BsWAx5MWdcnRd8L84Oys3veg1YrYtNtzgO4CFhiBg6MDSjk7Ay36HYOnU7/tuOzIzcw==} + '@types/node@22.16.0': + resolution: {integrity: sha512-B2egV9wALML1JCpv3VQoQ+yesQKAmNMBIAY7OteVrikcOcAkWm+dGL6qpeCktPjAv6N1JLnhbNiqS35UpFyBsQ==} '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} @@ -1024,8 +1024,8 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.30.0: - resolution: {integrity: sha512-iN/SiPxmQu6EVkf+m1qpBxzUhE12YqFLOSySuOyVLJLEF9nzTf+h/1AJYc1JWzCnktggeNrjvQGLngDzXirU6g==} + eslint@9.30.1: + resolution: {integrity: sha512-zmxXPNMOXmwm9E0yQLi5uqXHs7uq2UIiqEKo3Gq+3fwo1XrJ+hijAZImyF7hclW3E6oHz43Yk3RP8at6OTKflQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -1131,8 +1131,8 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} - globals@16.2.0: - resolution: {integrity: sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==} + globals@16.3.0: + resolution: {integrity: sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==} engines: {node: '>=18'} graceful-fs@4.2.11: @@ -1951,8 +1951,8 @@ snapshots: '@ampproject/remapping@2.3.0': dependencies: - '@jridgewell/gen-mapping': 0.3.11 - '@jridgewell/trace-mapping': 0.3.28 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.29 '@ark/schema@0.46.0': dependencies: @@ -2051,9 +2051,9 @@ snapshots: '@esbuild/win32-x64@0.25.5': optional: true - '@eslint-community/eslint-utils@4.7.0(eslint@9.30.0(jiti@2.4.2))': + '@eslint-community/eslint-utils@4.7.0(eslint@9.30.1(jiti@2.4.2))': dependencies: - eslint: 9.30.0(jiti@2.4.2) + eslint: 9.30.1(jiti@2.4.2) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -2090,7 +2090,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.30.0': {} + '@eslint/js@9.30.1': {} '@eslint/object-schema@2.1.6': {} @@ -2153,19 +2153,19 @@ snapshots: dependencies: minipass: 7.1.2 - '@jridgewell/gen-mapping@0.3.11': + '@jridgewell/gen-mapping@0.3.12': dependencies: - '@jridgewell/sourcemap-codec': 1.5.3 - '@jridgewell/trace-mapping': 0.3.28 + '@jridgewell/sourcemap-codec': 1.5.4 + '@jridgewell/trace-mapping': 0.3.29 '@jridgewell/resolve-uri@3.1.2': {} - '@jridgewell/sourcemap-codec@1.5.3': {} + '@jridgewell/sourcemap-codec@1.5.4': {} - '@jridgewell/trace-mapping@0.3.28': + '@jridgewell/trace-mapping@0.3.29': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.3 + '@jridgewell/sourcemap-codec': 1.5.4 '@lucide/svelte@0.515.0(svelte@5.34.9)': dependencies: @@ -2302,14 +2302,14 @@ snapshots: dependencies: acorn: 8.15.0 - '@sveltejs/adapter-static@3.0.8(@sveltejs/kit@2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))': + '@sveltejs/adapter-static@3.0.8(@sveltejs/kit@2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))': dependencies: - '@sveltejs/kit': 2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) + '@sveltejs/kit': 2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) - '@sveltejs/kit@2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0))': + '@sveltejs/kit@2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0))': dependencies: '@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0) - '@sveltejs/vite-plugin-svelte': 5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) + '@sveltejs/vite-plugin-svelte': 5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) '@types/cookie': 0.6.0 acorn: 8.15.0 cookie: 0.6.0 @@ -2322,28 +2322,28 @@ snapshots: set-cookie-parser: 2.7.1 sirv: 3.0.1 svelte: 5.34.9 - vite: 6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) - vitefu: 1.0.7(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) + vite: 6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) + vitefu: 1.0.7(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) - '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0))': + '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0))': dependencies: - '@sveltejs/vite-plugin-svelte': 5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) + '@sveltejs/vite-plugin-svelte': 5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) debug: 4.4.1 svelte: 5.34.9 - vite: 6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) + vite: 6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0))': + '@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) + '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) debug: 4.4.1 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.17 svelte: 5.34.9 - vite: 6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) - vitefu: 1.0.7(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) + vite: 6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) + vitefu: 1.0.7(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) transitivePeerDependencies: - supports-color @@ -2415,12 +2415,12 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.11 '@tailwindcss/oxide-win32-x64-msvc': 4.1.11 - '@tailwindcss/vite@4.1.11(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0))': + '@tailwindcss/vite@4.1.11(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0))': dependencies: '@tailwindcss/node': 4.1.11 '@tailwindcss/oxide': 4.1.11 tailwindcss: 4.1.11 - vite: 6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) + vite: 6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) '@tanstack/match-sorter-utils@8.19.4': dependencies: @@ -2447,7 +2447,7 @@ snapshots: dependencies: '@types/unist': 3.0.3 - '@types/node@22.15.34': + '@types/node@22.16.0': dependencies: undici-types: 6.21.0 @@ -2470,15 +2470,15 @@ snapshots: '@types/json-schema': 7.0.15 optional: true - '@typescript-eslint/eslint-plugin@8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)': + '@typescript-eslint/eslint-plugin@8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.35.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/parser': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3) '@typescript-eslint/scope-manager': 8.35.1 - '@typescript-eslint/type-utils': 8.35.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3) - '@typescript-eslint/utils': 8.35.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/type-utils': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/utils': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3) '@typescript-eslint/visitor-keys': 8.35.1 - eslint: 9.30.0(jiti@2.4.2) + eslint: 9.30.1(jiti@2.4.2) graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 @@ -2487,14 +2487,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.35.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)': + '@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)': dependencies: '@typescript-eslint/scope-manager': 8.35.1 '@typescript-eslint/types': 8.35.1 '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.8.3) '@typescript-eslint/visitor-keys': 8.35.1 debug: 4.4.1 - eslint: 9.30.0(jiti@2.4.2) + eslint: 9.30.1(jiti@2.4.2) typescript: 5.8.3 transitivePeerDependencies: - supports-color @@ -2517,12 +2517,12 @@ snapshots: dependencies: typescript: 5.8.3 - '@typescript-eslint/type-utils@8.35.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)': + '@typescript-eslint/type-utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)': dependencies: '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.8.3) - '@typescript-eslint/utils': 8.35.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/utils': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3) debug: 4.4.1 - eslint: 9.30.0(jiti@2.4.2) + eslint: 9.30.1(jiti@2.4.2) ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: @@ -2546,13 +2546,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.35.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3)': + '@typescript-eslint/utils@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3)': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.0(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1(jiti@2.4.2)) '@typescript-eslint/scope-manager': 8.35.1 '@typescript-eslint/types': 8.35.1 '@typescript-eslint/typescript-estree': 8.35.1(typescript@5.8.3) - eslint: 9.30.0(jiti@2.4.2) + eslint: 9.30.1(jiti@2.4.2) typescript: 5.8.3 transitivePeerDependencies: - supports-color @@ -2760,17 +2760,17 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.5(eslint@9.30.0(jiti@2.4.2)): + eslint-config-prettier@10.1.5(eslint@9.30.1(jiti@2.4.2)): dependencies: - eslint: 9.30.0(jiti@2.4.2) + eslint: 9.30.1(jiti@2.4.2) - eslint-plugin-svelte@3.10.1(eslint@9.30.0(jiti@2.4.2))(svelte@5.34.9): + eslint-plugin-svelte@3.10.1(eslint@9.30.1(jiti@2.4.2))(svelte@5.34.9): dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.0(jiti@2.4.2)) - '@jridgewell/sourcemap-codec': 1.5.3 - eslint: 9.30.0(jiti@2.4.2) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1(jiti@2.4.2)) + '@jridgewell/sourcemap-codec': 1.5.4 + eslint: 9.30.1(jiti@2.4.2) esutils: 2.0.3 - globals: 16.2.0 + globals: 16.3.0 known-css-properties: 0.37.0 postcss: 8.5.6 postcss-load-config: 3.1.4(postcss@8.5.6) @@ -2791,15 +2791,15 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.30.0(jiti@2.4.2): + eslint@9.30.1(jiti@2.4.2): dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.0(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.1(jiti@2.4.2)) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.21.0 '@eslint/config-helpers': 0.3.0 '@eslint/core': 0.14.0 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.30.0 + '@eslint/js': 9.30.1 '@eslint/plugin-kit': 0.3.3 '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 @@ -2847,7 +2847,7 @@ snapshots: esrap@1.4.9: dependencies: - '@jridgewell/sourcemap-codec': 1.5.3 + '@jridgewell/sourcemap-codec': 1.5.4 esrecurse@4.3.0: dependencies: @@ -2904,11 +2904,11 @@ snapshots: flatted@3.3.3: {} - formsnap@2.0.1(svelte@5.34.9)(sveltekit-superforms@2.27.1(@sveltejs/kit@2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(@types/json-schema@7.0.15)(esbuild@0.25.5)(svelte@5.34.9)(typescript@5.8.3)): + formsnap@2.0.1(svelte@5.34.9)(sveltekit-superforms@2.27.1(@sveltejs/kit@2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(@types/json-schema@7.0.15)(esbuild@0.25.5)(svelte@5.34.9)(typescript@5.8.3)): dependencies: svelte: 5.34.9 svelte-toolbelt: 0.5.0(svelte@5.34.9) - sveltekit-superforms: 2.27.1(@sveltejs/kit@2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(@types/json-schema@7.0.15)(esbuild@0.25.5)(svelte@5.34.9)(typescript@5.8.3) + sveltekit-superforms: 2.27.1(@sveltejs/kit@2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(@types/json-schema@7.0.15)(esbuild@0.25.5)(svelte@5.34.9)(typescript@5.8.3) fsevents@2.3.3: optional: true @@ -2923,7 +2923,7 @@ snapshots: globals@14.0.0: {} - globals@16.2.0: {} + globals@16.3.0: {} graceful-fs@4.2.11: {} @@ -3080,7 +3080,7 @@ snapshots: magic-string@0.30.17: dependencies: - '@jridgewell/sourcemap-codec': 1.5.3 + '@jridgewell/sourcemap-codec': 1.5.4 mdast-util-to-hast@13.2.0: dependencies: @@ -3379,7 +3379,7 @@ snapshots: svelte-check@4.2.2(picomatch@4.0.2)(svelte@5.34.9)(typescript@5.8.3): dependencies: - '@jridgewell/trace-mapping': 0.3.28 + '@jridgewell/trace-mapping': 0.3.29 chokidar: 4.0.3 fdir: 6.4.6(picomatch@4.0.2) picocolors: 1.1.1 @@ -3432,7 +3432,7 @@ snapshots: svelte@5.34.9: dependencies: '@ampproject/remapping': 2.3.0 - '@jridgewell/sourcemap-codec': 1.5.3 + '@jridgewell/sourcemap-codec': 1.5.4 '@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0) '@types/estree': 1.0.8 acorn: 8.15.0 @@ -3446,9 +3446,9 @@ snapshots: magic-string: 0.30.17 zimmerframe: 1.1.2 - sveltekit-superforms@2.27.1(@sveltejs/kit@2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(@types/json-schema@7.0.15)(esbuild@0.25.5)(svelte@5.34.9)(typescript@5.8.3): + sveltekit-superforms@2.27.1(@sveltejs/kit@2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(@types/json-schema@7.0.15)(esbuild@0.25.5)(svelte@5.34.9)(typescript@5.8.3): dependencies: - '@sveltejs/kit': 2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) + '@sveltejs/kit': 2.22.2(@sveltejs/vite-plugin-svelte@5.1.0(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)))(svelte@5.34.9)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) devalue: 5.1.1 memoize-weak: 1.0.2 svelte: 5.34.9 @@ -3540,12 +3540,12 @@ snapshots: type-fest@2.19.0: optional: true - typescript-eslint@8.35.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3): + typescript-eslint@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3) - '@typescript-eslint/parser': 8.35.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3) - '@typescript-eslint/utils': 8.35.1(eslint@9.30.0(jiti@2.4.2))(typescript@5.8.3) - eslint: 9.30.0(jiti@2.4.2) + '@typescript-eslint/eslint-plugin': 8.35.1(@typescript-eslint/parser@8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/parser': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/utils': 8.35.1(eslint@9.30.1(jiti@2.4.2))(typescript@5.8.3) + eslint: 9.30.1(jiti@2.4.2) typescript: 5.8.3 transitivePeerDependencies: - supports-color @@ -3606,7 +3606,7 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0): + vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0): dependencies: esbuild: 0.25.5 fdir: 6.4.6(picomatch@4.0.2) @@ -3615,15 +3615,15 @@ snapshots: rollup: 4.44.1 tinyglobby: 0.2.14 optionalDependencies: - '@types/node': 22.15.34 + '@types/node': 22.16.0 fsevents: 2.3.3 jiti: 2.4.2 lightningcss: 1.30.1 yaml: 2.8.0 - vitefu@1.0.7(vite@6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)): + vitefu@1.0.7(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)): optionalDependencies: - vite: 6.3.5(@types/node@22.15.34)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) + vite: 6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) which@2.0.2: dependencies: diff --git a/web/src/lib/api.ts b/web/src/lib/api.ts index 38a5442..544acc3 100644 --- a/web/src/lib/api.ts +++ b/web/src/lib/api.ts @@ -1,85 +1,95 @@ -import type { DescService } from '@bufbuild/protobuf'; -import { createClient, type Client } from '@connectrpc/connect'; -import { createConnectTransport } from '@connectrpc/connect-web'; -import { ProfileService } from './gen/mantrae/v1/profile_pb'; -import { UserService } from './gen/mantrae/v1/user_pb'; -import { RouterService } from './gen/mantrae/v1/router_pb'; -import { ServiceService } from './gen/mantrae/v1/service_pb'; -import { MiddlewareService } from './gen/mantrae/v1/middleware_pb'; -import { SettingService } from './gen/mantrae/v1/setting_pb'; -import { BackupService } from './gen/mantrae/v1/backup_pb'; -import { EntryPointService } from './gen/mantrae/v1/entry_point_pb'; -import { DnsProviderService } from './gen/mantrae/v1/dns_provider_pb'; -import { UtilService } from './gen/mantrae/v1/util_pb'; -import { AgentService } from './gen/mantrae/v1/agent_pb'; -import { toast } from 'svelte-sonner'; -import { AuditLogService } from './gen/mantrae/v1/auditlog_pb'; -import { profile } from './stores/profile'; - -// Global state variables -export const BACKEND_PORT = import.meta.env.PORT || 3000; -export const BASE_URL = import.meta.env.PROD ? '/' : `http://127.0.0.1:${BACKEND_PORT}`; +import type { DescService } from "@bufbuild/protobuf"; +import { createClient, type Client } from "@connectrpc/connect"; +import { createConnectTransport } from "@connectrpc/connect-web"; +import { ProfileService } from "./gen/mantrae/v1/profile_pb"; +import { UserService } from "./gen/mantrae/v1/user_pb"; +import { RouterService } from "./gen/mantrae/v1/router_pb"; +import { ServiceService } from "./gen/mantrae/v1/service_pb"; +import { MiddlewareService } from "./gen/mantrae/v1/middleware_pb"; +import { SettingService } from "./gen/mantrae/v1/setting_pb"; +import { BackupService } from "./gen/mantrae/v1/backup_pb"; +import { EntryPointService } from "./gen/mantrae/v1/entry_point_pb"; +import { DnsProviderService } from "./gen/mantrae/v1/dns_provider_pb"; +import { UtilService } from "./gen/mantrae/v1/util_pb"; +import { AgentService } from "./gen/mantrae/v1/agent_pb"; +import { toast } from "svelte-sonner"; +import { AuditLogService } from "./gen/mantrae/v1/auditlog_pb"; +import { profile } from "./stores/profile"; +import { baseURL } from "./stores/common"; export function useClient( service: T, - customFetch?: typeof fetch + customFetch?: typeof fetch, ): Client { const wrappedFetch: typeof fetch = (input, init = {}) => { return (customFetch || fetch)(input, { ...init, headers: new Headers(init.headers || {}), - credentials: 'include' + credentials: "include", }); }; + if (!baseURL.value) throw new Error("Base URL not set"); + const transport = createConnectTransport({ - baseUrl: BASE_URL, - fetch: wrappedFetch + baseUrl: baseURL.value, + fetch: wrappedFetch, }); return createClient(service, transport); } +// Basic health check function +export async function checkHealth() { + try { + const res = await fetch(`${baseURL.value}/healthz`, { method: "GET" }); + return res.ok; + } catch { + return false; + } +} + export function handleOIDCLogin() { - window.location.href = `${BASE_URL}/oidc/login`; + window.location.href = `${baseURL.value}/oidc/login`; } export async function upload(input: HTMLInputElement | null, endpoint: string) { if (!input?.files?.length) return; const body = new FormData(); - body.append('file', input.files[0]); + body.append("file", input.files[0]); - const response = await fetch(`${BASE_URL}/upload/${endpoint}`, { - method: 'POST', + const response = await fetch(`${baseURL.value}/upload/${endpoint}`, { + method: "POST", body, - credentials: 'include' + credentials: "include", }); if (!response.ok) { - throw new Error('Failed to upload'); + throw new Error("Failed to upload"); } - toast.success('Uploaded successfully'); + toast.success("Uploaded successfully"); } +// Get dynamic traefik config export async function getConfig(format: string) { - if (!profile.isValid()) return ''; + if (!profile.isValid()) return ""; const headers = new Headers(); - if (format === 'yaml') { - headers.set('Accept', 'application/x-yaml'); + if (format === "yaml") { + headers.set("Accept", "application/x-yaml"); } try { - const response = await fetch(`${BASE_URL}/api/${profile.name}`, { - headers + const response = await fetch(`${baseURL.value}/api/${profile.name}`, { + headers, }); - if (!response.ok) return ''; + if (!response.ok) return ""; return await response.text(); } catch (err) { const e = err as Error; - toast.error('Failed to fetch config', { description: e.message }); + toast.error("Failed to fetch config", { description: e.message }); } - return ''; + return ""; } // Clients diff --git a/web/src/lib/stores/common.ts b/web/src/lib/stores/common.ts index 001b8e3..7d1574e 100644 --- a/web/src/lib/stores/common.ts +++ b/web/src/lib/stores/common.ts @@ -1,16 +1,20 @@ -import { createLocalStorage } from '$lib/storage.svelte'; +import { createLocalStorage } from "$lib/storage.svelte"; +import { PUBLIC_BACKEND_URL } from "$env/static/public"; -export const pageIndex = createLocalStorage('page_index', 0); -export const pageSize = createLocalStorage('page_size', 10); -export const routerColumns = createLocalStorage('router_columns', []); -export const middlewareColumns = createLocalStorage('middleware_columns', []); -export const ruleTab = createLocalStorage('rule_tab', 'simple'); +export const DEFAULT_URL = import.meta.env.PROD ? "/" : `http://127.0.0.1:3000`; -export const DateFormat = new Intl.DateTimeFormat('en-US', { - year: 'numeric', - month: 'long', - day: 'numeric', - hour: 'numeric', - minute: 'numeric', - second: 'numeric' +export const baseURL = createLocalStorage("base_url", DEFAULT_URL); +export const pageIndex = createLocalStorage("page_index", 0); +export const pageSize = createLocalStorage("page_size", 10); +export const routerColumns = createLocalStorage("router_columns", []); +export const middlewareColumns = createLocalStorage("middleware_columns", []); +export const ruleTab = createLocalStorage("rule_tab", "simple"); + +export const DateFormat = new Intl.DateTimeFormat("en-US", { + year: "numeric", + month: "long", + day: "numeric", + hour: "numeric", + minute: "numeric", + second: "numeric", }); diff --git a/web/src/lib/stores/realtime.ts b/web/src/lib/stores/realtime.ts index eb38c21..d7806e8 100644 --- a/web/src/lib/stores/realtime.ts +++ b/web/src/lib/stores/realtime.ts @@ -1,18 +1,18 @@ -import { writable } from 'svelte/store'; +import { writable } from "svelte/store"; import { ResourceType, EventType, type ProfileEvent, type ProfileEventsResponse, - EventService -} from '$lib/gen/mantrae/v1/event_pb'; -import { profile } from './profile'; -import { ConnectError, createClient } from '@connectrpc/connect'; -import type { Router } from '$lib/gen/mantrae/v1/router_pb'; -import type { Service } from '$lib/gen/mantrae/v1/service_pb'; -import type { Middleware } from '$lib/gen/mantrae/v1/middleware_pb'; -import { createConnectTransport } from '@connectrpc/connect-web'; -import { BASE_URL } from '$lib/api'; + EventService, +} from "$lib/gen/mantrae/v1/event_pb"; +import { profile } from "./profile"; +import { ConnectError, createClient } from "@connectrpc/connect"; +import type { Router } from "$lib/gen/mantrae/v1/router_pb"; +import type { Service } from "$lib/gen/mantrae/v1/service_pb"; +import type { Middleware } from "$lib/gen/mantrae/v1/middleware_pb"; +import { createConnectTransport } from "@connectrpc/connect-web"; +import { baseURL } from "./common"; type ResourceUnion = Router | Service | Middleware; @@ -31,28 +31,28 @@ interface FetchResult { const eventClient = createClient( EventService, createConnectTransport({ - baseUrl: BASE_URL, + baseUrl: baseURL, useBinaryFormat: true, interceptors: [ (next) => async (req) => { // Debug the request - console.log('Request headers:', req.header); - console.log('Request method:', req.method); + console.log("Request headers:", req.header); + console.log("Request method:", req.method); return await next(req); - } - ] - }) + }, + ], + }), ); export function createRealtimeStore( resourceType: ResourceType, - fetchFn: (pageSize: number, pageIndex: number) => Promise> + fetchFn: (pageSize: number, pageIndex: number) => Promise>, ) { const { subscribe, set, update } = writable>({ data: [], rowCount: 0, loading: false, - error: null + error: null, }); let eventStream: AsyncIterable | null = null; @@ -63,11 +63,17 @@ export function createRealtimeStore( switch (resourceType) { case ResourceType.ROUTER: - return event.resource.case === 'router' ? (event.resource.value as T) : null; + return event.resource.case === "router" + ? (event.resource.value as T) + : null; case ResourceType.SERVICE: - return event.resource.case === 'service' ? (event.resource.value as T) : null; + return event.resource.case === "service" + ? (event.resource.value as T) + : null; case ResourceType.MIDDLEWARE: - return event.resource.case === 'middleware' ? (event.resource.value as T) : null; + return event.resource.case === "middleware" + ? (event.resource.value as T) + : null; default: return null; } @@ -80,11 +86,11 @@ export function createRealtimeStore( switch (resourceType) { case ResourceType.ROUTER: - return event.resource.case === 'router'; + return event.resource.case === "router"; case ResourceType.SERVICE: - return event.resource.case === 'service'; + return event.resource.case === "service"; case ResourceType.MIDDLEWARE: - return event.resource.case === 'middleware'; + return event.resource.case === "middleware"; default: return false; } @@ -97,7 +103,7 @@ export function createRealtimeStore( try { eventStream = eventClient.profileEvents({ profileId: profile.id, - resourceTypes: [resourceType] + resourceTypes: [resourceType], }); if (!eventStream) return; @@ -120,14 +126,16 @@ export function createRealtimeStore( return { ...state, data: newData, - rowCount: state.rowCount + 1 + rowCount: state.rowCount + 1, }; } return state; } case EventType.UPDATED: { - const updateIndex = newData.findIndex((item) => item.id === resource.id); + const updateIndex = newData.findIndex( + (item) => item.id === resource.id, + ); if (updateIndex !== -1) { newData[updateIndex] = resource; return { ...state, data: newData }; @@ -136,12 +144,14 @@ export function createRealtimeStore( } case EventType.DELETED: { - const filteredData = newData.filter((item) => item.id !== resource.id); + const filteredData = newData.filter( + (item) => item.id !== resource.id, + ); const rowCountDelta = newData.length - filteredData.length; return { ...state, data: filteredData, - rowCount: Math.max(0, state.rowCount - rowCountDelta) + rowCount: Math.max(0, state.rowCount - rowCountDelta), }; } @@ -152,7 +162,7 @@ export function createRealtimeStore( } } catch (error) { const e = ConnectError.from(error); - console.error('Event stream error:', e.message); + console.error("Event stream error:", e.message); update((state) => ({ ...state, error: e.message })); } finally { isStreaming = false; @@ -168,14 +178,14 @@ export function createRealtimeStore( data: result.data, rowCount: result.rowCount, loading: false, - error: null + error: null, }); } catch (error) { const e = ConnectError.from(error); update((state) => ({ ...state, loading: false, - error: e.message + error: e.message, })); } } @@ -194,27 +204,38 @@ export function createRealtimeStore( optimisticUpdate: (id: bigint, updates: Partial) => { update((state) => ({ ...state, - data: state.data.map((item) => (item.id === id ? { ...item, ...updates } : item)) + data: state.data.map((item) => + item.id === id ? { ...item, ...updates } : item, + ), })); - } + }, }; } // Type-safe factory functions for each resource type export function createRouterStore( - fetchFn: (pageSize: number, pageIndex: number) => Promise> + fetchFn: ( + pageSize: number, + pageIndex: number, + ) => Promise>, ) { return createRealtimeStore(ResourceType.ROUTER, fetchFn); } export function createServiceStore( - fetchFn: (pageSize: number, pageIndex: number) => Promise> + fetchFn: ( + pageSize: number, + pageIndex: number, + ) => Promise>, ) { return createRealtimeStore(ResourceType.SERVICE, fetchFn); } export function createMiddlewareStore( - fetchFn: (pageSize: number, pageIndex: number) => Promise> + fetchFn: ( + pageSize: number, + pageIndex: number, + ) => Promise>, ) { return createRealtimeStore(ResourceType.MIDDLEWARE, fetchFn); } diff --git a/web/src/routes/+layout.ts b/web/src/routes/+layout.ts index 47f718c..225de1b 100644 --- a/web/src/routes/+layout.ts +++ b/web/src/routes/+layout.ts @@ -1,6 +1,6 @@ import type { LayoutLoad } from "./$types"; import { goto } from "$app/navigation"; -import { useClient } from "$lib/api"; +import { checkHealth, useClient } from "$lib/api"; import { profile } from "$lib/stores/profile"; import { user } from "$lib/stores/user"; import { UserService } from "$lib/gen/mantrae/v1/user_pb"; @@ -12,23 +12,41 @@ export const trailingSlash = "always"; export const load: LayoutLoad = async ({ url, fetch }) => { const currentPath = url.pathname; - const isPublic = currentPath.startsWith("/login"); + const isPublic = + currentPath.startsWith("/login") || currentPath.startsWith("/welcome"); - try { - const userClient = useClient(UserService, fetch); - const resUser = await userClient.getUser({}); - if (!resUser.user) throw new Error("Authentication failed"); - user.value = resUser.user; - - if (!profile.id) { - const profileClient = useClient(ProfileService, fetch); - const resProfile = await profileClient.listProfiles({}); - profile.value = resProfile.profiles[0]; + const healthy = await checkHealth(); + if (!healthy) { + // No backend, force redirect to welcome screen to enter backend URL + if (currentPath !== "/welcome") { + await goto("/welcome"); + user.clear(); + return {}; // stop loading other data + } + } else { + // Backend reachable + if (currentPath === "/welcome") { + // Backend is back, redirect from welcome to login + await goto("/login"); + return {}; } - if (isPublic) await goto("/"); - } catch (_) { - user.clear(); - if (!isPublic) await goto("/login"); + try { + const userClient = useClient(UserService, fetch); + const resUser = await userClient.getUser({}); + if (!resUser.user) throw new Error("Authentication failed"); + user.value = resUser.user; + + if (!profile.id) { + const profileClient = useClient(ProfileService, fetch); + const resProfile = await profileClient.listProfiles({}); + profile.value = resProfile.profiles[0]; + } + + if (isPublic) await goto("/"); + } catch (_) { + user.clear(); + if (!isPublic) await goto("/login"); + } } }; diff --git a/web/src/routes/welcome/+page.svelte b/web/src/routes/welcome/+page.svelte new file mode 100644 index 0000000..dfa30a5 --- /dev/null +++ b/web/src/routes/welcome/+page.svelte @@ -0,0 +1,112 @@ + + + + +
+ Server Configuration +
+ + + {#if isChecking} + Checking connection... + {:else if isHealthy} + Connected + {:else} + Disconnected + {/if} + + + + Enter the URL where your backend server is running. + +
+ + +
+ + +
+ + +
+