From a8e01f6a747b0fe87aa3d76db6dd2e7ac771f9af Mon Sep 17 00:00:00 2001 From: Erik Beuschau Date: Mon, 22 Sep 2025 08:58:52 +0200 Subject: [PATCH 1/2] Bump Nordcraft dependencies + adjust code --- README.md | 4 + bun.lock | 216 ++++++----- hono.d.ts | 5 +- package.json | 26 +- src/index.ts | 37 +- src/routes/apiProxy.ts | 74 +++- .../{toddlePage.ts => nordcraftPage.ts} | 160 ++++---- src/routes/notFoundLoader.ts | 18 + src/routes/pageHandler.ts | 27 ++ src/routes/routeHandler.ts | 77 ++-- src/utils/api.ts | 356 ++++++++++++++++++ 11 files changed, 769 insertions(+), 231 deletions(-) rename src/routes/{toddlePage.ts => nordcraftPage.ts} (59%) create mode 100644 src/routes/notFoundLoader.ts create mode 100644 src/routes/pageHandler.ts create mode 100644 src/utils/api.ts diff --git a/README.md b/README.md index 6ee628d..c11e5eb 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ ## Cloudflare example application +This example will not always be up to date with the latest Nordcraft features. Please refer to the [Nordcraft repository](https://github.com/nordcraftengine/nordcraft) for the most accurate and up-to-date information. + +Learn more about Nordcraft [here](https://nordcraft.com), and visit our [documentation](https://docs.nordcraft.com) for more information. + ### Install ```sh diff --git a/bun.lock b/bun.lock index 5f6c955..4e2b71c 100644 --- a/bun.lock +++ b/bun.lock @@ -3,115 +3,113 @@ "workspaces": { "": { "dependencies": { - "@nordcraft/core": "1.0.1", - "@nordcraft/ssr": "1.0.1", - "hono": "4.7.7", + "@nordcraft/core": "1.0.48", + "@nordcraft/ssr": "1.0.48", + "hono": "4.9.8", }, "devDependencies": { - "@cloudflare/workers-types": "4.20250424.0", - "@eslint/js": "9.25.1", - "@nordcraft/runtime": "1.0.1", - "@typescript-eslint/eslint-plugin": "8.31.0", - "@typescript-eslint/parser": "8.31.0", - "eslint": "9.25.1", + "@cloudflare/workers-types": "4.20250922.0", + "@eslint/js": "9.36.0", + "@nordcraft/runtime": "1.0.48", + "@typescript-eslint/eslint-plugin": "8.44.0", + "@typescript-eslint/parser": "8.44.0", + "eslint": "9.36.0", "eslint-plugin-inclusive-language": "2.2.1", - "prettier": "3.5.3", - "prettier-plugin-organize-imports": "4.1.0", - "typescript": "5.8.3", - "wrangler": "4.13.0", + "prettier": "3.6.2", + "prettier-plugin-organize-imports": "4.3.0", + "typescript": "5.9.2", + "wrangler": "4.38.0", }, }, }, "packages": { "@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.4.0", "", { "dependencies": { "mime": "^3.0.0" } }, "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA=="], - "@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.3.1", "", { "peerDependencies": { "unenv": "2.0.0-rc.15", "workerd": "^1.20250320.0" }, "optionalPeers": ["workerd"] }, "sha512-Xq57Qd+ADpt6hibcVBO0uLG9zzRgyRhfCUgBT9s+g3+3Ivg5zDyVgLFy40ES1VdNcu8rPNSivm9A+kGP5IVaPg=="], + "@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.7.4", "", { "peerDependencies": { "unenv": "2.0.0-rc.21", "workerd": "^1.20250912.0" }, "optionalPeers": ["workerd"] }, "sha512-KIjbu/Dt50zseJIoOOK5y4eYpSojD9+xxkePYVK1Rg9k/p/st4YyMtz1Clju/zrenJHrOH+AAcjNArOPMwH4Bw=="], - "@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20250422.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-2FWl8TLpC4Knuyw8GmNgUSoJCNJNNGJ7Xv90j2n8FiXR5Clp9jSpm2ovK8RP9P751yX1/iIp8e7QufR/XDB6ow=="], + "@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20250917.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-0kL/kFnKUSycoo7b3PgM0nRyZ+1MGQAKaXtE6a2+SAeUkZ2FLnuFWmASi0s4rlWGsf/rlTw4AwXROePir9dUcQ=="], - "@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20250422.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-GY3W74ivqxsYldacEbMtcSbG7LsS9hPo5UybKIw4RO9GzP7UC5WGnPfuI4PE2SnJOnw7nwSrBLuhGRPe/QQHkQ=="], + "@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20250917.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-3/N1QmEJsC8Byxt1SGgVp5o0r+eKjuUEMbIL2yzLk/jrMdErPXy/DGf/tXZoACU68a/gMEbbT1itkYrm85iQHg=="], - "@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20250422.0", "", { "os": "linux", "cpu": "x64" }, "sha512-mtNkEygKtlRq9pMRlm9J4nX4uVHU1AtJ3mSkdNwPwhisTpo989O5Zd0SH9CYwAk8+NmlZsXELpODUVQxQ7FJgw=="], + "@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20250917.0", "", { "os": "linux", "cpu": "x64" }, "sha512-E7sEow7CErbWY3olMmlbj6iss9r7Xb2uMyc+MKzYC9/J6yFlJd/dNHvjey9QIdxzbkC9qGe90a+KxQrjs+fspA=="], - "@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20250422.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-ILlW4/kAoFJvSryrr/QJsiHBdMTf/fjUrIM0hxeuQue8zIEvAVqM1tzpUh8bPJT6AQEbk5ziwkfucA939Z6Tnw=="], + "@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20250917.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-roOnRjxut2FUxo6HA9spbfs32naXAsnSQqsgku3iq6BYKv1QqGiFoY5bReK72N5uxmhxo7+RiTo8ZEkxA/vMIQ=="], - "@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20250422.0", "", { "os": "win32", "cpu": "x64" }, "sha512-O2f6f7oxU/oaWX/3/5d/9qvzNSKsw72RsQFjpew2va7KwnnUciI2LnbYR6KYOqRGYrEoiMJxpWPQaYaFVj8t1w=="], + "@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20250917.0", "", { "os": "win32", "cpu": "x64" }, "sha512-gslh6Ou9+kshHjR1BJX47OsbPw3/cZCvGDompvaW/URCgr7aMzljbgmBb7p0uhwGy1qCXcIt31St6pd3IEcLng=="], - "@cloudflare/workers-types": ["@cloudflare/workers-types@4.20250424.0", "", {}, "sha512-tolHPBVlYSIZq5GWlGbbSqXg1P79u059YJ19cFULwRCF/KpElb9YDq/D9oPxqpw/niS9AvzVBCR5RCxsWv4LDQ=="], + "@cloudflare/workers-types": ["@cloudflare/workers-types@4.20250922.0", "", {}, "sha512-BaqlKnVc0Xzqm9xt3TC4v0yB9EHy5vVqpiWz+DAsbEmdcpUbqdBschvI9502p6FgFbZElD7XcxTEeViXLsoO0A=="], "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], "@emnapi/runtime": ["@emnapi/runtime@1.3.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw=="], - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag=="], + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q=="], - "@esbuild/android-arm": ["@esbuild/android-arm@0.25.2", "", { "os": "android", "cpu": "arm" }, "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA=="], + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.4", "", { "os": "android", "cpu": "arm" }, "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ=="], - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.2", "", { "os": "android", "cpu": "arm64" }, "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w=="], + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.4", "", { "os": "android", "cpu": "arm64" }, "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A=="], - "@esbuild/android-x64": ["@esbuild/android-x64@0.25.2", "", { "os": "android", "cpu": "x64" }, "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg=="], + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.4", "", { "os": "android", "cpu": "x64" }, "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ=="], - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA=="], + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g=="], - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA=="], + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A=="], - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w=="], + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ=="], - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ=="], + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ=="], - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.2", "", { "os": "linux", "cpu": "arm" }, "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g=="], + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.4", "", { "os": "linux", "cpu": "arm" }, "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ=="], - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g=="], + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ=="], - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ=="], + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.4", "", { "os": "linux", "cpu": "ia32" }, "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ=="], - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.2", "", { "os": "linux", "cpu": "none" }, "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w=="], + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.4", "", { "os": "linux", "cpu": "none" }, "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA=="], - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.2", "", { "os": "linux", "cpu": "none" }, "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q=="], + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.4", "", { "os": "linux", "cpu": "none" }, "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg=="], - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g=="], + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag=="], - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.2", "", { "os": "linux", "cpu": "none" }, "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw=="], + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.4", "", { "os": "linux", "cpu": "none" }, "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA=="], - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q=="], + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g=="], - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.2", "", { "os": "linux", "cpu": "x64" }, "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg=="], + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.4", "", { "os": "linux", "cpu": "x64" }, "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA=="], - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.2", "", { "os": "none", "cpu": "arm64" }, "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw=="], + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.4", "", { "os": "none", "cpu": "arm64" }, "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ=="], - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.2", "", { "os": "none", "cpu": "x64" }, "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg=="], + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.4", "", { "os": "none", "cpu": "x64" }, "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw=="], - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg=="], + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.4", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A=="], - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw=="], + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw=="], - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA=="], + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.4", "", { "os": "sunos", "cpu": "x64" }, "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q=="], - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q=="], + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ=="], - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg=="], + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg=="], - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.2", "", { "os": "win32", "cpu": "x64" }, "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA=="], + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.4", "", { "os": "win32", "cpu": "x64" }, "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ=="], - "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.5.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-RoV8Xs9eNwiDvhv7M+xcL4PWyRyIXRY/FLp3buU4h1EYfdF7unWUy3dOjPqb3C7rMUewIcqwW850PgS8h1o1yg=="], + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g=="], "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], - "@eslint/config-array": ["@eslint/config-array@0.20.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ=="], + "@eslint/config-array": ["@eslint/config-array@0.21.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ=="], - "@eslint/config-helpers": ["@eslint/config-helpers@0.2.1", "", {}, "sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw=="], + "@eslint/config-helpers": ["@eslint/config-helpers@0.3.1", "", {}, "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA=="], - "@eslint/core": ["@eslint/core@0.13.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw=="], + "@eslint/core": ["@eslint/core@0.15.2", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg=="], "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="], - "@eslint/js": ["@eslint/js@9.25.1", "", {}, "sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg=="], + "@eslint/js": ["@eslint/js@9.36.0", "", {}, "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw=="], "@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="], - "@eslint/plugin-kit": ["@eslint/plugin-kit@0.2.8", "", { "dependencies": { "@eslint/core": "^0.13.0", "levn": "^0.4.1" } }, "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA=="], - - "@fastify/busboy": ["@fastify/busboy@2.1.1", "", {}, "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA=="], + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.5", "", { "dependencies": { "@eslint/core": "^0.15.2", "levn": "^0.4.1" } }, "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w=="], "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], @@ -171,35 +169,49 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - "@nordcraft/core": ["@nordcraft/core@1.0.1", "", {}, "sha512-h1b8jMR8kFqTmpj+Tg4vQ5Dju6YmImGIqv4vzCGym0iyq4OOFv7M26lPKq/WRdL4RP9F/nwlCyvIpkrHBxqA4A=="], + "@nordcraft/core": ["@nordcraft/core@1.0.48", "", {}, "sha512-fqCuBOomefi4nyxMBgfjfFTLNdqB1TOLq1+cuZ6tivRQ7KbocJicVmoOxySzpTNaka5KFtiBYWjqzq3V1Iswrw=="], + + "@nordcraft/runtime": ["@nordcraft/runtime@1.0.48", "", { "dependencies": { "@nordcraft/core": "1.0.48", "@nordcraft/std-lib": "1.0.48", "fast-deep-equal": "3.1.3", "path-to-regexp": "6.3.0" } }, "sha512-Gg68Jvnm+vTCa0zX13/dUajDb2dueRr35KIayLo0mwXFyq1qv+rT+C1RzFAt6T63D0M3nQ7nUg4rpcvdbeTdIQ=="], + + "@nordcraft/ssr": ["@nordcraft/ssr@1.0.48", "", { "dependencies": { "@nordcraft/core": "1.0.48", "@nordcraft/std-lib": "1.0.48", "cookie": "1.0.2", "xss": "1.0.15" } }, "sha512-Fpo39v4DErLnDyPEO+FTSl6mGC3f4rtQOch7ayxclSIuX0cNajaBIKTQCG215w4kXwJ+aTNi+K4Ycf/hS7SI7Q=="], + + "@nordcraft/std-lib": ["@nordcraft/std-lib@1.0.48", "", { "dependencies": { "@nordcraft/core": "1.0.48", "fast-deep-equal": "3.1.3" } }, "sha512-BN5+Fg7UJ8GDXFttXV1X+zm/lDBK7YWsp5tT4C56UOJeeWnBJrzNZFbyqNwvbXBk/ajQ+eslIhXkP61XwsbSCQ=="], + + "@poppinss/colors": ["@poppinss/colors@4.1.5", "", { "dependencies": { "kleur": "^4.1.5" } }, "sha512-FvdDqtcRCtz6hThExcFOgW0cWX+xwSMWcRuQe5ZEb2m7cVQOAVZOIMt+/v9RxGiD9/OY16qJBXK4CVKWAPalBw=="], + + "@poppinss/dumper": ["@poppinss/dumper@0.6.4", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@sindresorhus/is": "^7.0.2", "supports-color": "^10.0.0" } }, "sha512-iG0TIdqv8xJ3Lt9O8DrPRxw1MRLjNpoqiSGU03P/wNLP/s0ra0udPJ1J2Tx5M0J3H/cVyEgpbn8xUKRY9j59kQ=="], - "@nordcraft/runtime": ["@nordcraft/runtime@1.0.1", "", { "dependencies": { "@nordcraft/core": "1.0.1", "@nordcraft/std-lib": "1.0.1", "fast-deep-equal": "3.1.3", "path-to-regexp": "6.3.0" } }, "sha512-n0Y3Vbzpq3oFGkg3nXdP2ndUC4qFLZkY7R8UgrJim0OHzR9TC7NMyZQC7OcTAf5ZFn4MEHXC2sG9crL9Ibz2MQ=="], + "@poppinss/exception": ["@poppinss/exception@1.2.2", "", {}, "sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg=="], - "@nordcraft/ssr": ["@nordcraft/ssr@1.0.1", "", { "dependencies": { "@nordcraft/core": "1.0.1", "@nordcraft/std-lib": "1.0.1", "cookie": "1.0.2", "xss": "1.0.15" } }, "sha512-zUG8l21mgJIPbwrcdd9CJhnXkMvdqOlDQm2LKpSGdTyEBctP0vx1h93l0suUra9Fy9JdHj3Trfs9SU+fGh3kqA=="], + "@sindresorhus/is": ["@sindresorhus/is@7.1.0", "", {}, "sha512-7F/yz2IphV39hiS2zB4QYVkivrptHHh0K8qJJd9HhuWSdvf8AN7NpebW3CcDZDBQsUPMoDKWsY2WWgW7bqOcfA=="], - "@nordcraft/std-lib": ["@nordcraft/std-lib@1.0.1", "", { "dependencies": { "@nordcraft/core": "1.0.1", "fast-deep-equal": "3.1.3" } }, "sha512-V0jk5defK9OScy7Zu3kSiVqslmEqIblqqsHS4cfxs8EVogxM2DDBlIRfvAdJTQfntYCE/hWJbUg/EzLsecD0rg=="], + "@speed-highlight/core": ["@speed-highlight/core@1.2.7", "", {}, "sha512-0dxmVj4gxg3Jg879kvFS/msl4s9F3T9UXC1InxgOf7t5NvcPD97u/WTA5vL/IxWHMn7qSxBozqrnnE2wvl1m8g=="], "@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.31.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.31.0", "@typescript-eslint/type-utils": "8.31.0", "@typescript-eslint/utils": "8.31.0", "@typescript-eslint/visitor-keys": "8.31.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-evaQJZ/J/S4wisevDvC1KFZkPzRetH8kYZbkgcTRyql3mcKsf+ZFDV1BVWUGTCAW5pQHoqn5gK5b8kn7ou9aFQ=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.44.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.44.0", "@typescript-eslint/type-utils": "8.44.0", "@typescript-eslint/utils": "8.44.0", "@typescript-eslint/visitor-keys": "8.44.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.44.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-EGDAOGX+uwwekcS0iyxVDmRV9HX6FLSM5kzrAToLTsr9OWCIKG/y3lQheCq18yZ5Xh78rRKJiEpP0ZaCs4ryOQ=="], - "@typescript-eslint/parser": ["@typescript-eslint/parser@8.31.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.31.0", "@typescript-eslint/types": "8.31.0", "@typescript-eslint/typescript-estree": "8.31.0", "@typescript-eslint/visitor-keys": "8.31.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-67kYYShjBR0jNI5vsf/c3WG4u+zDnCTHTPqVMQguffaWWFs7artgwKmfwdifl+r6XyM5LYLas/dInj2T0SgJyw=="], + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.44.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.44.0", "@typescript-eslint/types": "8.44.0", "@typescript-eslint/typescript-estree": "8.44.0", "@typescript-eslint/visitor-keys": "8.44.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-VGMpFQGUQWYT9LfnPcX8ouFojyrZ/2w3K5BucvxL/spdNehccKhB4jUyB1yBCXpr2XFm0jkECxgrpXBW2ipoAw=="], - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.31.0", "", { "dependencies": { "@typescript-eslint/types": "8.31.0", "@typescript-eslint/visitor-keys": "8.31.0" } }, "sha512-knO8UyF78Nt8O/B64i7TlGXod69ko7z6vJD9uhSlm0qkAbGeRUSudcm0+K/4CrRjrpiHfBCjMWlc08Vav1xwcw=="], + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.44.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.44.0", "@typescript-eslint/types": "^8.44.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ZeaGNraRsq10GuEohKTo4295Z/SuGcSq2LzfGlqiuEvfArzo/VRrT0ZaJsVPuKZ55lVbNk8U6FcL+ZMH8CoyVA=="], - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.31.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.31.0", "@typescript-eslint/utils": "8.31.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-DJ1N1GdjI7IS7uRlzJuEDCgDQix3ZVYVtgeWEyhyn4iaoitpMBX6Ndd488mXSx0xah/cONAkEaYyylDyAeHMHg=="], + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.44.0", "", { "dependencies": { "@typescript-eslint/types": "8.44.0", "@typescript-eslint/visitor-keys": "8.44.0" } }, "sha512-87Jv3E+al8wpD+rIdVJm/ItDBe/Im09zXIjFoipOjr5gHUhJmTzfFLuTJ/nPTMc2Srsroy4IBXwcTCHyRR7KzA=="], - "@typescript-eslint/types": ["@typescript-eslint/types@8.31.0", "", {}, "sha512-Ch8oSjVyYyJxPQk8pMiP2FFGYatqXQfQIaMp+TpuuLlDachRWpUAeEu1u9B/v/8LToehUIWyiKcA/w5hUFRKuQ=="], + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.44.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-x5Y0+AuEPqAInc6yd0n5DAcvtoQ/vyaGwuX5HE9n6qAefk1GaedqrLQF8kQGylLUb9pnZyLf+iEiL9fr8APDtQ=="], - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.31.0", "", { "dependencies": { "@typescript-eslint/types": "8.31.0", "@typescript-eslint/visitor-keys": "8.31.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-xLmgn4Yl46xi6aDSZ9KkyfhhtnYI15/CvHbpOy/eR5NWhK/BK8wc709KKwhAR0m4ZKRP7h07bm4BWUYOCuRpQQ=="], + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.44.0", "", { "dependencies": { "@typescript-eslint/types": "8.44.0", "@typescript-eslint/typescript-estree": "8.44.0", "@typescript-eslint/utils": "8.44.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-9cwsoSxJ8Sak67Be/hD2RNt/fsqmWnNE1iHohG8lxqLSNY8xNfyY7wloo5zpW3Nu9hxVgURevqfcH6vvKCt6yg=="], - "@typescript-eslint/utils": ["@typescript-eslint/utils@8.31.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.31.0", "@typescript-eslint/types": "8.31.0", "@typescript-eslint/typescript-estree": "8.31.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-qi6uPLt9cjTFxAb1zGNgTob4x9ur7xC6mHQJ8GwEzGMGE9tYniublmJaowOJ9V2jUzxrltTPfdG2nKlWsq0+Ww=="], + "@typescript-eslint/types": ["@typescript-eslint/types@8.44.0", "", {}, "sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA=="], - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.31.0", "", { "dependencies": { "@typescript-eslint/types": "8.31.0", "eslint-visitor-keys": "^4.2.0" } }, "sha512-QcGHmlRHWOl93o64ZUMNewCdwKGU6WItOU52H0djgNmn1EOrhVudrDzXz4OycCRSCPwFCDrE2iIt5vmuUdHxuQ=="], + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.44.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.44.0", "@typescript-eslint/tsconfig-utils": "8.44.0", "@typescript-eslint/types": "8.44.0", "@typescript-eslint/visitor-keys": "8.44.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-lqNj6SgnGcQZwL4/SBJ3xdPEfcBuhCG8zdcwCPgYcmiPLgokiNDKlbPzCwEwu7m279J/lBYWtDYL+87OEfn8Jw=="], - "acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.44.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.44.0", "@typescript-eslint/types": "8.44.0", "@typescript-eslint/typescript-estree": "8.44.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-nktOlVcg3ALo0mYlV+L7sWUD58KG4CMj1rb2HUVOO4aL3K/6wcD+NERqd0rrA5Vg06b42YhF6cFxeixsp9Riqg=="], + + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.44.0", "", { "dependencies": { "@typescript-eslint/types": "8.44.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-zaz9u8EJ4GBmnehlrpoKvj/E3dNbuQ7q0ucyZImm3cLqJ8INTc970B1qEqDX/Rzq65r3TvVTN7kHWPBoyW7DWw=="], + + "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], @@ -211,8 +223,6 @@ "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - "as-table": ["as-table@1.0.55", "", { "dependencies": { "printable-characters": "^1.0.42" } }, "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ=="], - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="], @@ -243,8 +253,6 @@ "cssfilter": ["cssfilter@0.0.10", "", {}, "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw=="], - "data-uri-to-buffer": ["data-uri-to-buffer@2.0.2", "", {}, "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA=="], - "debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="], "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], @@ -253,19 +261,21 @@ "detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="], - "esbuild": ["esbuild@0.25.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.2", "@esbuild/android-arm": "0.25.2", "@esbuild/android-arm64": "0.25.2", "@esbuild/android-x64": "0.25.2", "@esbuild/darwin-arm64": "0.25.2", "@esbuild/darwin-x64": "0.25.2", "@esbuild/freebsd-arm64": "0.25.2", "@esbuild/freebsd-x64": "0.25.2", "@esbuild/linux-arm": "0.25.2", "@esbuild/linux-arm64": "0.25.2", "@esbuild/linux-ia32": "0.25.2", "@esbuild/linux-loong64": "0.25.2", "@esbuild/linux-mips64el": "0.25.2", "@esbuild/linux-ppc64": "0.25.2", "@esbuild/linux-riscv64": "0.25.2", "@esbuild/linux-s390x": "0.25.2", "@esbuild/linux-x64": "0.25.2", "@esbuild/netbsd-arm64": "0.25.2", "@esbuild/netbsd-x64": "0.25.2", "@esbuild/openbsd-arm64": "0.25.2", "@esbuild/openbsd-x64": "0.25.2", "@esbuild/sunos-x64": "0.25.2", "@esbuild/win32-arm64": "0.25.2", "@esbuild/win32-ia32": "0.25.2", "@esbuild/win32-x64": "0.25.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ=="], + "error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="], + + "esbuild": ["esbuild@0.25.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.4", "@esbuild/android-arm": "0.25.4", "@esbuild/android-arm64": "0.25.4", "@esbuild/android-x64": "0.25.4", "@esbuild/darwin-arm64": "0.25.4", "@esbuild/darwin-x64": "0.25.4", "@esbuild/freebsd-arm64": "0.25.4", "@esbuild/freebsd-x64": "0.25.4", "@esbuild/linux-arm": "0.25.4", "@esbuild/linux-arm64": "0.25.4", "@esbuild/linux-ia32": "0.25.4", "@esbuild/linux-loong64": "0.25.4", "@esbuild/linux-mips64el": "0.25.4", "@esbuild/linux-ppc64": "0.25.4", "@esbuild/linux-riscv64": "0.25.4", "@esbuild/linux-s390x": "0.25.4", "@esbuild/linux-x64": "0.25.4", "@esbuild/netbsd-arm64": "0.25.4", "@esbuild/netbsd-x64": "0.25.4", "@esbuild/openbsd-arm64": "0.25.4", "@esbuild/openbsd-x64": "0.25.4", "@esbuild/sunos-x64": "0.25.4", "@esbuild/win32-arm64": "0.25.4", "@esbuild/win32-ia32": "0.25.4", "@esbuild/win32-x64": "0.25.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q=="], "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - "eslint": ["eslint@9.25.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.20.0", "@eslint/config-helpers": "^0.2.1", "@eslint/core": "^0.13.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.25.1", "@eslint/plugin-kit": "^0.2.8", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.3.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ=="], + "eslint": ["eslint@9.36.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.36.0", "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ=="], "eslint-plugin-inclusive-language": ["eslint-plugin-inclusive-language@2.2.1", "", { "dependencies": { "humps": "^2.0.1" } }, "sha512-RL6avDWXCS0Dcp9axhvHRUp65qG07qjOrh6J4BNNahPvRY3PuYGnAd0H1strZ9cob79JiEW4Bq0j3gEuzbv0/A=="], - "eslint-scope": ["eslint-scope@8.3.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ=="], + "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], - "eslint-visitor-keys": ["eslint-visitor-keys@4.2.0", "", {}, "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw=="], + "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], - "espree": ["espree@10.3.0", "", { "dependencies": { "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.0" } }, "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg=="], + "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], @@ -277,7 +287,7 @@ "exit-hook": ["exit-hook@2.2.1", "", {}, "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw=="], - "exsolve": ["exsolve@1.0.4", "", {}, "sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw=="], + "exsolve": ["exsolve@1.0.7", "", {}, "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw=="], "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], @@ -301,8 +311,6 @@ "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - "get-source": ["get-source@2.0.12", "", { "dependencies": { "data-uri-to-buffer": "^2.0.0", "source-map": "^0.6.1" } }, "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w=="], - "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], "glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="], @@ -313,11 +321,11 @@ "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - "hono": ["hono@4.7.7", "", {}, "sha512-2PCpQRbN87Crty8/L/7akZN3UyZIAopSoRxCwRbJgUuV1+MHNFHzYFxZTg4v/03cXUm+jce/qa2VSBZpKBm3Qw=="], + "hono": ["hono@4.9.8", "", {}, "sha512-JW8Bb4RFWD9iOKxg5PbUarBYGM99IcxFl2FPBo2gSJO11jjUDqlP1Bmfyqt8Z/dGhIQ63PMA9LdcLefXyIasyg=="], "humps": ["humps@2.0.1", "", {}, "sha512-E0eIbrFWUhwfXJmsbdjRQFQPrl5pTEoKlz163j1mTqqUnU9PgR4AgB8AIITzuB3vLBdxZXyZ9TDIrwB2OASz4g=="], - "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + "ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], @@ -343,6 +351,8 @@ "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], @@ -355,14 +365,12 @@ "mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="], - "miniflare": ["miniflare@4.20250422.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "stoppable": "1.1.0", "undici": "^5.28.5", "workerd": "1.20250422.0", "ws": "8.18.0", "youch": "3.3.4", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-3frXK9EZEWQkHMDyppeIbUKwd7OQkNOm2gBtQQzjQ4gtzQmh+yxkyJiiylf+fGbz86djQTLKKQdQ1FC4yM3AMg=="], + "miniflare": ["miniflare@4.20250917.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "7.14.0", "workerd": "1.20250917.0", "ws": "8.18.0", "youch": "4.1.0-beta.10", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-A7kYEc/Y6ohiiTji4W/qGJj3aJNc/9IMj/6wLy2phD/iMjcoY8t35654gR5mHbMx0AgUolDdr3HOsHB0cYBf+Q=="], "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - "mustache": ["mustache@4.2.0", "", { "bin": { "mustache": "bin/mustache" } }, "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ=="], - "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], "ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], @@ -387,11 +395,9 @@ "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], - "prettier": ["prettier@3.5.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw=="], - - "prettier-plugin-organize-imports": ["prettier-plugin-organize-imports@4.1.0", "", { "peerDependencies": { "prettier": ">=2.0", "typescript": ">=2.9", "vue-tsc": "^2.1.0" }, "optionalPeers": ["vue-tsc"] }, "sha512-5aWRdCgv645xaa58X8lOxzZoiHAldAPChljr/MT0crXVOWTZ+Svl4hIWlz+niYSlO6ikE5UXkN1JrRvIP2ut0A=="], + "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], - "printable-characters": ["printable-characters@1.0.42", "", {}, "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ=="], + "prettier-plugin-organize-imports": ["prettier-plugin-organize-imports@4.3.0", "", { "peerDependencies": { "prettier": ">=2.0", "typescript": ">=2.9", "vue-tsc": "^2.1.0 || 3" }, "optionalPeers": ["vue-tsc"] }, "sha512-FxFz0qFhyBsGdIsb697f/EkvHzi5SZOhWAjxcx2dLt+Q532bAlhswcXGYB1yzjZ69kW8UoadFBw7TyNwlq96Iw=="], "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], @@ -413,10 +419,6 @@ "simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="], - "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - - "stacktracey": ["stacktracey@2.1.8", "", { "dependencies": { "as-table": "^1.0.36", "get-source": "^2.0.12" } }, "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw=="], - "stoppable": ["stoppable@1.1.0", "", {}, "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw=="], "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], @@ -425,19 +427,19 @@ "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], - "ts-api-utils": ["ts-api-utils@2.0.1", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w=="], + "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], - "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], + "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], - "ufo": ["ufo@1.5.4", "", {}, "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ=="], + "ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="], - "undici": ["undici@5.28.5", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA=="], + "undici": ["undici@7.14.0", "", {}, "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ=="], - "unenv": ["unenv@2.0.0-rc.15", "", { "dependencies": { "defu": "^6.1.4", "exsolve": "^1.0.4", "ohash": "^2.0.11", "pathe": "^2.0.3", "ufo": "^1.5.4" } }, "sha512-J/rEIZU8w6FOfLNz/hNKsnY+fFHWnu9MH4yRbSZF3xbbGHovcetXPs7sD+9p8L6CeNC//I9bhRYAOsBt2u7/OA=="], + "unenv": ["unenv@2.0.0-rc.21", "", { "dependencies": { "defu": "^6.1.4", "exsolve": "^1.0.7", "ohash": "^2.0.11", "pathe": "^2.0.3", "ufo": "^1.6.1" } }, "sha512-Wj7/AMtE9MRnAXa6Su3Lk0LNCfqDYgfwVjwRFVum9U7wsto1imuHqk4kTm7Jni+5A0Hn7dttL6O/zjvUvoo+8A=="], "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], @@ -445,9 +447,9 @@ "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], - "workerd": ["workerd@1.20250422.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250422.0", "@cloudflare/workerd-darwin-arm64": "1.20250422.0", "@cloudflare/workerd-linux-64": "1.20250422.0", "@cloudflare/workerd-linux-arm64": "1.20250422.0", "@cloudflare/workerd-windows-64": "1.20250422.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-q3ws6MIa9GJQqq1Q52qoD7vCx1203fjKNPmtRV1vvplrsfYphjr5pOAnZGUODFB1BnsDWypr71Luy7OonT0vug=="], + "workerd": ["workerd@1.20250917.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250917.0", "@cloudflare/workerd-darwin-arm64": "1.20250917.0", "@cloudflare/workerd-linux-64": "1.20250917.0", "@cloudflare/workerd-linux-arm64": "1.20250917.0", "@cloudflare/workerd-windows-64": "1.20250917.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-0D+wWaccyYQb2Zx2DZDC77YDn9kOpkpGMCgyKgIHilghut5hBQ/adUIEseS4iuIZxBPeFSn6zFtICP0SxZ3z0g=="], - "wrangler": ["wrangler@4.13.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.0", "@cloudflare/unenv-preset": "2.3.1", "blake3-wasm": "2.1.5", "esbuild": "0.25.2", "miniflare": "4.20250422.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.15", "workerd": "1.20250422.0" }, "optionalDependencies": { "fsevents": "~2.3.2", "sharp": "^0.33.5" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20250422.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-CVRNL0unLmzhVeUkW+9neZHFITSo7UDROz8VYxi8YhitV9Rr1xMojS1cGjQTaQX8F3nAEsTRJXTwwTZ0JoJm6g=="], + "wrangler": ["wrangler@4.38.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.0", "@cloudflare/unenv-preset": "2.7.4", "blake3-wasm": "2.1.5", "esbuild": "0.25.4", "miniflare": "4.20250917.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.21", "workerd": "1.20250917.0" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20250917.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-ITL4VZ4KWs8LMDEttDTrAKLktwtv1NxHBd5QIqHOczvcjnAQr+GQoE6XYQws+w8jlOjDV7KyvbFqAdyRh5om3g=="], "ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], @@ -455,19 +457,33 @@ "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], - "youch": ["youch@3.3.4", "", { "dependencies": { "cookie": "^0.7.1", "mustache": "^4.2.0", "stacktracey": "^2.1.8" } }, "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg=="], + "youch": ["youch@4.1.0-beta.10", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@poppinss/dumper": "^0.6.4", "@speed-highlight/core": "^1.2.7", "cookie": "^1.0.2", "youch-core": "^0.3.3" } }, "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ=="], + + "youch-core": ["youch-core@0.3.3", "", { "dependencies": { "@poppinss/exception": "^1.2.2", "error-stack-parser-es": "^1.0.5" } }, "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA=="], "zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="], "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "@eslint/eslintrc/espree": ["espree@10.3.0", "", { "dependencies": { "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.0" } }, "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg=="], + + "@eslint/eslintrc/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], + "@poppinss/dumper/supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], + "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "eslint/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - "youch/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], + "miniflare/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], + + "@eslint/eslintrc/espree/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], + + "@eslint/eslintrc/espree/eslint-visitor-keys": ["eslint-visitor-keys@4.2.0", "", {}, "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw=="], "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], } diff --git a/hono.d.ts b/hono.d.ts index 2f26601..00ae55a 100644 --- a/hono.d.ts +++ b/hono.d.ts @@ -2,6 +2,9 @@ import type { ProjectFiles, ToddleProject } from '@nordcraft/ssr/dist/ssr.types' export interface HonoEnv { Variables: { - project: { files: ProjectFiles; project: ToddleProject } + project: { + files: ProjectFiles & { customCode: boolean } + project: ToddleProject + } } } diff --git a/package.json b/package.json index 4e3ac61..085a068 100644 --- a/package.json +++ b/package.json @@ -12,21 +12,21 @@ "prettier:write": "prettier --write '*.{json,js}' './**/*.{js,ts}'" }, "dependencies": { - "@nordcraft/core": "1.0.1", - "@nordcraft/ssr": "1.0.1", - "hono": "4.7.7" + "@nordcraft/core": "1.0.48", + "@nordcraft/ssr": "1.0.48", + "hono": "4.9.8" }, "devDependencies": { - "@cloudflare/workers-types": "4.20250424.0", - "@eslint/js": "9.25.1", - "@nordcraft/runtime": "1.0.1", - "@typescript-eslint/eslint-plugin": "8.31.0", - "@typescript-eslint/parser": "8.31.0", + "@cloudflare/workers-types": "4.20250922.0", + "@eslint/js": "9.36.0", + "@nordcraft/runtime": "1.0.48", + "@typescript-eslint/eslint-plugin": "8.44.0", + "@typescript-eslint/parser": "8.44.0", "eslint-plugin-inclusive-language": "2.2.1", - "eslint": "9.25.1", - "prettier-plugin-organize-imports": "4.1.0", - "prettier": "3.5.3", - "typescript": "5.8.3", - "wrangler": "4.13.0" + "eslint": "9.36.0", + "prettier-plugin-organize-imports": "4.3.0", + "prettier": "3.6.2", + "typescript": "5.9.2", + "wrangler": "4.38.0" } } diff --git a/src/index.ts b/src/index.ts index fe97292..983e55e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ import { initIsEqual } from '@nordcraft/ssr/dist/rendering/equals' import type { ProjectFiles, ToddleProject } from '@nordcraft/ssr/dist/ssr.types' import { Hono } from 'hono' +import { poweredBy } from 'hono/powered-by' import type { HonoEnv } from '../hono' import { proxyRequestHandler } from './routes/apiProxy' import { customCode } from './routes/customCode' @@ -8,30 +9,35 @@ import { customElement } from './routes/customElement' import { favicon } from './routes/favicon' import { fontRouter } from './routes/font' import { manifest } from './routes/manifest' +import { notFoundLoader } from './routes/notFoundLoader' +import { pageHandler } from './routes/pageHandler' import { robots } from './routes/robots' +import { routeHandler } from './routes/routeHandler' import { serviceWorker } from './routes/serviceWorker' import { sitemap } from './routes/sitemap' import { stylesheetHandler } from './routes/stylesheetHandler' -import { toddlePage } from './routes/toddlePage' // Inject isEqual on globalThis // this is currently used by some builtin formulas initIsEqual() const app = new Hono() +app.use(poweredBy({ serverName: 'Nordcraft' })) // 🌲🌲🌲 // Keep the project reference in memory for future requests -let project: { files: ProjectFiles; project: ToddleProject } +let project: + | { + files: ProjectFiles & { customCode: boolean } + project: ToddleProject + } + | undefined // Load the project onto context to make it easier to use for other routes app.use(async (c, next) => { if (!project) { const path = `./project.json` try { const content = await import(path) - project = JSON.parse(content.default) as { - files: ProjectFiles - project: ToddleProject - } + project = JSON.parse(content.default) } catch (e) { console.error( 'Unable to load project.json', @@ -46,12 +52,6 @@ app.use(async (c, next) => { return next() }) -app.get('/sitemap.xml', sitemap) -app.get('/robots.txt', robots) -app.get('/manifest.json', manifest) -app.get('/favicon.ico', favicon) -app.get('/serviceWorker.js', serviceWorker) - // Nordcraft specific endpoints/services on /.toddle/ subpath 👇 app.route('/.toddle/fonts', fontRouter) app.get('/.toddle/stylesheet/:pageName{.+.css}', stylesheetHandler) @@ -62,7 +62,18 @@ app.all( ) app.get('/.toddle/custom-element/:filename{.+.js}', customElement) +// Load a route if it matches the URL +app.all('/*', routeHandler) + +app.get('/sitemap.xml', sitemap) +app.get('/robots.txt', robots) +app.get('/manifest.json', manifest) +app.get('/favicon.ico', favicon) +app.get('/serviceWorker.js', serviceWorker) + // Treat all other requests as page requests -app.get('/*', toddlePage) +app.get('/*', pageHandler) + +app.notFound(notFoundLoader) export default app diff --git a/src/routes/apiProxy.ts b/src/routes/apiProxy.ts index 9df458c..89c1572 100644 --- a/src/routes/apiProxy.ts +++ b/src/routes/apiProxy.ts @@ -1,5 +1,13 @@ -import { NON_BODY_RESPONSE_CODES } from '@nordcraft/core/dist/api/api' -import { PROXY_URL_HEADER, validateUrl } from '@nordcraft/core/dist/utils/url' +import { + HttpMethodsWithAllowedBody, + NON_BODY_RESPONSE_CODES, +} from '@nordcraft/core/dist/api/api' +import type { ApiMethod } from '@nordcraft/core/dist/api/apiTypes' +import { + PROXY_TEMPLATES_IN_BODY, + PROXY_URL_HEADER, + validateUrl, +} from '@nordcraft/core/dist/utils/url' import { getRequestCookies } from '@nordcraft/ssr/dist/rendering/cookies' import { applyTemplateValues, @@ -13,9 +21,16 @@ export const proxyRequestHandler = async ( ): Promise => { const req = c.req.raw const requestCookies = getRequestCookies(req) + const requestUrl = new URL(req.url) const outgoingRequestUrl = validateUrl( // Replace potential cookie values in the URL - applyTemplateValues(req.headers.get(PROXY_URL_HEADER), requestCookies), + { + path: applyTemplateValues( + req.headers.get(PROXY_URL_HEADER), + requestCookies, + ), + origin: requestUrl.origin, + }, ) if (!outgoingRequestUrl) { return c.json( @@ -43,20 +58,65 @@ export const proxyRequestHandler = async ( ) } try { + let templateBody: string | undefined + if ( + HttpMethodsWithAllowedBody.includes(req.method as ApiMethod) && + req.headers.get(PROXY_TEMPLATES_IN_BODY) !== null + ) { + // If the request has the PROXY_TEMPLATES_IN_BODY header set, + // we must apply the template values to the body as well + try { + const bodyText = await req.text() + const contentType = req.headers.get('content-type')?.toLowerCase() + + if (contentType?.includes('application/x-www-form-urlencoded')) { + // Parse form data, apply templates to values, then re-encode + templateBody = new URLSearchParams( + Object.fromEntries( + new URLSearchParams(bodyText) + .entries() + .map(([key, value]) => [ + key, + applyTemplateValues(value, requestCookies), + ]), + ), + ).toString() + } else { + // Handle other content types (JSON, text, etc.) + templateBody = applyTemplateValues(bodyText, requestCookies) + } + } catch (e) { + // eslint-disable-next-line no-console + console.error('Error applying template values to request body', e) + return c.json( + { + error: + 'Error applying template values to request body. Perhaps the request body was not text?', + }, + { status: 400 }, + ) + } + } const request = new Request(outgoingRequestUrl.href, { // We copy over the method method: c.req.method, headers, - // We forward the body - body: req.body, + // We use the adjusted body or forward the body as is + body: templateBody ?? req.body, // Let's add a 5s timeout signal: AbortSignal.timeout(5000), }) let response: Response try { + // Remove the cf-connecting-ip header if the request is from localhost + // This is to prevent cf to throw an error when the requester ip is ::1 + if ((request.headers.get('host') ?? '').startsWith('localhost')) { + request.headers.delete('cf-connecting-ip') + } response = await fetch(request) } catch (e: any) { - console.log('API request error', e.message) + // eslint-disable-next-line no-console + console.error('API request error', e.message) const status = e instanceof Error && e.name === 'TimeoutError' ? 504 : 500 response = Response.json(e.message, { status }) } @@ -68,7 +128,7 @@ export const proxyRequestHandler = async ( const returnResponse = new Response(body, { status: response.status, - headers: Object.fromEntries(response.headers), + headers: new Headers(response.headers), }) return returnResponse } catch (e) { diff --git a/src/routes/toddlePage.ts b/src/routes/nordcraftPage.ts similarity index 59% rename from src/routes/toddlePage.ts rename to src/routes/nordcraftPage.ts index 50b6d89..b149475 100644 --- a/src/routes/toddlePage.ts +++ b/src/routes/nordcraftPage.ts @@ -1,9 +1,11 @@ +import type { PageComponent } from '@nordcraft/core/dist/component/component.types' import { ToddleComponent } from '@nordcraft/core/dist/component/ToddleComponent' import { type ToddleServerEnv } from '@nordcraft/core/dist/formula/formula' import { theme as defaultTheme } from '@nordcraft/core/dist/styling/theme.const' import type { ToddleInternals } from '@nordcraft/core/dist/types' import { isDefined } from '@nordcraft/core/dist/utils/util' import { takeIncludedComponents } from '@nordcraft/ssr/dist/components/utils' +import type { ApiCache } from '@nordcraft/ssr/dist/rendering/api' import { renderPageBody } from '@nordcraft/ssr/dist/rendering/components' import { getPageFormulaContext } from '@nordcraft/ssr/dist/rendering/formulaContext' import { @@ -11,42 +13,34 @@ import { renderHeadItems, } from '@nordcraft/ssr/dist/rendering/head' import { getCharset, getHtmlLanguage } from '@nordcraft/ssr/dist/rendering/html' -import { - get404Page, - matchPageForUrl, - matchRouteForUrl, -} from '@nordcraft/ssr/dist/routing/routing' -import { hasCustomCode } from '@nordcraft/ssr/src/custom-code/codeRefs' import { removeTestData } from '@nordcraft/ssr/src/rendering/testData' +import { + REDIRECT_API_NAME_HEADER, + REDIRECT_COMPONENT_NAME_HEADER, +} from '@nordcraft/ssr/src/utils/headers' import type { Context } from 'hono' import { html, raw } from 'hono/html' +import type { ContentfulStatusCode } from 'hono/utils/http-status' import type { HonoEnv } from '../../hono' -import { routeHandler } from './routeHandler' +import { evaluateComponentApis, RedirectError } from '../utils/api' -export const toddlePage = async (c: Context) => { - const project = c.var.project - const url = new URL(c.req.url) - // Prefer routes over pages in case of conflicts - const route = matchRouteForUrl({ url, routes: project.files.routes }) - if (route) { - return routeHandler(c, route) - } - let page = matchPageForUrl({ - url, - components: project.files.components, - }) - if (!page) { - page = get404Page(project.files.components) - if (!page) { - return c.html('Page not found', { status: 404 }) - } - } +export const nordcraftPage = async ({ + hono, + page, + status, +}: { + hono: Context + page: PageComponent + status: ContentfulStatusCode +}) => { + const { files, project } = hono.var.project + const url = new URL(hono.req.raw.url) const formulaContext = getPageFormulaContext({ component: page, branchName: 'main', - req: c.req.raw, + req: hono.req.raw, logErrors: true, - files: project.files, + files, }) const language = getHtmlLanguage({ pageInfo: page.route.info, @@ -56,15 +50,14 @@ export const toddlePage = async (c: Context) => { // Find the theme to use for the page const theme = - (project.files.themes - ? Object.values(project.files.themes)[0] - : project.files.config?.theme) ?? defaultTheme + (files.themes ? Object.values(files.themes)[0] : files.config?.theme) ?? + defaultTheme // Get all included components on the page const includedComponents = takeIncludedComponents({ root: page, - projectComponents: project.files.components, - packages: project.files.packages, + projectComponents: files.components, + packages: files.packages, includeRoot: true, }) @@ -73,9 +66,10 @@ export const toddlePage = async (c: Context) => { getComponent: (name, packageName) => { const nodeLookupKey = [packageName, name].filter(isDefined).join('/') const component = packageName - ? project.files.packages?.[packageName]?.components[name] - : project.files.components[name] + ? files.packages?.[packageName]?.components[name] + : files.components[name] if (!component) { + // eslint-disable-next-line no-console console.warn(`Unable to find component ${nodeLookupKey} in files`) return undefined } @@ -84,10 +78,38 @@ export const toddlePage = async (c: Context) => { }, packageName: undefined, globalFormulas: { - formulas: project.files.formulas, - packages: project.files.packages, + formulas: files.formulas, + packages: files.packages, }, }) + + let apiCache: ApiCache + let body: string + let customProperties: string[] = [] + try { + const pageBody = await renderPageBody({ + component: toddleComponent, + formulaContext, + env: formulaContext.env as ToddleServerEnv, + req: hono.req.raw, + files: files, + includedComponents, + evaluateComponentApis, + projectId: 'my_project', + }) + apiCache = pageBody.apiCache + body = pageBody.html + customProperties = pageBody.customProperties + } catch (e) { + if (e instanceof RedirectError) { + hono.header(REDIRECT_API_NAME_HEADER, e.redirect.apiName) + hono.header(REDIRECT_COMPONENT_NAME_HEADER, e.redirect.componentName) + return hono.redirect(e.redirect.url.href, e.redirect.statusCode ?? 302) + } else { + return hono.text('Internal server error', 500) + } + } + const head = renderHeadItems({ headItems: getHeadItems({ url, @@ -95,27 +117,16 @@ export const toddlePage = async (c: Context) => { cssBasePath: '/.toddle/fonts/stylesheet/css2', // Just to be explicit about where to grab the reset stylesheet from resetStylesheetPath: '/_static/reset.css', - // This refers to the stylesheet endpoint declared in index.ts + // This refers to the generated stylesheet for each page pageStylesheetPath: `/.toddle/stylesheet/${page.name}.css`, page: toddleComponent, - files: project.files, - project: project.project, + files: files, + project, context: formulaContext, theme, + customProperties, }), }) - const { html: body } = await renderPageBody({ - component: toddleComponent, - formulaContext, - env: formulaContext.env as ToddleServerEnv, - req: c.req.raw, - files: project.files, - includedComponents, - evaluateComponentApis: async (_) => ({ - // TODO: Show an example of how to evaluate APIs - potentially using an adapter - }), - projectId: 'my_project', - }) const charset = getCharset({ pageInfo: toddleComponent.route?.info, formulaContext, @@ -123,30 +134,36 @@ export const toddlePage = async (c: Context) => { // Prepare the data to be passed to the client for hydration const toddleInternals: ToddleInternals = { - project: c.var.project.project.short_id, + project: project.short_id, branch: 'main', commit: 'unknown', - pageState: formulaContext.data, + pageState: { + ...formulaContext.data, + Apis: { + ...apiCache, + }, + }, component: removeTestData(page), components: includedComponents.map(removeTestData), isPageLoaded: false, cookies: Object.keys(formulaContext.env.request.cookies), } - const usesCustomCode = hasCustomCode(toddleComponent, c.var.project.files) let codeImport = '' - if (usesCustomCode) { + if (files.customCode) { const customCodeSearchParams = new URLSearchParams([ ['entry', toddleComponent.name], ]) codeImport = ` - ', '<\\/script>', - )}; + )} + + ', + '<\\/script>', + )} + ', - '<\\/script>', - )}; + window.__toddle = JSON.parse(document.getElementById('nordcraft-data').textContent); window.__toddle.components = [window.__toddle.component, ...window.__toddle.components]; initGlobalObject({formulas: {}, actions: {}}); createRoot(document.getElementById("App")); @@ -169,20 +189,20 @@ export const toddlePage = async (c: Context) => { ` } - return c.html( + return hono.html( html` - ${raw(head)} ${raw(codeImport)} + ${raw(head)}
${raw(body)}
+ ${raw(codeImport)} `, + status, { - headers: { - 'Content-Type': `text/html; charset=${charset}`, - }, + 'Content-Type': `text/html; charset=${charset}`, }, ) } diff --git a/src/routes/notFoundLoader.ts b/src/routes/notFoundLoader.ts new file mode 100644 index 0000000..5d32588 --- /dev/null +++ b/src/routes/notFoundLoader.ts @@ -0,0 +1,18 @@ +import { isPageComponent } from '@nordcraft/core/dist/component/isPageComponent' +import type { NotFoundHandler } from 'hono' +import type { HonoEnv } from '../../hono' +import { nordcraftPage } from '../routes/nordcraftPage' + +export const notFoundLoader: NotFoundHandler = async (ctx) => { + const component = ctx.var.project.files.components['404'] + if (!component || !isPageComponent(component)) { + return ctx.text('Not Found', { + status: 404, + }) + } + return nordcraftPage({ + hono: ctx, + page: component, + status: 404, + }) +} diff --git a/src/routes/pageHandler.ts b/src/routes/pageHandler.ts new file mode 100644 index 0000000..6518754 --- /dev/null +++ b/src/routes/pageHandler.ts @@ -0,0 +1,27 @@ +import { isPageComponent } from '@nordcraft/core/dist/component/isPageComponent' +import { matchPageForUrl } from '@nordcraft/ssr/dist/routing/routing' +import type { MiddlewareHandler } from 'hono' +import type { HonoEnv } from '../../hono' +import { nordcraftPage } from './nordcraftPage' + +export const pageHandler: MiddlewareHandler = async (ctx, next) => { + const url = new URL(ctx.req.url) + const pageMatch = matchPageForUrl({ + url, + pages: Object.values(ctx.var.project.files.components).filter( + (c) => c !== undefined && isPageComponent(c), + ), + }) + if (pageMatch) { + const component = ctx.var.project.files.components[pageMatch.name] + if (!component || !isPageComponent(component)) { + return next() + } + return nordcraftPage({ + hono: ctx, + page: component, + status: pageMatch.name === '404' ? 404 : 200, + }) + } + return next() +} diff --git a/src/routes/routeHandler.ts b/src/routes/routeHandler.ts index 509398a..349d21c 100644 --- a/src/routes/routeHandler.ts +++ b/src/routes/routeHandler.ts @@ -1,45 +1,74 @@ -import { NON_BODY_RESPONSE_CODES } from '@nordcraft/core/dist/api/api' +import { + HttpMethodsWithAllowedBody, + NON_BODY_RESPONSE_CODES, +} from '@nordcraft/core/dist/api/api' +import type { ApiMethod } from '@nordcraft/core/dist/api/apiTypes' import { REWRITE_HEADER } from '@nordcraft/core/dist/utils/url' -import { getRouteDestination } from '@nordcraft/ssr/dist/routing/routing' -import type { Route } from '@nordcraft/ssr/dist/ssr.types' -import type { Context } from 'hono' +import { + getServerToddleObject, + serverEnv, +} from '@nordcraft/ssr/dist/rendering/formulaContext' +import { + getRouteDestination, + matchRouteForUrl, +} from '@nordcraft/ssr/dist/routing/routing' +import { REDIRECT_NAME_HEADER } from '@nordcraft/ssr/src/utils/headers' +import type { Handler } from 'hono' import type { HonoEnv } from '../../hono' -export const routeHandler = async (c: Context, route: Route) => { +export const routeHandler: Handler = async (c, next) => { + const url = new URL(c.req.url) + const routeMatch = matchRouteForUrl({ + url, + routes: c.var.project.files.routes ?? {}, + env: serverEnv({ branchName: 'main', req: c.req.raw, logErrors: false }), + req: c.req.raw, + // TODO: We should pass in global Nordcraft formulas from project + packages here + serverContext: getServerToddleObject({} as any), + }) + if (!routeMatch) { + return next() + } + const { route, name: routeName } = routeMatch const destination = getRouteDestination({ - files: c.var.project.files, + // might not want to use main branch here + env: serverEnv({ branchName: 'main', req: c.req.raw, logErrors: false }), req: c.req.raw, route, + // TODO: We should pass in global Nordcraft formulas from project + packages here + serverContext: getServerToddleObject({} as any), }) if (!destination) { - return c.html(`Invalid destination`, { + return c.text(`Invalid destination`, { status: 500, }) } if (route.type === 'redirect') { + if (c.req.raw.method !== 'GET') { + return c.text(`Method Not Allowed`, { status: 405 }) + } // Return a redirect to the destination with the provided status code - return c.redirect(destination.href, route.status ?? 302) + c.header(REDIRECT_NAME_HEADER, routeName) + return c.body(null, route.status ?? 302) } // Rewrite handling: fetch the destination and return the response if (c.req.raw.headers.get(REWRITE_HEADER) !== null) { - return c.html(`Nordcraft rewrites are not allowed to be recursive`, { + return c.text(`Nordcraft rewrites are not allowed to be recursive`, { status: 500, }) } try { - const requestHeaders = new Headers() - // Ensure this server can read the response by overriding potentially - // unsupported accept headers from the client (brotli etc.) - requestHeaders.set('accept-encoding', 'gzip') - requestHeaders.set('accept', '*/*') + const headers = new Headers() // Add header to identify that this is a rewrite // This allows us to avoid recursive fetch calls across Nordcraft routes - requestHeaders.set(REWRITE_HEADER, 'true') + headers.set(REWRITE_HEADER, 'true') const response = await fetch(destination, { - headers: requestHeaders, - // Routes can only be GET requests - method: 'GET', + headers, + method: c.req.raw.method, + body: HttpMethodsWithAllowedBody.includes(c.req.raw.method as ApiMethod) + ? c.req.raw.body + : undefined, }) // Pass the stream into a new response so we can write the headers const body = NON_BODY_RESPONSE_CODES.includes(response.status) @@ -48,19 +77,13 @@ export const routeHandler = async (c: Context, route: Route) => { const returnResponse = new Response(body, { status: response.status, - headers: { - ...Object.fromEntries( - response.headers - .entries() - // Filter out content-encoding as it breaks decoding on the client 🤷‍♂️ - .filter(([key]) => key !== 'content-encoding'), - ), - }, + statusText: response.statusText, + headers: Object.fromEntries(response.headers), }) return returnResponse } catch { return c.html( - `Internal server error when fetching url: ${destination.href}`, + `Unable to fetch resource defined in proxy destination: ${destination.href}`, { status: 500 }, ) } diff --git a/src/utils/api.ts b/src/utils/api.ts new file mode 100644 index 0000000..d5a8568 --- /dev/null +++ b/src/utils/api.ts @@ -0,0 +1,356 @@ +import { + createApiRequest, + isApiError, + requestHash, + sortApiEntries, +} from '@nordcraft/core/dist/api/api' +import type { + ApiParserMode, + ApiPerformance, + ApiStatus, + LegacyApiStatus, + RedirectStatusCode, +} from '@nordcraft/core/dist/api/apiTypes' +import { + isJsonHeader, + isTextHeader, + mapHeadersToObject, +} from '@nordcraft/core/dist/api/headers' +import { ToddleApiV2 } from '@nordcraft/core/dist/api/ToddleApiV2' +import type { FormulaContext } from '@nordcraft/core/dist/formula/formula' +import { applyFormula } from '@nordcraft/core/dist/formula/formula' +import { easySort } from '@nordcraft/core/dist/utils/collections' +import { validateUrl } from '@nordcraft/core/dist/utils/url' +import { isDefined, toBoolean } from '@nordcraft/core/dist/utils/util' +import type { ApiCache, ApiEvaluator } from '@nordcraft/ssr/dist/rendering/api' +import { + applyTemplateValues, + sanitizeProxyHeaders, +} from '@nordcraft/ssr/dist/rendering/template' + +export const evaluateComponentApis: ApiEvaluator = async ({ + component, + formulaContext: _formulaContext, + req, + apiCache, + updateApiCache, +}) => { + const formulaContext = { ..._formulaContext } + + // We only support v2 APIs in this function + const sortedApis: [string, ToddleApiV2][] = [] + sortApiEntries(Object.entries(component.apis)).forEach( + ([key, api]) => api instanceof ToddleApiV2 && sortedApis.push([key, api]), + ) + + // Sort APIs to improve the chance of APIs depending on each other being fetched in the correct order + const independentApiResponses: Record = Object.fromEntries( + await Promise.all( + // Evaluate independent API requests in parallel + sortedApis + .filter(([_, api]) => api.apiReferences.size === 0) + .map(async ([name, api]) => { + const { response, cacheKey } = await fetchApi({ + api, + formulaContext, + req, + apiCache, + componentName: component.name, + }) + if (isDefined(cacheKey)) { + updateApiCache(String(cacheKey), response) + } + return [name, response] + }), + ), + ) + formulaContext.data.Apis = { + ...formulaContext.data.Apis, + ...independentApiResponses, + } + const dependentApis = sortedApis.filter( + ([_, api]) => api.apiReferences.size > 0, + ) + const dependentApiResponses: Record = {} + for (const [_, api] of dependentApis) { + // Fetch dependent APIs sequentially + const { response, cacheKey } = await fetchApi({ + api, + formulaContext, + req, + apiCache, + componentName: component.name, + }) + dependentApiResponses[api.name] = response + formulaContext.data.Apis = { + ...formulaContext.data.Apis, + [api.name]: response, + } + if (isDefined(cacheKey)) { + updateApiCache(String(cacheKey), response) + } + } + return { + ...independentApiResponses, + ...dependentApiResponses, + } +} + +const fetchApi = async ({ + api, + formulaContext, + req, + apiCache, + componentName, +}: { + api: ToddleApiV2 + formulaContext: FormulaContext + req: Request + apiCache?: ApiCache + componentName: string +}): Promise<{ + response: LegacyApiStatus | ApiStatus + cacheKey?: number +}> => { + const evaluatedInputs = Object.entries(api.inputs).reduce< + Record + >((acc, [key, value]) => { + acc[key] = applyFormula(value.formula, formulaContext) + return acc + }, {}) + + const data = { + ...formulaContext.data, + ApiInputs: { + ...evaluatedInputs, + }, + } + + const newFormulaContext: FormulaContext = { + component: formulaContext.component, + package: formulaContext.package, + data, + env: formulaContext.env, + toddle: formulaContext.toddle, + } + + const ssrEnabled = isDefined(api.server?.ssr?.enabled) + ? toBoolean( + applyFormula(api.server?.ssr?.enabled.formula, newFormulaContext), + ) + : false + + const autoFetch = isDefined(api.autoFetch) + ? toBoolean(applyFormula(api.autoFetch, newFormulaContext)) + : false + + if (!ssrEnabled || !autoFetch) { + // Return early if the API is not enabled for SSR or autoFetch is disabled + return { + response: { + data: null, + isLoading: autoFetch, + error: null, + }, + } + } + + const url = new URL(req.url) + const { url: requestUrl, requestSettings } = createApiRequest({ + api, + formulaContext, + baseUrl: url.origin, + defaultHeaders: new Headers({ + ...mapHeadersToObject(req.headers), + // Override accept + accept-encoding to increase the chance that we can work with the response + // from an API fetched during SSR. Many servers don't support br encoding for instance. + accept: '*/*', + 'accept-encoding': 'gzip, deflate', + }), + }) + const cacheKey = requestHash(requestUrl, requestSettings) + + if (apiCache?.[cacheKey]) { + // Return early if the response is already cached + return { response: apiCache[cacheKey] } + } + + // Override potentially encoded cookies in url + requestUrl.searchParams.forEach((value, key) => { + requestUrl.searchParams.set( + key, + applyTemplateValues(value, newFormulaContext.env?.request?.cookies ?? {}), + ) + }) + + const request = new Request(requestUrl.href, { + ...requestSettings, + headers: sanitizeProxyHeaders({ + cookies: newFormulaContext.env?.request?.cookies ?? {}, + headers: requestSettings.headers, + }), + }) + + const response = await fetchApiV2({ + api, + formulaContext: newFormulaContext, + req: request, + originalRequest: req, + componentName, + }) + + return { response, cacheKey } +} + +const fetchApiV2 = async ({ + api, + formulaContext, + req, + originalRequest, + componentName, +}: { + api: ToddleApiV2 + formulaContext: FormulaContext + req: Request + originalRequest: Request + componentName: string +}): Promise => { + let isError = false + let response: Response + const performance: ApiPerformance = { + requestStart: Date.now(), + responseStart: null, + responseEnd: null, + } + try { + response = await executeFetchCall(req) + } catch (e) { + return { + data: null, + isLoading: false, + error: e instanceof Error ? e.message : 'Unknown error', + } + } + let responseBody: unknown + try { + performance.responseStart = Date.now() + responseBody = await getBody(response, api.client?.parserMode) + performance.responseEnd = Date.now() + } catch (e: any) { + return { + data: null, + isLoading: false, + error: `Error getting response body: ${e}`, + response: { + status: 500, + headers: mapHeadersToObject(response.headers), + }, + } + } + // Figure out if the response should be treated as an error + const errorFormula = api.isError + isError = isApiError({ + apiName: api.name, + response: { + body: responseBody, + ok: response.ok, + status: response.status, + headers: mapHeadersToObject(response.headers), + }, + formulaContext, + errorFormula, + performance, + }) + + const apiStatus: ApiStatus = { + data: isError ? null : responseBody, + isLoading: false, + error: isError ? (responseBody ?? response.statusText) : null, + response: { + status: response.status, + headers: mapHeadersToObject(response.headers), + performance, + }, + } + // Check for redirects + const originalRequestUrl = new URL(originalRequest.url) + easySort( + Object.values(api.redirectRules ?? {}), + (rule) => rule.index, + ).forEach((rule) => { + const location = applyFormula(rule.formula, { + ...formulaContext, + data: { + ...formulaContext.data, + Apis: { + [api.name]: apiStatus, + }, + }, + }) + if (typeof location === 'string') { + const url = validateUrl({ + path: location, + origin: originalRequestUrl.origin, + }) + if (url) { + // Opt out early to avoid additional API requests/rendering + throw new RedirectError({ + url, + statusCode: + typeof rule.statusCode === 'number' ? rule.statusCode : undefined, + componentName, + apiName: api.name, + }) + } + } + }) + return apiStatus +} + +const getBody = (res: Response, parserOverride: ApiParserMode = 'auto') => { + if (parserOverride !== 'auto') { + if (parserOverride === 'json') { + return res.json() + } else if (parserOverride === 'text') { + return res.text() + } + throw new Error(`Unsupported SSR API parser override: ${parserOverride}`) + } + const contentType = res.headers.get('content-type') + if (isJsonHeader(contentType)) { + return res.json() + } else if (isTextHeader(contentType)) { + return res.text() + } + throw new Error(`Unsupported SSR API content type: ${contentType}`) +} + +export class RedirectError extends Error { + constructor( + public readonly redirect: { + apiName: string + componentName: string + url: URL + statusCode?: RedirectStatusCode + }, + ) { + super() + } +} + +const executeFetchCall = async (request: Request) => { + try { + // Remove the cf-connecting-ip header if the request is from localhost + // This is to prevent cf to throw an error when the requester ip is ::1 + if ((request.headers.get('host') ?? '').startsWith('localhost')) { + request.headers.delete('cf-connecting-ip') + } + const response = await fetch(request) + return response + } catch (e: any) { + // eslint-disable-next-line no-console + console.log('API request threw error', e.message) + const status = e instanceof Error && e.name === 'TimeoutError' ? 504 : 500 + return Response.json(e.message, { status }) + } +} From 6160368b7c02e40c7196d453c7a5dbde59a01a44 Mon Sep 17 00:00:00 2001 From: Erik Beuschau Date: Tue, 23 Sep 2025 08:37:04 +0200 Subject: [PATCH 2/2] Update sample project with a more complex one --- __project__/project.json | 907 +-------------------------------------- 1 file changed, 1 insertion(+), 906 deletions(-) diff --git a/__project__/project.json b/__project__/project.json index 862b7f3..22fc063 100644 --- a/__project__/project.json +++ b/__project__/project.json @@ -1,906 +1 @@ -{ - "id": "7546cf70-4b38-48be-bcd3-a3dfb35b939f", - "name": "medium", - "project": { - "id": "2961e2d1-3c63-4d98-bd3b-302fbd35972b", - "name": "Untitled", - "type": "app", - "emoji": "🙌", - "accounts": { - "id": "f9e6ee17-c6b2-4cf5-9d67-0e3cba39d2a3", - "name": "erik-test-org", - "account_plans": { "plans": { "custom_domains": false }, "active": true } - }, - "short_id": "brown_sebulba_agreed_baboon", - "thumbnail": null, - "description": null, - "published_at": null, - "custom_domains": false - }, - "commit": "9c496ac007485f69af00463d9e13e8b8912bd9f1", - "files": { - "components": { - "HomePage": { - "apis": { - "WOW API": { - "url": { - "type": "value", - "value": "https://owen-wilson-wow-api.onrender.com" - }, - "name": "WOW API", - "path": { - "8dyQhOhHDyfv-BskOoSks": { - "index": 1, - "formula": { "type": "value", "value": "random" } - }, - "IbdbGqON7MJvvmNOO1TAg": { - "index": 0, - "formula": { "type": "value", "value": "wows" } - } - }, - "type": "http", - "client": {}, - "inputs": {}, - "method": "GET", - "server": { - "ssr": { - "enabled": { "formula": { "type": "value", "value": true } } - }, - "proxy": { - "enabled": { "formula": { "type": "value", "value": false } } - } - }, - "headers": {}, - "isError": {}, - "timeout": {}, - "version": 2, - "autoFetch": { "type": "value", "value": true }, - "queryParams": {}, - "redirectRules": {} - } - }, - "name": "HomePage", - "nodes": { - "root": { - "tag": "div", - "type": "element", - "attrs": {}, - "style": { - "gap": "8px", - "color": "var(--grey-200, #E5E5E5)", - "min-height": "100%", - "align-items": "center", - "justify-content": "center", - "background-color": "var(--grey-900)" - }, - "events": {}, - "classes": {}, - "children": [ - "p44ree-FsxJKSeiWKWQpa", - "D3FDz9GhM-ZyJChwJhxzK", - "pK1rq0usjmjwt2RZhiTFV", - "9cdB1ieO8k-D0guvB5q6d", - "co7vEt15EK6qGAVA2PGaM", - "SsJicr-d3CKhKiJ2O7CAO" - ], - "styleVariables": {} - }, - "9cdB1ieO8k-D0guvB5q6d": { - "tag": "button", - "type": "element", - "attrs": {}, - "style": { - "color": "var(--grey-200, #E5E5E5)", - "width": "fit-content", - "cursor": "pointer", - "padding-top": "8px", - "padding-left": "8px", - "border-radius": "6px", - "padding-right": "8px", - "padding-bottom": "8px", - "background-color": "var(--blue-600, #2563EB)" - }, - "events": {}, - "classes": {}, - "children": ["RGFpys0-7b_IQ8SYApMAL"], - "variants": [ - { - "hover": true, - "style": { "background-color": "var(--blue-500, #3B82F6)" } - } - ], - "condition": { - "name": "@toddle/equals", - "type": "function", - "label": null, - "arguments": [ - { - "name": "First", - "type": { "type": "Any" }, - "formula": { - "path": ["URL parameters", "test"], - "type": "path", - "label": null - } - }, - { - "name": "Second", - "type": { "type": "Any" }, - "formula": { "type": "value", "value": null } - } - ], - "display_name": "Equals" - }, - "styleVariables": {} - }, - "D3FDz9GhM-ZyJChwJhxzK": { - "tag": "p", - "type": "element", - "attrs": {}, - "style": { "color": "inherit", "display": "inline-block" }, - "events": {}, - "classes": {}, - "children": ["z5I8Rnxfdy2McmsNLlMhD"], - "styleVariables": {} - }, - "EEfz_0R8BhOvKve4YgCi6": { - "type": "text", - "value": { - "name": "@toddle/concatenate", - "type": "function", - "arguments": [ - { - "name": "0", - "type": { - "type": "Union", - "types": [ - { "type": "String" }, - { "type": "Array", "ofType": { "type": "Any" } } - ] - }, - "formula": { "type": "value", "value": "Wow API: " } - }, - { - "name": "0", - "type": { - "type": "Union", - "types": [ - { "type": "String" }, - { "type": "Array", "ofType": { "type": "Any" } } - ] - }, - "formula": { - "path": ["Apis", "WOW API", "data", "0", "movie"], - "type": "path" - } - } - ], - "display_name": "Concatenate", - "variableArguments": true - } - }, - "RGFpys0-7b_IQ8SYApMAL": { - "type": "text", - "value": { - "type": "value", - "value": "Element which is only visible when \"test\" query parameter doesn't have a value" - } - }, - "c8DBGzXyJIHSfoguEo7OL": { - "type": "text", - "value": { "type": "value", "value": "Hello world" } - }, - "co7vEt15EK6qGAVA2PGaM": { - "tag": "p", - "type": "element", - "attrs": {}, - "style": { "color": "inherit", "display": "inline-block" }, - "events": {}, - "classes": {}, - "children": ["EEfz_0R8BhOvKve4YgCi6"], - "styleVariables": {} - }, - "p44ree-FsxJKSeiWKWQpa": { - "tag": "h1", - "type": "element", - "attrs": {}, - "style": { - "color": "var(--grey-200, #E5E5E5)", - "font-size": "2.25rem", - "font-weight": "var(--font-weight-bold)" - }, - "events": {}, - "classes": {}, - "children": ["c8DBGzXyJIHSfoguEo7OL"], - "styleVariables": {} - }, - "pK1rq0usjmjwt2RZhiTFV": { - "tag": "p", - "type": "element", - "attrs": {}, - "style": { "color": "inherit", "display": "inline-block" }, - "events": {}, - "classes": {}, - "children": ["vnERXXaHU1zd6Jz79Ry5I"], - "styleVariables": {} - }, - "vnERXXaHU1zd6Jz79Ry5I": { - "type": "text", - "value": { "path": ["URL parameters", "q"], "type": "path" } - }, - "z5I8Rnxfdy2McmsNLlMhD": { - "type": "text", - "value": { - "name": "@toddle/concatenate", - "type": "function", - "arguments": [ - { - "name": "0", - "type": { - "type": "Union", - "types": [ - { "type": "String" }, - { "type": "Array", "ofType": { "type": "Any" } } - ] - }, - "formula": { "type": "value", "value": "Calculated value: " } - }, - { - "name": "0", - "type": { - "type": "Union", - "types": [ - { "type": "String" }, - { "type": "Array", "ofType": { "type": "Any" } } - ] - }, - "formula": { - "name": "@toddle/formatDate", - "type": "function", - "arguments": [ - { - "name": "Date", - "type": { "type": "Date" }, - "formula": { - "name": "@toddle/now", - "type": "function", - "arguments": [], - "display_name": "Now" - } - }, - { - "name": "Locale(s)", - "type": { "type": "String | Array" }, - "formula": { "type": "value", "value": null } - }, - { - "name": "Options", - "type": { "type": "Object" }, - "formula": { - "type": "object", - "arguments": [ - { - "Name": 0, - "name": "timeFormat", - "formula": { "type": "value", "value": "short" } - }, - { - "Name": 0, - "name": "dateFormat", - "formula": { "type": "value", "value": "short" } - } - ] - } - } - ], - "display_name": "Format Date" - } - }, - { - "name": "0", - "type": { - "type": "Union", - "types": [ - { "type": "String" }, - { "type": "Array", "ofType": { "type": "Any" } } - ] - }, - "formula": { "type": "value", "value": " and 4 + 9 is: " } - }, - { - "name": "0", - "type": { - "type": "Union", - "types": [ - { "type": "String" }, - { "type": "Array", "ofType": { "type": "Any" } } - ] - }, - "formula": { - "name": "@toddle/sum", - "type": "function", - "arguments": [ - { - "name": "Array", - "type": { "type": "Array" }, - "formula": { - "type": "array", - "arguments": [ - { - "Name": 0, - "formula": { "type": "value", "value": 4 } - }, - { - "Name": 0, - "formula": { "type": "value", "value": 9 } - } - ] - } - } - ], - "display_name": "Sum" - } - } - ], - "display_name": "Concatenate", - "variableArguments": true - } - }, - "SsJicr-d3CKhKiJ2O7CAO": { - "name": "counter", - "attrs": {}, - "events": {}, - "type": "component", - "children": [], - "repeat": null - } - }, - "route": { - "info": { - "title": { - "formula": { "type": "value", "value": "Toddle template" } - }, - "description": { - "formula": { - "type": "value", - "value": "A blank template from toddle" - } - } - }, - "path": [], - "query": { - "q": { "name": "q", "testValue": "search" }, - "test": { "name": "test", "testValue": "test" } - } - }, - "events": [], - "onLoad": { "actions": [], "trigger": "load" }, - "functions": {}, - "variables": {}, - "attributes": {} - }, - "counter": { - "attributes": {}, - "onLoad": null, - "events": [], - "formulas": {}, - "nodes": { - "root": { - "type": "element", - "tag": "div", - "attrs": {}, - "classes": {}, - "events": {}, - "children": [ - "8Xso9hlnAdBt6DxRYxND5", - "bUF7igS7dRCsLtiZGRSf_", - "bRDsUkUPHDiwSguz57dY1" - ], - "style": { - "color": "var(--grey-200, #E5E5E5)", - "align-items": "center", - "justify-content": "start", - "flex-direction": "row", - "gap": "8px" - }, - "styleVariables": {} - }, - "bUF7igS7dRCsLtiZGRSf_": { - "tag": "p", - "type": "element", - "attrs": {}, - "style": { "color": "inherit", "display": "inline-block" }, - "events": {}, - "classes": {}, - "children": ["olANeLrT3QHE_sAMkT2iC"], - "styleVariables": {} - }, - "olANeLrT3QHE_sAMkT2iC": { - "type": "text", - "value": { - "type": "function", - "name": "@toddle/concatenate", - "arguments": [ - { - "name": "0", - "formula": { "type": "value", "value": "Count: " }, - "type": { - "type": "Union", - "types": [ - { "type": "String" }, - { "type": "Array", "ofType": { "type": "Any" } } - ] - } - }, - { - "name": "0", - "formula": { "type": "path", "path": ["Variables", "count"] }, - "type": { - "type": "Union", - "types": [ - { "type": "String" }, - { "type": "Array", "ofType": { "type": "Any" } } - ] - } - } - ], - "variableArguments": true, - "display_name": "Concatenate" - } - }, - "bRDsUkUPHDiwSguz57dY1": { - "tag": "button", - "type": "element", - "attrs": {}, - "style": { - "color": "var(--grey-200, #E5E5E5)", - "border-radius": "6px", - "background-color": "var(--blue-600, #2563EB)", - "padding-left": "8px", - "padding-right": "8px", - "padding-top": "8px", - "padding-bottom": "8px", - "width": "fit-content", - "cursor": "pointer" - }, - "events": { - "click": { - "trigger": "click", - "actions": [ - { - "type": "SetVariable", - "data": { - "type": "function", - "name": "@toddle/add", - "arguments": [ - { - "name": "0", - "formula": { - "type": "path", - "path": ["Variables", "count"] - }, - "type": { "type": "Number" } - }, - { - "name": "1", - "formula": { "type": "value", "value": 1 }, - "type": { "type": "Number" } - } - ], - "variableArguments": true, - "display_name": "Add" - }, - "variable": "count" - } - ] - } - }, - "classes": {}, - "children": ["uuAFG8sArLI_tPfws2CYX"], - "variants": [ - { - "hover": true, - "style": { "background-color": "var(--blue-500, #3B82F6)" } - } - ], - "styleVariables": {} - }, - "uuAFG8sArLI_tPfws2CYX": { - "type": "text", - "value": { "type": "value", "value": "+" } - }, - "8Xso9hlnAdBt6DxRYxND5": { - "tag": "button", - "type": "element", - "attrs": {}, - "style": { - "color": "var(--grey-200, #E5E5E5)", - "border-radius": "6px", - "background-color": "var(--blue-600, #2563EB)", - "padding-left": "8px", - "padding-right": "8px", - "padding-top": "8px", - "padding-bottom": "8px", - "width": "fit-content", - "cursor": "pointer" - }, - "events": { - "click": { - "trigger": "click", - "actions": [ - { - "type": "SetVariable", - "data": { - "type": "function", - "name": "@toddle/max", - "arguments": [ - { - "name": "0", - "formula": { - "type": "function", - "name": "@toddle/minus", - "arguments": [ - { - "name": "Minuend", - "formula": { - "type": "path", - "path": ["Variables", "count"] - }, - "type": { "type": "Number" } - }, - { - "name": "Substrahend", - "formula": { "type": "value", "value": 1 }, - "type": { "type": "Number" } - } - ], - "display_name": "Minus" - }, - "type": { "type": "Number" } - }, - { - "name": "1", - "formula": { "type": "value", "value": 0 }, - "type": { "type": "Number" } - } - ], - "variableArguments": true, - "display_name": "Max" - }, - "variable": "count" - } - ] - } - }, - "classes": {}, - "children": ["fu2T-qOHbpd1ykskNnwiK"], - "variants": [ - { - "hover": true, - "style": { "background-color": "var(--blue-500, #3B82F6)" } - } - ], - "styleVariables": {} - }, - "fu2T-qOHbpd1ykskNnwiK": { - "type": "text", - "value": { "type": "value", "value": "-" } - } - }, - "variables": { - "count": { - "initialValue": { - "type": "function", - "name": "@toddle/number", - "arguments": [ - { - "name": "Input", - "formula": { "type": "value", "value": 0 }, - "type": { "type": "Any" } - } - ], - "display_name": "Number" - } - } - }, - "apis": {}, - "name": "counter" - } - }, - "actions": {}, - "formulas": {}, - "config": {}, - "packages": {}, - "themes": { - "Default": { - "color": [ - { - "name": "grey", - "tokens": [ - { "name": "grey-50", "type": "value", "value": "#FAFAFA" }, - { "name": "grey-100", "type": "value", "value": "#F5F5F5" }, - { "name": "grey-200", "type": "value", "value": "#E5E5E5" }, - { "name": "grey-300", "type": "value", "value": "#D4D4D4" }, - { "name": "grey-400", "type": "value", "value": "#A3A3A3" }, - { "name": "grey-500", "type": "value", "value": "#737373" }, - { "name": "grey-600", "type": "value", "value": "#525252" }, - { "name": "grey-700", "type": "value", "value": "#404040" }, - { "name": "grey-800", "type": "value", "value": "#262626" }, - { "name": "grey-900", "type": "value", "value": "#171717" } - ] - }, - { - "name": "red", - "tokens": [ - { "name": "red-50", "type": "value", "value": "#FEF2F2" }, - { "name": "red-100", "type": "value", "value": "#FEE2E2" }, - { "name": "red-200", "type": "value", "value": "#FECACA" }, - { "name": "red-300", "type": "value", "value": "#FCA5A5" }, - { "name": "red-400", "type": "value", "value": "#F87171" }, - { "name": "red-500", "type": "value", "value": "#EF4444" }, - { "name": "red-600", "type": "value", "value": "#DC2626" }, - { "name": "red-700", "type": "value", "value": "#B91C1C" }, - { "name": "red-800", "type": "value", "value": "#991B1B" }, - { "name": "red-900", "type": "value", "value": "#7F1D1D" } - ] - }, - { - "name": "blue", - "tokens": [ - { "name": "blue-50", "type": "value", "value": "#EFF6FF" }, - { "name": "blue-100", "type": "value", "value": "#DBEAFE" }, - { "name": "blue-200", "type": "value", "value": "#BFDBFE" }, - { "name": "blue-300", "type": "value", "value": "#93C5FD" }, - { "name": "blue-400", "type": "value", "value": "#60A5FA" }, - { "name": "blue-500", "type": "value", "value": "#3B82F6" }, - { "name": "blue-600", "type": "value", "value": "#2563EB" }, - { "name": "blue-700", "type": "value", "value": "#1D4ED8" }, - { "name": "blue-800", "type": "value", "value": "#1E40AF" }, - { "name": "blue-900", "type": "value", "value": "#1E3A8A" } - ] - }, - { - "name": "lime", - "tokens": [ - { "name": "lime-50", "type": "value", "value": "#F7FEE7" }, - { "name": "lime-100", "type": "value", "value": "#ECFCCB" }, - { "name": "lime-200", "type": "value", "value": "#D9F99D" }, - { "name": "lime-300", "type": "value", "value": "#BEF264" }, - { "name": "lime-400", "type": "value", "value": "#A3E635" }, - { "name": "lime-500", "type": "value", "value": "#84CC16" }, - { "name": "lime-600", "type": "value", "value": "#65A30D" }, - { "name": "lime-700", "type": "value", "value": "#4D7C0F" }, - { "name": "lime-800", "type": "value", "value": "#3F6212" }, - { "name": "lime-900", "type": "value", "value": "#365314" } - ] - }, - { - "name": "pink", - "tokens": [ - { "name": "pink-50", "type": "value", "value": "#FDF2F8" }, - { "name": "pink-100", "type": "value", "value": "#FCE7F3" }, - { "name": "pink-200", "type": "value", "value": "#FBCFE8" }, - { "name": "pink-300", "type": "value", "value": "#F9A8D4" }, - { "name": "pink-400", "type": "value", "value": "#F472B6" }, - { "name": "pink-500", "type": "value", "value": "#EC4899" }, - { "name": "pink-600", "type": "value", "value": "#DB2777" }, - { "name": "pink-700", "type": "value", "value": "#BE185D" }, - { "name": "pink-800", "type": "value", "value": "#9D174D" }, - { "name": "pink-900", "type": "value", "value": "#831843" } - ] - }, - { - "name": "teal", - "tokens": [ - { "name": "teal-50", "type": "value", "value": "#F0FDFA" }, - { "name": "teal-100", "type": "value", "value": "#CCFBF1" }, - { "name": "teal-200", "type": "value", "value": "#99F6E4" }, - { "name": "teal-300", "type": "value", "value": "#5EEAD4" }, - { "name": "teal-400", "type": "value", "value": "#2DD4BF" }, - { "name": "teal-500", "type": "value", "value": "#14B8A6" }, - { "name": "teal-600", "type": "value", "value": "#0D9488" }, - { "name": "teal-700", "type": "value", "value": "#0F766E" }, - { "name": "teal-800", "type": "value", "value": "#115E59" }, - { "name": "teal-900", "type": "value", "value": "#134E4A" } - ] - }, - { - "name": "green", - "tokens": [ - { "name": "green-50", "type": "value", "value": "#ECFDF5" }, - { "name": "green-100", "type": "value", "value": "#D1FAE5" }, - { "name": "green-200", "type": "value", "value": "#A7F3D0" }, - { "name": "green-300", "type": "value", "value": "#6EE7B7" }, - { "name": "green-400", "type": "value", "value": "#34D399" }, - { "name": "green-500", "type": "value", "value": "#10B981" }, - { "name": "green-600", "type": "value", "value": "#059669" }, - { "name": "green-700", "type": "value", "value": "#047857" }, - { "name": "green-800", "type": "value", "value": "#065F46" }, - { "name": "green-900", "type": "value", "value": "#064E3B" } - ] - }, - { - "name": "purple", - "tokens": [ - { "name": "purple-50", "type": "value", "value": "#F5F3FF" }, - { "name": "purple-100", "type": "value", "value": "#EDE9FE" }, - { "name": "purple-200", "type": "value", "value": "#DDD6FE" }, - { "name": "purple-300", "type": "value", "value": "#C4B5FD" }, - { "name": "purple-400", "type": "value", "value": "#A78BFA" }, - { "name": "purple-500", "type": "value", "value": "#8B5CF6" }, - { "name": "purple-600", "type": "value", "value": "#7C3AED" }, - { "name": "purple-700", "type": "value", "value": "#6D28D9" }, - { "name": "purple-800", "type": "value", "value": "#5B21B6" }, - { "name": "purple-900", "type": "value", "value": "#4C1D95" } - ] - }, - { - "name": "yellow", - "tokens": [ - { "name": "yellow-50", "type": "value", "value": "#FFFBEB" }, - { "name": "yellow-100", "type": "value", "value": "#FEF3C7" }, - { "name": "yellow-200", "type": "value", "value": "#FDE68A" }, - { "name": "yellow-300", "type": "value", "value": "#FCD34D" }, - { "name": "yellow-400", "type": "value", "value": "#FBBF24" }, - { "name": "yellow-500", "type": "value", "value": "#F59E0B" }, - { "name": "yellow-600", "type": "value", "value": "#D97706" }, - { "name": "yellow-700", "type": "value", "value": "#B45309" }, - { "name": "yellow-800", "type": "value", "value": "#92400E" }, - { "name": "yellow-900", "type": "value", "value": "#78350F" } - ] - } - ], - "fonts": [ - { - "name": "sans", - "type": "sans-serif", - "family": "Inter", - "provider": "google", - "variants": [ - { - "url": "https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyeMZ1rib2Bg-4.woff2", - "name": "100", - "italic": false, - "weight": "100" - }, - { - "url": "https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuDyfMZ1rib2Bg-4.woff2", - "name": "200", - "italic": false, - "weight": "200" - }, - { - "url": "https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuOKfMZ1rib2Bg-4.woff2", - "name": "300", - "italic": false, - "weight": "300" - }, - { - "url": "https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfMZ1rib2Bg-4.woff2", - "name": "regular", - "italic": false, - "weight": "400" - }, - { - "url": "https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuI6fMZ1rib2Bg-4.woff2", - "name": "500", - "italic": false, - "weight": "500" - }, - { - "url": "https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuGKYMZ1rib2Bg-4.woff2", - "name": "600", - "italic": false, - "weight": "600" - }, - { - "url": "https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuFuYMZ1rib2Bg-4.woff2", - "name": "700", - "italic": false, - "weight": "700" - }, - { - "url": "https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuDyYMZ1rib2Bg-4.woff2", - "name": "800", - "italic": false, - "weight": "800" - }, - { - "url": "https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuBWYMZ1rib2Bg-4.woff2", - "name": "900", - "italic": false, - "weight": "900" - } - ] - } - ], - "scheme": "dark", - "shadow": [ - { - "name": "Default", - "tokens": [ - { - "name": "shadow-sm", - "type": "value", - "value": " 0 1px 2px 0 rgba(0, 0, 0, 0.25)" - }, - { - "name": "shadow-base", - "type": "value", - "value": " 0 1px 3px 0 rgba(0, 0, 0, 0.25), 0 1px 2px 0 rgba(0, 0, 0, 0.25)" - }, - { - "name": "shadow-md", - "type": "value", - "value": " 0 4px 6px -1px rgba(0, 0, 0, 0.25), 0 2px 4px -1px rgba(0, 0, 0, 0.25)" - }, - { - "name": "shadow-lg", - "type": "value", - "value": " 0 10px 15px -3px rgba(0, 0, 0, 0.25), 0 4px 6px -2px rgba(0, 0, 0, 0.25)" - }, - { - "name": "shadow-xl", - "type": "value", - "value": "0 20px 25px -5px rgba(0, 0, 0, 0.25), 0 10px 10px -5px rgba(0, 0, 0, 0.25)" - }, - { - "name": "shadow-2xl", - "type": "value", - "value": " 0 25px 50px -12px rgba(0, 0, 0, 0.25)" - } - ] - } - ], - "spacing": [], - "z-index": [], - "font-size": [ - { - "name": "Default", - "tokens": [ - { "name": "font-size-xxs", "type": "value", "value": "0.625rem" }, - { "name": "font-size-xs", "type": "value", "value": "0.75rem" }, - { "name": "font-size-sm", "type": "value", "value": "0.875rem" }, - { "name": "font-size-base", "type": "value", "value": "1rem" }, - { "name": "font-size-lg", "type": "value", "value": "1.125rem" }, - { "name": "font-size-xl", "type": "value", "value": "1.25rem" }, - { "name": "font-size-2xl", "type": "value", "value": "1.5rem" }, - { "name": "font-size-3xl", "type": "value", "value": "1.875rem" }, - { "name": "font-size-4xl", "type": "value", "value": "2.25rem" }, - { "name": "font-size-5xl", "type": "value", "value": "3rem" } - ] - } - ], - "font-weight": [ - { - "name": "Default", - "tokens": [ - { "name": "font-weight-thin", "type": "value", "value": "100" }, - { - "name": "font-weight-lighter", - "type": "value", - "value": "200" - }, - { "name": "font-weight-light", "type": "value", "value": "300" }, - { - "name": "font-weight-regular", - "type": "value", - "value": "400" - }, - { "name": "font-weight-normal", "type": "value", "value": "500" }, - { "name": "font-weight-bold", "type": "value", "value": "700" }, - { - "name": "font-weight-semi-bold", - "type": "value", - "value": "600" - }, - { "name": "font-weight-bolder", "type": "value", "value": "800" }, - { "name": "font-weight-black", "type": "value", "value": "900" } - ] - } - ], - "border-radius": [] - } - } - } -} +{"id":"60e08c76-cbf9-44d4-add2-26fc62b20599","project":{"id":"13d6fae3-384d-4b70-9d00-682d1c6ee5ac","name":"Sample test OS project","type":"app","emoji":"🙂","public":true,"accounts":{"id":"f9e6ee17-c6b2-4cf5-9d67-0e3cba39d2a3","name":"erik-test-org"},"short_id":"sample_test_os_project","thumbnail":null,"description":"A test project for testing various use cases in open source libraries","published_at":null},"commit":"9d6edac182360a7213aca4a5f578402cc99ca89b","files":{"components":{"HomePage":{"apis":{"WOW API":{"url":{"type":"value","value":"https://owen-wilson-wow-api.onrender.com"},"name":"WOW API","path":{"1tIQqdGhob69846XO75yd":{"index":0,"formula":{"type":"value","value":"wows"}},"IHQfH7p6fYpoh7YgxXfVz":{"index":1,"formula":{"type":"value","value":"random"}}},"type":"http","client":{},"inputs":{},"method":"GET","server":{"ssr":{"enabled":{"formula":{"type":"value","value":false}}},"proxy":{"enabled":{"formula":{"type":"value","value":false}}}},"headers":{},"isError":{},"timeout":{},"version":2,"autoFetch":{"type":"value","value":true},"queryParams":{},"redirectRules":{}}},"name":"HomePage","nodes":{"root":{"tag":"main","type":"element","attrs":{},"style":{"color":"var(--grey-800)","display":"flex","row-gap":"8px","background":"var(--grey-200)","column-gap":"8px","min-height":"100%","align-items":"flex-start","padding-top":"24px","padding-left":"24px","padding-right":"24px","padding-bottom":"24px","justify-content":"flex-start"},"events":{},"classes":{},"children":["48qrlCFHthQy0Z6cSaN_s","mavhc8aBSpBbefMxKUmxq","0xoShjjvyS2ONk_JBvv4K","k4kdAiuEsuqbJ7Bde4kzx","CbfSJRbmTSDbdcHpWjEap","dvFpPeSgeTa4-Egm18rfA","qPOhO6iFBq2c4xfuaTSI7","L8nGekixiXlnIa6tXkzPJ","h4ngIdynyfkrMJhpKL7bK","urcpUdMessXz6BrkV2rI-","TvrgUySBxMwF6F6dsIVvf"],"styleVariables":{}},"0xoShjjvyS2ONk_JBvv4K":{"tag":"p","type":"element","attrs":{},"style":{},"events":{},"classes":{},"children":["wnZL1kvMevNKga0XZwmKE"],"style-variables":[]},"48qrlCFHthQy0Z6cSaN_s":{"tag":"div","type":"element","attrs":{},"style":{"row-gap":"8px","column-gap":"8px","flex-direction":"row"},"events":{},"classes":{},"children":["goDi48ydHDaim1-UCkhB1","eejsGXYaxtfocqzQzI8fL"]},"7zorxtwn-54JBGgk6ZKvN":{"tag":"p","type":"element","attrs":{},"style":{},"events":{},"classes":{},"children":["sCKtwkz02vg_cf1MR2cFe"],"style-variables":[]},"AJynAQgMyJP6bJ39NSw1M":{"type":"text","value":{"type":"value","value":"Random links"}},"CbfSJRbmTSDbdcHpWjEap":{"tag":"ul","type":"element","attrs":{},"style":{},"events":{},"classes":{},"children":["vPHrh8QAidCHOIVEJ_SYc"],"style-variables":[]},"DNAToE8J5QYxLvDVvOAaB":{"tag":"button","type":"element","attrs":{},"style":{"cursor":"pointer","background":"#afcaee","padding-top":"8px","padding-left":"8px","padding-right":"8px","padding-bottom":"8px","border-top-left-radius":"8px","border-top-right-radius":"8px","border-bottom-left-radius":"8px","border-bottom-right-radius":"8px"},"events":{"click":{"actions":[{"name":"@toddle/gotToURL","label":"Go to URL","arguments":[{"name":"URL","formula":{"name":"@toddle/currentURL","type":"function","arguments":[],"display_name":"Current URL"}}]}],"trigger":"click"}},"classes":{},"children":["e-3Mxyv3Biq-ad9tQWTMZ"],"variants":[{"hover":true,"style":{"background":"#5c8bf0"}},{"style":{"background":"#5050f7"},"active":true}],"style-variables":[]},"L8nGekixiXlnIa6tXkzPJ":{"tag":"h2","type":"element","attrs":{},"style":{"font-size":"var(--font-size-xl)"},"events":{},"classes":{},"children":["AJynAQgMyJP6bJ39NSw1M"],"style-variables":[]},"OKWInTu4ZPALaHWTxlFfj":{"type":"text","value":{"type":"value","value":"Repeated list of things:"}},"TvrgUySBxMwF6F6dsIVvf":{"name":"test-component","type":"component","attrs":{"href":{"type":"value","value":"https://ecosia.org"}},"events":{},"repeat":null,"children":[]},"_3x4CaRWcNmjWbJnpZ_0s":{"type":"text","value":{"type":"value","value":"Welcome Open Source"}},"dvFpPeSgeTa4-Egm18rfA":{"tag":"h2","type":"element","attrs":{},"style":{"font-size":"var(--font-size-xl)"},"events":{},"classes":{},"children":["kXknvjkiHozh7-lH0NfCE"],"style-variables":[]},"e-3Mxyv3Biq-ad9tQWTMZ":{"type":"text","value":{"type":"value","value":"Reload page"}},"eejsGXYaxtfocqzQzI8fL":{"name":"best-like-button","type":"component","attrs":{"size":{"type":"value","value":24},"color":{"type":"value","value":"#d00606"},"border_color":{"type":"value","value":"#000"},"border_radius":{"type":"value","value":1},"number_of_hearts":{"type":"value","value":5},"focus_outline_color":{"type":"value","value":"#000000"},"focus_outline_width":{"type":"value","value":1}},"events":{},"repeat":null,"package":"best_like_button","children":[]},"goDi48ydHDaim1-UCkhB1":{"tag":"h1","type":"element","attrs":{},"style":{"font-size":"var(--font-size-3xl)"},"events":{},"classes":{},"children":["_3x4CaRWcNmjWbJnpZ_0s"],"style-variables":[]},"h4ngIdynyfkrMJhpKL7bK":{"name":"test-component","type":"component","attrs":{"href":{"type":"value","value":"https://nordcraft.com"}},"events":{},"repeat":null,"children":[]},"k4kdAiuEsuqbJ7Bde4kzx":{"tag":"h2","type":"element","attrs":{},"style":{"font-size":"var(--font-size-xl)"},"events":{},"classes":{},"children":["OKWInTu4ZPALaHWTxlFfj"],"style-variables":[]},"kV05rMafX2BTh3oGXz0K8":{"tag":"button","type":"element","attrs":{},"style":{"cursor":"pointer","background":"#afcaee","padding-top":"8px","padding-left":"8px","padding-right":"8px","padding-bottom":"8px","border-top-left-radius":"8px","border-top-right-radius":"8px","border-bottom-left-radius":"8px","border-bottom-right-radius":"8px"},"events":{"click":{"actions":[{"name":"@toddle/saveToLocalStorage","label":"Save to local storage","arguments":[{"name":"Key","formula":{"type":"value","value":"my_key"}},{"name":"Value","formula":{"type":"value","value":"awesome value"}}]}],"trigger":"click"}},"classes":{},"children":["kXkQVZspvQh5m-T4OCY9Y"],"variants":[{"hover":true,"style":{"background":"#5c8bf0"}},{"style":{"background":"#5050f7"},"active":true}],"style-variables":[]},"kXkQVZspvQh5m-T4OCY9Y":{"type":"text","value":{"type":"value","value":"Save in local storage"}},"kXknvjkiHozh7-lH0NfCE":{"type":"text","value":{"type":"value","value":"Perform actions"}},"mavhc8aBSpBbefMxKUmxq":{"tag":"h2","type":"element","attrs":{},"style":{"font-size":"var(--font-size-xl)"},"events":{},"classes":{},"children":["tQqgQw-aQmlcWZAz1iFYZ"],"style-variables":[]},"qPOhO6iFBq2c4xfuaTSI7":{"tag":"div","type":"element","attrs":{},"style":{"row-gap":"8px","column-gap":"8px","flex-direction":"row"},"events":{},"classes":{},"children":["DNAToE8J5QYxLvDVvOAaB","kV05rMafX2BTh3oGXz0K8"]},"sCKtwkz02vg_cf1MR2cFe":{"type":"text","value":{"path":["ListItem","Item","name"],"type":"path"}},"tQqgQw-aQmlcWZAz1iFYZ":{"type":"text","value":{"type":"value","value":"Favorite Owen Wilson movie:"}},"urcpUdMessXz6BrkV2rI-":{"name":"test-component","type":"component","attrs":{"href":{"type":"value","value":"https://github.com/nordcraftengine/nordcraft"}},"events":{},"repeat":null,"children":[]},"vPHrh8QAidCHOIVEJ_SYc":{"tag":"li","type":"element","attrs":{},"style":{},"events":{},"repeat":{"path":["Variables","Items"],"type":"path"},"classes":{},"children":["7zorxtwn-54JBGgk6ZKvN"],"style-variables":[]},"wnZL1kvMevNKga0XZwmKE":{"type":"text","value":{"name":"@toddle/concatenate","type":"function","arguments":[{"name":"0","type":{"type":"Array \\| String"},"formula":{"path":["Apis","WOW API","data","0","movie"],"type":"path"}},{"name":"0","type":{"type":"Array \\| String"},"formula":{"type":"value","value":" from "}},{"name":"0","type":{"type":"Array \\| String"},"formula":{"path":["Apis","WOW API","data","0","year"],"type":"path"}}],"display_name":"Concatenate","variableArguments":true}}},"route":{"info":{"title":{"formula":{"type":"value","value":"Nordcraft Blank Template"}},"language":{"formula":{"type":"value","value":"en"}},"description":{"formula":{"type":"value","value":"Get started quickly with the blank template from Nordcraft."}}},"path":[],"query":{}},"events":[],"onLoad":{"actions":[],"trigger":"load"},"functions":{},"variables":{"Items":{"initialValue":{"type":"array","arguments":[{"Name":0,"formula":{"type":"object","arguments":[{"Name":0,"name":"name","formula":{"type":"value","value":"John"}}]}},{"Name":0,"formula":{"type":"object","arguments":[{"Name":0,"name":"name","formula":{"type":"value","value":"Johny"}}]}},{"Name":0,"formula":{"type":"object","arguments":[{"Name":0,"name":"name","formula":{"type":"value","value":"Jonny"}}]}}]}}},"attributes":{}},"test-component":{"apis":{},"name":"test-component","nodes":{"root":{"tag":"a","type":"element","attrs":{"href":{"path":["Attributes","href"],"type":"path"},"data-prerender":{"type":"value","value":"none"}},"style":{"color":"#353ede","font-size":"var(--font-size-sm)","padding-top":"4px","padding-left":"4px","padding-right":"4px","padding-bottom":"4px","text-decoration-line":"underline"},"events":{},"classes":{},"children":["TNilrfW71YLeD75DJt9iC"],"variants":[{"style":{"color":"#861ebe","text-decoration-line":"underline"},"visited":true}],"style-variables":[]},"TNilrfW71YLeD75DJt9iC":{"type":"text","value":{"path":["Attributes","href"],"type":"path"}}},"events":[],"onLoad":null,"formulas":{},"variables":{},"attributes":{"href":{"name":"href","testValue":"https://ecosia.org"}}}},"actions":{},"formulas":{},"config":{"meta":{"robots":null}},"packages":{"best_like_button":{"actions":{},"formulas":{},"manifest":{"name":"best_like_button","commit":"f25ab6fca0db952c0394f101e656e88a3efa7eb5"},"components":{"best-like-button":{"apis":{},"name":"best-like-button","nodes":{"root":{"tag":"button","type":"element","attrs":{"aria-label":{"name":"@toddle/concatenate","type":"function","arguments":[{"name":"0","type":{"type":"Array \\| String"},"formula":{"type":"value","value":"Click to "}},{"name":"0","type":{"type":"Array \\| String"},"formula":{"type":"switch","cases":[{"formula":{"type":"value","value":"like"},"condition":{"path":["Attributes","liked"],"type":"path"}}],"default":{"type":"value","value":"unlike"}}},{"name":"0","type":{"type":"Array \\| String"},"formula":{"type":"value","value":" "}},{"name":"0","type":{"type":"Array \\| String"},"formula":{"path":["Attributes","item_name"],"type":"path"}}],"display_name":"Concatenate","variableArguments":true}},"style":{"width":"fit-content","cursor":"pointer","height":"fit-content","display":"flex","row-gap":"0.5rem","position":"relative","background":"","column-gap":"0.5rem","transition":"all 300ms ease ","align-items":"center","padding-top":"8px","padding-left":"8px","padding-right":"8px","flex-direction":"row","padding-bottom":"8px","justify-content":"center","border-top-left-radius":"var(--border_radius)","border-top-right-radius":"var(--border_radius)","border-bottom-left-radius":"var(--border_radius)","border-bottom-right-radius":"var(--border_radius)"},"events":{"click":{"actions":[{"data":{"type":"value","value":""},"type":"TriggerEvent","event":"click-best-like-button"},{"data":{"type":"value","value":true},"type":"SetVariable","variable":"clicked"},{"data":{"name":"@toddle/not","type":"function","arguments":[{"name":"Input","type":{"type":"Boolean"},"formula":{"path":["Variables","liked"],"type":"path"}}],"display_name":"Not"},"type":"SetVariable","variable":"liked"}],"trigger":"click"},"animationend":{"actions":[{"data":{"type":"value","value":false},"type":"SetVariable","variable":"clicked"}],"trigger":"animationend"}},"classes":{"clicked":{"formula":{"path":["Variables","clicked"],"type":"path"}}},"children":["0zXILDCnIMeX0LRIZjz3u","VacuFa8yk8_vT97XQUbyU"],"variants":[{"style":{"outline-color":"var(--focus_outline_color)","outline-style":"solid","outline-width":"var(--focus_outline_width)"},"focus-visible":true}],"animations":{},"styleVariables":{},"style-variables":[{"name":"size","unit":"px","formula":{"path":["Attributes","size"],"type":"path"},"category":"spacing"},{"name":"border_radius","unit":"px","formula":{"path":["Attributes","border_radius"],"type":"path"},"category":"border-radius"},{"name":"focus_outline_width","unit":"px","formula":{"path":["Attributes","focus_outline_width"],"type":"path"},"category":"spacing"},{"name":"focus_outline_color","unit":"","formula":{"path":["Attributes","focus_outline_color"],"type":"path"},"category":"color"}]},"0zXILDCnIMeX0LRIZjz3u":{"tag":"svg","type":"element","attrs":{"fill":{"type":"switch","cases":[{"formula":{"path":["Attributes","color"],"type":"path"},"condition":{"path":["Variables","liked"],"type":"path"}}],"default":{"type":"value","value":"none"}},"xmlns":{"type":"value","value":"http://www.w3.org/2000/svg"},"stroke":{"path":["Attributes","border_color"],"type":"path"},"viewBox":{"type":"value","value":"0 0 24 24"},"stroke-width":{"type":"value","value":"1.5"}},"style":{"width":"var(--size)","height":"var(--size)"},"events":{},"classes":{"clicked-and-liked":{"formula":{"type":"and","arguments":[{"formula":{"path":["Variables","clicked"],"type":"path"}},{"formula":{"path":["Variables","liked"],"type":"path"}}]}},"clicked-and-unliked":{"formula":{"type":"and","arguments":[{"formula":{"path":["Variables","clicked"],"type":"path"}},{"formula":{"name":"@toddle/not","type":"function","arguments":[{"name":"Input","type":{"type":"Boolean"},"formula":{"path":["Variables","liked"],"type":"path"}}],"display_name":"Not"}}]}}},"children":["aG6M1I6Mtl2LRr0q5MMpe"],"variants":[{"style":{"animation":"1s cubic-bezier(0.42, 0, 0.58, 1) 0ms 1 normal none running animation-fEAIgP, 1s cubic-bezier(0.25, 0.1, 0.25, 1) 0ms 1 normal forwards running animation-bjjowI"},"className":"clicked-and-liked"},{"style":{"animation":"1s ease 0ms 1 normal none running animation-eCPXmj","background":""},"className":"clicked-and-unliked"}],"animations":{"animation-bjjowI":{"a":{"key":"rotate","value":"0deg","position":0},"b":{"key":"rotate","value":"400deg","position":0.7},"bE8RJz":{"key":"rotate","value":"0deg","position":1}},"animation-eCPXmj":{"0":{"key":"scale","value":"1 1","position":0},"1":{"key":"scale","value":"0.9 0.9","position":0.5},"2":{"key":"scale","value":"1 1","position":1}},"animation-fEAIgP":{"0":{"key":"scale","value":"1 1","position":0},"1":{"key":"scale","value":"0.85 0.85","position":0.2},"2":{"key":"scale","value":"1 1","position":1},"NqxMV_":{"key":"scale","value":"1.2 1.2","position":0.7}}},"styleVariables":{},"style-variables":[{"name":"size","unit":"px","formula":{"path":["Attributes","size"],"type":"path"},"category":"spacing"}]},"VacuFa8yk8_vT97XQUbyU":{"tag":"span","type":"element","attrs":{},"style":{"rotate":"0 0 1 var(--rotation)","opacity":"0.6","z-index":"1000","position":"absolute","font-size":"inherit","font-family":"inherit","font-weight":"inherit"},"events":{},"repeat":{"name":"@toddle/range","type":"function","arguments":[{"name":"Min","type":{"type":"Number"},"formula":{"type":"value","value":1}},{"name":"Max","type":{"type":"Number"},"formula":{"path":["Attributes","number_of_hearts"],"type":"path"}}],"display_name":"Range"},"classes":{},"children":["dU_QYk1U9ncxSaPo1iOGG"],"condition":null,"animations":{},"styleVariables":{},"style-variables":[{"name":"rotation","unit":"turn","formula":{"name":"@toddle/divide","type":"function","arguments":[{"name":"Dividend","type":{"type":"Number"},"formula":{"path":["ListItem","Index"],"type":"path"}},{"name":"Divisor","type":{"type":"Number"},"formula":{"path":["Attributes","number_of_hearts"],"type":"path"}}],"display_name":"Divide"},"category":"rotation"}]},"aG6M1I6Mtl2LRr0q5MMpe":{"tag":"path","type":"element","attrs":{"d":{"type":"value","value":"M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z"},"stroke-linecap":{"type":"value","value":"round"},"stroke-linejoin":{"type":"value","value":"round"}},"style":{},"events":{},"classes":{},"children":[],"styleVariables":{}},"dU_QYk1U9ncxSaPo1iOGG":{"tag":"svg","type":"element","attrs":{"fill":{"path":["Attributes","color"],"type":"path"},"xmlns":{"type":"value","value":"http://www.w3.org/2000/svg"},"viewBox":{"type":"value","value":"0 0 24 24"}},"style":{"width":"var(--size)","height":"var(--size)","animation":"1s cubic-bezier(0.42, 0, 0.58, 1) var(--delay) 1 normal forwards running animation-dJXdoH"},"events":{},"classes":{},"children":["hbUXossrsDKOwckeL9T0K"],"condition":{"type":"and","arguments":[{"formula":{"path":["Variables","clicked"],"type":"path"}},{"formula":{"path":["Variables","liked"],"type":"path"}}]},"animations":{"animation-dJXdoH":{"0":{"key":"translate","value":"0 0","position":0},"1":{"key":"translate","value":"0 calc(var(--distance) * -1)","position":0.3},"CIGTjx":{"key":"translate","value":"0px","position":1},"qcUIWS":{"key":"translate","value":"0 calc(var(--distance) * -1)","position":0.8}}},"styleVariables":{},"style-variables":[{"name":"size","unit":"px","formula":{"name":"@toddle/divide","type":"function","arguments":[{"name":"Dividend","type":{"type":"Number"},"formula":{"path":["Attributes","size"],"type":"path"}},{"name":"Divisor","type":{"type":"Number"},"formula":{"type":"value","value":2.5}}],"display_name":"Divide"},"category":"spacing"},{"name":"distance","unit":"px","formula":{"name":"@toddle/multiply","type":"function","arguments":[{"name":"0","type":{"type":"Number"},"formula":{"path":["Attributes","size"],"type":"path"}},{"name":"1","type":{"type":"Number"},"formula":{"type":"value","value":0.75}}],"display_name":"Multiply","variableArguments":true},"category":"spacing"},{"name":"delay","unit":"ms","formula":{"name":"@toddle/divide","type":"function","arguments":[{"name":"Dividend","type":{"type":"Number"},"formula":{"type":"value","value":100}},{"name":"Divisor","type":{"type":"Number"},"formula":{"name":"@toddle/add","type":"function","arguments":[{"name":"0","type":{"type":"Number"},"formula":{"path":["ListItem","Index"],"type":"path"}},{"name":"1","type":{"type":"Number"},"formula":{"type":"value","value":1}}],"display_name":"Add","variableArguments":true}}],"display_name":"Divide"},"category":"duration"}]},"hbUXossrsDKOwckeL9T0K":{"tag":"path","type":"element","attrs":{"d":{"type":"value","value":"M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z"},"stroke-linecap":{"type":"value","value":"round"},"stroke-linejoin":{"type":"value","value":"round"}},"style":{},"events":{},"classes":{},"children":[],"styleVariables":{}}},"events":[{"name":"click-best-like-button","dummyEvent":{"name":"click"}}],"exported":true,"variables":{"liked":{"initialValue":{"path":["Attributes","liked"],"type":"path"}},"clicked":{"initialValue":{"type":"value","value":false}}},"workflows":{},"attributes":{"size":{"name":"size","testValue":44},"color":{"name":"color","testValue":"red"},"liked":{"name":"liked","testValue":false},"item_name":{"name":"item_name","testValue":"package"},"border_color":{"name":"border_color","testValue":"white"},"border_radius":{"name":"border_radius","testValue":6},"number_of_hearts":{"name":"number_of_hearts","testValue":10},"focus_outline_color":{"name":"focus_outline_color","testValue":"red"},"focus_outline_width":{"name":"focus_outline_width","testValue":2}},"onAttributeChange":{"actions":[{"data":{"path":["Attributes","liked"],"type":"path"},"type":"SetVariable","variable":"liked"}],"trigger":"Attribute change"}}}}},"themes":{"Default":{"color":[{"name":"grey","tokens":[{"name":"grey-50","type":"value","value":"#FAFAFA"},{"name":"grey-100","type":"value","value":"#F5F5F5"},{"name":"grey-200","type":"value","value":"#E5E5E5"},{"name":"grey-300","type":"value","value":"#D4D4D4"},{"name":"grey-400","type":"value","value":"#A3A3A3"},{"name":"grey-500","type":"value","value":"#737373"},{"name":"grey-600","type":"value","value":"#525252"},{"name":"grey-700","type":"value","value":"#404040"},{"name":"grey-800","type":"value","value":"#262626"},{"name":"grey-900","type":"value","value":"#171717"}]},{"name":"red","tokens":[{"name":"red-50","type":"value","value":"#FEF2F2"},{"name":"red-100","type":"value","value":"#FEE2E2"},{"name":"red-200","type":"value","value":"#FECACA"},{"name":"red-300","type":"value","value":"#FCA5A5"},{"name":"red-400","type":"value","value":"#F87171"},{"name":"red-500","type":"value","value":"#EF4444"},{"name":"red-600","type":"value","value":"#DC2626"},{"name":"red-700","type":"value","value":"#B91C1C"},{"name":"red-800","type":"value","value":"#991B1B"},{"name":"red-900","type":"value","value":"#7F1D1D"}]},{"name":"blue","tokens":[{"name":"blue-50","type":"value","value":"#EFF6FF"},{"name":"blue-100","type":"value","value":"#DBEAFE"},{"name":"blue-200","type":"value","value":"#BFDBFE"},{"name":"blue-300","type":"value","value":"#93C5FD"},{"name":"blue-400","type":"value","value":"#60A5FA"},{"name":"blue-500","type":"value","value":"#3B82F6"},{"name":"blue-600","type":"value","value":"#2563EB"},{"name":"blue-700","type":"value","value":"#1D4ED8"},{"name":"blue-800","type":"value","value":"#1E40AF"},{"name":"blue-900","type":"value","value":"#1E3A8A"}]},{"name":"lime","tokens":[{"name":"lime-50","type":"value","value":"#F7FEE7"},{"name":"lime-100","type":"value","value":"#ECFCCB"},{"name":"lime-200","type":"value","value":"#D9F99D"},{"name":"lime-300","type":"value","value":"#BEF264"},{"name":"lime-400","type":"value","value":"#A3E635"},{"name":"lime-500","type":"value","value":"#84CC16"},{"name":"lime-600","type":"value","value":"#65A30D"},{"name":"lime-700","type":"value","value":"#4D7C0F"},{"name":"lime-800","type":"value","value":"#3F6212"},{"name":"lime-900","type":"value","value":"#365314"}]},{"name":"pink","tokens":[{"name":"pink-50","type":"value","value":"#FDF2F8"},{"name":"pink-100","type":"value","value":"#FCE7F3"},{"name":"pink-200","type":"value","value":"#FBCFE8"},{"name":"pink-300","type":"value","value":"#F9A8D4"},{"name":"pink-400","type":"value","value":"#F472B6"},{"name":"pink-500","type":"value","value":"#EC4899"},{"name":"pink-600","type":"value","value":"#DB2777"},{"name":"pink-700","type":"value","value":"#BE185D"},{"name":"pink-800","type":"value","value":"#9D174D"},{"name":"pink-900","type":"value","value":"#831843"}]},{"name":"teal","tokens":[{"name":"teal-50","type":"value","value":"#F0FDFA"},{"name":"teal-100","type":"value","value":"#CCFBF1"},{"name":"teal-200","type":"value","value":"#99F6E4"},{"name":"teal-300","type":"value","value":"#5EEAD4"},{"name":"teal-400","type":"value","value":"#2DD4BF"},{"name":"teal-500","type":"value","value":"#14B8A6"},{"name":"teal-600","type":"value","value":"#0D9488"},{"name":"teal-700","type":"value","value":"#0F766E"},{"name":"teal-800","type":"value","value":"#115E59"},{"name":"teal-900","type":"value","value":"#134E4A"}]},{"name":"green","tokens":[{"name":"green-50","type":"value","value":"#ECFDF5"},{"name":"green-100","type":"value","value":"#D1FAE5"},{"name":"green-200","type":"value","value":"#A7F3D0"},{"name":"green-300","type":"value","value":"#6EE7B7"},{"name":"green-400","type":"value","value":"#34D399"},{"name":"green-500","type":"value","value":"#10B981"},{"name":"green-600","type":"value","value":"#059669"},{"name":"green-700","type":"value","value":"#047857"},{"name":"green-800","type":"value","value":"#065F46"},{"name":"green-900","type":"value","value":"#064E3B"}]},{"name":"purple","tokens":[{"name":"purple-50","type":"value","value":"#F5F3FF"},{"name":"purple-100","type":"value","value":"#EDE9FE"},{"name":"purple-200","type":"value","value":"#DDD6FE"},{"name":"purple-300","type":"value","value":"#C4B5FD"},{"name":"purple-400","type":"value","value":"#A78BFA"},{"name":"purple-500","type":"value","value":"#8B5CF6"},{"name":"purple-600","type":"value","value":"#7C3AED"},{"name":"purple-700","type":"value","value":"#6D28D9"},{"name":"purple-800","type":"value","value":"#5B21B6"},{"name":"purple-900","type":"value","value":"#4C1D95"}]},{"name":"yellow","tokens":[{"name":"yellow-50","type":"value","value":"#FFFBEB"},{"name":"yellow-100","type":"value","value":"#FEF3C7"},{"name":"yellow-200","type":"value","value":"#FDE68A"},{"name":"yellow-300","type":"value","value":"#FCD34D"},{"name":"yellow-400","type":"value","value":"#FBBF24"},{"name":"yellow-500","type":"value","value":"#F59E0B"},{"name":"yellow-600","type":"value","value":"#D97706"},{"name":"yellow-700","type":"value","value":"#B45309"},{"name":"yellow-800","type":"value","value":"#92400E"},{"name":"yellow-900","type":"value","value":"#78350F"}]}],"fonts":[{"name":"sans","type":"sans-serif","family":"Inter","provider":"google","variants":[{"url":"https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyeMZ1rib2Bg-4.woff2","name":"100","italic":false,"weight":"100"},{"url":"https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuDyfMZ1rib2Bg-4.woff2","name":"200","italic":false,"weight":"200"},{"url":"https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuOKfMZ1rib2Bg-4.woff2","name":"300","italic":false,"weight":"300"},{"url":"https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfMZ1rib2Bg-4.woff2","name":"regular","italic":false,"weight":"400"},{"url":"https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuI6fMZ1rib2Bg-4.woff2","name":"500","italic":false,"weight":"500"},{"url":"https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuGKYMZ1rib2Bg-4.woff2","name":"600","italic":false,"weight":"600"},{"url":"https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuFuYMZ1rib2Bg-4.woff2","name":"700","italic":false,"weight":"700"},{"url":"https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuDyYMZ1rib2Bg-4.woff2","name":"800","italic":false,"weight":"800"},{"url":"https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuBWYMZ1rib2Bg-4.woff2","name":"900","italic":false,"weight":"900"}]}],"scheme":"dark","shadow":[{"name":"Default","tokens":[{"name":"shadow-sm","type":"value","value":" 0 1px 2px 0 rgba(0, 0, 0, 0.25)"},{"name":"shadow-base","type":"value","value":" 0 1px 3px 0 rgba(0, 0, 0, 0.25), 0 1px 2px 0 rgba(0, 0, 0, 0.25)"},{"name":"shadow-md","type":"value","value":" 0 4px 6px -1px rgba(0, 0, 0, 0.25), 0 2px 4px -1px rgba(0, 0, 0, 0.25)"},{"name":"shadow-lg","type":"value","value":" 0 10px 15px -3px rgba(0, 0, 0, 0.25), 0 4px 6px -2px rgba(0, 0, 0, 0.25)"},{"name":"shadow-xl","type":"value","value":"0 20px 25px -5px rgba(0, 0, 0, 0.25), 0 10px 10px -5px rgba(0, 0, 0, 0.25)"},{"name":"shadow-2xl","type":"value","value":" 0 25px 50px -12px rgba(0, 0, 0, 0.25)"}]}],"spacing":[],"z-index":[],"font-size":[{"name":"Default","tokens":[{"name":"font-size-xxs","type":"value","value":"0.625rem"},{"name":"font-size-xs","type":"value","value":"0.75rem"},{"name":"font-size-sm","type":"value","value":"0.875rem"},{"name":"font-size-base","type":"value","value":"1rem"},{"name":"font-size-lg","type":"value","value":"1.125rem"},{"name":"font-size-xl","type":"value","value":"1.25rem"},{"name":"font-size-2xl","type":"value","value":"1.5rem"},{"name":"font-size-3xl","type":"value","value":"1.875rem"},{"name":"font-size-4xl","type":"value","value":"2.25rem"},{"name":"font-size-5xl","type":"value","value":"3rem"}]}],"font-weight":[{"name":"Default","tokens":[{"name":"font-weight-thin","type":"value","value":"100"},{"name":"font-weight-lighter","type":"value","value":"200"},{"name":"font-weight-light","type":"value","value":"300"},{"name":"font-weight-regular","type":"value","value":"400"},{"name":"font-weight-normal","type":"value","value":"500"},{"name":"font-weight-bold","type":"value","value":"700"},{"name":"font-weight-semi-bold","type":"value","value":"600"},{"name":"font-weight-bolder","type":"value","value":"800"},{"name":"font-weight-black","type":"value","value":"900"}]}],"border-radius":[]}}}} \ No newline at end of file