From ea7d052af93414530b409e0dd4a3478c0dc6f6bb Mon Sep 17 00:00:00 2001 From: Natoandro Date: Thu, 22 May 2025 15:02:31 +0300 Subject: [PATCH 1/8] feat: tg-optimize --- .gitignore | 2 + Cargo.lock | 22 +- Cargo.toml | 3 +- deno.lock | 169 +- src/typegraph/core/src/t.rs | 9 +- src/typegraph/core/src/typedef/float.rs | 13 +- src/typegraph/core/src/types/sdk/core.rs | 13 +- src/typegraph/graph/Cargo.toml | 1 + src/typegraph/graph/src/types/float.rs | 11 +- src/typegraph/optimize/Cargo.toml | 10 + src/typegraph/optimize/src/dedup.rs | 319 ++ src/typegraph/optimize/src/kosaraju.rs | 105 + src/typegraph/optimize/src/lib.rs | 86 + src/typegraph/optimize/src/main.rs | 16 + src/typegraph/schema/Cargo.toml | 15 +- src/typegraph/schema/src/lib.rs | 4 +- src/typegraph/schema/src/types.rs | 21 +- src/typegraph/schema/src/validator/types.rs | 10 +- src/typegraph/schema/src/validator/value.rs | 10 +- tools/tree-view-web.ts | 196 +- tools/tree/.gitignore | 24 + tools/tree/.vite/deps/_metadata.json | 8 + tools/tree/.vite/deps/package.json | 3 + tools/tree/README.md | 54 + tools/tree/dist/assets/index-B7TWQuis.css | 1 + tools/tree/dist/assets/index-en07UP6E.js | 59 + tools/tree/dist/index.html | 14 + tools/tree/dist/logo.svg | 39 + tools/tree/eslint.config.js | 28 + tools/tree/index.html | 13 + tools/tree/package.json | 34 + tools/tree/pnpm-lock.yaml | 2913 +++++++++++++++++++ tools/tree/public/logo.svg | 1 + tools/tree/src/App.css | 48 + tools/tree/src/App.tsx | 166 ++ tools/tree/src/components/Type.tsx | 171 ++ tools/tree/src/index.css | 47 + tools/tree/src/main.tsx | 13 + tools/tree/src/vite-env.d.ts | 4 + tools/tree/tsconfig.app.json | 25 + tools/tree/tsconfig.json | 7 + tools/tree/tsconfig.node.json | 23 + tools/tree/vite.config.ts | 18 + 43 files changed, 4512 insertions(+), 236 deletions(-) create mode 100644 src/typegraph/optimize/Cargo.toml create mode 100644 src/typegraph/optimize/src/dedup.rs create mode 100644 src/typegraph/optimize/src/kosaraju.rs create mode 100644 src/typegraph/optimize/src/lib.rs create mode 100644 src/typegraph/optimize/src/main.rs create mode 100644 tools/tree/.gitignore create mode 100644 tools/tree/.vite/deps/_metadata.json create mode 100644 tools/tree/.vite/deps/package.json create mode 100644 tools/tree/README.md create mode 100644 tools/tree/dist/assets/index-B7TWQuis.css create mode 100644 tools/tree/dist/assets/index-en07UP6E.js create mode 100644 tools/tree/dist/index.html create mode 100644 tools/tree/dist/logo.svg create mode 100644 tools/tree/eslint.config.js create mode 100644 tools/tree/index.html create mode 100644 tools/tree/package.json create mode 100644 tools/tree/pnpm-lock.yaml create mode 120000 tools/tree/public/logo.svg create mode 100644 tools/tree/src/App.css create mode 100644 tools/tree/src/App.tsx create mode 100644 tools/tree/src/components/Type.tsx create mode 100644 tools/tree/src/index.css create mode 100644 tools/tree/src/main.tsx create mode 100644 tools/tree/src/vite-env.d.ts create mode 100644 tools/tree/tsconfig.app.json create mode 100644 tools/tree/tsconfig.json create mode 100644 tools/tree/tsconfig.node.json create mode 100644 tools/tree/vite.config.ts diff --git a/.gitignore b/.gitignore index 2c8c2027e0..4ec0d59753 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ __pycache__/ *.py[cod] dist/ +!tools/tree/dist/ .ruff_cache **/.terraform/* @@ -55,3 +56,4 @@ examples/typegraphs/**/*.wasm src/pyrt_wit_wire/wit_wire /.metatype/ +/vivavox/ diff --git a/Cargo.lock b/Cargo.lock index d9ca7d1667..1070203d6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8130,11 +8130,13 @@ dependencies = [ [[package]] name = "ordered-float" -version = "4.3.0" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d501f1a72f71d3c063a6bbc8f7271fa73aa09fe5d6283b6571e2ed176a2537" +checksum = "e2c1f9f56e534ac6a9b8a4600bdf0f530fb393b5f393e7b4d03489c3cf0c3f01" dependencies = [ "num-traits", + "rand 0.8.5", + "serde", ] [[package]] @@ -9488,6 +9490,7 @@ dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", + "serde", ] [[package]] @@ -9526,6 +9529,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom 0.2.15", + "serde", ] [[package]] @@ -12279,12 +12283,23 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "tg-optimize" +version = "0.5.1-rc.3" +dependencies = [ + "color-eyre", + "serde", + "serde_json", + "tg_schema", +] + [[package]] name = "tg_schema" version = "0.5.1-rc.3" dependencies = [ "anyhow", "indexmap 2.6.0", + "ordered-float 5.0.0", "serde", "serde_json", "serde_with", @@ -13085,6 +13100,7 @@ dependencies = [ "enum_dispatch", "indexmap 2.6.0", "insta", + "ordered-float 5.0.0", "paste", "serde", "serde_json", @@ -13108,7 +13124,7 @@ dependencies = [ "insta", "metagen", "once_cell", - "ordered-float 4.3.0", + "ordered-float 5.0.0", "paste", "ptree", "regex", diff --git a/Cargo.toml b/Cargo.toml index 4730619420..b4c21056ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ members = [ "src/typegate_api", "src/typegraph/core", "src/typegraph/graph", + "src/typegraph/optimize", "src/typegraph/schema", "src/utils/archive", "src/utils/grpc", @@ -131,7 +132,7 @@ dashmap = "6.1.0" connection-string = "0.2.0" chrono = { version = "0.4.38", features = ["serde"] } tera = { version = "1.20", default-features = false } -ordered-float = "4.3.0" +ordered-float = { version = "5.0.0", features = ["std", "serde"] } graphql-parser = "0.4.0" uuid = "1.10.0" rustpython-parser = "0.4.0" diff --git a/deno.lock b/deno.lock index 4a49a91f62..eba4087c3f 100644 --- a/deno.lock +++ b/deno.lock @@ -4,49 +4,55 @@ "specifiers": { "jsr:@david/dax@0.41.0": "jsr:@david/dax@0.41.0", "jsr:@david/which@^0.4.1": "jsr:@david/which@0.4.1", + "jsr:@oak/commons@^1.0": "jsr:@oak/commons@1.0.1", + "jsr:@oak/oak": "jsr:@oak/oak@17.1.4", "jsr:@std/archive@^0.225.0": "jsr:@std/archive@0.225.4", "jsr:@std/assert@^0.221.0": "jsr:@std/assert@0.221.0", - "jsr:@std/assert@^1.0.12": "jsr:@std/assert@1.0.12", - "jsr:@std/assert@^1.0.3": "jsr:@std/assert@1.0.12", - "jsr:@std/assert@^1.0.6": "jsr:@std/assert@1.0.12", - "jsr:@std/async@^1.0.3": "jsr:@std/async@1.0.12", + "jsr:@std/assert@^1.0": "jsr:@std/assert@1.0.10", + "jsr:@std/assert@^1.0.3": "jsr:@std/assert@1.0.10", + "jsr:@std/assert@^1.0.6": "jsr:@std/assert@1.0.10", "jsr:@std/bytes@^0.221.0": "jsr:@std/bytes@0.221.0", + "jsr:@std/bytes@^1.0": "jsr:@std/bytes@1.0.5", "jsr:@std/bytes@^1.0.2": "jsr:@std/bytes@1.0.5", "jsr:@std/bytes@^1.0.3": "jsr:@std/bytes@1.0.4", "jsr:@std/bytes@^1.0.5": "jsr:@std/bytes@1.0.5", "jsr:@std/cli@^1.0.3": "jsr:@std/cli@1.0.10", "jsr:@std/cli@^1.0.4": "jsr:@std/cli@1.0.10", "jsr:@std/collections@^1.0.5": "jsr:@std/collections@1.0.9", + "jsr:@std/crypto@^1.0": "jsr:@std/crypto@1.0.3", "jsr:@std/crypto@^1.0.2": "jsr:@std/crypto@1.0.3", "jsr:@std/crypto@^1.0.3": "jsr:@std/crypto@1.0.3", + "jsr:@std/encoding@^1.0": "jsr:@std/encoding@1.0.6", "jsr:@std/encoding@^1.0.2": "jsr:@std/encoding@1.0.6", + "jsr:@std/encoding@^1.0.5": "jsr:@std/encoding@1.0.6", "jsr:@std/fmt@^0.221.0": "jsr:@std/fmt@0.221.0", "jsr:@std/fmt@^1.0.0": "jsr:@std/fmt@1.0.4", "jsr:@std/fmt@^1.0.4": "jsr:@std/fmt@1.0.4", "jsr:@std/fs@0.221.0": "jsr:@std/fs@0.221.0", - "jsr:@std/fs@^1.0.1": "jsr:@std/fs@1.0.9", + "jsr:@std/fs@^1.0.1": "jsr:@std/fs@1.0.16", "jsr:@std/fs@^1.0.16": "jsr:@std/fs@1.0.16", "jsr:@std/fs@^1.0.9": "jsr:@std/fs@1.0.16", + "jsr:@std/http@^1.0": "jsr:@std/http@1.0.12", "jsr:@std/http@^1.0.3": "jsr:@std/http@1.0.12", - "jsr:@std/internal@^1.0.6": "jsr:@std/internal@1.0.6", + "jsr:@std/internal@^1.0.5": "jsr:@std/internal@1.0.5", "jsr:@std/io@0.221.0": "jsr:@std/io@0.221.0", "jsr:@std/io@^0.221.0": "jsr:@std/io@0.221.0", "jsr:@std/io@^0.224.5": "jsr:@std/io@0.224.9", "jsr:@std/io@^0.224.9": "jsr:@std/io@0.224.9", "jsr:@std/io@^0.225.0": "jsr:@std/io@0.225.0", "jsr:@std/log@^0.224.5": "jsr:@std/log@0.224.13", + "jsr:@std/media-types@^1.0": "jsr:@std/media-types@1.1.0", "jsr:@std/path": "jsr:@std/path@1.0.8", "jsr:@std/path@0.221.0": "jsr:@std/path@0.221.0", "jsr:@std/path@^0.221.0": "jsr:@std/path@0.221.0", + "jsr:@std/path@^1.0": "jsr:@std/path@1.0.8", "jsr:@std/path@^1.0.2": "jsr:@std/path@1.0.8", "jsr:@std/path@^1.0.8": "jsr:@std/path@1.0.8", "jsr:@std/semver@^1.0.1": "jsr:@std/semver@1.0.3", "jsr:@std/streams@0.221.0": "jsr:@std/streams@0.221.0", "jsr:@std/streams@1": "jsr:@std/streams@1.0.9", - "jsr:@std/testing@^1.0.1": "jsr:@std/testing@1.0.11", "jsr:@std/text@^1.0.7": "jsr:@std/text@1.0.10", "jsr:@std/uuid@^1.0.1": "jsr:@std/uuid@1.0.4", - "jsr:@std/yaml@^1.0.4": "jsr:@std/yaml@1.0.5", "npm:@noble/hashes@1.4.0": "npm:@noble/hashes@1.4.0", "npm:@sentry/node@7.70.0": "npm:@sentry/node@7.70.0", "npm:@sinonjs/fake-timers@13.0.5": "npm:@sinonjs/fake-timers@13.0.5", @@ -58,7 +64,7 @@ "npm:marked": "npm:marked@15.0.6", "npm:mathjs@11.11.1": "npm:mathjs@11.11.1", "npm:multiformats@13.1.0": "npm:multiformats@13.1.0", - "npm:pg@8.12.0": "npm:pg@8.12.0", + "npm:path-to-regexp@^6.3.0": "npm:path-to-regexp@6.3.0", "npm:tree-sitter-typescript@^0.23.0": "npm:tree-sitter-typescript@0.23.2_tree-sitter@0.21.1", "npm:tree-sitter@^0.21.1": "npm:tree-sitter@0.21.1", "npm:validator@13.12.0": "npm:validator@13.12.0", @@ -81,6 +87,29 @@ "@david/which@0.4.1": { "integrity": "896a682b111f92ab866cc70c5b4afab2f5899d2f9bde31ed00203b9c250f225e" }, + "@oak/commons@1.0.1": { + "integrity": "889ff210f0b4292591721be07244ecb1b5c118742f5273c70cf30d7cd4184d0c", + "dependencies": [ + "jsr:@std/assert@^1.0", + "jsr:@std/bytes@^1.0", + "jsr:@std/crypto@^1.0", + "jsr:@std/encoding@^1.0", + "jsr:@std/http@^1.0", + "jsr:@std/media-types@^1.0" + ] + }, + "@oak/oak@17.1.4": { + "integrity": "60530b582bf276ff741e39cc664026781aa08dd5f2bc5134d756cc427bf2c13e", + "dependencies": [ + "jsr:@oak/commons@^1.0", + "jsr:@std/assert@^1.0", + "jsr:@std/bytes@^1.0", + "jsr:@std/http@^1.0", + "jsr:@std/media-types@^1.0", + "jsr:@std/path@^1.0", + "npm:path-to-regexp@^6.3.0" + ] + }, "@std/archive@0.225.4": { "integrity": "59fe5d1834cbb6a2a7913b102d41c11d51475328d5b843bea75b94a40b44a115", "dependencies": [ @@ -90,15 +119,12 @@ "@std/assert@0.221.0": { "integrity": "a5f1aa6e7909dbea271754fd4ab3f4e687aeff4873b4cef9a320af813adb489a" }, - "@std/assert@1.0.12": { - "integrity": "08009f0926dda9cbd8bef3a35d3b6a4b964b0ab5c3e140a4e0351fbf34af5b9a", + "@std/assert@1.0.10": { + "integrity": "59b5cbac5bd55459a19045d95cc7c2ff787b4f8527c0dd195078ff6f9481fbb3", "dependencies": [ - "jsr:@std/internal@^1.0.6" + "jsr:@std/internal@^1.0.5" ] }, - "@std/async@1.0.12": { - "integrity": "d1bfcec459e8012846fe4e38dfc4241ab23240ecda3d8d6dfcf6d81a632e803d" - }, "@std/bytes@0.221.0": { "integrity": "64a047011cf833890a4a2ab7293ac55a1b4f5a050624ebc6a0159c357de91966" }, @@ -146,10 +172,13 @@ ] }, "@std/http@1.0.12": { - "integrity": "85246d8bfe9c8e2538518725b158bdc31f616e0869255f4a8d9e3de919cab2aa" + "integrity": "85246d8bfe9c8e2538518725b158bdc31f616e0869255f4a8d9e3de919cab2aa", + "dependencies": [ + "jsr:@std/encoding@^1.0.5" + ] }, - "@std/internal@1.0.6": { - "integrity": "9533b128f230f73bd209408bb07a4b12f8d4255ab2a4d22a1fd6d87304aca9a4" + "@std/internal@1.0.5": { + "integrity": "54a546004f769c1ac9e025abd15a76b6671ddc9687e2313b67376125650dc7ba" }, "@std/io@0.221.0": { "integrity": "faf7f8700d46ab527fa05cc6167f4b97701a06c413024431c6b4d207caa010da", @@ -175,6 +204,9 @@ "jsr:@std/io@^0.225.0" ] }, + "@std/media-types@1.1.0": { + "integrity": "c9d093f0c05c3512932b330e3cc1fe1d627b301db33a4c2c2185c02471d6eaa4" + }, "@std/path@0.221.0": { "integrity": "0a36f6b17314ef653a3a1649740cc8db51b25a133ecfe838f20b79a56ebe0095", "dependencies": [ @@ -199,15 +231,6 @@ "jsr:@std/bytes@^1.0.5" ] }, - "@std/testing@1.0.11": { - "integrity": "12b3db12d34f0f385a26248933bde766c0f8c5ad8b6ab34d4d38f528ab852f48", - "dependencies": [ - "jsr:@std/assert@^1.0.12", - "jsr:@std/fs@^1.0.16", - "jsr:@std/internal@^1.0.6", - "jsr:@std/path@^1.0.8" - ] - }, "@std/text@1.0.10": { "integrity": "9dcab377450253c0efa9a9a0c731040bfd4e1c03f8303b5934381467b7954338" }, @@ -217,9 +240,6 @@ "jsr:@std/bytes@^1.0.2", "jsr:@std/crypto@^1.0.3" ] - }, - "@std/yaml@1.0.5": { - "integrity": "71ba3d334305ee2149391931508b2c293a8490f94a337eef3a09cade1a2a2742" } }, "npm": { @@ -443,73 +463,10 @@ "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", "dependencies": {} }, - "pg-cloudflare@1.1.1": { - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "dependencies": {} - }, - "pg-connection-string@2.7.0": { - "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==", + "path-to-regexp@6.3.0": { + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", "dependencies": {} }, - "pg-int8@1.0.1": { - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "dependencies": {} - }, - "pg-pool@3.8.0_pg@8.12.0": { - "integrity": "sha512-VBw3jiVm6ZOdLBTIcXLNdSotb6Iy3uOCwDGFAksZCXmi10nyRvnP2v3jl4d+IsLYRyXf6o9hIm/ZtUzlByNUdw==", - "dependencies": { - "pg": "pg@8.12.0" - } - }, - "pg-protocol@1.8.0": { - "integrity": "sha512-jvuYlEkL03NRvOoyoRktBK7+qU5kOvlAwvmrH8sr3wbLrOdVWsRxQfz8mMy9sZFsqJ1hEWNfdWKI4SAmoL+j7g==", - "dependencies": {} - }, - "pg-types@2.2.0": { - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "dependencies": { - "pg-int8": "pg-int8@1.0.1", - "postgres-array": "postgres-array@2.0.0", - "postgres-bytea": "postgres-bytea@1.0.0", - "postgres-date": "postgres-date@1.0.7", - "postgres-interval": "postgres-interval@1.2.0" - } - }, - "pg@8.12.0": { - "integrity": "sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ==", - "dependencies": { - "pg-cloudflare": "pg-cloudflare@1.1.1", - "pg-connection-string": "pg-connection-string@2.7.0", - "pg-pool": "pg-pool@3.8.0_pg@8.12.0", - "pg-protocol": "pg-protocol@1.8.0", - "pg-types": "pg-types@2.2.0", - "pgpass": "pgpass@1.0.5" - } - }, - "pgpass@1.0.5": { - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "dependencies": { - "split2": "split2@4.2.0" - } - }, - "postgres-array@2.0.0": { - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "dependencies": {} - }, - "postgres-bytea@1.0.0": { - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", - "dependencies": {} - }, - "postgres-date@1.0.7": { - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "dependencies": {} - }, - "postgres-interval@1.2.0": { - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "dependencies": { - "xtend": "xtend@4.0.2" - } - }, "regenerator-runtime@0.14.1": { "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", "dependencies": {} @@ -518,10 +475,6 @@ "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", "dependencies": {} }, - "split2@4.2.0": { - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "dependencies": {} - }, "tiny-emitter@2.1.0": { "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", "dependencies": {} @@ -566,10 +519,6 @@ "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", "dependencies": {} }, - "xtend@4.0.2": { - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dependencies": {} - }, "yaml@2.7.0": { "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", "dependencies": {} @@ -1520,19 +1469,5 @@ "https://raw.githubusercontent.com/metatypedev/ghjk/v0.2.2/utils/unarchive.ts": "f6d0e9e75f470eeef5aecd0089169f4350fc30ebfdc05466bb7b30042294d6d3", "https://raw.githubusercontent.com/metatypedev/ghjk/v0.2.2/utils/url.ts": "e1ada6fd30fc796b8918c88456ea1b5bbd87a07d0a0538b092b91fd2bb9b7623", "https://raw.githubusercontent.com/metatypedev/ghjk/v0.2.2/utils/worker.ts": "ac4caf72a36d2e4af4f4e92f2e0a95f9fc2324b568640f24c7c2ff6dc0c11d62" - }, - "workspace": { - "members": { - "tests": { - "dependencies": [ - "jsr:@std/async@^1.0.3", - "jsr:@std/streams@^1.0.2", - "jsr:@std/testing@^1.0.1", - "jsr:@std/yaml@^1.0.4", - "npm:json-schema-faker@0.5.3", - "npm:pg@8.12.0" - ] - } - } } } diff --git a/src/typegraph/core/src/t.rs b/src/typegraph/core/src/t.rs index 97c971a319..b5e828a38a 100644 --- a/src/typegraph/core/src/t.rs +++ b/src/typegraph/core/src/t.rs @@ -10,6 +10,7 @@ use crate::sdk::core::{ use crate::types::RefAttr; use crate::types::TypeRefBuilder; use crate::types::{Named as _, TypeId, TypeRef}; +use ordered_float::NotNan; #[cfg(test)] use tg_schema::{Injection, InjectionData, SingleValue}; @@ -168,25 +169,25 @@ impl Default for TypeFloat { impl FloatBuilder { #[allow(dead_code)] pub fn min(mut self, min: f64) -> Self { - self.data.min = Some(min); + self.data.min = Some(NotNan::new(min).unwrap()); self } #[allow(dead_code)] pub fn max(mut self, max: f64) -> Self { - self.data.max = Some(max); + self.data.max = Some(NotNan::new(max).unwrap()); self } #[allow(dead_code)] pub fn x_min(mut self, min: f64) -> Self { - self.data.exclusive_minimum = Some(min); + self.data.exclusive_minimum = Some(NotNan::new(min).unwrap()); self } #[allow(dead_code)] pub fn x_max(mut self, max: f64) -> Self { - self.data.exclusive_maximum = Some(max); + self.data.exclusive_maximum = Some(NotNan::new(max).unwrap()); self } } diff --git a/src/typegraph/core/src/typedef/float.rs b/src/typegraph/core/src/typedef/float.rs index 60b827c53e..680c7565d3 100644 --- a/src/typegraph/core/src/typedef/float.rs +++ b/src/typegraph/core/src/typedef/float.rs @@ -4,7 +4,6 @@ use std::hash::Hash as _; use errors::Result; -use ordered_float::OrderedFloat; use tg_schema::types::{FloatTypeData, TypeNode}; use crate::{ @@ -71,16 +70,16 @@ impl Hashable for TypeFloat { _tg: &mut TypegraphContext, ) -> Result<()> { "float".hash(hasher); - self.min.map(OrderedFloat).hash(hasher); - self.max.map(OrderedFloat).hash(hasher); - self.exclusive_minimum.map(OrderedFloat).hash(hasher); - self.exclusive_maximum.map(OrderedFloat).hash(hasher); - self.multiple_of.map(OrderedFloat).hash(hasher); + self.min.hash(hasher); + self.max.hash(hasher); + self.exclusive_minimum.hash(hasher); + self.exclusive_maximum.hash(hasher); + self.multiple_of.hash(hasher); if let Some(enumeration) = &self.enumeration { "enum".hash(hasher); for value in enumeration { - OrderedFloat(*value).hash(hasher); + (*value).hash(hasher); } } diff --git a/src/typegraph/core/src/types/sdk/core.rs b/src/typegraph/core/src/types/sdk/core.rs index ded5fbccbe..058298b150 100644 --- a/src/typegraph/core/src/types/sdk/core.rs +++ b/src/typegraph/core/src/types/sdk/core.rs @@ -1,6 +1,7 @@ // Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0. // SPDX-License-Identifier: MPL-2.0 +use ordered_float::NotNan; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -95,12 +96,12 @@ pub struct TypeInteger { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TypeFloat { - pub min: Option, - pub max: Option, - pub exclusive_minimum: Option, - pub exclusive_maximum: Option, - pub multiple_of: Option, - pub enumeration: Option>, + pub min: Option>, + pub max: Option>, + pub exclusive_minimum: Option>, + pub exclusive_maximum: Option>, + pub multiple_of: Option>, + pub enumeration: Option>>, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/src/typegraph/graph/Cargo.toml b/src/typegraph/graph/Cargo.toml index 094cf8c4a3..79f0a9d000 100644 --- a/src/typegraph/graph/Cargo.toml +++ b/src/typegraph/graph/Cargo.toml @@ -13,6 +13,7 @@ paste.workspace = true color-eyre.workspace = true tracing.workspace = true derive_more.workspace = true +ordered-float.workspace = true [dev-dependencies] insta.workspace = true diff --git a/src/typegraph/graph/src/types/float.rs b/src/typegraph/graph/src/types/float.rs index e119b66b1c..7dabc8736a 100644 --- a/src/typegraph/graph/src/types/float.rs +++ b/src/typegraph/graph/src/types/float.rs @@ -2,15 +2,16 @@ // SPDX-License-Identifier: MPL-2.0 use super::interlude::*; +use ordered_float::NotNan; #[derive(Debug)] pub struct FloatType { pub base: TypeBase, - pub minimum: Option, - pub maximum: Option, - pub exclusive_minimum: Option, - pub exclusive_maximum: Option, - pub multiple_of: Option, + pub minimum: Option>, + pub maximum: Option>, + pub exclusive_minimum: Option>, + pub exclusive_maximum: Option>, + pub multiple_of: Option>, } impl TypeNode for Arc { diff --git a/src/typegraph/optimize/Cargo.toml b/src/typegraph/optimize/Cargo.toml new file mode 100644 index 0000000000..ed35db7f4a --- /dev/null +++ b/src/typegraph/optimize/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "tg-optimize" +version.workspace = true +edition.workspace = true + +[dependencies] +color-eyre.workspace = true +serde.workspace = true +serde_json.workspace = true +tg_schema.workspace = true diff --git a/src/typegraph/optimize/src/dedup.rs b/src/typegraph/optimize/src/dedup.rs new file mode 100644 index 0000000000..f4e6de6d1d --- /dev/null +++ b/src/typegraph/optimize/src/dedup.rs @@ -0,0 +1,319 @@ +// Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0. +// SPDX-License-Identifier: MPL-2.0 + +use std::{ + collections::{BTreeMap, HashMap}, + hash::{DefaultHasher, Hash as _, Hasher as _}, + sync::Arc, +}; +use tg_schema::{ + runtimes::{KnownRuntime, TGRuntime}, + TypeNode, Typegraph, +}; + +use crate::TypeIdx; + +#[derive(Debug)] +pub struct DedupEngine { + tg: Arc, + components: HashMap>, + component_roots: Vec, + hashes: Vec>, + buckets: HashMap>, +} + +impl From for DedupEngine { + fn from(k: crate::Kosaraju) -> Self { + let mut hashes = Vec::new(); + hashes.resize(k.one.tg.types.len(), None); + let component_roots: Vec<_> = k.component_roots.iter().map(|idx| idx.unwrap()).collect(); + Self { + tg: k.one.tg.clone(), + components: k.components, + component_roots, + hashes, + buckets: HashMap::new(), + } + } +} + +impl DedupEngine { + fn register_hash(&mut self, idx: TypeIdx, hash: u64) -> u64 { + let prev = self.hashes[idx.size()].replace(hash); + assert!(prev.is_none()); + self.buckets + .entry(hash) + .and_modify(|b| b.push(idx)) + .or_insert_with(|| vec![idx]); + hash + } + + fn hash_type(&mut self, idx: TypeIdx) -> u64 { + let i = idx.size(); + if let Some(h) = self.hashes[i] { + return h; + } + + let root_idx = self.component_roots[i]; + let same_component = self.components.get(&root_idx).unwrap().len(); + if same_component > 1 { + let mut hasher = DefaultHasher::new(); + "idx".hash(&mut hasher); + idx.hash(&mut hasher); + let res = hasher.finish(); + return self.register_hash(idx, res); + } + + let tg = self.tg.clone(); + let type_node = &tg.types[idx.size()]; + + use TypeNode as N; + let mut hasher = DefaultHasher::new(); + match &type_node { + N::Boolean { .. } => { + "boolean".hash(&mut hasher); + } + N::Integer { data, base } => { + "integer".hash(&mut hasher); + data.hash(&mut hasher); + let mut enumeration = base.enumeration.clone(); + if let Some(e) = enumeration.as_mut() { + e.sort() + } + enumeration.hash(&mut hasher); + } + N::Float { data, .. } => { + "float".hash(&mut hasher); + data.hash(&mut hasher); + } + N::String { data, base } => { + "string".hash(&mut hasher); + data.hash(&mut hasher); + let mut enumeration = base.enumeration.clone(); + if let Some(e) = enumeration.as_mut() { + e.sort(); + } + enumeration.hash(&mut hasher); + } + N::File { data, .. } => { + "file".hash(&mut hasher); + let mut data = data.clone(); + if let Some(m) = data.mime_types.as_mut() { + m.sort(); + } + data.hash(&mut hasher); + } + + N::Optional { data, .. } => { + "optional".hash(&mut hasher); + data.default_value.hash(&mut hasher); + self.hash_type(data.item.into()).hash(&mut hasher); + } + + N::List { data, .. } => { + "list".hash(&mut hasher); + data.max_items.hash(&mut hasher); + data.min_items.hash(&mut hasher); + data.unique_items.hash(&mut hasher); + self.hash_type(data.items.into()).hash(&mut hasher); + } + + N::Object { data, .. } => { + "object".hash(&mut hasher); + data.id.hash(&mut hasher); + let mut required = data.required.clone(); + required.sort(); + let policies: BTreeMap<_, _> = data.policies.iter().collect(); // TODO + policies.hash(&mut hasher); + data.additional_props.hash(&mut hasher); + for (k, ty) in &data.properties { + k.hash(&mut hasher); + self.hash_type(ty.into()).hash(&mut hasher); + } + } + + N::Union { data, .. } => { + "union".hash(&mut hasher); + let mut variants: Vec<_> = data + .any_of + .iter() + .map(|ty| self.hash_type((*ty).into())) + .collect(); + variants.sort(); + variants.hash(&mut hasher); + } + + N::Either { data, .. } => { + "either".hash(&mut hasher); + let mut variants: Vec<_> = data + .one_of + .iter() + .map(|ty| self.hash_type((*ty).into())) + .collect(); + variants.sort(); + variants.hash(&mut hasher); + } + + N::Function { .. } => { + "function".hash(&mut hasher); + // TODO do we need to deduplication functions?? + idx.hash(&mut hasher); + // self.hash_type(data.input.into()).hash(&mut hasher); + // self.hash_type(data.output.into()).hash(&mut hasher); + // if let Some(pt) = data. + } + + N::Any { .. } => unreachable!(), + } + + let res = hasher.finish(); + self.register_hash(idx, res) + } + + pub fn hash_types(&mut self) { + for idx in 0..self.tg.types.len() { + let idx = TypeIdx(idx as u32); + self.hash_type(idx); + } + } + + pub fn get_converted_typegraph(&self) -> Arc { + let map = self.generate_conversion_map(); + + let types = map + .rev + .iter() + .map(|hash| { + let bucket = self.buckets.get(hash).unwrap(); + let sample_idx = bucket[0]; + // FIXME we have multiple names for the type, but only one is used + // let names: Vec<_> = bucket.iter().map(|idx| { + // let type_node = &self.tg.types[idx.size()]; + // type_node.base().title + // }).collect(); + let type_node = &self.tg.types[sample_idx.size()]; + map.convert_type(type_node) + }) + .collect(); + + let mut runtimes = self.tg.runtimes.clone(); + for rt in &mut runtimes { + if let TGRuntime::Known(KnownRuntime::Prisma(d)) = rt { + for m in &mut d.models { + map.update(&mut m.type_idx) + } + } + } + + let mut auths = self.tg.meta.auths.clone(); + for auth in &mut auths { + auth.auth_data + .entry("profiler".to_string()) + .and_modify(|v| { + let mut idx: u32 = serde_json::from_value(v.clone()).unwrap(); + map.update(&mut idx); + *v = serde_json::to_value(idx).unwrap(); + }); + } + + let mut namespaces = self.tg.meta.namespaces.clone(); + for ns in &mut namespaces { + map.update(ns); + } + + let mut meta = self.tg.meta.clone(); + meta.auths = auths; + meta.namespaces = namespaces; + + Typegraph { + types, + materializers: self.tg.materializers.clone(), + runtimes, + policies: self.tg.policies.clone(), + meta, + path: self.tg.path.clone(), + deps: self.tg.deps.clone(), + } + .into() + } + + pub fn generate_conversion_map(&self) -> ConversionMap { + let mut rev = Vec::new(); + let mut hash_to_idx = HashMap::new(); + + let direct: Vec<_> = self + .hashes + .iter() + .map(|h| { + let hash = h.unwrap(); + *hash_to_idx.entry(hash).or_insert_with(|| { + let idx = TypeIdx(rev.len() as u32); + rev.push(hash); + idx + }) + }) + .collect(); + + ConversionMap { direct, rev } + } +} + +pub struct ConversionMap { + direct: Vec, // old index -> new index + rev: Vec, // new index -> hash +} + +impl ConversionMap { + fn convert_type(&self, ty: &TypeNode) -> TypeNode { + let mut type_node = ty.clone(); + use TypeNode as N; + match &mut type_node { + N::Boolean { .. } + | N::Integer { .. } + | N::Float { .. } + | N::String { .. } + | N::File { .. } => (), + + N::Optional { data, .. } => { + self.update(&mut data.item); + } + + N::List { data, .. } => { + self.update(&mut data.items); + } + + N::Object { data, .. } => { + for prop_ty in data.properties.values_mut() { + self.update(prop_ty); + } + } + + N::Union { data, .. } => { + for ty in data.any_of.iter_mut() { + self.update(ty); + } + } + + N::Either { data, .. } => { + for ty in data.one_of.iter_mut() { + self.update(ty); + } + } + + N::Function { data, .. } => { + self.update(&mut data.input); + self.update(&mut data.output); + if let Some(pt) = data.parameter_transform.as_mut() { + self.update(&mut pt.resolver_input); + } + } + + N::Any { .. } => unreachable!(), + } + type_node + } + + fn update(&self, idx: &mut u32) { + *idx = self.direct[*idx as usize].0; + } +} diff --git a/src/typegraph/optimize/src/kosaraju.rs b/src/typegraph/optimize/src/kosaraju.rs new file mode 100644 index 0000000000..477096156a --- /dev/null +++ b/src/typegraph/optimize/src/kosaraju.rs @@ -0,0 +1,105 @@ +// Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0. +// SPDX-License-Identifier: MPL-2.0 + +use crate::{DirectedGraph as _, TypeIdx}; +use std::{collections::HashMap, rc::Rc, sync::Arc}; +use tg_schema::Typegraph; + +pub struct KosarajuOne { + pub tg: Arc, + transpose: Vec>, + list: Vec, + visited: Vec, +} + +impl KosarajuOne { + pub fn new(tg: Arc) -> Self { + let mut transpose = Vec::new(); + transpose.resize_with(tg.types.len(), Vec::new); + let mut visited = Vec::new(); + visited.resize(tg.types.len(), false); + Self { + tg, + transpose, + list: Vec::new(), + visited, + } + } + + fn run(&mut self) { + for idx in 0..self.tg.types.len() { + let idx = TypeIdx(idx as u32); + self.visit(idx); + } + } + + fn visit(&mut self, idx: TypeIdx) { + if self.is_visited(idx) { + } else { + self.set_visited(idx); + for v in self.tg.out_neighbours(&idx) { + self.visit(v); + self.register_in_neighbour(v, idx); + } + self.list.push(idx); + } + } + + fn register_in_neighbour(&mut self, idx: TypeIdx, neighbour: TypeIdx) { + self.transpose[idx.size()].push(neighbour); + } + + fn is_visited(&self, type_idx: TypeIdx) -> bool { + self.visited[type_idx.size()] + } + + fn set_visited(&mut self, type_idx: TypeIdx) { + self.visited[type_idx.size()] = true; + } +} + +pub struct Kosaraju { + pub one: Rc, + pub components: HashMap>, + pub component_roots: Vec>, +} + +impl Kosaraju { + pub fn new(tg: Arc) -> Self { + let mut one = KosarajuOne::new(tg); + one.run(); + let mut assigned = Vec::new(); + assigned.resize(one.tg.types.len(), None); + + Self { + one: one.into(), + components: HashMap::new(), + component_roots: assigned, + } + } + + pub fn run(&mut self) { + let one = self.one.clone(); + for idx in one.list.iter().rev().cloned() { + self.assign(idx, idx); + } + } + + fn assign(&mut self, vertex: TypeIdx, root: TypeIdx) { + if !self.is_assigned(vertex) { + self.component_roots[vertex.size()] = Some(root); + self.components + .entry(root) + .and_modify(|l| l.push(vertex)) + .or_insert_with(|| vec![vertex]); + let one = self.one.clone(); + for idx in &one.transpose[vertex.size()] { + self.assign(*idx, root); + } + } + } + + fn is_assigned(&self, vertex: TypeIdx) -> bool { + self.component_roots[vertex.size()].is_some() + } +} diff --git a/src/typegraph/optimize/src/lib.rs b/src/typegraph/optimize/src/lib.rs new file mode 100644 index 0000000000..d675e427e6 --- /dev/null +++ b/src/typegraph/optimize/src/lib.rs @@ -0,0 +1,86 @@ +// Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0. +// SPDX-License-Identifier: MPL-2.0 + +mod dedup; +mod kosaraju; + +use std::{collections::BTreeMap, sync::Arc}; + +use kosaraju::Kosaraju; +use tg_schema::{TypeNode, Typegraph}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct TypeIdx(u32); + +impl From for TypeIdx { + fn from(value: u32) -> Self { + Self(value) + } +} +impl From<&u32> for TypeIdx { + fn from(value: &u32) -> Self { + Self(*value) + } +} + +impl TypeIdx { + pub fn size(&self) -> usize { + self.0 as usize + } +} + +pub fn optimize(tg: Arc) -> Arc { + let mut k = Kosaraju::new(tg); + k.run(); + + let mut sizes = BTreeMap::new(); + for c in &k.components { + sizes.entry(c.1.len()).and_modify(|l| *l += 1).or_insert(1); + } + + let mut dedup = crate::dedup::DedupEngine::from(k); + dedup.hash_types(); + dedup.get_converted_typegraph() +} + +trait DirectedGraph { + type VertexRef; + fn out_neighbours(&self, v: &Self::VertexRef) -> Vec; +} + +impl DirectedGraph for Typegraph { + type VertexRef = TypeIdx; + + fn out_neighbours(&self, v: &TypeIdx) -> Vec { + let type_node = &self.types[v.size()]; + + use TypeNode as N; + match type_node { + N::Boolean { .. } + | N::Integer { .. } + | N::Float { .. } + | N::String { .. } + | N::File { .. } => vec![], + + N::Optional { data, .. } => vec![data.item.into()], + + N::List { data, .. } => vec![data.items.into()], + + N::Object { data, .. } => data.properties.values().map(|v| v.into()).collect(), + + N::Union { data, .. } => data.any_of.iter().map(|v| v.into()).collect(), + + N::Either { data, .. } => data.one_of.iter().map(|v| v.into()).collect(), + + N::Function { data, .. } => { + let mut res = vec![data.input.into(), data.output.into()]; + if let Some(pt) = &data.parameter_transform { + res.push(pt.resolver_input.into()); + } + res + } + + N::Any { .. } => unreachable!(), + } + } +} diff --git a/src/typegraph/optimize/src/main.rs b/src/typegraph/optimize/src/main.rs new file mode 100644 index 0000000000..3e6476ce00 --- /dev/null +++ b/src/typegraph/optimize/src/main.rs @@ -0,0 +1,16 @@ +// Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0. +// SPDX-License-Identifier: MPL-2.0 + +use std::sync::Arc; + +use tg_schema::Typegraph; + +fn main() -> color_eyre::eyre::Result<()> { + let mut buffer = String::new(); + std::io::stdin().read_line(&mut buffer)?; + let tg: Typegraph = serde_json::from_str(&buffer)?; + let opt_tg = tg_optimize::optimize(Arc::new(tg)); + println!("{}", serde_json::to_string(opt_tg.as_ref())?); + + Ok(()) +} diff --git a/src/typegraph/schema/Cargo.toml b/src/typegraph/schema/Cargo.toml index 7ad1b411d5..fe32a4530b 100644 --- a/src/typegraph/schema/Cargo.toml +++ b/src/typegraph/schema/Cargo.toml @@ -4,22 +4,9 @@ version.workspace = true edition.workspace = true [dependencies] -# patterns anyhow.workspace = true -# itertools.workspace = true -# indoc.workspace = true -# thiserror.workspace = true - - -# encoding -# base64.workspace = true -# flate2.workspace = true -# tar.workspace = true - serde.workspace = true serde_json = { workspace = true, features = ["preserve_order"] } serde_with.workspace = true - - -# ds indexmap.workspace = true +ordered-float.workspace = true diff --git a/src/typegraph/schema/src/lib.rs b/src/typegraph/schema/src/lib.rs index 266bfae9d5..9f25739c14 100644 --- a/src/typegraph/schema/src/lib.rs +++ b/src/typegraph/schema/src/lib.rs @@ -132,7 +132,7 @@ pub struct Policy { } #[skip_serializing_none] -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Deserialize, Clone, Debug, Hash)] pub struct PolicyIndicesByEffect { pub read: Option, pub create: Option, @@ -141,7 +141,7 @@ pub struct PolicyIndicesByEffect { } #[skip_serializing_none] -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Deserialize, Clone, Debug, Hash)] #[serde(untagged)] pub enum PolicyIndices { Policy(u32), diff --git a/src/typegraph/schema/src/types.rs b/src/typegraph/schema/src/types.rs index 8338ebbed1..209efebd18 100644 --- a/src/typegraph/schema/src/types.rs +++ b/src/typegraph/schema/src/types.rs @@ -5,6 +5,7 @@ use std::collections::BTreeMap; use anyhow::Result; use indexmap::IndexMap; +use ordered_float::NotNan; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; use std::hash::Hash; @@ -78,18 +79,18 @@ pub struct OptionalTypeData { } #[skip_serializing_none] -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Deserialize, Clone, Debug, Hash)] #[serde(rename_all = "camelCase")] pub struct FloatTypeData { - pub minimum: Option, - pub maximum: Option, - pub exclusive_minimum: Option, - pub exclusive_maximum: Option, - pub multiple_of: Option, + pub minimum: Option>, + pub maximum: Option>, + pub exclusive_minimum: Option>, + pub exclusive_maximum: Option>, + pub multiple_of: Option>, } #[skip_serializing_none] -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Deserialize, Clone, Debug, Hash)] #[serde(rename_all = "camelCase")] pub struct IntegerTypeData { // we use i32 as GraphQL spec only support 32-bit integers (Int) @@ -100,7 +101,7 @@ pub struct IntegerTypeData { pub multiple_of: Option, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash)] #[serde(rename_all = "kebab-case")] pub enum StringFormat { Uuid, @@ -132,7 +133,7 @@ impl core::fmt::Display for StringFormat { } #[skip_serializing_none] -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Deserialize, Clone, Debug, Hash)] #[serde(rename_all = "camelCase")] pub struct StringTypeData { pub min_length: Option, @@ -142,7 +143,7 @@ pub struct StringTypeData { } #[skip_serializing_none] -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Deserialize, Clone, Debug, Hash)] #[serde(rename_all = "camelCase")] pub struct FileTypeData { pub min_size: Option, diff --git a/src/typegraph/schema/src/validator/types.rs b/src/typegraph/schema/src/validator/types.rs index ac631f2eed..1a57378e29 100644 --- a/src/typegraph/schema/src/validator/types.rs +++ b/src/typegraph/schema/src/validator/types.rs @@ -174,31 +174,31 @@ impl EnsureSubtypeOf for IntegerTypeData { ) { ensure_subtype_of_for_min( self.minimum.map(|m| m as f64), - other.minimum, + other.minimum.map(|m| m.into_inner()), "minimum", errors, ); ensure_subtype_of_for_max( self.maximum.map(|m| m as f64), - other.maximum, + other.maximum.map(|n| n.into_inner()), "maximum", errors, ); ensure_subtype_of_for_min( self.exclusive_minimum.map(|m| m as f64), - other.exclusive_minimum, + other.exclusive_minimum.map(|n| n.into_inner()), "exclusive_minimum", errors, ); ensure_subtype_of_for_max( self.exclusive_maximum.map(|m| m as f64), - other.exclusive_maximum, + other.exclusive_maximum.map(|n| n.into_inner()), "exclusive_maximum", errors, ); ensure_subtype_of_for_multiple_of( self.multiple_of.map(|m| m as f64), - other.multiple_of, + other.multiple_of.map(|n| n.into_inner()), "multiple_of", errors, ); diff --git a/src/typegraph/schema/src/validator/value.rs b/src/typegraph/schema/src/validator/value.rs index 58d5a57fe4..7c7ea4c4d7 100644 --- a/src/typegraph/schema/src/validator/value.rs +++ b/src/typegraph/schema/src/validator/value.rs @@ -79,19 +79,19 @@ impl Typegraph { bail!("Float value {value:?} cannot be stored in f64"); }; if let Some(min) = data.minimum { - number_validator::expect_min(min, value)?; + number_validator::expect_min(min.into_inner(), value)?; } if let Some(max) = data.maximum { - number_validator::expect_max(max, value)?; + number_validator::expect_max(max.into_inner(), value)?; } if let Some(xmin) = data.exclusive_minimum { - number_validator::expect_xmin(xmin, value)?; + number_validator::expect_xmin(xmin.into_inner(), value)?; } if let Some(xmax) = data.exclusive_maximum { - number_validator::expect_xmax(xmax, value)?; + number_validator::expect_xmax(xmax.into_inner(), value)?; } if let Some(divisor) = data.multiple_of.as_ref() { - let quot = value / divisor; + let quot = value / divisor.into_inner(); if quot.round() != quot { bail!("Expected a multiple of {divisor}, got {value}"); } diff --git a/tools/tree-view-web.ts b/tools/tree-view-web.ts index 42db0fd892..0ba8c585b7 100755 --- a/tools/tree-view-web.ts +++ b/tools/tree-view-web.ts @@ -8,15 +8,14 @@ * deno run -A tools/tree-view-web.ts [] */ +import { Application, Router, Status } from "jsr:@oak/oak"; import { TypeGraphDS } from "../src/typegate/src/typegraph/mod.ts"; import { projectDir } from "./utils.ts"; -import { join, parseArgs } from "./deps.ts"; - -const dirname = import.meta.dirname ?? new URL(".", import.meta.url).pathname; -const indexHtml = join(dirname, "tree-view/index.html"); +import { parseArgs } from "./deps.ts"; const args = parseArgs(Deno.args, { string: ["port"], + boolean: ["json"], }); const argsPort = parseInt(args.port ?? ""); @@ -27,35 +26,51 @@ const files = args._ as string[]; if (files.length === 0) { throw new Error("Path to typegraph definition module is required."); } -const cmdBase = [ - "cargo", - "run", - "--manifest-path", - `${projectDir}/Cargo.toml`, - "-p", - "meta-cli", - "--", - "serialize", - "-vvv", - "-f", -]; + const tgs: TypeGraphDS[] = []; -for (const file of files) { - const cmd = [...cmdBase, file]; - const { stdout, code } = await new Deno.Command(cmd[0], { - args: cmd.slice(1), - stdout: "piped", - stderr: "inherit", - }).output(); - if (code !== 0) { - console.log( - `[error] command ${ - cmd.map((c) => JSON.stringify(c)).join(" ") - } failed with code ${code}`, - ); - continue; + +if (args.json) { + for (const file of files) { + const raw = await Deno.readFile(file); + const str = new TextDecoder().decode(raw); + const parsed = JSON.parse(str); + if (Array.isArray(parsed)) { + tgs.push(...parsed); + } else { + tgs.push(parsed); + } + } +} else { + const cmdBase = [ + "cargo", + "run", + "--manifest-path", + `${projectDir}/Cargo.toml`, + "-p", + "meta-cli", + "--", + "serialize", + "-vvv", + "-f", + ]; + + for (const file of files) { + const cmd = [...cmdBase, file]; + const { stdout, code } = await new Deno.Command(cmd[0], { + args: cmd.slice(1), + stdout: "piped", + stderr: "inherit", + }).output(); + if (code !== 0) { + console.log( + `[error] command ${ + cmd.map((c) => JSON.stringify(c)).join(" ") + } failed with code ${code}`, + ); + continue; + } + tgs.push(...JSON.parse(new TextDecoder().decode(stdout))); } - tgs.push(...JSON.parse(new TextDecoder().decode(stdout))); } if (tgs.length === 0) { @@ -63,33 +78,100 @@ if (tgs.length === 0) { Deno.exit(1); } -Deno.serve({ - port, - onListen({ port, hostname }) { - console.log( - `server running at http://${hostname ?? "localhost"}:${port}`, - ); - }, -}, async (req) => { - const url = new URL(req.url); - const pathname = url.pathname; - console.log(`[info] method=${req.method} url=${req.url}`); - - if (req.method !== "GET") { - console.log(`[error] method '${req.method}' not allowed`); - return new Response("Method not allowed", { status: 405 }); +const byName: Map = new Map(); + +for (const tg of tgs) { + byName.set(tg.types[0].title, tg); +} + +const router = new Router(); + +const fsCache: Map = new Map(); + +async function getDistFile(path: string) { + const cached = fsCache.get(path); + if (cached != null) { + return cached; + } + const value = await Deno.readTextFile( + `${projectDir}/tools/tree/dist/${path}`, + ); + fsCache.set(path, value); + return value; +} + +router.get("/logo.svg", async (ctx) => { + ctx.response.body = await getDistFile("logo.svg"); + ctx.response.type = "svg"; +}); + +router.get("/assets/:asset", async (ctx) => { + ctx.response.body = await getDistFile(`assets/${ctx.params.asset}`); + ctx.response.type = ctx.params.asset.split(".").slice(-1)[0]; +}); + +router.get("/api/typegraphs", (ctx) => { + ctx.response.body = [...byName.keys()]; + ctx.response.type = "json"; +}); + +router.get("/api/typegraphs/:tgName", (ctx) => { + const tg = byName.get(ctx.params.tgName); + if (tg == null) { + ctx.response.body = `typegraph "${ctx.params.tgName}" not found`; + ctx.response.status = Status.NotFound; + } else { + ctx.response.body = { + stats: { + types: tg.types.length, + runtimes: tg.runtimes.length, + materializers: tg.materializers.length, + policies: tg.policies.length, + }, + }; + ctx.response.type = "json"; } - if (pathname === "/") { - return new Response(await Deno.readTextFile(indexHtml), { - headers: { "content-type": "text/html" }, - }); +}); + +router.get("/api/typegraphs/:tgName/types/:typeIdx", (ctx) => { + const tg = byName.get(ctx.params.tgName); + if (tg == null) { + ctx.response.body = `typegraph "${ctx.params.tgName}" not found`; + ctx.response.status = Status.NotFound; + } else { + ctx.response.body = tg.types[+ctx.params.typeIdx]; + ctx.response.type = "json"; } - // TODO typegraph list and typegraph by name - if (pathname === "/tg.json") { - return new Response(JSON.stringify(tgs), { - headers: { "content-type": "application/json" }, - }); +}); + +const app = new Application(); + +app.use(async (ctx, next) => { + await next(); + console.log( + `- ${ctx.request.method} ${ctx.response.status} - ${ctx.request.url.pathname}${ctx.request.url.search}`, + ); +}); + +app.use(async (ctx, next) => { + const pathname = ctx.request.url.pathname; + if ( + pathname.startsWith("/api") || + pathname == "/logo.svg" || + pathname.startsWith("/assets") + ) { + await next(); + } else { + ctx.response.body = await getDistFile("index.html"); + ctx.response.type = "html"; } - console.log(`[error] path '${pathname}' not found`); - return new Response("Not found", { status: 404 }); }); + +app.use(router.routes()); +app.use(router.allowedMethods()); + +app.addEventListener("listen", (evt) => { + console.log(`[info] server running at http://${evt.hostname}:${evt.port}`); +}); + +app.listen({ port }); diff --git a/tools/tree/.gitignore b/tools/tree/.gitignore new file mode 100644 index 0000000000..cf7ff2f72e --- /dev/null +++ b/tools/tree/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +# dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/tools/tree/.vite/deps/_metadata.json b/tools/tree/.vite/deps/_metadata.json new file mode 100644 index 0000000000..d751e9689f --- /dev/null +++ b/tools/tree/.vite/deps/_metadata.json @@ -0,0 +1,8 @@ +{ + "hash": "f0e17266", + "configHash": "363b4baa", + "lockfileHash": "e5b2b695", + "browserHash": "8900fa32", + "optimized": {}, + "chunks": {} +} diff --git a/tools/tree/.vite/deps/package.json b/tools/tree/.vite/deps/package.json new file mode 100644 index 0000000000..3dbc1ca591 --- /dev/null +++ b/tools/tree/.vite/deps/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/tools/tree/README.md b/tools/tree/README.md new file mode 100644 index 0000000000..da9844432b --- /dev/null +++ b/tools/tree/README.md @@ -0,0 +1,54 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: + +```js +export default tseslint.config({ + extends: [ + // Remove ...tseslint.configs.recommended and replace with this + ...tseslint.configs.recommendedTypeChecked, + // Alternatively, use this for stricter rules + ...tseslint.configs.strictTypeChecked, + // Optionally, add this for stylistic rules + ...tseslint.configs.stylisticTypeChecked, + ], + languageOptions: { + // other options... + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + }, +}) +``` + +You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: + +```js +// eslint.config.js +import reactX from 'eslint-plugin-react-x' +import reactDom from 'eslint-plugin-react-dom' + +export default tseslint.config({ + plugins: { + // Add the react-x and react-dom plugins + 'react-x': reactX, + 'react-dom': reactDom, + }, + rules: { + // other rules... + // Enable its recommended typescript rules + ...reactX.configs['recommended-typescript'].rules, + ...reactDom.configs.recommended.rules, + }, +}) +``` diff --git a/tools/tree/dist/assets/index-B7TWQuis.css b/tools/tree/dist/assets/index-B7TWQuis.css new file mode 100644 index 0000000000..508fa6e1e7 --- /dev/null +++ b/tools/tree/dist/assets/index-B7TWQuis.css @@ -0,0 +1 @@ +/*! tailwindcss v4.1.6 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-outline-style:solid}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-orange-500:oklch(70.5% .213 47.604);--color-cyan-500:oklch(71.5% .143 215.221);--color-blue-400:oklch(70.7% .165 254.624);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-white:#fff;--spacing:.25rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-bold:700;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.flex{display:flex}.h-4{height:calc(var(--spacing)*4)}.w-4{width:calc(var(--spacing)*4)}.min-w-0{min-width:calc(var(--spacing)*0)}.flex-shrink-0{flex-shrink:0}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.flex-row{flex-direction:row}.items-center{align-items:center}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.border,.border-1{border-style:var(--tw-border-style);border-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l-6{border-left-style:var(--tw-border-style);border-left-width:6px}.border-gray-400{border-color:var(--color-gray-400)}.border-gray-600{border-color:var(--color-gray-600)}.border-white\/5{border-color:#ffffff0d}@supports (color:color-mix(in lab,red,red)){.border-white\/5{border-color:color-mix(in oklab,var(--color-white)5%,transparent)}}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.border-white\/10{border-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.bg-blue-400\/10{background-color:#54a2ff1a}@supports (color:color-mix(in lab,red,red)){.bg-blue-400\/10{background-color:color-mix(in oklab,var(--color-blue-400)10%,transparent)}}.bg-blue-400\/20{background-color:#54a2ff33}@supports (color:color-mix(in lab,red,red)){.bg-blue-400\/20{background-color:color-mix(in oklab,var(--color-blue-400)20%,transparent)}}.bg-gray-800{background-color:var(--color-gray-800)}.bg-gray-900{background-color:var(--color-gray-900)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-4{padding-inline:calc(var(--spacing)*4)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.pl-2{padding-left:calc(var(--spacing)*2)}.pl-3{padding-left:calc(var(--spacing)*3)}.font-mono{font-family:var(--font-mono)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.text-blue-400{color:var(--color-blue-400)}.text-cyan-500{color:var(--color-cyan-500)}.text-gray-300{color:var(--color-gray-300)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-orange-500{color:var(--color-orange-500)}.text-red-400{color:var(--color-red-400)}.text-red-500{color:var(--color-red-500)}.text-white{color:var(--color-white)}.outline-0{outline-style:var(--tw-outline-style);outline-width:0}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}@media (hover:hover){.hover\:text-white:hover{color:var(--color-white)}}.focus\:border-white\/20:focus{border-color:#fff3}@supports (color:color-mix(in lab,red,red)){.focus\:border-white\/20:focus{border-color:color-mix(in oklab,var(--color-white)20%,transparent)}}}:root{color-scheme:light dark;color:#ffffffde;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-color:#242424;font-family:system-ui,Avenir,Helvetica,Arial,sans-serif;font-weight:400;line-height:1.5}a{color:#646cff;-webkit-text-decoration:inherit;text-decoration:inherit;font-weight:500}a:hover{color:#535bf2}body{min-width:320px;min-height:100vh;margin:0}#root{flex-direction:column;min-height:100vh;display:flex}@media (prefers-color-scheme:light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}main{flex:1;max-width:1280px;display:flex;flex-direction:column;align-items:stretch}h1{font-size:3.2em;line-height:1.1}.logo{height:6em;padding:1.5em;will-change:filter;transition:filter .3s}.logo:hover{filter:drop-shadow(0 0 2em #646cffaa)}.logo.react:hover{filter:drop-shadow(0 0 2em #61dafbaa)}@keyframes logo-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media (prefers-reduced-motion: no-preference){a:nth-of-type(2) .logo{animation:logo-spin infinite 20s linear}}.card{padding:2em}.read-the-docs{color:#888} diff --git a/tools/tree/dist/assets/index-en07UP6E.js b/tools/tree/dist/assets/index-en07UP6E.js new file mode 100644 index 0000000000..836e235cc5 --- /dev/null +++ b/tools/tree/dist/assets/index-en07UP6E.js @@ -0,0 +1,59 @@ +(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const d of document.querySelectorAll('link[rel="modulepreload"]'))f(d);new MutationObserver(d=>{for(const h of d)if(h.type==="childList")for(const b of h.addedNodes)b.tagName==="LINK"&&b.rel==="modulepreload"&&f(b)}).observe(document,{childList:!0,subtree:!0});function o(d){const h={};return d.integrity&&(h.integrity=d.integrity),d.referrerPolicy&&(h.referrerPolicy=d.referrerPolicy),d.crossOrigin==="use-credentials"?h.credentials="include":d.crossOrigin==="anonymous"?h.credentials="omit":h.credentials="same-origin",h}function f(d){if(d.ep)return;d.ep=!0;const h=o(d);fetch(d.href,h)}})();function zy(i){return i&&i.__esModule&&Object.prototype.hasOwnProperty.call(i,"default")?i.default:i}var Yf={exports:{}},Qu={};/** + * @license React + * react-jsx-runtime.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var hh;function My(){if(hh)return Qu;hh=1;var i=Symbol.for("react.transitional.element"),r=Symbol.for("react.fragment");function o(f,d,h){var b=null;if(h!==void 0&&(b=""+h),d.key!==void 0&&(b=""+d.key),"key"in d){h={};for(var A in d)A!=="key"&&(h[A]=d[A])}else h=d;return d=h.ref,{$$typeof:i,type:f,key:b,ref:d!==void 0?d:null,props:h}}return Qu.Fragment=r,Qu.jsx=o,Qu.jsxs=o,Qu}var mh;function Uy(){return mh||(mh=1,Yf.exports=My()),Yf.exports}var V=Uy(),wf={exports:{}},at={};/** + * @license React + * react.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var yh;function Ny(){if(yh)return at;yh=1;var i=Symbol.for("react.transitional.element"),r=Symbol.for("react.portal"),o=Symbol.for("react.fragment"),f=Symbol.for("react.strict_mode"),d=Symbol.for("react.profiler"),h=Symbol.for("react.consumer"),b=Symbol.for("react.context"),A=Symbol.for("react.forward_ref"),g=Symbol.for("react.suspense"),y=Symbol.for("react.memo"),O=Symbol.for("react.lazy"),N=Symbol.iterator;function D(v){return v===null||typeof v!="object"?null:(v=N&&v[N]||v["@@iterator"],typeof v=="function"?v:null)}var j={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},H=Object.assign,L={};function w(v,B,G){this.props=v,this.context=B,this.refs=L,this.updater=G||j}w.prototype.isReactComponent={},w.prototype.setState=function(v,B){if(typeof v!="object"&&typeof v!="function"&&v!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,v,B,"setState")},w.prototype.forceUpdate=function(v){this.updater.enqueueForceUpdate(this,v,"forceUpdate")};function U(){}U.prototype=w.prototype;function P(v,B,G){this.props=v,this.context=B,this.refs=L,this.updater=G||j}var Q=P.prototype=new U;Q.constructor=P,H(Q,w.prototype),Q.isPureReactComponent=!0;var lt=Array.isArray,Z={H:null,A:null,T:null,S:null,V:null},rt=Object.prototype.hasOwnProperty;function gt(v,B,G,Y,k,it){return G=it.ref,{$$typeof:i,type:v,key:B,ref:G!==void 0?G:null,props:it}}function et(v,B){return gt(v.type,B,void 0,void 0,void 0,v.props)}function ht(v){return typeof v=="object"&&v!==null&&v.$$typeof===i}function Ot(v){var B={"=":"=0",":":"=2"};return"$"+v.replace(/[=:]/g,function(G){return B[G]})}var Xt=/\/+/g;function Dt(v,B){return typeof v=="object"&&v!==null&&v.key!=null?Ot(""+v.key):B.toString(36)}function Qt(){}function se(v){switch(v.status){case"fulfilled":return v.value;case"rejected":throw v.reason;default:switch(typeof v.status=="string"?v.then(Qt,Qt):(v.status="pending",v.then(function(B){v.status==="pending"&&(v.status="fulfilled",v.value=B)},function(B){v.status==="pending"&&(v.status="rejected",v.reason=B)})),v.status){case"fulfilled":return v.value;case"rejected":throw v.reason}}throw v}function Bt(v,B,G,Y,k){var it=typeof v;(it==="undefined"||it==="boolean")&&(v=null);var tt=!1;if(v===null)tt=!0;else switch(it){case"bigint":case"string":case"number":tt=!0;break;case"object":switch(v.$$typeof){case i:case r:tt=!0;break;case O:return tt=v._init,Bt(tt(v._payload),B,G,Y,k)}}if(tt)return k=k(v),tt=Y===""?"."+Dt(v,0):Y,lt(k)?(G="",tt!=null&&(G=tt.replace(Xt,"$&/")+"/"),Bt(k,B,G,"",function(Le){return Le})):k!=null&&(ht(k)&&(k=et(k,G+(k.key==null||v&&v.key===k.key?"":(""+k.key).replace(Xt,"$&/")+"/")+tt)),B.push(k)),1;tt=0;var ae=Y===""?".":Y+":";if(lt(v))for(var xt=0;xt>>1,v=z[yt];if(0>>1;ytd(Y,$))kd(it,Y)?(z[yt]=it,z[k]=$,yt=k):(z[yt]=Y,z[G]=$,yt=G);else if(kd(it,$))z[yt]=it,z[k]=$,yt=k;else break t}}return X}function d(z,X){var $=z.sortIndex-X.sortIndex;return $!==0?$:z.id-X.id}if(i.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var h=performance;i.unstable_now=function(){return h.now()}}else{var b=Date,A=b.now();i.unstable_now=function(){return b.now()-A}}var g=[],y=[],O=1,N=null,D=3,j=!1,H=!1,L=!1,w=!1,U=typeof setTimeout=="function"?setTimeout:null,P=typeof clearTimeout=="function"?clearTimeout:null,Q=typeof setImmediate<"u"?setImmediate:null;function lt(z){for(var X=o(y);X!==null;){if(X.callback===null)f(y);else if(X.startTime<=z)f(y),X.sortIndex=X.expirationTime,r(g,X);else break;X=o(y)}}function Z(z){if(L=!1,lt(z),!H)if(o(g)!==null)H=!0,rt||(rt=!0,Dt());else{var X=o(y);X!==null&&Bt(Z,X.startTime-z)}}var rt=!1,gt=-1,et=5,ht=-1;function Ot(){return w?!0:!(i.unstable_now()-htz&&Ot());){var yt=N.callback;if(typeof yt=="function"){N.callback=null,D=N.priorityLevel;var v=yt(N.expirationTime<=z);if(z=i.unstable_now(),typeof v=="function"){N.callback=v,lt(z),X=!0;break e}N===o(g)&&f(g),lt(z)}else f(g);N=o(g)}if(N!==null)X=!0;else{var B=o(y);B!==null&&Bt(Z,B.startTime-z),X=!1}}break t}finally{N=null,D=$,j=!1}X=void 0}}finally{X?Dt():rt=!1}}}var Dt;if(typeof Q=="function")Dt=function(){Q(Xt)};else if(typeof MessageChannel<"u"){var Qt=new MessageChannel,se=Qt.port2;Qt.port1.onmessage=Xt,Dt=function(){se.postMessage(null)}}else Dt=function(){U(Xt,0)};function Bt(z,X){gt=U(function(){z(i.unstable_now())},X)}i.unstable_IdlePriority=5,i.unstable_ImmediatePriority=1,i.unstable_LowPriority=4,i.unstable_NormalPriority=3,i.unstable_Profiling=null,i.unstable_UserBlockingPriority=2,i.unstable_cancelCallback=function(z){z.callback=null},i.unstable_forceFrameRate=function(z){0>z||125yt?(z.sortIndex=$,r(y,z),o(g)===null&&z===o(y)&&(L?(P(gt),gt=-1):L=!0,Bt(Z,$-yt))):(z.sortIndex=v,r(g,z),H||j||(H=!0,rt||(rt=!0,Dt()))),z},i.unstable_shouldYield=Ot,i.unstable_wrapCallback=function(z){var X=D;return function(){var $=D;D=X;try{return z.apply(this,arguments)}finally{D=$}}}}(Qf)),Qf}var ph;function Hy(){return ph||(ph=1,Xf.exports=Cy()),Xf.exports}var Vf={exports:{}},ie={};/** + * @license React + * react-dom.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Sh;function qy(){if(Sh)return ie;Sh=1;var i=Ai();function r(g){var y="https://react.dev/errors/"+g;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(i)}catch(r){console.error(r)}}return i(),Vf.exports=qy(),Vf.exports}/** + * @license React + * react-dom-client.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Eh;function jy(){if(Eh)return Vu;Eh=1;var i=Hy(),r=Ai(),o=By();function f(t){var e="https://react.dev/errors/"+t;if(1v||(t.current=yt[v],yt[v]=null,v--)}function Y(t,e){v++,yt[v]=t.current,t.current=e}var k=B(null),it=B(null),tt=B(null),ae=B(null);function xt(t,e){switch(Y(tt,e),Y(it,t),Y(k,null),e.nodeType){case 9:case 11:t=(t=e.documentElement)&&(t=t.namespaceURI)?Gd(t):0;break;default:if(t=e.tagName,e=e.namespaceURI)e=Gd(e),t=Xd(e,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}G(k),Y(k,t)}function Le(){G(k),G(it),G(tt)}function $e(t){t.memoizedState!==null&&Y(ae,t);var e=k.current,l=Xd(e,t.type);e!==l&&(Y(it,t),Y(k,l))}function Yl(t){it.current===t&&(G(k),G(it)),ae.current===t&&(G(ae),Lu._currentValue=$)}var Iu=Object.prototype.hasOwnProperty,pt=i.unstable_scheduleCallback,vt=i.unstable_cancelCallback,Kt=i.unstable_shouldYield,Mt=i.unstable_requestPaint,Ct=i.unstable_now,ml=i.unstable_getCurrentPriorityLevel,Yt=i.unstable_ImmediatePriority,Jt=i.unstable_UserBlockingPriority,oe=i.unstable_NormalPriority,tn=i.unstable_LowPriority,Ka=i.unstable_IdlePriority,en=i.log,de=i.unstable_setDisableYieldValue,fe=null,Pt=null;function Ye(t){if(typeof en=="function"&&de(t),Pt&&typeof Pt.setStrictMode=="function")try{Pt.setStrictMode(fe,t)}catch{}}var It=Math.clz32?Math.clz32:ym,hm=Math.log,mm=Math.LN2;function ym(t){return t>>>=0,t===0?32:31-(hm(t)/mm|0)|0}var ln=256,an=4194304;function wl(t){var e=t&42;if(e!==0)return e;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t&4194048;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function un(t,e,l){var a=t.pendingLanes;if(a===0)return 0;var u=0,n=t.suspendedLanes,c=t.pingedLanes;t=t.warmLanes;var s=a&134217727;return s!==0?(a=s&~n,a!==0?u=wl(a):(c&=s,c!==0?u=wl(c):l||(l=s&~t,l!==0&&(u=wl(l))))):(s=a&~n,s!==0?u=wl(s):c!==0?u=wl(c):l||(l=a&~t,l!==0&&(u=wl(l)))),u===0?0:e!==0&&e!==u&&(e&n)===0&&(n=u&-u,l=e&-e,n>=l||n===32&&(l&4194048)!==0)?e:u}function Ja(t,e){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&e)===0}function vm(t,e){switch(t){case 1:case 2:case 4:case 8:case 64:return e+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Rr(){var t=ln;return ln<<=1,(ln&4194048)===0&&(ln=256),t}function Ar(){var t=an;return an<<=1,(an&62914560)===0&&(an=4194304),t}function _i(t){for(var e=[],l=0;31>l;l++)e.push(t);return e}function $a(t,e){t.pendingLanes|=e,e!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function gm(t,e,l,a,u,n){var c=t.pendingLanes;t.pendingLanes=l,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=l,t.entangledLanes&=l,t.errorRecoveryDisabledLanes&=l,t.shellSuspendCounter=0;var s=t.entanglements,m=t.expirationTimes,T=t.hiddenUpdates;for(l=c&~l;0)":-1u||m[a]!==T[u]){var M=` +`+m[a].replace(" at new "," at ");return t.displayName&&M.includes("")&&(M=M.replace("",t.displayName)),M}while(1<=a&&0<=u);break}}}finally{Ci=!1,Error.prepareStackTrace=l}return(l=t?t.displayName||t.name:"")?sa(l):""}function Rm(t){switch(t.tag){case 26:case 27:case 5:return sa(t.type);case 16:return sa("Lazy");case 13:return sa("Suspense");case 19:return sa("SuspenseList");case 0:case 15:return Hi(t.type,!1);case 11:return Hi(t.type.render,!1);case 1:return Hi(t.type,!0);case 31:return sa("Activity");default:return""}}function Hr(t){try{var e="";do e+=Rm(t),t=t.return;while(t);return e}catch(l){return` +Error generating stack: `+l.message+` +`+l.stack}}function Oe(t){switch(typeof t){case"bigint":case"boolean":case"number":case"string":case"undefined":return t;case"object":return t;default:return""}}function qr(t){var e=t.type;return(t=t.nodeName)&&t.toLowerCase()==="input"&&(e==="checkbox"||e==="radio")}function Am(t){var e=qr(t)?"checked":"value",l=Object.getOwnPropertyDescriptor(t.constructor.prototype,e),a=""+t[e];if(!t.hasOwnProperty(e)&&typeof l<"u"&&typeof l.get=="function"&&typeof l.set=="function"){var u=l.get,n=l.set;return Object.defineProperty(t,e,{configurable:!0,get:function(){return u.call(this)},set:function(c){a=""+c,n.call(this,c)}}),Object.defineProperty(t,e,{enumerable:l.enumerable}),{getValue:function(){return a},setValue:function(c){a=""+c},stopTracking:function(){t._valueTracker=null,delete t[e]}}}}function fn(t){t._valueTracker||(t._valueTracker=Am(t))}function Br(t){if(!t)return!1;var e=t._valueTracker;if(!e)return!0;var l=e.getValue(),a="";return t&&(a=qr(t)?t.checked?"true":"false":t.value),t=a,t!==l?(e.setValue(t),!0):!1}function rn(t){if(t=t||(typeof document<"u"?document:void 0),typeof t>"u")return null;try{return t.activeElement||t.body}catch{return t.body}}var Om=/[\n"\\]/g;function xe(t){return t.replace(Om,function(e){return"\\"+e.charCodeAt(0).toString(16)+" "})}function qi(t,e,l,a,u,n,c,s){t.name="",c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"?t.type=c:t.removeAttribute("type"),e!=null?c==="number"?(e===0&&t.value===""||t.value!=e)&&(t.value=""+Oe(e)):t.value!==""+Oe(e)&&(t.value=""+Oe(e)):c!=="submit"&&c!=="reset"||t.removeAttribute("value"),e!=null?Bi(t,c,Oe(e)):l!=null?Bi(t,c,Oe(l)):a!=null&&t.removeAttribute("value"),u==null&&n!=null&&(t.defaultChecked=!!n),u!=null&&(t.checked=u&&typeof u!="function"&&typeof u!="symbol"),s!=null&&typeof s!="function"&&typeof s!="symbol"&&typeof s!="boolean"?t.name=""+Oe(s):t.removeAttribute("name")}function jr(t,e,l,a,u,n,c,s){if(n!=null&&typeof n!="function"&&typeof n!="symbol"&&typeof n!="boolean"&&(t.type=n),e!=null||l!=null){if(!(n!=="submit"&&n!=="reset"||e!=null))return;l=l!=null?""+Oe(l):"",e=e!=null?""+Oe(e):l,s||e===t.value||(t.value=e),t.defaultValue=e}a=a??u,a=typeof a!="function"&&typeof a!="symbol"&&!!a,t.checked=s?t.checked:!!a,t.defaultChecked=!!a,c!=null&&typeof c!="function"&&typeof c!="symbol"&&typeof c!="boolean"&&(t.name=c)}function Bi(t,e,l){e==="number"&&rn(t.ownerDocument)===t||t.defaultValue===""+l||(t.defaultValue=""+l)}function oa(t,e,l,a){if(t=t.options,e){e={};for(var u=0;u"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Gi=!1;if(We)try{var Pa={};Object.defineProperty(Pa,"passive",{get:function(){Gi=!0}}),window.addEventListener("test",Pa,Pa),window.removeEventListener("test",Pa,Pa)}catch{Gi=!1}var vl=null,Xi=null,on=null;function Vr(){if(on)return on;var t,e=Xi,l=e.length,a,u="value"in vl?vl.value:vl.textContent,n=u.length;for(t=0;t=eu),Wr=" ",Fr=!1;function Pr(t,e){switch(t){case"keyup":return Im.indexOf(e.keyCode)!==-1;case"keydown":return e.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Ir(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var ya=!1;function e0(t,e){switch(t){case"compositionend":return Ir(e);case"keypress":return e.which!==32?null:(Fr=!0,Wr);case"textInput":return t=e.data,t===Wr&&Fr?null:t;default:return null}}function l0(t,e){if(ya)return t==="compositionend"||!Ji&&Pr(t,e)?(t=Vr(),on=Xi=vl=null,ya=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(e.ctrlKey||e.altKey||e.metaKey)||e.ctrlKey&&e.altKey){if(e.char&&1=e)return{node:l,offset:e-t};t=a}t:{for(;l;){if(l.nextSibling){l=l.nextSibling;break t}l=l.parentNode}l=void 0}l=cs(l)}}function rs(t,e){return t&&e?t===e?!0:t&&t.nodeType===3?!1:e&&e.nodeType===3?rs(t,e.parentNode):"contains"in t?t.contains(e):t.compareDocumentPosition?!!(t.compareDocumentPosition(e)&16):!1:!1}function ss(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var e=rn(t.document);e instanceof t.HTMLIFrameElement;){try{var l=typeof e.contentWindow.location.href=="string"}catch{l=!1}if(l)t=e.contentWindow;else break;e=rn(t.document)}return e}function Wi(t){var e=t&&t.nodeName&&t.nodeName.toLowerCase();return e&&(e==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||e==="textarea"||t.contentEditable==="true")}var s0=We&&"documentMode"in document&&11>=document.documentMode,va=null,Fi=null,nu=null,Pi=!1;function os(t,e,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;Pi||va==null||va!==rn(a)||(a=va,"selectionStart"in a&&Wi(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),nu&&uu(nu,a)||(nu=a,a=ei(Fi,"onSelect"),0>=c,u-=c,Pe=1<<32-It(e)+u|l<n?n:8;var c=z.T,s={};z.T=s,jc(t,!1,e,l);try{var m=u(),T=z.S;if(T!==null&&T(s,m),m!==null&&typeof m=="object"&&typeof m.then=="function"){var M=S0(m,a);bu(t,e,M,Re(t))}else bu(t,e,a,Re(t))}catch(q){bu(t,e,{then:function(){},status:"rejected",reason:q},Re())}finally{X.p=n,z.T=c}}function A0(){}function qc(t,e,l,a){if(t.tag!==5)throw Error(f(476));var u=ho(t).queue;oo(t,u,e,$,l===null?A0:function(){return mo(t),l(a)})}function ho(t){var e=t.memoizedState;if(e!==null)return e;e={memoizedState:$,baseState:$,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ll,lastRenderedState:$},next:null};var l={};return e.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ll,lastRenderedState:l},next:null},t.memoizedState=e,t=t.alternate,t!==null&&(t.memoizedState=e),e}function mo(t){var e=ho(t).next.queue;bu(t,e,{},Re())}function Bc(){return ne(Lu)}function yo(){return Gt().memoizedState}function vo(){return Gt().memoizedState}function O0(t){for(var e=t.return;e!==null;){switch(e.tag){case 24:case 3:var l=Re();t=Sl(l);var a=bl(e,t,l);a!==null&&(Ae(a,e,l),mu(a,e,l)),e={cache:dc()},t.payload=e;return}e=e.return}}function x0(t,e,l){var a=Re();l={lane:a,revertLane:0,action:l,hasEagerState:!1,eagerState:null,next:null},qn(t)?po(e,l):(l=lc(t,e,l,a),l!==null&&(Ae(l,t,a),So(l,e,a)))}function go(t,e,l){var a=Re();bu(t,e,l,a)}function bu(t,e,l,a){var u={lane:a,revertLane:0,action:l,hasEagerState:!1,eagerState:null,next:null};if(qn(t))po(e,u);else{var n=t.alternate;if(t.lanes===0&&(n===null||n.lanes===0)&&(n=e.lastRenderedReducer,n!==null))try{var c=e.lastRenderedState,s=n(c,l);if(u.hasEagerState=!0,u.eagerState=s,pe(s,c))return pn(t,e,u,0),_t===null&&gn(),!1}catch{}finally{}if(l=lc(t,e,u,a),l!==null)return Ae(l,t,a),So(l,e,a),!0}return!1}function jc(t,e,l,a){if(a={lane:2,revertLane:vf(),action:a,hasEagerState:!1,eagerState:null,next:null},qn(t)){if(e)throw Error(f(479))}else e=lc(t,l,a,2),e!==null&&Ae(e,t,2)}function qn(t){var e=t.alternate;return t===ut||e!==null&&e===ut}function po(t,e){xa=zn=!0;var l=t.pending;l===null?e.next=e:(e.next=l.next,l.next=e),t.pending=e}function So(t,e,l){if((l&4194048)!==0){var a=e.lanes;a&=t.pendingLanes,l|=a,e.lanes=l,xr(t,l)}}var Bn={readContext:ne,use:Un,useCallback:jt,useContext:jt,useEffect:jt,useImperativeHandle:jt,useLayoutEffect:jt,useInsertionEffect:jt,useMemo:jt,useReducer:jt,useRef:jt,useState:jt,useDebugValue:jt,useDeferredValue:jt,useTransition:jt,useSyncExternalStore:jt,useId:jt,useHostTransitionStatus:jt,useFormState:jt,useActionState:jt,useOptimistic:jt,useMemoCache:jt,useCacheRefresh:jt},bo={readContext:ne,use:Un,useCallback:function(t,e){return ye().memoizedState=[t,e===void 0?null:e],t},useContext:ne,useEffect:lo,useImperativeHandle:function(t,e,l){l=l!=null?l.concat([t]):null,Hn(4194308,4,io.bind(null,e,t),l)},useLayoutEffect:function(t,e){return Hn(4194308,4,t,e)},useInsertionEffect:function(t,e){Hn(4,2,t,e)},useMemo:function(t,e){var l=ye();e=e===void 0?null:e;var a=t();if(Il){Ye(!0);try{t()}finally{Ye(!1)}}return l.memoizedState=[a,e],a},useReducer:function(t,e,l){var a=ye();if(l!==void 0){var u=l(e);if(Il){Ye(!0);try{l(e)}finally{Ye(!1)}}}else u=e;return a.memoizedState=a.baseState=u,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:u},a.queue=t,t=t.dispatch=x0.bind(null,ut,t),[a.memoizedState,t]},useRef:function(t){var e=ye();return t={current:t},e.memoizedState=t},useState:function(t){t=Uc(t);var e=t.queue,l=go.bind(null,ut,e);return e.dispatch=l,[t.memoizedState,l]},useDebugValue:Cc,useDeferredValue:function(t,e){var l=ye();return Hc(l,t,e)},useTransition:function(){var t=Uc(!1);return t=oo.bind(null,ut,t.queue,!0,!1),ye().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,e,l){var a=ut,u=ye();if(mt){if(l===void 0)throw Error(f(407));l=l()}else{if(l=e(),_t===null)throw Error(f(349));(st&124)!==0||ws(a,e,l)}u.memoizedState=l;var n={value:l,getSnapshot:e};return u.queue=n,lo(Xs.bind(null,a,n,t),[t]),a.flags|=2048,Da(9,Cn(),Gs.bind(null,a,n,l,e),null),l},useId:function(){var t=ye(),e=_t.identifierPrefix;if(mt){var l=Ie,a=Pe;l=(a&~(1<<32-It(a)-1)).toString(32)+l,e="«"+e+"R"+l,l=Mn++,0F?(Ft=J,J=null):Ft=J.sibling;var dt=R(S,J,E[F],C);if(dt===null){J===null&&(J=Ft);break}t&&J&&dt.alternate===null&&e(S,J),p=n(dt,p,F),nt===null?K=dt:nt.sibling=dt,nt=dt,J=Ft}if(F===E.length)return l(S,J),mt&&Jl(S,F),K;if(J===null){for(;FF?(Ft=J,J=null):Ft=J.sibling;var jl=R(S,J,dt.value,C);if(jl===null){J===null&&(J=Ft);break}t&&J&&jl.alternate===null&&e(S,J),p=n(jl,p,F),nt===null?K=jl:nt.sibling=jl,nt=jl,J=Ft}if(dt.done)return l(S,J),mt&&Jl(S,F),K;if(J===null){for(;!dt.done;F++,dt=E.next())dt=q(S,dt.value,C),dt!==null&&(p=n(dt,p,F),nt===null?K=dt:nt.sibling=dt,nt=dt);return mt&&Jl(S,F),K}for(J=a(J);!dt.done;F++,dt=E.next())dt=x(J,S,F,dt.value,C),dt!==null&&(t&&dt.alternate!==null&&J.delete(dt.key===null?F:dt.key),p=n(dt,p,F),nt===null?K=dt:nt.sibling=dt,nt=dt);return t&&J.forEach(function(Dy){return e(S,Dy)}),mt&&Jl(S,F),K}function Rt(S,p,E,C){if(typeof E=="object"&&E!==null&&E.type===H&&E.key===null&&(E=E.props.children),typeof E=="object"&&E!==null){switch(E.$$typeof){case D:t:{for(var K=E.key;p!==null;){if(p.key===K){if(K=E.type,K===H){if(p.tag===7){l(S,p.sibling),C=u(p,E.props.children),C.return=S,S=C;break t}}else if(p.elementType===K||typeof K=="object"&&K!==null&&K.$$typeof===et&&To(K)===p.type){l(S,p.sibling),C=u(p,E.props),Tu(C,E),C.return=S,S=C;break t}l(S,p);break}else e(S,p);p=p.sibling}E.type===H?(C=Zl(E.props.children,S.mode,C,E.key),C.return=S,S=C):(C=bn(E.type,E.key,E.props,null,S.mode,C),Tu(C,E),C.return=S,S=C)}return c(S);case j:t:{for(K=E.key;p!==null;){if(p.key===K)if(p.tag===4&&p.stateNode.containerInfo===E.containerInfo&&p.stateNode.implementation===E.implementation){l(S,p.sibling),C=u(p,E.children||[]),C.return=S,S=C;break t}else{l(S,p);break}else e(S,p);p=p.sibling}C=nc(E,S.mode,C),C.return=S,S=C}return c(S);case et:return K=E._init,E=K(E._payload),Rt(S,p,E,C)}if(Bt(E))return I(S,p,E,C);if(Dt(E)){if(K=Dt(E),typeof K!="function")throw Error(f(150));return E=K.call(E),W(S,p,E,C)}if(typeof E.then=="function")return Rt(S,p,jn(E),C);if(E.$$typeof===Q)return Rt(S,p,An(S,E),C);Ln(S,E)}return typeof E=="string"&&E!==""||typeof E=="number"||typeof E=="bigint"?(E=""+E,p!==null&&p.tag===6?(l(S,p.sibling),C=u(p,E),C.return=S,S=C):(l(S,p),C=uc(E,S.mode,C),C.return=S,S=C),c(S)):l(S,p)}return function(S,p,E,C){try{Eu=0;var K=Rt(S,p,E,C);return za=null,K}catch(J){if(J===du||J===xn)throw J;var nt=Se(29,J,null,S.mode);return nt.lanes=C,nt.return=S,nt}finally{}}}var Ma=Ro(!0),Ao=Ro(!1),Ue=B(null),Ge=null;function Tl(t){var e=t.alternate;Y(Zt,Zt.current&1),Y(Ue,t),Ge===null&&(e===null||Oa.current!==null||e.memoizedState!==null)&&(Ge=t)}function Oo(t){if(t.tag===22){if(Y(Zt,Zt.current),Y(Ue,t),Ge===null){var e=t.alternate;e!==null&&e.memoizedState!==null&&(Ge=t)}}else Rl()}function Rl(){Y(Zt,Zt.current),Y(Ue,Ue.current)}function al(t){G(Ue),Ge===t&&(Ge=null),G(Zt)}var Zt=B(0);function Yn(t){for(var e=t;e!==null;){if(e.tag===13){var l=e.memoizedState;if(l!==null&&(l=l.dehydrated,l===null||l.data==="$?"||Df(l)))return e}else if(e.tag===19&&e.memoizedProps.revealOrder!==void 0){if((e.flags&128)!==0)return e}else if(e.child!==null){e.child.return=e,e=e.child;continue}if(e===t)break;for(;e.sibling===null;){if(e.return===null||e.return===t)return null;e=e.return}e.sibling.return=e.return,e=e.sibling}return null}function Lc(t,e,l,a){e=t.memoizedState,l=l(a,e),l=l==null?e:O({},e,l),t.memoizedState=l,t.lanes===0&&(t.updateQueue.baseState=l)}var Yc={enqueueSetState:function(t,e,l){t=t._reactInternals;var a=Re(),u=Sl(a);u.payload=e,l!=null&&(u.callback=l),e=bl(t,u,a),e!==null&&(Ae(e,t,a),mu(e,t,a))},enqueueReplaceState:function(t,e,l){t=t._reactInternals;var a=Re(),u=Sl(a);u.tag=1,u.payload=e,l!=null&&(u.callback=l),e=bl(t,u,a),e!==null&&(Ae(e,t,a),mu(e,t,a))},enqueueForceUpdate:function(t,e){t=t._reactInternals;var l=Re(),a=Sl(l);a.tag=2,e!=null&&(a.callback=e),e=bl(t,a,l),e!==null&&(Ae(e,t,l),mu(e,t,l))}};function xo(t,e,l,a,u,n,c){return t=t.stateNode,typeof t.shouldComponentUpdate=="function"?t.shouldComponentUpdate(a,n,c):e.prototype&&e.prototype.isPureReactComponent?!uu(l,a)||!uu(u,n):!0}function _o(t,e,l,a){t=e.state,typeof e.componentWillReceiveProps=="function"&&e.componentWillReceiveProps(l,a),typeof e.UNSAFE_componentWillReceiveProps=="function"&&e.UNSAFE_componentWillReceiveProps(l,a),e.state!==t&&Yc.enqueueReplaceState(e,e.state,null)}function ta(t,e){var l=e;if("ref"in e){l={};for(var a in e)a!=="ref"&&(l[a]=e[a])}if(t=t.defaultProps){l===e&&(l=O({},l));for(var u in t)l[u]===void 0&&(l[u]=t[u])}return l}var wn=typeof reportError=="function"?reportError:function(t){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var e=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof t=="object"&&t!==null&&typeof t.message=="string"?String(t.message):String(t),error:t});if(!window.dispatchEvent(e))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",t);return}console.error(t)};function Do(t){wn(t)}function zo(t){console.error(t)}function Mo(t){wn(t)}function Gn(t,e){try{var l=t.onUncaughtError;l(e.value,{componentStack:e.stack})}catch(a){setTimeout(function(){throw a})}}function Uo(t,e,l){try{var a=t.onCaughtError;a(l.value,{componentStack:l.stack,errorBoundary:e.tag===1?e.stateNode:null})}catch(u){setTimeout(function(){throw u})}}function wc(t,e,l){return l=Sl(l),l.tag=3,l.payload={element:null},l.callback=function(){Gn(t,e)},l}function No(t){return t=Sl(t),t.tag=3,t}function Co(t,e,l,a){var u=l.type.getDerivedStateFromError;if(typeof u=="function"){var n=a.value;t.payload=function(){return u(n)},t.callback=function(){Uo(e,l,a)}}var c=l.stateNode;c!==null&&typeof c.componentDidCatch=="function"&&(t.callback=function(){Uo(e,l,a),typeof u!="function"&&(zl===null?zl=new Set([this]):zl.add(this));var s=a.stack;this.componentDidCatch(a.value,{componentStack:s!==null?s:""})})}function D0(t,e,l,a,u){if(l.flags|=32768,a!==null&&typeof a=="object"&&typeof a.then=="function"){if(e=l.alternate,e!==null&&ru(e,l,u,!0),l=Ue.current,l!==null){switch(l.tag){case 13:return Ge===null?of():l.alternate===null&&qt===0&&(qt=3),l.flags&=-257,l.flags|=65536,l.lanes=u,a===yc?l.flags|=16384:(e=l.updateQueue,e===null?l.updateQueue=new Set([a]):e.add(a),hf(t,a,u)),!1;case 22:return l.flags|=65536,a===yc?l.flags|=16384:(e=l.updateQueue,e===null?(e={transitions:null,markerInstances:null,retryQueue:new Set([a])},l.updateQueue=e):(l=e.retryQueue,l===null?e.retryQueue=new Set([a]):l.add(a)),hf(t,a,u)),!1}throw Error(f(435,l.tag))}return hf(t,a,u),of(),!1}if(mt)return e=Ue.current,e!==null?((e.flags&65536)===0&&(e.flags|=256),e.flags|=65536,e.lanes=u,a!==fc&&(t=Error(f(422),{cause:a}),fu(_e(t,l)))):(a!==fc&&(e=Error(f(423),{cause:a}),fu(_e(e,l))),t=t.current.alternate,t.flags|=65536,u&=-u,t.lanes|=u,a=_e(a,l),u=wc(t.stateNode,a,u),pc(t,u),qt!==4&&(qt=2)),!1;var n=Error(f(520),{cause:a});if(n=_e(n,l),zu===null?zu=[n]:zu.push(n),qt!==4&&(qt=2),e===null)return!0;a=_e(a,l),l=e;do{switch(l.tag){case 3:return l.flags|=65536,t=u&-u,l.lanes|=t,t=wc(l.stateNode,a,t),pc(l,t),!1;case 1:if(e=l.type,n=l.stateNode,(l.flags&128)===0&&(typeof e.getDerivedStateFromError=="function"||n!==null&&typeof n.componentDidCatch=="function"&&(zl===null||!zl.has(n))))return l.flags|=65536,u&=-u,l.lanes|=u,u=No(u),Co(u,t,l,a),pc(l,u),!1}l=l.return}while(l!==null);return!1}var Ho=Error(f(461)),kt=!1;function te(t,e,l,a){e.child=t===null?Ao(e,null,l,a):Ma(e,t.child,l,a)}function qo(t,e,l,a,u){l=l.render;var n=e.ref;if("ref"in a){var c={};for(var s in a)s!=="ref"&&(c[s]=a[s])}else c=a;return Fl(e),a=Rc(t,e,l,c,n,u),s=Ac(),t!==null&&!kt?(Oc(t,e,u),ul(t,e,u)):(mt&&s&&ic(e),e.flags|=1,te(t,e,a,u),e.child)}function Bo(t,e,l,a,u){if(t===null){var n=l.type;return typeof n=="function"&&!ac(n)&&n.defaultProps===void 0&&l.compare===null?(e.tag=15,e.type=n,jo(t,e,n,a,u)):(t=bn(l.type,null,a,e,e.mode,u),t.ref=e.ref,t.return=e,e.child=t)}if(n=t.child,!$c(t,u)){var c=n.memoizedProps;if(l=l.compare,l=l!==null?l:uu,l(c,a)&&t.ref===e.ref)return ul(t,e,u)}return e.flags|=1,t=Fe(n,a),t.ref=e.ref,t.return=e,e.child=t}function jo(t,e,l,a,u){if(t!==null){var n=t.memoizedProps;if(uu(n,a)&&t.ref===e.ref)if(kt=!1,e.pendingProps=a=n,$c(t,u))(t.flags&131072)!==0&&(kt=!0);else return e.lanes=t.lanes,ul(t,e,u)}return Gc(t,e,l,a,u)}function Lo(t,e,l){var a=e.pendingProps,u=a.children,n=t!==null?t.memoizedState:null;if(a.mode==="hidden"){if((e.flags&128)!==0){if(a=n!==null?n.baseLanes|l:l,t!==null){for(u=e.child=t.child,n=0;u!==null;)n=n|u.lanes|u.childLanes,u=u.sibling;e.childLanes=n&~a}else e.childLanes=0,e.child=null;return Yo(t,e,a,l)}if((l&536870912)!==0)e.memoizedState={baseLanes:0,cachePool:null},t!==null&&On(e,n!==null?n.cachePool:null),n!==null?Bs(e,n):bc(),Oo(e);else return e.lanes=e.childLanes=536870912,Yo(t,e,n!==null?n.baseLanes|l:l,l)}else n!==null?(On(e,n.cachePool),Bs(e,n),Rl(),e.memoizedState=null):(t!==null&&On(e,null),bc(),Rl());return te(t,e,u,l),e.child}function Yo(t,e,l,a){var u=mc();return u=u===null?null:{parent:Vt._currentValue,pool:u},e.memoizedState={baseLanes:l,cachePool:u},t!==null&&On(e,null),bc(),Oo(e),t!==null&&ru(t,e,a,!0),null}function Xn(t,e){var l=e.ref;if(l===null)t!==null&&t.ref!==null&&(e.flags|=4194816);else{if(typeof l!="function"&&typeof l!="object")throw Error(f(284));(t===null||t.ref!==l)&&(e.flags|=4194816)}}function Gc(t,e,l,a,u){return Fl(e),l=Rc(t,e,l,a,void 0,u),a=Ac(),t!==null&&!kt?(Oc(t,e,u),ul(t,e,u)):(mt&&a&&ic(e),e.flags|=1,te(t,e,l,u),e.child)}function wo(t,e,l,a,u,n){return Fl(e),e.updateQueue=null,l=Ls(e,a,l,u),js(t),a=Ac(),t!==null&&!kt?(Oc(t,e,n),ul(t,e,n)):(mt&&a&&ic(e),e.flags|=1,te(t,e,l,n),e.child)}function Go(t,e,l,a,u){if(Fl(e),e.stateNode===null){var n=ba,c=l.contextType;typeof c=="object"&&c!==null&&(n=ne(c)),n=new l(a,n),e.memoizedState=n.state!==null&&n.state!==void 0?n.state:null,n.updater=Yc,e.stateNode=n,n._reactInternals=e,n=e.stateNode,n.props=a,n.state=e.memoizedState,n.refs={},vc(e),c=l.contextType,n.context=typeof c=="object"&&c!==null?ne(c):ba,n.state=e.memoizedState,c=l.getDerivedStateFromProps,typeof c=="function"&&(Lc(e,l,c,a),n.state=e.memoizedState),typeof l.getDerivedStateFromProps=="function"||typeof n.getSnapshotBeforeUpdate=="function"||typeof n.UNSAFE_componentWillMount!="function"&&typeof n.componentWillMount!="function"||(c=n.state,typeof n.componentWillMount=="function"&&n.componentWillMount(),typeof n.UNSAFE_componentWillMount=="function"&&n.UNSAFE_componentWillMount(),c!==n.state&&Yc.enqueueReplaceState(n,n.state,null),vu(e,a,n,u),yu(),n.state=e.memoizedState),typeof n.componentDidMount=="function"&&(e.flags|=4194308),a=!0}else if(t===null){n=e.stateNode;var s=e.memoizedProps,m=ta(l,s);n.props=m;var T=n.context,M=l.contextType;c=ba,typeof M=="object"&&M!==null&&(c=ne(M));var q=l.getDerivedStateFromProps;M=typeof q=="function"||typeof n.getSnapshotBeforeUpdate=="function",s=e.pendingProps!==s,M||typeof n.UNSAFE_componentWillReceiveProps!="function"&&typeof n.componentWillReceiveProps!="function"||(s||T!==c)&&_o(e,n,a,c),pl=!1;var R=e.memoizedState;n.state=R,vu(e,a,n,u),yu(),T=e.memoizedState,s||R!==T||pl?(typeof q=="function"&&(Lc(e,l,q,a),T=e.memoizedState),(m=pl||xo(e,l,m,a,R,T,c))?(M||typeof n.UNSAFE_componentWillMount!="function"&&typeof n.componentWillMount!="function"||(typeof n.componentWillMount=="function"&&n.componentWillMount(),typeof n.UNSAFE_componentWillMount=="function"&&n.UNSAFE_componentWillMount()),typeof n.componentDidMount=="function"&&(e.flags|=4194308)):(typeof n.componentDidMount=="function"&&(e.flags|=4194308),e.memoizedProps=a,e.memoizedState=T),n.props=a,n.state=T,n.context=c,a=m):(typeof n.componentDidMount=="function"&&(e.flags|=4194308),a=!1)}else{n=e.stateNode,gc(t,e),c=e.memoizedProps,M=ta(l,c),n.props=M,q=e.pendingProps,R=n.context,T=l.contextType,m=ba,typeof T=="object"&&T!==null&&(m=ne(T)),s=l.getDerivedStateFromProps,(T=typeof s=="function"||typeof n.getSnapshotBeforeUpdate=="function")||typeof n.UNSAFE_componentWillReceiveProps!="function"&&typeof n.componentWillReceiveProps!="function"||(c!==q||R!==m)&&_o(e,n,a,m),pl=!1,R=e.memoizedState,n.state=R,vu(e,a,n,u),yu();var x=e.memoizedState;c!==q||R!==x||pl||t!==null&&t.dependencies!==null&&Rn(t.dependencies)?(typeof s=="function"&&(Lc(e,l,s,a),x=e.memoizedState),(M=pl||xo(e,l,M,a,R,x,m)||t!==null&&t.dependencies!==null&&Rn(t.dependencies))?(T||typeof n.UNSAFE_componentWillUpdate!="function"&&typeof n.componentWillUpdate!="function"||(typeof n.componentWillUpdate=="function"&&n.componentWillUpdate(a,x,m),typeof n.UNSAFE_componentWillUpdate=="function"&&n.UNSAFE_componentWillUpdate(a,x,m)),typeof n.componentDidUpdate=="function"&&(e.flags|=4),typeof n.getSnapshotBeforeUpdate=="function"&&(e.flags|=1024)):(typeof n.componentDidUpdate!="function"||c===t.memoizedProps&&R===t.memoizedState||(e.flags|=4),typeof n.getSnapshotBeforeUpdate!="function"||c===t.memoizedProps&&R===t.memoizedState||(e.flags|=1024),e.memoizedProps=a,e.memoizedState=x),n.props=a,n.state=x,n.context=m,a=M):(typeof n.componentDidUpdate!="function"||c===t.memoizedProps&&R===t.memoizedState||(e.flags|=4),typeof n.getSnapshotBeforeUpdate!="function"||c===t.memoizedProps&&R===t.memoizedState||(e.flags|=1024),a=!1)}return n=a,Xn(t,e),a=(e.flags&128)!==0,n||a?(n=e.stateNode,l=a&&typeof l.getDerivedStateFromError!="function"?null:n.render(),e.flags|=1,t!==null&&a?(e.child=Ma(e,t.child,null,u),e.child=Ma(e,null,l,u)):te(t,e,l,u),e.memoizedState=n.state,t=e.child):t=ul(t,e,u),t}function Xo(t,e,l,a){return cu(),e.flags|=256,te(t,e,l,a),e.child}var Xc={dehydrated:null,treeContext:null,retryLane:0,hydrationErrors:null};function Qc(t){return{baseLanes:t,cachePool:Ds()}}function Vc(t,e,l){return t=t!==null?t.childLanes&~l:0,e&&(t|=Ne),t}function Qo(t,e,l){var a=e.pendingProps,u=!1,n=(e.flags&128)!==0,c;if((c=n)||(c=t!==null&&t.memoizedState===null?!1:(Zt.current&2)!==0),c&&(u=!0,e.flags&=-129),c=(e.flags&32)!==0,e.flags&=-33,t===null){if(mt){if(u?Tl(e):Rl(),mt){var s=Ht,m;if(m=s){t:{for(m=s,s=we;m.nodeType!==8;){if(!s){s=null;break t}if(m=Be(m.nextSibling),m===null){s=null;break t}}s=m}s!==null?(e.memoizedState={dehydrated:s,treeContext:Kl!==null?{id:Pe,overflow:Ie}:null,retryLane:536870912,hydrationErrors:null},m=Se(18,null,null,0),m.stateNode=s,m.return=e,e.child=m,re=e,Ht=null,m=!0):m=!1}m||kl(e)}if(s=e.memoizedState,s!==null&&(s=s.dehydrated,s!==null))return Df(s)?e.lanes=32:e.lanes=536870912,null;al(e)}return s=a.children,a=a.fallback,u?(Rl(),u=e.mode,s=Qn({mode:"hidden",children:s},u),a=Zl(a,u,l,null),s.return=e,a.return=e,s.sibling=a,e.child=s,u=e.child,u.memoizedState=Qc(l),u.childLanes=Vc(t,c,l),e.memoizedState=Xc,a):(Tl(e),Zc(e,s))}if(m=t.memoizedState,m!==null&&(s=m.dehydrated,s!==null)){if(n)e.flags&256?(Tl(e),e.flags&=-257,e=Kc(t,e,l)):e.memoizedState!==null?(Rl(),e.child=t.child,e.flags|=128,e=null):(Rl(),u=a.fallback,s=e.mode,a=Qn({mode:"visible",children:a.children},s),u=Zl(u,s,l,null),u.flags|=2,a.return=e,u.return=e,a.sibling=u,e.child=a,Ma(e,t.child,null,l),a=e.child,a.memoizedState=Qc(l),a.childLanes=Vc(t,c,l),e.memoizedState=Xc,e=u);else if(Tl(e),Df(s)){if(c=s.nextSibling&&s.nextSibling.dataset,c)var T=c.dgst;c=T,a=Error(f(419)),a.stack="",a.digest=c,fu({value:a,source:null,stack:null}),e=Kc(t,e,l)}else if(kt||ru(t,e,l,!1),c=(l&t.childLanes)!==0,kt||c){if(c=_t,c!==null&&(a=l&-l,a=(a&42)!==0?1:Di(a),a=(a&(c.suspendedLanes|l))!==0?0:a,a!==0&&a!==m.retryLane))throw m.retryLane=a,Sa(t,a),Ae(c,t,a),Ho;s.data==="$?"||of(),e=Kc(t,e,l)}else s.data==="$?"?(e.flags|=192,e.child=t.child,e=null):(t=m.treeContext,Ht=Be(s.nextSibling),re=e,mt=!0,$l=null,we=!1,t!==null&&(ze[Me++]=Pe,ze[Me++]=Ie,ze[Me++]=Kl,Pe=t.id,Ie=t.overflow,Kl=e),e=Zc(e,a.children),e.flags|=4096);return e}return u?(Rl(),u=a.fallback,s=e.mode,m=t.child,T=m.sibling,a=Fe(m,{mode:"hidden",children:a.children}),a.subtreeFlags=m.subtreeFlags&65011712,T!==null?u=Fe(T,u):(u=Zl(u,s,l,null),u.flags|=2),u.return=e,a.return=e,a.sibling=u,e.child=a,a=u,u=e.child,s=t.child.memoizedState,s===null?s=Qc(l):(m=s.cachePool,m!==null?(T=Vt._currentValue,m=m.parent!==T?{parent:T,pool:T}:m):m=Ds(),s={baseLanes:s.baseLanes|l,cachePool:m}),u.memoizedState=s,u.childLanes=Vc(t,c,l),e.memoizedState=Xc,a):(Tl(e),l=t.child,t=l.sibling,l=Fe(l,{mode:"visible",children:a.children}),l.return=e,l.sibling=null,t!==null&&(c=e.deletions,c===null?(e.deletions=[t],e.flags|=16):c.push(t)),e.child=l,e.memoizedState=null,l)}function Zc(t,e){return e=Qn({mode:"visible",children:e},t.mode),e.return=t,t.child=e}function Qn(t,e){return t=Se(22,t,null,e),t.lanes=0,t.stateNode={_visibility:1,_pendingMarkers:null,_retryCache:null,_transitions:null},t}function Kc(t,e,l){return Ma(e,t.child,null,l),t=Zc(e,e.pendingProps.children),t.flags|=2,e.memoizedState=null,t}function Vo(t,e,l){t.lanes|=e;var a=t.alternate;a!==null&&(a.lanes|=e),sc(t.return,e,l)}function Jc(t,e,l,a,u){var n=t.memoizedState;n===null?t.memoizedState={isBackwards:e,rendering:null,renderingStartTime:0,last:a,tail:l,tailMode:u}:(n.isBackwards=e,n.rendering=null,n.renderingStartTime=0,n.last=a,n.tail=l,n.tailMode=u)}function Zo(t,e,l){var a=e.pendingProps,u=a.revealOrder,n=a.tail;if(te(t,e,a.children,l),a=Zt.current,(a&2)!==0)a=a&1|2,e.flags|=128;else{if(t!==null&&(t.flags&128)!==0)t:for(t=e.child;t!==null;){if(t.tag===13)t.memoizedState!==null&&Vo(t,l,e);else if(t.tag===19)Vo(t,l,e);else if(t.child!==null){t.child.return=t,t=t.child;continue}if(t===e)break t;for(;t.sibling===null;){if(t.return===null||t.return===e)break t;t=t.return}t.sibling.return=t.return,t=t.sibling}a&=1}switch(Y(Zt,a),u){case"forwards":for(l=e.child,u=null;l!==null;)t=l.alternate,t!==null&&Yn(t)===null&&(u=l),l=l.sibling;l=u,l===null?(u=e.child,e.child=null):(u=l.sibling,l.sibling=null),Jc(e,!1,u,l,n);break;case"backwards":for(l=null,u=e.child,e.child=null;u!==null;){if(t=u.alternate,t!==null&&Yn(t)===null){e.child=u;break}t=u.sibling,u.sibling=l,l=u,u=t}Jc(e,!0,l,null,n);break;case"together":Jc(e,!1,null,null,void 0);break;default:e.memoizedState=null}return e.child}function ul(t,e,l){if(t!==null&&(e.dependencies=t.dependencies),Dl|=e.lanes,(l&e.childLanes)===0)if(t!==null){if(ru(t,e,l,!1),(l&e.childLanes)===0)return null}else return null;if(t!==null&&e.child!==t.child)throw Error(f(153));if(e.child!==null){for(t=e.child,l=Fe(t,t.pendingProps),e.child=l,l.return=e;t.sibling!==null;)t=t.sibling,l=l.sibling=Fe(t,t.pendingProps),l.return=e;l.sibling=null}return e.child}function $c(t,e){return(t.lanes&e)!==0?!0:(t=t.dependencies,!!(t!==null&&Rn(t)))}function z0(t,e,l){switch(e.tag){case 3:xt(e,e.stateNode.containerInfo),gl(e,Vt,t.memoizedState.cache),cu();break;case 27:case 5:$e(e);break;case 4:xt(e,e.stateNode.containerInfo);break;case 10:gl(e,e.type,e.memoizedProps.value);break;case 13:var a=e.memoizedState;if(a!==null)return a.dehydrated!==null?(Tl(e),e.flags|=128,null):(l&e.child.childLanes)!==0?Qo(t,e,l):(Tl(e),t=ul(t,e,l),t!==null?t.sibling:null);Tl(e);break;case 19:var u=(t.flags&128)!==0;if(a=(l&e.childLanes)!==0,a||(ru(t,e,l,!1),a=(l&e.childLanes)!==0),u){if(a)return Zo(t,e,l);e.flags|=128}if(u=e.memoizedState,u!==null&&(u.rendering=null,u.tail=null,u.lastEffect=null),Y(Zt,Zt.current),a)break;return null;case 22:case 23:return e.lanes=0,Lo(t,e,l);case 24:gl(e,Vt,t.memoizedState.cache)}return ul(t,e,l)}function Ko(t,e,l){if(t!==null)if(t.memoizedProps!==e.pendingProps)kt=!0;else{if(!$c(t,l)&&(e.flags&128)===0)return kt=!1,z0(t,e,l);kt=(t.flags&131072)!==0}else kt=!1,mt&&(e.flags&1048576)!==0&&Es(e,Tn,e.index);switch(e.lanes=0,e.tag){case 16:t:{t=e.pendingProps;var a=e.elementType,u=a._init;if(a=u(a._payload),e.type=a,typeof a=="function")ac(a)?(t=ta(a,t),e.tag=1,e=Go(null,e,a,t,l)):(e.tag=0,e=Gc(null,e,a,t,l));else{if(a!=null){if(u=a.$$typeof,u===lt){e.tag=11,e=qo(null,e,a,t,l);break t}else if(u===gt){e.tag=14,e=Bo(null,e,a,t,l);break t}}throw e=se(a)||a,Error(f(306,e,""))}}return e;case 0:return Gc(t,e,e.type,e.pendingProps,l);case 1:return a=e.type,u=ta(a,e.pendingProps),Go(t,e,a,u,l);case 3:t:{if(xt(e,e.stateNode.containerInfo),t===null)throw Error(f(387));a=e.pendingProps;var n=e.memoizedState;u=n.element,gc(t,e),vu(e,a,null,l);var c=e.memoizedState;if(a=c.cache,gl(e,Vt,a),a!==n.cache&&oc(e,[Vt],l,!0),yu(),a=c.element,n.isDehydrated)if(n={element:a,isDehydrated:!1,cache:c.cache},e.updateQueue.baseState=n,e.memoizedState=n,e.flags&256){e=Xo(t,e,a,l);break t}else if(a!==u){u=_e(Error(f(424)),e),fu(u),e=Xo(t,e,a,l);break t}else{switch(t=e.stateNode.containerInfo,t.nodeType){case 9:t=t.body;break;default:t=t.nodeName==="HTML"?t.ownerDocument.body:t}for(Ht=Be(t.firstChild),re=e,mt=!0,$l=null,we=!0,l=Ao(e,null,a,l),e.child=l;l;)l.flags=l.flags&-3|4096,l=l.sibling}else{if(cu(),a===u){e=ul(t,e,l);break t}te(t,e,a,l)}e=e.child}return e;case 26:return Xn(t,e),t===null?(l=Wd(e.type,null,e.pendingProps,null))?e.memoizedState=l:mt||(l=e.type,t=e.pendingProps,a=ai(tt.current).createElement(l),a[ue]=e,a[he]=t,le(a,l,t),$t(a),e.stateNode=a):e.memoizedState=Wd(e.type,t.memoizedProps,e.pendingProps,t.memoizedState),null;case 27:return $e(e),t===null&&mt&&(a=e.stateNode=Jd(e.type,e.pendingProps,tt.current),re=e,we=!0,u=Ht,Nl(e.type)?(zf=u,Ht=Be(a.firstChild)):Ht=u),te(t,e,e.pendingProps.children,l),Xn(t,e),t===null&&(e.flags|=4194304),e.child;case 5:return t===null&&mt&&((u=a=Ht)&&(a=ay(a,e.type,e.pendingProps,we),a!==null?(e.stateNode=a,re=e,Ht=Be(a.firstChild),we=!1,u=!0):u=!1),u||kl(e)),$e(e),u=e.type,n=e.pendingProps,c=t!==null?t.memoizedProps:null,a=n.children,Of(u,n)?a=null:c!==null&&Of(u,c)&&(e.flags|=32),e.memoizedState!==null&&(u=Rc(t,e,E0,null,null,l),Lu._currentValue=u),Xn(t,e),te(t,e,a,l),e.child;case 6:return t===null&&mt&&((t=l=Ht)&&(l=uy(l,e.pendingProps,we),l!==null?(e.stateNode=l,re=e,Ht=null,t=!0):t=!1),t||kl(e)),null;case 13:return Qo(t,e,l);case 4:return xt(e,e.stateNode.containerInfo),a=e.pendingProps,t===null?e.child=Ma(e,null,a,l):te(t,e,a,l),e.child;case 11:return qo(t,e,e.type,e.pendingProps,l);case 7:return te(t,e,e.pendingProps,l),e.child;case 8:return te(t,e,e.pendingProps.children,l),e.child;case 12:return te(t,e,e.pendingProps.children,l),e.child;case 10:return a=e.pendingProps,gl(e,e.type,a.value),te(t,e,a.children,l),e.child;case 9:return u=e.type._context,a=e.pendingProps.children,Fl(e),u=ne(u),a=a(u),e.flags|=1,te(t,e,a,l),e.child;case 14:return Bo(t,e,e.type,e.pendingProps,l);case 15:return jo(t,e,e.type,e.pendingProps,l);case 19:return Zo(t,e,l);case 31:return a=e.pendingProps,l=e.mode,a={mode:a.mode,children:a.children},t===null?(l=Qn(a,l),l.ref=e.ref,e.child=l,l.return=e,e=l):(l=Fe(t.child,a),l.ref=e.ref,e.child=l,l.return=e,e=l),e;case 22:return Lo(t,e,l);case 24:return Fl(e),a=ne(Vt),t===null?(u=mc(),u===null&&(u=_t,n=dc(),u.pooledCache=n,n.refCount++,n!==null&&(u.pooledCacheLanes|=l),u=n),e.memoizedState={parent:a,cache:u},vc(e),gl(e,Vt,u)):((t.lanes&l)!==0&&(gc(t,e),vu(e,null,null,l),yu()),u=t.memoizedState,n=e.memoizedState,u.parent!==a?(u={parent:a,cache:a},e.memoizedState=u,e.lanes===0&&(e.memoizedState=e.updateQueue.baseState=u),gl(e,Vt,a)):(a=n.cache,gl(e,Vt,a),a!==u.cache&&oc(e,[Vt],l,!0))),te(t,e,e.pendingProps.children,l),e.child;case 29:throw e.pendingProps}throw Error(f(156,e.tag))}function nl(t){t.flags|=4}function Jo(t,e){if(e.type!=="stylesheet"||(e.state.loading&4)!==0)t.flags&=-16777217;else if(t.flags|=16777216,!eh(e)){if(e=Ue.current,e!==null&&((st&4194048)===st?Ge!==null:(st&62914560)!==st&&(st&536870912)===0||e!==Ge))throw hu=yc,zs;t.flags|=8192}}function Vn(t,e){e!==null&&(t.flags|=4),t.flags&16384&&(e=t.tag!==22?Ar():536870912,t.lanes|=e,Ha|=e)}function Ru(t,e){if(!mt)switch(t.tailMode){case"hidden":e=t.tail;for(var l=null;e!==null;)e.alternate!==null&&(l=e),e=e.sibling;l===null?t.tail=null:l.sibling=null;break;case"collapsed":l=t.tail;for(var a=null;l!==null;)l.alternate!==null&&(a=l),l=l.sibling;a===null?e||t.tail===null?t.tail=null:t.tail.sibling=null:a.sibling=null}}function Ut(t){var e=t.alternate!==null&&t.alternate.child===t.child,l=0,a=0;if(e)for(var u=t.child;u!==null;)l|=u.lanes|u.childLanes,a|=u.subtreeFlags&65011712,a|=u.flags&65011712,u.return=t,u=u.sibling;else for(u=t.child;u!==null;)l|=u.lanes|u.childLanes,a|=u.subtreeFlags,a|=u.flags,u.return=t,u=u.sibling;return t.subtreeFlags|=a,t.childLanes=l,e}function M0(t,e,l){var a=e.pendingProps;switch(cc(e),e.tag){case 31:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Ut(e),null;case 1:return Ut(e),null;case 3:return l=e.stateNode,a=null,t!==null&&(a=t.memoizedState.cache),e.memoizedState.cache!==a&&(e.flags|=2048),el(Vt),Le(),l.pendingContext&&(l.context=l.pendingContext,l.pendingContext=null),(t===null||t.child===null)&&(iu(e)?nl(e):t===null||t.memoizedState.isDehydrated&&(e.flags&256)===0||(e.flags|=1024,As())),Ut(e),null;case 26:return l=e.memoizedState,t===null?(nl(e),l!==null?(Ut(e),Jo(e,l)):(Ut(e),e.flags&=-16777217)):l?l!==t.memoizedState?(nl(e),Ut(e),Jo(e,l)):(Ut(e),e.flags&=-16777217):(t.memoizedProps!==a&&nl(e),Ut(e),e.flags&=-16777217),null;case 27:Yl(e),l=tt.current;var u=e.type;if(t!==null&&e.stateNode!=null)t.memoizedProps!==a&&nl(e);else{if(!a){if(e.stateNode===null)throw Error(f(166));return Ut(e),null}t=k.current,iu(e)?Ts(e):(t=Jd(u,a,l),e.stateNode=t,nl(e))}return Ut(e),null;case 5:if(Yl(e),l=e.type,t!==null&&e.stateNode!=null)t.memoizedProps!==a&&nl(e);else{if(!a){if(e.stateNode===null)throw Error(f(166));return Ut(e),null}if(t=k.current,iu(e))Ts(e);else{switch(u=ai(tt.current),t){case 1:t=u.createElementNS("http://www.w3.org/2000/svg",l);break;case 2:t=u.createElementNS("http://www.w3.org/1998/Math/MathML",l);break;default:switch(l){case"svg":t=u.createElementNS("http://www.w3.org/2000/svg",l);break;case"math":t=u.createElementNS("http://www.w3.org/1998/Math/MathML",l);break;case"script":t=u.createElement("div"),t.innerHTML=" + + + +
+ + diff --git a/tools/tree/dist/logo.svg b/tools/tree/dist/logo.svg new file mode 100644 index 0000000000..2c2d92a09a --- /dev/null +++ b/tools/tree/dist/logo.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/tools/tree/eslint.config.js b/tools/tree/eslint.config.js new file mode 100644 index 0000000000..092408a9f0 --- /dev/null +++ b/tools/tree/eslint.config.js @@ -0,0 +1,28 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' + +export default tseslint.config( + { ignores: ['dist'] }, + { + extends: [js.configs.recommended, ...tseslint.configs.recommended], + files: ['**/*.{ts,tsx}'], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + plugins: { + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...reactHooks.configs.recommended.rules, + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, + }, +) diff --git a/tools/tree/index.html b/tools/tree/index.html new file mode 100644 index 0000000000..6114d67225 --- /dev/null +++ b/tools/tree/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React + TS + + +
+ + + diff --git a/tools/tree/package.json b/tools/tree/package.json new file mode 100644 index 0000000000..f0caddf865 --- /dev/null +++ b/tools/tree/package.json @@ -0,0 +1,34 @@ +{ + "name": "tree", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@tailwindcss/vite": "^4.1.6", + "clsx": "^2.1.1", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-router-dom": "^7.6.0", + "swr": "^2.3.3", + "tailwindcss": "^4.1.6" + }, + "devDependencies": { + "@eslint/js": "^9.25.0", + "@types/react": "^19.1.2", + "@types/react-dom": "^19.1.2", + "@vitejs/plugin-react-swc": "^3.9.0", + "eslint": "^9.25.0", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.19", + "globals": "^16.0.0", + "typescript": "~5.8.3", + "typescript-eslint": "^8.30.1", + "vite": "^6.3.5" + } +} diff --git a/tools/tree/pnpm-lock.yaml b/tools/tree/pnpm-lock.yaml new file mode 100644 index 0000000000..560215885e --- /dev/null +++ b/tools/tree/pnpm-lock.yaml @@ -0,0 +1,2913 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@tailwindcss/vite': + specifier: ^4.1.6 + version: 4.1.6(vite@6.3.5(jiti@2.4.2)(lightningcss@1.29.2)) + clsx: + specifier: ^2.1.1 + version: 2.1.1 + react: + specifier: ^19.1.0 + version: 19.1.0 + react-dom: + specifier: ^19.1.0 + version: 19.1.0(react@19.1.0) + react-router-dom: + specifier: ^7.6.0 + version: 7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + swr: + specifier: ^2.3.3 + version: 2.3.3(react@19.1.0) + tailwindcss: + specifier: ^4.1.6 + version: 4.1.6 + devDependencies: + '@eslint/js': + specifier: ^9.25.0 + version: 9.26.0 + '@types/react': + specifier: ^19.1.2 + version: 19.1.4 + '@types/react-dom': + specifier: ^19.1.2 + version: 19.1.5(@types/react@19.1.4) + '@vitejs/plugin-react-swc': + specifier: ^3.9.0 + version: 3.9.0(vite@6.3.5(jiti@2.4.2)(lightningcss@1.29.2)) + eslint: + specifier: ^9.25.0 + version: 9.26.0(jiti@2.4.2) + eslint-plugin-react-hooks: + specifier: ^5.2.0 + version: 5.2.0(eslint@9.26.0(jiti@2.4.2)) + eslint-plugin-react-refresh: + specifier: ^0.4.19 + version: 0.4.20(eslint@9.26.0(jiti@2.4.2)) + globals: + specifier: ^16.0.0 + version: 16.1.0 + typescript: + specifier: ~5.8.3 + version: 5.8.3 + typescript-eslint: + specifier: ^8.30.1 + version: 8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) + vite: + specifier: ^6.3.5 + version: 6.3.5(jiti@2.4.2)(lightningcss@1.29.2) + +packages: + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@esbuild/aix-ppc64@0.25.4': + resolution: {integrity: sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.4': + resolution: {integrity: sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.4': + resolution: {integrity: sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.4': + resolution: {integrity: sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.4': + resolution: {integrity: sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.4': + resolution: {integrity: sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.4': + resolution: {integrity: sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.4': + resolution: {integrity: sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.4': + resolution: {integrity: sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.4': + resolution: {integrity: sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.4': + resolution: {integrity: sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.4': + resolution: {integrity: sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.4': + resolution: {integrity: sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.4': + resolution: {integrity: sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.4': + resolution: {integrity: sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.4': + resolution: {integrity: sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.4': + resolution: {integrity: sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.4': + resolution: {integrity: sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.4': + resolution: {integrity: sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.4': + resolution: {integrity: sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.4': + resolution: {integrity: sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.25.4': + resolution: {integrity: sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.4': + resolution: {integrity: sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.4': + resolution: {integrity: sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.4': + resolution: {integrity: sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.7.0': + resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.20.0': + resolution: {integrity: sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.2.2': + resolution: {integrity: sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.13.0': + resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.26.0': + resolution: {integrity: sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.2.8': + resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@isaacs/fs-minipass@4.0.1': + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} + engines: {node: '>=18.0.0'} + + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@modelcontextprotocol/sdk@1.11.2': + resolution: {integrity: sha512-H9vwztj5OAqHg9GockCQC06k1natgcxWQSRpQcPJf6i5+MWBzfKkRtxGbjQf0X2ihii0ffLZCRGbYV2f2bjNCQ==} + engines: {node: '>=18'} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@rollup/rollup-android-arm-eabi@4.40.2': + resolution: {integrity: sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.40.2': + resolution: {integrity: sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.40.2': + resolution: {integrity: sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.40.2': + resolution: {integrity: sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.40.2': + resolution: {integrity: sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.40.2': + resolution: {integrity: sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.40.2': + resolution: {integrity: sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.40.2': + resolution: {integrity: sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.40.2': + resolution: {integrity: sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.40.2': + resolution: {integrity: sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.40.2': + resolution: {integrity: sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.40.2': + resolution: {integrity: sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.40.2': + resolution: {integrity: sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.40.2': + resolution: {integrity: sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.40.2': + resolution: {integrity: sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.40.2': + resolution: {integrity: sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.40.2': + resolution: {integrity: sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.40.2': + resolution: {integrity: sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.40.2': + resolution: {integrity: sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.40.2': + resolution: {integrity: sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==} + cpu: [x64] + os: [win32] + + '@swc/core-darwin-arm64@1.11.24': + resolution: {integrity: sha512-dhtVj0PC1APOF4fl5qT2neGjRLgHAAYfiVP8poJelhzhB/318bO+QCFWAiimcDoyMgpCXOhTp757gnoJJrheWA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + + '@swc/core-darwin-x64@1.11.24': + resolution: {integrity: sha512-H/3cPs8uxcj2Fe3SoLlofN5JG6Ny5bl8DuZ6Yc2wr7gQFBmyBkbZEz+sPVgsID7IXuz7vTP95kMm1VL74SO5AQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + + '@swc/core-linux-arm-gnueabihf@1.11.24': + resolution: {integrity: sha512-PHJgWEpCsLo/NGj+A2lXZ2mgGjsr96ULNW3+T3Bj2KTc8XtMUkE8tmY2Da20ItZOvPNC/69KroU7edyo1Flfbw==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + + '@swc/core-linux-arm64-gnu@1.11.24': + resolution: {integrity: sha512-C2FJb08+n5SD4CYWCTZx1uR88BN41ZieoHvI8A55hfVf2woT8+6ZiBzt74qW2g+ntZ535Jts5VwXAKdu41HpBg==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + + '@swc/core-linux-arm64-musl@1.11.24': + resolution: {integrity: sha512-ypXLIdszRo0re7PNNaXN0+2lD454G8l9LPK/rbfRXnhLWDBPURxzKlLlU/YGd2zP98wPcVooMmegRSNOKfvErw==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + + '@swc/core-linux-x64-gnu@1.11.24': + resolution: {integrity: sha512-IM7d+STVZD48zxcgo69L0yYptfhaaE9cMZ+9OoMxirNafhKKXwoZuufol1+alEFKc+Wbwp+aUPe/DeWC/Lh3dg==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + + '@swc/core-linux-x64-musl@1.11.24': + resolution: {integrity: sha512-DZByJaMVzSfjQKKQn3cqSeqwy6lpMaQDQQ4HPlch9FWtDx/dLcpdIhxssqZXcR2rhaQVIaRQsCqwV6orSDGAGw==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + + '@swc/core-win32-arm64-msvc@1.11.24': + resolution: {integrity: sha512-Q64Ytn23y9aVDKN5iryFi8mRgyHw3/kyjTjT4qFCa8AEb5sGUuSj//AUZ6c0J7hQKMHlg9do5Etvoe61V98/JQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + + '@swc/core-win32-ia32-msvc@1.11.24': + resolution: {integrity: sha512-9pKLIisE/Hh2vJhGIPvSoTK4uBSPxNVyXHmOrtdDot4E1FUUI74Vi8tFdlwNbaj8/vusVnb8xPXsxF1uB0VgiQ==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + + '@swc/core-win32-x64-msvc@1.11.24': + resolution: {integrity: sha512-sybnXtOsdB+XvzVFlBVGgRHLqp3yRpHK7CrmpuDKszhj/QhmsaZzY/GHSeALlMtLup13M0gqbcQvsTNlAHTg3w==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + + '@swc/core@1.11.24': + resolution: {integrity: sha512-MaQEIpfcEMzx3VWWopbofKJvaraqmL6HbLlw2bFZ7qYqYw3rkhM0cQVEgyzbHtTWwCwPMFZSC2DUbhlZgrMfLg==} + engines: {node: '>=10'} + peerDependencies: + '@swc/helpers': '>=0.5.17' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + '@swc/types@0.1.21': + resolution: {integrity: sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ==} + + '@tailwindcss/node@4.1.6': + resolution: {integrity: sha512-ed6zQbgmKsjsVvodAS1q1Ld2BolEuxJOSyyNc+vhkjdmfNUDCmQnlXBfQkHrlzNmslxHsQU/bFmzcEbv4xXsLg==} + + '@tailwindcss/oxide-android-arm64@4.1.6': + resolution: {integrity: sha512-VHwwPiwXtdIvOvqT/0/FLH/pizTVu78FOnI9jQo64kSAikFSZT7K4pjyzoDpSMaveJTGyAKvDjuhxJxKfmvjiQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.1.6': + resolution: {integrity: sha512-weINOCcqv1HVBIGptNrk7c6lWgSFFiQMcCpKM4tnVi5x8OY2v1FrV76jwLukfT6pL1hyajc06tyVmZFYXoxvhQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.1.6': + resolution: {integrity: sha512-3FzekhHG0ww1zQjQ1lPoq0wPrAIVXAbUkWdWM8u5BnYFZgb9ja5ejBqyTgjpo5mfy0hFOoMnMuVDI+7CXhXZaQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.1.6': + resolution: {integrity: sha512-4m5F5lpkBZhVQJq53oe5XgJ+aFYWdrgkMwViHjRsES3KEu2m1udR21B1I77RUqie0ZYNscFzY1v9aDssMBZ/1w==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.6': + resolution: {integrity: sha512-qU0rHnA9P/ZoaDKouU1oGPxPWzDKtIfX7eOGi5jOWJKdxieUJdVV+CxWZOpDWlYTd4N3sFQvcnVLJWJ1cLP5TA==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.6': + resolution: {integrity: sha512-jXy3TSTrbfgyd3UxPQeXC3wm8DAgmigzar99Km9Sf6L2OFfn/k+u3VqmpgHQw5QNfCpPe43em6Q7V76Wx7ogIQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.1.6': + resolution: {integrity: sha512-8kjivE5xW0qAQ9HX9reVFmZj3t+VmljDLVRJpVBEoTR+3bKMnvC7iLcoSGNIUJGOZy1mLVq7x/gerVg0T+IsYw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.1.6': + resolution: {integrity: sha512-A4spQhwnWVpjWDLXnOW9PSinO2PTKJQNRmL/aIl2U/O+RARls8doDfs6R41+DAXK0ccacvRyDpR46aVQJJCoCg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.1.6': + resolution: {integrity: sha512-YRee+6ZqdzgiQAHVSLfl3RYmqeeaWVCk796MhXhLQu2kJu2COHBkqlqsqKYx3p8Hmk5pGCQd2jTAoMWWFeyG2A==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.1.6': + resolution: {integrity: sha512-qAp4ooTYrBQ5pk5jgg54/U1rCJ/9FLYOkkQ/nTE+bVMseMfB6O7J8zb19YTpWuu4UdfRf5zzOrNKfl6T64MNrQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.6': + resolution: {integrity: sha512-nqpDWk0Xr8ELO/nfRUDjk1pc9wDJ3ObeDdNMHLaymc4PJBWj11gdPCWZFKSK2AVKjJQC7J2EfmSmf47GN7OuLg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.1.6': + resolution: {integrity: sha512-5k9xF33xkfKpo9wCvYcegQ21VwIBU1/qEbYlVukfEIyQbEA47uK8AAwS7NVjNE3vHzcmxMYwd0l6L4pPjjm1rQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.1.6': + resolution: {integrity: sha512-0bpEBQiGx+227fW4G0fLQ8vuvyy5rsB1YIYNapTq3aRsJ9taF3f5cCaovDjN5pUGKKzcpMrZst/mhNaKAPOHOA==} + engines: {node: '>= 10'} + + '@tailwindcss/vite@4.1.6': + resolution: {integrity: sha512-zjtqjDeY1w3g2beYQtrMAf51n5G7o+UwmyOjtsDMP7t6XyoRMOidcoKP32ps7AkNOHIXEOK0bhIC05dj8oJp4w==} + peerDependencies: + vite: ^5.2.0 || ^6 + + '@types/estree@1.0.7': + resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/react-dom@19.1.5': + resolution: {integrity: sha512-CMCjrWucUBZvohgZxkjd6S9h0nZxXjzus6yDfUb+xLxYM7VvjKNH1tQrE9GWLql1XoOP4/Ds3bwFqShHUYraGg==} + peerDependencies: + '@types/react': ^19.0.0 + + '@types/react@19.1.4': + resolution: {integrity: sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g==} + + '@typescript-eslint/eslint-plugin@8.32.1': + resolution: {integrity: sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + 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' + + '@typescript-eslint/parser@8.32.1': + resolution: {integrity: sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/scope-manager@8.32.1': + resolution: {integrity: sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/type-utils@8.32.1': + resolution: {integrity: sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/types@8.32.1': + resolution: {integrity: sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.32.1': + resolution: {integrity: sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/utils@8.32.1': + resolution: {integrity: sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/visitor-keys@8.32.1': + resolution: {integrity: sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@vitejs/plugin-react-swc@3.9.0': + resolution: {integrity: sha512-jYFUSXhwMCYsh/aQTgSGLIN3Foz5wMbH9ahb0Zva//UzwZYbMiZd7oT3AU9jHT9DLswYDswsRwPU9jVF3yA48Q==} + peerDependencies: + vite: ^4 || ^5 || ^6 + + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.14.1: + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + body-parser@2.2.0: + resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==} + engines: {node: '>=18'} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chownr@3.0.0: + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} + engines: {node: '>=18'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + content-disposition@1.0.0: + resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + cookie-signature@1.2.2: + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + cookie@1.0.2: + resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} + engines: {node: '>=18'} + + cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + detect-libc@2.0.4: + resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} + engines: {node: '>=8'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + enhanced-resolve@5.18.1: + resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} + engines: {node: '>=10.13.0'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + esbuild@0.25.4: + resolution: {integrity: sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==} + engines: {node: '>=18'} + hasBin: true + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-plugin-react-hooks@5.2.0: + resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + + eslint-plugin-react-refresh@0.4.20: + resolution: {integrity: sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==} + peerDependencies: + eslint: '>=8.40' + + eslint-scope@8.3.0: + resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.26.0: + resolution: {integrity: sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + eventsource-parser@3.0.2: + resolution: {integrity: sha512-6RxOBZ/cYgd8usLwsEl+EC09Au/9BcmCKYF2/xbml6DNczf7nv0MQb+7BA2F+li6//I+28VNlQR37XfQtcAJuA==} + engines: {node: '>=18.0.0'} + + eventsource@3.0.7: + resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} + engines: {node: '>=18.0.0'} + + express-rate-limit@7.5.0: + resolution: {integrity: sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==} + engines: {node: '>= 16'} + peerDependencies: + express: ^4.11 || 5 || ^5.0.0-beta.1 + + express@5.1.0: + resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} + engines: {node: '>= 18'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + + fdir@6.4.4: + resolution: {integrity: sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + finalhandler@2.1.0: + resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==} + engines: {node: '>= 0.8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@16.1.0: + resolution: {integrity: sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==} + engines: {node: '>=18'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.4: + resolution: {integrity: sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lightningcss-darwin-arm64@1.29.2: + resolution: {integrity: sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.29.2: + resolution: {integrity: sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.29.2: + resolution: {integrity: sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.29.2: + resolution: {integrity: sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.29.2: + resolution: {integrity: sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.29.2: + resolution: {integrity: sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.29.2: + resolution: {integrity: sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.29.2: + resolution: {integrity: sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.29.2: + resolution: {integrity: sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.29.2: + resolution: {integrity: sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.29.2: + resolution: {integrity: sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==} + engines: {node: '>= 12.0.0'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + media-typer@1.1.0: + resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + engines: {node: '>= 0.8'} + + merge-descriptors@2.0.0: + resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} + engines: {node: '>=18'} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@3.0.1: + resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} + engines: {node: '>= 0.6'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + minizlib@3.0.2: + resolution: {integrity: sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==} + engines: {node: '>= 18'} + + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-to-regexp@8.2.0: + resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} + engines: {node: '>=16'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + pkce-challenge@5.0.0: + resolution: {integrity: sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==} + engines: {node: '>=16.20.0'} + + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@3.0.0: + resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==} + engines: {node: '>= 0.8'} + + react-dom@19.1.0: + resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==} + peerDependencies: + react: ^19.1.0 + + react-router-dom@7.6.0: + resolution: {integrity: sha512-DYgm6RDEuKdopSyGOWZGtDfSm7Aofb8CCzgkliTjtu/eDuB0gcsv6qdFhhi8HdtmA+KHkt5MfZ5K2PdzjugYsA==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + + react-router@7.6.0: + resolution: {integrity: sha512-GGufuHIVCJDbnIAXP3P9Sxzq3UUsddG3rrI3ut1q6m0FI6vxVBF3JoPQ38+W/blslLH4a5Yutp8drkEpXoddGQ==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + peerDependenciesMeta: + react-dom: + optional: true + + react@19.1.0: + resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rollup@4.40.2: + resolution: {integrity: sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + router@2.2.0: + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + scheduler@0.26.0: + resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + + send@1.2.0: + resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} + engines: {node: '>= 18'} + + serve-static@2.2.0: + resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==} + engines: {node: '>= 18'} + + set-cookie-parser@2.7.1: + resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + swr@2.3.3: + resolution: {integrity: sha512-dshNvs3ExOqtZ6kJBaAsabhPdHyeY4P2cKwRCniDVifBMoG/SVI7tfLWqPXriVspf2Rg4tPzXJTnwaihIeFw2A==} + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + tailwindcss@4.1.6: + resolution: {integrity: sha512-j0cGLTreM6u4OWzBeLBpycK0WIh8w7kSwcUsQZoGLHZ7xDTdM69lN64AgoIEEwFi0tnhs4wSykUa5YWxAzgFYg==} + + tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + + tar@7.4.3: + resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} + engines: {node: '>=18'} + + tinyglobby@0.2.13: + resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==} + engines: {node: '>=12.0.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-is@2.0.1: + resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} + engines: {node: '>= 0.6'} + + typescript-eslint@8.32.1: + resolution: {integrity: sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + engines: {node: '>=14.17'} + hasBin: true + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + use-sync-external-store@1.5.0: + resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vite@6.3.5: + resolution: {integrity: sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + yallist@5.0.0: + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} + engines: {node: '>=18'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zod-to-json-schema@3.24.5: + resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==} + peerDependencies: + zod: ^3.24.1 + + zod@3.24.4: + resolution: {integrity: sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==} + +snapshots: + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + '@esbuild/aix-ppc64@0.25.4': + optional: true + + '@esbuild/android-arm64@0.25.4': + optional: true + + '@esbuild/android-arm@0.25.4': + optional: true + + '@esbuild/android-x64@0.25.4': + optional: true + + '@esbuild/darwin-arm64@0.25.4': + optional: true + + '@esbuild/darwin-x64@0.25.4': + optional: true + + '@esbuild/freebsd-arm64@0.25.4': + optional: true + + '@esbuild/freebsd-x64@0.25.4': + optional: true + + '@esbuild/linux-arm64@0.25.4': + optional: true + + '@esbuild/linux-arm@0.25.4': + optional: true + + '@esbuild/linux-ia32@0.25.4': + optional: true + + '@esbuild/linux-loong64@0.25.4': + optional: true + + '@esbuild/linux-mips64el@0.25.4': + optional: true + + '@esbuild/linux-ppc64@0.25.4': + optional: true + + '@esbuild/linux-riscv64@0.25.4': + optional: true + + '@esbuild/linux-s390x@0.25.4': + optional: true + + '@esbuild/linux-x64@0.25.4': + optional: true + + '@esbuild/netbsd-arm64@0.25.4': + optional: true + + '@esbuild/netbsd-x64@0.25.4': + optional: true + + '@esbuild/openbsd-arm64@0.25.4': + optional: true + + '@esbuild/openbsd-x64@0.25.4': + optional: true + + '@esbuild/sunos-x64@0.25.4': + optional: true + + '@esbuild/win32-arm64@0.25.4': + optional: true + + '@esbuild/win32-ia32@0.25.4': + optional: true + + '@esbuild/win32-x64@0.25.4': + optional: true + + '@eslint-community/eslint-utils@4.7.0(eslint@9.26.0(jiti@2.4.2))': + dependencies: + eslint: 9.26.0(jiti@2.4.2) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.20.0': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.1 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.2.2': {} + + '@eslint/core@0.13.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.1 + espree: 10.3.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.26.0': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.2.8': + dependencies: + '@eslint/core': 0.13.0 + levn: 0.4.1 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@isaacs/fs-minipass@4.0.1': + dependencies: + minipass: 7.1.2 + + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@modelcontextprotocol/sdk@1.11.2': + dependencies: + content-type: 1.0.5 + cors: 2.8.5 + cross-spawn: 7.0.6 + eventsource: 3.0.7 + express: 5.1.0 + express-rate-limit: 7.5.0(express@5.1.0) + pkce-challenge: 5.0.0 + raw-body: 3.0.0 + zod: 3.24.4 + zod-to-json-schema: 3.24.5(zod@3.24.4) + transitivePeerDependencies: + - supports-color + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + + '@rollup/rollup-android-arm-eabi@4.40.2': + optional: true + + '@rollup/rollup-android-arm64@4.40.2': + optional: true + + '@rollup/rollup-darwin-arm64@4.40.2': + optional: true + + '@rollup/rollup-darwin-x64@4.40.2': + optional: true + + '@rollup/rollup-freebsd-arm64@4.40.2': + optional: true + + '@rollup/rollup-freebsd-x64@4.40.2': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.40.2': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.40.2': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.40.2': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.40.2': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.40.2': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.40.2': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.40.2': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.40.2': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.40.2': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.40.2': + optional: true + + '@rollup/rollup-linux-x64-musl@4.40.2': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.40.2': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.40.2': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.40.2': + optional: true + + '@swc/core-darwin-arm64@1.11.24': + optional: true + + '@swc/core-darwin-x64@1.11.24': + optional: true + + '@swc/core-linux-arm-gnueabihf@1.11.24': + optional: true + + '@swc/core-linux-arm64-gnu@1.11.24': + optional: true + + '@swc/core-linux-arm64-musl@1.11.24': + optional: true + + '@swc/core-linux-x64-gnu@1.11.24': + optional: true + + '@swc/core-linux-x64-musl@1.11.24': + optional: true + + '@swc/core-win32-arm64-msvc@1.11.24': + optional: true + + '@swc/core-win32-ia32-msvc@1.11.24': + optional: true + + '@swc/core-win32-x64-msvc@1.11.24': + optional: true + + '@swc/core@1.11.24': + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.21 + optionalDependencies: + '@swc/core-darwin-arm64': 1.11.24 + '@swc/core-darwin-x64': 1.11.24 + '@swc/core-linux-arm-gnueabihf': 1.11.24 + '@swc/core-linux-arm64-gnu': 1.11.24 + '@swc/core-linux-arm64-musl': 1.11.24 + '@swc/core-linux-x64-gnu': 1.11.24 + '@swc/core-linux-x64-musl': 1.11.24 + '@swc/core-win32-arm64-msvc': 1.11.24 + '@swc/core-win32-ia32-msvc': 1.11.24 + '@swc/core-win32-x64-msvc': 1.11.24 + + '@swc/counter@0.1.3': {} + + '@swc/types@0.1.21': + dependencies: + '@swc/counter': 0.1.3 + + '@tailwindcss/node@4.1.6': + dependencies: + '@ampproject/remapping': 2.3.0 + enhanced-resolve: 5.18.1 + jiti: 2.4.2 + lightningcss: 1.29.2 + magic-string: 0.30.17 + source-map-js: 1.2.1 + tailwindcss: 4.1.6 + + '@tailwindcss/oxide-android-arm64@4.1.6': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.1.6': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.1.6': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.1.6': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.6': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.6': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.1.6': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.1.6': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.1.6': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.1.6': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.6': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.1.6': + optional: true + + '@tailwindcss/oxide@4.1.6': + dependencies: + detect-libc: 2.0.4 + tar: 7.4.3 + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.1.6 + '@tailwindcss/oxide-darwin-arm64': 4.1.6 + '@tailwindcss/oxide-darwin-x64': 4.1.6 + '@tailwindcss/oxide-freebsd-x64': 4.1.6 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.6 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.6 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.6 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.6 + '@tailwindcss/oxide-linux-x64-musl': 4.1.6 + '@tailwindcss/oxide-wasm32-wasi': 4.1.6 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.6 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.6 + + '@tailwindcss/vite@4.1.6(vite@6.3.5(jiti@2.4.2)(lightningcss@1.29.2))': + dependencies: + '@tailwindcss/node': 4.1.6 + '@tailwindcss/oxide': 4.1.6 + tailwindcss: 4.1.6 + vite: 6.3.5(jiti@2.4.2)(lightningcss@1.29.2) + + '@types/estree@1.0.7': {} + + '@types/json-schema@7.0.15': {} + + '@types/react-dom@19.1.5(@types/react@19.1.4)': + dependencies: + '@types/react': 19.1.4 + + '@types/react@19.1.4': + dependencies: + csstype: 3.1.3 + + '@typescript-eslint/eslint-plugin@8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.32.1 + '@typescript-eslint/type-utils': 8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/utils': 8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.32.1 + eslint: 9.26.0(jiti@2.4.2) + graphemer: 1.4.0 + ignore: 7.0.4 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.32.1 + '@typescript-eslint/types': 8.32.1 + '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.32.1 + debug: 4.4.1 + eslint: 9.26.0(jiti@2.4.2) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.32.1': + dependencies: + '@typescript-eslint/types': 8.32.1 + '@typescript-eslint/visitor-keys': 8.32.1 + + '@typescript-eslint/type-utils@8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)': + dependencies: + '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3) + '@typescript-eslint/utils': 8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) + debug: 4.4.1 + eslint: 9.26.0(jiti@2.4.2) + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.32.1': {} + + '@typescript-eslint/typescript-estree@8.32.1(typescript@5.8.3)': + dependencies: + '@typescript-eslint/types': 8.32.1 + '@typescript-eslint/visitor-keys': 8.32.1 + debug: 4.4.1 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)': + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.32.1 + '@typescript-eslint/types': 8.32.1 + '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3) + eslint: 9.26.0(jiti@2.4.2) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.32.1': + dependencies: + '@typescript-eslint/types': 8.32.1 + eslint-visitor-keys: 4.2.0 + + '@vitejs/plugin-react-swc@3.9.0(vite@6.3.5(jiti@2.4.2)(lightningcss@1.29.2))': + dependencies: + '@swc/core': 1.11.24 + vite: 6.3.5(jiti@2.4.2)(lightningcss@1.29.2) + transitivePeerDependencies: + - '@swc/helpers' + + accepts@2.0.0: + dependencies: + mime-types: 3.0.1 + negotiator: 1.0.0 + + acorn-jsx@5.3.2(acorn@8.14.1): + dependencies: + acorn: 8.14.1 + + acorn@8.14.1: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + argparse@2.0.1: {} + + balanced-match@1.0.2: {} + + body-parser@2.2.0: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 4.4.1 + http-errors: 2.0.0 + iconv-lite: 0.6.3 + on-finished: 2.4.1 + qs: 6.14.0 + raw-body: 3.0.0 + type-is: 2.0.1 + transitivePeerDependencies: + - supports-color + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + bytes@3.1.2: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chownr@3.0.0: {} + + clsx@2.1.1: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + concat-map@0.0.1: {} + + content-disposition@1.0.0: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + cookie-signature@1.2.2: {} + + cookie@0.7.2: {} + + cookie@1.0.2: {} + + cors@2.8.5: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + csstype@3.1.3: {} + + debug@4.4.1: + dependencies: + ms: 2.1.3 + + deep-is@0.1.4: {} + + depd@2.0.0: {} + + dequal@2.0.3: {} + + detect-libc@2.0.4: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + ee-first@1.1.1: {} + + encodeurl@2.0.0: {} + + enhanced-resolve@5.18.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + 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 + + escape-html@1.0.3: {} + + escape-string-regexp@4.0.0: {} + + eslint-plugin-react-hooks@5.2.0(eslint@9.26.0(jiti@2.4.2)): + dependencies: + eslint: 9.26.0(jiti@2.4.2) + + eslint-plugin-react-refresh@0.4.20(eslint@9.26.0(jiti@2.4.2)): + dependencies: + eslint: 9.26.0(jiti@2.4.2) + + eslint-scope@8.3.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.0: {} + + eslint@9.26.0(jiti@2.4.2): + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.20.0 + '@eslint/config-helpers': 0.2.2 + '@eslint/core': 0.13.0 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.26.0 + '@eslint/plugin-kit': 0.2.8 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@modelcontextprotocol/sdk': 1.11.2 + '@types/estree': 1.0.7 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.1 + escape-string-regexp: 4.0.0 + eslint-scope: 8.3.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + 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.4 + zod: 3.24.4 + optionalDependencies: + jiti: 2.4.2 + transitivePeerDependencies: + - supports-color + + espree@10.3.0: + dependencies: + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) + eslint-visitor-keys: 4.2.0 + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + etag@1.8.1: {} + + eventsource-parser@3.0.2: {} + + eventsource@3.0.7: + dependencies: + eventsource-parser: 3.0.2 + + express-rate-limit@7.5.0(express@5.1.0): + dependencies: + express: 5.1.0 + + express@5.1.0: + dependencies: + accepts: 2.0.0 + body-parser: 2.2.0 + content-disposition: 1.0.0 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.2.2 + debug: 4.4.1 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 2.1.0 + fresh: 2.0.0 + http-errors: 2.0.0 + merge-descriptors: 2.0.0 + mime-types: 3.0.1 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: 1.3.3 + proxy-addr: 2.0.7 + qs: 6.14.0 + range-parser: 1.2.1 + router: 2.2.0 + send: 1.2.0 + serve-static: 2.2.0 + statuses: 2.0.1 + type-is: 2.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + + fdir@6.4.4(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@2.1.0: + dependencies: + debug: 4.4.1 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flatted@3.3.3: {} + + forwarded@0.2.0: {} + + fresh@2.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + globals@14.0.0: {} + + globals@16.1.0: {} + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + ignore@5.3.2: {} + + ignore@7.0.4: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + inherits@2.0.4: {} + + ipaddr.js@1.9.1: {} + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + is-promise@4.0.0: {} + + isexe@2.0.0: {} + + jiti@2.4.2: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lightningcss-darwin-arm64@1.29.2: + optional: true + + lightningcss-darwin-x64@1.29.2: + optional: true + + lightningcss-freebsd-x64@1.29.2: + optional: true + + lightningcss-linux-arm-gnueabihf@1.29.2: + optional: true + + lightningcss-linux-arm64-gnu@1.29.2: + optional: true + + lightningcss-linux-arm64-musl@1.29.2: + optional: true + + lightningcss-linux-x64-gnu@1.29.2: + optional: true + + lightningcss-linux-x64-musl@1.29.2: + optional: true + + lightningcss-win32-arm64-msvc@1.29.2: + optional: true + + lightningcss-win32-x64-msvc@1.29.2: + optional: true + + lightningcss@1.29.2: + dependencies: + detect-libc: 2.0.4 + optionalDependencies: + lightningcss-darwin-arm64: 1.29.2 + lightningcss-darwin-x64: 1.29.2 + lightningcss-freebsd-x64: 1.29.2 + lightningcss-linux-arm-gnueabihf: 1.29.2 + lightningcss-linux-arm64-gnu: 1.29.2 + lightningcss-linux-arm64-musl: 1.29.2 + lightningcss-linux-x64-gnu: 1.29.2 + lightningcss-linux-x64-musl: 1.29.2 + lightningcss-win32-arm64-msvc: 1.29.2 + lightningcss-win32-x64-msvc: 1.29.2 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.merge@4.6.2: {} + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + math-intrinsics@1.1.0: {} + + media-typer@1.1.0: {} + + merge-descriptors@2.0.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.54.0: {} + + mime-types@3.0.1: + dependencies: + mime-db: 1.54.0 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minipass@7.1.2: {} + + minizlib@3.0.2: + dependencies: + minipass: 7.1.2 + + mkdirp@3.0.1: {} + + ms@2.1.3: {} + + nanoid@3.3.11: {} + + natural-compare@1.4.0: {} + + negotiator@1.0.0: {} + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parseurl@1.3.3: {} + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-to-regexp@8.2.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.2: {} + + pkce-challenge@5.0.0: {} + + postcss@8.5.3: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + punycode@2.3.1: {} + + qs@6.14.0: + dependencies: + side-channel: 1.1.0 + + queue-microtask@1.2.3: {} + + range-parser@1.2.1: {} + + raw-body@3.0.0: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.6.3 + unpipe: 1.0.0 + + react-dom@19.1.0(react@19.1.0): + dependencies: + react: 19.1.0 + scheduler: 0.26.0 + + react-router-dom@7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + dependencies: + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + react-router: 7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + + react-router@7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + dependencies: + cookie: 1.0.2 + react: 19.1.0 + set-cookie-parser: 2.7.1 + optionalDependencies: + react-dom: 19.1.0(react@19.1.0) + + react@19.1.0: {} + + resolve-from@4.0.0: {} + + reusify@1.1.0: {} + + rollup@4.40.2: + dependencies: + '@types/estree': 1.0.7 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.40.2 + '@rollup/rollup-android-arm64': 4.40.2 + '@rollup/rollup-darwin-arm64': 4.40.2 + '@rollup/rollup-darwin-x64': 4.40.2 + '@rollup/rollup-freebsd-arm64': 4.40.2 + '@rollup/rollup-freebsd-x64': 4.40.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.40.2 + '@rollup/rollup-linux-arm-musleabihf': 4.40.2 + '@rollup/rollup-linux-arm64-gnu': 4.40.2 + '@rollup/rollup-linux-arm64-musl': 4.40.2 + '@rollup/rollup-linux-loongarch64-gnu': 4.40.2 + '@rollup/rollup-linux-powerpc64le-gnu': 4.40.2 + '@rollup/rollup-linux-riscv64-gnu': 4.40.2 + '@rollup/rollup-linux-riscv64-musl': 4.40.2 + '@rollup/rollup-linux-s390x-gnu': 4.40.2 + '@rollup/rollup-linux-x64-gnu': 4.40.2 + '@rollup/rollup-linux-x64-musl': 4.40.2 + '@rollup/rollup-win32-arm64-msvc': 4.40.2 + '@rollup/rollup-win32-ia32-msvc': 4.40.2 + '@rollup/rollup-win32-x64-msvc': 4.40.2 + fsevents: 2.3.3 + + router@2.2.0: + dependencies: + debug: 4.4.1 + depd: 2.0.0 + is-promise: 4.0.0 + parseurl: 1.3.3 + path-to-regexp: 8.2.0 + transitivePeerDependencies: + - supports-color + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-buffer@5.2.1: {} + + safer-buffer@2.1.2: {} + + scheduler@0.26.0: {} + + semver@7.7.2: {} + + send@1.2.0: + dependencies: + debug: 4.4.1 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.0 + mime-types: 3.0.1 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + serve-static@2.2.0: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.0 + transitivePeerDependencies: + - supports-color + + set-cookie-parser@2.7.1: {} + + setprototypeof@1.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + source-map-js@1.2.1: {} + + statuses@2.0.1: {} + + strip-json-comments@3.1.1: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + swr@2.3.3(react@19.1.0): + dependencies: + dequal: 2.0.3 + react: 19.1.0 + use-sync-external-store: 1.5.0(react@19.1.0) + + tailwindcss@4.1.6: {} + + tapable@2.2.1: {} + + tar@7.4.3: + dependencies: + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.2 + minizlib: 3.0.2 + mkdirp: 3.0.1 + yallist: 5.0.0 + + tinyglobby@0.2.13: + dependencies: + fdir: 6.4.4(picomatch@4.0.2) + picomatch: 4.0.2 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toidentifier@1.0.1: {} + + ts-api-utils@2.1.0(typescript@5.8.3): + dependencies: + typescript: 5.8.3 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-is@2.0.1: + dependencies: + content-type: 1.0.5 + media-typer: 1.1.0 + mime-types: 3.0.1 + + typescript-eslint@8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/parser': 8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/utils': 8.32.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) + eslint: 9.26.0(jiti@2.4.2) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + typescript@5.8.3: {} + + unpipe@1.0.0: {} + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + use-sync-external-store@1.5.0(react@19.1.0): + dependencies: + react: 19.1.0 + + vary@1.1.2: {} + + vite@6.3.5(jiti@2.4.2)(lightningcss@1.29.2): + dependencies: + esbuild: 0.25.4 + fdir: 6.4.4(picomatch@4.0.2) + picomatch: 4.0.2 + postcss: 8.5.3 + rollup: 4.40.2 + tinyglobby: 0.2.13 + optionalDependencies: + fsevents: 2.3.3 + jiti: 2.4.2 + lightningcss: 1.29.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + wrappy@1.0.2: {} + + yallist@5.0.0: {} + + yocto-queue@0.1.0: {} + + zod-to-json-schema@3.24.5(zod@3.24.4): + dependencies: + zod: 3.24.4 + + zod@3.24.4: {} diff --git a/tools/tree/public/logo.svg b/tools/tree/public/logo.svg new file mode 120000 index 0000000000..73e4ef3b87 --- /dev/null +++ b/tools/tree/public/logo.svg @@ -0,0 +1 @@ +../../../docs/metatype.dev/static/images/logo.svg \ No newline at end of file diff --git a/tools/tree/src/App.css b/tools/tree/src/App.css new file mode 100644 index 0000000000..c2d88e5a1b --- /dev/null +++ b/tools/tree/src/App.css @@ -0,0 +1,48 @@ +main { + flex: 1; + max-width: 1280px; + display: flex; + flex-direction: column; + align-items: stretch; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} diff --git a/tools/tree/src/App.tsx b/tools/tree/src/App.tsx new file mode 100644 index 0000000000..4ad264a62b --- /dev/null +++ b/tools/tree/src/App.tsx @@ -0,0 +1,166 @@ +// Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0. +// SPDX-License-Identifier: MPL-2.0 + +import "./App.css"; +import useSWR, { SWRConfig } from "swr"; +import { BrowserRouter, Routes, Route, useNavigate, useParams } from "react-router-dom"; +import { Type } from "./components/Type"; + +const fetcher = async (url: string): Promise => { + const response = await fetch(url); + if (!response.ok) { + throw new Error(`Failed to fetch: ${response.status}`); + } + return response.json(); +}; + +function Header() { + const navigate = useNavigate(); + const { typegraph: currentTypegraph } = useParams(); + const { data: typegraphs, error, isLoading } = useSWR('/api/typegraphs'); + + const handleTypegraphChange = (event: React.ChangeEvent) => { + const selectedTypegraph = event.target.value; + if (selectedTypegraph) { + navigate(`/${selectedTypegraph}`); + } + }; + + return ( +
+ + +
+ ); +} + +type Stats = { + stats: { + types: number; + runtimes: number; + materializers: number; + policies: number; + } +} + +function Status() { + const { typegraph } = useParams(); + const { data: typegraphData, error, isLoading } = useSWR( + typegraph ? `/api/typegraphs/${typegraph}` : null + ); + + if (isLoading) { + return ( +
+ Loading... +
+ ); + } + + if (error) { + return ( +
+ Error: {error.message} +
+ ); + } + + if (!typegraphData) { + return ( +
+ No typegraph selected +
+ ); + } + + return ( +
+ {typegraphData && ( + <> +
+ Type count: + {typegraphData.stats.types} +
+
+ Runtimes: + {typegraphData.stats.runtimes} +
+
+ Materializers: + {typegraphData.stats.materializers} +
+
+ Policies: + {typegraphData.stats.policies} +
+ + )} +
+ ); +} + +function TypegraphView() { + return ( + <> +
+
+ +
+ + ); +} + +function AppContent() { + return ( + <> + + +
+
+ Select a typegraph... +
+ + } /> + + } /> + + + ); +} + +function App() { + return ( + + + + + + ); +} + +export default App; diff --git a/tools/tree/src/components/Type.tsx b/tools/tree/src/components/Type.tsx new file mode 100644 index 0000000000..d0d7a78c30 --- /dev/null +++ b/tools/tree/src/components/Type.tsx @@ -0,0 +1,171 @@ +// Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0. +// SPDX-License-Identifier: MPL-2.0 + +import { useParams } from "react-router-dom"; +import useSWR from "swr"; +import { useMemo, useState } from "react"; +import clsx from "clsx"; +import type { TypeNode } from "../../../../src/typegate/src/typegraph/types"; +import type { ReactNode } from "react"; + +interface ExpandIconProps { + variant: "plus" | "minus" | "disk"; +} + +function ExpandIcon({ variant }: ExpandIconProps) { + return ( + + {variant === "disk" ? ( + + ) : variant === "minus" ? ( + + ) : ( + + )} + + ); +} + +interface ExpandButtonProps { + expanded: boolean; + disabled?: boolean; + onClick: () => void; +} + +function ExpandButton({ expanded, disabled = false, onClick }: ExpandButtonProps) { + return ( + + ); +} + +interface TypeHeaderProps { + idx: number; + tag: string; + typeNode: TypeNode; + expandButton: ReactNode; + isHovered: boolean; + onMouseEnter: () => void; + onMouseLeave: () => void; +} + +function TypeHeader({ + idx, + tag, + typeNode, + expandButton, + isHovered, + onMouseEnter, + onMouseLeave +}: TypeHeaderProps) { + return ( +
+
+ {expandButton} + #{idx} + {tag} + {typeNode.type} + {typeNode.title} +
+
+ ); +} + +interface TypeProps { + idx: number; + tag: string; +} + +export function Type({ idx, tag }: TypeProps) { + const { typegraph } = useParams(); + const { data: typeNode, error, isLoading } = useSWR( + typegraph ? `/api/typegraphs/${typegraph}/types/${idx}` : null + ); + + const [expanded, setExpanded] = useState(false); + const [isHovered, setIsHovered] = useState(false); + const edges = useMemo(() => typeNode ? getTypeEdges(typeNode) : [], [typeNode]); + + if (isLoading) { + return ( +
+ Loading type #{idx}... +
+ ); + } + + if (error) { + return ( +
+ Error: {error.message} +
+ ); + } + + if (!typeNode) { + return null; + } + + return ( + <> + setExpanded(!expanded)} + /> + } + isHovered={isHovered} + onMouseEnter={() => setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + /> +
+
+ {expanded && edges.map(([tag, typeIdx]) => ( + + ))} +
+
+ + ); +} + +function getTypeEdges(typeNode: TypeNode): [tag: string, typeIdx: number][] { + switch (typeNode.type) { + case "object": + return Object.entries(typeNode.properties).map(([key, idx]) => [`.${key}`, idx]); + case "list": + return [["[*]", typeNode.items]]; + case "optional": + return [["?", typeNode.item]]; + case "union": + return typeNode.anyOf.map((idx, i) => [`(${i})`, idx]); + case "either": + return typeNode.oneOf.map((idx, i) => [`(${i})`, idx]); + case "function": + return [["in", typeNode.input], ["out", typeNode.output]]; + default: + return []; + } +} diff --git a/tools/tree/src/index.css b/tools/tree/src/index.css new file mode 100644 index 0000000000..b66d26d8aa --- /dev/null +++ b/tools/tree/src/index.css @@ -0,0 +1,47 @@ +@import "tailwindcss"; + +:root { + font-family: system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + min-width: 320px; + min-height: 100vh; +} + +#root { + min-height: 100vh; + display: flex; + flex-direction: column; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } +} diff --git a/tools/tree/src/main.tsx b/tools/tree/src/main.tsx new file mode 100644 index 0000000000..4581bf6f32 --- /dev/null +++ b/tools/tree/src/main.tsx @@ -0,0 +1,13 @@ +// Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0. +// SPDX-License-Identifier: MPL-2.0 + +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import App from './App.tsx' + +createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/tools/tree/src/vite-env.d.ts b/tools/tree/src/vite-env.d.ts new file mode 100644 index 0000000000..bd5db122cb --- /dev/null +++ b/tools/tree/src/vite-env.d.ts @@ -0,0 +1,4 @@ +// Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0. +// SPDX-License-Identifier: MPL-2.0 + +/// diff --git a/tools/tree/tsconfig.app.json b/tools/tree/tsconfig.app.json new file mode 100644 index 0000000000..b464276b26 --- /dev/null +++ b/tools/tree/tsconfig.app.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src"] +} diff --git a/tools/tree/tsconfig.json b/tools/tree/tsconfig.json new file mode 100644 index 0000000000..1ffef600d9 --- /dev/null +++ b/tools/tree/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/tools/tree/tsconfig.node.json b/tools/tree/tsconfig.node.json new file mode 100644 index 0000000000..c6047864da --- /dev/null +++ b/tools/tree/tsconfig.node.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2022", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/tools/tree/vite.config.ts b/tools/tree/vite.config.ts new file mode 100644 index 0000000000..65e01339ec --- /dev/null +++ b/tools/tree/vite.config.ts @@ -0,0 +1,18 @@ +// Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0. +// SPDX-License-Identifier: MPL-2.0 + +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react-swc"; +import tailwindcss from "@tailwindcss/vite"; + +export default defineConfig({ + plugins: [react(), tailwindcss()], + server: { + host: "0.0.0.0", + proxy: { + "/api": { + target: "http://localhost:9000", + }, + }, + }, +}); From 7b50fcf8da8823fcc0d43637b0a15bdc10bb8fb1 Mon Sep 17 00:00:00 2001 From: Natoandro Date: Thu, 22 May 2025 15:30:35 +0300 Subject: [PATCH 2/8] add to tg_core --- Cargo.lock | 3 ++- Cargo.toml | 1 + src/typegraph/core/Cargo.toml | 2 +- src/typegraph/core/src/typegraph.rs | 2 ++ src/typegraph/optimize/Cargo.toml | 2 +- src/typegraph/optimize/src/dedup.rs | 3 +-- src/typegraph/optimize/src/lib.rs | 2 +- src/typegraph/optimize/src/main.rs | 2 +- 8 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1070203d6d..5fa285c9cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12284,7 +12284,7 @@ dependencies = [ ] [[package]] -name = "tg-optimize" +name = "tg_optimize" version = "0.5.1-rc.3" dependencies = [ "color-eyre", @@ -13132,6 +13132,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.8", + "tg_optimize", "tg_schema", "unindent", ] diff --git a/Cargo.toml b/Cargo.toml index b4c21056ff..4df84c06e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ edition = "2021" # internal crates mt_deno = { path = "src/mt_deno/" } tg_schema = { path = "src/typegraph/schema" } +tg_optimize = { path = "src/typegraph/optimize" } typegraph_core = { path = "src/typegraph/core" } substantial = { path = "src/substantial/" } metagen = { path = "src/metagen/" } diff --git a/src/typegraph/core/Cargo.toml b/src/typegraph/core/Cargo.toml index 21e951db91..24f2991cc7 100644 --- a/src/typegraph/core/Cargo.toml +++ b/src/typegraph/core/Cargo.toml @@ -4,8 +4,8 @@ version = "0.5.1-rc.3" edition = "2021" [dependencies] -# common.workspace = true tg_schema.workspace = true +tg_optimize.workspace = true metagen.workspace = true grpc_utils.workspace = true archive_utils.workspace = true diff --git a/src/typegraph/core/src/typegraph.rs b/src/typegraph/core/src/typegraph.rs index 98599b1b6b..bec1d103ee 100644 --- a/src/typegraph/core/src/typegraph.rs +++ b/src/typegraph/core/src/typegraph.rs @@ -241,6 +241,8 @@ pub fn serialize(params: SerializeParams) -> Result<(String, Vec)> } .postprocess(&mut tg)?; + let tg = tg_optimize::optimize(tg.into()); + let artifacts = tg .meta .artifacts diff --git a/src/typegraph/optimize/Cargo.toml b/src/typegraph/optimize/Cargo.toml index ed35db7f4a..6f38169f99 100644 --- a/src/typegraph/optimize/Cargo.toml +++ b/src/typegraph/optimize/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "tg-optimize" +name = "tg_optimize" version.workspace = true edition.workspace = true diff --git a/src/typegraph/optimize/src/dedup.rs b/src/typegraph/optimize/src/dedup.rs index f4e6de6d1d..b982a76c8f 100644 --- a/src/typegraph/optimize/src/dedup.rs +++ b/src/typegraph/optimize/src/dedup.rs @@ -177,7 +177,7 @@ impl DedupEngine { } } - pub fn get_converted_typegraph(&self) -> Arc { + pub fn get_converted_typegraph(&self) -> Typegraph { let map = self.generate_conversion_map(); let types = map @@ -234,7 +234,6 @@ impl DedupEngine { path: self.tg.path.clone(), deps: self.tg.deps.clone(), } - .into() } pub fn generate_conversion_map(&self) -> ConversionMap { diff --git a/src/typegraph/optimize/src/lib.rs b/src/typegraph/optimize/src/lib.rs index d675e427e6..60ac3ca177 100644 --- a/src/typegraph/optimize/src/lib.rs +++ b/src/typegraph/optimize/src/lib.rs @@ -29,7 +29,7 @@ impl TypeIdx { } } -pub fn optimize(tg: Arc) -> Arc { +pub fn optimize(tg: Arc) -> Typegraph { let mut k = Kosaraju::new(tg); k.run(); diff --git a/src/typegraph/optimize/src/main.rs b/src/typegraph/optimize/src/main.rs index 3e6476ce00..0acf3f7b33 100644 --- a/src/typegraph/optimize/src/main.rs +++ b/src/typegraph/optimize/src/main.rs @@ -10,7 +10,7 @@ fn main() -> color_eyre::eyre::Result<()> { std::io::stdin().read_line(&mut buffer)?; let tg: Typegraph = serde_json::from_str(&buffer)?; let opt_tg = tg_optimize::optimize(Arc::new(tg)); - println!("{}", serde_json::to_string(opt_tg.as_ref())?); + println!("{}", serde_json::to_string(&opt_tg)?); Ok(()) } From d6254f2f0dedd12d9840b26cf7d70bc562cad317 Mon Sep 17 00:00:00 2001 From: Natoandro Date: Thu, 22 May 2025 15:57:29 +0300 Subject: [PATCH 3/8] doc: doc comment in the optimize crate --- src/typegraph/optimize/src/lib.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/typegraph/optimize/src/lib.rs b/src/typegraph/optimize/src/lib.rs index 60ac3ca177..7dd35aa7d5 100644 --- a/src/typegraph/optimize/src/lib.rs +++ b/src/typegraph/optimize/src/lib.rs @@ -1,6 +1,17 @@ // Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0. // SPDX-License-Identifier: MPL-2.0 +/** + * This crate implement the optimization step for the serialized typegraph. + * It runs in three steps. + * - Step 1: We run the Kosaraju's algorithm to partition the graph (only the + * type related vertices) into strongly connected components. + * - Step 2: We assign a bucket for each type, according to its hash. The + * hash function does not currently try to deduplicate types that belong + * in a strongly connected component of size larger than one. + * - Step 3: To each bucket is assigned a type index, then we translate all + * the type references in the typegraph into the new type indices. + */ mod dedup; mod kosaraju; From caae59a9f5ef934d6e31f30ce027b999eeb2e1ee Mon Sep 17 00:00:00 2001 From: Natoandro Date: Thu, 22 May 2025 16:42:50 +0300 Subject: [PATCH 4/8] cleanup --- src/typegraph/optimize/src/dedup.rs | 3 --- src/typegraph/optimize/src/kosaraju.rs | 3 +-- tools/tree-view-web.ts | 25 ++++++++++++++++--- tools/tree/dist/assets/index-B7TWQuis.css | 1 - tools/tree/dist/assets/index-BF0z4CXe.css | 1 + .../{index-en07UP6E.js => index-cH6Zi8mN.js} | 0 tools/tree/dist/index.html | 6 ++--- tools/tree/index.html | 2 +- 8 files changed, 27 insertions(+), 14 deletions(-) delete mode 100644 tools/tree/dist/assets/index-B7TWQuis.css create mode 100644 tools/tree/dist/assets/index-BF0z4CXe.css rename tools/tree/dist/assets/{index-en07UP6E.js => index-cH6Zi8mN.js} (100%) diff --git a/src/typegraph/optimize/src/dedup.rs b/src/typegraph/optimize/src/dedup.rs index b982a76c8f..7dd7897517 100644 --- a/src/typegraph/optimize/src/dedup.rs +++ b/src/typegraph/optimize/src/dedup.rs @@ -158,9 +158,6 @@ impl DedupEngine { "function".hash(&mut hasher); // TODO do we need to deduplication functions?? idx.hash(&mut hasher); - // self.hash_type(data.input.into()).hash(&mut hasher); - // self.hash_type(data.output.into()).hash(&mut hasher); - // if let Some(pt) = data. } N::Any { .. } => unreachable!(), diff --git a/src/typegraph/optimize/src/kosaraju.rs b/src/typegraph/optimize/src/kosaraju.rs index 477096156a..433a14a277 100644 --- a/src/typegraph/optimize/src/kosaraju.rs +++ b/src/typegraph/optimize/src/kosaraju.rs @@ -34,8 +34,7 @@ impl KosarajuOne { } fn visit(&mut self, idx: TypeIdx) { - if self.is_visited(idx) { - } else { + if !self.is_visited(idx) { self.set_visited(idx); for v in self.tg.out_neighbours(&idx) { self.visit(v); diff --git a/tools/tree-view-web.ts b/tools/tree-view-web.ts index 0ba8c585b7..f138faf956 100755 --- a/tools/tree-view-web.ts +++ b/tools/tree-view-web.ts @@ -81,19 +81,25 @@ if (tgs.length === 0) { const byName: Map = new Map(); for (const tg of tgs) { + const name = tg.types[0].title; + if (byName.has(name)) { + console.log( + `[warn] Duplicate typegraph name '${name}'. The older one will be dropped`, + ); + } byName.set(tg.types[0].title, tg); } const router = new Router(); -const fsCache: Map = new Map(); +const fsCache: Map = new Map(); async function getDistFile(path: string) { const cached = fsCache.get(path); if (cached != null) { return cached; } - const value = await Deno.readTextFile( + const value = await Deno.readFile( `${projectDir}/tools/tree/dist/${path}`, ); fsCache.set(path, value); @@ -139,8 +145,19 @@ router.get("/api/typegraphs/:tgName/types/:typeIdx", (ctx) => { ctx.response.body = `typegraph "${ctx.params.tgName}" not found`; ctx.response.status = Status.NotFound; } else { - ctx.response.body = tg.types[+ctx.params.typeIdx]; - ctx.response.type = "json"; + const typeIdx = +ctx.params.typeIdx; + if (Number.isNaN(typeIdx)) { + ctx.response.body = `invalid type index "${ctx.params.typeIdx}"`; + ctx.response.status = Status.BadRequest; + } + const typeNode = tg.types[typeIdx]; + if (typeNode == null) { + ctx.response.body = `type index out of bounds #${typeIdx}`; + ctx.response.status = Status.NotFound; + } else { + ctx.response.body = tg.types[+ctx.params.typeIdx]; + ctx.response.type = "json"; + } } }); diff --git a/tools/tree/dist/assets/index-B7TWQuis.css b/tools/tree/dist/assets/index-B7TWQuis.css deleted file mode 100644 index 508fa6e1e7..0000000000 --- a/tools/tree/dist/assets/index-B7TWQuis.css +++ /dev/null @@ -1 +0,0 @@ -/*! tailwindcss v4.1.6 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-outline-style:solid}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-orange-500:oklch(70.5% .213 47.604);--color-cyan-500:oklch(71.5% .143 215.221);--color-blue-400:oklch(70.7% .165 254.624);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-white:#fff;--spacing:.25rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-bold:700;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.flex{display:flex}.h-4{height:calc(var(--spacing)*4)}.w-4{width:calc(var(--spacing)*4)}.min-w-0{min-width:calc(var(--spacing)*0)}.flex-shrink-0{flex-shrink:0}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.flex-row{flex-direction:row}.items-center{align-items:center}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.border,.border-1{border-style:var(--tw-border-style);border-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l-6{border-left-style:var(--tw-border-style);border-left-width:6px}.border-gray-400{border-color:var(--color-gray-400)}.border-gray-600{border-color:var(--color-gray-600)}.border-white\/5{border-color:#ffffff0d}@supports (color:color-mix(in lab,red,red)){.border-white\/5{border-color:color-mix(in oklab,var(--color-white)5%,transparent)}}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.border-white\/10{border-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.bg-blue-400\/10{background-color:#54a2ff1a}@supports (color:color-mix(in lab,red,red)){.bg-blue-400\/10{background-color:color-mix(in oklab,var(--color-blue-400)10%,transparent)}}.bg-blue-400\/20{background-color:#54a2ff33}@supports (color:color-mix(in lab,red,red)){.bg-blue-400\/20{background-color:color-mix(in oklab,var(--color-blue-400)20%,transparent)}}.bg-gray-800{background-color:var(--color-gray-800)}.bg-gray-900{background-color:var(--color-gray-900)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-4{padding-inline:calc(var(--spacing)*4)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.pl-2{padding-left:calc(var(--spacing)*2)}.pl-3{padding-left:calc(var(--spacing)*3)}.font-mono{font-family:var(--font-mono)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.text-blue-400{color:var(--color-blue-400)}.text-cyan-500{color:var(--color-cyan-500)}.text-gray-300{color:var(--color-gray-300)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-orange-500{color:var(--color-orange-500)}.text-red-400{color:var(--color-red-400)}.text-red-500{color:var(--color-red-500)}.text-white{color:var(--color-white)}.outline-0{outline-style:var(--tw-outline-style);outline-width:0}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}@media (hover:hover){.hover\:text-white:hover{color:var(--color-white)}}.focus\:border-white\/20:focus{border-color:#fff3}@supports (color:color-mix(in lab,red,red)){.focus\:border-white\/20:focus{border-color:color-mix(in oklab,var(--color-white)20%,transparent)}}}:root{color-scheme:light dark;color:#ffffffde;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-color:#242424;font-family:system-ui,Avenir,Helvetica,Arial,sans-serif;font-weight:400;line-height:1.5}a{color:#646cff;-webkit-text-decoration:inherit;text-decoration:inherit;font-weight:500}a:hover{color:#535bf2}body{min-width:320px;min-height:100vh;margin:0}#root{flex-direction:column;min-height:100vh;display:flex}@media (prefers-color-scheme:light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}main{flex:1;max-width:1280px;display:flex;flex-direction:column;align-items:stretch}h1{font-size:3.2em;line-height:1.1}.logo{height:6em;padding:1.5em;will-change:filter;transition:filter .3s}.logo:hover{filter:drop-shadow(0 0 2em #646cffaa)}.logo.react:hover{filter:drop-shadow(0 0 2em #61dafbaa)}@keyframes logo-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media (prefers-reduced-motion: no-preference){a:nth-of-type(2) .logo{animation:logo-spin infinite 20s linear}}.card{padding:2em}.read-the-docs{color:#888} diff --git a/tools/tree/dist/assets/index-BF0z4CXe.css b/tools/tree/dist/assets/index-BF0z4CXe.css new file mode 100644 index 0000000000..dc7e207b29 --- /dev/null +++ b/tools/tree/dist/assets/index-BF0z4CXe.css @@ -0,0 +1 @@ +/*! tailwindcss v4.1.6 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-orange-500:oklch(70.5% .213 47.604);--color-cyan-500:oklch(71.5% .143 215.221);--color-blue-400:oklch(70.7% .165 254.624);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-white:#fff;--spacing:.25rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-bold:700;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.visible{visibility:visible}.absolute{position:absolute}.relative{position:relative}.static{position:static}.flex{display:flex}.hidden{display:none}.h-4{height:calc(var(--spacing)*4)}.w-4{width:calc(var(--spacing)*4)}.min-w-0{min-width:calc(var(--spacing)*0)}.flex-shrink-0{flex-shrink:0}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-row{flex-direction:row}.items-center{align-items:center}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.border,.border-1{border-style:var(--tw-border-style);border-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l-6{border-left-style:var(--tw-border-style);border-left-width:6px}.border-gray-400{border-color:var(--color-gray-400)}.border-gray-600{border-color:var(--color-gray-600)}.border-white\/5{border-color:#ffffff0d}@supports (color:color-mix(in lab,red,red)){.border-white\/5{border-color:color-mix(in oklab,var(--color-white)5%,transparent)}}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.border-white\/10{border-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.bg-blue-400\/10{background-color:#54a2ff1a}@supports (color:color-mix(in lab,red,red)){.bg-blue-400\/10{background-color:color-mix(in oklab,var(--color-blue-400)10%,transparent)}}.bg-blue-400\/20{background-color:#54a2ff33}@supports (color:color-mix(in lab,red,red)){.bg-blue-400\/20{background-color:color-mix(in oklab,var(--color-blue-400)20%,transparent)}}.bg-gray-800{background-color:var(--color-gray-800)}.bg-gray-900{background-color:var(--color-gray-900)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-4{padding-inline:calc(var(--spacing)*4)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.pl-2{padding-left:calc(var(--spacing)*2)}.pl-3{padding-left:calc(var(--spacing)*3)}.font-mono{font-family:var(--font-mono)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.text-blue-400{color:var(--color-blue-400)}.text-cyan-500{color:var(--color-cyan-500)}.text-gray-300{color:var(--color-gray-300)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-orange-500{color:var(--color-orange-500)}.text-red-400{color:var(--color-red-400)}.text-red-500{color:var(--color-red-500)}.text-white{color:var(--color-white)}.italic{font-style:italic}.outline-0{outline-style:var(--tw-outline-style);outline-width:0}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}@media (hover:hover){.hover\:text-white:hover{color:var(--color-white)}}.focus\:border-white\/20:focus{border-color:#fff3}@supports (color:color-mix(in lab,red,red)){.focus\:border-white\/20:focus{border-color:color-mix(in oklab,var(--color-white)20%,transparent)}}}:root{color-scheme:light dark;color:#ffffffde;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-color:#242424;font-family:system-ui,Avenir,Helvetica,Arial,sans-serif;font-weight:400;line-height:1.5}a{color:#646cff;-webkit-text-decoration:inherit;text-decoration:inherit;font-weight:500}a:hover{color:#535bf2}body{min-width:320px;min-height:100vh;margin:0}#root{flex-direction:column;min-height:100vh;display:flex}@media (prefers-color-scheme:light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}main{flex:1;max-width:1280px;display:flex;flex-direction:column;align-items:stretch}h1{font-size:3.2em;line-height:1.1}.logo{height:6em;padding:1.5em;will-change:filter;transition:filter .3s}.logo:hover{filter:drop-shadow(0 0 2em #646cffaa)}.logo.react:hover{filter:drop-shadow(0 0 2em #61dafbaa)}@keyframes logo-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media (prefers-reduced-motion: no-preference){a:nth-of-type(2) .logo{animation:logo-spin infinite 20s linear}}.card{padding:2em}.read-the-docs{color:#888} diff --git a/tools/tree/dist/assets/index-en07UP6E.js b/tools/tree/dist/assets/index-cH6Zi8mN.js similarity index 100% rename from tools/tree/dist/assets/index-en07UP6E.js rename to tools/tree/dist/assets/index-cH6Zi8mN.js diff --git a/tools/tree/dist/index.html b/tools/tree/dist/index.html index 0943794bd4..711814f29d 100644 --- a/tools/tree/dist/index.html +++ b/tools/tree/dist/index.html @@ -4,9 +4,9 @@ - Vite + React + TS - - + Typegraph Explorer + +
diff --git a/tools/tree/index.html b/tools/tree/index.html index 6114d67225..2fe12f6ce1 100644 --- a/tools/tree/index.html +++ b/tools/tree/index.html @@ -4,7 +4,7 @@ - Vite + React + TS + Typegraph Explorer
From 75860e017cb31486353b0d7f2211a10c2dae090b Mon Sep 17 00:00:00 2001 From: Natoandro Date: Fri, 23 May 2025 14:08:28 +0300 Subject: [PATCH 5/8] fix: update test snapshots --- deno.lock | 14 ++++++++++++++ src/typegraph/core/src/global_store.rs | 2 +- .../snapshots/expanded__expanded_graph-2.snap | 2 +- .../snapshots/expanded__expanded_graph-3.snap | 8 -------- tools/tree-view-web.ts | 11 +++++++++-- 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/deno.lock b/deno.lock index eba4087c3f..7bc6d320d3 100644 --- a/deno.lock +++ b/deno.lock @@ -1469,5 +1469,19 @@ "https://raw.githubusercontent.com/metatypedev/ghjk/v0.2.2/utils/unarchive.ts": "f6d0e9e75f470eeef5aecd0089169f4350fc30ebfdc05466bb7b30042294d6d3", "https://raw.githubusercontent.com/metatypedev/ghjk/v0.2.2/utils/url.ts": "e1ada6fd30fc796b8918c88456ea1b5bbd87a07d0a0538b092b91fd2bb9b7623", "https://raw.githubusercontent.com/metatypedev/ghjk/v0.2.2/utils/worker.ts": "ac4caf72a36d2e4af4f4e92f2e0a95f9fc2324b568640f24c7c2ff6dc0c11d62" + }, + "workspace": { + "members": { + "tests": { + "dependencies": [ + "jsr:@std/async@^1.0.3", + "jsr:@std/streams@^1.0.2", + "jsr:@std/testing@^1.0.1", + "jsr:@std/yaml@^1.0.4", + "npm:json-schema-faker@0.5.3", + "npm:pg@8.12.0" + ] + } + } } } diff --git a/src/typegraph/core/src/global_store.rs b/src/typegraph/core/src/global_store.rs index 8426bc16bd..fe12005af2 100644 --- a/src/typegraph/core/src/global_store.rs +++ b/src/typegraph/core/src/global_store.rs @@ -428,7 +428,7 @@ impl Store { /// Generate a pub fn for asserting/unwrapping a Type as a specific TypeDef variant /// e.g.: `as_variant!(Struct)` gives -/// ```rust +/// ```ignore /// pub fn as_struct(&self) -> Result> { /// match self.as_type()? { /// Type::Def(TypeDef::Struct(inner)) => Ok(inner), diff --git a/src/typegraph/graph/tests/snapshots/expanded__expanded_graph-2.snap b/src/typegraph/graph/tests/snapshots/expanded__expanded_graph-2.snap index ce2da62c52..d7ca31a05e 100644 --- a/src/typegraph/graph/tests/snapshots/expanded__expanded_graph-2.snap +++ b/src/typegraph/graph/tests/snapshots/expanded__expanded_graph-2.snap @@ -5,5 +5,5 @@ expression: "tg.functions.iter().map(|(idx, func)|\n { (idx, func.nam { 1: "root_one_fn", 8: "root_two_fn", - 10: "root_three_fn", + 9: "root_three_fn", } diff --git a/src/typegraph/graph/tests/snapshots/expanded__expanded_graph-3.snap b/src/typegraph/graph/tests/snapshots/expanded__expanded_graph-3.snap index c98ea77f8d..5cac64a756 100644 --- a/src/typegraph/graph/tests/snapshots/expanded__expanded_graph-3.snap +++ b/src/typegraph/graph/tests/snapshots/expanded__expanded_graph-3.snap @@ -11,12 +11,4 @@ expression: "tg.input_types.iter().map(|(idx, ty)|\n { (idx, (ty.tag( "string", "string_3fb09", ), - Ty_9/0: ( - "object", - "TwoInput", - ), - Ty_11/0: ( - "object", - "root_three_fn_input", - ), } diff --git a/tools/tree-view-web.ts b/tools/tree-view-web.ts index f138faf956..1fb02e0866 100755 --- a/tools/tree-view-web.ts +++ b/tools/tree-view-web.ts @@ -112,8 +112,14 @@ router.get("/logo.svg", async (ctx) => { }); router.get("/assets/:asset", async (ctx) => { - ctx.response.body = await getDistFile(`assets/${ctx.params.asset}`); - ctx.response.type = ctx.params.asset.split(".").slice(-1)[0]; + const asset = ctx.params.asset; + if (asset.includes("..") || asset.includes("/")) { + ctx.response.body = `invalid assset name '${asset}'`; + ctx.response.status = Status.BadRequest; + } else { + ctx.response.body = await getDistFile(`assets/${ctx.params.asset}`); + ctx.response.type = ctx.params.asset.split(".").slice(-1)[0]; + } }); router.get("/api/typegraphs", (ctx) => { @@ -149,6 +155,7 @@ router.get("/api/typegraphs/:tgName/types/:typeIdx", (ctx) => { if (Number.isNaN(typeIdx)) { ctx.response.body = `invalid type index "${ctx.params.typeIdx}"`; ctx.response.status = Status.BadRequest; + return; } const typeNode = tg.types[typeIdx]; if (typeNode == null) { From 8768231e4b71b3a7a0f1841f20be68c6c13e7763 Mon Sep 17 00:00:00 2001 From: Natoandro Date: Fri, 23 May 2025 15:45:08 +0300 Subject: [PATCH 6/8] fix: (...) --- src/typegraph/core/src/types/sdk/aws.rs | 2 ++ src/typegraph/core/src/types/sdk/core.rs | 1 + src/typegraph/core/src/types/sdk/runtimes.rs | 2 ++ src/typegraph/core/src/types/sdk/utils.rs | 2 ++ src/typegraph/specs/codegen/src/lib/rust_lib.ts | 5 +++-- 5 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/typegraph/core/src/types/sdk/aws.rs b/src/typegraph/core/src/types/sdk/aws.rs index 03c6ac11dc..0a26cc2713 100644 --- a/src/typegraph/core/src/types/sdk/aws.rs +++ b/src/typegraph/core/src/types/sdk/aws.rs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: MPL-2.0 use super::core::{MaterializerId, RuntimeId}; +#[allow(unused)] +use ordered_float::NotNan; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/src/typegraph/core/src/types/sdk/core.rs b/src/typegraph/core/src/types/sdk/core.rs index 058298b150..a688e54623 100644 --- a/src/typegraph/core/src/types/sdk/core.rs +++ b/src/typegraph/core/src/types/sdk/core.rs @@ -1,6 +1,7 @@ // Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0. // SPDX-License-Identifier: MPL-2.0 +#[allow(unused)] use ordered_float::NotNan; use serde::{Deserialize, Serialize}; diff --git a/src/typegraph/core/src/types/sdk/runtimes.rs b/src/typegraph/core/src/types/sdk/runtimes.rs index ec9999701a..75340f799c 100644 --- a/src/typegraph/core/src/types/sdk/runtimes.rs +++ b/src/typegraph/core/src/types/sdk/runtimes.rs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: MPL-2.0 use super::core::{FuncParams, MaterializerId, RuntimeId, TypeId}; +#[allow(unused)] +use ordered_float::NotNan; use serde::{Deserialize, Serialize}; pub type Idempotency = bool; diff --git a/src/typegraph/core/src/types/sdk/utils.rs b/src/typegraph/core/src/types/sdk/utils.rs index c4633a6a22..1af39ce56b 100644 --- a/src/typegraph/core/src/types/sdk/utils.rs +++ b/src/typegraph/core/src/types/sdk/utils.rs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: MPL-2.0 use super::core::TypeId; +#[allow(unused)] +use ordered_float::NotNan; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/src/typegraph/specs/codegen/src/lib/rust_lib.ts b/src/typegraph/specs/codegen/src/lib/rust_lib.ts index 26dd1306ba..a556236a65 100644 --- a/src/typegraph/specs/codegen/src/lib/rust_lib.ts +++ b/src/typegraph/specs/codegen/src/lib/rust_lib.ts @@ -15,7 +15,7 @@ import type { const typeMap = { UInt: "u32", SInt: "i32", - Float: "f64", + Float: "NotNan", string: "String", boolean: "bool", void: "()", @@ -39,7 +39,8 @@ class RustLibCodeGenerator extends TypeDefProcessor { } override formatHeaders(_moduleName?: string) { - const baseImport = "use serde::{Deserialize, Serialize};"; + const baseImport = + "use serde::{Deserialize, Serialize};\n#[allow(unused)] use ordered_float::NotNan;"; const imports = this.imports.map( ({ imports, source }) => From 89d4632cc3798080b1bff46d524b1b619d8ba69d Mon Sep 17 00:00:00 2001 From: Natoandro Date: Fri, 23 May 2025 16:34:13 +0300 Subject: [PATCH 7/8] fix(test): fix codegen test --- deno.lock | 1 + src/typegraph/specs/codegen/tests/rust_lib.test.ts | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/deno.lock b/deno.lock index 7bc6d320d3..a9e8049d30 100644 --- a/deno.lock +++ b/deno.lock @@ -7,6 +7,7 @@ "jsr:@oak/commons@^1.0": "jsr:@oak/commons@1.0.1", "jsr:@oak/oak": "jsr:@oak/oak@17.1.4", "jsr:@std/archive@^0.225.0": "jsr:@std/archive@0.225.4", + "jsr:@std/assert": "jsr:@std/assert@1.0.10", "jsr:@std/assert@^0.221.0": "jsr:@std/assert@0.221.0", "jsr:@std/assert@^1.0": "jsr:@std/assert@1.0.10", "jsr:@std/assert@^1.0.3": "jsr:@std/assert@1.0.10", diff --git a/src/typegraph/specs/codegen/tests/rust_lib.test.ts b/src/typegraph/specs/codegen/tests/rust_lib.test.ts index 5705ddd959..78eaf09d89 100644 --- a/src/typegraph/specs/codegen/tests/rust_lib.test.ts +++ b/src/typegraph/specs/codegen/tests/rust_lib.test.ts @@ -27,7 +27,7 @@ pub struct RecordLike { pub num: u32, pub key: String, pub str_arr: Vec, - pub tup: (f64, f64), + pub tup: (NotNan, NotNan), pub opt: Option, pub comp: Option>, }`; @@ -72,7 +72,8 @@ Deno.test("Rust import codegen", () => { const result = rustcg.formatHeaders(); const expected = `use super::foobar::{Foo, Bar}; -use serde::{Deserialize, Serialize};`; +use serde::{Deserialize, Serialize}; +#[allow(unused)] use ordered_float::NotNan;`; assertEquals(result, expected); }); From 46a9589db816dc73b41d500a01cc6b52a8bd9df7 Mon Sep 17 00:00:00 2001 From: Natoandro Date: Wed, 18 Jun 2025 17:28:59 +0300 Subject: [PATCH 8/8] fix: prisma runtime types after optimization, keep user-named types --- Cargo.lock | 1 + deno.lock | 95 +++++++++++++++++++ src/meta-cli/src/main.rs | 9 +- src/typegraph/core/Cargo.toml | 1 + src/typegraph/core/src/global_store.rs | 49 ++-------- src/typegraph/core/src/lib.rs | 5 +- .../type_generation/additional_filters.rs | 13 +-- .../prisma/type_generation/aggregate.rs | 4 +- .../runtimes/prisma/type_generation/count.rs | 2 +- .../prisma/type_generation/filters.rs | 14 +-- .../prisma/type_generation/group_by.rs | 8 +- .../prisma/type_generation/input_type.rs | 2 +- .../prisma/type_generation/order_by.rs | 12 +-- .../prisma/type_generation/out_type.rs | 2 +- .../type_generation/query_input_type.rs | 2 +- .../type_generation/query_where_expr.rs | 2 +- .../runtimes/prisma/type_generation/where_.rs | 2 +- .../type_generation/with_nested_count.rs | 2 +- .../src/runtimes/substantial/type_utils.rs | 20 ++-- src/typegraph/core/src/t.rs | 16 +++- src/typegraph/core/src/typegraph.rs | 50 +++++++--- src/typegraph/core/src/types/type_ref.rs | 13 ++- src/typegraph/core/src/types/type_ref/xdef.rs | 2 +- .../core/src/utils/postprocess/naming.rs | 20 ++-- src/typegraph/optimize/src/dedup.rs | 20 +++- src/typegraph/optimize/src/lib.rs | 35 +++++-- src/typegraph/optimize/src/main.rs | 2 +- src/typegraph/schema/src/types.rs | 1 + .../migration.sql | 0 tools/tasks/test.ts | 3 + tools/verdaccio/config.yaml | 22 ----- 31 files changed, 279 insertions(+), 150 deletions(-) rename tests/prisma-migrations/migration-failure-test-dev/main/{20250430193822_generated => 20250618092719_generated}/migration.sql (100%) delete mode 100644 tools/verdaccio/config.yaml diff --git a/Cargo.lock b/Cargo.lock index 5fa285c9cd..7b29e97ecf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13134,6 +13134,7 @@ dependencies = [ "sha2 0.10.8", "tg_optimize", "tg_schema", + "tracing", "unindent", ] diff --git a/deno.lock b/deno.lock index a9e8049d30..0ea73b3366 100644 --- a/deno.lock +++ b/deno.lock @@ -10,8 +10,10 @@ "jsr:@std/assert": "jsr:@std/assert@1.0.10", "jsr:@std/assert@^0.221.0": "jsr:@std/assert@0.221.0", "jsr:@std/assert@^1.0": "jsr:@std/assert@1.0.10", + "jsr:@std/assert@^1.0.10": "jsr:@std/assert@1.0.10", "jsr:@std/assert@^1.0.3": "jsr:@std/assert@1.0.10", "jsr:@std/assert@^1.0.6": "jsr:@std/assert@1.0.10", + "jsr:@std/async@^1.0.3": "jsr:@std/async@1.0.9", "jsr:@std/bytes@^0.221.0": "jsr:@std/bytes@0.221.0", "jsr:@std/bytes@^1.0": "jsr:@std/bytes@1.0.5", "jsr:@std/bytes@^1.0.2": "jsr:@std/bytes@1.0.5", @@ -52,8 +54,10 @@ "jsr:@std/semver@^1.0.1": "jsr:@std/semver@1.0.3", "jsr:@std/streams@0.221.0": "jsr:@std/streams@0.221.0", "jsr:@std/streams@1": "jsr:@std/streams@1.0.9", + "jsr:@std/testing@^1.0.1": "jsr:@std/testing@1.0.9", "jsr:@std/text@^1.0.7": "jsr:@std/text@1.0.10", "jsr:@std/uuid@^1.0.1": "jsr:@std/uuid@1.0.4", + "jsr:@std/yaml@^1.0.4": "jsr:@std/yaml@1.0.5", "npm:@noble/hashes@1.4.0": "npm:@noble/hashes@1.4.0", "npm:@sentry/node@7.70.0": "npm:@sentry/node@7.70.0", "npm:@sinonjs/fake-timers@13.0.5": "npm:@sinonjs/fake-timers@13.0.5", @@ -66,6 +70,7 @@ "npm:mathjs@11.11.1": "npm:mathjs@11.11.1", "npm:multiformats@13.1.0": "npm:multiformats@13.1.0", "npm:path-to-regexp@^6.3.0": "npm:path-to-regexp@6.3.0", + "npm:pg@8.12.0": "npm:pg@8.12.0", "npm:tree-sitter-typescript@^0.23.0": "npm:tree-sitter-typescript@0.23.2_tree-sitter@0.21.1", "npm:tree-sitter@^0.21.1": "npm:tree-sitter@0.21.1", "npm:validator@13.12.0": "npm:validator@13.12.0", @@ -126,6 +131,9 @@ "jsr:@std/internal@^1.0.5" ] }, + "@std/async@1.0.9": { + "integrity": "c6472fd0623b3f3daae023cdf7ca5535e1b721dfbf376562c0c12b3fb4867f91" + }, "@std/bytes@0.221.0": { "integrity": "64a047011cf833890a4a2ab7293ac55a1b4f5a050624ebc6a0159c357de91966" }, @@ -232,6 +240,15 @@ "jsr:@std/bytes@^1.0.5" ] }, + "@std/testing@1.0.9": { + "integrity": "9bdd4ac07cb13e7594ac30e90f6ceef7254ac83a9aeaa089be0008f33aab5cd4", + "dependencies": [ + "jsr:@std/assert@^1.0.10", + "jsr:@std/fs@^1.0.9", + "jsr:@std/internal@^1.0.5", + "jsr:@std/path@^1.0.8" + ] + }, "@std/text@1.0.10": { "integrity": "9dcab377450253c0efa9a9a0c731040bfd4e1c03f8303b5934381467b7954338" }, @@ -241,6 +258,9 @@ "jsr:@std/bytes@^1.0.2", "jsr:@std/crypto@^1.0.3" ] + }, + "@std/yaml@1.0.5": { + "integrity": "71ba3d334305ee2149391931508b2c293a8490f94a337eef3a09cade1a2a2742" } }, "npm": { @@ -468,6 +488,73 @@ "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", "dependencies": {} }, + "pg-cloudflare@1.1.1": { + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "dependencies": {} + }, + "pg-connection-string@2.7.0": { + "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==", + "dependencies": {} + }, + "pg-int8@1.0.1": { + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "dependencies": {} + }, + "pg-pool@3.8.0_pg@8.12.0": { + "integrity": "sha512-VBw3jiVm6ZOdLBTIcXLNdSotb6Iy3uOCwDGFAksZCXmi10nyRvnP2v3jl4d+IsLYRyXf6o9hIm/ZtUzlByNUdw==", + "dependencies": { + "pg": "pg@8.12.0" + } + }, + "pg-protocol@1.8.0": { + "integrity": "sha512-jvuYlEkL03NRvOoyoRktBK7+qU5kOvlAwvmrH8sr3wbLrOdVWsRxQfz8mMy9sZFsqJ1hEWNfdWKI4SAmoL+j7g==", + "dependencies": {} + }, + "pg-types@2.2.0": { + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "pg-int8@1.0.1", + "postgres-array": "postgres-array@2.0.0", + "postgres-bytea": "postgres-bytea@1.0.0", + "postgres-date": "postgres-date@1.0.7", + "postgres-interval": "postgres-interval@1.2.0" + } + }, + "pg@8.12.0": { + "integrity": "sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ==", + "dependencies": { + "pg-cloudflare": "pg-cloudflare@1.1.1", + "pg-connection-string": "pg-connection-string@2.7.0", + "pg-pool": "pg-pool@3.8.0_pg@8.12.0", + "pg-protocol": "pg-protocol@1.8.0", + "pg-types": "pg-types@2.2.0", + "pgpass": "pgpass@1.0.5" + } + }, + "pgpass@1.0.5": { + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": { + "split2": "split2@4.2.0" + } + }, + "postgres-array@2.0.0": { + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "dependencies": {} + }, + "postgres-bytea@1.0.0": { + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "dependencies": {} + }, + "postgres-date@1.0.7": { + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "dependencies": {} + }, + "postgres-interval@1.2.0": { + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "xtend@4.0.2" + } + }, "regenerator-runtime@0.14.1": { "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", "dependencies": {} @@ -476,6 +563,10 @@ "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", "dependencies": {} }, + "split2@4.2.0": { + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dependencies": {} + }, "tiny-emitter@2.1.0": { "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", "dependencies": {} @@ -520,6 +611,10 @@ "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", "dependencies": {} }, + "xtend@4.0.2": { + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dependencies": {} + }, "yaml@2.7.0": { "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", "dependencies": {} diff --git a/src/meta-cli/src/main.rs b/src/meta-cli/src/main.rs index 5b663c9d53..569a1364aa 100644 --- a/src/meta-cli/src/main.rs +++ b/src/meta-cli/src/main.rs @@ -111,8 +111,13 @@ fn main() -> Result<()> { .unwrap_or_log() }); - if let Err(err) = runner.block_on(upgrade_check()) { - warn!("cannot check for update: {err}"); + let upgrade = std::env::var("MCLI_NO_UPGRADE_CHECK") + .map(|v| v == "1") + .unwrap_or(false); + if upgrade { + if let Err(err) = runner.block_on(upgrade_check()) { + warn!("cannot check for update: {err}"); + } } runner.block_on(async move { diff --git a/src/typegraph/core/Cargo.toml b/src/typegraph/core/Cargo.toml index 24f2991cc7..c5c668496d 100644 --- a/src/typegraph/core/Cargo.toml +++ b/src/typegraph/core/Cargo.toml @@ -14,6 +14,7 @@ enum_dispatch.workspace = true color-eyre.workspace = true anyhow.workspace = true paste.workspace = true +tracing.workspace = true serde.workspace = true serde_json.workspace = true diff --git a/src/typegraph/core/src/global_store.rs b/src/typegraph/core/src/global_store.rs index fe12005af2..b3140c8094 100644 --- a/src/typegraph/core/src/global_store.rs +++ b/src/typegraph/core/src/global_store.rs @@ -20,8 +20,6 @@ use std::rc::Rc; use std::{cell::RefCell, collections::HashMap}; use tg_schema::runtimes::deno::PredefinedFunctionMatData; -const PLACEHOLDER_TYPE_SUFFIX: &str = "_____PLACEHOLDER_____"; - pub type Policy = Rc; /// As all the store entries are append only, we can set a restore point @@ -49,7 +47,7 @@ pub struct Store { pub types: Vec, // the bool indicates weather the name was from // user or generated placeholder (false) - pub type_by_names: IndexMap, (NamedTypeRef, bool)>, + pub type_by_names: IndexMap, NamedTypeRef>, pub runtimes: Vec, pub materializers: Vec, @@ -148,7 +146,7 @@ impl Store { } pub fn get_type_by_name(name: &str) -> Option { - with_store(|s| s.type_by_names.get(name).map(|id| id.0.clone())) + with_store(|s| s.type_by_names.get(name).cloned()) } pub fn register_type_ref(builder: TypeRefBuilder) -> Result { @@ -162,34 +160,13 @@ impl Store { // allow the ref system to work match &type_ref { TypeRef::Named(name_ref) => { - let (type_ref, name_ref, name, user_named) = - if name_ref.name.ends_with(PLACEHOLDER_TYPE_SUFFIX) { - let name = name_ref.name.strip_suffix(PLACEHOLDER_TYPE_SUFFIX).unwrap(); - let name_ref = NamedTypeRef { - id: name_ref.id, - name: name.into(), - target: name_ref.target.clone(), - }; - ( - TypeRef::Named(name_ref.clone()), - name_ref, - name.to_string().into(), - false, - ) - } else { - ( - type_ref.clone(), - name_ref.clone(), - name_ref.name.clone(), - true, - ) - }; let res = type_ref.clone(); + let type_ref = type_ref.clone(); with_store_mut(move |s| -> Result<()> { s.types.push(Type::Ref(type_ref)); Ok(()) })?; - Self::register_type_name(name, name_ref, user_named)?; + Self::register_type_name(name_ref.clone())?; Ok(res) } _ => { @@ -239,27 +216,17 @@ impl Store { // } } - pub fn register_type_name( - name: Rc, - name_ref: NamedTypeRef, - user_named: bool, - ) -> Result<()> { + pub fn register_type_name(name_ref: NamedTypeRef) -> Result<()> { with_store_mut(move |s| -> Result<()> { - if s.type_by_names.contains_key(&name) { + let name = &name_ref.name; + if s.type_by_names.contains_key(name) { return Err(format!("type with name {:?} already exists", name).into()); } - s.type_by_names.insert(name, (name_ref, user_named)); + s.type_by_names.insert(name.clone(), name_ref); Ok(()) }) } - pub fn is_user_named(name: &str) -> Option { - with_store(|s| { - let (_id, user_named) = s.type_by_names.get(name)?; - Some(*user_named) - }) - } - pub fn get_random_seed() -> Option { with_store(|store| store.random_seed) } diff --git a/src/typegraph/core/src/lib.rs b/src/typegraph/core/src/lib.rs index 7d6c4f0858..fd65788d3f 100644 --- a/src/typegraph/core/src/lib.rs +++ b/src/typegraph/core/src/lib.rs @@ -4,6 +4,7 @@ pub mod errors; use tg_schema::runtimes::deno::{ContextCheckX, PredefinedFunctionMatData}; use tg_schema::Injection; +use typegraph::NameSource; pub use types::sdk; mod conversion; @@ -234,7 +235,9 @@ impl sdk::core::Handler for Lib { } fn rename_type(type_id: CoreTypeId, new_name: String) -> Result { - TypeId(type_id).named(new_name).map(|t| t.id().0) + TypeId(type_id) + .named(new_name, NameSource::User) + .map(|t| t.id().0) } fn get_type_repr(type_id: CoreTypeId) -> Result { diff --git a/src/typegraph/core/src/runtimes/prisma/type_generation/additional_filters.rs b/src/typegraph/core/src/runtimes/prisma/type_generation/additional_filters.rs index b74cf923e8..528f28d4e2 100644 --- a/src/typegraph/core/src/runtimes/prisma/type_generation/additional_filters.rs +++ b/src/typegraph/core/src/runtimes/prisma/type_generation/additional_filters.rs @@ -4,7 +4,6 @@ use crate::runtimes::prisma::context::PrismaContext; use crate::runtimes::prisma::model::Property; use crate::t::{self, TypeBuilder}; -use crate::types::Named as _; use crate::{errors::Result, types::TypeId}; use super::TypeGen; @@ -13,11 +12,7 @@ pub struct Take; impl TypeGen for Take { fn generate(&self, context: &PrismaContext) -> Result { - t::integer() - .x_min(0) - .build()? - .named(self.name(context)?) - .map(|t| t.id()) + t::integer().x_min(0).build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { @@ -29,7 +24,7 @@ pub struct Skip; impl TypeGen for Skip { fn generate(&self, context: &PrismaContext) -> Result { - t::integer().min(0).build_named(self.name(context)?) + t::integer().min(0).build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { @@ -52,7 +47,7 @@ impl TypeGen for Distinct { }) .collect(); - t::listx(t::string().enum_(cols)).build_named(self.name(context)?) + t::listx(t::string().enum_(cols)).build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { @@ -89,7 +84,7 @@ impl TypeGen for Cursor { let variant = t::struct_().prop(k, id).build()?; variants.push(variant) } - t::union(variants).build_named(self.name(context)?) + t::union(variants).build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { diff --git a/src/typegraph/core/src/runtimes/prisma/type_generation/aggregate.rs b/src/typegraph/core/src/runtimes/prisma/type_generation/aggregate.rs index 8e8b92d0a6..e332f9c0b7 100644 --- a/src/typegraph/core/src/runtimes/prisma/type_generation/aggregate.rs +++ b/src/typegraph/core/src/runtimes/prisma/type_generation/aggregate.rs @@ -38,7 +38,7 @@ impl TypeGen for CountOutput { } // TODO union - builder.build_named(self.name(context)?) + builder.build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { @@ -88,7 +88,7 @@ impl TypeGen for NumberAggregateOutput { } } - builder.build_named(self.name(context)?) + builder.build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { diff --git a/src/typegraph/core/src/runtimes/prisma/type_generation/count.rs b/src/typegraph/core/src/runtimes/prisma/type_generation/count.rs index e23a52155d..488dc15090 100644 --- a/src/typegraph/core/src/runtimes/prisma/type_generation/count.rs +++ b/src/typegraph/core/src/runtimes/prisma/type_generation/count.rs @@ -14,7 +14,7 @@ pub struct Count; impl TypeGen for Count { fn generate(&self, context: &PrismaContext) -> Result { - t::optionalx(t::integer()).build_named(self.name(context)?) + t::optionalx(t::integer()).build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { diff --git a/src/typegraph/core/src/runtimes/prisma/type_generation/filters.rs b/src/typegraph/core/src/runtimes/prisma/type_generation/filters.rs index 0ef7fda229..4c1d9d2f02 100644 --- a/src/typegraph/core/src/runtimes/prisma/type_generation/filters.rs +++ b/src/typegraph/core/src/runtimes/prisma/type_generation/filters.rs @@ -15,7 +15,7 @@ impl TypeGen for CompleteFilter { let inner = context.generate(&self.0)?; // TODO and, or ??? t::optionalx(t::unionx![inner, t::struct_().prop("not", inner)]) - .build_named(self.name(context)?) + .build_named_p(self.name(context)?) } fn name(&self, context: &PrismaContext) -> Result { @@ -32,7 +32,7 @@ impl TypeGen for BooleanFilter { t::struct_().propx("equals", t::boolean())?, t::struct_().propx("not", t::boolean())?, ] - .build_named(self.name(context)?) + .build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { @@ -74,7 +74,7 @@ impl TypeGen for NumberFilter { t::struct_().prop("_min", base), t::struct_().prop("_max", base), ] - .build_named(self.name(context)?) + .build_named_p(self.name(context)?) } else { let type_id = match self.number_type { NumberType::Integer => t::integer().build()?, @@ -95,7 +95,7 @@ impl TypeGen for NumberFilter { t::struct_().prop("in", list_type_id), t::struct_().prop("notIn", list_type_id), ] - .build_named(self.name(context)?) + .build_named_p(self.name(context)?) } } @@ -137,7 +137,7 @@ impl TypeGen for StringFilter { .prop("endsWith", opt_type_id) .min(1), ] - .build_named(self.name(context)?) + .build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { @@ -164,7 +164,7 @@ impl TypeGen for ScalarListFilter { // TODO "isSet": mongo only t::struct_().propx("equals", t::list(self.0))?, ] - .build_named(self.name(context)?) + .build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { @@ -336,5 +336,5 @@ fn gen_aggregate_filter (String, NumberType)>( ); } - builder.build_named(name) + builder.build_named_p(name) } diff --git a/src/typegraph/core/src/runtimes/prisma/type_generation/group_by.rs b/src/typegraph/core/src/runtimes/prisma/type_generation/group_by.rs index 627e4e83d5..6ac441bc9e 100644 --- a/src/typegraph/core/src/runtimes/prisma/type_generation/group_by.rs +++ b/src/typegraph/core/src/runtimes/prisma/type_generation/group_by.rs @@ -33,7 +33,7 @@ impl TypeGen for GroupingFields { }) .collect(); - t::listx(t::string().enum_(fields))?.build_named(self.name(context)?) + t::listx(t::string().enum_(fields))?.build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { @@ -66,7 +66,7 @@ impl TypeGen for Having { t::struct_().propx("OR", t::list(self_ref))?, t::struct_().prop("NOT", self_ref) ] - .build_named(name) + .build_named_p(name) } fn name(&self, _context: &PrismaContext) -> Result { @@ -112,7 +112,7 @@ impl TypeGen for GroupByResult { ) .build()?, ) - .build_named(self.name(context)?) + .build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { @@ -164,7 +164,7 @@ impl TypeGen for SelectNumbers { } } - builder.build_named(self.name(context)?) + builder.build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { diff --git a/src/typegraph/core/src/runtimes/prisma/type_generation/input_type.rs b/src/typegraph/core/src/runtimes/prisma/type_generation/input_type.rs index efe0269a15..abcb5b6937 100644 --- a/src/typegraph/core/src/runtimes/prisma/type_generation/input_type.rs +++ b/src/typegraph/core/src/runtimes/prisma/type_generation/input_type.rs @@ -210,7 +210,7 @@ impl TypeGen for InputType { } } - builder.build_named(self.name(context)?) + builder.build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { diff --git a/src/typegraph/core/src/runtimes/prisma/type_generation/order_by.rs b/src/typegraph/core/src/runtimes/prisma/type_generation/order_by.rs index 021f339e56..e3d9fdd116 100644 --- a/src/typegraph/core/src/runtimes/prisma/type_generation/order_by.rs +++ b/src/typegraph/core/src/runtimes/prisma/type_generation/order_by.rs @@ -91,7 +91,7 @@ impl TypeGen for OrderBy { } } - t::listx(builder)?.build_named(self.name(context)?) + t::listx(builder)?.build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { @@ -117,7 +117,7 @@ impl TypeGen for SortOrder { fn generate(&self, context: &PrismaContext) -> Result { t::string() .enum_(vec!["asc".to_string(), "desc".to_string()]) - .build_named(self.name(context)?) + .build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { @@ -131,7 +131,7 @@ impl TypeGen for NullsOrder { fn generate(&self, context: &PrismaContext) -> Result { t::string() .enum_(vec!["first".to_string(), "last".to_string()]) - .build_named(self.name(context)?) + .build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { @@ -153,7 +153,7 @@ impl TypeGen for Sort { builder.prop("nulls", nulls_order); } - t::optionalx(t::unionx![builder, sort_order])?.build_named(self.name(context)?) + t::optionalx(t::unionx![builder, sort_order])?.build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { @@ -174,7 +174,7 @@ impl TypeGen for SortByAggregates { builder.prop("_min", sort); builder.prop("_max", sort); - t::optionalx(builder)?.build_named(self.name(context)?) + t::optionalx(builder)?.build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { @@ -244,7 +244,7 @@ impl TypeGen for AggregateSorting { .prop("_sum", others) .prop("_min", others) .prop("_max", others) - .build_named(self.name(context)?) + .build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { diff --git a/src/typegraph/core/src/runtimes/prisma/type_generation/out_type.rs b/src/typegraph/core/src/runtimes/prisma/type_generation/out_type.rs index 993738bcb3..dac6e12a03 100644 --- a/src/typegraph/core/src/runtimes/prisma/type_generation/out_type.rs +++ b/src/typegraph/core/src/runtimes/prisma/type_generation/out_type.rs @@ -70,7 +70,7 @@ impl TypeGen for OutType { } } - builder.build_named(self.name(context)?) + builder.build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { diff --git a/src/typegraph/core/src/runtimes/prisma/type_generation/query_input_type.rs b/src/typegraph/core/src/runtimes/prisma/type_generation/query_input_type.rs index 79aef2d345..ec24a68471 100644 --- a/src/typegraph/core/src/runtimes/prisma/type_generation/query_input_type.rs +++ b/src/typegraph/core/src/runtimes/prisma/type_generation/query_input_type.rs @@ -69,7 +69,7 @@ impl TypeGen for QueryInputType { )?; } - builder.build_named(self.name(context)?) + builder.build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { diff --git a/src/typegraph/core/src/runtimes/prisma/type_generation/query_where_expr.rs b/src/typegraph/core/src/runtimes/prisma/type_generation/query_where_expr.rs index e97229497b..e714c38415 100644 --- a/src/typegraph/core/src/runtimes/prisma/type_generation/query_where_expr.rs +++ b/src/typegraph/core/src/runtimes/prisma/type_generation/query_where_expr.rs @@ -55,7 +55,7 @@ impl TypeGen for QueryWhereExpr { builder.prop("OR", and); builder.propx("NOT", t::optional(self_ref))?; - builder.build_named(name) + builder.build_named_p(name) } fn name(&self, _context: &PrismaContext) -> Result { diff --git a/src/typegraph/core/src/runtimes/prisma/type_generation/where_.rs b/src/typegraph/core/src/runtimes/prisma/type_generation/where_.rs index 85d5e1e20d..b99b28c8ad 100644 --- a/src/typegraph/core/src/runtimes/prisma/type_generation/where_.rs +++ b/src/typegraph/core/src/runtimes/prisma/type_generation/where_.rs @@ -108,7 +108,7 @@ impl TypeGen for Where { } } - builder.build_named(name) + builder.build_named_p(name) } fn name(&self, _context: &PrismaContext) -> Result { diff --git a/src/typegraph/core/src/runtimes/prisma/type_generation/with_nested_count.rs b/src/typegraph/core/src/runtimes/prisma/type_generation/with_nested_count.rs index a3afeae1e7..827598b627 100644 --- a/src/typegraph/core/src/runtimes/prisma/type_generation/with_nested_count.rs +++ b/src/typegraph/core/src/runtimes/prisma/type_generation/with_nested_count.rs @@ -92,7 +92,7 @@ impl TypeGen for WithNestedCount { builder.propx("_count", count)?; } - builder.build_named(self.name(context)?) + builder.build_named_p(self.name(context)?) } fn name(&self, _context: &PrismaContext) -> Result { diff --git a/src/typegraph/core/src/runtimes/substantial/type_utils.rs b/src/typegraph/core/src/runtimes/substantial/type_utils.rs index 35cb4a8ce0..f4b3480b88 100644 --- a/src/typegraph/core/src/runtimes/substantial/type_utils.rs +++ b/src/typegraph/core/src/runtimes/substantial/type_utils.rs @@ -94,16 +94,20 @@ fn filter_term_variants() -> Result> { .into_iter() .map(|op| { save(op, |n| { - t::struct_().prop(op, value_to_comp_against).build_named(n) + t::struct_() + .prop(op, value_to_comp_against) + .build_named_subs(n) }) }) .collect::>>()?; - let op_value = save("op", |n| t::either(ops.clone().into_iter()).build_named(n))?; + let op_value = save("op", |n| { + t::either(ops.clone().into_iter()).build_named_subs(n) + })?; let special = ["run_id", "started_at", "ended_at", "status"] .into_iter() - .map(|sp| save(sp, |n| t::struct_().prop(sp, op_value).build_named(n))) + .map(|sp| save(sp, |n| t::struct_().prop(sp, op_value).build_named_subs(n))) .collect::>>()?; let mut variants = vec![]; @@ -124,19 +128,19 @@ pub fn filter_expr_ty() -> Result { loc_ref("not_expr")?, ]); - let expr = save("expr", |n| t::either(op_expr_variants).build_named(n))?; - let expr_list = save("list_expr", |n| t::listx(expr).build_named(n))?; + let expr = save("expr", |n| t::either(op_expr_variants).build_named_subs(n))?; + let expr_list = save("list_expr", |n| t::listx(expr).build_named_subs(n))?; let _and = save("and_expr", |n| { - t::struct_().prop("and", expr_list).build_named(n) + t::struct_().prop("and", expr_list).build_named_subs(n) })?; let _or = save("or_expr", |n| { - t::struct_().prop("or", expr_list).build_named(n) + t::struct_().prop("or", expr_list).build_named_subs(n) })?; let _not = save("not_expr", |n| { - t::struct_().prop("not", expr).build_named(n) + t::struct_().prop("not", expr).build_named_subs(n) })?; t::struct_() diff --git a/src/typegraph/core/src/t.rs b/src/typegraph/core/src/t.rs index b5e828a38a..88b80505f1 100644 --- a/src/typegraph/core/src/t.rs +++ b/src/typegraph/core/src/t.rs @@ -7,6 +7,7 @@ use crate::sdk::core::{ Handler, TypeEither, TypeFloat, TypeFunc, TypeInteger, TypeList, TypeOptional, TypeString, TypeStruct, TypeUnion, }; +use crate::typegraph::NameSource; use crate::types::RefAttr; use crate::types::TypeRefBuilder; use crate::types::{Named as _, TypeId, TypeRef}; @@ -22,8 +23,21 @@ pub trait TypeBuilder { Ok(optional(self.build()?)) } + fn build_named_p(&self, name: impl Into) -> Result { + Ok(self.build()?.named(name, NameSource::PrismaTypeGen)?.id()) + } + fn build_named_subs(&self, name: impl Into) -> Result { + Ok(self.build()?.named(name, NameSource::Substantial)?.id()) + } + + #[allow(unused)] + fn build_named_s(&self, name: impl Into, name_source: NameSource) -> Result { + Ok(self.build()?.named(name, name_source)?.id()) + } + + #[allow(unused)] fn build_named(&self, name: impl Into) -> Result { - Ok(self.build()?.named(name)?.id()) + Ok(self.build()?.named(name, NameSource::User)?.id()) } #[cfg(test)] diff --git a/src/typegraph/core/src/typegraph.rs b/src/typegraph/core/src/typegraph.rs index bec1d103ee..e61f8a7d2f 100644 --- a/src/typegraph/core/src/typegraph.rs +++ b/src/typegraph/core/src/typegraph.rs @@ -19,7 +19,7 @@ use crate::{ use indexmap::IndexMap; use std::cell::RefCell; use std::collections::hash_map::Entry; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::hash::Hasher as _; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -48,6 +48,13 @@ struct RuntimeContexts { prisma_typegen_cache: Rc>>, } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum NameSource { + User, + PrismaTypeGen, + Substantial, +} + #[derive(Default)] pub struct TypegraphContext { name: String, @@ -60,7 +67,7 @@ pub struct TypegraphContext { mapping: IdMapping, runtime_contexts: RuntimeContexts, saved_store_state: Option, - user_named_types: HashSet, + named_types: HashMap, } thread_local! { @@ -235,13 +242,27 @@ pub fn serialize(params: SerializeParams) -> Result<(String, Vec)> // dedup_types(&mut tg); + tracing::info!("postprocessing typegraph..."); + TypegraphPostProcessor::new(params).postprocess(&mut tg)?; NamingProcessor { - user_named: ctx.user_named_types, + named_types: &ctx.named_types, } .postprocess(&mut tg)?; - let tg = tg_optimize::optimize(tg.into()); + tracing::info!("optimizing typegraph..."); + + let tg = tg_optimize::OptimizeOptions::default() + .preserve( + ctx.named_types + .iter() + .filter_map(|(idx, s)| match s { + NameSource::User => Some(*idx), + _ => None, + }) + .collect(), + ) + .optimize(tg.into()); let artifacts = tg .meta @@ -369,12 +390,17 @@ impl TypegraphContext { // we remove the name before hashing if it's not // user named let xdef = type_id.as_xdef()?; - let is_user_named = if let Some(name) = xdef.name.as_deref() { - Store::is_user_named(name).unwrap_or(false) - } else { - false - }; - let xdef = type_id.as_xdef()?; + let name_source = + xdef.name + .as_deref() + .and_then(Store::get_type_by_name) + .map(|named_type| { + if named_type.name_source == NameSource::User { + NameSource::User + } else { + NameSource::PrismaTypeGen + } + }); let hash = self.hash_type(type_id)?; match self.mapping.hash_to_type.entry(hash) { @@ -393,8 +419,8 @@ impl TypegraphContext { let type_node = xdef.type_def.clone().convert(self, xdef)?; self.types[idx] = Some(type_node); - if is_user_named { - self.user_named_types.insert(idx as u32); + if let Some(name_source) = name_source { + self.named_types.insert(idx as u32, name_source); } Ok((idx as u32).into()) diff --git a/src/typegraph/core/src/types/type_ref.rs b/src/typegraph/core/src/types/type_ref.rs index 8514220590..d117b5c618 100644 --- a/src/typegraph/core/src/types/type_ref.rs +++ b/src/typegraph/core/src/types/type_ref.rs @@ -7,6 +7,7 @@ use std::rc::Rc; use super::Type; use crate::errors::Result; use crate::global_store::Store; +use crate::typegraph::NameSource; use crate::types::{TypeDef, TypeDefExt as _, TypeId}; use serde::{Deserialize, Serialize}; use tg_schema::Injection; @@ -78,6 +79,7 @@ pub struct NamedTypeRef { pub id: TypeId, pub name: Rc, pub target: Box, + pub name_source: NameSource, } #[derive(Clone, Debug)] @@ -110,6 +112,7 @@ pub struct IndirectRefBuilder { pub struct NamedRefBuilder { pub name: Rc, target: Type, + name_source: NameSource, } pub enum FlatTypeRefTarget { @@ -207,11 +210,12 @@ impl TypeRef { attributes: attributes.into_iter().map(Rc::new).collect(), }) } - pub fn named(name: impl Into, target: Type) -> TypeRefBuilder { + pub fn named(name: impl Into, target: Type, name_source: NameSource) -> TypeRefBuilder { let name: String = name.into(); TypeRefBuilder::Named(NamedRefBuilder { name: name.into(), target, + name_source, }) } } @@ -238,6 +242,7 @@ impl TypeRefBuilder { id, name: builder.name, target: Box::new(builder.target), + name_source: builder.name_source, }), } } @@ -370,7 +375,7 @@ impl FindAttribute for RefAttrs { } pub trait Named { - fn named(self, name: impl Into) -> Result; + fn named(self, name: impl Into, name_source: NameSource) -> Result; } impl Named for T @@ -378,7 +383,7 @@ where T: TryInto, crate::errors::TgError: From<>::Error>, { - fn named(self, name: impl Into) -> Result { - TypeRef::named(name, self.try_into()?).register() + fn named(self, name: impl Into, name_source: NameSource) -> Result { + TypeRef::named(name, self.try_into()?, name_source).register() } } diff --git a/src/typegraph/core/src/types/type_ref/xdef.rs b/src/typegraph/core/src/types/type_ref/xdef.rs index 613c5c9635..7c11ba9f0f 100644 --- a/src/typegraph/core/src/types/type_ref/xdef.rs +++ b/src/typegraph/core/src/types/type_ref/xdef.rs @@ -27,7 +27,7 @@ impl ExtendedTypeDef { hasher: &mut crate::conversion::hash::Hasher, tg: &mut TypegraphContext, ) -> Result<()> { - if let Some(name) = self.name.as_deref() { + if let Some(name) = self.name.as_ref() { "named".hash(hasher); name.hash(hasher); return Ok(()); diff --git a/src/typegraph/core/src/utils/postprocess/naming.rs b/src/typegraph/core/src/utils/postprocess/naming.rs index 722b6cbb3c..f12345d938 100644 --- a/src/typegraph/core/src/utils/postprocess/naming.rs +++ b/src/typegraph/core/src/utils/postprocess/naming.rs @@ -13,16 +13,16 @@ use tg_schema::{ StringFormat, TypeNode, Typegraph, }; -use crate::errors::TgError; +use crate::{errors::TgError, typegraph::NameSource}; -pub struct NamingProcessor { - pub user_named: HashSet, +pub struct NamingProcessor<'un> { + pub named_types: &'un HashMap, } -impl super::PostProcessor for NamingProcessor { +impl<'un> super::PostProcessor for NamingProcessor<'un> { fn postprocess(self, tg: &mut tg_schema::Typegraph) -> Result<(), crate::errors::TgError> { let cx = VisitContext { tg, - user_named: self.user_named, + named_types: self.named_types.keys().cloned().collect(), }; let TypeNode::Object { @@ -64,9 +64,9 @@ impl super::PostProcessor for NamingProcessor { } } -struct VisitContext<'a> { - tg: &'a Typegraph, - user_named: HashSet, +struct VisitContext<'tg> { + tg: &'tg Typegraph, + named_types: HashSet, } struct VisitCollector { named_types: HashMap>, @@ -262,7 +262,7 @@ fn collect_ref_info( id: u32, visited: &mut HashSet, ) -> anyhow::Result<()> { - if cx.user_named.contains(&id) || visited.contains(&id) { + if cx.named_types.contains(&id) || visited.contains(&id) { return Ok(()); } @@ -320,7 +320,7 @@ fn collect_ref_info( fn gen_name(cx: &VisitContext, acc: &mut VisitCollector, id: u32, ty_name: &str) -> Rc { let node = &cx.tg.types[id as usize]; - let name: Rc = if cx.user_named.contains(&id) { + let name: Rc = if cx.named_types.contains(&id) { node.base().title.clone().into() } else { macro_rules! join_if_ok { diff --git a/src/typegraph/optimize/src/dedup.rs b/src/typegraph/optimize/src/dedup.rs index 7dd7897517..d283143c37 100644 --- a/src/typegraph/optimize/src/dedup.rs +++ b/src/typegraph/optimize/src/dedup.rs @@ -7,7 +7,7 @@ use std::{ sync::Arc, }; use tg_schema::{ - runtimes::{KnownRuntime, TGRuntime}, + runtimes::{prisma::Property, KnownRuntime, TGRuntime}, TypeNode, Typegraph, }; @@ -197,7 +197,23 @@ impl DedupEngine { for rt in &mut runtimes { if let TGRuntime::Known(KnownRuntime::Prisma(d)) = rt { for m in &mut d.models { - map.update(&mut m.type_idx) + map.update(&mut m.type_idx); + + for prop in &mut m.props { + match prop { + Property::Scalar(scalar_prop) => { + map.update(&mut scalar_prop.type_idx); + } + Property::Relationship(rel_prop) => { + map.update(&mut rel_prop.type_idx); + } + } + } + } + + for rel in &mut d.relationships { + map.update(&mut rel.left.type_idx); + map.update(&mut rel.right.type_idx); } } } diff --git a/src/typegraph/optimize/src/lib.rs b/src/typegraph/optimize/src/lib.rs index 7dd35aa7d5..9b6131acab 100644 --- a/src/typegraph/optimize/src/lib.rs +++ b/src/typegraph/optimize/src/lib.rs @@ -15,7 +15,10 @@ mod dedup; mod kosaraju; -use std::{collections::BTreeMap, sync::Arc}; +use std::{ + collections::{BTreeMap, HashSet}, + sync::Arc, +}; use kosaraju::Kosaraju; use tg_schema::{TypeNode, Typegraph}; @@ -40,18 +43,30 @@ impl TypeIdx { } } -pub fn optimize(tg: Arc) -> Typegraph { - let mut k = Kosaraju::new(tg); - k.run(); +#[derive(Default)] +pub struct OptimizeOptions { + preserved_types: HashSet, +} - let mut sizes = BTreeMap::new(); - for c in &k.components { - sizes.entry(c.1.len()).and_modify(|l| *l += 1).or_insert(1); +impl OptimizeOptions { + pub fn preserve(mut self, preserved_types: HashSet) -> Self { + self.preserved_types = preserved_types; + self } - let mut dedup = crate::dedup::DedupEngine::from(k); - dedup.hash_types(); - dedup.get_converted_typegraph() + pub fn optimize(&self, tg: Arc) -> Typegraph { + let mut k = Kosaraju::new(tg); + k.run(); + + let mut sizes = BTreeMap::new(); + for c in &k.components { + sizes.entry(c.1.len()).and_modify(|l| *l += 1).or_insert(1); + } + + let mut dedup = crate::dedup::DedupEngine::from(k); + dedup.hash_types(); + dedup.get_converted_typegraph() + } } trait DirectedGraph { diff --git a/src/typegraph/optimize/src/main.rs b/src/typegraph/optimize/src/main.rs index 0acf3f7b33..7fa220a334 100644 --- a/src/typegraph/optimize/src/main.rs +++ b/src/typegraph/optimize/src/main.rs @@ -9,7 +9,7 @@ fn main() -> color_eyre::eyre::Result<()> { let mut buffer = String::new(); std::io::stdin().read_line(&mut buffer)?; let tg: Typegraph = serde_json::from_str(&buffer)?; - let opt_tg = tg_optimize::optimize(Arc::new(tg)); + let opt_tg = tg_optimize::OptimizeOptions::default().optimize(Arc::new(tg)); println!("{}", serde_json::to_string(&opt_tg)?); Ok(()) diff --git a/src/typegraph/schema/src/types.rs b/src/typegraph/schema/src/types.rs index 209efebd18..ae6d243e13 100644 --- a/src/typegraph/schema/src/types.rs +++ b/src/typegraph/schema/src/types.rs @@ -62,6 +62,7 @@ pub enum Injection { #[skip_serializing_none] #[derive(Serialize, Deserialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] pub struct TypeNodeBase { pub title: String, #[serde(default)] diff --git a/tests/prisma-migrations/migration-failure-test-dev/main/20250430193822_generated/migration.sql b/tests/prisma-migrations/migration-failure-test-dev/main/20250618092719_generated/migration.sql similarity index 100% rename from tests/prisma-migrations/migration-failure-test-dev/main/20250430193822_generated/migration.sql rename to tests/prisma-migrations/migration-failure-test-dev/main/20250618092719_generated/migration.sql diff --git a/tools/tasks/test.ts b/tools/tasks/test.ts index b0838e466e..c83a9681c2 100644 --- a/tools/tasks/test.ts +++ b/tools/tasks/test.ts @@ -8,6 +8,9 @@ export default { "test-e2e": { inherit: "ci", desc: "Shorthand for `tools/test.ts`", + vars: { + MCLI_NO_UPGRADE_CHECK: "1", + }, fn: async ($) => { if ((await testE2eCli($.argv)) != 0) { throw new Error("tests failed"); diff --git a/tools/verdaccio/config.yaml b/tools/verdaccio/config.yaml deleted file mode 100644 index 19ed888dd3..0000000000 --- a/tools/verdaccio/config.yaml +++ /dev/null @@ -1,22 +0,0 @@ -storage: ../storage -uplinks: - npmjs: - url: https://registry.npmjs.org/ -packages: - '@typegraph/*': - access: $all - publish: $all - # proxy: npmjs - '@*/*': - access: $all - publish: $authenticated - proxy: npmjs - '**': - access: $all - publish: $authenticated - proxy: npmjs -log: - type: stdout - format: pretty - level: http -max_body_size: 100mb