diff --git a/bun.lock b/bun.lock index d052703..0b70d82 100644 --- a/bun.lock +++ b/bun.lock @@ -5,7 +5,7 @@ "": { "name": "graphy", "dependencies": { - "@anthropic-ai/sdk": "^0.96.0", + "@anthropic-ai/sdk": "^0.97.0", "@base-ui/react": "^1.4.1", "@codemirror/autocomplete": "^6.20.2", "@codemirror/commands": "^6.10.3", @@ -15,8 +15,7 @@ "@codemirror/theme-one-dark": "^6.1.3", "@codemirror/view": "^6.43.0", "@fontsource-variable/geist": "^5.2.9", - "@openai/codex-sdk": "^0.130.0", - "@tabler/icons-react": "^3.44.0", + "@openai/codex-sdk": "^0.131.0", "@tailwindcss/vite": "^4.3.0", "@tanstack/react-devtools": "^0.10.5", "@tanstack/react-router": "^1.170.4", @@ -28,21 +27,14 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", - "codemirror": "^6.0.2", - "date-fns": "^4.2.1", - "elkjs": "^0.11.1", - "embla-carousel-react": "^8.6.0", - "input-otp": "^1.4.2", "lucide-react": "^1.16.0", "next-themes": "^0.4.6", - "nitro": "npm:nitro-nightly@^3.0.1-20260512-093145-0498ce70", + "nitro": "npm:nitro-nightly@^3.0.1-20260518-130639-31265391", "radix-ui": "^1.4.3", "react": "^19.2.6", - "react-day-picker": "^10.0.1", "react-dom": "^19.2.6", "react-markdown": "^10.1.0", "react-resizable-panels": "^4.11.1", - "recharts": "3.8.0", "remark-gfm": "^4.0.1", "shadcn": "^4.7.0", "simple-git": "^3.36.0", @@ -51,13 +43,12 @@ "tailwindcss": "^4.3.0", "ts-morph": "^28.0.0", "tw-animate-css": "^1.4.0", - "vaul": "^1.1.2", }, "devDependencies": { "@tailwindcss/typography": "^0.5.19", "@tanstack/devtools-vite": "^0.7.0", "@tanstack/eslint-config": "^0.4.0", - "@types/node": "^25.8.0", + "@types/node": "^25.9.0", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^6.0.2", @@ -65,13 +56,13 @@ "concurrently": "^9.2.1", "cross-env": "^10.1.0", "electron": "^42.1.0", - "electron-builder": "^25.1.8", - "eslint": "^9.20.0", - "jsdom": "^28.1.0", - "prettier": "^3.8.1", - "typescript": "^6.0.2", - "vite": "^8.0.0", - "vitest": "^4.1.5", + "electron-builder": "^26.8.1", + "eslint": "^10.4.0", + "jsdom": "^29.1.1", + "prettier": "^3.8.3", + "typescript": "^6.0.3", + "vite": "^8.0.13", + "vitest": "^4.1.6", "wait-on": "^9.0.10", }, }, @@ -79,13 +70,11 @@ "packages": { "7zip-bin": ["7zip-bin@5.2.0", "", {}, "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A=="], - "@acemir/cssom": ["@acemir/cssom@0.9.31", "", {}, "sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA=="], - - "@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.96.0", "", { "dependencies": { "json-schema-to-ts": "^3.1.1", "standardwebhooks": "^1.0.0" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-KlCsODtTyb17bLUVCSDC2HtSvAbJf60sEiPEax9dInF+aDF92vS4TZJ5XD7YCQXNb1/5icYaw8Y7wMjPlIV9Zg=="], + "@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.97.0", "", { "dependencies": { "json-schema-to-ts": "^3.1.1", "standardwebhooks": "^1.0.0" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-124Ebx14aEFlyr2/wRtQjcQ3IRbuON6GgoRKEPGffVV0Nu5DCXs7nlkocVQ4NLI8MxDT+7ezXCwRWXoBpWEuVw=="], "@asamuzakjp/css-color": ["@asamuzakjp/css-color@5.1.11", "", { "dependencies": { "@asamuzakjp/generational-cache": "^1.0.1", "@csstools/css-calc": "^3.2.0", "@csstools/css-color-parser": "^4.1.0", "@csstools/css-parser-algorithms": "^4.0.0", "@csstools/css-tokenizer": "^4.0.0" } }, "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg=="], - "@asamuzakjp/dom-selector": ["@asamuzakjp/dom-selector@6.8.1", "", { "dependencies": { "@asamuzakjp/nwsapi": "^2.3.9", "bidi-js": "^1.0.3", "css-tree": "^3.1.0", "is-potential-custom-element-name": "^1.0.1", "lru-cache": "^11.2.6" } }, "sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ=="], + "@asamuzakjp/dom-selector": ["@asamuzakjp/dom-selector@7.1.1", "", { "dependencies": { "@asamuzakjp/generational-cache": "^1.0.1", "@asamuzakjp/nwsapi": "^2.3.9", "bidi-js": "^1.0.3", "css-tree": "^3.2.1", "is-potential-custom-element-name": "^1.0.1" } }, "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ=="], "@asamuzakjp/generational-cache": ["@asamuzakjp/generational-cache@1.0.1", "", {}, "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg=="], @@ -165,8 +154,6 @@ "@codemirror/lint": ["@codemirror/lint@6.9.6", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.42.0", "crelt": "^1.0.5" } }, "sha512-6Kp7r6XfCi/D/5sdXieMfg9pJU1bUEx96WITuLU6ESaKizCz0QHFMjY/TaFSbigDdEAIgi93itLBIUETP4oK+A=="], - "@codemirror/search": ["@codemirror/search@6.7.0", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.37.0", "crelt": "^1.0.5" } }, "sha512-ZvGm99wc/s2cITtMT15LFdn8aH/aS+V+DqyGq/N5ZlV5vWtH+nILvC2nw0zX7ByNoHHDZ2IxxdW38O0tc5nVHg=="], - "@codemirror/state": ["@codemirror/state@6.6.0", "", { "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } }, "sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ=="], "@codemirror/theme-one-dark": ["@codemirror/theme-one-dark@6.1.3", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "@lezer/highlight": "^1.0.0" } }, "sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA=="], @@ -195,15 +182,17 @@ "@electron/asar": ["@electron/asar@3.4.1", "", { "dependencies": { "commander": "^5.0.0", "glob": "^7.1.6", "minimatch": "^3.0.4" }, "bin": { "asar": "bin/asar.js" } }, "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA=="], + "@electron/fuses": ["@electron/fuses@1.8.0", "", { "dependencies": { "chalk": "^4.1.1", "fs-extra": "^9.0.1", "minimist": "^1.2.5" }, "bin": { "electron-fuses": "dist/bin.js" } }, "sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw=="], + "@electron/get": ["@electron/get@5.0.0", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^3.0.0", "graceful-fs": "^4.2.11", "progress": "^2.0.3", "semver": "^7.6.3", "sumchecker": "^3.0.1" }, "optionalDependencies": { "undici": "^7.24.4" } }, "sha512-pjoBpru1KdEtcExBnuHAP1cAc/5faoedw0hzJkL3o4/IJp7HNF1+fbrdxT3gMYRX2oJfvnA/WXeCTVQpYYxyJA=="], "@electron/notarize": ["@electron/notarize@2.5.0", "", { "dependencies": { "debug": "^4.1.1", "fs-extra": "^9.0.1", "promise-retry": "^2.0.1" } }, "sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A=="], - "@electron/osx-sign": ["@electron/osx-sign@1.3.1", "", { "dependencies": { "compare-version": "^0.1.2", "debug": "^4.3.4", "fs-extra": "^10.0.0", "isbinaryfile": "^4.0.8", "minimist": "^1.2.6", "plist": "^3.0.5" }, "bin": { "electron-osx-flat": "bin/electron-osx-flat.js", "electron-osx-sign": "bin/electron-osx-sign.js" } }, "sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw=="], + "@electron/osx-sign": ["@electron/osx-sign@1.3.3", "", { "dependencies": { "compare-version": "^0.1.2", "debug": "^4.3.4", "fs-extra": "^10.0.0", "isbinaryfile": "^4.0.8", "minimist": "^1.2.6", "plist": "^3.0.5" }, "bin": { "electron-osx-flat": "bin/electron-osx-flat.js", "electron-osx-sign": "bin/electron-osx-sign.js" } }, "sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg=="], - "@electron/rebuild": ["@electron/rebuild@3.6.1", "", { "dependencies": { "@malept/cross-spawn-promise": "^2.0.0", "chalk": "^4.0.0", "debug": "^4.1.1", "detect-libc": "^2.0.1", "fs-extra": "^10.0.0", "got": "^11.7.0", "node-abi": "^3.45.0", "node-api-version": "^0.2.0", "node-gyp": "^9.0.0", "ora": "^5.1.0", "read-binary-file-arch": "^1.0.6", "semver": "^7.3.5", "tar": "^6.0.5", "yargs": "^17.0.1" }, "bin": { "electron-rebuild": "lib/cli.js" } }, "sha512-f6596ZHpEq/YskUd8emYvOUne89ij8mQgjYFA5ru25QwbrRO+t1SImofdDv7kKOuWCmVOuU5tvfkbgGxIl3E/w=="], + "@electron/rebuild": ["@electron/rebuild@4.0.4", "", { "dependencies": { "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.1.1", "node-abi": "^4.2.0", "node-api-version": "^0.2.1", "node-gyp": "^12.2.0", "read-binary-file-arch": "^1.0.6" }, "bin": { "electron-rebuild": "lib/cli.js" } }, "sha512-Rzc39XPdk/+/wBG8MfwAHohXflep0ITUfulb6Rgz3R0NeSB1noE+E9/M/cb8ftCAiyDD9PPhLuuWgE1GaInbKg=="], - "@electron/universal": ["@electron/universal@2.0.1", "", { "dependencies": { "@electron/asar": "^3.2.7", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", "dir-compare": "^4.2.0", "fs-extra": "^11.1.1", "minimatch": "^9.0.3", "plist": "^3.1.0" } }, "sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA=="], + "@electron/universal": ["@electron/universal@2.0.3", "", { "dependencies": { "@electron/asar": "^3.3.1", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", "dir-compare": "^4.2.0", "fs-extra": "^11.1.1", "minimatch": "^9.0.3", "plist": "^3.1.0" } }, "sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g=="], "@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="], @@ -217,19 +206,17 @@ "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], - "@eslint/config-array": ["@eslint/config-array@0.21.2", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.5" } }, "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw=="], - - "@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="], + "@eslint/config-array": ["@eslint/config-array@0.23.5", "", { "dependencies": { "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA=="], - "@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="], + "@eslint/config-helpers": ["@eslint/config-helpers@0.6.0", "", { "dependencies": { "@eslint/core": "^1.2.1" } }, "sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA=="], - "@eslint/eslintrc": ["@eslint/eslintrc@3.3.5", "", { "dependencies": { "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" } }, "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg=="], + "@eslint/core": ["@eslint/core@1.2.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ=="], "@eslint/js": ["@eslint/js@10.0.1", "", { "peerDependencies": { "eslint": "^10.0.0" }, "optionalPeers": ["eslint"] }, "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA=="], - "@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="], + "@eslint/object-schema": ["@eslint/object-schema@3.0.5", "", {}, "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw=="], - "@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="], + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.7.1", "", { "dependencies": { "@eslint/core": "^1.2.1", "levn": "^0.4.1" } }, "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ=="], "@exodus/bytes": ["@exodus/bytes@1.15.0", "", { "peerDependencies": { "@noble/hashes": "^1.8.0 || ^2.0.0" }, "optionalPeers": ["@noble/hashes"] }, "sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ=="], @@ -281,6 +268,8 @@ "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="], + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], @@ -345,21 +334,21 @@ "@open-draft/until": ["@open-draft/until@2.1.0", "", {}, "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg=="], - "@openai/codex": ["@openai/codex@0.130.0", "", { "optionalDependencies": { "@openai/codex-darwin-arm64": "npm:@openai/codex@0.130.0-darwin-arm64", "@openai/codex-darwin-x64": "npm:@openai/codex@0.130.0-darwin-x64", "@openai/codex-linux-arm64": "npm:@openai/codex@0.130.0-linux-arm64", "@openai/codex-linux-x64": "npm:@openai/codex@0.130.0-linux-x64", "@openai/codex-win32-arm64": "npm:@openai/codex@0.130.0-win32-arm64", "@openai/codex-win32-x64": "npm:@openai/codex@0.130.0-win32-x64" }, "bin": { "codex": "bin/codex.js" } }, "sha512-WGDj+RZ3TXWC/7MlwprgLWOqzpwatPIINPhP3IRzHA0ni+o3QZ4i4xrS2uWwGmHUJ395J5JHwoZAAZYyfJyz6w=="], + "@openai/codex": ["@openai/codex@0.131.0", "", { "optionalDependencies": { "@openai/codex-darwin-arm64": "npm:@openai/codex@0.131.0-darwin-arm64", "@openai/codex-darwin-x64": "npm:@openai/codex@0.131.0-darwin-x64", "@openai/codex-linux-arm64": "npm:@openai/codex@0.131.0-linux-arm64", "@openai/codex-linux-x64": "npm:@openai/codex@0.131.0-linux-x64", "@openai/codex-win32-arm64": "npm:@openai/codex@0.131.0-win32-arm64", "@openai/codex-win32-x64": "npm:@openai/codex@0.131.0-win32-x64" }, "bin": { "codex": "bin/codex.js" } }, "sha512-5/fNFAotnPaNSX1jGAAGgWk65HGZupWPnka+DzXdoNzl78RGw0eGpOjpowF+dtPRTEvdwt0U8qoptUjtefitBQ=="], - "@openai/codex-darwin-arm64": ["@openai/codex@0.130.0-darwin-arm64", "", { "os": "darwin", "cpu": "arm64" }, "sha512-R9pkGC7kwC8yQ8el5hvBlmugQlcsG/pHMEFgZluu03X9fD2TezGxdq3KqRDRCZuMYl07ILamVEoqknuJ0cq7MA=="], + "@openai/codex-darwin-arm64": ["@openai/codex@0.131.0-darwin-arm64", "", { "os": "darwin", "cpu": "arm64" }, "sha512-e4EZ7XjK1zrkW65nZdhCqQFVKd/zt/of26w4L32wcfibzKE15/Lw2i3FGTD9ufUUqVzF+gowu/lEiBRvDoh21w=="], - "@openai/codex-darwin-x64": ["@openai/codex@0.130.0-darwin-x64", "", { "os": "darwin", "cpu": "x64" }, "sha512-gJ+7J8djevgtdra+NgDAiQQPW+O3KTsgGfE3E5dpDfww3zS5OCeV0V2dhxqnJdlOjOSDw99o0P2LqBv19mhpRw=="], + "@openai/codex-darwin-x64": ["@openai/codex@0.131.0-darwin-x64", "", { "os": "darwin", "cpu": "x64" }, "sha512-BkFwUVU+yJhw5a85p1oagiSjkRvBs9Xp1b1q1Qbvg4Y9Chtatj4SjI7HRjH5uespNs/Wnh48cMnTsxkAILqlBw=="], - "@openai/codex-linux-arm64": ["@openai/codex@0.130.0-linux-arm64", "", { "os": "linux", "cpu": "arm64" }, "sha512-tFtH0V9/hEI3d9y7zP92BXI9FM4Z3+STNQaOR52Czv18TRtCFUp7CbIUYaToopuq6UBfnE1VKr8RLhwT5FcbmA=="], + "@openai/codex-linux-arm64": ["@openai/codex@0.131.0-linux-arm64", "", { "os": "linux", "cpu": "arm64" }, "sha512-I12Ou5I5oR/nfUyMJ/D95OMm83HoXMBHdl+4YrPay/XGd9KkyMhvZxp9Es/h9x/xt8yiBIk+k0Ehtr093r8AFw=="], - "@openai/codex-linux-x64": ["@openai/codex@0.130.0-linux-x64", "", { "os": "linux", "cpu": "x64" }, "sha512-3VcNlez99xdnEf+kB1IOpWv9fICYV9PiGj4sLCO4TCcShLnyxe+YBGa3poknkvXLnMG0qiN9SMnYS2FGrMxQcA=="], + "@openai/codex-linux-x64": ["@openai/codex@0.131.0-linux-x64", "", { "os": "linux", "cpu": "x64" }, "sha512-Fj9P7h3iBgjAQKzoEyUkb1Q8QMVLqaf62UzlL1jYeDhIzbDMI/gaV0tOackIGXPcfguzzORJC1g5pD9SMWqU5g=="], - "@openai/codex-sdk": ["@openai/codex-sdk@0.130.0", "", { "dependencies": { "@openai/codex": "0.130.0" } }, "sha512-ICKaZ5zrIDg71AiQcsUToVoe5Icmrc3LwSM5+2z7Cf8F1x6nOaY7/ucpFlr4aH8oDe7t3dangc+MsWZTkdvDFw=="], + "@openai/codex-sdk": ["@openai/codex-sdk@0.131.0", "", { "dependencies": { "@openai/codex": "0.131.0" } }, "sha512-fSIJKPGkxVsKu5TsU9pcCvGfYxiPLtfuJOkuk9VIqeZHQwlhVByZ8MVTiBhsd4mr5hxgyeyPSiofUONULdaPWQ=="], - "@openai/codex-win32-arm64": ["@openai/codex@0.130.0-win32-arm64", "", { "os": "win32", "cpu": "arm64" }, "sha512-vdpmiNp57L/arZabltLXn8TyEtNa7W1meOEkr+3R6W/8ZyBt++wuqz1Orv134OT2grrcFJsIVCAIPiqUxCvBkA=="], + "@openai/codex-win32-arm64": ["@openai/codex@0.131.0-win32-arm64", "", { "os": "win32", "cpu": "arm64" }, "sha512-aGXsk8GYNFCjHYH61mVG0PulheBq6ZxZWM2BLYAJabzGarzRQpPknc60mx8mSm93BebjPkX0Wpf+0qInBPbF0w=="], - "@openai/codex-win32-x64": ["@openai/codex@0.130.0-win32-x64", "", { "os": "win32", "cpu": "x64" }, "sha512-FzMznm7fr5/nbjZgOujZ9Y9AbdGm7ji1FOoWiY3U+srqauvZaTgn6o6aCheSL7kuymu7nTLOO/cAyWV6NuesqQ=="], + "@openai/codex-win32-x64": ["@openai/codex@0.131.0-win32-x64", "", { "os": "win32", "cpu": "x64" }, "sha512-RlIRs0hi6xIaBXWFhiPTPlz+Dfibc3pXrnVXjJtpbeYcNyBOO+SIMMVuQUswpz3RnJpsxA70dQA+05hKYraKhA=="], "@oxc-parser/binding-android-arm-eabi": ["@oxc-parser/binding-android-arm-eabi@0.120.0", "", { "os": "android", "cpu": "arm" }, "sha512-WU3qtINx802wOl8RxAF1v0VvmC2O4D9M8Sv486nLeQ7iPHVmncYZrtBhB4SYyX+XZxj2PNnCcN+PW21jHgiOxg=="], @@ -473,7 +462,7 @@ "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="], - "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="], + "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], "@radix-ui/react-progress": ["@radix-ui/react-progress@1.1.7", "", { "dependencies": { "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg=="], @@ -527,8 +516,6 @@ "@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="], - "@reduxjs/toolkit": ["@reduxjs/toolkit@2.12.0", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@standard-schema/utils": "^0.3.0", "immer": "^11.0.0", "redux": "^5.0.1", "redux-thunk": "^3.1.0", "reselect": "^5.1.0" }, "peerDependencies": { "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" }, "optionalPeers": ["react", "react-redux"] }, "sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw=="], - "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.1", "", { "os": "android", "cpu": "arm64" }, "sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg=="], "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg=="], @@ -587,16 +574,10 @@ "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], - "@standard-schema/utils": ["@standard-schema/utils@0.3.0", "", {}, "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g=="], - "@stylistic/eslint-plugin": ["@stylistic/eslint-plugin@5.10.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/types": "^8.56.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "estraverse": "^5.3.0", "picomatch": "^4.0.3" }, "peerDependencies": { "eslint": "^9.0.0 || ^10.0.0" } }, "sha512-nPK52ZHvot8Ju/0A4ucSX1dcPV2/1clx0kLcH5wDmrE4naKso7TUC/voUyU1O9OTKTrR6MYip6LP0ogEMQ9jPQ=="], "@szmarczak/http-timer": ["@szmarczak/http-timer@4.0.6", "", { "dependencies": { "defer-to-connect": "^2.0.0" } }, "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w=="], - "@tabler/icons": ["@tabler/icons@3.44.0", "", {}, "sha512-Wn0AOZG9sg0L+bjfMqq4eNhC6pQjIrk94LvvWYNYkY8KH8wC3YILRzQlrnVJc4FUeMxH/AK97QsYCX35H3LndA=="], - - "@tabler/icons-react": ["@tabler/icons-react@3.44.0", "", { "dependencies": { "@tabler/icons": "3.44.0" }, "peerDependencies": { "react": ">= 16" } }, "sha512-8+rvzBbVm/1Z3sG3x7GUNAaxIKxwgz8xaMhRs23nrCnMTKRFAhEC+82zAIFeAA0seXdrAGX5HFCkaLpGK2rVHg=="], - "@tailwindcss/node": ["@tailwindcss/node@4.3.0", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.21.0", "jiti": "^2.6.1", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.3.0" } }, "sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g=="], "@tailwindcss/oxide": ["@tailwindcss/oxide@4.3.0", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.3.0", "@tailwindcss/oxide-darwin-arm64": "4.3.0", "@tailwindcss/oxide-darwin-x64": "4.3.0", "@tailwindcss/oxide-freebsd-x64": "4.3.0", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.0", "@tailwindcss/oxide-linux-arm64-gnu": "4.3.0", "@tailwindcss/oxide-linux-arm64-musl": "4.3.0", "@tailwindcss/oxide-linux-x64-gnu": "4.3.0", "@tailwindcss/oxide-linux-x64-musl": "4.3.0", "@tailwindcss/oxide-wasm32-wasi": "4.3.0", "@tailwindcss/oxide-win32-arm64-msvc": "4.3.0", "@tailwindcss/oxide-win32-x64-msvc": "4.3.0" } }, "sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg=="], @@ -703,28 +684,14 @@ "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], - "@types/d3-array": ["@types/d3-array@3.2.2", "", {}, "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw=="], - "@types/d3-color": ["@types/d3-color@3.1.3", "", {}, "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="], "@types/d3-drag": ["@types/d3-drag@3.0.7", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ=="], - "@types/d3-ease": ["@types/d3-ease@3.0.2", "", {}, "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="], - "@types/d3-interpolate": ["@types/d3-interpolate@3.0.4", "", { "dependencies": { "@types/d3-color": "*" } }, "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA=="], - "@types/d3-path": ["@types/d3-path@3.1.1", "", {}, "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg=="], - - "@types/d3-scale": ["@types/d3-scale@4.0.9", "", { "dependencies": { "@types/d3-time": "*" } }, "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw=="], - "@types/d3-selection": ["@types/d3-selection@3.0.11", "", {}, "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w=="], - "@types/d3-shape": ["@types/d3-shape@3.1.8", "", { "dependencies": { "@types/d3-path": "*" } }, "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w=="], - - "@types/d3-time": ["@types/d3-time@3.0.4", "", {}, "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="], - - "@types/d3-timer": ["@types/d3-timer@3.0.2", "", {}, "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="], - "@types/d3-transition": ["@types/d3-transition@3.0.9", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg=="], "@types/d3-zoom": ["@types/d3-zoom@3.0.8", "", { "dependencies": { "@types/d3-interpolate": "*", "@types/d3-selection": "*" } }, "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw=="], @@ -733,6 +700,8 @@ "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="], + "@types/esrecurse": ["@types/esrecurse@4.3.1", "", {}, "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw=="], + "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="], "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="], @@ -751,7 +720,7 @@ "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], - "@types/node": ["@types/node@25.8.0", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ=="], + "@types/node": ["@types/node@25.9.0", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-AOQwYUNolgy3VosiRqXrACUXTN8nJUtPl7FJXMqZVyxiiCLhQuG3jXKvCS1ALr+Y2OmZhzzLVlYPEqJaiqkaJQ=="], "@types/plist": ["@types/plist@3.0.5", "", { "dependencies": { "@types/node": "*", "xmlbuilder": ">=11.0.1" } }, "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA=="], @@ -767,8 +736,6 @@ "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], - "@types/use-sync-external-store": ["@types/use-sync-external-store@0.0.6", "", {}, "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg=="], - "@types/validate-npm-package-name": ["@types/validate-npm-package-name@4.0.2", "", {}, "sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw=="], "@types/verror": ["@types/verror@1.10.11", "", {}, "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg=="], @@ -851,13 +818,13 @@ "@vitest/utils": ["@vitest/utils@4.1.6", "", { "dependencies": { "@vitest/pretty-format": "4.1.6", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-FxIY+U81R3LGKCxaHHFRQ5+g6/iRgGLmeHWdp2Amj4ljQRrEIWHmZyDfDYBRZlpyqA7qKxtS9DD1dhk8RnRIVQ=="], - "@xmldom/xmldom": ["@xmldom/xmldom@0.9.10", "", {}, "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw=="], + "@xmldom/xmldom": ["@xmldom/xmldom@0.8.13", "", {}, "sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw=="], "@xyflow/react": ["@xyflow/react@12.10.2", "", { "dependencies": { "@xyflow/system": "0.0.76", "classcat": "^5.0.3", "zustand": "^4.4.0" }, "peerDependencies": { "react": ">=17", "react-dom": ">=17" } }, "sha512-CgIi6HwlcHXwlkTpr0fxLv/0sRVNZ8IdwKLzzeCscaYBwpvfcH1QFOCeaTCuEn1FQEs/B8CjnTSjhs8udgmBgQ=="], "@xyflow/system": ["@xyflow/system@0.0.76", "", { "dependencies": { "@types/d3-drag": "^3.0.7", "@types/d3-interpolate": "^3.0.4", "@types/d3-selection": "^3.0.10", "@types/d3-transition": "^3.0.8", "@types/d3-zoom": "^3.0.8", "d3-drag": "^3.0.0", "d3-interpolate": "^3.0.1", "d3-selection": "^3.0.0", "d3-zoom": "^3.0.0" } }, "sha512-hvwvnRS1B3REwVDlWexsq7YQaPZeG3/mKo1jv38UmnpWmxihp14bW6VtEOuHEwJX2FvzFw8k77LyKSk/wiZVNA=="], - "abbrev": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="], + "abbrev": ["abbrev@4.0.0", "", {}, "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA=="], "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], @@ -885,9 +852,9 @@ "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], - "app-builder-bin": ["app-builder-bin@5.0.0-alpha.10", "", {}, "sha512-Ev4jj3D7Bo+O0GPD2NMvJl+PGiBAfS7pUGawntBNpCbxtpncfUixqFj9z9Jme7V7s3LBGqsWZZP54fxBX3JKJw=="], + "app-builder-bin": ["app-builder-bin@5.0.0-alpha.12", "", {}, "sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w=="], - "app-builder-lib": ["app-builder-lib@25.1.8", "", { "dependencies": { "@develar/schema-utils": "~2.6.5", "@electron/notarize": "2.5.0", "@electron/osx-sign": "1.3.1", "@electron/rebuild": "3.6.1", "@electron/universal": "2.0.1", "@malept/flatpak-bundler": "^0.4.0", "@types/fs-extra": "9.0.13", "async-exit-hook": "^2.0.1", "bluebird-lst": "^1.0.9", "builder-util": "25.1.7", "builder-util-runtime": "9.2.10", "chromium-pickle-js": "^0.2.0", "config-file-ts": "0.2.8-rc1", "debug": "^4.3.4", "dotenv": "^16.4.5", "dotenv-expand": "^11.0.6", "ejs": "^3.1.8", "electron-publish": "25.1.7", "form-data": "^4.0.0", "fs-extra": "^10.1.0", "hosted-git-info": "^4.1.0", "is-ci": "^3.0.0", "isbinaryfile": "^5.0.0", "js-yaml": "^4.1.0", "json5": "^2.2.3", "lazy-val": "^1.0.5", "minimatch": "^10.0.0", "resedit": "^1.7.0", "sanitize-filename": "^1.6.3", "semver": "^7.3.8", "tar": "^6.1.12", "temp-file": "^3.4.0" }, "peerDependencies": { "dmg-builder": "25.1.8", "electron-builder-squirrel-windows": "25.1.8" } }, "sha512-pCqe7dfsQFBABC1jeKZXQWhGcCPF3rPCXDdfqVKjIeWBcXzyC1iOWZdfFhGl+S9MyE/k//DFmC6FzuGAUudNDg=="], + "app-builder-lib": ["app-builder-lib@26.8.1", "", { "dependencies": { "@develar/schema-utils": "~2.6.5", "@electron/asar": "3.4.1", "@electron/fuses": "^1.8.0", "@electron/get": "^3.0.0", "@electron/notarize": "2.5.0", "@electron/osx-sign": "1.3.3", "@electron/rebuild": "^4.0.3", "@electron/universal": "2.0.3", "@malept/flatpak-bundler": "^0.4.0", "@types/fs-extra": "9.0.13", "async-exit-hook": "^2.0.1", "builder-util": "26.8.1", "builder-util-runtime": "9.5.1", "chromium-pickle-js": "^0.2.0", "ci-info": "4.3.1", "debug": "^4.3.4", "dotenv": "^16.4.5", "dotenv-expand": "^11.0.6", "ejs": "^3.1.8", "electron-publish": "26.8.1", "fs-extra": "^10.1.0", "hosted-git-info": "^4.1.0", "isbinaryfile": "^5.0.0", "jiti": "^2.4.2", "js-yaml": "^4.1.0", "json5": "^2.2.3", "lazy-val": "^1.0.5", "minimatch": "^10.0.3", "plist": "3.1.0", "proper-lockfile": "^4.1.2", "resedit": "^1.7.0", "semver": "~7.7.3", "tar": "^7.5.7", "temp-file": "^3.4.0", "tiny-async-pool": "1.3.0", "which": "^5.0.0" }, "peerDependencies": { "dmg-builder": "26.8.1", "electron-builder-squirrel-windows": "26.8.1" } }, "sha512-p0Im/Dx5C4tmz8QEE1Yn4MkuPC8PrnlRneMhWJj7BBXQfNTJUshM/bp3lusdEsDbvvfJZpXWnYesgSLvwtM2Zw=="], "aproba": ["aproba@2.1.0", "", {}, "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew=="], @@ -923,7 +890,7 @@ "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="], - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], @@ -943,7 +910,9 @@ "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], - "brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], + "boolean": ["boolean@3.2.0", "", {}, "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw=="], + + "brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], @@ -955,9 +924,9 @@ "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], - "builder-util": ["builder-util@25.1.7", "", { "dependencies": { "7zip-bin": "~5.2.0", "@types/debug": "^4.1.6", "app-builder-bin": "5.0.0-alpha.10", "bluebird-lst": "^1.0.9", "builder-util-runtime": "9.2.10", "chalk": "^4.1.2", "cross-spawn": "^7.0.3", "debug": "^4.3.4", "fs-extra": "^10.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "is-ci": "^3.0.0", "js-yaml": "^4.1.0", "source-map-support": "^0.5.19", "stat-mode": "^1.0.0", "temp-file": "^3.4.0" } }, "sha512-7jPjzBwEGRbwNcep0gGNpLXG9P94VA3CPAZQCzxkFXiV2GMQKlziMbY//rXPI7WKfhsvGgFXjTcXdBEwgXw9ww=="], + "builder-util": ["builder-util@26.8.1", "", { "dependencies": { "7zip-bin": "~5.2.0", "@types/debug": "^4.1.6", "app-builder-bin": "5.0.0-alpha.12", "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "cross-spawn": "^7.0.6", "debug": "^4.3.4", "fs-extra": "^10.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "js-yaml": "^4.1.0", "sanitize-filename": "^1.6.3", "source-map-support": "^0.5.19", "stat-mode": "^1.0.0", "temp-file": "^3.4.0", "tiny-async-pool": "1.3.0" } }, "sha512-pm1lTYbGyc90DHgCDO7eo8Rl4EqKLciayNbZqGziqnH9jrlKe8ZANGdityLZU+pJh16dfzjAx2xQq9McuIPEtw=="], - "builder-util-runtime": ["builder-util-runtime@9.2.10", "", { "dependencies": { "debug": "^4.3.4", "sax": "^1.2.4" } }, "sha512-6p/gfG1RJSQeIbz8TK5aPNkoztgY1q5TgmGFMAXcY8itsGW6Y2ld1ALsZ5UJn8rog7hKF3zHx5iQbNQ8uLcRlw=="], + "builder-util-runtime": ["builder-util-runtime@9.5.1", "", { "dependencies": { "debug": "^4.3.4", "sax": "^1.2.4" } }, "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ=="], "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], @@ -997,11 +966,11 @@ "chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], - "chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], + "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="], "chromium-pickle-js": ["chromium-pickle-js@0.2.0", "", {}, "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw=="], - "ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="], + "ci-info": ["ci-info@4.4.0", "", {}, "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg=="], "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="], @@ -1029,8 +998,6 @@ "code-block-writer": ["code-block-writer@13.0.3", "", {}, "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg=="], - "codemirror": ["codemirror@6.0.2", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/commands": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/lint": "^6.0.0", "@codemirror/search": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0" } }, "sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw=="], - "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], @@ -1099,12 +1066,8 @@ "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], - "cssstyle": ["cssstyle@6.2.0", "", { "dependencies": { "@asamuzakjp/css-color": "^5.0.1", "@csstools/css-syntax-patches-for-csstree": "^1.0.28", "css-tree": "^3.1.0", "lru-cache": "^11.2.6" } }, "sha512-Fm5NvhYathRnXNVndkUsCCuR63DCLVVwGOOwQw782coXFi5HhkXdu289l59HlXZBawsyNccXfWRYvLzcDCdDig=="], - "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], - "d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="], - "d3-color": ["d3-color@3.1.0", "", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="], "d3-dispatch": ["d3-dispatch@3.0.1", "", {}, "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg=="], @@ -1113,22 +1076,10 @@ "d3-ease": ["d3-ease@3.0.1", "", {}, "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w=="], - "d3-format": ["d3-format@3.1.2", "", {}, "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg=="], - "d3-interpolate": ["d3-interpolate@3.0.1", "", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="], - "d3-path": ["d3-path@3.1.0", "", {}, "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="], - - "d3-scale": ["d3-scale@4.0.2", "", { "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" } }, "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="], - "d3-selection": ["d3-selection@3.0.0", "", {}, "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ=="], - "d3-shape": ["d3-shape@3.2.0", "", { "dependencies": { "d3-path": "^3.1.0" } }, "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA=="], - - "d3-time": ["d3-time@3.1.0", "", { "dependencies": { "d3-array": "2 - 3" } }, "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="], - - "d3-time-format": ["d3-time-format@4.1.0", "", { "dependencies": { "d3-time": "1 - 3" } }, "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="], - "d3-timer": ["d3-timer@3.0.1", "", {}, "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="], "d3-transition": ["d3-transition@3.0.1", "", { "dependencies": { "d3-color": "1 - 3", "d3-dispatch": "1 - 3", "d3-ease": "1 - 3", "d3-interpolate": "1 - 3", "d3-timer": "1 - 3" }, "peerDependencies": { "d3-selection": "2 - 3" } }, "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w=="], @@ -1149,8 +1100,6 @@ "decimal.js": ["decimal.js@10.6.0", "", {}, "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg=="], - "decimal.js-light": ["decimal.js-light@2.5.1", "", {}, "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="], - "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="], "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="], @@ -1169,8 +1118,12 @@ "defer-to-connect": ["defer-to-connect@2.0.1", "", {}, "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg=="], + "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], + "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="], + "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="], + "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], "delegates": ["delegates@1.0.0", "", {}, "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="], @@ -1181,6 +1134,8 @@ "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + "detect-node": ["detect-node@2.1.0", "", {}, "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g=="], + "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="], "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], @@ -1189,7 +1144,7 @@ "dir-compare": ["dir-compare@4.2.0", "", { "dependencies": { "minimatch": "^3.0.5", "p-limit": "^3.1.0 " } }, "sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ=="], - "dmg-builder": ["dmg-builder@25.1.8", "", { "dependencies": { "app-builder-lib": "25.1.8", "builder-util": "25.1.7", "builder-util-runtime": "9.2.10", "fs-extra": "^10.1.0", "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" }, "optionalDependencies": { "dmg-license": "^1.0.11" } }, "sha512-NoXo6Liy2heSklTI5OIZbCgXC1RzrDQsZkeEwXhdOro3FT1VBOvbubvscdPnjVuQ4AMwwv61oaH96AbiYg9EnQ=="], + "dmg-builder": ["dmg-builder@26.8.1", "", { "dependencies": { "app-builder-lib": "26.8.1", "builder-util": "26.8.1", "fs-extra": "^10.1.0", "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" }, "optionalDependencies": { "dmg-license": "^1.0.11" } }, "sha512-glMJgnTreo8CFINujtAhCgN96QAqApDMZ8Vl1r8f0QT8QprvC1UCltV4CcWj20YoIyLZx6IUskaJZ0NV8fokcg=="], "dmg-license": ["dmg-license@1.0.11", "", { "dependencies": { "@types/plist": "^3.0.1", "@types/verror": "^1.10.3", "ajv": "^6.10.0", "crc": "^3.8.0", "iconv-corefoundation": "^1.1.7", "plist": "^3.0.4", "smart-buffer": "^4.0.2", "verror": "^1.10.0" }, "os": "darwin", "bin": { "dmg-license": "bin/dmg-license.js" } }, "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q=="], @@ -1217,22 +1172,14 @@ "electron": ["electron@42.1.0", "", { "dependencies": { "@electron/get": "^5.0.0", "@types/node": "^24.9.0", "extract-zip": "^2.0.1" }, "bin": { "electron": "cli.js", "install-electron": "install.js" } }, "sha512-0szNwC/0dWtkvNce5j3ThiuL0TxBNrZN/BZhdOiGwbLreiD/+u3MGpkct4hA5Ycagb8MXjpEr5/oosi+FwuKRQ=="], - "electron-builder": ["electron-builder@25.1.8", "", { "dependencies": { "app-builder-lib": "25.1.8", "builder-util": "25.1.7", "builder-util-runtime": "9.2.10", "chalk": "^4.1.2", "dmg-builder": "25.1.8", "fs-extra": "^10.1.0", "is-ci": "^3.0.0", "lazy-val": "^1.0.5", "simple-update-notifier": "2.0.0", "yargs": "^17.6.2" }, "bin": { "electron-builder": "cli.js", "install-app-deps": "install-app-deps.js" } }, "sha512-poRgAtUHHOnlzZnc9PK4nzG53xh74wj2Jy7jkTrqZ0MWPoHGh1M2+C//hGeYdA+4K8w4yiVCNYoLXF7ySj2Wig=="], + "electron-builder": ["electron-builder@26.8.1", "", { "dependencies": { "app-builder-lib": "26.8.1", "builder-util": "26.8.1", "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "ci-info": "^4.2.0", "dmg-builder": "26.8.1", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", "simple-update-notifier": "2.0.0", "yargs": "^17.6.2" }, "bin": { "electron-builder": "cli.js", "install-app-deps": "install-app-deps.js" } }, "sha512-uWhx1r74NGpCagG0ULs/P9Nqv2nsoo+7eo4fLUOB8L8MdWltq9odW/uuLXMFCDGnPafknYLZgjNX0ZIFRzOQAw=="], "electron-builder-squirrel-windows": ["electron-builder-squirrel-windows@25.1.8", "", { "dependencies": { "app-builder-lib": "25.1.8", "archiver": "^5.3.1", "builder-util": "25.1.7", "fs-extra": "^10.1.0" } }, "sha512-2ntkJ+9+0GFP6nAISiMabKt6eqBB0kX1QqHNWFWAXgi0VULKGisM46luRFpIBiU3u/TDmhZMM8tzvo2Abn3ayg=="], - "electron-publish": ["electron-publish@25.1.7", "", { "dependencies": { "@types/fs-extra": "^9.0.11", "builder-util": "25.1.7", "builder-util-runtime": "9.2.10", "chalk": "^4.1.2", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", "mime": "^2.5.2" } }, "sha512-+jbTkR9m39eDBMP4gfbqglDd6UvBC7RLh5Y0MhFSsc6UkGHj9Vj9TWobxevHYMMqmoujL11ZLjfPpMX+Pt6YEg=="], + "electron-publish": ["electron-publish@26.8.1", "", { "dependencies": { "@types/fs-extra": "^9.0.11", "builder-util": "26.8.1", "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "form-data": "^4.0.5", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", "mime": "^2.5.2" } }, "sha512-q+jrSTIh/Cv4eGZa7oVR+grEJo/FoLMYBAnSL5GCtqwUpr1T+VgKB/dn1pnzxIxqD8S/jP1yilT9VrwCqINR4w=="], "electron-to-chromium": ["electron-to-chromium@1.5.357", "", {}, "sha512-NHlTIQDK8fmVwHwuIzmXYEJ1Ewq3D9wDNc0cWXxDGysP6Pb21giwGNkxiTifyKy/4SoPuN5l6GLP1W9Sv7zB2g=="], - "elkjs": ["elkjs@0.11.1", "", {}, "sha512-zxxR9k+rx5ktMwT/FwyLdPCrq7xN6e4VGGHH8hA01vVYKjTFik7nHOxBnAYtrgYUB1RpAiLvA1/U2YraWxyKKg=="], - - "embla-carousel": ["embla-carousel@8.6.0", "", {}, "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA=="], - - "embla-carousel-react": ["embla-carousel-react@8.6.0", "", { "dependencies": { "embla-carousel": "8.6.0", "embla-carousel-reactive-utils": "8.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA=="], - - "embla-carousel-reactive-utils": ["embla-carousel-reactive-utils@8.6.0", "", { "peerDependencies": { "embla-carousel": "8.6.0" } }, "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A=="], - "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], @@ -1265,7 +1212,7 @@ "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], - "es-toolkit": ["es-toolkit@1.46.1", "", {}, "sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ=="], + "es6-error": ["es6-error@4.1.1", "", {}, "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg=="], "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], @@ -1273,7 +1220,7 @@ "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - "eslint": ["eslint@9.39.4", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.2", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.5", "@eslint/js": "9.39.4", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ=="], + "eslint": ["eslint@10.4.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.6.0", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-loXy6bWOoP3EP6JA7jo6p5jMpBJmHmsNZM5SFRHLdh1MGOPurMnNBj4ZlAbaqUAaQWbCr7jHV4P7gzAyryZWkQ=="], "eslint-compat-utils": ["eslint-compat-utils@0.5.1", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q=="], @@ -1285,11 +1232,11 @@ "eslint-plugin-n": ["eslint-plugin-n@17.24.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.5.0", "enhanced-resolve": "^5.17.1", "eslint-plugin-es-x": "^7.8.0", "get-tsconfig": "^4.8.1", "globals": "^15.11.0", "globrex": "^0.1.2", "ignore": "^5.3.2", "semver": "^7.6.3", "ts-declaration-location": "^1.0.6" }, "peerDependencies": { "eslint": ">=8.23.0" } }, "sha512-/gC7/KAYmfNnPNOb3eu8vw+TdVnV0zhdQwexsw6FLXbhzroVj20vRn2qL8lDWDGnAQ2J8DhdfvXxX9EoxvERvw=="], - "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], + "eslint-scope": ["eslint-scope@9.1.2", "", { "dependencies": { "@types/esrecurse": "^4.3.1", "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ=="], - "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + "eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], - "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], + "espree": ["espree@11.2.0", "", { "dependencies": { "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^5.0.1" } }, "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw=="], "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], @@ -1307,8 +1254,6 @@ "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], - "eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="], - "eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="], "eventsource-parser": ["eventsource-parser@3.0.8", "", {}, "sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ=="], @@ -1421,12 +1366,16 @@ "get-tsconfig": ["get-tsconfig@4.14.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA=="], - "glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], + "glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + "global-agent": ["global-agent@3.0.0", "", { "dependencies": { "boolean": "^3.0.1", "es6-error": "^4.1.1", "matcher": "^3.0.0", "roarr": "^2.15.3", "semver": "^7.3.2", "serialize-error": "^7.0.1" } }, "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q=="], + "globals": ["globals@17.6.0", "", {}, "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA=="], + "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], + "globrex": ["globrex@0.1.2", "", {}, "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="], "goober": ["goober@2.1.19", "", { "peerDependencies": { "csstype": "^3.0.10" } }, "sha512-U7veizMqxyKlM58+Z5j2ngJBH/r9siDmxpvNxSw0PylF6WQvrASJEZrxh1hidRBJc2jqoBVSyOban5u8m+6Rxg=="], @@ -1445,6 +1394,8 @@ "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="], + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], @@ -1511,10 +1462,6 @@ "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="], - "input-otp": ["input-otp@1.4.2", "", { "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA=="], - - "internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="], - "ip-address": ["ip-address@10.2.0", "", {}, "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA=="], "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], @@ -1591,7 +1538,7 @@ "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], - "jsdom": ["jsdom@28.1.0", "", { "dependencies": { "@acemir/cssom": "^0.9.31", "@asamuzakjp/dom-selector": "^6.8.1", "@bramus/specificity": "^2.4.2", "@exodus/bytes": "^1.11.0", "cssstyle": "^6.0.1", "data-urls": "^7.0.0", "decimal.js": "^10.6.0", "html-encoding-sniffer": "^6.0.0", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.6", "is-potential-custom-element-name": "^1.0.1", "parse5": "^8.0.0", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^6.0.0", "undici": "^7.21.0", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^8.0.1", "whatwg-mimetype": "^5.0.0", "whatwg-url": "^16.0.0", "xml-name-validator": "^5.0.0" }, "peerDependencies": { "canvas": "^3.0.0" }, "optionalPeers": ["canvas"] }, "sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug=="], + "jsdom": ["jsdom@29.1.1", "", { "dependencies": { "@asamuzakjp/css-color": "^5.1.11", "@asamuzakjp/dom-selector": "^7.1.1", "@bramus/specificity": "^2.4.2", "@csstools/css-syntax-patches-for-csstree": "^1.1.3", "@exodus/bytes": "^1.15.0", "css-tree": "^3.2.1", "data-urls": "^7.0.0", "decimal.js": "^10.6.0", "html-encoding-sniffer": "^6.0.0", "is-potential-custom-element-name": "^1.0.1", "lru-cache": "^11.3.5", "parse5": "^8.0.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^6.0.1", "undici": "^7.25.0", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^8.0.1", "whatwg-mimetype": "^5.0.0", "whatwg-url": "^16.0.1", "xml-name-validator": "^5.0.0" }, "peerDependencies": { "canvas": "^3.0.0" }, "optionalPeers": ["canvas"] }, "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q=="], "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], @@ -1607,6 +1554,8 @@ "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + "json-stringify-safe": ["json-stringify-safe@5.0.1", "", {}, "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="], + "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], "jsonfile": ["jsonfile@6.2.1", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q=="], @@ -1661,8 +1610,6 @@ "lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="], - "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], - "lodash.union": ["lodash.union@4.6.0", "", {}, "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw=="], "log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="], @@ -1681,6 +1628,8 @@ "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], + "matcher": ["matcher@3.0.0", "", { "dependencies": { "escape-string-regexp": "^4.0.0" } }, "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng=="], + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], "mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="], @@ -1793,11 +1742,11 @@ "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="], - "minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], + "minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], - "minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], + "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], "minipass-collect": ["minipass-collect@1.0.2", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA=="], @@ -1809,7 +1758,7 @@ "minipass-sized": ["minipass-sized@1.0.3", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g=="], - "minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="], + "minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="], "mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], @@ -1831,9 +1780,9 @@ "nf3": ["nf3@0.3.17", "", {}, "sha512-N9zEWySuJFw+gR0lhS5863YsvNeudOdqRyFvNb+jMXbeTJOdrjDqkCpDginIZfUm0LzT1t1nCRiDeqQm/8kirQ=="], - "nitro": ["nitro-nightly@3.0.1-20260512-093145-0498ce70", "", { "dependencies": { "consola": "^3.4.2", "crossws": "^0.4.5", "db0": "^0.3.4", "env-runner": "^0.1.7", "h3": "^2.0.1-rc.22", "hookable": "^6.1.1", "nf3": "^0.3.17", "ocache": "^0.1.4", "ofetch": "^2.0.0-alpha.3", "ohash": "^2.0.11", "rolldown": "^1.0.0", "srvx": "^0.11.15", "unenv": "^2.0.0-rc.24", "unstorage": "^2.0.0-alpha.7" }, "peerDependencies": { "@vercel/queue": "^0.1.6", "dotenv": "*", "giget": "*", "jiti": "^2.6.1", "rollup": "^4.60.3", "vite": "^7 || ^8", "xml2js": "^0.6.2", "zephyr-agent": "^0.2.0" }, "optionalPeers": ["@vercel/queue", "dotenv", "giget", "jiti", "rollup", "vite", "xml2js", "zephyr-agent"], "bin": { "nitro": "dist/cli/index.mjs" } }, "sha512-5vIbEn1ORiNIymy9RtRx3AavX4CAQqWNnsh1vOLag/fzsEQRD2wLBhR+ZcMeVTUbQb0mo8fIbMH2NkSeiGu6fw=="], + "nitro": ["nitro-nightly@3.0.1-20260518-130639-31265391", "", { "dependencies": { "consola": "^3.4.2", "crossws": "^0.4.5", "db0": "^0.3.4", "env-runner": "^0.1.7", "h3": "^2.0.1-rc.22", "hookable": "^6.1.1", "nf3": "^0.3.17", "ocache": "^0.1.4", "ofetch": "^2.0.0-alpha.3", "ohash": "^2.0.11", "rolldown": "^1.0.0", "srvx": "^0.11.15", "unenv": "^2.0.0-rc.24", "unstorage": "^2.0.0-alpha.7" }, "peerDependencies": { "@vercel/queue": "^0.1.6", "dotenv": "*", "giget": "*", "jiti": "^2.6.1", "rollup": "^4.60.3", "vite": "^7 || ^8", "xml2js": "^0.6.2", "zephyr-agent": "^0.2.0" }, "optionalPeers": ["@vercel/queue", "dotenv", "giget", "jiti", "rollup", "vite", "xml2js", "zephyr-agent"], "bin": { "nitro": "dist/cli/index.mjs" } }, "sha512-JhmqcyNdah1zLNeHzAIeNcTqNT1GW5UveEdK39hGB776K4ydPlijTsm821MTDNZjdEmSTs8Pzxzr+xmi7lBgdw=="], - "node-abi": ["node-abi@3.92.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ=="], + "node-abi": ["node-abi@4.31.0", "", { "dependencies": { "semver": "^7.6.3" } }, "sha512-Erq5w/t3syw3s4sDsUaX4QttIdBPsGKTT1DTRsCkTonGggczhlDKm/wDX3o+HPJpQ41EjXCbcmXf0tgr5YZJXw=="], "node-addon-api": ["node-addon-api@1.7.2", "", {}, "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg=="], @@ -1843,11 +1792,11 @@ "node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], - "node-gyp": ["node-gyp@9.4.1", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "glob": "^7.1.4", "graceful-fs": "^4.2.6", "make-fetch-happen": "^10.0.3", "nopt": "^6.0.0", "npmlog": "^6.0.0", "rimraf": "^3.0.2", "semver": "^7.3.5", "tar": "^6.1.2", "which": "^2.0.2" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ=="], + "node-gyp": ["node-gyp@12.3.0", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "graceful-fs": "^4.2.6", "nopt": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", "tar": "^7.5.4", "tinyglobby": "^0.2.12", "undici": "^6.25.0", "which": "^6.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-QNcUWM+HgJplcPzBvFBZ9VXacyGZ4+VTOb80PwWR+TlVzoHbRKULNEzpRsnaoxG3Wzr7Qh7BYxGDU3CbKib2Yg=="], "node-releases": ["node-releases@2.0.44", "", {}, "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ=="], - "nopt": ["nopt@6.0.0", "", { "dependencies": { "abbrev": "^1.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g=="], + "nopt": ["nopt@9.0.0", "", { "dependencies": { "abbrev": "^4.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw=="], "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], @@ -1863,6 +1812,8 @@ "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], + "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="], + "object-treeify": ["object-treeify@1.1.33", "", {}, "sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A=="], "obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="], @@ -1939,7 +1890,7 @@ "pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="], - "plist": ["plist@3.1.1", "", { "dependencies": { "@xmldom/xmldom": "^0.9.10", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA=="], + "plist": ["plist@3.1.0", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ=="], "postcss": ["postcss@8.5.14", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg=="], @@ -1953,6 +1904,8 @@ "pretty-ms": ["pretty-ms@9.3.0", "", { "dependencies": { "parse-ms": "^4.0.0" } }, "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ=="], + "proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="], + "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="], "progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="], @@ -1963,6 +1916,8 @@ "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="], + "proper-lockfile": ["proper-lockfile@4.1.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "retry": "^0.12.0", "signal-exit": "^3.0.2" } }, "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA=="], + "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="], "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], @@ -1987,16 +1942,10 @@ "react": ["react@19.2.6", "", {}, "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q=="], - "react-day-picker": ["react-day-picker@10.0.1", "", { "dependencies": { "@date-fns/tz": "^1.4.1", "date-fns": "^4.1.0" }, "peerDependencies": { "@types/react": ">=16.8.0", "react": ">=16.8.0" }, "optionalPeers": ["@types/react"] }, "sha512-eNh6BlwcYInWaJtRv18mXQ06Ys/H6rdTZAnTaSdOYJuTpwP1JMCHNd1FDRadA+gbeinq+psdULN5Xnowy9mV8w=="], - "react-dom": ["react-dom@19.2.6", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.6" } }, "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g=="], - "react-is": ["react-is@19.2.6", "", {}, "sha512-XjBR15BhXuylgWGuslhDKqlSayuqvqBX91BP8pauG8kd1zY8kotkNWbXksTCNRarse4kuGbe2kIY05ARtwNIvw=="], - "react-markdown": ["react-markdown@10.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ=="], - "react-redux": ["react-redux@9.3.0", "", { "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" }, "peerDependencies": { "@types/react": "^18.2.25 || ^19", "react": "^18.0 || ^19", "redux": "^5.0.0" }, "optionalPeers": ["@types/react", "redux"] }, "sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/g=="], - "react-remove-scroll": ["react-remove-scroll@2.7.2", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q=="], "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="], @@ -2015,12 +1964,6 @@ "recast": ["recast@0.23.11", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA=="], - "recharts": ["recharts@3.8.0", "", { "dependencies": { "@reduxjs/toolkit": "^1.9.0 || 2.x.x", "clsx": "^2.1.1", "decimal.js-light": "^2.5.1", "es-toolkit": "^1.39.3", "eventemitter3": "^5.0.1", "immer": "^10.1.1", "react-redux": "8.x.x || 9.x.x", "reselect": "5.1.1", "tiny-invariant": "^1.3.3", "use-sync-external-store": "^1.2.2", "victory-vendor": "^37.0.2" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Z/m38DX3L73ExO4Tpc9/iZWHmHnlzWG4njQbxsF5aSjwqmHNDDIm0rdEBArkwsBvR8U6EirlEHiQNYWCVh9sGQ=="], - - "redux": ["redux@5.0.1", "", {}, "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="], - - "redux-thunk": ["redux-thunk@3.1.0", "", { "peerDependencies": { "redux": "^5.0.0" } }, "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw=="], - "remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="], "remark-parse": ["remark-parse@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "micromark-util-types": "^2.0.0", "unified": "^11.0.0" } }, "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA=="], @@ -2055,6 +1998,8 @@ "rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], + "roarr": ["roarr@2.15.4", "", { "dependencies": { "boolean": "^3.0.1", "detect-node": "^2.0.4", "globalthis": "^1.0.1", "json-stringify-safe": "^5.0.1", "semver-compare": "^1.0.0", "sprintf-js": "^1.1.2" } }, "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A=="], + "rolldown": ["rolldown@1.0.1", "", { "dependencies": { "@oxc-project/types": "=0.130.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.1", "@rolldown/binding-darwin-arm64": "1.0.1", "@rolldown/binding-darwin-x64": "1.0.1", "@rolldown/binding-freebsd-x64": "1.0.1", "@rolldown/binding-linux-arm-gnueabihf": "1.0.1", "@rolldown/binding-linux-arm64-gnu": "1.0.1", "@rolldown/binding-linux-arm64-musl": "1.0.1", "@rolldown/binding-linux-ppc64-gnu": "1.0.1", "@rolldown/binding-linux-s390x-gnu": "1.0.1", "@rolldown/binding-linux-x64-gnu": "1.0.1", "@rolldown/binding-linux-x64-musl": "1.0.1", "@rolldown/binding-openharmony-arm64": "1.0.1", "@rolldown/binding-wasm32-wasi": "1.0.1", "@rolldown/binding-win32-arm64-msvc": "1.0.1", "@rolldown/binding-win32-x64-msvc": "1.0.1" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ=="], "rou3": ["rou3@0.8.1", "", {}, "sha512-ePa+XGk00/3HuCqrEnK3LxJW7I0SdNg6EFzKUJG73hMAdDcOUC/i/aSz7LSDwLrGr33kal/rqOGydzwl6U7zBA=="], @@ -2081,8 +2026,12 @@ "semver": ["semver@7.8.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA=="], + "semver-compare": ["semver-compare@1.0.0", "", {}, "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow=="], + "send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="], + "serialize-error": ["serialize-error@7.0.1", "", { "dependencies": { "type-fest": "^0.13.1" } }, "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw=="], + "seroval": ["seroval@1.5.4", "", {}, "sha512-46uFvgrXTVxZcUorgSSRZ4y+ieqLLQRMlG4bnCZKW3qI6BZm7Rg4ntMW4p1mILEEBZWrFlcpp0AyIIlM6jD9iw=="], "seroval-plugins": ["seroval-plugins@1.5.4", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-S0xQPhUTefAhNvNWFg0c1J8qJArHt5KdtJ/cFAofo06KD1MVSeFWyl4iiu+ApDIuw0WhjpOfCdgConOfAnLgkw=="], @@ -2141,6 +2090,8 @@ "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], + "sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="], + "srvx": ["srvx@0.11.15", "", { "bin": { "srvx": "bin/srvx.mjs" } }, "sha512-iXsux0UcOjdvs0LCMa2Ws3WwcDUozA3JN3BquNXkaFPP7TpRqgunKdEgoZ/uwb1J6xaYHfxtz9Twlh6yzwM6Tg=="], "ssri": ["ssri@9.0.1", "", { "dependencies": { "minipass": "^3.1.1" } }, "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q=="], @@ -2179,8 +2130,6 @@ "strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="], - "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], - "style-mod": ["style-mod@4.1.3", "", {}, "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ=="], "style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="], @@ -2201,12 +2150,14 @@ "tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="], - "tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="], + "tar": ["tar@7.5.15", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-dzGK0boVlC4W5QFuQN1EFSl3bIDYsk7Tj40U6eIBnK2k/8ml7TZ5agbI5j5+qnoVcAA+rNtBml8SEiLxZpNqRQ=="], "tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="], "temp-file": ["temp-file@3.4.0", "", { "dependencies": { "async-exit-hook": "^2.0.1", "fs-extra": "^10.0.0" } }, "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg=="], + "tiny-async-pool": ["tiny-async-pool@1.3.0", "", { "dependencies": { "semver": "^5.5.0" } }, "sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA=="], + "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="], "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], @@ -2321,16 +2272,12 @@ "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], - "vaul": ["vaul@1.1.2", "", { "dependencies": { "@radix-ui/react-dialog": "^1.1.1" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA=="], - "verror": ["verror@1.10.1", "", { "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg=="], "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="], - "victory-vendor": ["victory-vendor@37.3.6", "", { "dependencies": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", "@types/d3-interpolate": "^3.0.1", "@types/d3-scale": "^4.0.2", "@types/d3-shape": "^3.1.0", "@types/d3-time": "^3.0.0", "@types/d3-timer": "^3.0.0", "d3-array": "^3.1.6", "d3-ease": "^3.0.1", "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-shape": "^3.1.0", "d3-time": "^3.0.0", "d3-timer": "^3.0.1" } }, "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ=="], - "vite": ["vite@8.0.13", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.14", "rolldown": "1.0.1", "tinyglobby": "^0.2.16" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.18", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw=="], "vitefu": ["vitefu@1.1.3", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["vite"] }, "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg=="], @@ -2387,7 +2334,7 @@ "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], - "yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + "yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], @@ -2435,23 +2382,25 @@ "@electron/asar/commander": ["commander@5.1.0", "", {}, "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="], - "@electron/asar/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + "@electron/asar/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], + + "@electron/fuses/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "@electron/fuses/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], "@electron/notarize/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], "@electron/osx-sign/isbinaryfile": ["isbinaryfile@4.0.10", "", {}, "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw=="], - "@electron/rebuild/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "@electron/rebuild/ora": ["ora@5.4.1", "", { "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.5.0", "is-interactive": "^1.0.0", "is-unicode-supported": "^0.1.0", "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ=="], + "@electron/osx-sign/plist": ["plist@3.1.1", "", { "dependencies": { "@xmldom/xmldom": "^0.9.10", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA=="], "@electron/universal/fs-extra": ["fs-extra@11.3.5", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg=="], "@electron/universal/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], - "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "@electron/universal/plist": ["plist@3.1.1", "", { "dependencies": { "@xmldom/xmldom": "^0.9.10", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA=="], - "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], @@ -2463,87 +2412,9 @@ "@mswjs/interceptors/@open-draft/deferred-promise": ["@open-draft/deferred-promise@2.2.0", "", {}, "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA=="], - "@radix-ui/react-accordion/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-alert-dialog/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-arrow/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-aspect-ratio/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-avatar/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-checkbox/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-collapsible/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-collection/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-context-menu/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-dialog/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-dismissable-layer/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-dropdown-menu/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-focus-scope/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-form/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-hover-card/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-label/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-menu/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-menubar/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-navigation-menu/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-one-time-password-field/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-password-toggle-field/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-popover/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-popper/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-portal/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="], - - "@radix-ui/react-progress/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-radio-group/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-roving-focus/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-scroll-area/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-select/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-separator/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-slider/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-switch/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-tabs/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-toast/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-toggle/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-toggle-group/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-toolbar/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-tooltip/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - - "@radix-ui/react-visually-hidden/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], + "@stylistic/eslint-plugin/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], - "@reduxjs/toolkit/immer": ["immer@11.1.8", "", {}, "sha512-/tbkHMW7y10Lx6i1crLjD4/OhNkRG+Fo7byZHtah0547nIeXYcpIXaUh0IAQY6gO5459qpGGYapcEOHtFXkIuA=="], + "@stylistic/eslint-plugin/espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="], @@ -2561,15 +2432,21 @@ "@tanstack/start-plugin-core/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.40", "", {}, "sha512-s3GeJKSQOwBlzdUrj4ISjJj5SfSh+aqn0wjOar4Bx95iV1ETI7F6S/5hLcfAxZ9kXDcyrAkxPlqmd1ZITttf+w=="], - "@ts-morph/common/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], + "@types/cacheable-request/@types/node": ["@types/node@25.8.0", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ=="], - "@types/yauzl/@types/node": ["@types/node@24.12.4", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA=="], + "@types/fs-extra/@types/node": ["@types/node@25.8.0", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ=="], - "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], + "@types/keyv/@types/node": ["@types/node@25.8.0", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ=="], + + "@types/plist/@types/node": ["@types/node@25.8.0", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ=="], + + "@types/responselike/@types/node": ["@types/node@25.8.0", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ=="], - "@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], + "@types/set-cookie-parser/@types/node": ["@types/node@25.8.0", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ=="], - "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], + "@types/yauzl/@types/node": ["@types/node@24.12.4", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA=="], + + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], "@unrs/resolver-binding-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], @@ -2579,9 +2456,13 @@ "anymatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], - "app-builder-lib/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], + "app-builder-lib/@electron/get": ["@electron/get@3.1.0", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-F+nKc0xW+kVbBRhFzaMgPy3KwmuNTYX1fx6+FxxoSnNgwYX6LD7AKBTWkU0MQ6IBoe7dz069CNkR673sPAgkCQ=="], - "archiver-utils/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + "app-builder-lib/ci-info": ["ci-info@4.3.1", "", {}, "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA=="], + + "app-builder-lib/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], + + "app-builder-lib/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="], "archiver-utils/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], @@ -2591,12 +2472,16 @@ "builder-util/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "cacache/chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], + "cacache/glob": ["glob@8.1.0", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^5.0.1", "once": "^1.3.0" } }, "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ=="], "cacache/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], "cacache/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + "cacache/tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="], + "cheerio/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], "cheerio/whatwg-mimetype": ["whatwg-mimetype@4.0.0", "", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="], @@ -2607,23 +2492,27 @@ "concurrently/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "config-file-ts/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], + "config-file-ts/typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], "cosmiconfig/env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], + "dir-compare/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], + + "dmg-license/plist": ["plist@3.1.1", "", { "dependencies": { "@xmldom/xmldom": "^0.9.10", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA=="], + "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], "electron/@types/node": ["@types/node@24.12.4", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA=="], "electron-builder/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "electron-publish/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "eslint/@eslint/js": ["@eslint/js@9.39.4", "", {}, "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw=="], + "electron-builder-squirrel-windows/app-builder-lib": ["app-builder-lib@25.1.8", "", { "dependencies": { "@develar/schema-utils": "~2.6.5", "@electron/notarize": "2.5.0", "@electron/osx-sign": "1.3.1", "@electron/rebuild": "3.6.1", "@electron/universal": "2.0.1", "@malept/flatpak-bundler": "^0.4.0", "@types/fs-extra": "9.0.13", "async-exit-hook": "^2.0.1", "bluebird-lst": "^1.0.9", "builder-util": "25.1.7", "builder-util-runtime": "9.2.10", "chromium-pickle-js": "^0.2.0", "config-file-ts": "0.2.8-rc1", "debug": "^4.3.4", "dotenv": "^16.4.5", "dotenv-expand": "^11.0.6", "ejs": "^3.1.8", "electron-publish": "25.1.7", "form-data": "^4.0.0", "fs-extra": "^10.1.0", "hosted-git-info": "^4.1.0", "is-ci": "^3.0.0", "isbinaryfile": "^5.0.0", "js-yaml": "^4.1.0", "json5": "^2.2.3", "lazy-val": "^1.0.5", "minimatch": "^10.0.0", "resedit": "^1.7.0", "sanitize-filename": "^1.6.3", "semver": "^7.3.8", "tar": "^6.1.12", "temp-file": "^3.4.0" }, "peerDependencies": { "dmg-builder": "25.1.8", "electron-builder-squirrel-windows": "25.1.8" } }, "sha512-pCqe7dfsQFBABC1jeKZXQWhGcCPF3rPCXDdfqVKjIeWBcXzyC1iOWZdfFhGl+S9MyE/k//DFmC6FzuGAUudNDg=="], - "eslint/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "electron-builder-squirrel-windows/builder-util": ["builder-util@25.1.7", "", { "dependencies": { "7zip-bin": "~5.2.0", "@types/debug": "^4.1.6", "app-builder-bin": "5.0.0-alpha.10", "bluebird-lst": "^1.0.9", "builder-util-runtime": "9.2.10", "chalk": "^4.1.2", "cross-spawn": "^7.0.3", "debug": "^4.3.4", "fs-extra": "^10.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "is-ci": "^3.0.0", "js-yaml": "^4.1.0", "source-map-support": "^0.5.19", "stat-mode": "^1.0.0", "temp-file": "^3.4.0" } }, "sha512-7jPjzBwEGRbwNcep0gGNpLXG9P94VA3CPAZQCzxkFXiV2GMQKlziMbY//rXPI7WKfhsvGgFXjTcXdBEwgXw9ww=="], - "eslint-plugin-import-x/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], + "electron-publish/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "eslint-plugin-n/globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="], @@ -2643,14 +2532,14 @@ "gauge/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], - - "glob/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], + "glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], "hosted-git-info/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], "htmlparser2/entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], + "is-ci/ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="], + "lazystream/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], "log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], @@ -2673,17 +2562,19 @@ "minipass-fetch/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + "minipass-fetch/minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="], + "minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], "minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], "minipass-sized/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - "minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - "node-gyp/env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], - "node-gyp/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + "node-gyp/undici": ["undici@6.25.0", "", {}, "sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg=="], + + "node-gyp/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="], "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], @@ -2699,11 +2590,9 @@ "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], - "path-scurry/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], - "prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], - "radix-ui/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], + "proper-lockfile/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], "raw-body/iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], @@ -2713,14 +2602,14 @@ "restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], - "rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - "rolldown/@oxc-project/types": ["@oxc-project/types@0.130.0", "", {}, "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q=="], "router/path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="], "send/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], + "serialize-error/type-fest": ["type-fest@0.13.1", "", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="], + "shadcn/fs-extra": ["fs-extra@11.3.5", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg=="], "shadcn/postcss-selector-parser": ["postcss-selector-parser@7.1.1", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg=="], @@ -2741,10 +2630,18 @@ "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "tiny-async-pool/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], + "type-is/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], "type-is/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], + "vue-eslint-parser/eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], + + "vue-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + + "vue-eslint-parser/espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], + "wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], @@ -2767,20 +2664,16 @@ "@dotenvx/dotenvx/which/isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="], - "@electron/rebuild/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "@electron/rebuild/ora/cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="], - - "@electron/rebuild/ora/is-interactive": ["is-interactive@1.0.0", "", {}, "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="], + "@electron/asar/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], - "@electron/rebuild/ora/is-unicode-supported": ["is-unicode-supported@0.1.0", "", {}, "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="], + "@electron/fuses/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - "@electron/rebuild/ora/log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="], - - "@electron/rebuild/ora/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "@electron/osx-sign/plist/@xmldom/xmldom": ["@xmldom/xmldom@0.9.10", "", {}, "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw=="], "@electron/universal/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], + "@electron/universal/plist/@xmldom/xmldom": ["@xmldom/xmldom@0.9.10", "", {}, "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw=="], + "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], @@ -2791,17 +2684,19 @@ "@tanstack/router-plugin/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], - "@ts-morph/common/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="], - "@types/yauzl/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="], - "accepts/mime-types/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], "ajv-formats/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - "app-builder-lib/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="], + "app-builder-lib/@electron/get/env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], + + "app-builder-lib/@electron/get/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], + + "app-builder-lib/@electron/get/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "app-builder-lib/which/isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="], "archiver-utils/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], @@ -2811,29 +2706,63 @@ "cacache/glob/minimatch": ["minimatch@5.1.9", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw=="], + "cacache/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "cacache/tar/minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], + + "cacache/tar/minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="], + + "cacache/tar/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + "cheerio/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "concurrently/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "config-file-ts/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], + + "dir-compare/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], + + "dmg-license/plist/@xmldom/xmldom": ["@xmldom/xmldom@0.9.10", "", {}, "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/osx-sign": ["@electron/osx-sign@1.3.1", "", { "dependencies": { "compare-version": "^0.1.2", "debug": "^4.3.4", "fs-extra": "^10.0.0", "isbinaryfile": "^4.0.8", "minimist": "^1.2.6", "plist": "^3.0.5" }, "bin": { "electron-osx-flat": "bin/electron-osx-flat.js", "electron-osx-sign": "bin/electron-osx-sign.js" } }, "sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild": ["@electron/rebuild@3.6.1", "", { "dependencies": { "@malept/cross-spawn-promise": "^2.0.0", "chalk": "^4.0.0", "debug": "^4.1.1", "detect-libc": "^2.0.1", "fs-extra": "^10.0.0", "got": "^11.7.0", "node-abi": "^3.45.0", "node-api-version": "^0.2.0", "node-gyp": "^9.0.0", "ora": "^5.1.0", "read-binary-file-arch": "^1.0.6", "semver": "^7.3.5", "tar": "^6.0.5", "yargs": "^17.0.1" }, "bin": { "electron-rebuild": "lib/cli.js" } }, "sha512-f6596ZHpEq/YskUd8emYvOUne89ij8mQgjYFA5ru25QwbrRO+t1SImofdDv7kKOuWCmVOuU5tvfkbgGxIl3E/w=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/universal": ["@electron/universal@2.0.1", "", { "dependencies": { "@electron/asar": "^3.2.7", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", "dir-compare": "^4.2.0", "fs-extra": "^11.1.1", "minimatch": "^9.0.3", "plist": "^3.1.0" } }, "sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA=="], + + "electron-builder-squirrel-windows/app-builder-lib/builder-util-runtime": ["builder-util-runtime@9.2.10", "", { "dependencies": { "debug": "^4.3.4", "sax": "^1.2.4" } }, "sha512-6p/gfG1RJSQeIbz8TK5aPNkoztgY1q5TgmGFMAXcY8itsGW6Y2ld1ALsZ5UJn8rog7hKF3zHx5iQbNQ8uLcRlw=="], + + "electron-builder-squirrel-windows/app-builder-lib/dmg-builder": ["dmg-builder@25.1.8", "", { "dependencies": { "app-builder-lib": "25.1.8", "builder-util": "25.1.7", "builder-util-runtime": "9.2.10", "fs-extra": "^10.1.0", "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" }, "optionalDependencies": { "dmg-license": "^1.0.11" } }, "sha512-NoXo6Liy2heSklTI5OIZbCgXC1RzrDQsZkeEwXhdOro3FT1VBOvbubvscdPnjVuQ4AMwwv61oaH96AbiYg9EnQ=="], + + "electron-builder-squirrel-windows/app-builder-lib/electron-publish": ["electron-publish@25.1.7", "", { "dependencies": { "@types/fs-extra": "^9.0.11", "builder-util": "25.1.7", "builder-util-runtime": "9.2.10", "chalk": "^4.1.2", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", "mime": "^2.5.2" } }, "sha512-+jbTkR9m39eDBMP4gfbqglDd6UvBC7RLh5Y0MhFSsc6UkGHj9Vj9TWobxevHYMMqmoujL11ZLjfPpMX+Pt6YEg=="], + + "electron-builder-squirrel-windows/app-builder-lib/tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="], + + "electron-builder-squirrel-windows/builder-util/app-builder-bin": ["app-builder-bin@5.0.0-alpha.10", "", {}, "sha512-Ev4jj3D7Bo+O0GPD2NMvJl+PGiBAfS7pUGawntBNpCbxtpncfUixqFj9z9Jme7V7s3LBGqsWZZP54fxBX3JKJw=="], + + "electron-builder-squirrel-windows/builder-util/builder-util-runtime": ["builder-util-runtime@9.2.10", "", { "dependencies": { "debug": "^4.3.4", "sax": "^1.2.4" } }, "sha512-6p/gfG1RJSQeIbz8TK5aPNkoztgY1q5TgmGFMAXcY8itsGW6Y2ld1ALsZ5UJn8rog7hKF3zHx5iQbNQ8uLcRlw=="], + + "electron-builder-squirrel-windows/builder-util/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "electron-builder/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "electron-publish/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "electron/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], - "eslint-plugin-import-x/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="], - - "eslint/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - "express/mime-types/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], "filelist/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], + "fs-minipass/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + "gauge/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], + "glob/minimatch/brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="], + + "hosted-git-info/lru-cache/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], "lazystream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], @@ -2841,6 +2770,22 @@ "make-fetch-happen/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + "make-fetch-happen/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "minipass-collect/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "minipass-fetch/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "minipass-fetch/minizlib/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "minipass-flush/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "minipass-pipeline/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "minipass-sized/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "node-gyp/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="], + "ora/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], "parse5-htmlparser2-tree-adapter/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], @@ -2853,6 +2798,8 @@ "shadcn/ts-morph/@ts-morph/common": ["@ts-morph/common@0.27.0", "", { "dependencies": { "fast-glob": "^3.3.3", "minimatch": "^10.0.1", "path-browserify": "^1.0.1" } }, "sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ=="], + "ssri/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], @@ -2863,30 +2810,98 @@ "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "zip-stream/archiver-utils/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - - "@electron/rebuild/ora/cli-cursor/restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="], + "@electron/asar/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "@electron/rebuild/ora/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "@electron/universal/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "@tanstack/router-plugin/chokidar/readdirp/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], - "@ts-morph/common/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], + "app-builder-lib/@electron/get/fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], - "@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], - - "app-builder-lib/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], + "app-builder-lib/@electron/get/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], "cacache/glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], - "eslint-plugin-import-x/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], + "cacache/tar/minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "config-file-ts/glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], + + "dir-compare/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/osx-sign/isbinaryfile": ["isbinaryfile@4.0.10", "", {}, "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/osx-sign/plist": ["plist@3.1.1", "", { "dependencies": { "@xmldom/xmldom": "^0.9.10", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild/node-abi": ["node-abi@3.92.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild/node-gyp": ["node-gyp@9.4.1", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "glob": "^7.1.4", "graceful-fs": "^4.2.6", "make-fetch-happen": "^10.0.3", "nopt": "^6.0.0", "npmlog": "^6.0.0", "rimraf": "^3.0.2", "semver": "^7.3.5", "tar": "^6.1.2", "which": "^2.0.2" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild/ora": ["ora@5.4.1", "", { "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.5.0", "is-interactive": "^1.0.0", "is-unicode-supported": "^0.1.0", "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/universal/fs-extra": ["fs-extra@11.3.5", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/universal/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/universal/plist": ["plist@3.1.1", "", { "dependencies": { "@xmldom/xmldom": "^0.9.10", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA=="], + + "electron-builder-squirrel-windows/app-builder-lib/electron-publish/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "electron-builder-squirrel-windows/app-builder-lib/tar/chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], + + "electron-builder-squirrel-windows/app-builder-lib/tar/minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], + + "electron-builder-squirrel-windows/app-builder-lib/tar/minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="], + + "electron-builder-squirrel-windows/app-builder-lib/tar/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "electron-builder-squirrel-windows/builder-util/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "filelist/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "readdir-glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "cacache/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "config-file-ts/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/osx-sign/plist/@xmldom/xmldom": ["@xmldom/xmldom@0.9.10", "", {}, "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild/node-gyp/env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild/node-gyp/nopt": ["nopt@6.0.0", "", { "dependencies": { "abbrev": "^1.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild/ora/cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild/ora/is-interactive": ["is-interactive@1.0.0", "", {}, "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild/ora/is-unicode-supported": ["is-unicode-supported@0.1.0", "", {}, "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild/ora/log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild/ora/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/universal/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/universal/plist/@xmldom/xmldom": ["@xmldom/xmldom@0.9.10", "", {}, "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw=="], + + "electron-builder-squirrel-windows/app-builder-lib/electron-publish/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "electron-builder-squirrel-windows/app-builder-lib/tar/minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild/node-gyp/nopt/abbrev": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="], - "shadcn/ts-morph/@ts-morph/common/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild/ora/cli-cursor/restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="], - "@electron/rebuild/ora/cli-cursor/restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild/ora/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "shadcn/ts-morph/@ts-morph/common/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="], + "electron-builder-squirrel-windows/app-builder-lib/@electron/universal/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "shadcn/ts-morph/@ts-morph/common/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], + "electron-builder-squirrel-windows/app-builder-lib/@electron/rebuild/ora/cli-cursor/restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], } } diff --git a/electron/main.cjs b/electron/main.cjs index c77f60e..fd94738 100644 --- a/electron/main.cjs +++ b/electron/main.cjs @@ -43,12 +43,10 @@ function matchGlob(pattern, filePath) { } const { applyMenu } = require('./menu.cjs') -const { parseFolder, parseFiles } = require('./parser-service.cjs') +const { parseFolder, disposeParser } = require('./parser-service.cjs') const projectState = require('./project-state.cjs') const { watchFolder, buildIgnoreSet } = require('./watcher.cjs') -const INCREMENTAL_FILE_THRESHOLD = 25 - let _gitCache = null function getGit() { if (!currentFolder) throw new Error('No project folder is open') @@ -118,14 +116,6 @@ async function resolveSafePath(file) { return absoluteFile } -function detectLineEnding(text) { - return text.includes('\r\n') ? '\r\n' : '\n' -} - -function splitLines(text) { - return text.split(/\r\n|\n/) -} - app.setName('Graphy') app.setAppUserModelId('com.ntgrm.graphy') @@ -290,40 +280,32 @@ async function openFolder(folder) { stopWatcher() stopWatcher = null } - stopWatcher = watchFolder(resolved, (changedFiles) => { + stopWatcher = watchFolder(resolved, () => { if (currentFolder === resolved) { - void runParse(resolved, changedFiles) + void runParse(resolved) } }) await runParse(resolved) } -async function runParse(folder, changedFiles = null) { +async function runParse(folder) { const generation = ++parseGeneration parseError = null parseInFlight = folder broadcastGraph() - const useIncremental = - Array.isArray(changedFiles) && - changedFiles.length > 0 && - changedFiles.length <= INCREMENTAL_FILE_THRESHOLD && - currentGraph !== null - try { - const graph = useIncremental - ? await parseFiles(app, folder, changedFiles, currentGraph) - : await parseFolder(app, folder) + const graph = await parseFolder(app, folder) if (generation !== parseGeneration) return currentGraph = graph - if (!useIncremental) currentLayout = null + currentLayout = null parseError = null projectState.writeCache(folder, graph, currentLayout) } catch (err) { if (generation !== parseGeneration) return parseError = err instanceof Error ? err.message : String(err) - if (!useIncremental) currentGraph = null + currentGraph = null } finally { if (generation === parseGeneration) { parseInFlight = null @@ -1318,3 +1300,7 @@ app.on('window-all-closed', () => { app.quit() } }) + +app.on('before-quit', () => { + disposeParser() +}) diff --git a/electron/parser-service.cjs b/electron/parser-service.cjs index 43429e2..dce4960 100644 --- a/electron/parser-service.cjs +++ b/electron/parser-service.cjs @@ -4,6 +4,11 @@ const path = require('node:path') const PARSER_TIMEOUT_MS = 5 * 60 * 1000 +let child = null +let childBundleMtime = 0 +let nextRequestId = 0 +const pending = new Map() + function resolveParserBundle(app) { const candidates = [ path.join(app.getAppPath(), 'dist-electron', 'parser.cjs'), @@ -23,70 +28,99 @@ function resolveParserBundle(app) { return found } -function runParser(app, folder, { incremental = false, input = null } = {}) { - return new Promise((resolve, reject) => { - const bundlePath = resolveParserBundle(app) - const args = incremental ? [folder, '--incremental'] : [folder] - const child = fork(bundlePath, args, { - env: { ...process.env, ELECTRON_RUN_AS_NODE: '1' }, - stdio: ['ignore', 'inherit', 'inherit', 'ipc'], - }) - - let settled = false - const finish = (fn) => { - if (settled) return - settled = true - clearTimeout(timer) - child.removeAllListeners() - fn() - } +function rejectAllPending(err) { + for (const entry of pending.values()) { + clearTimeout(entry.timer) + entry.reject(err) + } + pending.clear() +} - const timer = setTimeout(() => { - child.kill('SIGKILL') - finish(() => - reject(new Error(`Parser timed out after ${PARSER_TIMEOUT_MS}ms`)), - ) - }, PARSER_TIMEOUT_MS) +function killChild() { + if (!child) return + const existing = child + child = null + existing.removeAllListeners() + try { + existing.kill('SIGKILL') + } catch { + // ignore — process may already be gone + } +} + +function ensureChild(app) { + const bundlePath = resolveParserBundle(app) + const mtime = fs.statSync(bundlePath).mtimeMs + + // Dev: when the parser bundle is rebuilt, recycle the worker so + // the next request runs the freshly built code. + if (child && mtime !== childBundleMtime) { + rejectAllPending(new Error('Parser bundle changed; restarting worker')) + killChild() + } + + if (child) return child + + childBundleMtime = mtime + child = fork(bundlePath, [], { + env: { ...process.env, ELECTRON_RUN_AS_NODE: '1' }, + stdio: ['ignore', 'inherit', 'inherit', 'ipc'], + }) - child.on('message', (msg) => { - if (!msg || typeof msg !== 'object') return - if (msg.type === 'graph') { - finish(() => resolve(msg.graph)) - } else if (msg.type === 'error') { - finish(() => reject(new Error(msg.message))) - } - }) - - child.on('error', (err) => { - finish(() => reject(err)) - }) - - child.on('exit', (code, signal) => { - if (settled) return - finish(() => - reject( - new Error( - `Parser exited unexpectedly (code=${code}, signal=${signal})`, - ), - ), - ) - }) - - if (incremental && input) { - child.send({ type: 'input', ...input }) + child.on('message', (msg) => { + if (!msg || typeof msg !== 'object' || typeof msg.id !== 'number') return + const entry = pending.get(msg.id) + if (!entry) return + pending.delete(msg.id) + clearTimeout(entry.timer) + if (msg.type === 'result') { + entry.resolve(msg.graph) + } else if (msg.type === 'error') { + entry.reject(new Error(msg.message)) } }) + + child.on('error', (err) => { + rejectAllPending(err) + }) + + child.on('exit', (code, signal) => { + child = null + rejectAllPending( + new Error(`Parser exited unexpectedly (code=${code}, signal=${signal})`), + ) + }) + + return child } function parseFolder(app, folder) { - return runParser(app, folder) -} + return new Promise((resolve, reject) => { + let worker + try { + worker = ensureChild(app) + } catch (err) { + reject(err) + return + } -function parseFiles(app, folder, changedFiles, previousGraph) { - return runParser(app, folder, { - incremental: true, - input: { changedFiles, previousGraph }, + const id = ++nextRequestId + const timer = setTimeout(() => { + pending.delete(id) + // The worker may be wedged in a long parse; force a respawn so + // the next request gets a clean state. + killChild() + reject(new Error(`Parser timed out after ${PARSER_TIMEOUT_MS}ms`)) + }, PARSER_TIMEOUT_MS) + + pending.set(id, { resolve, reject, timer }) + worker.send({ type: 'parse', id, folder }) }) } -module.exports = { parseFolder, parseFiles } +function disposeParser() { + rejectAllPending(new Error('Parser disposed')) + killChild() +} + +module.exports = { parseFolder, disposeParser } diff --git a/electron/preload.cjs b/electron/preload.cjs index 007e1c5..6014dfd 100644 --- a/electron/preload.cjs +++ b/electron/preload.cjs @@ -21,9 +21,6 @@ contextBridge.exposeInMainWorld('graphyDesktop', { ipcRenderer.invoke('summary:delete', { nodeId }), onProject: (handler) => subscribe('project:set', handler), onGraph: (handler) => subscribe('graph:set', handler), - readFunctionSource: (payload) => ipcRenderer.invoke('function:read', payload), - writeFunctionSource: (payload) => - ipcRenderer.invoke('function:write', payload), getFileTree: () => ipcRenderer.invoke('graphy:file-tree'), createFile: (filePath) => ipcRenderer.invoke('graphy:create-file', filePath), createDir: (dirPath) => ipcRenderer.invoke('graphy:create-dir', dirPath), diff --git a/package.json b/package.json index 51b40bd..6640b74 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ } }, "dependencies": { - "@anthropic-ai/sdk": "^0.96.0", + "@anthropic-ai/sdk": "^0.97.0", "@base-ui/react": "^1.4.1", "@codemirror/autocomplete": "^6.20.2", "@codemirror/commands": "^6.10.3", @@ -86,8 +86,7 @@ "@codemirror/theme-one-dark": "^6.1.3", "@codemirror/view": "^6.43.0", "@fontsource-variable/geist": "^5.2.9", - "@openai/codex-sdk": "^0.130.0", - "@tabler/icons-react": "^3.44.0", + "@openai/codex-sdk": "^0.131.0", "@tailwindcss/vite": "^4.3.0", "@tanstack/react-devtools": "^0.10.5", "@tanstack/react-router": "^1.170.4", @@ -99,21 +98,14 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", - "codemirror": "^6.0.2", - "date-fns": "^4.2.1", - "elkjs": "^0.11.1", - "embla-carousel-react": "^8.6.0", - "input-otp": "^1.4.2", "lucide-react": "^1.16.0", "next-themes": "^0.4.6", - "nitro": "npm:nitro-nightly@^3.0.1-20260512-093145-0498ce70", + "nitro": "npm:nitro-nightly@^3.0.1-20260518-130639-31265391", "radix-ui": "^1.4.3", "react": "^19.2.6", - "react-day-picker": "^10.0.1", "react-dom": "^19.2.6", "react-markdown": "^10.1.0", "react-resizable-panels": "^4.11.1", - "recharts": "3.8.0", "remark-gfm": "^4.0.1", "shadcn": "^4.7.0", "simple-git": "^3.36.0", @@ -121,14 +113,13 @@ "tailwind-merge": "^3.6.0", "tailwindcss": "^4.3.0", "ts-morph": "^28.0.0", - "tw-animate-css": "^1.4.0", - "vaul": "^1.1.2" + "tw-animate-css": "^1.4.0" }, "devDependencies": { "@tailwindcss/typography": "^0.5.19", "@tanstack/devtools-vite": "^0.7.0", "@tanstack/eslint-config": "^0.4.0", - "@types/node": "^25.8.0", + "@types/node": "^25.9.0", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^6.0.2", @@ -136,13 +127,13 @@ "concurrently": "^9.2.1", "cross-env": "^10.1.0", "electron": "^42.1.0", - "electron-builder": "^25.1.8", - "eslint": "^9.20.0", - "jsdom": "^28.1.0", - "prettier": "^3.8.1", - "typescript": "^6.0.2", - "vite": "^8.0.0", - "vitest": "^4.1.5", + "electron-builder": "^26.8.1", + "eslint": "^10.4.0", + "jsdom": "^29.1.1", + "prettier": "^3.8.3", + "typescript": "^6.0.3", + "vite": "^8.0.13", + "vitest": "^4.1.6", "wait-on": "^9.0.10" }, "pnpm": { diff --git a/scripts/build-parser.ts b/scripts/build-parser.ts index 1fb293e..c4fd412 100644 --- a/scripts/build-parser.ts +++ b/scripts/build-parser.ts @@ -15,7 +15,7 @@ declare const Bun: { } const root = process.cwd() -const entry = path.join(root, 'src/modules/parser/parse-cli.ts') +const entry = path.join(root, 'src/modules/parser/parse-service.ts') const outDir = path.join(root, 'dist-electron') const outFile = 'parser.cjs' diff --git a/src/app/styles.css b/src/app/styles.css index 1066756..037bce9 100644 --- a/src/app/styles.css +++ b/src/app/styles.css @@ -25,7 +25,7 @@ body { .thin-scrollbar { scrollbar-width: thin; - scrollbar-color: rgba(255, 255, 255, 0.06) transparent; + scrollbar-color: var(--chat-scrollbar) transparent; } .thin-scrollbar::-webkit-scrollbar { @@ -36,17 +36,17 @@ body { background: transparent; } .thin-scrollbar::-webkit-scrollbar-thumb { - background: rgba(255, 255, 255, 0.06); + background: var(--chat-scrollbar); border-radius: 8px; border: 2px solid transparent; background-clip: padding-box; } .thin-scrollbar::-webkit-scrollbar-thumb:hover { - background: rgba(255, 255, 255, 0.1); + background: var(--chat-scrollbar-hover); background-clip: padding-box; } .thin-scrollbar::-webkit-scrollbar-thumb:active { - background: rgba(255, 255, 255, 0.14); + background: var(--chat-scrollbar-hover); background-clip: padding-box; } .thin-scrollbar::-webkit-scrollbar-corner { @@ -249,9 +249,9 @@ body { transparent ); --xy-node-color-default: var(--foreground); - --xy-node-border-default: 1px solid var(--border); + --xy-node-border-default: none; --xy-node-background-color-default: var(--card); - --xy-node-boxshadow-selected-default: 0 0 0 1px var(--primary); + --xy-node-boxshadow-selected-default: none; --xy-node-border-radius-default: var(--radius-md); --xy-edge-stroke-default: color-mix( in oklab, @@ -270,29 +270,6 @@ body { --xy-selection-border-default: 1px dashed var(--primary); } -.react-flow__edge.graph-edge .react-flow__edge-path { - stroke: color-mix(in oklab, var(--muted-foreground) 46%, transparent); - stroke-width: 1; - stroke-linecap: square; - shape-rendering: optimizeSpeed; -} - -.react-flow__edge.graph-edge:hover .react-flow__edge-path, -.react-flow__edge.graph-edge.selected .react-flow__edge-path { - stroke: color-mix(in oklab, var(--muted-foreground) 60%, transparent); -} - -.graph-canvas-edges { - color: color-mix(in oklab, var(--muted-foreground) 62%, transparent); -} - -.react-flow__node-code, -.react-flow__node-section, -.react-flow__node-summary { - contain: layout paint style; - z-index: 2; -} - @supports (corner-shape: round) { :where([class~='rounded'], [class*='rounded-']) { corner-shape: var(--corner-continuous); diff --git a/src/modules/ai/tools/graph/graph-stats.tool.ts b/src/modules/ai/tools/graph/graph-stats.tool.ts index 422b7d8..dec9477 100644 --- a/src/modules/ai/tools/graph/graph-stats.tool.ts +++ b/src/modules/ai/tools/graph/graph-stats.tool.ts @@ -51,10 +51,10 @@ export function createGraphStatsTool(graph: Graph): AiTool { const { topN = DEFAULT_TOP_N } = input as GraphStatsInput const n = Math.min(Math.max(topN, 1), 50) - const countsByType = { function: 0, method: 0, arrow: 0, class: 0 } + const countsByType: Partial> = {} const fileCounts = new Map() for (const node of graph.nodes) { - if (node.type in countsByType) countsByType[node.type]++ + countsByType[node.type] = (countsByType[node.type] ?? 0) + 1 fileCounts.set(node.file, (fileCounts.get(node.file) ?? 0) + 1) } diff --git a/src/modules/ai/tools/graph/imported-by.tool.ts b/src/modules/ai/tools/graph/imported-by.tool.ts deleted file mode 100644 index 161e47b..0000000 --- a/src/modules/ai/tools/graph/imported-by.tool.ts +++ /dev/null @@ -1,60 +0,0 @@ -import type { Graph, GraphNode } from '@/modules/parser' - -import type { AiTool } from '../tools.interface' - -interface ImportedByInput { - id?: string -} - -interface SlimNode { - id: string - name: string - type: GraphNode['type'] - file: string - line: number -} - -function slim(node: GraphNode): SlimNode { - return { - id: node.id, - name: node.name, - type: node.type, - file: node.file, - line: node.line, - } -} - -export function createImportedByTool(graph: Graph): AiTool { - const byId = new Map(graph.nodes.map((n) => [n.id, n])) - const importEdges = graph.edges.filter((e) => e.type === 'imports') - - return { - name: 'imported_by', - description: - 'Return every node that imports the given node (incoming "imports" edges). Use this to answer "who imports X?" or "what depends on X?".', - inputSchema: { - type: 'object', - properties: { - id: { - type: 'string', - description: - 'Target node id formatted as "::".', - }, - }, - required: ['id'], - additionalProperties: false, - }, - handler: (input: unknown) => { - const { id } = input as ImportedByInput - if (!id) { - throw new Error('`id` is required.') - } - const sources = importEdges - .filter((e) => e.target === id) - .map((e) => byId.get(e.source)) - .filter((n): n is GraphNode => n !== undefined) - .map(slim) - return { id, importedBy: sources } - }, - } -} diff --git a/src/modules/ai/tools/graph/imports-of.tool.ts b/src/modules/ai/tools/graph/imports-of.tool.ts deleted file mode 100644 index 4f51605..0000000 --- a/src/modules/ai/tools/graph/imports-of.tool.ts +++ /dev/null @@ -1,60 +0,0 @@ -import type { Graph, GraphNode } from '@/modules/parser' - -import type { AiTool } from '../tools.interface' - -interface ImportsOfInput { - id?: string -} - -interface SlimNode { - id: string - name: string - type: GraphNode['type'] - file: string - line: number -} - -function slim(node: GraphNode): SlimNode { - return { - id: node.id, - name: node.name, - type: node.type, - file: node.file, - line: node.line, - } -} - -export function createImportsOfTool(graph: Graph): AiTool { - const byId = new Map(graph.nodes.map((n) => [n.id, n])) - const importEdges = graph.edges.filter((e) => e.type === 'imports') - - return { - name: 'imports_of', - description: - 'Return every node that the given node imports (outgoing "imports" edges). Use this to answer "what does X import?" or "what modules does X depend on?".', - inputSchema: { - type: 'object', - properties: { - id: { - type: 'string', - description: - 'Source node id formatted as "::".', - }, - }, - required: ['id'], - additionalProperties: false, - }, - handler: (input: unknown) => { - const { id } = input as ImportsOfInput - if (!id) { - throw new Error('`id` is required.') - } - const targets = importEdges - .filter((e) => e.source === id) - .map((e) => byId.get(e.target)) - .filter((n): n is GraphNode => n !== undefined) - .map(slim) - return { id, imports: targets } - }, - } -} diff --git a/src/modules/ai/tools/graph/index.ts b/src/modules/ai/tools/graph/index.ts index ee4c946..dfe5af1 100644 --- a/src/modules/ai/tools/graph/index.ts +++ b/src/modules/ai/tools/graph/index.ts @@ -9,8 +9,6 @@ import { createFindPathTool } from './find-path.tool' import { createGetNeighborsTool } from './get-neighbors.tool' import { createGetNodeTool } from './get-node.tool' import { createGraphStatsTool } from './graph-stats.tool' -import { createImportedByTool } from './imported-by.tool' -import { createImportsOfTool } from './imports-of.tool' import { createInspectClassTool } from './inspect-class.tool' import { createListNodesTool } from './list-nodes.tool' import { createReadNodeSourceTool } from './read-node-source.tool' @@ -26,8 +24,6 @@ export function createGraphTools(graph: Graph | null): AiTool[] { createFindCallersTool(inspector), createFindCalleesTool(inspector), createReadNodeSourceTool(graph), - createImportsOfTool(graph), - createImportedByTool(graph), createTypeAtTool(), createGetNeighborsTool(graph, inspector), createFindPathTool(graph), diff --git a/src/modules/ai/tools/graph/list-nodes.tool.ts b/src/modules/ai/tools/graph/list-nodes.tool.ts index fd9bd15..0d1ff8a 100644 --- a/src/modules/ai/tools/graph/list-nodes.tool.ts +++ b/src/modules/ai/tools/graph/list-nodes.tool.ts @@ -3,8 +3,6 @@ import type { Graph, GraphNode, NodeType } from '@/modules/parser' import type { AiTool } from '../tools.interface' const NODE_TYPES: NodeType[] = [ - 'file', - 'route', 'component', 'hook', 'function', @@ -50,7 +48,7 @@ export function createListNodesTool(graph: Graph): AiTool { return { name: 'list_nodes', description: - 'List nodes in the parsed code graph. Nodes include files, routes, components, hooks, functions, classes, objects, and methods. Filters are optional and combine with AND. Use this to discover what exists before asking for details with `get_node` or `inspect_class`.', + 'List nodes in the parsed code graph. Nodes include components, hooks, functions, classes, objects, and methods. Filters are optional and combine with AND. Use this to discover what exists before asking for details with `get_node` or `inspect_class`.', inputSchema: { type: 'object', properties: { diff --git a/src/modules/ai/tools/graph/read-node-source.tool.ts b/src/modules/ai/tools/graph/read-node-source.tool.ts index 04a7db2..2be99f0 100644 --- a/src/modules/ai/tools/graph/read-node-source.tool.ts +++ b/src/modules/ai/tools/graph/read-node-source.tool.ts @@ -11,7 +11,6 @@ export function createReadNodeSourceTool(graph: Graph): AiTool { const byId = new Map( graph.nodes.map((node) => [node.id, node]), ) - const root = graph.root return { name: 'read_node_source', description: @@ -44,12 +43,14 @@ export function createReadNodeSourceTool(graph: Graph): AiTool { reason: 'Desktop bridge unavailable in this runtime.', } } - const result = await desktop.readFunctionSource({ - root, - file: node.file, + const result = await desktop.readProjectFile({ + path: node.file, startLine: node.line, endLine: node.endLine, }) + if (!result.found) { + return { found: false, id } + } return { found: true, id, diff --git a/src/modules/diff-viewer/lib/diff-to-node-status.ts b/src/modules/diff-viewer/lib/diff-to-node-status.ts index 71cd619..d8512fb 100644 --- a/src/modules/diff-viewer/lib/diff-to-node-status.ts +++ b/src/modules/diff-viewer/lib/diff-to-node-status.ts @@ -22,8 +22,6 @@ export function diffToNodeStatus( const result = new Map() for (const node of graph.nodes) { - if (node.type === 'file') continue - const ranges = fileRanges.get(node.file) if (!ranges) continue diff --git a/src/modules/files/components/file-tree-node.tsx b/src/modules/files/components/file-tree-node.tsx index d19f6a0..7a05581 100644 --- a/src/modules/files/components/file-tree-node.tsx +++ b/src/modules/files/components/file-tree-node.tsx @@ -161,7 +161,7 @@ export function FileTreeNode({ node, depth }: Props) { } const isActive = currentFile?.path === node.path - const { icon: FileIcon, color } = getFileIcon(node.name) + const FileIcon = getFileIcon(node.name) return ( - + {isRenaming ? ( void onCancel: () => void } ->(function RenameInput({ value, onChange, onCommit, onCancel }, ref) { +>(function ({ value, onChange, onCommit, onCancel }, ref) { return ( void onCancel: () => void } ->(function NewEntryInput({ kind, onCommit, onCancel }, ref) { +>(function ({ kind, onCommit, onCancel }, ref) { const [value, setValue] = useState('') const doneRef = useRef(false) const Icon = kind === 'dir' ? Folder : File @@ -46,3 +46,5 @@ export const NewEntryInput = forwardRef< ) }) + +NewEntryInput.displayName = 'NewEntryInput' diff --git a/src/modules/files/components/tab-bar.tsx b/src/modules/files/components/tab-bar.tsx index 93c6fd7..8dcb76e 100644 --- a/src/modules/files/components/tab-bar.tsx +++ b/src/modules/files/components/tab-bar.tsx @@ -15,7 +15,7 @@ export function TabBar() { {tabs.map((tab, i) => { const isActive = i === activeIndex const isDirty = tab.content !== tab.savedContent - const { icon: Icon, color } = getFileIcon(tab.name) + const Icon = getFileIcon(tab.name) return ( @@ -147,7 +125,12 @@ export function FunctionSheet({ )} {(status === 'ready' || status === 'saving') && ( - + )} diff --git a/src/modules/graph/components/graph-canvas.tsx b/src/modules/graph/components/graph-canvas.tsx index e1b99cd..dc30786 100644 --- a/src/modules/graph/components/graph-canvas.tsx +++ b/src/modules/graph/components/graph-canvas.tsx @@ -1,115 +1,120 @@ import { ReactFlow, useNodesState, useReactFlow } from '@xyflow/react' import type { Edge, Node, NodeTypes } from '@xyflow/react' -import { useCallback, useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' -import { CanvasEdges } from '@/modules/graph/components/canvas-edges' -import { CodeNode } from '@/modules/graph/components/code-node' +import { DiffBootstrap } from '@/modules/diff-viewer' import { EmptyState } from '@/modules/graph/components/empty-state' +import { FileNode } from '@/modules/graph/components/file-node' +import { FolderNode } from '@/modules/graph/components/folder-node' import { FunctionSheet } from '@/modules/graph/components/function-sheet' import type { FunctionSheetTarget } from '@/modules/graph/components/function-sheet' -import { SectionNode } from '@/modules/graph/components/section-node' -import { SummaryNode } from '@/modules/graph/components/summary-node' import { useGraph } from '@/modules/graph/hooks/use-graph' import { useProject } from '@/modules/graph/hooks/use-project' import { toXYFlow } from '@/modules/graph/lib/to-xyflow' -import type { XYFlowGraph } from '@/modules/graph/lib/to-xyflow' -import type { GraphNodeData } from '@/modules/graph/types' -import { NodeSummarySheet } from '@/modules/node-summary' -import { getDesktop } from '@/shared/lib/desktop' +import type { GraphLayout, GraphNodeData } from '@/modules/graph/types' import { clearGraphFocus, useGraphFocusRequest } from '@/shared/lib/graph-focus' -import { DiffBootstrap } from '@/modules/diff-viewer' const nodeTypes: NodeTypes = { - code: CodeNode, - section: SectionNode, - summary: SummaryNode, + file: FileNode, + folder: FolderNode, +} + +const OUTGOING_COLOR = '#38bdf8' +const INCOMING_COLOR = '#fbbf24' + +type GraphCanvasProps = { + layout: GraphLayout } -export function GraphCanvas() { - const { graph, folder, loading, error, layout: rawLayout } = useGraph() - const cachedLayout = rawLayout as XYFlowGraph | null +export function GraphCanvas({ layout }: GraphCanvasProps) { + const { graph, folder, loading, error } = useGraph() const { recents, openFolder, openRecent } = useProject() const { fitView } = useReactFlow() const [nodes, setNodes, onNodesChange] = useNodesState>( [], ) - const [layoutEdges, setLayoutEdges] = useState([]) + const [treeEdges, setTreeEdges] = useState([]) + const [callEdges, setCallEdges] = useState([]) const [layouting, setLayouting] = useState(false) const [layoutError, setLayoutError] = useState(null) const [sheetTarget, setSheetTarget] = useState( null, ) - const [summaryNodeId, setSummaryNodeId] = useState(null) - const [expandedGroups, setExpandedGroups] = useState>( - () => new Set(), - ) + const [hoveredId, setHoveredId] = useState(null) const focusRequest = useGraphFocusRequest() const lastFocusTs = useRef(0) - const pendingClickTimer = useRef(null) + + const callAdjacency = useMemo(() => { + const outgoing = new Map() + const incoming = new Map() + for (const edge of callEdges) { + const out = outgoing.get(edge.source) ?? [] + out.push(edge) + outgoing.set(edge.source, out) + const inc = incoming.get(edge.target) ?? [] + inc.push(edge) + incoming.set(edge.target, inc) + } + return { outgoing, incoming } + }, [callEdges]) + + const hoveredCallEdges = useMemo(() => { + if (!hoveredId) return [] + const out = (callAdjacency.outgoing.get(hoveredId) ?? []).map((edge) => ({ + ...edge, + style: { stroke: OUTGOING_COLOR, strokeWidth: 1.5 }, + zIndex: 1000, + })) + const inc = (callAdjacency.incoming.get(hoveredId) ?? []).map((edge) => ({ + ...edge, + style: { stroke: INCOMING_COLOR, strokeWidth: 1.5 }, + zIndex: 1000, + })) + return [...out, ...inc] + }, [hoveredId, callAdjacency]) + + const renderedEdges = useMemo( + () => [...treeEdges, ...hoveredCallEdges], + [treeEdges, hoveredCallEdges], + ) const handleNodeClick = useCallback( (_event: unknown, node: Node) => { - if (node.data.kind === 'summary') { - setExpandedGroups((current) => { - const next = new Set(current) - next.add(node.id) - return next - }) - return - } - if (node.data.kind !== 'code') return + if (node.data.kind !== 'file') return - if (pendingClickTimer.current !== null) { - window.clearTimeout(pendingClickTimer.current) - } - pendingClickTimer.current = window.setTimeout(() => { - pendingClickTimer.current = null - setSummaryNodeId(node.id) - }, 220) + setSheetTarget({ + displayName: node.data.displayName, + file: node.data.file, + line: 1, + }) }, [], ) - const handleNodeDoubleClick = useCallback( + const handleNodeMouseEnter = useCallback( (_event: unknown, node: Node) => { - if (node.data.kind !== 'code') return - if (pendingClickTimer.current !== null) { - window.clearTimeout(pendingClickTimer.current) - pendingClickTimer.current = null - } - setSheetTarget({ - displayName: node.data.displayName, - file: node.data.file, - startLine: node.data.line, - endLine: node.data.endLine, - }) + if (node.data.kind !== 'file') return + setHoveredId(node.id) }, [], ) - useEffect(() => { - return () => { - if (pendingClickTimer.current !== null) { - window.clearTimeout(pendingClickTimer.current) - } - } + const handleNodeMouseLeave = useCallback(() => { + setHoveredId(null) }, []) const handleSheetOpenChange = useCallback((open: boolean) => { if (!open) setSheetTarget(null) }, []) - useEffect(() => { - setExpandedGroups(new Set()) - }, [graph]) - useEffect(() => { let cancelled = false let fitFrame: number | null = null if (!graph) { setNodes([]) - setLayoutEdges([]) + setTreeEdges([]) + setCallEdges([]) setLayouting(false) setLayoutError(null) return () => { @@ -117,31 +122,18 @@ export function GraphCanvas() { } } - if (cachedLayout && expandedGroups.size === 0) { - setNodes(cachedLayout.nodes) - setLayoutEdges(cachedLayout.edges) - setLayouting(false) - setLayoutError(null) - fitFrame = window.requestAnimationFrame(() => { - fitView({ padding: 0.25, duration: 220 }) - }) - return () => { - if (fitFrame !== null) window.cancelAnimationFrame(fitFrame) - } - } - setLayouting(true) setLayoutError(null) - toXYFlow(graph, { expandedGroups }) + toXYFlow(graph, layout) .then((xyflow) => { if (cancelled) return setNodes(xyflow.nodes) - setLayoutEdges(xyflow.edges) + setTreeEdges(xyflow.treeEdges) + setCallEdges(xyflow.callEdges) fitFrame = window.requestAnimationFrame(() => { fitView({ padding: 0.25, duration: 220 }) }) - if (expandedGroups.size === 0) getDesktop()?.cacheLayout(xyflow) }) .catch((err: unknown) => { if (cancelled) return @@ -155,14 +147,14 @@ export function GraphCanvas() { cancelled = true if (fitFrame !== null) window.cancelAnimationFrame(fitFrame) } - }, [expandedGroups, fitView, graph, cachedLayout, setNodes]) + }, [fitView, graph, layout, setNodes]) useEffect(() => { if (!focusRequest || focusRequest.timestamp === lastFocusTs.current) return lastFocusTs.current = focusRequest.timestamp const matching = nodes .filter( - (n) => n.data.kind === 'code' && n.data.file === focusRequest.file, + (n) => n.data.kind === 'file' && n.data.file === focusRequest.file, ) .map((n) => n.id) if (matching.length > 0) { @@ -195,7 +187,7 @@ export function GraphCanvas() { ) } - if ((loading || layouting) && nodes.length === 0 && !cachedLayout) { + if ((loading || layouting) && nodes.length === 0) { return (
{loading ? 'Parsing…' : 'Arranging…'} @@ -208,10 +200,11 @@ export function GraphCanvas() { - - + /> - { - if (!open) setSummaryNodeId(null) - }} - /> ) } diff --git a/src/modules/graph/components/graph-legend.tsx b/src/modules/graph/components/graph-legend.tsx deleted file mode 100644 index f896abf..0000000 --- a/src/modules/graph/components/graph-legend.tsx +++ /dev/null @@ -1,116 +0,0 @@ -import { Info } from 'lucide-react' -import { useState } from 'react' - -import type { NodeType } from '@/modules/parser' -import { Button } from '@/shared/ui/button' -import { Tooltip, TooltipContent, TooltipTrigger } from '@/shared/ui/tooltip' - -const LEGEND_ITEMS: { type: NodeType; abbr: string; label: string }[] = [ - { type: 'file', abbr: 'file', label: 'File' }, - { type: 'route', abbr: 'route', label: 'Route file' }, - { type: 'component', abbr: 'cmp', label: 'Component' }, - { type: 'hook', abbr: 'hook', label: 'Hook' }, - { type: 'function', abbr: 'fn', label: 'Function' }, - { type: 'arrow', abbr: 'fn', label: 'Arrow function' }, - { type: 'class', abbr: 'cls', label: 'Class' }, - { type: 'object', abbr: 'obj', label: 'Object literal' }, - { type: 'method', abbr: 'm', label: 'Method' }, - { type: 'constructor', abbr: 'ctor', label: 'Constructor' }, - { type: 'getter', abbr: 'get', label: 'Getter' }, - { type: 'setter', abbr: 'set', label: 'Setter' }, -] - -function accentColor(type: NodeType): string { - switch (type) { - case 'file': - return 'bg-muted-foreground' - case 'route': - return 'bg-rose-500' - case 'component': - case 'class': - case 'object': - return 'bg-amber-500' - case 'hook': - case 'method': - case 'constructor': - return 'bg-violet-500' - case 'getter': - case 'setter': - return 'bg-teal-500' - case 'arrow': - return 'bg-sky-500' - case 'function': - default: - return 'bg-primary' - } -} - -function labelColor(type: NodeType): string { - switch (type) { - case 'file': - return 'text-muted-foreground' - case 'route': - return 'text-rose-500' - case 'component': - case 'class': - case 'object': - return 'text-amber-600' - case 'hook': - case 'method': - case 'constructor': - return 'text-violet-500' - case 'getter': - case 'setter': - return 'text-teal-500' - case 'arrow': - return 'text-sky-500' - case 'function': - default: - return 'text-primary' - } -} - -export function GraphLegend() { - const [open, setOpen] = useState(false) - - return ( -
- {open && ( -
- {LEGEND_ITEMS.map((item) => ( -
- - - {item.abbr} - - - {item.label} - -
- ))} -
- )} - - - - - - Node legend - -
- ) -} diff --git a/src/modules/graph/components/layout-selector.tsx b/src/modules/graph/components/layout-selector.tsx new file mode 100644 index 0000000..e3d1673 --- /dev/null +++ b/src/modules/graph/components/layout-selector.tsx @@ -0,0 +1,69 @@ +import { Network, Orbit } from 'lucide-react' + +import { Button } from '@/shared/ui/button' +import { Separator } from '@/shared/ui/separator' +import { Tooltip, TooltipContent, TooltipTrigger } from '@/shared/ui/tooltip' + +import type { GraphLayout } from '@/modules/graph/types' + +type Props = { + value: GraphLayout + onChange: (layout: GraphLayout) => void +} + +export function LayoutSelector({ value, onChange }: Props) { + return ( +
+ onChange('tree')} + > + + +
+ +
+ onChange('radial')} + > + + +
+ ) +} + +function LayoutBtn({ + active, + tip, + onClick, + children, +}: { + active: boolean + tip: string + onClick: () => void + children: React.ReactNode +}) { + return ( + + + + + {tip} + + ) +} diff --git a/src/modules/graph/components/section-node.tsx b/src/modules/graph/components/section-node.tsx deleted file mode 100644 index 550c478..0000000 --- a/src/modules/graph/components/section-node.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import type { NodeProps } from '@xyflow/react' -import { memo } from 'react' - -import type { SectionNodeData } from '@/modules/graph/types' - -type SectionNodeProps = NodeProps & { data: SectionNodeData } - -function SectionNodeImpl({ data, selected }: SectionNodeProps) { - return ( -
- ) -} - -export const SectionNode = memo(SectionNodeImpl) diff --git a/src/modules/graph/components/summary-node.tsx b/src/modules/graph/components/summary-node.tsx deleted file mode 100644 index 31d92a8..0000000 --- a/src/modules/graph/components/summary-node.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { Handle, Position } from '@xyflow/react' -import type { NodeProps } from '@xyflow/react' -import { Layers } from 'lucide-react' -import { memo } from 'react' - -import type { SummaryNodeData } from '@/modules/graph/types' - -type SummaryNodeProps = NodeProps & { data: SummaryNodeData } - -function SummaryNodeImpl({ data, selected }: SummaryNodeProps) { - return ( -
- - -
-
- - - {data.label} - -
- -
- {data.subtitle} -
-
- - - -
- ) -} - -export const SummaryNode = memo(SummaryNodeImpl) diff --git a/src/modules/graph/lib/depth-color.ts b/src/modules/graph/lib/depth-color.ts new file mode 100644 index 0000000..49935e1 --- /dev/null +++ b/src/modules/graph/lib/depth-color.ts @@ -0,0 +1,12 @@ +export interface DepthColor { + accent: string + surface: string +} + +export function colorForDepth(depth: number): DepthColor { + const hue = (depth * 55 + 30) % 360 + return { + accent: `hsl(${hue} 70% 58%)`, + surface: `hsl(${hue} 70% 55% / 0.10)`, + } +} diff --git a/src/modules/graph/lib/to-xyflow.test.ts b/src/modules/graph/lib/to-xyflow.test.ts deleted file mode 100644 index e0fb551..0000000 --- a/src/modules/graph/lib/to-xyflow.test.ts +++ /dev/null @@ -1,256 +0,0 @@ -import { describe, expect, it } from 'vitest' - -import type { Graph, GraphNode } from '@/modules/parser' -import { toXYFlow } from '@/modules/graph/lib/to-xyflow' - -describe('toXYFlow', () => { - it('summarizes noisy detail without losing cross-boundary edges', async () => { - const graph = makeGraph() - - const result = await toXYFlow(graph) - - expect(result.nodes.map((node) => node.id).sort()).toEqual([ - 'api/userController.ts::registerUser', - 'db/database.ts::Database.saveUser', - 'index.ts::seedDemo', - 'section:index.ts::seedDemo', - 'services/userService.ts::UserService.create', - 'summary:isolated:utils/format.ts', - 'summary:src/shared/ui', - ]) - expect( - result.edges.map((edge) => `${edge.source}->${edge.target}`), - ).toEqual( - expect.arrayContaining([ - 'api/userController.ts::registerUser->summary:src/shared/ui', - ]), - ) - expect(new Set(result.edges.map((edge) => edge.id)).size).toBe( - result.edges.length, - ) - }) - - it('places connected nodes inside an entry section', async () => { - const result = await toXYFlow(makeGraph()) - const section = result.nodes.find( - (node) => node.id === 'section:index.ts::seedDemo', - ) - const sectionChildren = result.nodes.filter( - (node) => node.parentId === section?.id, - ) - - expect(section?.type).toBe('section') - expect(sectionChildren.length).toBeGreaterThan(0) - expect( - sectionChildren.every( - (node) => node.position.x >= 0 && node.position.y >= 0, - ), - ).toBe(true) - }) - - it('assigns finite numeric positions', async () => { - const result = await toXYFlow(makeGraph()) - - for (const node of result.nodes) { - expect(Number.isFinite(node.position.x)).toBe(true) - expect(Number.isFinite(node.position.y)).toBe(true) - } - }) - - it('expands summarized groups on request', async () => { - const result = await toXYFlow(makeGraph(), { - expandedGroups: ['summary:src/shared/ui'], - }) - - expect(result.nodes.map((node) => node.id)).toContain( - 'src/shared/ui/button.tsx::Button', - ) - expect(result.nodes.map((node) => node.id)).not.toContain( - 'summary:src/shared/ui', - ) - }) - - it('places direct callees to the right of their callers', async () => { - const result = await toXYFlow(makeGraph()) - const byId = new Map(result.nodes.map((node) => [node.id, node])) - const caller = byId.get('api/userController.ts::registerUser') - const callee = byId.get('services/userService.ts::UserService.create') - - expect(caller).toBeDefined() - expect(callee).toBeDefined() - expect(callee?.position.x).toBeGreaterThan(caller?.position.x ?? Infinity) - }) - - it('centers source-only entry nodes against their outgoing flow', async () => { - const result = await toXYFlow(makeGraph()) - const byId = new Map(result.nodes.map((node) => [node.id, node])) - const entry = byId.get('index.ts::seedDemo') - const firstTarget = byId.get('api/userController.ts::registerUser') - const secondTarget = byId.get('db/database.ts::Database.saveUser') - - expect(entry).toBeDefined() - expect(firstTarget).toBeDefined() - expect(secondTarget).toBeDefined() - - const entryCenter = (entry?.position.y ?? 0) + 27 - const targetMedian = - ((firstTarget?.position.y ?? 0) + (secondTarget?.position.y ?? 0)) / 2 + - 27 - - expect(Math.abs(entryCenter - targetMedian)).toBeLessThan(1) - }) - - it('keeps nodes in the same column from overlapping', async () => { - const result = await toXYFlow(makeGraph()) - const columns = new Map() - - for (const node of result.nodes) { - const columnKey = Math.round(node.position.x / 8) * 8 - const columnNodes = columns.get(columnKey) ?? [] - columnNodes.push(node) - columns.set(columnKey, columnNodes) - } - - for (const columnNodes of columns.values()) { - const sortedNodes = [...columnNodes].sort( - (a, b) => a.position.y - b.position.y, - ) - - for (let index = 1; index < sortedNodes.length; index += 1) { - const previous = sortedNodes[index - 1] - const current = sortedNodes[index] - - expect(current.position.y - previous.position.y).toBeGreaterThanOrEqual( - 54, - ) - } - } - }) - - it('keeps disconnected nodes separated from the main flow', async () => { - const result = await toXYFlow(makeGraph()) - const connectedNodes = result.nodes.filter( - (node) => node.id !== 'summary:isolated:utils/format.ts', - ) - const unusedNode = result.nodes.find( - (node) => node.id === 'summary:isolated:utils/format.ts', - ) - const connectedBottom = Math.max( - ...connectedNodes.map((node) => node.position.y), - ) - - expect(unusedNode).toBeDefined() - expect(unusedNode?.position.y).toBeGreaterThan(connectedBottom + 200) - }) - - it('handles empty graphs', async () => { - const result = await toXYFlow({ - version: '1', - language: 'typescript', - root: '/tmp/project', - nodes: [], - edges: [], - }) - - expect(result).toEqual({ nodes: [], edges: [] }) - }) -}) - -function makeGraph(): Graph { - return { - version: '1', - language: 'typescript', - root: '/tmp/project', - nodes: [ - makeNode({ - id: 'index.ts::seedDemo', - name: 'seedDemo', - file: 'index.ts', - line: 4, - outDegree: 2, - }), - makeNode({ - id: 'api/userController.ts::registerUser', - name: 'registerUser', - file: 'api/userController.ts', - line: 4, - inDegree: 1, - outDegree: 1, - }), - makeNode({ - id: 'services/userService.ts::UserService.create', - name: 'UserService.create', - type: 'method', - file: 'services/userService.ts', - line: 7, - inDegree: 1, - outDegree: 1, - }), - makeNode({ - id: 'db/database.ts::Database.saveUser', - name: 'Database.saveUser', - type: 'method', - file: 'db/database.ts', - line: 8, - inDegree: 2, - }), - makeNode({ - id: 'utils/format.ts::slugify', - name: 'slugify', - file: 'utils/format.ts', - line: 1, - }), - makeNode({ - id: 'src/shared/ui/button.tsx::Button', - name: 'Button', - file: 'src/shared/ui/button.tsx', - line: 4, - inDegree: 1, - }), - ], - edges: [ - { - source: 'index.ts::seedDemo', - target: 'api/userController.ts::registerUser', - type: 'calls', - }, - { - source: 'index.ts::seedDemo', - target: 'db/database.ts::Database.saveUser', - type: 'calls', - }, - { - source: 'api/userController.ts::registerUser', - target: 'services/userService.ts::UserService.create', - type: 'calls', - }, - { - source: 'services/userService.ts::UserService.create', - target: 'db/database.ts::Database.saveUser', - type: 'calls', - }, - { - source: 'api/userController.ts::registerUser', - target: 'src/shared/ui/button.tsx::Button', - type: 'calls', - }, - ], - } -} - -function makeNode(node: Partial & Pick) { - return { - type: 'function', - file: 'index.ts', - line: 1, - endLine: 1, - signature: '()', - isAsync: false, - isExported: true, - isStatic: false, - bodyLines: 1, - inDegree: 0, - outDegree: 0, - ...node, - } satisfies GraphNode -} diff --git a/src/modules/graph/lib/to-xyflow.ts b/src/modules/graph/lib/to-xyflow.ts index 4883ab1..5dba3aa 100644 --- a/src/modules/graph/lib/to-xyflow.ts +++ b/src/modules/graph/lib/to-xyflow.ts @@ -1,694 +1,424 @@ import type { Edge, Node } from '@xyflow/react' -import ELK from 'elkjs/lib/elk.bundled.js' -import type { ElkExtendedEdge, ElkNode } from 'elkjs/lib/elk.bundled.js' import type { Graph } from '@/modules/parser' import type { - CodeNodeData, + FileNodeData, + FolderNodeData, + GraphLayout, GraphNodeData, - SectionNodeData, - SummaryNodeData, } from '@/modules/graph/types' -const NODE_WIDTH = 240 -const NODE_HEIGHT = 54 -const COLUMN_X_TOLERANCE = 8 -const MIN_COLUMN_NODE_GAP = 18 -const COMPONENT_ROW_WIDTH = 3600 -const COMPONENT_GAP_X = 220 -const COMPONENT_GAP_Y = 160 -const SECTION_PADDING_X = 48 -const SECTION_PADDING_TOP = 42 -const SECTION_PADDING_BOTTOM = 42 -const SECTION_MIN_WIDTH = 420 -const SECTION_MIN_HEIGHT = 180 -const UNUSED_COLUMNS = 6 -const UNUSED_COLUMN_GAP = 300 -const UNUSED_ROW_GAP = 92 -const UNUSED_SECTION_GAP = 180 - -const elk = new ELK() +const FILE_NODE_WIDTH = 240 +const FILE_NODE_HEIGHT = 54 +const FOLDER_NODE_WIDTH = 160 +const FOLDER_NODE_HEIGHT = 32 + +const RING_BASE = 220 +const RING_STEP = 240 +const MIN_ARC = 170 + +const COL_CLEARANCE = 80 +const ROW_GAP = 78 +const SUBTREE_GAP = 96 + +const TREE_EDGE_STYLE = { + stroke: 'var(--muted-foreground)', + strokeWidth: 2, +} export interface XYFlowGraph { nodes: Array> - edges: Array + treeEdges: Edge[] + callEdges: Edge[] } -export interface XYFlowOptions { - expandedGroups?: Iterable +interface FolderTree { + path: string + name: string + subfolders: FolderTree[] + files: Array<{ id: string; data: FileNodeData }> +} + +interface Placed { + id: string + x: number + y: number } export async function toXYFlow( graph: Graph, - options: XYFlowOptions = {}, + layout: GraphLayout = 'tree', ): Promise { - const summarized = summarizeGraph(graph, options) - const nodes = summarized.nodes - const edges = summarized.edges + const edgeType = layout === 'radial' ? 'straight' : 'smoothstep' + const { files, callEdges } = collectFiles(graph, edgeType, layout) + if (files.length === 0) { + return { nodes: [], treeEdges: [], callEdges } + } - if (nodes.length === 0) return { nodes, edges } + const root = buildFolderTree(files) + const placements = + layout === 'radial' ? layoutRadial(root) : layoutTidyTree(root) + const { nodes, treeEdges } = emitTree(root, placements, layout, edgeType) - const connectedIds = new Set() - for (const edge of edges) { - connectedIds.add(edge.source) - connectedIds.add(edge.target) - } + return { nodes, treeEdges, callEdges } +} - const connectedNodes = nodes.filter((node) => connectedIds.has(node.id)) - const unusedNodes = nodes.filter((node) => !connectedIds.has(node.id)) +function radiusForDepth(depth: number): number { + if (depth < 0) return 0 + return RING_BASE + depth * RING_STEP +} - if (connectedNodes.length === 0) { - return { - nodes: placeUnusedNodes(unusedNodes, { x: 0, y: 0 }), - edges, +function buildFolderTree( + files: Array<{ id: string; data: FileNodeData }>, +): FolderTree { + const root: FolderTree = { + path: '', + name: '/', + subfolders: [], + files: [], + } + const byPath = new Map([['', root]]) + + function ensure(folderPath: string): FolderTree { + const existing = byPath.get(folderPath) + if (existing) return existing + + const parts = folderPath.split('/') + const name = parts[parts.length - 1] ?? folderPath + const parentPath = parts.slice(0, -1).join('/') + const parent = ensure(parentPath) + const folder: FolderTree = { + path: folderPath, + name, + subfolders: [], + files: [], } + parent.subfolders.push(folder) + byPath.set(folderPath, folder) + return folder } - const layoutedConnectedNodes = packComponents( - await Promise.all( - splitConnectedComponents(connectedNodes, edges).map((component) => - layoutComponent(component.nodes, component.edges), - ), - ), - ) - const unusedOrigin = unusedShelfOrigin(layoutedConnectedNodes) - - return { - nodes: [ - ...layoutedConnectedNodes, - ...placeUnusedNodes(unusedNodes, unusedOrigin), - ], - edges, + for (const file of files) { + ensure(file.data.folder).files.push(file) } -} -interface ConnectedComponent { - nodes: Array> - edges: Array + sortTree(root) + return root } -interface LayoutedComponent { - nodes: Array> - width: number - height: number +function sortTree(folder: FolderTree): void { + folder.subfolders.sort((a, b) => a.name.localeCompare(b.name)) + folder.files.sort((a, b) => + a.data.displayName.localeCompare(b.data.displayName), + ) + for (const sub of folder.subfolders) sortTree(sub) } -function splitConnectedComponents( - nodes: Array>, - edges: Array, -): ConnectedComponent[] { - const nodesById = new Map(nodes.map((node) => [node.id, node])) - const adjacency = new Map>() - - for (const node of nodes) adjacency.set(node.id, new Set()) - - for (const edge of edges) { - if (!nodesById.has(edge.source) || !nodesById.has(edge.target)) continue - adjacency.get(edge.source)?.add(edge.target) - adjacency.get(edge.target)?.add(edge.source) +function layoutTidyTree(root: FolderTree): Map { + // Columns left-to-right, one per depth. Each column is centered on the + // widest node it holds. Children stack vertically inside their parent's + // sub-range; placements store node *centers*. + const widths: number[] = [] + function walkWidth(folder: FolderTree, depth: number): void { + widths[depth] = Math.max(widths[depth] ?? 0, FOLDER_NODE_WIDTH) + if (folder.files.length > 0) { + widths[depth + 1] = Math.max(widths[depth + 1] ?? 0, FILE_NODE_WIDTH) + } + for (const sub of folder.subfolders) walkWidth(sub, depth + 1) + } + walkWidth(root, 0) + + const columnCenters: number[] = [] + let xCursor = 0 + for (let i = 0; i < widths.length; i++) { + const w = widths[i] ?? FOLDER_NODE_WIDTH + columnCenters[i] = xCursor + w / 2 + xCursor += w + COL_CLEARANCE } - const visited = new Set() - const components: ConnectedComponent[] = [] - - for (const node of nodes) { - if (visited.has(node.id)) continue + const placements = new Map() + let nextCenterY = FILE_NODE_HEIGHT / 2 - const stack = [node.id] - const componentIds = new Set() + function place(folder: FolderTree, depth: number): number { + const x = columnCenters[depth] ?? 0 + const childCenters: number[] = [] - while (stack.length > 0) { - const id = stack.pop() - if (!id || visited.has(id)) continue + folder.subfolders.forEach((sub, idx) => { + if (idx > 0) nextCenterY += SUBTREE_GAP + childCenters.push(place(sub, depth + 1)) + }) - visited.add(id) - componentIds.add(id) + if (folder.subfolders.length > 0 && folder.files.length > 0) { + nextCenterY += SUBTREE_GAP + } - for (const next of adjacency.get(id) ?? []) { - if (!visited.has(next)) stack.push(next) - } + for (const file of folder.files) { + const centerY = nextCenterY + nextCenterY += ROW_GAP + placements.set(file.id, { + id: file.id, + x: columnCenters[depth + 1] ?? 0, + y: centerY, + }) + childCenters.push(centerY) } - components.push({ - nodes: nodes.filter((candidate) => componentIds.has(candidate.id)), - edges: edges.filter( - (edge) => - componentIds.has(edge.source) && componentIds.has(edge.target), - ), + let centerY: number + if (childCenters.length === 0) { + centerY = nextCenterY + nextCenterY += ROW_GAP + } else { + const first = childCenters[0] ?? 0 + const last = childCenters[childCenters.length - 1] ?? 0 + centerY = (first + last) / 2 + } + placements.set(folderId(folder.path), { + id: folderId(folder.path), + x, + y: centerY, }) + return centerY } - return components.sort((a, b) => b.nodes.length - a.nodes.length) + place(root, 0) + return placements } -async function layoutComponent( - nodes: Array>, - edges: Array, -): Promise { - if (nodes.length === 0) return { nodes: [], width: 0, height: 0 } - - if (nodes.length === 1) { - const node = nodes[0] - const framed = frameComponent([node], edges) - - return { - nodes: framed.nodes, - width: framed.width, - height: framed.height, +function layoutRadial(root: FolderTree): Map { + // Each node requires a minimum arc length (MIN_ARC) at its ring; an + // internal folder needs at least the sum of its children's required + // angles. The whole tree is uniformly scaled so root's required angle + // fits inside 2π. + const placements = new Map() + const angleCache = new Map() + + function requiredAngle(folder: FolderTree, depth: number): number { + const cached = angleCache.get(folder) + if (cached !== undefined) return cached + + let sum = 0 + for (const sub of folder.subfolders) { + sum += requiredAngle(sub, depth + 1) } + if (folder.files.length > 0) { + sum += (folder.files.length * MIN_ARC) / radiusForDepth(depth + 1) + } + if (sum === 0) { + sum = MIN_ARC / Math.max(radiusForDepth(depth), 1) + } + angleCache.set(folder, sum) + return sum } - const layoutedGraph = await elk.layout({ - id: 'root', - layoutOptions: { - 'elk.algorithm': 'layered', - 'elk.direction': 'RIGHT', - 'elk.edgeRouting': 'ORTHOGONAL', - 'elk.spacing.nodeNode': '44', - 'elk.layered.spacing.nodeNodeBetweenLayers': '135', - 'elk.layered.spacing.edgeEdgeBetweenLayers': '18', - 'elk.layered.spacing.edgeNodeBetweenLayers': '28', - 'elk.layered.nodePlacement.strategy': 'NETWORK_SIMPLEX', - 'elk.layered.crossingMinimization.strategy': 'LAYER_SWEEP', - 'elk.layered.cycleBreaking.strategy': 'GREEDY', - }, - children: nodes.map((node) => ({ - id: node.id, - width: NODE_WIDTH, - height: NODE_HEIGHT, - })), - edges: edges.map((edge) => ({ - id: edge.id, - sources: [edge.source], - targets: [edge.target], - })), - }) - - const layoutedById = new Map( - layoutedGraph.children?.map((node) => [node.id, node]) ?? [], - ) - const layoutedNodes = normalizeNodes( - resolveColumnOverlaps( - centerEntryNodes( - nodes.map((node) => { - const layoutedNode = layoutedById.get(node.id) - return { - ...node, - position: { - x: layoutedNode?.x ?? node.position.x, - y: layoutedNode?.y ?? node.position.y, - }, - } - }), - edges, - ), - ), - ) - const bounds = nodeBounds(layoutedNodes) - const framed = frameComponent(layoutedNodes, edges) - - return { - nodes: framed.nodes, - width: Math.max(bounds.width, framed.width), - height: Math.max(bounds.height, framed.height), - } -} - -function frameComponent( - nodes: Array>, - edges: Array, -): LayoutedComponent { - const bounds = nodeBounds(nodes) - const contentWidth = bounds.width + SECTION_PADDING_X * 2 - const contentHeight = - bounds.height + SECTION_PADDING_TOP + SECTION_PADDING_BOTTOM - const width = Math.max(contentWidth, SECTION_MIN_WIDTH) - const height = Math.max(contentHeight, SECTION_MIN_HEIGHT) - const extraX = Math.max(0, width - contentWidth) / 2 - const extraY = Math.max(0, height - contentHeight) / 2 - const sectionId = `section:${entryNodeIds(nodes, edges).join('|') || nodes[0]?.id || 'empty'}` - const label = sectionLabel(nodes, edges) - const childNodes = nodes.map((node) => ({ - ...node, - parentId: sectionId, - extent: 'parent' as const, - position: { - x: node.position.x + SECTION_PADDING_X + extraX, - y: node.position.y + SECTION_PADDING_TOP + extraY, - }, - })) - const sectionNode: Node = { - id: sectionId, - type: 'section', - position: { x: 0, y: 0 }, - selectable: false, - draggable: false, - data: { - kind: 'section', - label: label.title, - subtitle: label.subtitle, - width, - height, - }, - style: { width, height }, + let rootTotal = 0 + for (const sub of root.subfolders) rootTotal += requiredAngle(sub, 0) + if (root.files.length > 0) { + rootTotal += (root.files.length * MIN_ARC) / radiusForDepth(0) } + const scale = Math.max(1, rootTotal / (2 * Math.PI)) - return { - nodes: [sectionNode, ...childNodes], - width, - height, + function ringRadius(depth: number): number { + if (depth < 0) return 0 + return scale * radiusForDepth(depth) } -} -function entryNodeIds( - nodes: Array>, - edges: Array, -): string[] { - const ids = new Set(nodes.map((node) => node.id)) - const incomingIds = new Set( - edges - .filter((edge) => ids.has(edge.source) && ids.has(edge.target)) - .map((edge) => edge.target), - ) - const outgoingIds = new Set( - edges - .filter((edge) => ids.has(edge.source) && ids.has(edge.target)) - .map((edge) => edge.source), - ) - - return nodes - .filter((node) => !incomingIds.has(node.id) && outgoingIds.has(node.id)) - .map((node) => node.id) - .sort() -} - -function sectionLabel( - nodes: Array>, - edges: Array, -): { title: string; subtitle: string } { - const byId = new Map(nodes.map((node) => [node.id, node])) - const entries = entryNodeIds(nodes, edges) - .map((id) => byId.get(id)) - .filter((node): node is Node => Boolean(node)) - const firstEntry = entries.length > 0 ? entries[0] : undefined - let title = 'Entry flow' - if (firstEntry?.data.kind === 'code') title = firstEntry.data.displayName - if (firstEntry?.data.kind === 'summary') title = firstEntry.data.label - const suffix = entries.length > 1 ? ` + ${entries.length - 1} more` : '' - - return { - title: `${title}${suffix}`, - subtitle: `${nodes.length} symbols`, - } -} + function placeSubtree( + folder: FolderTree, + depth: number, + start: number, + ): void { + const span = requiredAngle(folder, depth) / scale + const angle = start + span / 2 + const r = ringRadius(depth) + placements.set(folderId(folder.path), { + id: folderId(folder.path), + x: r * Math.cos(angle), + y: r * Math.sin(angle), + }) -function packComponents( - components: LayoutedComponent[], -): Array> { - const packedNodes: Array> = [] - let x = 0 - let y = 0 - let rowHeight = 0 - - for (const component of components) { - if (x > 0 && x + component.width > COMPONENT_ROW_WIDTH) { - x = 0 - y += rowHeight + COMPONENT_GAP_Y - rowHeight = 0 + let cursor = start + for (const sub of folder.subfolders) { + const subSpan = requiredAngle(sub, depth + 1) / scale + placeSubtree(sub, depth + 1, cursor) + cursor += subSpan + } + for (const file of folder.files) { + const fileSpan = MIN_ARC / radiusForDepth(depth + 1) / scale + const fileAngle = cursor + fileSpan / 2 + const fr = ringRadius(depth + 1) + placements.set(file.id, { + id: file.id, + x: fr * Math.cos(fileAngle), + y: fr * Math.sin(fileAngle), + }) + cursor += fileSpan } - - packedNodes.push( - ...component.nodes.map((node) => ({ - ...node, - position: { - x: node.parentId ? node.position.x : node.position.x + x, - y: node.parentId ? node.position.y : node.position.y + y, - }, - })), - ) - - x += component.width + COMPONENT_GAP_X - rowHeight = Math.max(rowHeight, component.height) } - return packedNodes -} - -function resolveColumnOverlaps( - nodes: Array>, -): Array> { - const columns = new Map>>() - - for (const node of nodes) { - const columnKey = - Math.round(node.position.x / COLUMN_X_TOLERANCE) * COLUMN_X_TOLERANCE - const columnNodes = columns.get(columnKey) ?? [] - columnNodes.push(node) - columns.set(columnKey, columnNodes) + let cursor = -Math.PI / 2 + for (const sub of root.subfolders) { + placeSubtree(sub, 0, cursor) + cursor += requiredAngle(sub, 0) / scale } - - const yById = new Map() - const minGap = NODE_HEIGHT + MIN_COLUMN_NODE_GAP - - for (const columnNodes of columns.values()) { - if (columnNodes.length < 2) continue - - const sortedNodes = [...columnNodes].sort( - (a, b) => a.position.y - b.position.y, - ) - const originalTop = sortedNodes[0]?.position.y ?? 0 - const originalBottom = - (sortedNodes[sortedNodes.length - 1]?.position.y ?? 0) + NODE_HEIGHT - const packedPositions: number[] = [] - let previousY = -Infinity - - for (const node of sortedNodes) { - const y = Math.max(node.position.y, previousY + minGap) - packedPositions.push(y) - previousY = y - } - - const packedTop = packedPositions[0] ?? 0 - const packedBottom = - (packedPositions[packedPositions.length - 1] ?? 0) + NODE_HEIGHT - const offset = - (originalTop + originalBottom) / 2 - (packedTop + packedBottom) / 2 - - sortedNodes.forEach((node, index) => { - yById.set(node.id, (packedPositions[index] ?? node.position.y) + offset) + for (const file of root.files) { + const fileSpan = MIN_ARC / radiusForDepth(0) / scale + const fileAngle = cursor + fileSpan / 2 + const fr = ringRadius(0) + placements.set(file.id, { + id: file.id, + x: fr * Math.cos(fileAngle), + y: fr * Math.sin(fileAngle), }) + cursor += fileSpan } - return nodes.map((node) => { - const y = yById.get(node.id) - if (y === undefined) return node + return placements +} - return { - ...node, +function emitTree( + root: FolderTree, + placements: Map, + layout: GraphLayout, + edgeType: 'straight' | 'smoothstep', +): { nodes: Array>; treeEdges: Edge[] } { + const nodes: Array> = [] + const treeEdges: Edge[] = [] + + function pushFile( + file: { id: string; data: FileNodeData }, + depth: number, + ): void { + const fileCenter = placements.get(file.id) ?? { x: 0, y: 0 } + nodes.push({ + id: file.id, + type: 'file', position: { - ...node.position, - y, + x: fileCenter.x - FILE_NODE_WIDTH / 2, + y: fileCenter.y - FILE_NODE_HEIGHT / 2, }, - } - }) -} - -function centerEntryNodes( - nodes: Array>, - edges: Array, -): Array> { - const nodesById = new Map(nodes.map((node) => [node.id, node])) - const incomingIds = new Set(edges.map((edge) => edge.target)) - const targetsBySource = new Map() - - for (const edge of edges) { - if (!nodesById.has(edge.source) || !nodesById.has(edge.target)) continue - const targets = targetsBySource.get(edge.source) ?? [] - targets.push(edge.target) - targetsBySource.set(edge.source, targets) - } - - const entryPlacements = nodes - .filter((node) => !incomingIds.has(node.id) && targetsBySource.has(node.id)) - .map((node) => { - const targetCenters = (targetsBySource.get(node.id) ?? []) - .map((targetId) => nodesById.get(targetId)) - .filter((target): target is Node => Boolean(target)) - .map((target) => target.position.y + NODE_HEIGHT / 2) - .sort((a, b) => a - b) - const desiredCenter = median(targetCenters) - - return { - id: node.id, - y: desiredCenter - NODE_HEIGHT / 2, - } + width: FILE_NODE_WIDTH, + height: FILE_NODE_HEIGHT, + data: { ...file.data, depth, layout }, }) - .sort((a, b) => a.y - b.y) - - const entryYById = new Map() - const minEntryGap = NODE_HEIGHT + 52 - let previousY = -Infinity - - for (const placement of entryPlacements) { - const y = Math.max(placement.y, previousY + minEntryGap) - entryYById.set(placement.id, y) - previousY = y } - return nodes.map((node) => { - const y = entryYById.get(node.id) - if (y === undefined) return node - - return { - ...node, + function visit(folder: FolderTree, depth: number): void { + const id = folderId(folder.path) + const center = placements.get(id) ?? { x: 0, y: 0 } + const folderData: FolderNodeData = { + kind: 'folder', + path: folder.path, + name: folder.name, + depth, + layout, + } + nodes.push({ + id, + type: 'folder', position: { - ...node.position, - y, + x: center.x - FOLDER_NODE_WIDTH / 2, + y: center.y - FOLDER_NODE_HEIGHT / 2, }, - } - }) -} - -function median(values: number[]): number { - if (values.length === 0) return 0 - const middle = Math.floor(values.length / 2) - if (values.length % 2 === 1) return values[middle] ?? 0 - - return ((values[middle - 1] ?? 0) + (values[middle] ?? 0)) / 2 -} - -function normalizeNodes( - nodes: Array>, -): Array> { - const bounds = nodeBounds(nodes) - - return nodes.map((node) => ({ - ...node, - position: { - x: node.position.x - bounds.minX, - y: node.position.y - bounds.minY, - }, - })) -} - -function nodeBounds(nodes: Array>): { - minX: number - minY: number - width: number - height: number -} { - const bounds = nodes.reduce( - (acc, node) => ({ - minX: Math.min(acc.minX, node.position.x), - minY: Math.min(acc.minY, node.position.y), - maxX: Math.max(acc.maxX, node.position.x + NODE_WIDTH), - maxY: Math.max(acc.maxY, node.position.y + NODE_HEIGHT), - }), - { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity }, - ) + width: FOLDER_NODE_WIDTH, + height: FOLDER_NODE_HEIGHT, + selectable: false, + draggable: false, + data: folderData, + }) - if (!Number.isFinite(bounds.minX) || !Number.isFinite(bounds.minY)) { - return { minX: 0, minY: 0, width: 0, height: 0 } - } + for (const sub of folder.subfolders) { + const childId = folderId(sub.path) + treeEdges.push({ + id: `tree:${id}->${childId}`, + source: id, + target: childId, + type: edgeType, + style: TREE_EDGE_STYLE, + }) + visit(sub, depth + 1) + } - return { - minX: bounds.minX, - minY: bounds.minY, - width: bounds.maxX - bounds.minX, - height: bounds.maxY - bounds.minY, + for (const file of folder.files) { + pushFile(file, depth + 1) + treeEdges.push({ + id: `tree:${id}->${file.id}`, + source: id, + target: file.id, + type: edgeType, + style: TREE_EDGE_STYLE, + }) + } } -} -function placeUnusedNodes( - nodes: Array>, - origin: { x: number; y: number }, -): Array> { - return nodes.map((node, index) => ({ - ...node, - position: { - x: origin.x + (index % UNUSED_COLUMNS) * UNUSED_COLUMN_GAP, - y: origin.y + Math.floor(index / UNUSED_COLUMNS) * UNUSED_ROW_GAP, - }, - })) -} + for (const sub of root.subfolders) visit(sub, 0) + for (const file of root.files) pushFile(file, 0) -function unusedShelfOrigin(nodes: Array>): { - x: number - y: number -} { - const bounds = nodes.reduce( - (acc, node) => ({ - minX: Math.min(acc.minX, node.position.x), - maxY: Math.max(acc.maxY, node.position.y + nodeHeight(node)), - }), - { minX: Infinity, maxY: -Infinity }, - ) - - return { - x: Number.isFinite(bounds.minX) ? bounds.minX : 0, - y: Number.isFinite(bounds.maxY) ? bounds.maxY + UNUSED_SECTION_GAP : 0, - } -} - -function nodeHeight(node: Node): number { - return node.data.kind === 'section' ? node.data.height : NODE_HEIGHT + return { nodes, treeEdges } } -function qualifiedName(id: string, fallback: string): string { - const idx = id.indexOf('::') - return idx >= 0 ? id.slice(idx + 2) : fallback +function folderId(folderPath: string): string { + return `dir:${folderPath || '/'}` } -function summarizeGraph(graph: Graph, options: XYFlowOptions): XYFlowGraph { - const expandedGroups = new Set(options.expandedGroups ?? []) - const groups = new Map< - string, - { - data: Omit - memberIds: Set - files: Set - } - >() - const visibleIdByOriginalId = new Map() - const visibleNodes: Array> = [] +function collectFiles( + graph: Graph, + edgeType: 'straight' | 'smoothstep', + layout: GraphLayout, +): { + files: Array<{ id: string; data: FileNodeData }> + callEdges: Edge[] +} { + const fileBySymbolId = new Map() + const fileSet = new Set() for (const node of graph.nodes) { - const group = groupForNode(node) - if (!group || expandedGroups.has(group.id)) { - visibleIdByOriginalId.set(node.id, node.id) - visibleNodes.push({ - id: node.id, - type: 'code', - position: { x: 0, y: 0 }, - data: { - kind: 'code', - displayName: qualifiedName(node.id, node.name), - type: node.type, - signature: node.signature, - file: node.file, - line: node.line, - endLine: node.endLine, - isAsync: node.isAsync, - isExported: node.isExported, - isStatic: node.isStatic, - bodyLines: node.bodyLines, - inDegree: node.inDegree, - outDegree: node.outDegree, - }, - }) - continue - } - - const existing = groups.get(group.id) ?? { - data: { - kind: 'summary' as const, - label: group.label, - subtitle: group.subtitle, - count: 0, - fileCount: 0, - }, - memberIds: new Set(), - files: new Set(), - } - existing.data.count += 1 - existing.memberIds.add(node.id) - existing.files.add(node.file) - groups.set(group.id, existing) - visibleIdByOriginalId.set(node.id, group.id) + fileBySymbolId.set(node.id, node.file) + fileSet.add(node.file) } const edgeKeys = new Set() - const visibleEdges: Edge[] = [] + const callEdges: Edge[] = [] + const callsOut = new Map() + const callsIn = new Map() for (const edge of graph.edges) { - const source = visibleIdByOriginalId.get(edge.source) - const target = visibleIdByOriginalId.get(edge.target) + const source = fileBySymbolId.get(edge.source) + const target = fileBySymbolId.get(edge.target) if (!source || !target || source === target) continue - const key = `${source}->${target}:${edge.type}` + const key = `${source}->${target}` if (edgeKeys.has(key)) continue edgeKeys.add(key) - visibleEdges.push({ - id: key, + callsOut.set(source, (callsOut.get(source) ?? 0) + 1) + callsIn.set(target, (callsIn.get(target) ?? 0) + 1) + + callEdges.push({ + id: `call:${key}`, source, target, - type: 'straight', - className: 'graph-edge', - interactionWidth: 0, - selectable: false, - focusable: false, + type: edgeType, }) } - const degreeById = new Map() - for (const edge of visibleEdges) { - const sourceDegree = degreeById.get(edge.source) ?? { - inDegree: 0, - outDegree: 0, - } - sourceDegree.outDegree += 1 - degreeById.set(edge.source, sourceDegree) - - const targetDegree = degreeById.get(edge.target) ?? { - inDegree: 0, - outDegree: 0, - } - targetDegree.inDegree += 1 - degreeById.set(edge.target, targetDegree) - } - - for (const [id, group] of groups) { - const degree = degreeById.get(id) ?? { inDegree: 0, outDegree: 0 } - visibleNodes.push({ - id, - type: 'summary', - position: { x: 0, y: 0 }, + const files = Array.from(fileSet).map((file) => { + const parts = file.split('/') + const displayName = parts[parts.length - 1] ?? file + const folder = parts.slice(0, -1).join('/') + return { + id: file, data: { - ...group.data, - fileCount: group.files.size, - subtitle: `${group.data.subtitle} · ${group.data.count} symbols`, - inDegree: degree.inDegree, - outDegree: degree.outDegree, + kind: 'file' as const, + file, + displayName, + folder, + callsOut: callsOut.get(file) ?? 0, + callsIn: callsIn.get(file) ?? 0, + depth: 0, + layout, }, - }) - } - - return { nodes: visibleNodes, edges: visibleEdges } -} - -function groupForNode(node: Graph['nodes'][number]): - | { - id: string - label: string - subtitle: string - } - | undefined { - if (node.file.startsWith('src/shared/ui/')) { - return { - id: 'summary:src/shared/ui', - label: 'UI primitives', - subtitle: 'src/shared/ui', - } - } - - if (node.inDegree === 0 && node.outDegree === 0) { - const folder = summaryFolder(node.file) - return { - id: `summary:isolated:${folder}`, - label: 'Unconnected symbols', - subtitle: folder, } - } - - return undefined -} + }) -function summaryFolder(file: string): string { - const parts = file.split('/') - if (parts.length <= 1) return file - if (parts[0] === 'src' && parts.length >= 3) { - return parts.slice(0, 3).join('/') - } - return parts.slice(0, 2).join('/') + return { files, callEdges } } diff --git a/src/modules/graph/types.ts b/src/modules/graph/types.ts index f72bd20..c6a28a5 100644 --- a/src/modules/graph/types.ts +++ b/src/modules/graph/types.ts @@ -1,37 +1,22 @@ -import type { NodeType } from '@/modules/parser' +export type GraphLayout = 'tree' | 'radial' -export type CodeNodeData = { - kind: 'code' - displayName: string - type: NodeType - signature: string +export type FileNodeData = { + kind: 'file' file: string - line: number - endLine: number - isAsync: boolean - isExported: boolean - isStatic: boolean - bodyLines: number - inDegree: number - outDegree: number -} - -export type SummaryNodeData = { - kind: 'summary' - label: string - subtitle: string - count: number - fileCount: number - inDegree: number - outDegree: number + displayName: string + folder: string + callsOut: number + callsIn: number + depth: number + layout: GraphLayout } -export type SectionNodeData = { - kind: 'section' - label: string - subtitle: string - width: number - height: number +export type FolderNodeData = { + kind: 'folder' + path: string + name: string + depth: number + layout: GraphLayout } -export type GraphNodeData = CodeNodeData | SummaryNodeData | SectionNodeData +export type GraphNodeData = FileNodeData | FolderNodeData diff --git a/src/modules/node-summary/components/node-summary-sheet.tsx b/src/modules/node-summary/components/node-summary-sheet.tsx deleted file mode 100644 index 7ab92c9..0000000 --- a/src/modules/node-summary/components/node-summary-sheet.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import { FileCode, RefreshCw, Sparkles } from 'lucide-react' - -import { Button } from '@/shared/ui/button' -import { - Sheet, - SheetContent, - SheetDescription, - SheetFooter, - SheetHeader, - SheetTitle, -} from '@/shared/ui/sheet' - -import { useNodeSummary } from '../hooks/use-node-summary' -import { SummaryFacts } from './summary-facts' -import { SummaryOverview } from './summary-overview' -import { SummaryRelationsList } from './summary-relations-list' - -type NodeSummarySheetProps = { - nodeId: string | null - onOpenChange: (open: boolean) => void -} - -export function NodeSummarySheet({ - nodeId, - onOpenChange, -}: NodeSummarySheetProps) { - const { header, callers, callees, overview, status, error, refresh } = - useNodeSummary(nodeId) - const open = nodeId !== null - - return ( - - - -
-
- - Node summary -
- -
- - {header?.displayName ?? 'Node'} - - - {header ? `${header.file}:${header.line}` : ''} - -
- - {header && ( -
- - - {header.signature && ( -
- {header.displayName} - - {header.signature} - -
- )} - -
-

- Overview -

- -
- - - - -
- )} - - - - - -
-
- ) -} diff --git a/src/modules/node-summary/components/summary-facts.tsx b/src/modules/node-summary/components/summary-facts.tsx deleted file mode 100644 index 77f2972..0000000 --- a/src/modules/node-summary/components/summary-facts.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { Badge } from '@/shared/ui/badge' - -import type { NodeSummaryFacts } from '../types' - -type SummaryFactsProps = { - facts: NodeSummaryFacts -} - -export function SummaryFacts({ facts }: SummaryFactsProps) { - const chips: string[] = [] - if (facts.isAsync) chips.push('async') - if (facts.isExported) chips.push('exported') - if (facts.bodyLines > 0) chips.push(`${facts.bodyLines} lines`) - if (facts.inDegree > 0) chips.push(`${facts.inDegree} in`) - if (facts.outDegree > 0) chips.push(`${facts.outDegree} out`) - - if (chips.length === 0) return null - - return ( -
- {chips.map((label) => ( - - {label} - - ))} -
- ) -} diff --git a/src/modules/node-summary/components/summary-overview.tsx b/src/modules/node-summary/components/summary-overview.tsx deleted file mode 100644 index aae31b4..0000000 --- a/src/modules/node-summary/components/summary-overview.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { openSettings } from '@/shared/lib/settings-open' -import { Button } from '@/shared/ui/button' -import { Skeleton } from '@/shared/ui/skeleton' - -import type { SummaryStatus } from '../types' - -type SummaryOverviewProps = { - paragraphs: string[] - status: SummaryStatus - error: string | null - onRetry: () => void -} - -export function SummaryOverview({ - paragraphs, - status, - error, - onRetry, -}: SummaryOverviewProps) { - if (status === 'no-key') { - return - } - - if (status === 'error') { - return ( -
- {error ?? 'Failed to generate summary.'} -
- -
-
- ) - } - - if (status === 'loading' || status === 'validating') { - return - } - - const showCursor = status === 'streaming' - return ( -
- {paragraphs.length === 0 && showCursor && ( - - )} - {paragraphs.map((paragraph, index) => ( -

- {paragraph} - {showCursor && index === paragraphs.length - 1 && ( - - ▍ - - )} -

- ))} -
- ) -} - -function LoadingState({ label }: { label: string }) { - return ( -
-
- {label} -
- - - -
- ) -} - -function NoKeyState() { - return ( -
- - Add a Claude API key in settings to generate node summaries. - -
- -
-
- ) -} - -function statusLabel(status: SummaryStatus): string { - if (status === 'validating') return 'Checking cached summary…' - return 'Generating summary…' -} diff --git a/src/modules/node-summary/components/summary-relations-list.tsx b/src/modules/node-summary/components/summary-relations-list.tsx deleted file mode 100644 index 9adc467..0000000 --- a/src/modules/node-summary/components/summary-relations-list.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import type { NodeType } from '@/modules/parser' - -import type { NodeSummaryRelation } from '../types' - -const TYPE_LABEL: Record = { - file: 'file', - route: 'route', - component: 'cmp', - hook: 'hook', - function: 'fn', - arrow: 'fn', - method: 'm', - class: 'cls', - object: 'obj', - constructor: 'ctor', - getter: 'get', - setter: 'set', -} - -type SummaryRelationsListProps = { - title: string - emptyLabel: string - items: NodeSummaryRelation[] -} - -export function SummaryRelationsList({ - title, - emptyLabel, - items, -}: SummaryRelationsListProps) { - return ( -
-
- {title} - · {items.length} -
- - {items.length === 0 ? ( -

{emptyLabel}

- ) : ( -
    - {items.map((item) => ( -
  • - -
  • - ))} -
- )} -
- ) -} - -function shortFile(file: string): string { - return file.split('/').slice(-2).join('/') -} diff --git a/src/modules/node-summary/hooks/use-node-summary.ts b/src/modules/node-summary/hooks/use-node-summary.ts deleted file mode 100644 index db32e0d..0000000 --- a/src/modules/node-summary/hooks/use-node-summary.ts +++ /dev/null @@ -1,239 +0,0 @@ -import { useCallback, useEffect, useMemo, useRef, useState } from 'react' - -import { CHAT_MODEL_API_ID, readAiConfig } from '@/modules/ai-chat' -import { useGraph } from '@/modules/graph' -import { getDesktop } from '@/shared/lib/desktop' - -import type { - CachedSummary, - NodeSummaryHeader, - NodeSummaryRelation, - SummaryStatus, -} from '../types' -import { buildSummaryPrompt, buildValidatorPrompt } from '../lib/build-prompts' -import { readCachedSummary, writeCachedSummary } from '../lib/cache' -import { computeFingerprint, fingerprintMatches } from '../lib/fingerprint' -import { streamSummary } from '../lib/generate-summary' -import { getNeighbors, getNodeMetadata, toHeader } from '../lib/relations' -import { validateCached } from '../lib/validate-cache' - -export type UseNodeSummary = { - header: NodeSummaryHeader | null - callers: NodeSummaryRelation[] - callees: NodeSummaryRelation[] - overview: string[] - status: SummaryStatus - error: string | null - refresh: () => void -} - -export function useNodeSummary(nodeId: string | null): UseNodeSummary { - const { graph, folder } = useGraph() - const [overview, setOverview] = useState([]) - const [status, setStatus] = useState('idle') - const [error, setError] = useState(null) - const [runToken, setRunToken] = useState(0) - const forceNextRef = useRef(false) - - const derived = useMemo(() => { - if (!graph || !nodeId) { - return { - header: null as NodeSummaryHeader | null, - callers: [] as NodeSummaryRelation[], - callees: [] as NodeSummaryRelation[], - } - } - const node = getNodeMetadata(graph, nodeId) - if (!node) return { header: null, callers: [], callees: [] } - const header = toHeader(node) - const { callers, callees } = getNeighbors(graph, nodeId) - return { header, callers, callees } - }, [graph, nodeId]) - - useEffect(() => { - if (!nodeId) { - setStatus('idle') - setOverview([]) - setError(null) - return - } - if (!graph || !folder || !derived.header) { - setStatus('loading') - setOverview([]) - setError(null) - return - } - - const controller = new AbortController() - const force = forceNextRef.current - forceNextRef.current = false - - void resolve({ - signal: controller.signal, - nodeId, - folder, - header: derived.header, - callers: derived.callers, - callees: derived.callees, - force, - setStatus, - setOverview, - setError, - }) - - return () => controller.abort() - // runToken is intentionally a dep so refresh() forces a re-run. - }, [nodeId, graph, folder, derived, runToken]) - - const refresh = useCallback(() => { - forceNextRef.current = true - setRunToken((n) => n + 1) - }, []) - - return { - header: derived.header, - callers: derived.callers, - callees: derived.callees, - overview, - status, - error, - refresh, - } -} - -async function resolve({ - signal, - nodeId, - folder, - header, - callers, - callees, - force, - setStatus, - setOverview, - setError, -}: { - signal: AbortSignal - nodeId: string - folder: string - header: NodeSummaryHeader - callers: NodeSummaryRelation[] - callees: NodeSummaryRelation[] - force: boolean - setStatus: (s: SummaryStatus) => void - setOverview: (paragraphs: string[]) => void - setError: (msg: string | null) => void -}): Promise { - setError(null) - setOverview([]) - setStatus('loading') - - const config = readAiConfig() - const apiKey = config.keys.claude - if (!apiKey) { - setStatus('no-key') - return - } - const summaryModel = CHAT_MODEL_API_ID[config.defaultModel] - - const desktop = getDesktop() - if (!desktop?.readFunctionSource) { - setError('Summaries require the Graphy desktop app.') - setStatus('error') - return - } - - try { - const { source } = await desktop.readFunctionSource({ - root: folder, - file: header.file, - startLine: header.line, - endLine: header.endLine, - }) - if (isAborted(signal)) return - - const currentFingerprint = await computeFingerprint({ - source, - callers, - callees, - }) - if (isAborted(signal)) return - - const cached = force ? null : await readCachedSummary(nodeId) - if (isAborted(signal)) return - - if (cached) { - if (fingerprintMatches(cached.fingerprint, currentFingerprint)) { - setOverview(cached.overview) - setStatus('ready') - return - } - - setStatus('validating') - const { system, user } = buildValidatorPrompt({ - oldOverview: cached.overview, - newSource: source, - oldFingerprint: cached.fingerprint, - newFingerprint: currentFingerprint, - }) - const verdict = await validateCached({ apiKey, system, user, signal }) - if (isAborted(signal)) return - - if (verdict.stillValid) { - setOverview(cached.overview) - setStatus('ready') - await writeCachedSummary({ - ...cached, - fingerprint: currentFingerprint, - }) - return - } - } - - setStatus('streaming') - const { system, user } = buildSummaryPrompt({ - header, - source, - callers, - callees, - }) - let final: string[] = [] - for await (const accumulated of streamSummary({ - apiKey, - model: summaryModel, - system, - user, - signal, - })) { - if (isAborted(signal)) return - final = splitParagraphs(accumulated) - setOverview(final) - } - if (isAborted(signal)) return - - setStatus('ready') - const payload: CachedSummary = { - nodeId, - overview: final, - fingerprint: currentFingerprint, - model: summaryModel, - generatedAt: Date.now(), - } - await writeCachedSummary(payload) - } catch (err) { - if (isAborted(signal)) return - setError(err instanceof Error ? err.message : String(err)) - setStatus('error') - } -} - -function splitParagraphs(text: string): string[] { - return text - .split(/\n{2,}/) - .map((p) => p.trim()) - .filter((p) => p.length > 0) -} - -function isAborted(signal: AbortSignal): boolean { - return signal.aborted -} diff --git a/src/modules/node-summary/index.ts b/src/modules/node-summary/index.ts deleted file mode 100644 index b70c38c..0000000 --- a/src/modules/node-summary/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export { NodeSummarySheet } from './components/node-summary-sheet' -export type { - CachedSummary, - NodeSummaryFacts, - NodeSummaryHeader, - NodeSummaryRelation, - SummaryStatus, -} from './types' diff --git a/src/modules/node-summary/lib/build-prompts.ts b/src/modules/node-summary/lib/build-prompts.ts deleted file mode 100644 index 946c617..0000000 --- a/src/modules/node-summary/lib/build-prompts.ts +++ /dev/null @@ -1,114 +0,0 @@ -import type { - CachedSummaryFingerprint, - NodeSummaryHeader, - NodeSummaryRelation, -} from '../types' - -const SUMMARY_SYSTEM = `You explain code from a project graph to engineers. Given one node's source, its callers, and what it calls, write 2 to 3 short paragraphs (2-4 sentences each). - -Cover, in order: -1. What this code does, in plain language. -2. Its role in the larger codebase - how it is used by callers and how it depends on its callees. - -Rules: -- Output plain text. Paragraphs separated by a blank line. No markdown headings, no bullet lists, no code fences. -- Reference callers and callees by name only when it clarifies the role. Do not enumerate them all. -- Do not restate the signature or file path. Skip filler ("This function..."). -- Stay concrete. If the code is short or trivial, the summary should be too.` - -export function buildSummaryPrompt({ - header, - source, - callers, - callees, -}: { - header: NodeSummaryHeader - source: string - callers: NodeSummaryRelation[] - callees: NodeSummaryRelation[] -}): { system: string; user: string } { - const lines: string[] = [] - lines.push(`Node: ${header.displayName} (${header.type})`) - lines.push(`Location: ${header.file}:${header.line}`) - lines.push(`Signature: ${header.signature || '(none)'}`) - lines.push('') - lines.push('Source:') - lines.push('```') - lines.push(source) - lines.push('```') - lines.push('') - lines.push('Callers (nodes that invoke this):') - lines.push(formatRelations(callers)) - lines.push('') - lines.push('Callees (nodes invoked by this):') - lines.push(formatRelations(callees)) - return { system: SUMMARY_SYSTEM, user: lines.join('\n') } -} - -const VALIDATOR_SYSTEM = `You judge whether a saved summary of code is still accurate after edits. Compare the saved summary to the current source and neighborhood. - -Return JSON: { "stillValid": boolean, "reason": "" }. - -- stillValid: true if every claim in the saved summary still describes the current code. Cosmetic changes (whitespace, renamed locals, refactors that preserve behavior) do not invalidate. -- stillValid: false if any concrete claim is now wrong or missing, or the role of the code has shifted in a way a reader would care about. -- Be strict but not pedantic. Reader value drives the decision.` - -export function buildValidatorPrompt({ - oldOverview, - newSource, - oldFingerprint, - newFingerprint, -}: { - oldOverview: string[] - newSource: string - oldFingerprint: CachedSummaryFingerprint - newFingerprint: CachedSummaryFingerprint -}): { system: string; user: string } { - const callerDiff = diffSets( - oldFingerprint.callerIds, - newFingerprint.callerIds, - ) - const calleeDiff = diffSets( - oldFingerprint.calleeIds, - newFingerprint.calleeIds, - ) - - const lines: string[] = [] - lines.push('Saved summary:') - for (const paragraph of oldOverview) { - lines.push(paragraph) - lines.push('') - } - lines.push('Current source:') - lines.push('```') - lines.push(newSource) - lines.push('```') - lines.push('') - lines.push('Caller changes:') - lines.push(` added: ${callerDiff.added.join(', ') || '(none)'}`) - lines.push(` removed: ${callerDiff.removed.join(', ') || '(none)'}`) - lines.push('Callee changes:') - lines.push(` added: ${calleeDiff.added.join(', ') || '(none)'}`) - lines.push(` removed: ${calleeDiff.removed.join(', ') || '(none)'}`) - - return { system: VALIDATOR_SYSTEM, user: lines.join('\n') } -} - -function formatRelations(items: NodeSummaryRelation[]): string { - if (items.length === 0) return ' (none)' - return items - .map((r) => ` - ${r.displayName} (${r.type}) at ${r.file}:${r.line}`) - .join('\n') -} - -function diffSets( - oldIds: string[], - newIds: string[], -): { added: string[]; removed: string[] } { - const oldSet = new Set(oldIds) - const newSet = new Set(newIds) - return { - added: newIds.filter((id) => !oldSet.has(id)), - removed: oldIds.filter((id) => !newSet.has(id)), - } -} diff --git a/src/modules/node-summary/lib/cache.ts b/src/modules/node-summary/lib/cache.ts deleted file mode 100644 index f68ca90..0000000 --- a/src/modules/node-summary/lib/cache.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { getDesktop } from '@/shared/lib/desktop' -import type { CachedSummary } from '@/shared/lib/desktop' - -export async function readCachedSummary( - nodeId: string, -): Promise { - const desktop = getDesktop() - if (!desktop?.readNodeSummary) return null - return desktop.readNodeSummary(nodeId) -} - -export async function writeCachedSummary( - payload: CachedSummary, -): Promise { - const desktop = getDesktop() - if (!desktop?.writeNodeSummary) return - await desktop.writeNodeSummary(payload) -} - -export async function deleteCachedSummary(nodeId: string): Promise { - const desktop = getDesktop() - if (!desktop?.deleteNodeSummary) return - await desktop.deleteNodeSummary(nodeId) -} diff --git a/src/modules/node-summary/lib/fingerprint.ts b/src/modules/node-summary/lib/fingerprint.ts deleted file mode 100644 index 3964e23..0000000 --- a/src/modules/node-summary/lib/fingerprint.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { CachedSummaryFingerprint, NodeSummaryRelation } from '../types' -import { sha256Hex } from './hash' - -export async function computeFingerprint({ - source, - callers, - callees, -}: { - source: string - callers: NodeSummaryRelation[] - callees: NodeSummaryRelation[] -}): Promise { - return { - sourceHash: await sha256Hex(source), - callerIds: callers.map((c) => c.id).sort(), - calleeIds: callees.map((c) => c.id).sort(), - } -} - -export function fingerprintMatches( - a: CachedSummaryFingerprint, - b: CachedSummaryFingerprint, -): boolean { - if (a.sourceHash !== b.sourceHash) return false - if (!arrayEq(a.callerIds, b.callerIds)) return false - if (!arrayEq(a.calleeIds, b.calleeIds)) return false - return true -} - -function arrayEq(a: string[], b: string[]): boolean { - if (a.length !== b.length) return false - for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false - return true -} diff --git a/src/modules/node-summary/lib/generate-summary.ts b/src/modules/node-summary/lib/generate-summary.ts deleted file mode 100644 index da39cf3..0000000 --- a/src/modules/node-summary/lib/generate-summary.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { AiMessage } from '@/modules/ai' -import { ClaudeService } from '@/modules/ai' - -export async function* streamSummary({ - apiKey, - model, - system, - user, - signal, -}: { - apiKey: string - model: string - system: string - user: string - signal: AbortSignal -}): AsyncIterable { - const service = new ClaudeService({ apiKey, dangerouslyAllowBrowser: true }) - const messages: AiMessage[] = [ - { role: 'system', content: system }, - { role: 'user', content: user }, - ] - let accumulated = '' - for await (const chunk of service.stream({ - messages, - model, - maxTokens: 700, - signal, - })) { - if (chunk.delta) { - accumulated += chunk.delta - yield accumulated - } - if (chunk.done) return - } -} diff --git a/src/modules/node-summary/lib/hash.ts b/src/modules/node-summary/lib/hash.ts deleted file mode 100644 index 839b255..0000000 --- a/src/modules/node-summary/lib/hash.ts +++ /dev/null @@ -1,7 +0,0 @@ -export async function sha256Hex(text: string): Promise { - const bytes = new TextEncoder().encode(text) - const digest = await crypto.subtle.digest('SHA-256', bytes) - return Array.from(new Uint8Array(digest)) - .map((b) => b.toString(16).padStart(2, '0')) - .join('') -} diff --git a/src/modules/node-summary/lib/relations.ts b/src/modules/node-summary/lib/relations.ts deleted file mode 100644 index 5843e9c..0000000 --- a/src/modules/node-summary/lib/relations.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { inspectClasses } from '@/modules/parser' -import type { Graph, GraphNode } from '@/modules/parser' - -import type { NodeSummaryHeader, NodeSummaryRelation } from '../types' - -export function getNodeMetadata( - graph: Graph, - nodeId: string, -): GraphNode | null { - return graph.nodes.find((n) => n.id === nodeId) ?? null -} - -export function toHeader(node: GraphNode): NodeSummaryHeader { - return { - displayName: node.name, - type: node.type, - signature: node.signature, - file: node.file, - line: node.line, - endLine: node.endLine, - facts: { - isAsync: node.isAsync, - isExported: node.isExported, - bodyLines: node.bodyLines, - inDegree: node.inDegree, - outDegree: node.outDegree, - }, - } -} - -function toRelation(node: GraphNode): NodeSummaryRelation { - return { - id: node.id, - displayName: node.name, - type: node.type, - file: node.file, - line: node.line, - } -} - -export function getNeighbors( - graph: Graph, - nodeId: string, -): { callers: NodeSummaryRelation[]; callees: NodeSummaryRelation[] } { - const inspector = inspectClasses(graph) - return { - callers: inspector.callersOf(nodeId).map(toRelation), - callees: inspector.calleesOf(nodeId).map(toRelation), - } -} diff --git a/src/modules/node-summary/lib/validate-cache.ts b/src/modules/node-summary/lib/validate-cache.ts deleted file mode 100644 index e69de1d..0000000 --- a/src/modules/node-summary/lib/validate-cache.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { AiMessage } from '@/modules/ai' -import { ClaudeService } from '@/modules/ai' - -export const VALIDATOR_MODEL = 'claude-haiku-4-5-20251001' - -const VALIDATOR_SCHEMA = { - type: 'object', - properties: { - stillValid: { type: 'boolean' }, - reason: { type: 'string' }, - }, - required: ['stillValid', 'reason'], - additionalProperties: false, -} as const - -export type ValidatorResult = { stillValid: boolean; reason: string } - -export async function validateCached({ - apiKey, - system, - user, - signal, -}: { - apiKey: string - system: string - user: string - signal: AbortSignal -}): Promise { - const service = new ClaudeService({ apiKey, dangerouslyAllowBrowser: true }) - const messages: AiMessage[] = [ - { role: 'system', content: system }, - { role: 'user', content: user }, - ] - const { data } = await service.generateObject({ - messages, - model: VALIDATOR_MODEL, - maxTokens: 200, - schema: VALIDATOR_SCHEMA, - signal, - }) - return data -} diff --git a/src/modules/node-summary/types.ts b/src/modules/node-summary/types.ts deleted file mode 100644 index 0e53630..0000000 --- a/src/modules/node-summary/types.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { NodeType } from '@/modules/parser' - -export type NodeSummaryFacts = { - isAsync: boolean - isExported: boolean - bodyLines: number - inDegree: number - outDegree: number -} - -export type NodeSummaryRelation = { - id: string - displayName: string - type: NodeType - file: string - line: number -} - -export type NodeSummaryHeader = { - displayName: string - type: NodeType - signature: string - file: string - line: number - endLine: number - facts: NodeSummaryFacts -} - -export type SummaryStatus = - | 'idle' - | 'loading' - | 'validating' - | 'streaming' - | 'ready' - | 'error' - | 'no-key' - -export type { - CachedSummary, - CachedSummaryFingerprint, -} from '@/shared/lib/desktop' diff --git a/src/modules/parser/bindingExtractor.ts b/src/modules/parser/bindingExtractor.ts new file mode 100644 index 0000000..39737cd --- /dev/null +++ b/src/modules/parser/bindingExtractor.ts @@ -0,0 +1,117 @@ +import { Node, SyntaxKind } from 'ts-morph' +import type { + ObjectLiteralExpression, + SourceFile, + VariableDeclaration, +} from 'ts-morph' + +import type { CollectedNode } from './core/models' +import { makeNodeId } from './core/models' + +export function extractBindings( + sourceFile: SourceFile, + relativeFilePath: string, +): CollectedNode[] { + const collected: CollectedNode[] = [] + + for (const variable of sourceFile.getVariableDeclarations()) { + if (!isTopLevel(variable)) continue + + const nameNode = variable.getNameNode() + if (!Node.isIdentifier(nameNode)) continue + + const initializer = variable.getInitializer() + if (!initializer) continue + if (isCoveredByFunctionExtractor(initializer)) continue + if (isCoveredByObjectExtractor(initializer)) continue + if (isPureLiteral(initializer)) continue + + const statement = variable.getVariableStatement() + const startLine = + statement?.getStartLineNumber() ?? variable.getStartLineNumber() + const endLine = + statement?.getEndLineNumber() ?? initializer.getEndLineNumber() + const name = variable.getName() + + collected.push({ + graphNode: { + id: makeNodeId(relativeFilePath, name), + name, + type: 'object', + file: relativeFilePath, + line: startLine, + endLine, + signature: '', + isAsync: false, + isExported: statement?.isExported() ?? false, + isStatic: false, + bodyLines: spanLines( + initializer.getStartLineNumber(), + initializer.getEndLineNumber(), + ), + inDegree: 0, + outDegree: 0, + }, + declaration: variable, + }) + } + + return collected +} + +function isTopLevel(variable: VariableDeclaration): boolean { + const statement = variable.getVariableStatement() + if (!statement) return false + return statement.getParent().getKind() === SyntaxKind.SourceFile +} + +function isCoveredByFunctionExtractor(initializer: Node): boolean { + return ( + Node.isArrowFunction(initializer) || Node.isFunctionExpression(initializer) + ) +} + +function isCoveredByObjectExtractor(initializer: Node): boolean { + if (!Node.isObjectLiteralExpression(initializer)) return false + return hasMethodLikeMember(initializer) +} + +function hasMethodLikeMember(obj: ObjectLiteralExpression): boolean { + for (const prop of obj.getProperties()) { + if ( + Node.isMethodDeclaration(prop) || + Node.isGetAccessorDeclaration(prop) || + Node.isSetAccessorDeclaration(prop) + ) { + return true + } + if (Node.isPropertyAssignment(prop)) { + const init = prop.getInitializer() + if ( + init && + (Node.isArrowFunction(init) || Node.isFunctionExpression(init)) + ) { + return true + } + } + } + return false +} + +function isPureLiteral(node: Node): boolean { + const kind = node.getKind() + return ( + kind === SyntaxKind.StringLiteral || + kind === SyntaxKind.NumericLiteral || + kind === SyntaxKind.BigIntLiteral || + kind === SyntaxKind.NoSubstitutionTemplateLiteral || + kind === SyntaxKind.RegularExpressionLiteral || + kind === SyntaxKind.TrueKeyword || + kind === SyntaxKind.FalseKeyword || + kind === SyntaxKind.NullKeyword + ) +} + +function spanLines(start: number, end: number): number { + return Math.max(1, end - start + 1) +} diff --git a/src/modules/parser/core/models.ts b/src/modules/parser/core/models.ts index 3c56da1..2f63c11 100644 --- a/src/modules/parser/core/models.ts +++ b/src/modules/parser/core/models.ts @@ -6,8 +6,6 @@ import type { Node as TsMorphNode } from 'ts-morph' export type NodeType = - | 'file' - | 'route' | 'component' | 'hook' | 'function' @@ -21,10 +19,10 @@ export type NodeType = export type EdgeType = | 'owns' - | 'imports' + | 'calls' + | 'references' | 'renders' | 'uses-hook' - | 'routes-to' | 'instantiates' | 'extends' | 'implements' diff --git a/src/modules/parser/importExtractor.ts b/src/modules/parser/importExtractor.ts deleted file mode 100644 index ebf01cd..0000000 --- a/src/modules/parser/importExtractor.ts +++ /dev/null @@ -1,80 +0,0 @@ -import path from 'node:path' -import type { Node, SourceFile } from 'ts-morph' - -import type { GraphEdge, GraphNode } from './core/models' - -export function extractImports( - sourceFiles: SourceFile[], - nodes: GraphNode[], - declarationMap: Map, - root: string, -): GraphEdge[] { - const edges: GraphEdge[] = [] - const seen = new Set() - - const nodesByFile = new Map() - for (const node of nodes) { - const list = nodesByFile.get(node.file) - if (list) list.push(node) - else nodesByFile.set(node.file, [node]) - } - - for (const sourceFile of sourceFiles) { - const relSource = path.relative(root, sourceFile.getFilePath()) - const sourceNodes = nodesByFile.get(relSource) - if (!sourceNodes || sourceNodes.length === 0) continue - - for (const importDecl of sourceFile.getImportDeclarations()) { - const targetIds = new Set() - - for (const namedImport of importDecl.getNamedImports()) { - const nameNode = namedImport.getNameNode() - const symbol = nameNode.getSymbol() - if (!symbol) continue - const candidates = [symbol] - const aliased = symbol.getAliasedSymbol() - if (aliased) candidates.push(aliased) - for (const candidate of candidates) { - for (const declaration of candidate.getDeclarations()) { - const id = declarationMap.get(declaration) - if (id) targetIds.add(id) - } - } - } - - const defaultImport = importDecl.getDefaultImport() - if (defaultImport) { - const symbol = defaultImport.getSymbol() - if (symbol) { - const candidates = [symbol] - const aliased = symbol.getAliasedSymbol() - if (aliased) candidates.push(aliased) - for (const candidate of candidates) { - for (const declaration of candidate.getDeclarations()) { - const id = declarationMap.get(declaration) - if (id) targetIds.add(id) - } - } - } - } - - if (targetIds.size === 0) continue - - for (const sourceNode of sourceNodes) { - for (const targetId of targetIds) { - if (sourceNode.id === targetId) continue - const key = `${sourceNode.id}->${targetId}` - if (seen.has(key)) continue - seen.add(key) - edges.push({ - source: sourceNode.id, - target: targetId, - type: 'imports', - }) - } - } - } - } - - return edges -} diff --git a/src/modules/parser/index.ts b/src/modules/parser/index.ts index 841e2cf..dcb15c8 100644 --- a/src/modules/parser/index.ts +++ b/src/modules/parser/index.ts @@ -3,16 +3,15 @@ import path from 'node:path' import { Project, ScriptTarget } from 'ts-morph' import type { Node, SourceFile } from 'ts-morph' +import { extractBindings } from './bindingExtractor' +import { extractCalls } from './callExtractor' import { extractClasses } from './classExtractor' import { extractFunctions } from './functionExtractor' import { extractObjects } from './objectExtractor' +import { extractReferences } from './referenceExtractor' import type { Graph, GraphEdge, GraphNode } from './core/models' import { SCHEMA_VERSION, validateGraph } from './core/schema' -import { - classifyNode, - extractStructuralEdges, - makeFileNode, -} from './structureExtractor' +import { classifyNode, extractStructuralEdges } from './structureExtractor' export type { EdgeType, @@ -61,10 +60,8 @@ export function parseProject(root: string): Graph { (sourceFile) => !sourceFile.isDeclarationFile(), ) - // Pass 1 — collect files, symbols, and the ts-morph-declaration → id map. - const nodes: GraphNode[] = sourceFiles.map((sourceFile) => - makeFileNode(root, sourceFile), - ) + // Pass 1 — collect symbols and the ts-morph-declaration → id map. + const nodes: GraphNode[] = [] const declarationMap = new Map() for (const sourceFile of sourceFiles) { @@ -73,6 +70,7 @@ export function parseProject(root: string): Graph { ...extractFunctions(sourceFile, relativePath), ...extractClasses(sourceFile, relativePath), ...extractObjects(sourceFile, relativePath), + ...extractBindings(sourceFile, relativePath), ] for (const { graphNode, declaration } of collected) { @@ -82,100 +80,20 @@ export function parseProject(root: string): Graph { } } - // Pass 2 — resolve structure-first relationships. We intentionally do not - // emit direct call edges here; the graph is organized by app/module shape. + // Pass 2 — resolve structural relationships (ownership, JSX, hooks, + // instantiation, inheritance) and append plain function-call edges. const edges: GraphEdge[] = extractStructuralEdges( - root, sourceFiles, declarationMap, nodes, ) - // Pass 3 — annotate each node with its in/out degree - annotateDegrees(nodes, edges) - - const graph: Graph = { - version: SCHEMA_VERSION, - language: 'typescript', - root, - nodes, - edges, - } - - validateGraph(graph) - return graph -} - -export function parseFilesIncremental( - root: string, - changedFiles: string[], - previousGraph: Graph, -): Graph { - const sourceFiles = loadSourceFiles(root).filter( - (sourceFile) => !sourceFile.isDeclarationFile(), - ) - - const changedSet = new Set(changedFiles) - const presentFiles = new Set() - - // Pass 1 — re-extract nodes and ts-morph-declaration map for every file. - // This is the cheap top-level scan; the expensive AST descent in pass 2 is - // what we skip for unchanged files. - const nodes: GraphNode[] = [] - const declarationMap = new Map() - for (const sourceFile of sourceFiles) { - const rel = path.relative(root, sourceFile.getFilePath()) - presentFiles.add(rel) - nodes.push(makeFileNode(root, sourceFile)) - const collected = [ - ...extractFunctions(sourceFile, rel), - ...extractClasses(sourceFile, rel), - ...extractObjects(sourceFile, rel), - ] - for (const { graphNode, declaration } of collected) { - const node = classifyNode(graphNode) - nodes.push(node) - declarationMap.set(declaration, node.id) - } - } - - const nodeIds = new Set(nodes.map((n) => n.id)) - - // Pass 2a — keep cached edges that originate from unchanged files and whose - // endpoints still exist. - const edges: GraphEdge[] = [] - const seen = new Set() - - for (const cached of previousGraph.edges) { - const owningFile = edgeSourceFile(cached.source) - if (owningFile === null) continue - if (changedSet.has(owningFile)) continue - if (!presentFiles.has(owningFile)) continue - if (!nodeIds.has(cached.source) || !nodeIds.has(cached.target)) continue - const key = `${cached.source}->${cached.target}:${cached.type}` - if (seen.has(key)) continue - seen.add(key) - edges.push(cached) - } - - // Pass 2b — re-extract structural edges for changed files only. - const changedSourceFiles = sourceFiles.filter((sourceFile) => - changedSet.has(path.relative(root, sourceFile.getFilePath())), - ) - const fresh = extractStructuralEdges( - root, - changedSourceFiles, - declarationMap, - nodes, - ) - for (const edge of fresh) { - const key = `${edge.source}->${edge.target}:${edge.type}` - if (seen.has(key)) continue - seen.add(key) - edges.push(edge) + edges.push(...extractCalls(sourceFile, declarationMap)) + edges.push(...extractReferences(sourceFile, declarationMap)) } + // Pass 3 — annotate each node with its in/out degree annotateDegrees(nodes, edges) const graph: Graph = { @@ -190,13 +108,6 @@ export function parseFilesIncremental( return graph } -function edgeSourceFile(source: string): string | null { - if (!source.startsWith('file:')) return null - const tail = source.slice('file:'.length) - const sep = tail.indexOf('::') - return sep === -1 ? tail : tail.slice(0, sep) -} - function annotateDegrees(nodes: GraphNode[], edges: GraphEdge[]): void { const byId = new Map() for (const node of nodes) byId.set(node.id, node) diff --git a/src/modules/parser/parse-cli.ts b/src/modules/parser/parse-cli.ts deleted file mode 100644 index a59377c..0000000 --- a/src/modules/parser/parse-cli.ts +++ /dev/null @@ -1,85 +0,0 @@ -import path from 'node:path' - -import { parseFilesIncremental, parseProject } from './index' -import type { Graph } from './core/models' - -type Outbound = - | { type: 'graph'; graph: unknown } - | { type: 'error'; message: string } - -type Inbound = { - type: 'input' - changedFiles: string[] - previousGraph: Graph -} - -function emit(message: Outbound): Promise { - return new Promise((resolve) => { - if (typeof process.send === 'function') { - process.send(message, undefined, undefined, () => resolve()) - return - } - if (message.type === 'graph') { - process.stdout.write(JSON.stringify(message.graph)) - } else { - process.stderr.write(`${message.message}\n`) - } - resolve() - }) -} - -function waitForInput(timeoutMs: number): Promise { - return new Promise((resolve, reject) => { - const timer = setTimeout(() => { - reject(new Error('parser-cli: timed out waiting for incremental input')) - }, timeoutMs) - process.on('message', (msg: unknown) => { - if ( - msg && - typeof msg === 'object' && - (msg as { type?: string }).type === 'input' - ) { - clearTimeout(timer) - resolve(msg as Inbound) - } - }) - }) -} - -async function main(): Promise { - const rawArg = process.argv[2] - if (!rawArg) { - await emit({ - type: 'error', - message: 'parser-cli: missing folder argument', - }) - process.exit(2) - } - - const root = path.resolve(rawArg) - const incremental = process.argv.includes('--incremental') - - try { - let graph - if (incremental) { - const input = await waitForInput(30_000) - graph = parseFilesIncremental( - root, - input.changedFiles, - input.previousGraph, - ) - } else { - graph = parseProject(root) - } - await emit({ type: 'graph', graph }) - process.exit(0) - } catch (err) { - await emit({ - type: 'error', - message: err instanceof Error ? (err.stack ?? err.message) : String(err), - }) - process.exit(1) - } -} - -void main() diff --git a/src/modules/parser/parse-service.ts b/src/modules/parser/parse-service.ts new file mode 100644 index 0000000..4643be4 --- /dev/null +++ b/src/modules/parser/parse-service.ts @@ -0,0 +1,42 @@ +import path from 'node:path' + +import { parseProject } from './index' + +type Incoming = { type: 'parse'; id: number; folder: string } + +type Outgoing = + | { type: 'result'; id: number; graph: unknown } + | { type: 'error'; id: number; message: string } + +if (typeof process.send !== 'function') { + process.stderr.write('parser-service must be spawned via fork() with IPC\n') + process.exit(2) +} + +function send(message: Outgoing): void { + process.send!(message) +} + +function handle(message: Incoming): void { + try { + const graph = parseProject(path.resolve(message.folder)) + send({ type: 'result', id: message.id, graph }) + } catch (err) { + send({ + type: 'error', + id: message.id, + message: err instanceof Error ? (err.stack ?? err.message) : String(err), + }) + } +} + +process.on('message', (raw) => { + if (!raw || typeof raw !== 'object') return + const candidate = raw as { type?: unknown } + if (candidate.type !== 'parse') return + handle(raw as Incoming) +}) + +process.on('disconnect', () => { + process.exit(0) +}) diff --git a/src/modules/parser/referenceExtractor.ts b/src/modules/parser/referenceExtractor.ts new file mode 100644 index 0000000..c161e0b --- /dev/null +++ b/src/modules/parser/referenceExtractor.ts @@ -0,0 +1,69 @@ +import { SyntaxKind } from 'ts-morph' +import type { SourceFile, Node } from 'ts-morph' + +import type { GraphEdge } from './core/models' + +export function extractReferences( + sourceFile: SourceFile, + declarationMap: Map, +): GraphEdge[] { + const edges: GraphEdge[] = [] + const seen = new Set() + + for (const identifier of sourceFile.getDescendantsOfKind( + SyntaxKind.Identifier, + )) { + let targetId: string | undefined + let sourceId: string | undefined + try { + targetId = resolveTargetId(identifier, declarationMap) + if (!targetId) continue + sourceId = resolveReferenceSourceId(identifier, declarationMap) + } catch { + // ts-morph's checker can throw on partially-resolved symbols. Skip. + continue + } + if (!sourceId || sourceId === targetId) continue + + const key = `${sourceId}->${targetId}` + if (seen.has(key)) continue + seen.add(key) + + edges.push({ source: sourceId, target: targetId, type: 'references' }) + } + + return edges +} + +function resolveTargetId( + identifier: Node, + declarationMap: Map, +): string | undefined { + const symbol = identifier.getSymbol() + if (!symbol) return undefined + + const candidates = [symbol] + const aliased = symbol.getAliasedSymbol() + if (aliased) candidates.push(aliased) + + for (const candidate of candidates) { + for (const declaration of candidate.getDeclarations()) { + const id = declarationMap.get(declaration) + if (id) return id + } + } + return undefined +} + +function resolveReferenceSourceId( + node: Node, + declarationMap: Map, +): string | undefined { + let current = node.getParent() + while (current) { + const id = declarationMap.get(current) + if (id) return id + current = current.getParent() + } + return undefined +} diff --git a/src/modules/parser/structureExtractor.ts b/src/modules/parser/structureExtractor.ts index d6759ec..7ebeba2 100644 --- a/src/modules/parser/structureExtractor.ts +++ b/src/modules/parser/structureExtractor.ts @@ -2,52 +2,21 @@ import { Node } from 'ts-morph' import type { GraphEdge, GraphNode } from './core/models' import { makeNodeId } from './core/models' import type { SourceFile } from 'ts-morph' -import path from 'node:path' - -export function makeFileNode(root: string, sourceFile: SourceFile): GraphNode { - const file = sourceFile.getFilePath().slice(root.length + 1) - const statements = sourceFile.getStatements() - const endLine = - statements.length > 0 - ? (statements[statements.length - 1]?.getEndLineNumber() ?? 1) - : 1 - - return { - id: fileNodeId(file), - name: file.split('/').at(-1) ?? file, - type: file.startsWith('src/routes/') ? 'route' : 'file', - file, - line: 1, - endLine, - signature: '', - isAsync: false, - isExported: false, - isStatic: false, - bodyLines: endLine, - inDegree: 0, - outDegree: 0, - } -} export function extractStructuralEdges( - root: string, sourceFiles: SourceFile[], declarationMap: Map, nodes: GraphNode[], ): GraphEdge[] { - const nodeIds = new Set(nodes.map((node) => node.id)) const edges: GraphEdge[] = [] const seen = new Set() + addOwnershipEdges(edges, seen, nodes) + for (const sourceFile of sourceFiles) { - const file = relativePath(root, sourceFile) - const sourceFileId = fileNodeId(file) - - addOwnershipEdges(edges, seen, sourceFileId, nodes) - addImportEdges(edges, seen, root, sourceFile, sourceFileId, nodeIds) - addJsxEdges(edges, seen, sourceFile, sourceFileId, declarationMap) - addHookEdges(edges, seen, sourceFile, sourceFileId, declarationMap) - addInstantiationEdges(edges, seen, sourceFile, sourceFileId, declarationMap) + addJsxEdges(edges, seen, sourceFile, declarationMap) + addHookEdges(edges, seen, sourceFile, declarationMap) + addInstantiationEdges(edges, seen, sourceFile, declarationMap) addInheritanceEdges(edges, seen, sourceFile, declarationMap) } @@ -71,35 +40,14 @@ export function classifyNode(node: GraphNode): GraphNode { function addOwnershipEdges( edges: GraphEdge[], seen: Set, - fileId: string, nodes: GraphNode[], ): void { - const file = fileId.slice('file:'.length) + const nodeIds = new Set(nodes.map((node) => node.id)) for (const node of nodes) { - if (node.id === fileId || node.file !== file) continue - const ownerId = ownerNodeId(node) - addEdge(edges, seen, ownerId ?? fileId, node.id, 'owns') - } -} - -function addImportEdges( - edges: GraphEdge[], - seen: Set, - root: string, - sourceFile: SourceFile, - sourceFileId: string, - nodeIds: Set, -): void { - for (const importDeclaration of sourceFile.getImportDeclarations()) { - const target = importDeclaration.getModuleSpecifierSourceFile() - if (!target) continue - - const targetId = fileNodeId(relativePath(root, target)) - if (!nodeIds.has(targetId) || targetId === sourceFileId) continue - - addEdge(edges, seen, sourceFileId, targetId, 'imports') + if (!ownerId || !nodeIds.has(ownerId)) continue + addEdge(edges, seen, ownerId, node.id, 'owns') } } @@ -107,7 +55,6 @@ function addJsxEdges( edges: GraphEdge[], seen: Set, sourceFile: SourceFile, - sourceFileId: string, declarationMap: Map, ): void { const jsxNodes = [ @@ -116,15 +63,12 @@ function addJsxEdges( ] for (const jsx of jsxNodes) { + const sourceId = resolveSourceId(jsx, declarationMap) + if (!sourceId) continue + const targetId = resolveSymbolTargetId(jsx.getTagNameNode(), declarationMap) if (targetId) { - addEdge( - edges, - seen, - resolveSourceId(jsx, declarationMap) ?? sourceFileId, - targetId, - 'renders', - ) + addEdge(edges, seen, sourceId, targetId, 'renders') } for (const attribute of jsx.getAttributes()) { @@ -138,13 +82,7 @@ function addJsxEdges( const callbackId = resolveSymbolTargetId(identifier, declarationMap) if (!callbackId) continue - addEdge( - edges, - seen, - resolveSourceId(jsx, declarationMap) ?? sourceFileId, - callbackId, - 'passes-callback', - ) + addEdge(edges, seen, sourceId, callbackId, 'passes-callback') } } } @@ -154,7 +92,6 @@ function addHookEdges( edges: GraphEdge[], seen: Set, sourceFile: SourceFile, - sourceFileId: string, declarationMap: Map, ): void { for (const call of sourceFile @@ -164,16 +101,13 @@ function addHookEdges( const name = expression.getText() if (!isHookName(name.split('.').at(-1) ?? name)) continue + const sourceId = resolveSourceId(call, declarationMap) + if (!sourceId) continue + const targetId = resolveSymbolTargetId(expression, declarationMap) if (!targetId) continue - addEdge( - edges, - seen, - resolveSourceId(call, declarationMap) ?? sourceFileId, - targetId, - 'uses-hook', - ) + addEdge(edges, seen, sourceId, targetId, 'uses-hook') } } @@ -181,25 +115,21 @@ function addInstantiationEdges( edges: GraphEdge[], seen: Set, sourceFile: SourceFile, - sourceFileId: string, declarationMap: Map, ): void { for (const expression of sourceFile .getDescendants() .filter(Node.isNewExpression)) { + const sourceId = resolveSourceId(expression, declarationMap) + if (!sourceId) continue + const targetId = resolveSymbolTargetId( expression.getExpression(), declarationMap, ) if (!targetId) continue - addEdge( - edges, - seen, - resolveSourceId(expression, declarationMap) ?? sourceFileId, - targetId, - 'instantiates', - ) + addEdge(edges, seen, sourceId, targetId, 'instantiates') } } @@ -314,14 +244,6 @@ function addEdge( edges.push({ source, target, type }) } -function fileNodeId(file: string): string { - return `file:${file}` -} - -function relativePath(root: string, sourceFile: SourceFile): string { - return path.relative(root, sourceFile.getFilePath()) -} - function isComponentName(name: string): boolean { return /^[A-Z]/.test(name) } diff --git a/src/shared/lib/active-panel.ts b/src/shared/lib/active-panel.ts index 8f3ec69..344641a 100644 --- a/src/shared/lib/active-panel.ts +++ b/src/shared/lib/active-panel.ts @@ -20,12 +20,6 @@ export function useActivePanel() { return useSyncExternalStore(subscribe, getSnapshot, getSnapshot) } -export function setActivePanel(next: ActivePanel) { - if (active === next) return - active = next - for (const listener of listeners) listener() -} - export function toggleActivePanel(id: Exclude) { active = active === id ? null : id for (const listener of listeners) listener() diff --git a/src/shared/lib/desktop.ts b/src/shared/lib/desktop.ts index ae11bfe..00c3012 100644 --- a/src/shared/lib/desktop.ts +++ b/src/shared/lib/desktop.ts @@ -15,27 +15,6 @@ export interface GraphPayload { export interface InitialState extends ProjectPayload, GraphPayload {} -export interface ReadFunctionSourcePayload { - root: string - file: string - startLine: number - endLine: number -} - -export interface ReadFunctionSourceResult { - source: string - startLine: number - endLine: number -} - -export interface WriteFunctionSourcePayload extends ReadFunctionSourcePayload { - source: string -} - -export interface WriteFunctionSourceResult { - endLine: number -} - export interface FileNode { name: string path: string @@ -249,12 +228,6 @@ export interface GraphyDesktop { deleteNodeSummary: (nodeId: string) => Promise onProject: (handler: (payload: ProjectPayload) => void) => () => void onGraph: (handler: (payload: GraphPayload) => void) => () => void - readFunctionSource: ( - payload: ReadFunctionSourcePayload, - ) => Promise - writeFunctionSource: ( - payload: WriteFunctionSourcePayload, - ) => Promise getFileTree: () => Promise readFile: (filePath: string) => Promise writeFile: (filePath: string, content: string) => Promise diff --git a/src/shared/ui/accordion.tsx b/src/shared/ui/accordion.tsx deleted file mode 100644 index c8c4f83..0000000 --- a/src/shared/ui/accordion.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import * as React from 'react' -import { Accordion as AccordionPrimitive } from 'radix-ui' - -import { cn } from '@/shared/lib/utils' -import { ChevronDownIcon, ChevronUpIcon } from 'lucide-react' - -function Accordion({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function AccordionItem({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function AccordionTrigger({ - className, - children, - ...props -}: React.ComponentProps) { - return ( - - - {children} - - - - - ) -} - -function AccordionContent({ - className, - children, - ...props -}: React.ComponentProps) { - return ( - -
- {children} -
-
- ) -} - -export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/src/shared/ui/alert.tsx b/src/shared/ui/alert.tsx deleted file mode 100644 index 0d5475c..0000000 --- a/src/shared/ui/alert.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import * as React from 'react' -import { cva } from 'class-variance-authority' -import type { VariantProps } from 'class-variance-authority' - -import { cn } from '@/shared/lib/utils' - -const alertVariants = cva( - "group/alert relative grid w-full gap-0.5 rounded-lg border px-4 py-3 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4", - { - variants: { - variant: { - default: 'bg-card text-card-foreground', - destructive: - 'bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current', - }, - }, - defaultVariants: { - variant: 'default', - }, - }, -) - -function Alert({ - className, - variant, - ...props -}: React.ComponentProps<'div'> & VariantProps) { - return ( -
- ) -} - -function AlertTitle({ className, ...props }: React.ComponentProps<'div'>) { - return ( -
svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground', - className, - )} - {...props} - /> - ) -} - -function AlertDescription({ - className, - ...props -}: React.ComponentProps<'div'>) { - return ( -
- ) -} - -function AlertAction({ className, ...props }: React.ComponentProps<'div'>) { - return ( -
- ) -} - -export { Alert, AlertTitle, AlertDescription, AlertAction } diff --git a/src/shared/ui/aspect-ratio.tsx b/src/shared/ui/aspect-ratio.tsx deleted file mode 100644 index 47732b8..0000000 --- a/src/shared/ui/aspect-ratio.tsx +++ /dev/null @@ -1,11 +0,0 @@ -'use client' - -import { AspectRatio as AspectRatioPrimitive } from 'radix-ui' - -function AspectRatio({ - ...props -}: React.ComponentProps) { - return -} - -export { AspectRatio } diff --git a/src/shared/ui/avatar.tsx b/src/shared/ui/avatar.tsx deleted file mode 100644 index 626e22c..0000000 --- a/src/shared/ui/avatar.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import * as React from 'react' -import { Avatar as AvatarPrimitive } from 'radix-ui' - -import { cn } from '@/shared/lib/utils' - -function Avatar({ - className, - size = 'default', - ...props -}: React.ComponentProps & { - size?: 'default' | 'sm' | 'lg' -}) { - return ( - - ) -} - -function AvatarImage({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function AvatarFallback({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function AvatarBadge({ className, ...props }: React.ComponentProps<'span'>) { - return ( - svg]:hidden', - 'group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2', - 'group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2', - className, - )} - {...props} - /> - ) -} - -function AvatarGroup({ className, ...props }: React.ComponentProps<'div'>) { - return ( -
- ) -} - -function AvatarGroupCount({ - className, - ...props -}: React.ComponentProps<'div'>) { - return ( -
svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3', - className, - )} - {...props} - /> - ) -} - -export { - Avatar, - AvatarImage, - AvatarFallback, - AvatarGroup, - AvatarGroupCount, - AvatarBadge, -} diff --git a/src/shared/ui/badge.tsx b/src/shared/ui/badge.tsx deleted file mode 100644 index 43f0780..0000000 --- a/src/shared/ui/badge.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import * as React from 'react' -import { cva } from 'class-variance-authority' -import type { VariantProps } from 'class-variance-authority' -import { Slot } from 'radix-ui' - -import { cn } from '@/shared/lib/utils' - -const badgeVariants = cva( - 'group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!', - { - variants: { - variant: { - default: 'bg-primary text-primary-foreground [a]:hover:bg-primary/80', - secondary: - 'bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80', - destructive: - 'bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20', - outline: - 'border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground', - ghost: - 'hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50', - link: 'text-primary underline-offset-4 hover:underline', - }, - }, - defaultVariants: { - variant: 'default', - }, - }, -) - -function Badge({ - className, - variant = 'default', - asChild = false, - ...props -}: React.ComponentProps<'span'> & - VariantProps & { asChild?: boolean }) { - const Comp = asChild ? Slot.Root : 'span' - - return ( - - ) -} - -export { Badge, badgeVariants } diff --git a/src/shared/ui/button-group.tsx b/src/shared/ui/button-group.tsx deleted file mode 100644 index 5b96347..0000000 --- a/src/shared/ui/button-group.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { cva } from 'class-variance-authority' -import type { VariantProps } from 'class-variance-authority' -import { Slot } from 'radix-ui' - -import { cn } from '@/shared/lib/utils' -import { Separator } from '@/shared/ui/separator' - -const buttonGroupVariants = cva( - "group/button-group flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1", - { - variants: { - orientation: { - horizontal: - '[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-r-md!', - vertical: - 'flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-b-md!', - }, - }, - defaultVariants: { - orientation: 'horizontal', - }, - }, -) - -function ButtonGroup({ - className, - orientation, - ...props -}: React.ComponentProps<'div'> & VariantProps) { - return ( -
- ) -} - -function ButtonGroupText({ - className, - asChild = false, - ...props -}: React.ComponentProps<'div'> & { - asChild?: boolean -}) { - const Comp = asChild ? Slot.Root : 'div' - - return ( - - ) -} - -function ButtonGroupSeparator({ - className, - orientation = 'vertical', - ...props -}: React.ComponentProps) { - return ( - - ) -} - -export { - ButtonGroup, - ButtonGroupSeparator, - ButtonGroupText, - buttonGroupVariants, -} diff --git a/src/shared/ui/calendar.tsx b/src/shared/ui/calendar.tsx deleted file mode 100644 index bda6481..0000000 --- a/src/shared/ui/calendar.tsx +++ /dev/null @@ -1,225 +0,0 @@ -'use client' - -import * as React from 'react' -import { DayPicker, getDefaultClassNames } from 'react-day-picker' -import type { DayButton, Locale } from 'react-day-picker' - -import { cn } from '@/shared/lib/utils' -import { Button, buttonVariants } from '@/shared/ui/button' -import { - ChevronLeftIcon, - ChevronRightIcon, - ChevronDownIcon, -} from 'lucide-react' - -function Calendar({ - className, - classNames, - showOutsideDays = true, - captionLayout = 'label', - buttonVariant = 'ghost', - locale, - formatters, - components, - ...props -}: React.ComponentProps & { - buttonVariant?: React.ComponentProps['variant'] -}) { - const defaultClassNames = getDefaultClassNames() - - return ( - svg]:rotate-180`, - String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`, - className, - )} - captionLayout={captionLayout} - locale={locale} - formatters={{ - formatMonthDropdown: (date) => - date.toLocaleString(locale?.code, { month: 'short' }), - ...formatters, - }} - classNames={{ - root: cn('w-fit', defaultClassNames.root), - months: cn( - 'relative flex flex-col gap-4 md:flex-row', - defaultClassNames.months, - ), - month: cn('flex w-full flex-col gap-4', defaultClassNames.month), - nav: cn( - 'absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1', - defaultClassNames.nav, - ), - button_previous: cn( - buttonVariants({ variant: buttonVariant }), - 'size-(--cell-size) p-0 select-none aria-disabled:opacity-50', - defaultClassNames.button_previous, - ), - button_next: cn( - buttonVariants({ variant: buttonVariant }), - 'size-(--cell-size) p-0 select-none aria-disabled:opacity-50', - defaultClassNames.button_next, - ), - month_caption: cn( - 'flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)', - defaultClassNames.month_caption, - ), - dropdowns: cn( - 'flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium', - defaultClassNames.dropdowns, - ), - dropdown_root: cn( - 'relative rounded-(--cell-radius)', - defaultClassNames.dropdown_root, - ), - dropdown: cn( - 'absolute inset-0 bg-popover opacity-0', - defaultClassNames.dropdown, - ), - caption_label: cn( - 'font-medium select-none', - captionLayout === 'label' - ? 'text-sm' - : 'flex items-center gap-1 rounded-(--cell-radius) text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground', - defaultClassNames.caption_label, - ), - table: 'w-full border-collapse', - weekdays: cn('flex', defaultClassNames.weekdays), - weekday: cn( - 'flex-1 rounded-(--cell-radius) text-[0.8rem] font-normal text-muted-foreground select-none', - defaultClassNames.weekday, - ), - week: cn('mt-2 flex w-full', defaultClassNames.week), - week_number_header: cn( - 'w-(--cell-size) select-none', - defaultClassNames.week_number_header, - ), - week_number: cn( - 'text-[0.8rem] text-muted-foreground select-none', - defaultClassNames.week_number, - ), - day: cn( - 'group/day relative aspect-square h-full w-full rounded-(--cell-radius) p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-(--cell-radius)', - props.showWeekNumber - ? '[&:nth-child(2)[data-selected=true]_button]:rounded-l-(--cell-radius)' - : '[&:first-child[data-selected=true]_button]:rounded-l-(--cell-radius)', - defaultClassNames.day, - ), - range_start: cn( - 'relative isolate z-0 rounded-l-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:right-0 after:w-4 after:bg-muted', - defaultClassNames.range_start, - ), - range_middle: cn('rounded-none', defaultClassNames.range_middle), - range_end: cn( - 'relative isolate z-0 rounded-r-(--cell-radius) bg-muted after:absolute after:inset-y-0 after:left-0 after:w-4 after:bg-muted', - defaultClassNames.range_end, - ), - today: cn( - 'rounded-(--cell-radius) bg-muted text-foreground data-[selected=true]:rounded-none', - defaultClassNames.today, - ), - outside: cn( - 'text-muted-foreground aria-selected:text-muted-foreground', - defaultClassNames.outside, - ), - disabled: cn( - 'text-muted-foreground opacity-50', - defaultClassNames.disabled, - ), - hidden: cn('invisible', defaultClassNames.hidden), - ...classNames, - }} - components={{ - Root: ({ className, rootRef, ...props }) => { - return ( -
- ) - }, - Chevron: ({ className, orientation, ...props }) => { - if (orientation === 'left') { - return ( - - ) - } - - if (orientation === 'right') { - return ( - - ) - } - - return ( - - ) - }, - DayButton: ({ ...props }) => ( - - ), - WeekNumber: ({ children, ...props }) => { - return ( - -
- {children} -
- - ) - }, - ...components, - }} - {...props} - /> - ) -} - -function CalendarDayButton({ - className, - day, - modifiers, - locale, - ...props -}: React.ComponentProps & { locale?: Partial }) { - const defaultClassNames = getDefaultClassNames() - - const ref = React.useRef(null) - React.useEffect(() => { - if (modifiers.focused) ref.current?.focus() - }, [modifiers.focused]) - - return ( - - ) -} - -function CarouselNext({ - className, - variant = 'outline', - size = 'icon-sm', - ...props -}: React.ComponentProps) { - const { orientation, scrollNext, canScrollNext } = useCarousel() - - return ( - - ) -} - -export { - type CarouselApi, - Carousel, - CarouselContent, - CarouselItem, - CarouselPrevious, - CarouselNext, - useCarousel, -} diff --git a/src/shared/ui/chart.tsx b/src/shared/ui/chart.tsx deleted file mode 100644 index eddaa2d..0000000 --- a/src/shared/ui/chart.tsx +++ /dev/null @@ -1,371 +0,0 @@ -'use client' - -import * as React from 'react' -import * as RechartsPrimitive from 'recharts' -import type { TooltipValueType } from 'recharts' - -import { cn } from '@/shared/lib/utils' - -// Format: { THEME_NAME: CSS_SELECTOR } -const THEMES = { light: '', dark: '.dark' } as const - -const INITIAL_DIMENSION = { width: 320, height: 200 } as const -type TooltipNameType = number | string - -export type ChartConfig = Record< - string, - { - label?: React.ReactNode - icon?: React.ComponentType - } & ( - | { color?: string; theme?: never } - | { color?: never; theme: Record } - ) -> - -type ChartContextProps = { - config: ChartConfig -} - -const ChartContext = React.createContext(null) - -function useChart() { - const context = React.useContext(ChartContext) - - if (!context) { - throw new Error('useChart must be used within a ') - } - - return context -} - -function ChartContainer({ - id, - className, - children, - config, - initialDimension = INITIAL_DIMENSION, - ...props -}: React.ComponentProps<'div'> & { - config: ChartConfig - children: React.ComponentProps< - typeof RechartsPrimitive.ResponsiveContainer - >['children'] - initialDimension?: { - width: number - height: number - } -}) { - const uniqueId = React.useId() - const chartId = `chart-${id ?? uniqueId.replace(/:/g, '')}` - - return ( - -
- - - {children} - -
-
- ) -} - -const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { - const colorConfig = Object.entries(config).filter( - ([, config]) => config.theme ?? config.color, - ) - - if (!colorConfig.length) { - return null - } - - return ( -