View update

This commit is contained in:
Dominic Ferrando
2025-09-18 00:01:27 -04:00
parent bd0b7ea828
commit e9f9821222
40 changed files with 1646 additions and 242 deletions
+263 -5
View File
@@ -2,18 +2,276 @@
"lockfileVersion": 1, "lockfileVersion": 1,
"workspaces": { "workspaces": {
"": { "": {
"dependencies": {
"@elysiajs/cors": "^1.4.0",
"@elysiajs/eden": "^1.4.1",
"elysia": "^1.4.5",
},
"devDependencies": { "devDependencies": {
"@types/bun": "^1.2.11", "@sveltejs/kit": "^2.22.0",
"@sveltejs/vite-plugin-svelte": "^6.0.0",
"@types/bun": "^1.2.22",
"svelte": "^5.0.0",
"svelte-adapter-bun": "^0.5.2",
"svelte-check": "^4.0.0",
"typescript": "^5.0.0",
"vite": "^7.0.4",
}, },
}, },
}, },
"packages": { "packages": {
"@types/bun": ["@types/bun@1.2.11", "", { "dependencies": { "bun-types": "1.2.11" } }, "sha512-ZLbbI91EmmGwlWTRWuV6J19IUiUC5YQ3TCEuSHI3usIP75kuoA8/0PVF+LTrbEnVc8JIhpElWOxv1ocI1fJBbw=="], "@borewit/text-codec": ["@borewit/text-codec@0.1.1", "", {}, "sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA=="],
"@types/node": ["@types/node@22.15.3", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw=="], "@elysiajs/cors": ["@elysiajs/cors@1.4.0", "", { "peerDependencies": { "elysia": ">= 1.4.0" } }, "sha512-pb0SCzBfFbFSYA/U40HHO7R+YrcXBJXOWgL20eSViK33ol1e20ru2/KUaZYo5IMUn63yaTJI/bQERuQ+77ND8g=="],
"bun-types": ["bun-types@1.2.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-dbkp5Lo8HDrXkLrONm6bk+yiiYQSntvFUzQp0v3pzTAsXk6FtgVMjdQ+lzFNVAmQFUkPQZ3WMZqH5tTo+Dp/IA=="], "@elysiajs/eden": ["@elysiajs/eden@1.4.1", "", { "peerDependencies": { "elysia": ">= 1.4.0-exp.0" } }, "sha512-9VXMau/cvafuBa1r19ucKi+l9eesCmeuvD6uYSeq5MFO/URc233JaxZmUlWQ8gztu+pp6L7auTZdkzOQz26O+A=="],
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.10", "", { "os": "aix", "cpu": "ppc64" }, "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw=="],
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.10", "", { "os": "android", "cpu": "arm" }, "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w=="],
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.10", "", { "os": "android", "cpu": "arm64" }, "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg=="],
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.10", "", { "os": "android", "cpu": "x64" }, "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg=="],
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA=="],
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg=="],
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.10", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg=="],
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.10", "", { "os": "freebsd", "cpu": "x64" }, "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA=="],
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.10", "", { "os": "linux", "cpu": "arm" }, "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg=="],
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ=="],
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.10", "", { "os": "linux", "cpu": "ia32" }, "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ=="],
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg=="],
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA=="],
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.10", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA=="],
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA=="],
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.10", "", { "os": "linux", "cpu": "s390x" }, "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew=="],
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.10", "", { "os": "linux", "cpu": "x64" }, "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA=="],
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.10", "", { "os": "none", "cpu": "arm64" }, "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A=="],
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.10", "", { "os": "none", "cpu": "x64" }, "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig=="],
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.10", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw=="],
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.10", "", { "os": "openbsd", "cpu": "x64" }, "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw=="],
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.10", "", { "os": "none", "cpu": "arm64" }, "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag=="],
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.10", "", { "os": "sunos", "cpu": "x64" }, "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ=="],
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw=="],
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.10", "", { "os": "win32", "cpu": "ia32" }, "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw=="],
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.10", "", { "os": "win32", "cpu": "x64" }, "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw=="],
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.50.2", "", { "os": "android", "cpu": "arm" }, "sha512-uLN8NAiFVIRKX9ZQha8wy6UUs06UNSZ32xj6giK/rmMXAgKahwExvK6SsmgU5/brh4w/nSgj8e0k3c1HBQpa0A=="],
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.50.2", "", { "os": "android", "cpu": "arm64" }, "sha512-oEouqQk2/zxxj22PNcGSskya+3kV0ZKH+nQxuCCOGJ4oTXBdNTbv+f/E3c74cNLeMO1S5wVWacSws10TTSB77g=="],
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.50.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-OZuTVTpj3CDSIxmPgGH8en/XtirV5nfljHZ3wrNwvgkT5DQLhIKAeuFSiwtbMto6oVexV0k1F1zqURPKf5rI1Q=="],
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.50.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-Wa/Wn8RFkIkr1vy1k1PB//VYhLnlnn5eaJkfTQKivirOvzu5uVd2It01ukeQstMursuz7S1bU+8WW+1UPXpa8A=="],
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.50.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-QkzxvH3kYN9J1w7D1A+yIMdI1pPekD+pWx7G5rXgnIlQ1TVYVC6hLl7SOV9pi5q9uIDF9AuIGkuzcbF7+fAhow=="],
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.50.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dkYXB0c2XAS3a3jmyDkX4Jk0m7gWLFzq1C3qUnJJ38AyxIF5G/dyS4N9B30nvFseCfgtCEdbYFhk0ChoCGxPog=="],
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.50.2", "", { "os": "linux", "cpu": "arm" }, "sha512-9VlPY/BN3AgbukfVHAB8zNFWB/lKEuvzRo1NKev0Po8sYFKx0i+AQlCYftgEjcL43F2h9Ui1ZSdVBc4En/sP2w=="],
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.50.2", "", { "os": "linux", "cpu": "arm" }, "sha512-+GdKWOvsifaYNlIVf07QYan1J5F141+vGm5/Y8b9uCZnG/nxoGqgCmR24mv0koIWWuqvFYnbURRqw1lv7IBINw=="],
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.50.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-df0Eou14ojtUdLQdPFnymEQteENwSJAdLf5KCDrmZNsy1c3YaCNaJvYsEUHnrg+/DLBH612/R0xd3dD03uz2dg=="],
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.50.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-iPeouV0UIDtz8j1YFR4OJ/zf7evjauqv7jQ/EFs0ClIyL+by++hiaDAfFipjOgyz6y6xbDvJuiU4HwpVMpRFDQ=="],
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.50.2", "", { "os": "linux", "cpu": "none" }, "sha512-OL6KaNvBopLlj5fTa5D5bau4W82f+1TyTZRr2BdnfsrnQnmdxh4okMxR2DcDkJuh4KeoQZVuvHvzuD/lyLn2Kw=="],
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.50.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-I21VJl1w6z/K5OTRl6aS9DDsqezEZ/yKpbqlvfHbW0CEF5IL8ATBMuUx6/mp683rKTK8thjs/0BaNrZLXetLag=="],
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.50.2", "", { "os": "linux", "cpu": "none" }, "sha512-Hq6aQJT/qFFHrYMjS20nV+9SKrXL2lvFBENZoKfoTH2kKDOJqff5OSJr4x72ZaG/uUn+XmBnGhfr4lwMRrmqCQ=="],
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.50.2", "", { "os": "linux", "cpu": "none" }, "sha512-82rBSEXRv5qtKyr0xZ/YMF531oj2AIpLZkeNYxmKNN6I2sVE9PGegN99tYDLK2fYHJITL1P2Lgb4ZXnv0PjQvw=="],
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.50.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-4Q3S3Hy7pC6uaRo9gtXUTJ+EKo9AKs3BXKc2jYypEcMQ49gDPFU2P1ariX9SEtBzE5egIX6fSUmbmGazwBVF9w=="],
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.50.2", "", { "os": "linux", "cpu": "x64" }, "sha512-9Jie/At6qk70dNIcopcL4p+1UirusEtznpNtcq/u/C5cC4HBX7qSGsYIcG6bdxj15EYWhHiu02YvmdPzylIZlA=="],
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.50.2", "", { "os": "linux", "cpu": "x64" }, "sha512-HPNJwxPL3EmhzeAnsWQCM3DcoqOz3/IC6de9rWfGR8ZCuEHETi9km66bH/wG3YH0V3nyzyFEGUZeL5PKyy4xvw=="],
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.50.2", "", { "os": "none", "cpu": "arm64" }, "sha512-nMKvq6FRHSzYfKLHZ+cChowlEkR2lj/V0jYj9JnGUVPL2/mIeFGmVM2mLaFeNa5Jev7W7TovXqXIG2d39y1KYA=="],
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.50.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-eFUvvnTYEKeTyHEijQKz81bLrUQOXKZqECeiWH6tb8eXXbZk+CXSG2aFrig2BQ/pjiVRj36zysjgILkqarS2YA=="],
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.50.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-cBaWmXqyfRhH8zmUxK3d3sAhEWLrtMjWBRwdMMHJIXSjvjLKvv49adxiEz+FJ8AP90apSDDBx2Tyd/WylV6ikA=="],
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.50.2", "", { "os": "win32", "cpu": "x64" }, "sha512-APwKy6YUhvZaEoHyM+9xqmTpviEI+9eL7LoCH+aLcvWYHJ663qG5zx7WzWZY+a9qkg5JtzcMyJ9z0WtQBMDmgA=="],
"@sinclair/typebox": ["@sinclair/typebox@0.34.41", "", {}, "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g=="],
"@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="],
"@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.5", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ=="],
"@sveltejs/kit": ["@sveltejs/kit@2.42.1", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.3.2", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["@opentelemetry/api"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-SoWdb/OxEKHMlXZ78eNZa4pR1YdOGnUfcFj5NylJv+ZaTrnHK5xapw+7RJP2MiS1D4T+sEH25/tmMtmEl8p6VA=="],
"@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@6.2.0", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "debug": "^4.4.1", "deepmerge": "^4.3.1", "magic-string": "^0.30.17", "vitefu": "^1.1.1" }, "peerDependencies": { "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-nJsV36+o7rZUDlrnSduMNl11+RoDE1cKqOI0yUEBCcqFoAZOk47TwD3dPKS2WmRutke9StXnzsPBslY7prDM9w=="],
"@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@5.0.1", "", { "dependencies": { "debug": "^4.4.1" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA=="],
"@tokenizer/inflate": ["@tokenizer/inflate@0.2.7", "", { "dependencies": { "debug": "^4.4.0", "fflate": "^0.8.2", "token-types": "^6.0.0" } }, "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg=="],
"@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="],
"@types/bun": ["@types/bun@1.2.22", "", { "dependencies": { "bun-types": "1.2.22" } }, "sha512-5A/KrKos2ZcN0c6ljRSOa1fYIyCKhZfIVYeuyb4snnvomnpFqC0tTsEkdqNxbAgExV384OETQ//WAjl3XbYqQA=="],
"@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
"@types/node": ["@types/node@24.5.1", "", { "dependencies": { "undici-types": "~7.12.0" } }, "sha512-/SQdmUP2xa+1rdx7VwB9yPq8PaKej8TD5cQ+XfKDPWWC+VDJU4rvVVagXqKUzhKjtFoNA8rXDJAkCxQPAe00+Q=="],
"@types/react": ["@types/react@19.1.13", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ=="],
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
"aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="],
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
"bun-types": ["bun-types@1.2.22", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-hwaAu8tct/Zn6Zft4U9BsZcXkYomzpHJX28ofvx7k0Zz2HNz54n1n+tDgxoWFGB4PcFvJXJQloPhaV2eP3Q6EA=="],
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
"cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="],
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
"deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],
"devalue": ["devalue@5.3.2", "", {}, "sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw=="],
"elysia": ["elysia@1.4.5", "", { "dependencies": { "cookie": "^1.0.2", "elysia": "1.4.3-beta.0", "exact-mirror": "0.2.2", "fast-decode-uri-component": "^1.0.1" }, "optionalDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "openapi-types": ">= 12.0.0" }, "peerDependencies": { "file-type": ">= 20.0.0", "typescript": ">= 5.0.0" } }, "sha512-slSMNyAuh6lFEjEwSkSkpzbUOLCtx6hOw4AYhpGOHqczu27eqxHbNtRtIPQuXDq6sqJ1ezXgw3gUjoasZozWRg=="],
"esbuild": ["esbuild@0.25.10", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.10", "@esbuild/android-arm": "0.25.10", "@esbuild/android-arm64": "0.25.10", "@esbuild/android-x64": "0.25.10", "@esbuild/darwin-arm64": "0.25.10", "@esbuild/darwin-x64": "0.25.10", "@esbuild/freebsd-arm64": "0.25.10", "@esbuild/freebsd-x64": "0.25.10", "@esbuild/linux-arm": "0.25.10", "@esbuild/linux-arm64": "0.25.10", "@esbuild/linux-ia32": "0.25.10", "@esbuild/linux-loong64": "0.25.10", "@esbuild/linux-mips64el": "0.25.10", "@esbuild/linux-ppc64": "0.25.10", "@esbuild/linux-riscv64": "0.25.10", "@esbuild/linux-s390x": "0.25.10", "@esbuild/linux-x64": "0.25.10", "@esbuild/netbsd-arm64": "0.25.10", "@esbuild/netbsd-x64": "0.25.10", "@esbuild/openbsd-arm64": "0.25.10", "@esbuild/openbsd-x64": "0.25.10", "@esbuild/openharmony-arm64": "0.25.10", "@esbuild/sunos-x64": "0.25.10", "@esbuild/win32-arm64": "0.25.10", "@esbuild/win32-ia32": "0.25.10", "@esbuild/win32-x64": "0.25.10" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ=="],
"esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="],
"esrap": ["esrap@2.1.0", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } }, "sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA=="],
"exact-mirror": ["exact-mirror@0.2.2", "", { "peerDependencies": { "@sinclair/typebox": "^0.34.15" }, "optionalPeers": ["@sinclair/typebox"] }, "sha512-CrGe+4QzHZlnrXZVlo/WbUZ4qQZq8C0uATQVGVgXIrNXgHDBBNFD1VRfssRA2C9t3RYvh3MadZSdg2Wy7HBoQA=="],
"fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="],
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
"fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="],
"file-type": ["file-type@21.0.0", "", { "dependencies": { "@tokenizer/inflate": "^0.2.7", "strtok3": "^10.2.2", "token-types": "^6.0.0", "uint8array-extras": "^1.4.0" } }, "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg=="],
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
"globalyzer": ["globalyzer@0.1.0", "", {}, "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q=="],
"globrex": ["globrex@0.1.2", "", {}, "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="],
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
"is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="],
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
"locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="],
"magic-string": ["magic-string@0.30.19", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw=="],
"mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
"rollup": ["rollup@4.50.2", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.50.2", "@rollup/rollup-android-arm64": "4.50.2", "@rollup/rollup-darwin-arm64": "4.50.2", "@rollup/rollup-darwin-x64": "4.50.2", "@rollup/rollup-freebsd-arm64": "4.50.2", "@rollup/rollup-freebsd-x64": "4.50.2", "@rollup/rollup-linux-arm-gnueabihf": "4.50.2", "@rollup/rollup-linux-arm-musleabihf": "4.50.2", "@rollup/rollup-linux-arm64-gnu": "4.50.2", "@rollup/rollup-linux-arm64-musl": "4.50.2", "@rollup/rollup-linux-loong64-gnu": "4.50.2", "@rollup/rollup-linux-ppc64-gnu": "4.50.2", "@rollup/rollup-linux-riscv64-gnu": "4.50.2", "@rollup/rollup-linux-riscv64-musl": "4.50.2", "@rollup/rollup-linux-s390x-gnu": "4.50.2", "@rollup/rollup-linux-x64-gnu": "4.50.2", "@rollup/rollup-linux-x64-musl": "4.50.2", "@rollup/rollup-openharmony-arm64": "4.50.2", "@rollup/rollup-win32-arm64-msvc": "4.50.2", "@rollup/rollup-win32-ia32-msvc": "4.50.2", "@rollup/rollup-win32-x64-msvc": "4.50.2", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-BgLRGy7tNS9H66aIMASq1qSYbAAJV6Z6WR4QYTvj5FgF15rZ/ympT1uixHXwzbZUBDbkvqUI1KR0fH1FhMaQ9w=="],
"sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="],
"set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="],
"sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="],
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"strtok3": ["strtok3@10.3.4", "", { "dependencies": { "@tokenizer/token": "^0.3.0" } }, "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg=="],
"svelte": ["svelte@5.38.10", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@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": "^2.1.0", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-UY+OhrWK7WI22bCZ00P/M3HtyWgwJPi9IxSRkoAE2MeAy6kl7ZlZWJZ8RaB+X4KD/G+wjis+cGVnVYaoqbzBqg=="],
"svelte-adapter-bun": ["svelte-adapter-bun@0.5.2", "", { "dependencies": { "tiny-glob": "^0.2.9" } }, "sha512-xEtFgaal6UgrCwwkSIcapO9kopoFNUYCYqyKCikdqxX9bz2TDYnrWQZ7qBnkunMxi1HOIERUCvTcebYGiarZLA=="],
"svelte-check": ["svelte-check@4.3.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-lkh8gff5gpHLjxIV+IaApMxQhTGnir2pNUAqcNgeKkvK5bT/30Ey/nzBxNLDlkztCH4dP7PixkMt9SWEKFPBWg=="],
"tiny-glob": ["tiny-glob@0.2.9", "", { "dependencies": { "globalyzer": "0.1.0", "globrex": "^0.1.2" } }, "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg=="],
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
"token-types": ["token-types@6.1.1", "", { "dependencies": { "@borewit/text-codec": "^0.1.0", "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ=="],
"totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
"typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
"uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="],
"undici-types": ["undici-types@7.12.0", "", {}, "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ=="],
"vite": ["vite@7.1.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ=="],
"vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="],
"zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="],
"elysia/cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
"elysia/elysia": ["elysia@1.4.3-beta.0", "", { "dependencies": { "cookie": "^1.0.2", "exact-mirror": "0.2.2", "fast-decode-uri-component": "^1.0.1" }, "optionalDependencies": { "@sinclair/typebox": ">= 0.34.0 < 1", "openapi-types": ">= 12.0.0" }, "peerDependencies": { "file-type": ">= 20.0.0", "typescript": ">= 5.0.0" } }, "sha512-UzanGZSqoKKcKgg+I4YB+ZOGeJNA7mlA8JPj7klYi0LDVcj/vtXKGRmsp4jEzZO+LjSpFuYTZcwHi4rCnvJj1w=="],
} }
} }
-113
View File
@@ -1,113 +0,0 @@
import { ActivityStandards, LevelCalculator, Standards } from "./calculator/calc.ts";
import { ActivityPerformance, Player } from "./calculator/util.ts";
import { Printful } from "./commerce/printful.ts"
import { Webflow } from "./commerce/webflow.ts";
import rawStandards from "./data/standards.json" assert { type: "json" }
interface CalcRequest {
player: Player,
activityPerformances: ActivityPerformance[]
}
export class ClientResponse extends Response {
constructor(body?: BodyInit | null, init: ResponseInit = {}) {
const headers = new Headers(init.headers);
headers.set("Access-Control-Allow-Origin", "*");
headers.set("Access-Control-Allow-Methods", "POST, OPTIONS");
headers.set("Access-Control-Allow-Headers", "Content-Type");
super(body, { ...init, headers });
}
static json(data: unknown, init: ResponseInit = {}) {
const body = JSON.stringify(data);
const headers = new Headers(init.headers);
headers.set("Content-Type", "application/json");
return new ClientResponse(body, { ...init, headers });
}
}
const MAIN_STANDARDS = new Standards(rawStandards as ActivityStandards);
const server = Bun.serve({
idleTimeout: 180,
routes: {
"/calc": {
OPTIONS() {
return new ClientResponse(undefined, { status: 204 });
},
async POST(req) {
const calcReq: CalcRequest = await req.json();
const { player, activityPerformances } = calcReq;
const levelCalculator = new LevelCalculator(MAIN_STANDARDS);
return ClientResponse.json({
levels: levelCalculator.calculate(player, activityPerformances)
})
}
},
"/products/sync": {
OPTIONS() {
return new ClientResponse(undefined, { status: 204 });
},
async POST(req) {
const printfulProducts = await Printful.Products.getAll();
// handle update/create
for (const printfulProduct of printfulProducts) {
const webflowProductExists = await Webflow.Products.exists(printfulProduct.sync_product.external_id);
if (webflowProductExists) {
await Webflow.Products.updateUsingPrintful(printfulProduct);
}
else {
await Webflow.Products.createUsingPrintful(printfulProduct);
}
console.log("DONE");
}
// handle delete (TODO)
return ClientResponse.json({});
}
},
"/webhook/printful": {
OPTIONS() {
return new ClientResponse(undefined, { status: 204 });
},
async POST(req) {
const payload: Printful.Webhook.EventPayload = await req.json()
try {
switch (payload.type) {
// ADD/UPDATE
case Printful.Webhook.Event.ProductUpdated: {
const printfulProduct = await Printful.Products.get(payload.data.sync_product.id);
const webflowProductExists = await Webflow.Products.exists(printfulProduct.sync_product.external_id);
if (webflowProductExists) {
await Webflow.Products.updateUsingPrintful(printfulProduct);
}
else {
await Webflow.Products.createUsingPrintful(printfulProduct);
}
break;
}
// DELETE
case Printful.Webhook.Event.ProductDeleted: {
const webflowProductId = payload.data.sync_product.external_id;
await Webflow.Products.remove(webflowProductId);
break;
}
}
}
catch (error) {
console.error(error);
ClientResponse.error();
}
return ClientResponse.json("");
}
}
},
development: true
})
console.log(`Listening on ${server.url}`);
+20 -3
View File
@@ -1,11 +1,28 @@
{ {
"dependencies": {}, "type": "module",
"devDependencies": { "devDependencies": {
"@types/bun": "^1.2.11" "@sveltejs/kit": "^2.22.0",
"@sveltejs/vite-plugin-svelte": "^6.0.0",
"@types/bun": "^1.2.22",
"svelte": "^5.0.0",
"svelte-adapter-bun": "^0.5.2",
"svelte-check": "^4.0.0",
"typescript": "^5.0.0",
"vite": "^7.0.4"
}, },
"scripts": { "scripts": {
"db:seed:dev": "sqlite3 ./data/data.db < ./data/seed.sql", "db:seed:dev": "sqlite3 ./data/data.db < ./data/seed.sql",
"db:seed:prod": "sqlite3 /data/data.db < ./data/seed.sql", "db:seed:prod": "sqlite3 /data/data.db < ./data/seed.sql",
"start": "bun run main.ts" "dev": "cd ./src/view && vite dev",
"build": "cd ./src/view && vite build",
"preview": "cd ./src/view && vite preview",
"prepare": "cd ./src/view && svelte-kit sync || echo ''",
"check": "cd ./src/view && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "cd ./src/view && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
},
"dependencies": {
"@elysiajs/cors": "^1.4.0",
"@elysiajs/eden": "^1.4.1",
"elysia": "^1.4.5"
} }
} }
+88
View File
@@ -0,0 +1,88 @@
import { Elysia } from "elysia";
import { cors } from "@elysiajs/cors";
import { ActivityStandards, LevelCalculator, Standards } from "./services/calculator/main";
import { ActivityPerformance, Player } from "./services/calculator/util";
import { Printful } from "./services/commerce/printful";
import { Webflow } from "./services/commerce/webflow";
import rawStandards from "./data/standards.json" assert { type: "json" }
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __dirname = dirname(fileURLToPath(import.meta.url));
export const app = new Elysia({ prefix: "/api" })
.use(cors())
.get("/", () => "Hello world")
// CALCULATOR
.post("/calculate", async ({ body }) => {
const MAIN_STANDARDS = new Standards(rawStandards as ActivityStandards);
interface CalcRequest {
player: Player;
activityPerformances: ActivityPerformance[];
}
const { player, activityPerformances } = body as CalcRequest;
const levelCalculator = new LevelCalculator(MAIN_STANDARDS);
return { levels: levelCalculator.calculate(player, activityPerformances) };
})
// COMMERCE
.post("/products/sync", async () => {
const printfulProducts = await Printful.Products.getAll();
for (const p of printfulProducts) {
const exists = await Webflow.Products.exists(p.sync_product.external_id);
if (exists) await Webflow.Products.updateUsingPrintful(p);
else await Webflow.Products.createUsingPrintful(p);
}
return {};
})
// DATA
.get("/data/standards", async () => {
try {
return Bun.file(join(__dirname, "data/standards.json")).json();
} catch (error) {
console.error(error);
return new Response("Failed to load standards", { status: 500 });
}
})
// WEBHOOKS
.post("/webhook/printful", async ({ body, set }) => {
const payload = body as Printful.Webhook.EventPayload;
try {
switch (payload.type) {
case Printful.Webhook.Event.ProductUpdated: {
const prod = await Printful.Products.get(payload.data.sync_product.id);
const exists = await Webflow.Products.exists(prod.sync_product.external_id);
if (exists) await Webflow.Products.updateUsingPrintful(prod);
else await Webflow.Products.createUsingPrintful(prod);
break;
}
case Printful.Webhook.Event.ProductDeleted: {
await Webflow.Products.remove(payload.data.sync_product.external_id);
break;
}
}
} catch (error) {
console.error(error);
set.status = 500;
return { error: "internal_error" };
}
return "";
});
if (import.meta.main) {
app.listen(3000);
console.log(
`Listening at ${app.server?.hostname}:${app.server?.port}`,
);
}
export type App = typeof app;
View File
View File
@@ -2,7 +2,9 @@
"BackSquat": { "BackSquat": {
"metadata": { "metadata": {
"attribute": "Strength", "attribute": "Strength",
"generators": [] "generators": [],
"unit": "kg",
"name": "Squat"
}, },
"standards": [ "standards": [
{ {
@@ -1578,7 +1580,9 @@
"Deadlift": { "Deadlift": {
"metadata": { "metadata": {
"attribute": "Strength", "attribute": "Strength",
"generators": [] "generators": [],
"unit": "kg",
"name": "Deadlift"
}, },
"standards": [ "standards": [
{ {
@@ -3154,7 +3158,9 @@
"BenchPress": { "BenchPress": {
"metadata": { "metadata": {
"attribute": "Strength", "attribute": "Strength",
"generators": [] "generators": [],
"unit": "kg",
"name": "Bench Press"
}, },
"standards": [ "standards": [
{ {
@@ -4737,7 +4743,9 @@
"step": 12, "step": 12,
"ratio": "inverse" "ratio": "inverse"
} }
] ],
"unit": "ms",
"name": "Mile Run"
}, },
"standards": [ "standards": [
{ {
@@ -5221,7 +5229,9 @@
"BroadJump": { "BroadJump": {
"metadata": { "metadata": {
"attribute": "Power", "attribute": "Power",
"generators": [] "generators": [],
"unit": "cm",
"name": "Broad Jump"
}, },
"standards": [ "standards": [
{ {
@@ -5257,7 +5267,9 @@
"ConeDrill": { "ConeDrill": {
"metadata": { "metadata": {
"attribute": "Agility", "attribute": "Agility",
"generators": [] "generators": [],
"unit": "ms",
"name": "3 Cone Drill"
}, },
"standards": [ "standards": [
{ {
@@ -1,4 +1,4 @@
import { Activity, Attribute, Player, Gender, ActivityPerformance, lbToKg } from "./util"; import { Activity, Attribute, Player, Gender, ActivityPerformance, lbToKg, StandardUnit } from "./util";
// SOURCES // SOURCES
// Squat, Bench, Dead Lift: // Squat, Bench, Dead Lift:
@@ -45,7 +45,9 @@ type Generator = {
export type ActivityStandards = Record<Activity, { export type ActivityStandards = Record<Activity, {
metadata: { metadata: {
attribute: Attribute, attribute: Attribute,
generators: Generator[] generators: Generator[],
unit: StandardUnit,
name: string
}, },
standards: Standard[] standards: Standard[]
}>; }>;
@@ -112,7 +114,7 @@ export class LevelCalculator {
(Object.values(Attribute) as Attribute[]).forEach((attribute) => { (Object.values(Attribute) as Attribute[]).forEach((attribute) => {
const attrActivityPerformances = activityPerformances.filter( const attrActivityPerformances = activityPerformances.filter(
(p) => this.standards.getActivityAttribute(p.activity) === attribute, (p) => this.standards.byActivity(p.activity).getMetadata().attribute === attribute,
); );
attrLevels[attribute] = this.calculateAttributeLevel(attribute, player, attrActivityPerformances); attrLevels[attribute] = this.calculateAttributeLevel(attribute, player, attrActivityPerformances);
}); });
@@ -127,7 +129,7 @@ export class LevelCalculator {
activityPerformances: ActivityPerformance[], activityPerformances: ActivityPerformance[],
): number { ): number {
// must be activities of the given attribute // must be activities of the given attribute
if (activityPerformances.some((p) => this.standards.getActivityAttribute(p.activity) !== attribute)) { if (activityPerformances.some((p) => this.standards.byActivity(p.activity).getMetadata().attribute !== attribute)) {
throw new Error("Wrong activity performance attribute"); throw new Error("Wrong activity performance attribute");
} }
@@ -148,7 +150,7 @@ export class LevelCalculator {
const interpolatedStandard = this.standards const interpolatedStandard = this.standards
.byActivity(p.activity) .byActivity(p.activity)
.byMetrics(player.metrics) .byMetrics(player.metrics)
.getInterpolated(); .getOneInterpolated();
return this.findLevel(interpolatedStandard, p.performance); return this.findLevel(interpolatedStandard, p.performance);
}); });
@@ -168,7 +170,9 @@ export class LevelCalculator {
let resultLevelDiff = Infinity; let resultLevelDiff = Infinity;
for (const level in standard.levels) { for (const level in standard.levels) {
const diff = Math.abs(performance - standard.levels[level as unknown as number]); if (!standard.levels[level]) continue;
const diff = Math.abs(performance - standard.levels[level]);
if (diff < resultLevelDiff) { if (diff < resultLevelDiff) {
resultLevel = +level; resultLevel = +level;
resultLevelDiff = diff; resultLevelDiff = diff;
@@ -178,17 +182,26 @@ export class LevelCalculator {
} }
} }
type StandardsConfig = {
maxLevel: number
}
export class Standards { export class Standards {
readonly cfg: StandardsConfig;
private activityStandards: ActivityStandards; private activityStandards: ActivityStandards;
constructor(activityStandards: ActivityStandards) { constructor(activityStandards: ActivityStandards, cfg?: Partial<StandardsConfig>) {
this.cfg = {
maxLevel: cfg?.maxLevel ?? 100
};
// prepare data // prepare data
this.activityStandards = activityStandards; this.activityStandards = structuredClone(activityStandards);
for (const activity of Object.keys(this.activityStandards) as Activity[]) { for (const activity of Object.keys(this.activityStandards) as Activity[]) {
// expand/compress // expand/compress
for (const standard of this.activityStandards[activity].standards) { for (const standard of this.activityStandards[activity].standards) {
const expandedLevels = this.expandLevels(standard.levels, 5); const expandedLevels = this.expandLevels(standard.levels, 5);
const compressedLevels = this.compressLevels(expandedLevels, 100); const compressedLevels = this.compressLevels(expandedLevels, this.cfg.maxLevel);
standard.levels = compressedLevels; standard.levels = compressedLevels;
} }
@@ -216,7 +229,7 @@ export class Standards {
const referenceStandard = this const referenceStandard = this
.byActivity(activity) .byActivity(activity)
.byMetrics({ weight: referenceWeight, gender: gender, age: age }) .byMetrics({ weight: referenceWeight, gender: gender, age: age })
.getInterpolated(); .getOneInterpolated();
let currWeight = minWeight; let currWeight = minWeight;
while (currWeight <= maxWeight) { while (currWeight <= maxWeight) {
@@ -231,6 +244,8 @@ export class Standards {
// apply allometric scaling to generate levels // apply allometric scaling to generate levels
for (const lvl in referenceStandard.levels) { for (const lvl in referenceStandard.levels) {
if (!referenceStandard.levels[lvl]) continue;
const scalingExponent = .1; const scalingExponent = .1;
const coefficient = weightGenerator.ratio === "inverse" ? const coefficient = weightGenerator.ratio === "inverse" ?
referenceWeight / currWeight : referenceWeight / currWeight :
@@ -257,8 +272,6 @@ export class Standards {
} }
} }
Bun.write("./newStandards.json", JSON.stringify(this.activityStandards, null, 2));
} }
public byActivity(activity: Activity) { public byActivity(activity: Activity) {
@@ -270,35 +283,50 @@ export class Standards {
const execMethods = { const execMethods = {
exact: { exact: {
// these will get EXACT matches // these will get EXACT matches
getAll: function(): Standard[] { getAll(): Standard[] {
let filtered = [...self.activityStandards[activity].standards]; const src = self.activityStandards[activity].standards;
if (state.gender)
filtered = filtered.filter((s) => s.metrics.gender === state.gender); const out: Standard[] = [];
if (state.age) for (let i = 0; i < src.length; i++) {
filtered = filtered.filter((s) => s.metrics.age === state.age); const s = src[i];
if (state.weight) if (state.gender != null && s.metrics.gender !== state.gender) continue;
filtered = filtered.filter((s) => s.metrics.weight === state.weight); if (state.age != null && s.metrics.age !== state.age) continue;
return filtered; if (state.weight != null && s.metrics.weight !== state.weight) continue;
out.push(s);
}
return out;
}, },
getOne: function(): Standard | undefined { getOne: function(): Standard | undefined {
return execMethods.exact.getAll()[0]; return execMethods.exact.getAll()[0];
}, },
getNearest(metric: NumberMetric, target: number): { lower: Standard, upper: Standard } { getNearest(metric: NumberMetric, target: number): { lower: Standard; upper: Standard } {
const standards = execMethods.exact.getAll(); const standards = execMethods.exact.getAll();
const lower = [...standards] if (standards.length === 0) throw new Error('no standards');
.sort((a, b) => a.metrics[metric] - b.metrics[metric])
.reverse()
.find((s) => s.metrics[metric] <= target) ?? standards.at(0)!;
const upper = [...standards]
.sort((a, b) => a.metrics[metric] - b.metrics[metric])
.find((s) => s.metrics[metric] >= target) ?? standards.at(-1)!;
return { lower, upper };
},
},
interpolated: {
getInterpolated: (): Standard => {
const metrics: Metrics = state as Metrics;
let lower = standards[0]; // best <= target
let upper = standards[0]; // best >= target
let hasLower = false, hasUpper = false;
for (const standard of standards) {
const standardMetricValue = standard.metrics[metric];
if (standardMetricValue <= target) {
if (!hasLower || standardMetricValue > lower.metrics[metric]) { lower = standard; hasLower = true; }
}
if (standardMetricValue >= target) {
if (!hasUpper || standardMetricValue < upper.metrics[metric]) { upper = standard; hasUpper = true; }
}
}
// clamp to ends if one side missing
if (!hasLower) lower = standards[0];
if (!hasUpper) upper = standards[standards.length - 1];
return { lower, upper };
}
}
};
const interpolateByAgeAndWeight = (metrics: Metrics): Standard => {
const interpolateByWeight = (targetAge: number): Levels => { const interpolateByWeight = (targetAge: number): Levels => {
const { lower: lowerAgeWeightStandard, upper: upperAgeWeightStandard } = this const { lower: lowerAgeWeightStandard, upper: upperAgeWeightStandard } = this
.byActivity(activity) .byActivity(activity)
@@ -335,13 +363,32 @@ export class Standards {
); );
return { return {
metrics, metrics: metrics,
levels: interpolatedLevels levels: interpolatedLevels
};
}
} }
}; };
const getAllInterpolated = (): Standard[] => {
const metrics: Metrics = state as Metrics;
const weights = [... new Set(this
.byActivity(activity)
.byGender(metrics.gender)
.getAll().map((s) => s.metrics.weight))];
const interpolatedStandards: Standard[] = weights
.map((w) => interpolateByAgeAndWeight({ gender: metrics.gender, age: metrics.age, weight: w }));
return interpolatedStandards;
};
const getOneInterpolated = (): Standard => {
const metrics: Metrics = state as Metrics;
return interpolateByAgeAndWeight(metrics);
};
const getMetadata = () => this.activityStandards[activity].metadata;
// QUERY METHODS // QUERY METHODS
const byGender = (gender: Gender) => { const byGender = (gender: Gender) => {
@@ -351,30 +398,26 @@ export class Standards {
const byAge = (age: number) => { const byAge = (age: number) => {
state.age = age; state.age = age;
return { byWeight, ...execMethods.exact }; return { byWeight, ...execMethods.exact, getAllInterpolated };
} }
const byWeight = (weight: number) => { const byWeight = (weight: number) => {
state.weight = weight; state.weight = weight;
return { ...execMethods.exact, ...execMethods.interpolated }; return { ...execMethods.exact, getOneInterpolated };
} }
const byMetrics = (metrics: Metrics) => { const byMetrics = (metrics: Metrics) => {
Object.assign(state, metrics); Object.assign(state, metrics);
return { ...execMethods.exact, ...execMethods.interpolated }; return { ...execMethods.exact, getOneInterpolated };
} }
const initialMethods = { byGender, byMetrics, ...execMethods.exact }; const initialMethods = { byGender, byMetrics, getMetadata, ...execMethods.exact };
return initialMethods; return initialMethods;
} }
getActivityAttribute(activity: Activity): Attribute { public getAttributeActivities(attribute: Attribute): Activity[] {
return this.activityStandards[activity].metadata.attribute;
};
getAttributeActivities(attribute: Attribute): Activity[] {
const activities: Activity[] = []; const activities: Activity[] = [];
for (const activity in this.activityStandards) { for (const activity of Object.keys(this.activityStandards) as Activity[]) {
const activityStandard = this.activityStandards[activity] as ActivityStandards[Activity]; const activityStandard = this.activityStandards[activity] as ActivityStandards[Activity];
if (activityStandard.metadata.attribute === attribute) { if (activityStandard.metadata.attribute === attribute) {
activities.push(activity as Activity); activities.push(activity as Activity);
@@ -1,4 +1,4 @@
import { Metrics } from "./calc"; import { Metrics } from "../calculator/main";
// ------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------
// DATA MODELS // DATA MODELS
@@ -37,35 +37,18 @@ export enum Gender {
// ------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------
// Conversion utilities // Conversion utilities
// ------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------
export type StandardUnit = "ms" | "cm" | "kg";
export const lbToKg = (lb: number | string): number => +lb * 0.453592; export const lbToKg = (lb: number | string): number => +lb * 0.453592;
export const kgToLb = (kg: number | string): number => +kg * 2.20462; export const kgToLb = (kg: number | string): number => +kg * 2.20462;
export const minToMs = (min) => min * 60000; export const minToMs = (min: number) => min * 60000;
export const secToMs = (sec) => sec * 1000; export const secToMs = (sec: number) => sec * 1000;
export const msToMin = (ms: number) => ms / 60000;
export const feetToCm = (feet) => feet * 30.48; export const feetToCm = (feet: number) => feet * 30.48;
export const inchesToCm = (inches) => inches * 2.54; export const inchesToCm = (inches: number) => inches * 2.54;
export const mphToMtrsPerMs = (mph: number): number => (mph * 0.44704) / 1000;
export const timeToMs = (time: string): number => {
const [main, decimal = "0"] = time.split(".");
const milliseconds = Number(decimal.padEnd(3, "0").slice(0, 3));
const parts = main.split(":").map(Number);
let minutes = 0,
seconds = 0;
if (parts.length === 1) {
seconds = parts[0];
} else if (parts.length === 2) {
[minutes, seconds] = parts as [number, number];
} else {
throw new Error("Invalid time format");
}
return (minutes * 60 + seconds) * 1000 + milliseconds;
};
export const msToTime = (ms: number, includeMs = false): string => { export const msToTime = (ms: number, includeMs = false): string => {
const minutes = Math.floor(ms / 60000); const minutes = Math.floor(ms / 60000);
@@ -78,3 +61,7 @@ export const msToTime = (ms: number, includeMs = false): string => {
} }
return formattedTime; return formattedTime;
}; };
export const range = (length: number) => Array.from({ length: length }, (_, i) => i + 1);
@@ -249,9 +249,9 @@ export namespace Webflow {
"skus": webflowVariants.slice(1) "skus": webflowVariants.slice(1)
}) })
}); });
createSkuResponse = await createSkuResponse.json(); const createSkuObj = await createSkuResponse.json();
const responseSkus = [addProductResponse["sku"], ...createSkuResponse["skus"]]; const responseSkus = [addProductResponse["sku"], ...createSkuObj["skus"]];
// SYNC WEBFLOW/PRINTFUL PRODUCT AND VARIANT IDs // SYNC WEBFLOW/PRINTFUL PRODUCT AND VARIANT IDs
let modifyPrintfulProductResponse = await fetch(`${Printful.API_URL}/store/products/${printfulProductId}`, { let modifyPrintfulProductResponse = await fetch(`${Printful.API_URL}/store/products/${printfulProductId}`, {
@@ -1,5 +1,5 @@
import { Activity, ActivityPerformance, feetToCm, Gender, inchesToCm, lbToKg, minToMs, Player, secToMs } from "./util"; import { Activity, ActivityPerformance, feetToCm, Gender, inchesToCm, lbToKg, minToMs, Player, secToMs } from "../services/calculator/util";
import { ActivityStandards, LevelCalculator, Standards } from "./calc.ts"; import { ActivityStandards, LevelCalculator, Standards } from "../services/calculator/main"
import rawStandards from "../data/standards.json" assert { type: "json" } import rawStandards from "../data/standards.json" assert { type: "json" }
const player: Player = { const player: Player = {
@@ -41,11 +41,6 @@ const computedPerformances: ActivityPerformance[] = [
}, },
]; ];
const standards = new Standards(rawStandards as ActivityStandards);
const levelCalculator = new LevelCalculator(standards);
console.log(levelCalculator.calculate(player, computedPerformances));
// const newStandards: Standards = { // const newStandards: Standards = {
// "Back Squat": [], // "Back Squat": [],
// "Deadlift": [], // "Deadlift": [],
+271
View File
@@ -0,0 +1,271 @@
// this file is generated — do not edit it
/// <reference types="@sveltejs/kit" />
/**
* Environment variables [loaded by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files) from `.env` files and `process.env`. Like [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private), this module cannot be imported into client-side code. This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](https://svelte.dev/docs/kit/configuration#env) (if configured).
*
* _Unlike_ [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private), the values exported from this module are statically injected into your bundle at build time, enabling optimisations like dead code elimination.
*
* ```ts
* import { API_KEY } from '$env/static/private';
* ```
*
* Note that all environment variables referenced in your code should be declared (for example in an `.env` file), even if they don't have a value until the app is deployed:
*
* ```
* MY_FEATURE_FLAG=""
* ```
*
* You can override `.env` values from the command line like so:
*
* ```sh
* MY_FEATURE_FLAG="enabled" npm run dev
* ```
*/
declare module '$env/static/private' {
export const IMSETTINGS_INTEGRATE_DESKTOP: string;
export const SHELL: string;
export const npm_command: string;
export const SESSION_MANAGER: string;
export const WINDOWID: string;
export const COLORTERM: string;
export const XDG_CONFIG_DIRS: string;
export const KGLOBALACCELD_PLATFORM: string;
export const XDG_SESSION_PATH: string;
export const HISTCONTROL: string;
export const XDG_MENU_PREFIX: string;
export const HISTSIZE: string;
export const HOSTNAME: string;
export const ICEAUTHORITY: string;
export const LANGUAGE: string;
export const NODE: string;
export const DOTNET_ROOT: string;
export const SSH_AUTH_SOCK: string;
export const FLYCTL_INSTALL: string;
export const SHELL_SESSION_ID: string;
export const MEMORY_PRESSURE_WRITE: string;
export const npm_config_local_prefix: string;
export const XMODIFIERS: string;
export const DESKTOP_SESSION: string;
export const SSH_AGENT_PID: string;
export const GTK_RC_FILES: string;
export const GDK_CORE_DEVICE_EVENTS: string;
export const GPG_TTY: string;
export const EDITOR: string;
export const XDG_SEAT: string;
export const PWD: string;
export const NIX_PROFILES: string;
export const LOGNAME: string;
export const XDG_SESSION_DESKTOP: string;
export const XDG_SESSION_TYPE: string;
export const SYSTEMD_EXEC_PID: string;
export const XAUTHORITY: string;
export const SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS: string;
export const XKB_DEFAULT_MODEL: string;
export const GTK2_RC_FILES: string;
export const HOME: string;
export const SSH_ASKPASS: string;
export const LANG: string;
export const LS_COLORS: string;
export const XDG_CURRENT_DESKTOP: string;
export const KONSOLE_DBUS_SERVICE: string;
export const MEMORY_PRESSURE_WATCH: string;
export const WAYLAND_DISPLAY: string;
export const NIX_SSL_CERT_FILE: string;
export const KONSOLE_DBUS_SESSION: string;
export const PROFILEHOME: string;
export const XDG_SEAT_PATH: string;
export const INVOCATION_ID: string;
export const KONSOLE_VERSION: string;
export const MANAGERPID: string;
export const IMSETTINGS_MODULE: string;
export const DOTNET_BUNDLE_EXTRACT_BASE_DIR: string;
export const STEAM_FRAME_FORCE_CLOSE: string;
export const KDE_SESSION_UID: string;
export const npm_lifecycle_script: string;
export const MOZ_GMP_PATH: string;
export const NVM_DIR: string;
export const XKB_DEFAULT_LAYOUT: string;
export const XDG_SESSION_CLASS: string;
export const TERM: string;
export const LESSOPEN: string;
export const USER: string;
export const COLORFGBG: string;
export const QT_WAYLAND_RECONNECT: string;
export const KDE_SESSION_VERSION: string;
export const PAM_KWALLET5_LOGIN: string;
export const DISPLAY: string;
export const npm_lifecycle_event: string;
export const SHLVL: string;
export const XDG_VTNR: string;
export const XDG_SESSION_ID: string;
export const npm_config_user_agent: string;
export const npm_execpath: string;
export const XDG_RUNTIME_DIR: string;
export const DEBUGINFOD_URLS: string;
export const npm_package_json: string;
export const BUN_INSTALL: string;
export const DEBUGINFOD_IMA_CERT_PATH: string;
export const KDEDIRS: string;
export const JOURNAL_STREAM: string;
export const XDG_DATA_DIRS: string;
export const KDE_FULL_SESSION: string;
export const PATH: string;
export const DBUS_SESSION_BUS_ADDRESS: string;
export const KDE_APPLICATIONS_AS_SCOPE: string;
export const MAIL: string;
export const npm_node_execpath: string;
export const OLDPWD: string;
export const GOPATH: string;
export const KONSOLE_DBUS_WINDOW: string;
export const _: string;
export const NODE_ENV: string;
}
/**
* Similar to [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private), except that it only includes environment variables that begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) (which defaults to `PUBLIC_`), and can therefore safely be exposed to client-side code.
*
* Values are replaced statically at build time.
*
* ```ts
* import { PUBLIC_BASE_URL } from '$env/static/public';
* ```
*/
declare module '$env/static/public' {
}
/**
* This module provides access to runtime environment variables, as defined by the platform you're running on. For example if you're using [`adapter-node`](https://github.com/sveltejs/kit/tree/main/packages/adapter-node) (or running [`vite preview`](https://svelte.dev/docs/kit/cli)), this is equivalent to `process.env`. This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](https://svelte.dev/docs/kit/configuration#env) (if configured).
*
* This module cannot be imported into client-side code.
*
* ```ts
* import { env } from '$env/dynamic/private';
* console.log(env.DEPLOYMENT_SPECIFIC_VARIABLE);
* ```
*
* > [!NOTE] In `dev`, `$env/dynamic` always includes environment variables from `.env`. In `prod`, this behavior will depend on your adapter.
*/
declare module '$env/dynamic/private' {
export const env: {
IMSETTINGS_INTEGRATE_DESKTOP: string;
SHELL: string;
npm_command: string;
SESSION_MANAGER: string;
WINDOWID: string;
COLORTERM: string;
XDG_CONFIG_DIRS: string;
KGLOBALACCELD_PLATFORM: string;
XDG_SESSION_PATH: string;
HISTCONTROL: string;
XDG_MENU_PREFIX: string;
HISTSIZE: string;
HOSTNAME: string;
ICEAUTHORITY: string;
LANGUAGE: string;
NODE: string;
DOTNET_ROOT: string;
SSH_AUTH_SOCK: string;
FLYCTL_INSTALL: string;
SHELL_SESSION_ID: string;
MEMORY_PRESSURE_WRITE: string;
npm_config_local_prefix: string;
XMODIFIERS: string;
DESKTOP_SESSION: string;
SSH_AGENT_PID: string;
GTK_RC_FILES: string;
GDK_CORE_DEVICE_EVENTS: string;
GPG_TTY: string;
EDITOR: string;
XDG_SEAT: string;
PWD: string;
NIX_PROFILES: string;
LOGNAME: string;
XDG_SESSION_DESKTOP: string;
XDG_SESSION_TYPE: string;
SYSTEMD_EXEC_PID: string;
XAUTHORITY: string;
SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS: string;
XKB_DEFAULT_MODEL: string;
GTK2_RC_FILES: string;
HOME: string;
SSH_ASKPASS: string;
LANG: string;
LS_COLORS: string;
XDG_CURRENT_DESKTOP: string;
KONSOLE_DBUS_SERVICE: string;
MEMORY_PRESSURE_WATCH: string;
WAYLAND_DISPLAY: string;
NIX_SSL_CERT_FILE: string;
KONSOLE_DBUS_SESSION: string;
PROFILEHOME: string;
XDG_SEAT_PATH: string;
INVOCATION_ID: string;
KONSOLE_VERSION: string;
MANAGERPID: string;
IMSETTINGS_MODULE: string;
DOTNET_BUNDLE_EXTRACT_BASE_DIR: string;
STEAM_FRAME_FORCE_CLOSE: string;
KDE_SESSION_UID: string;
npm_lifecycle_script: string;
MOZ_GMP_PATH: string;
NVM_DIR: string;
XKB_DEFAULT_LAYOUT: string;
XDG_SESSION_CLASS: string;
TERM: string;
LESSOPEN: string;
USER: string;
COLORFGBG: string;
QT_WAYLAND_RECONNECT: string;
KDE_SESSION_VERSION: string;
PAM_KWALLET5_LOGIN: string;
DISPLAY: string;
npm_lifecycle_event: string;
SHLVL: string;
XDG_VTNR: string;
XDG_SESSION_ID: string;
npm_config_user_agent: string;
npm_execpath: string;
XDG_RUNTIME_DIR: string;
DEBUGINFOD_URLS: string;
npm_package_json: string;
BUN_INSTALL: string;
DEBUGINFOD_IMA_CERT_PATH: string;
KDEDIRS: string;
JOURNAL_STREAM: string;
XDG_DATA_DIRS: string;
KDE_FULL_SESSION: string;
PATH: string;
DBUS_SESSION_BUS_ADDRESS: string;
KDE_APPLICATIONS_AS_SCOPE: string;
MAIL: string;
npm_node_execpath: string;
OLDPWD: string;
GOPATH: string;
KONSOLE_DBUS_WINDOW: string;
_: string;
NODE_ENV: string;
[key: `PUBLIC_${string}`]: undefined;
[key: `${string}`]: string | undefined;
}
}
/**
* Similar to [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private), but only includes variables that begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) (which defaults to `PUBLIC_`), and can therefore safely be exposed to client-side code.
*
* Note that public dynamic environment variables must all be sent from the server to the client, causing larger network requests — when possible, use `$env/static/public` instead.
*
* ```ts
* import { env } from '$env/dynamic/public';
* console.log(env.PUBLIC_DEPLOYMENT_SPECIFIC_VARIABLE);
* ```
*/
declare module '$env/dynamic/public' {
export const env: {
[key: `PUBLIC_${string}`]: string | undefined;
}
}
@@ -0,0 +1,28 @@
export { matchers } from './matchers.js';
export const nodes = [
() => import('./nodes/0'),
() => import('./nodes/1'),
() => import('./nodes/2')
];
export const server_loads = [0];
export const dictionary = {
"/": [2]
};
export const hooks = {
handleError: (({ error }) => { console.error(error) }),
reroute: (() => {}),
transport: {}
};
export const decoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.decode]));
export const hash = false;
export const decode = (type, value) => decoders[type](value);
export { default as root } from '../root.js';
@@ -0,0 +1 @@
export const matchers = {};
@@ -0,0 +1 @@
export { default as component } from "../../../../src/routes/+layout.svelte";
@@ -0,0 +1 @@
export { default as component } from "../../../../../../node_modules/@sveltejs/kit/src/runtime/components/svelte-5/error.svelte";
@@ -0,0 +1 @@
export { default as component } from "../../../../src/routes/+page.svelte";
+3
View File
@@ -0,0 +1,3 @@
import { asClassComponent } from 'svelte/legacy';
import Root from './root.svelte';
export default asClassComponent(Root);
@@ -0,0 +1,66 @@
<!-- This file is generated by @sveltejs/kit — do not edit it! -->
<svelte:options runes={true} />
<script>
import { setContext, onMount, tick } from 'svelte';
import { browser } from '$app/environment';
// stores
let { stores, page, constructors, components = [], form, data_0 = null, data_1 = null } = $props();
if (!browser) {
setContext('__svelte__', stores);
}
if (browser) {
$effect.pre(() => stores.page.set(page));
} else {
stores.page.set(page);
}
$effect(() => {
stores;page;constructors;components;form;data_0;data_1;
stores.page.notify();
});
let mounted = $state(false);
let navigated = $state(false);
let title = $state(null);
onMount(() => {
const unsubscribe = stores.page.subscribe(() => {
if (mounted) {
navigated = true;
tick().then(() => {
title = document.title || 'untitled page';
});
}
});
mounted = true;
return unsubscribe;
});
const Pyramid_1=$derived(constructors[1])
</script>
{#if constructors[1]}
{@const Pyramid_0 = constructors[0]}
<!-- svelte-ignore binding_property_non_reactive -->
<Pyramid_0 bind:this={components[0]} data={data_0} {form} params={page.params}>
<!-- svelte-ignore binding_property_non_reactive -->
<Pyramid_1 bind:this={components[1]} data={data_1} {form} params={page.params} />
</Pyramid_0>
{:else}
{@const Pyramid_0 = constructors[0]}
<!-- svelte-ignore binding_property_non_reactive -->
<Pyramid_0 bind:this={components[0]} data={data_0} {form} params={page.params} />
{/if}
{#if mounted}
<div id="svelte-announcer" aria-live="assertive" aria-atomic="true" style="position: absolute; left: 0; top: 0; clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; white-space: nowrap; width: 1px; height: 1px">
{#if navigated}
{title}
{/if}
</div>
{/if}
@@ -0,0 +1,52 @@
import root from '../root.js';
import { set_building, set_prerendering } from '__sveltekit/environment';
import { set_assets } from '__sveltekit/paths';
import { set_manifest, set_read_implementation } from '__sveltekit/server';
import { set_private_env, set_public_env } from '../../../../../node_modules/@sveltejs/kit/src/runtime/shared-server.js';
export const options = {
app_template_contains_nonce: false,
csp: {"mode":"auto","directives":{"upgrade-insecure-requests":false,"block-all-mixed-content":false},"reportOnly":{"upgrade-insecure-requests":false,"block-all-mixed-content":false}},
csrf_check_origin: true,
csrf_trusted_origins: [],
embedded: false,
env_public_prefix: 'PUBLIC_',
env_private_prefix: '',
hash_routing: false,
hooks: null, // added lazily, via `get_hooks`
preload_strategy: "modulepreload",
root,
service_worker: false,
service_worker_options: undefined,
templates: {
app: ({ head, body, assets, nonce, env }) => "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n\t\t" + head + "\n\t</head>\n\t<body data-sveltekit-preload-data=\"hover\">\n\t\t<div style=\"display: contents\">" + body + "</div>\n\t</body>\n</html>\n",
error: ({ status, message }) => "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<title>" + message + "</title>\n\n\t\t<style>\n\t\t\tbody {\n\t\t\t\t--bg: white;\n\t\t\t\t--fg: #222;\n\t\t\t\t--divider: #ccc;\n\t\t\t\tbackground: var(--bg);\n\t\t\t\tcolor: var(--fg);\n\t\t\t\tfont-family:\n\t\t\t\t\tsystem-ui,\n\t\t\t\t\t-apple-system,\n\t\t\t\t\tBlinkMacSystemFont,\n\t\t\t\t\t'Segoe UI',\n\t\t\t\t\tRoboto,\n\t\t\t\t\tOxygen,\n\t\t\t\t\tUbuntu,\n\t\t\t\t\tCantarell,\n\t\t\t\t\t'Open Sans',\n\t\t\t\t\t'Helvetica Neue',\n\t\t\t\t\tsans-serif;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tjustify-content: center;\n\t\t\t\theight: 100vh;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t.error {\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tmax-width: 32rem;\n\t\t\t\tmargin: 0 1rem;\n\t\t\t}\n\n\t\t\t.status {\n\t\t\t\tfont-weight: 200;\n\t\t\t\tfont-size: 3rem;\n\t\t\t\tline-height: 1;\n\t\t\t\tposition: relative;\n\t\t\t\ttop: -0.05rem;\n\t\t\t}\n\n\t\t\t.message {\n\t\t\t\tborder-left: 1px solid var(--divider);\n\t\t\t\tpadding: 0 0 0 1rem;\n\t\t\t\tmargin: 0 0 0 1rem;\n\t\t\t\tmin-height: 2.5rem;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t}\n\n\t\t\t.message h1 {\n\t\t\t\tfont-weight: 400;\n\t\t\t\tfont-size: 1em;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t@media (prefers-color-scheme: dark) {\n\t\t\t\tbody {\n\t\t\t\t\t--bg: #222;\n\t\t\t\t\t--fg: #ddd;\n\t\t\t\t\t--divider: #666;\n\t\t\t\t}\n\t\t\t}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<div class=\"error\">\n\t\t\t<span class=\"status\">" + status + "</span>\n\t\t\t<div class=\"message\">\n\t\t\t\t<h1>" + message + "</h1>\n\t\t\t</div>\n\t\t</div>\n\t</body>\n</html>\n"
},
version_hash: "hxbxsl"
};
export async function get_hooks() {
let handle;
let handleFetch;
let handleError;
let handleValidationError;
let init;
let reroute;
let transport;
return {
handle,
handleFetch,
handleError,
handleValidationError,
init,
reroute,
transport
};
}
export { set_assets, set_building, set_manifest, set_prerendering, set_private_env, set_public_env, set_read_implementation };
+42
View File
@@ -0,0 +1,42 @@
// this file is generated — do not edit it
declare module "svelte/elements" {
export interface HTMLAttributes<T> {
'data-sveltekit-keepfocus'?: true | '' | 'off' | undefined | null;
'data-sveltekit-noscroll'?: true | '' | 'off' | undefined | null;
'data-sveltekit-preload-code'?:
| true
| ''
| 'eager'
| 'viewport'
| 'hover'
| 'tap'
| 'off'
| undefined
| null;
'data-sveltekit-preload-data'?: true | '' | 'hover' | 'tap' | 'off' | undefined | null;
'data-sveltekit-reload'?: true | '' | 'off' | undefined | null;
'data-sveltekit-replacestate'?: true | '' | 'off' | undefined | null;
}
}
export {};
declare module "$app/types" {
export interface AppTypes {
RouteId(): "/" | "/[...slugs]";
RouteParams(): {
"/[...slugs]": { slugs: string }
};
LayoutParams(): {
"/": { slugs?: string };
"/[...slugs]": { slugs: string }
};
Pathname(): "/" | `/${string}` & {} | `/${string}/` & {};
ResolvedPathname(): `${"" | `/${string}`}${ReturnType<AppTypes['Pathname']>}`;
Asset(): "/robots.txt" | string & {};
}
}
+52
View File
@@ -0,0 +1,52 @@
{
"compilerOptions": {
"paths": {
"$lib": [
"../src/lib"
],
"$lib/*": [
"../src/lib/*"
],
"$app/types": [
"./types/index.d.ts"
]
},
"rootDirs": [
"..",
"./types"
],
"verbatimModuleSyntax": true,
"isolatedModules": true,
"lib": [
"esnext",
"DOM",
"DOM.Iterable"
],
"moduleResolution": "bundler",
"module": "esnext",
"noEmit": true,
"target": "esnext"
},
"include": [
"ambient.d.ts",
"non-ambient.d.ts",
"./types/**/$types.d.ts",
"../vite.config.js",
"../vite.config.ts",
"../src/**/*.js",
"../src/**/*.ts",
"../src/**/*.svelte",
"../tests/**/*.js",
"../tests/**/*.ts",
"../tests/**/*.svelte"
],
"exclude": [
"../node_modules/**",
"../src/service-worker.js",
"../src/service-worker/**/*.js",
"../src/service-worker.ts",
"../src/service-worker/**/*.ts",
"../src/service-worker.d.ts",
"../src/service-worker/**/*.d.ts"
]
}
@@ -0,0 +1,9 @@
{
"/": [
"src/routes/+layout.server.ts",
"src/routes/+layout.server.ts"
],
"/[...slugs]": [
"src/routes/[...slugs]/+server.ts"
]
}
+28
View File
@@ -0,0 +1,28 @@
import type * as Kit from '@sveltejs/kit';
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
// @ts-ignore
type MatcherParam<M> = M extends (param : string) => param is infer U ? U extends string ? U : string : string;
type RouteParams = { };
type RouteId = '/';
type MaybeWithVoid<T> = {} extends T ? T | void : T;
export type RequiredKeys<T> = { [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; }[keyof T];
type OutputDataShape<T> = MaybeWithVoid<Omit<App.PageData, RequiredKeys<T>> & Partial<Pick<App.PageData, keyof T & keyof App.PageData>> & Record<string, any>>
type EnsureDefined<T> = T extends null | undefined ? {} : T;
type OptionalUnion<U extends Record<string, any>, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude<A, keyof U>]?: never } & U : never;
export type Snapshot<T = any> = Kit.Snapshot<T>;
type PageParentData = EnsureDefined<LayoutData>;
type LayoutRouteId = RouteId | "/" | null
type LayoutParams = RouteParams & { }
type LayoutServerParentData = EnsureDefined<{}>;
type LayoutParentData = EnsureDefined<{}>;
export type PageServerData = null;
export type PageData = Expand<PageParentData>;
export type PageProps = { params: RouteParams; data: PageData }
export type LayoutServerLoad<OutputData extends OutputDataShape<LayoutServerParentData> = OutputDataShape<LayoutServerParentData>> = Kit.ServerLoad<LayoutParams, LayoutServerParentData, OutputData, LayoutRouteId>;
export type LayoutServerLoadEvent = Parameters<LayoutServerLoad>[0];
export type LayoutServerData = Expand<OptionalUnion<EnsureDefined<Kit.LoadProperties<Awaited<ReturnType<typeof import('./proxy+layout.server.js').load>>>>>>;
export type LayoutData = Expand<Omit<LayoutParentData, keyof LayoutServerData> & EnsureDefined<LayoutServerData>>;
export type LayoutProps = { params: LayoutParams; data: LayoutData; children: import("svelte").Snippet }
export type RequestEvent = Kit.RequestEvent<RouteParams, RouteId>;
@@ -0,0 +1,11 @@
import type * as Kit from '@sveltejs/kit';
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
// @ts-ignore
type MatcherParam<M> = M extends (param : string) => param is infer U ? U extends string ? U : string : string;
type RouteParams = { slugs: string };
type RouteId = '/[...slugs]';
export type EntryGenerator = () => Promise<Array<RouteParams>> | Array<RouteParams>;
export type RequestHandler = Kit.RequestHandler<RouteParams, RouteId>;
export type RequestEvent = Kit.RequestEvent<RouteParams, RouteId>;
@@ -0,0 +1,12 @@
// @ts-nocheck
import { api } from "$lib";
import type { ActivityStandards } from "../../../services/calculator/main";
import type { LayoutServerLoad } from "./$types";
export const load = async ({ }: Parameters<LayoutServerLoad>[0]) => {
const { data: allStandardsRaw } = await api.data.standards.get();
return {
allStandardsRaw: allStandardsRaw as ActivityStandards
};
};
+27
View File
@@ -0,0 +1,27 @@
:root {
--bg: #0b0f14;
--fg: #e5e7eb;
--muted: #9ca3af;
--card: #0f141a;
--border: #1f2937;
--accent: #e5e7eb;
}
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
background: var(--bg);
color: var(--fg);
font:
14px/1.45 system-ui,
-apple-system,
Segoe UI,
Roboto,
Inter,
sans-serif;
}
+13
View File
@@ -0,0 +1,13 @@
// See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}
export {};
+11
View File
@@ -0,0 +1,11 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="107" height="128" viewBox="0 0 107 128"><title>svelte-logo</title><path d="M94.157 22.819c-10.4-14.885-30.94-19.297-45.792-9.835L22.282 29.608A29.92 29.92 0 0 0 8.764 49.65a31.5 31.5 0 0 0 3.108 20.231 30 30 0 0 0-4.477 11.183 31.9 31.9 0 0 0 5.448 24.116c10.402 14.887 30.942 19.297 45.791 9.835l26.083-16.624A29.92 29.92 0 0 0 98.235 78.35a31.53 31.53 0 0 0-3.105-20.232 30 30 0 0 0 4.474-11.182 31.88 31.88 0 0 0-5.447-24.116" style="fill:#ff3e00"/><path d="M45.817 106.582a20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.503 18 18 0 0 1 .624-2.435l.49-1.498 1.337.981a33.6 33.6 0 0 0 10.203 5.098l.97.294-.09.968a5.85 5.85 0 0 0 1.052 3.878 6.24 6.24 0 0 0 6.695 2.485 5.8 5.8 0 0 0 1.603-.704L69.27 76.28a5.43 5.43 0 0 0 2.45-3.631 5.8 5.8 0 0 0-.987-4.371 6.24 6.24 0 0 0-6.698-2.487 5.7 5.7 0 0 0-1.6.704l-9.953 6.345a19 19 0 0 1-5.296 2.326 20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.502 17.99 17.99 0 0 1 8.13-12.052l26.081-16.623a19 19 0 0 1 5.3-2.329 20.72 20.72 0 0 1 22.237 8.243 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-.624 2.435l-.49 1.498-1.337-.98a33.6 33.6 0 0 0-10.203-5.1l-.97-.294.09-.968a5.86 5.86 0 0 0-1.052-3.878 6.24 6.24 0 0 0-6.696-2.485 5.8 5.8 0 0 0-1.602.704L37.73 51.72a5.42 5.42 0 0 0-2.449 3.63 5.79 5.79 0 0 0 .986 4.372 6.24 6.24 0 0 0 6.698 2.486 5.8 5.8 0 0 0 1.602-.704l9.952-6.342a19 19 0 0 1 5.295-2.328 20.72 20.72 0 0 1 22.237 8.242 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-8.13 12.053l-26.081 16.622a19 19 0 0 1-5.3 2.328" style="fill:#fff"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+6
View File
@@ -0,0 +1,6 @@
import { treaty } from "@elysiajs/eden";
import { app, type App } from "../../../api";
const apiWrapper = treaty<App>(app);
export const api = apiWrapper.api;
+11
View File
@@ -0,0 +1,11 @@
import { api } from "$lib";
import type { ActivityStandards } from "../../../services/calculator/main";
import type { LayoutServerLoad } from "./$types";
export const load: LayoutServerLoad = async ({ }) => {
const { data: allStandardsRaw } = await api.data.standards.get();
return {
allStandardsRaw: allStandardsRaw as ActivityStandards
};
};
+12
View File
@@ -0,0 +1,12 @@
<script lang="ts">
import favicon from "$lib/assets/favicon.svg";
import "../app.css";
let { children } = $props();
</script>
<svelte:head>
<link rel="icon" href={favicon} />
</svelte:head>
{@render children?.()}
+407
View File
@@ -0,0 +1,407 @@
<script lang="ts">
import {
Standards,
type Standard,
} from "../../../services/calculator/main";
import {
Activity,
Gender,
kgToLb,
lbToKg,
msToTime,
range,
} from "../../../services/calculator/util";
// data
const { data } = $props();
const selected = $state({
activity: Activity.BenchPress,
gender: Gender.Male,
age: 18,
weight: 0,
maxLevel: 5,
});
const allStandards = $derived(
new Standards(data.allStandardsRaw, { maxLevel: selected.maxLevel }),
);
const getFormattedLevelValue = (
activity: Activity,
standard: Standard,
lvl: number,
): string => {
const rawValue = standard.levels[lvl];
const unit = allStandards.byActivity(activity).getMetadata().unit;
switch (unit) {
case "ms":
return msToTime(rawValue);
case "cm":
return String(Math.round(rawValue));
case "kg":
return String(Math.round(kgToLb(rawValue)));
default:
return "";
}
};
</script>
<div id="activityTables">
<div class="activity-section">
<div class="toolbar">
<fieldset class="group">
<legend>Metrics</legend>
<label class="field">
<span>Activity</span>
<select
class="select"
name="activities"
bind:value={selected.activity}
>
{#each Object.values(Activity) as activity}
<option value={activity}
>{allStandards
.byActivity(activity)
.getMetadata().name}</option
>
{/each}
</select>
</label>
<label class="field">
<span>Gender</span>
<select
class="select"
name="genders"
bind:value={selected.gender}
>
{#each Object.values(Gender) as gender}
<option value={gender}>{gender}</option>
{/each}
</select>
</label>
<label class="field w-20">
<span>Age</span>
<input
type="number"
min="0"
max="100"
placeholder="18"
bind:value={selected.age}
/>
</label>
<label class="field w-24">
<span>Weight (lb)</span>
<input
type="number"
min="0"
max="600"
placeholder="170"
bind:value={selected.weight}
/>
</label>
</fieldset>
<fieldset class="group">
<legend>Parameters</legend>
<label class="field w-24">
<span>Max level</span>
<input
type="number"
min="1"
max="100"
placeholder="5"
bind:value={selected.maxLevel}
/>
</label>
</fieldset>
</div>
{#if !selected.gender || !selected.age}
<p>Not enough info entered</p>
{:else}
{@render standardsTable(
selected.gender,
selected.age,
selected.weight,
)}
{/if}
</div>
</div>
{#snippet standardsTable(gender: Gender, age: number, weight: number)}
<section class="gender-section">
<div class="age-section">
<div class="standards-table">
<div class="scroll">
<table>
<thead>
<tr>
<th class="levels-th">Body weight</th>
{#each range(selected.maxLevel) as lvl}
<th class="levels-th">{lvl}</th>
{/each}
</tr>
</thead>
<tbody>
{#if weight}
{@const standard = allStandards
.byActivity(selected.activity)
.byGender(gender)
.byAge(age)
.byWeight(lbToKg(weight))
.getOneInterpolated()}
<tr>
<th scope="row"
>{Math.round(
kgToLb(standard.metrics.weight),
)}</th
>
{#each range(selected.maxLevel) as lvl}
<td
>{getFormattedLevelValue(
selected.activity,
standard,
lvl,
)}</td
>
{/each}
</tr>
{:else}
{@const standards = allStandards
.byActivity(selected.activity)
.byGender(gender)
.byAge(age)
.getAllInterpolated()}
{#each standards as standard}
<tr>
<th scope="row"
>{Math.round(
kgToLb(standard.metrics.weight),
)}</th
>
{#each range(allStandards.cfg.maxLevel) as lvl}
<td
>{getFormattedLevelValue(
selected.activity,
standard,
lvl,
)}</td
>
{/each}
</tr>
{/each}
{/if}
</tbody>
</table>
</div>
</div>
</div>
</section>
{/snippet}
<style>
#activityTables {
max-width: 1600px;
margin: 24px auto;
padding: 0 16px;
}
h1,
h2,
h3 {
line-height: 1.2;
margin: 0 0 8px;
color: var(--accent);
}
h1 {
font-size: 1.4rem;
margin-top: 24px;
}
h2 {
font-size: 1.1rem;
margin-top: 16px;
}
h3 {
font-size: 1rem;
color: var(--muted);
font-weight: 600;
}
/* Toolbar container */
.toolbar {
display: grid;
grid-template-columns: 1fr auto; /* metrics | params */
gap: 16px;
align-items: start;
}
/* Stack groups on small screens */
@media (max-width: 840px) {
.toolbar {
grid-template-columns: 1fr;
}
}
/* Group card */
.group {
margin: 0;
padding: 12px;
border: 1px solid var(--border);
background: var(--card);
display: flex;
flex-wrap: wrap;
gap: 12px 16px;
}
/* Group title */
.group > legend {
font-size: 12px;
font-weight: 700;
color: var(--muted);
padding: 0 6px;
}
/* Field (label+control) */
.field {
display: grid;
grid-template-rows: auto auto;
gap: 6px;
min-width: 160px;
}
/* Label text */
.field > span {
font-size: 12px;
font-weight: 600;
color: var(--muted);
}
/* Inputs/selects inherit your existing styles.
If you used the "select-as-title" style, keep it;
otherwise add a minimal baseline here: */
.field input[type="number"],
.field .select {
font-size: 1rem;
color: var(--fg);
background: transparent;
border: none;
border-bottom: 2px solid var(--border);
padding: 6px 0;
outline: none;
}
/* Focus */
.field input[type="number"]:focus,
.field .select:focus {
border-bottom-color: var(--accent);
}
/* Width helpers */
.w-20 {
width: 8rem;
} /* ~128px */
.w-24 {
width: 10rem;
} /* ~160px */
.activity-section {
padding: 16px;
margin: 16px 0;
background: var(--card);
border: 1px solid var(--border);
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.03);
}
.gender-section {
margin-top: 8px;
}
.age-section {
margin: 12px 0 20px;
}
.standards-table {
margin-top: 8px;
border: 1px solid var(--border);
overflow: hidden;
}
/* Horizontal scroll wrapper for very wide tables */
.standards-table > .scroll {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
/* Table */
.standards-table table {
width: max-content;
/* prevents squish; enables horizontal scroll */
min-width: 100%;
/* fill container if not too wide */
border-collapse: separate;
border-spacing: 0;
font-variant-numeric: tabular-nums;
}
.standards-table th,
.standards-table td {
padding: 6px 10px;
border-bottom: 1px solid var(--border);
border-right: 1px solid var(--border);
text-align: center;
white-space: nowrap;
}
.standards-table th:first-child,
.standards-table td:first-child {
border-left: 1px solid var(--border);
}
/* Header row */
.standards-table thead th {
position: sticky;
top: 0;
z-index: 2;
background: var(--bg);
font-weight: 700;
}
.standards-table thead th:first-child {
left: 0;
z-index: 3;
}
/* Row header (first column) */
.standards-table tbody th[scope="row"],
.standards-table tbody td:first-child {
position: sticky;
left: 0;
background: var(--card);
text-align: left;
font-weight: 600;
}
.standards-table tbody tr:nth-child(even) td {
background: rgba(0, 0, 0, 0.02);
}
.standards-table tbody tr:hover td {
background: rgba(0, 128, 255, 0.06);
}
/* Compact header for the “levels” row */
.levels-th {
font-size: 12px;
color: var(--muted);
}
</style>
@@ -0,0 +1,4 @@
import { app } from "../../../../api"
type RequestHandler = (v: { request: Request }) => Response | Promise<Response>
export const fallback: RequestHandler = ({ request }) => app.handle(request)
+3
View File
@@ -0,0 +1,3 @@
# allow crawling everything by default
User-agent: *
Disallow:
+18
View File
@@ -0,0 +1,18 @@
import adapter from "svelte-adapter-bun";
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://svelte.dev/docs/kit/integrations
// for more information about preprocessors
preprocess: vitePreprocess(),
kit: {
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
adapter: adapter(),
}
};
export default config;
+20
View File
@@ -0,0 +1,20 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"verbatimModuleSyntax": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
}
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
//
// To make changes to top-level options such as include and exclude, we recommend extending
// the generated config; see https://svelte.dev/docs/kit/configuration#typescript
}
+6
View File
@@ -0,0 +1,6 @@
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [sveltekit()]
});