diff --git a/bun.lock b/bun.lock index c997b82..a369067 100644 --- a/bun.lock +++ b/bun.lock @@ -6,20 +6,20 @@ "dependencies": { "@ai-sdk/openai": "^1.3.22", "@hookform/resolvers": "^4.1.3", - "@modelcontextprotocol/sdk": "^1.14.0", + "@modelcontextprotocol/sdk": "^1.15.0", "@radix-ui/react-hover-card": "^1.1.14", "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-select": "^2.2.5", "@radix-ui/react-slot": "^1.2.3", "@tailwindcss/postcss": "^4.1.11", "@tailwindcss/vite": "^4.1.11", - "@tanstack/react-form": "^1.12.4", + "@tanstack/react-form": "^1.13.2", "@tanstack/react-pacer": "^0.8.0", "@tanstack/react-query": "^5.81.5", - "@tanstack/react-router": "^1.124.0", - "@tanstack/react-router-with-query": "^1.124.0", - "@tanstack/react-start": "^1.124.1", - "@tanstack/zod-adapter": "^1.124.0", + "@tanstack/react-router": "^1.125.3", + "@tanstack/react-router-with-query": "^1.125.3", + "@tanstack/react-start": "^1.125.3", + "@tanstack/zod-adapter": "^1.125.3", "ai": "^4.3.16", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", @@ -30,18 +30,18 @@ "radix-ui": "^1.4.2", "react": "^19.1.0", "react-dom": "^19.1.0", - "sonner": "^2.0.5", + "sonner": "^2.0.6", "tailwind-merge": "^3.3.1", "tailwindcss": "^4.1.11", "tailwindcss-animate": "^1.0.7", "uuid": "^11.1.0", "vite": "^6.3.5", - "zod": "^3.25.71", + "zod": "^3.25.74", }, "devDependencies": { "@tanstack/react-query-devtools": "^5.81.5", - "@tanstack/react-router-devtools": "^1.124.0", - "@tanstack/router-plugin": "^1.124.0", + "@tanstack/react-router-devtools": "^1.125.3", + "@tanstack/router-plugin": "^1.125.3", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^14.6.1", @@ -53,6 +53,7 @@ "@vitest/coverage-v8": "3.2.4", "jsdom": "^26.1.0", "oxlint": "^1.5.0", + "shadcn": "^2.8.0-canary.1", "typescript": "^5.8.3", "vite-tsconfig-paths": "^5.1.4", "vitest": "^3.2.4", @@ -76,6 +77,8 @@ "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], + "@antfu/ni": ["@antfu/ni@23.3.1", "", { "bin": { "na": "bin/na.mjs", "ni": "bin/ni.mjs", "nr": "bin/nr.mjs", "nu": "bin/nu.mjs", "nci": "bin/nci.mjs", "nlx": "bin/nlx.mjs", "nun": "bin/nun.mjs" } }, "sha512-C90iyzm/jLV7Lomv2UzwWUzRv9WZr1oRsFRKsX5HjQL4EXrbi9H/RtBkjCP+NF+ABZXUKpAa4F1dkoTaea4zHg=="], + "@asamuzakjp/css-color": ["@asamuzakjp/css-color@3.2.0", "", { "dependencies": { "@csstools/css-calc": "^2.1.3", "@csstools/css-color-parser": "^3.0.9", "@csstools/css-parser-algorithms": "^3.0.4", "@csstools/css-tokenizer": "^3.0.3", "lru-cache": "^10.4.3" } }, "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw=="], "@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], @@ -140,6 +143,12 @@ "@bcoe/v8-coverage": ["@bcoe/v8-coverage@1.0.2", "", {}, "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA=="], + "@bundled-es-modules/cookie": ["@bundled-es-modules/cookie@2.0.1", "", { "dependencies": { "cookie": "^0.7.2" } }, "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw=="], + + "@bundled-es-modules/statuses": ["@bundled-es-modules/statuses@1.0.1", "", { "dependencies": { "statuses": "^2.0.1" } }, "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg=="], + + "@bundled-es-modules/tough-cookie": ["@bundled-es-modules/tough-cookie@0.1.6", "", { "dependencies": { "@types/tough-cookie": "^4.0.5", "tough-cookie": "^4.1.4" } }, "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw=="], + "@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.4.0", "", { "dependencies": { "mime": "^3.0.0" } }, "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA=="], "@colors/colors": ["@colors/colors@1.6.0", "", {}, "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA=="], @@ -220,6 +229,14 @@ "@hookform/resolvers": ["@hookform/resolvers@4.1.3", "", { "dependencies": { "@standard-schema/utils": "^0.3.0" }, "peerDependencies": { "react-hook-form": "^7.0.0" } }, "sha512-Jsv6UOWYTrEFJ/01ZrnwVXs7KDvP8XIo115i++5PWvNkNvkrsTfGiLS6w+eJ57CYtUtDQalUWovCZDHFJ8u1VQ=="], + "@inquirer/confirm": ["@inquirer/confirm@5.1.13", "", { "dependencies": { "@inquirer/core": "^10.1.14", "@inquirer/type": "^3.0.7" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-EkCtvp67ICIVVzjsquUiVSd+V5HRGOGQfsqA4E4vMWhYnB7InUL0pa0TIWt1i+OfP16Gkds8CdIu6yGZwOM1Yw=="], + + "@inquirer/core": ["@inquirer/core@10.1.14", "", { "dependencies": { "@inquirer/figures": "^1.0.12", "@inquirer/type": "^3.0.7", "ansi-escapes": "^4.3.2", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-Ma+ZpOJPewtIYl6HZHZckeX1STvDnHTCB2GVINNUlSEn2Am6LddWwfPkIGY0IUFVjUUrr/93XlBwTK6mfLjf0A=="], + + "@inquirer/figures": ["@inquirer/figures@1.0.12", "", {}, "sha512-MJttijd8rMFcKJC8NYmprWr6hD3r9Gd9qUC0XwPNwoEPWSMVJwA2MlXxF+nhZZNMY+HXsWa+o7KY2emWYIn0jQ=="], + + "@inquirer/type": ["@inquirer/type@3.0.7", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-PfunHQcjwnju84L+ycmcMKB/pTPIngjUJvfnRhKY6FKPuYXlM4aQCb/nIdTFR6BEhMjFvngzvng/vBAJMZpLSA=="], + "@ioredis/commands": ["@ioredis/commands@1.2.0", "", {}, "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg=="], "@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=="], @@ -256,6 +273,8 @@ "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.15.0", "", { "dependencies": { "ajv": "^6.12.6", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.23.8", "zod-to-json-schema": "^3.24.1" } }, "sha512-67hnl/ROKdb03Vuu0YOr+baKTvf1/5YBHBm9KnZdjdAh8hjt4FRCPD5ucwxGB237sBpzlqQsLy1PFu7z/ekZ9Q=="], + "@mswjs/interceptors": ["@mswjs/interceptors@0.39.2", "", { "dependencies": { "@open-draft/deferred-promise": "^2.2.0", "@open-draft/logger": "^0.3.0", "@open-draft/until": "^2.0.0", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "strict-event-emitter": "^0.5.1" } }, "sha512-RuzCup9Ct91Y7V79xwCb146RaBRHZ7NBbrIUySumd1rpKqHL5OonaqrGIbug5hNwP/fRyxFMA6ISgw4FTtYFYg=="], + "@netlify/binary-info": ["@netlify/binary-info@1.0.0", "", {}, "sha512-4wMPu9iN3/HL97QblBsBay3E1etIciR84izI3U+4iALY+JHCrI+a2jO0qbAZ/nxKoegypYEaiiqWXylm+/zfrw=="], "@netlify/blobs": ["@netlify/blobs@9.1.2", "", { "dependencies": { "@netlify/dev-utils": "2.2.0", "@netlify/runtime-utils": "1.3.1" } }, "sha512-7dMjExSH4zj4ShvLem49mE3mf0K171Tx2pV4WDWhJbRUWW3SJIR2qntz0LvUGS97N5HO1SmnzrgWUhEXCsApiw=="], @@ -286,6 +305,12 @@ "@oozcitak/util": ["@oozcitak/util@8.3.8", "", {}, "sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ=="], + "@open-draft/deferred-promise": ["@open-draft/deferred-promise@2.2.0", "", {}, "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA=="], + + "@open-draft/logger": ["@open-draft/logger@0.3.0", "", { "dependencies": { "is-node-process": "^1.2.0", "outvariant": "^1.4.0" } }, "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ=="], + + "@open-draft/until": ["@open-draft/until@2.1.0", "", {}, "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg=="], + "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], "@oxlint/darwin-arm64": ["@oxlint/darwin-arm64@1.5.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-CxzOtmOwQfaXXwAAJzPInNHhzldMeFsga7oe9mUp5bYIa/mm/Aqs0lxyAP9RZXoxaUHJTbfJovSsl6PU6gbCHw=="], @@ -574,7 +599,7 @@ "@tanstack/query-devtools": ["@tanstack/query-devtools@5.81.2", "", {}, "sha512-jCeJcDCwKfoyyBXjXe9+Lo8aTkavygHHsUHAlxQKKaDeyT0qyQNLKl7+UyqYH2dDF6UN/14873IPBHchcsU+Zg=="], - "@tanstack/react-form": ["@tanstack/react-form@1.12.4", "", { "dependencies": { "@tanstack/form-core": "1.12.4", "@tanstack/react-store": "^0.7.1", "decode-formdata": "^0.9.0", "devalue": "^5.1.1" }, "peerDependencies": { "@tanstack/react-start": "^1.112.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0", "vinxi": "^0.5.0" }, "optionalPeers": ["@tanstack/react-start", "vinxi"] }, "sha512-MsWHTTUl1Db7tcawbREEMjUtnjK1wC9HnwEITFFhO6e9jN4vR8gb7qRM6TDKg0tkBf42fd5jhEI5qCYA8Sl2pQ=="], + "@tanstack/react-form": ["@tanstack/react-form@1.13.2", "", { "dependencies": { "@tanstack/form-core": "1.12.4", "@tanstack/react-store": "^0.7.1", "decode-formdata": "^0.9.0", "devalue": "^5.1.1" }, "peerDependencies": { "@tanstack/react-start": "^1.112.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0", "vinxi": "^0.5.0" }, "optionalPeers": ["@tanstack/react-start", "vinxi"] }, "sha512-ykO/J7yBegs917OmHgIB8zIWWmEWKTxKwvvQUa5gWv8HqOWwGbw3+MCEiz7W1ONxZjY/rCgJpNd7Rh1qFlglsg=="], "@tanstack/react-pacer": ["@tanstack/react-pacer@0.8.0", "", { "dependencies": { "@tanstack/pacer": "0.8.0" }, "peerDependencies": { "react": ">=16.8", "react-dom": ">=16.8" } }, "sha512-nQX5ACRHdOiZjPOudA3Ii64mPfRkeRkSYtjQaRMD3FqY9AQKuQJgPglAFA7U4UenLOXJvqXiKMWzFDi1Bw9EZQ=="], @@ -582,43 +607,43 @@ "@tanstack/react-query-devtools": ["@tanstack/react-query-devtools@5.81.5", "", { "dependencies": { "@tanstack/query-devtools": "5.81.2" }, "peerDependencies": { "@tanstack/react-query": "^5.81.5", "react": "^18 || ^19" } }, "sha512-lCGMu4RX0uGnlrlLeSckBfnW/UV+KMlTBVqa97cwK7Z2ED5JKnZRSjNXwoma6sQBTJrcULvzgx2K6jEPvNUpDw=="], - "@tanstack/react-router": ["@tanstack/react-router@1.124.0", "", { "dependencies": { "@tanstack/history": "1.121.34", "@tanstack/react-store": "^0.7.0", "@tanstack/router-core": "1.124.0", "isbot": "^5.1.22", "jsesc": "^3.1.0", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-jJxuLbPP/Cxirnft3CoiGWyH0aj94VTmLNcYauvjTGRNbUitK4udvGaHXVEP8bcifYvpko7ptsqqBlisaosugA=="], + "@tanstack/react-router": ["@tanstack/react-router@1.125.3", "", { "dependencies": { "@tanstack/history": "1.121.34", "@tanstack/react-store": "^0.7.0", "@tanstack/router-core": "1.125.3", "isbot": "^5.1.22", "jsesc": "^3.1.0", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-o3nXGActTL9gSsLxb7e0n5fH4a8eM7zRN+GptPgGhmUz4hAKTWuP/8sx/BuaVYReMvncWTTCYI2PQVKaFxtq6A=="], - "@tanstack/react-router-devtools": ["@tanstack/react-router-devtools@1.124.0", "", { "dependencies": { "@tanstack/router-devtools-core": "^1.124.0" }, "peerDependencies": { "@tanstack/react-router": "^1.124.0", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-CpOUUvtOYfLQEQS/ikGL9FQgEgYzBOKq9/2LqqFDXhZZgCVW18rBvR3LZeejkYSHAWlRphG33sdXCYVRM02sZQ=="], + "@tanstack/react-router-devtools": ["@tanstack/react-router-devtools@1.125.3", "", { "dependencies": { "@tanstack/router-devtools-core": "^1.125.3" }, "peerDependencies": { "@tanstack/react-router": "^1.125.3", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-fQKgKkSwphtj906ULB7RVwM7xmJm9UAP2fc6sapBR3Ix/VYajI4bGvZWLuYJEZ7GM7jwqGLkQGiNbWuOkoFDCw=="], - "@tanstack/react-router-with-query": ["@tanstack/react-router-with-query@1.124.0", "", { "peerDependencies": { "@tanstack/react-query": ">=5.49.2", "@tanstack/react-router": ">=1.43.2", "@tanstack/router-core": ">=1.114.7", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-gZeN5VdGIIfD7V5UrxmZfP6EjYK9wbxzUniETMDdlQdMz/cGVbVYmAj5khqtvHVsGdAz4ZXJ5xfiARE78djLsw=="], + "@tanstack/react-router-with-query": ["@tanstack/react-router-with-query@1.125.3", "", { "peerDependencies": { "@tanstack/react-query": ">=5.49.2", "@tanstack/react-router": ">=1.43.2", "@tanstack/router-core": ">=1.114.7", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-I+3kmAGOs8KzFULSju+lZKYwJmiMaUDXXQwnCqJCGiu49qWvl3oEbAILWWzeN1HMHEmwpn5sR67mF0BjvTWoSA=="], - "@tanstack/react-start": ["@tanstack/react-start@1.124.1", "", { "dependencies": { "@tanstack/react-start-client": "1.124.0", "@tanstack/react-start-plugin": "1.124.1", "@tanstack/react-start-server": "1.124.0", "@tanstack/start-server-functions-client": "1.124.1", "@tanstack/start-server-functions-server": "1.124.1" }, "peerDependencies": { "@vitejs/plugin-react": ">=4.3.4", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0", "vite": ">=6.0.0" } }, "sha512-/R/7efpNDtTh85oSrc035O+rjYync5PQV2WixrbUWkDZ2jjkwGhIHblwNDSqMxTDboyuCxF2b9K2EIGDGIwF5A=="], + "@tanstack/react-start": ["@tanstack/react-start@1.125.3", "", { "dependencies": { "@tanstack/react-start-client": "1.125.3", "@tanstack/react-start-plugin": "1.125.3", "@tanstack/react-start-server": "1.125.3", "@tanstack/start-server-functions-client": "1.125.3", "@tanstack/start-server-functions-server": "1.124.1" }, "peerDependencies": { "@vitejs/plugin-react": ">=4.3.4", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0", "vite": ">=6.0.0" } }, "sha512-B+9YAo7JUCqxUJxjCe/ESaAD51YkWz19exVyz9YR+tvR4cip0G8iQrJGAla54Y04UrP/O0pXPietorQrS0aczA=="], - "@tanstack/react-start-client": ["@tanstack/react-start-client@1.124.0", "", { "dependencies": { "@tanstack/react-router": "1.124.0", "@tanstack/router-core": "1.124.0", "@tanstack/start-client-core": "1.124.0", "cookie-es": "^1.2.2", "jsesc": "^3.1.0", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-levx9QH0cswxf+VgmBkgQnk1BxtLaEK3bCWgjPGfVGgrLPR+QItf9jBp50mjLbbvc5flC6XcYBLEVFxvlB28kQ=="], + "@tanstack/react-start-client": ["@tanstack/react-start-client@1.125.3", "", { "dependencies": { "@tanstack/react-router": "1.125.3", "@tanstack/router-core": "1.125.3", "@tanstack/start-client-core": "1.125.3", "cookie-es": "^1.2.2", "jsesc": "^3.1.0", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-No2rU53rsb1VKAyCvs+h4pgxH8N7p0wJD23edXZcc6Rjj1yu6V8TKqZRS7Qt86N1dBLH7YWt5jE74RVIjkarHQ=="], - "@tanstack/react-start-plugin": ["@tanstack/react-start-plugin@1.124.1", "", { "dependencies": { "@tanstack/start-plugin-core": "1.124.1", "zod": "^3.24.2" }, "peerDependencies": { "@vitejs/plugin-react": ">=4.3.4", "vite": ">=6.0.0" } }, "sha512-K6T1bxmLbh7xBH2uxi7eLsk0SfBbaoaBWMcA/mZ5w4SiFi2FMkGS+LzORrWm/RYSTw6zPJ/iTWBRdCBIJDVgWg=="], + "@tanstack/react-start-plugin": ["@tanstack/react-start-plugin@1.125.3", "", { "dependencies": { "@tanstack/start-plugin-core": "1.125.3", "zod": "^3.24.2" }, "peerDependencies": { "@vitejs/plugin-react": ">=4.3.4", "vite": ">=6.0.0" } }, "sha512-/JdCzWsViIYikyNBhLy7BloWPjbxO/7WLX3WL/iQfYGYiC5arfrYU/Ihun460XuxcGdt6ZBCkxzmVeG1qtg9RQ=="], - "@tanstack/react-start-server": ["@tanstack/react-start-server@1.124.0", "", { "dependencies": { "@tanstack/history": "^1.121.34", "@tanstack/react-router": "^1.124.0", "@tanstack/router-core": "^1.124.0", "@tanstack/start-client-core": "1.124.0", "@tanstack/start-server-core": "1.124.0", "h3": "1.13.0", "isbot": "^5.1.22" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-DTsPJRUXqpTOxhRRXobGyi2Dn4GiTkjR/U76meYQf0aBePvSdjBDXJkmG/3+kyRYTF1MUA/l4mnvIXujmP0Nkg=="], + "@tanstack/react-start-server": ["@tanstack/react-start-server@1.125.3", "", { "dependencies": { "@tanstack/history": "^1.121.34", "@tanstack/react-router": "^1.125.3", "@tanstack/router-core": "^1.125.3", "@tanstack/start-client-core": "1.125.3", "@tanstack/start-server-core": "1.125.3", "h3": "1.13.0", "isbot": "^5.1.22" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-qaO+/Twjah1JhlCKXTl2VE5ip9gRLfvUVhkil2Wdpc2c2/PWKB+ABYybbuoBY36gAMps0Z1NF2WynjyGt6rzpA=="], "@tanstack/react-store": ["@tanstack/react-store@0.7.1", "", { "dependencies": { "@tanstack/store": "0.7.1", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-qUTEKdId6QPWGiWyKAPf/gkN29scEsz6EUSJ0C3HgLMgaqTAyBsQ2sMCfGVcqb+kkhEXAdjleCgH6LAPD6f2sA=="], - "@tanstack/router-core": ["@tanstack/router-core@1.124.0", "", { "dependencies": { "@tanstack/history": "1.121.34", "@tanstack/store": "^0.7.0", "cookie-es": "^1.2.2", "jsesc": "^3.1.0", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" } }, "sha512-mU2KA2v+ZFWC3NIjY2y+pPCx1sZDXPsUkzPjPPZxRgonE11nIu9MB89WuukqYuPbxoSWeodKNXsLe4KksGFCKA=="], + "@tanstack/router-core": ["@tanstack/router-core@1.125.3", "", { "dependencies": { "@tanstack/history": "1.121.34", "@tanstack/store": "^0.7.0", "cookie-es": "^1.2.2", "jsesc": "^3.1.0", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" } }, "sha512-Nz4mcVqRJR7O9A1+/l9RZJV/bFVjWNEajtg6ZzlXomeZ+Dqo5vNBf5zzkmG2bAi1iibcQDAgt8T2LjCEn1JsGg=="], - "@tanstack/router-devtools-core": ["@tanstack/router-devtools-core@1.124.0", "", { "dependencies": { "clsx": "^2.1.1", "goober": "^2.1.16", "solid-js": "^1.9.5" }, "peerDependencies": { "@tanstack/router-core": "^1.124.0", "csstype": "^3.0.10", "tiny-invariant": "^1.3.3" }, "optionalPeers": ["csstype"] }, "sha512-F4xejY63XrQmQZ8q6IJmLHJGeow/5CzdCAWChYEHIFy9SWYiFMMvdGFpB8SReJuwld+eoHvvtp2qhUqNloqzRA=="], + "@tanstack/router-devtools-core": ["@tanstack/router-devtools-core@1.125.3", "", { "dependencies": { "clsx": "^2.1.1", "goober": "^2.1.16", "solid-js": "^1.9.5" }, "peerDependencies": { "@tanstack/router-core": "^1.125.3", "csstype": "^3.0.10", "tiny-invariant": "^1.3.3" }, "optionalPeers": ["csstype"] }, "sha512-cQLDzNGr5M055XpJ5lZoi91OoO30BL8TTPkolARnPmnWaceJtGq4FLSfBlrKUhq/NONHG8fzP1hfQpDLxv/klg=="], - "@tanstack/router-generator": ["@tanstack/router-generator@1.124.0", "", { "dependencies": { "@tanstack/router-core": "^1.124.0", "@tanstack/router-utils": "1.121.21", "@tanstack/virtual-file-routes": "^1.121.21", "prettier": "^3.5.0", "recast": "^0.23.11", "source-map": "^0.7.4", "tsx": "^4.19.2", "zod": "^3.24.2" } }, "sha512-fatjfBvgLh7i2xcLKO3QaM5egHAhMy57B7DfE44sYx1D7/xxLOubSEjSnVSLE3dWBrstZ3aqyuYYhw7NuoXB7g=="], + "@tanstack/router-generator": ["@tanstack/router-generator@1.125.3", "", { "dependencies": { "@tanstack/router-core": "^1.125.3", "@tanstack/router-utils": "1.121.21", "@tanstack/virtual-file-routes": "^1.121.21", "prettier": "^3.5.0", "recast": "^0.23.11", "source-map": "^0.7.4", "tsx": "^4.19.2", "zod": "^3.24.2" } }, "sha512-3Qf7OIz5K2fAAgC5ihz3EYknNFIQc8tkpyVPg+ihuAxgUQc/qj14G/P7uNkvqp6nUDBoFBryIhsPOKsvAYeLAw=="], - "@tanstack/router-plugin": ["@tanstack/router-plugin@1.124.0", "", { "dependencies": { "@babel/core": "^7.27.7", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/template": "^7.27.2", "@babel/traverse": "^7.27.7", "@babel/types": "^7.27.7", "@tanstack/router-core": "^1.124.0", "@tanstack/router-generator": "1.124.0", "@tanstack/router-utils": "1.121.21", "@tanstack/virtual-file-routes": "^1.121.21", "babel-dead-code-elimination": "^1.0.10", "chokidar": "^3.6.0", "unplugin": "^2.1.2", "zod": "^3.24.2" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", "@tanstack/react-router": "^1.124.0", "vite": ">=5.0.0 || >=6.0.0", "vite-plugin-solid": "^2.11.2", "webpack": ">=5.92.0" }, "optionalPeers": ["@rsbuild/core", "@tanstack/react-router", "vite", "vite-plugin-solid", "webpack"] }, "sha512-CqV3PCVoMrHw0HyTioIGHTTjaMRgfwbW4ax2Pule++smyetn+3KPLV6C3VWc0vdukZMQz13JvLORSSeM0B2cYQ=="], + "@tanstack/router-plugin": ["@tanstack/router-plugin@1.125.3", "", { "dependencies": { "@babel/core": "^7.27.7", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/template": "^7.27.2", "@babel/traverse": "^7.27.7", "@babel/types": "^7.27.7", "@tanstack/router-core": "^1.125.3", "@tanstack/router-generator": "1.125.3", "@tanstack/router-utils": "1.121.21", "@tanstack/virtual-file-routes": "^1.121.21", "babel-dead-code-elimination": "^1.0.10", "chokidar": "^3.6.0", "unplugin": "^2.1.2", "zod": "^3.24.2" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", "@tanstack/react-router": "^1.125.3", "vite": ">=5.0.0 || >=6.0.0", "vite-plugin-solid": "^2.11.2", "webpack": ">=5.92.0" }, "optionalPeers": ["@rsbuild/core", "@tanstack/react-router", "vite", "vite-plugin-solid", "webpack"] }, "sha512-fU0V9yztsC/ZlZ1EVeMhnK7GOoDhPvJsrF+J1UFOQEhWMJqVjErLSIgRUsevzCNsxeO/mQgHXkEN3KZcsLyNoA=="], "@tanstack/router-utils": ["@tanstack/router-utils@1.121.21", "", { "dependencies": { "@babel/core": "^7.27.4", "@babel/generator": "^7.27.5", "@babel/parser": "^7.27.5", "@babel/preset-typescript": "^7.27.1", "ansis": "^4.1.0", "diff": "^8.0.2" } }, "sha512-u7ubq1xPBtNiU7Fm+EOWlVWdgFLzuKOa1thhqdscVn8R4dNMUd1VoOjZ6AKmLw201VaUhFtlX+u0pjzI6szX7A=="], "@tanstack/server-functions-plugin": ["@tanstack/server-functions-plugin@1.124.1", "", { "dependencies": { "@babel/code-frame": "7.27.1", "@babel/core": "^7.27.7", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/template": "^7.27.2", "@babel/traverse": "^7.27.7", "@babel/types": "^7.27.7", "@tanstack/directive-functions-plugin": "1.124.1", "babel-dead-code-elimination": "^1.0.9", "tiny-invariant": "^1.3.3" } }, "sha512-9GIu+PXu5itj+Q74FJQpd4WV3FikzkAAxvBl9hrnmiEwz+AGDZL0GOiGy++MdupHJXuHXXss9mHqKtNmw9wMdw=="], - "@tanstack/start-client-core": ["@tanstack/start-client-core@1.124.0", "", { "dependencies": { "@tanstack/router-core": "1.124.0", "cookie-es": "^1.2.2", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" } }, "sha512-BT8oVtaElSKlRN6rySV2M7cn+2duuSJPe4iMMGq7h2fSo9Su85ZNMrIGisU85BAvQ7Vn2LS0LDVScFCahOoPPA=="], + "@tanstack/start-client-core": ["@tanstack/start-client-core@1.125.3", "", { "dependencies": { "@tanstack/router-core": "1.125.3", "cookie-es": "^1.2.2", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" } }, "sha512-rfda21zwvy/Xr7QHz92+ltrgOnL9/nKrSo+s9ZwCphgqpJSR+LKhb7UgnUXdQs6lnleoyzuf14+VEjpznx9I+g=="], - "@tanstack/start-plugin-core": ["@tanstack/start-plugin-core@1.124.1", "", { "dependencies": { "@babel/code-frame": "7.26.2", "@babel/core": "^7.26.8", "@babel/types": "^7.26.8", "@tanstack/router-core": "1.124.0", "@tanstack/router-generator": "1.124.0", "@tanstack/router-plugin": "1.124.0", "@tanstack/router-utils": "1.121.21", "@tanstack/server-functions-plugin": "1.124.1", "@tanstack/start-server-core": "1.124.0", "@types/babel__code-frame": "^7.0.6", "@types/babel__core": "^7.20.5", "babel-dead-code-elimination": "^1.0.9", "cheerio": "^1.0.0", "h3": "1.13.0", "nitropack": "^2.11.12", "pathe": "^2.0.3", "ufo": "^1.5.4", "xmlbuilder2": "^3.1.1", "zod": "^3.24.2" }, "peerDependencies": { "vite": ">=6.0.0" } }, "sha512-9qksni/DRKWIPtXBUZ9CBgdD9NibHscMSi8+g4W5Fj2hlN9TvyQ0fxymyMx9dpmqtNx7GeFAu8bZh0Kk+H5YrA=="], + "@tanstack/start-plugin-core": ["@tanstack/start-plugin-core@1.125.3", "", { "dependencies": { "@babel/code-frame": "7.26.2", "@babel/core": "^7.26.8", "@babel/types": "^7.26.8", "@tanstack/router-core": "1.125.3", "@tanstack/router-generator": "1.125.3", "@tanstack/router-plugin": "1.125.3", "@tanstack/router-utils": "1.121.21", "@tanstack/server-functions-plugin": "1.124.1", "@tanstack/start-server-core": "1.125.3", "@types/babel__code-frame": "^7.0.6", "@types/babel__core": "^7.20.5", "babel-dead-code-elimination": "^1.0.9", "cheerio": "^1.0.0", "h3": "1.13.0", "nitropack": "^2.11.12", "pathe": "^2.0.3", "ufo": "^1.5.4", "xmlbuilder2": "^3.1.1", "zod": "^3.24.2" }, "peerDependencies": { "vite": ">=6.0.0" } }, "sha512-1JgQpzRPG/1lsts23Oed0FiSE3s/0ul5DYmKqpQ5StLkG+RRDfRJvD63yMivRjaCTAOMPszKhLFMML32wl2KVA=="], - "@tanstack/start-server-core": ["@tanstack/start-server-core@1.124.0", "", { "dependencies": { "@tanstack/history": "1.121.34", "@tanstack/router-core": "1.124.0", "@tanstack/start-client-core": "1.124.0", "h3": "1.13.0", "isbot": "^5.1.22", "jsesc": "^3.1.0", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3", "unctx": "^2.4.1" } }, "sha512-tNduQzWkjKR4PIwmFNRh9K9sotEuOmc0pIpQ3FECBhLcyVF/32KAnu3uRXF3aoovvma3XhNYldQN4aM74WxPfg=="], + "@tanstack/start-server-core": ["@tanstack/start-server-core@1.125.3", "", { "dependencies": { "@tanstack/history": "1.121.34", "@tanstack/router-core": "1.125.3", "@tanstack/start-client-core": "1.125.3", "h3": "1.13.0", "isbot": "^5.1.22", "jsesc": "^3.1.0", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3", "unctx": "^2.4.1" } }, "sha512-cd0oRNK5i5Y+hN47a/zQFJ6TTG+mT/bnK/2p3rJBfod9Ia8Z354UWwP2kAPOUT0VVZcvyCI5jKjLGY8NLC4w4A=="], - "@tanstack/start-server-functions-client": ["@tanstack/start-server-functions-client@1.124.1", "", { "dependencies": { "@tanstack/server-functions-plugin": "1.124.1", "@tanstack/start-server-functions-fetcher": "1.124.0" } }, "sha512-r0h3stJP/15T+GQmMaBXCUkmW8t6RbMKys6S6ELXt9AmXfxEbD0V+KxVIxvp7LktubYVRuuZPom6w6+n1oNkwQ=="], + "@tanstack/start-server-functions-client": ["@tanstack/start-server-functions-client@1.125.3", "", { "dependencies": { "@tanstack/server-functions-plugin": "1.124.1", "@tanstack/start-server-functions-fetcher": "1.125.3" } }, "sha512-byopum8LsqCEtkFY6BiPfDMb8FLOHrC+wI8Djh3sKil3H/07Lf/qHPOSU9GHBQMOZ7Im4fsU4165G157A1K1tQ=="], - "@tanstack/start-server-functions-fetcher": ["@tanstack/start-server-functions-fetcher@1.124.0", "", { "dependencies": { "@tanstack/router-core": "1.124.0", "@tanstack/start-client-core": "1.124.0" } }, "sha512-UztOiOUFYXnS9wlkWw2OQSgM9g/KG88FFEjC4UVOAPbXdAJtkROp1FoES/grEUgzE9bXGXo7YANJXL/mLN+JyQ=="], + "@tanstack/start-server-functions-fetcher": ["@tanstack/start-server-functions-fetcher@1.125.3", "", { "dependencies": { "@tanstack/router-core": "1.125.3", "@tanstack/start-client-core": "1.125.3" } }, "sha512-l006+XmmRMNxcKUz8glmfXlSmrJOiTwy4DQ1/Qpa4qxEDeBiiHLU4IkDbGTwUk7IQUgHO8ooL56BFCIfn/1RfA=="], "@tanstack/start-server-functions-server": ["@tanstack/start-server-functions-server@1.124.1", "", { "dependencies": { "@tanstack/server-functions-plugin": "1.124.1", "tiny-invariant": "^1.3.3" } }, "sha512-59NJqtdXm2c+JmwDqm3ZuvgcN1KT2LlvApelydj9y201lj76XjcEH4RqbJKm5G7C/wc98QPhghFHY8cwHJUCTg=="], @@ -626,7 +651,7 @@ "@tanstack/virtual-file-routes": ["@tanstack/virtual-file-routes@1.121.21", "", {}, "sha512-3nuYsTyaq6ZN7jRZ9z6Gj3GXZqBOqOT0yzd/WZ33ZFfv4yVNIvsa5Lw+M1j3sgyEAxKMqGu/FaNi7FCjr3yOdw=="], - "@tanstack/zod-adapter": ["@tanstack/zod-adapter@1.124.0", "", { "peerDependencies": { "@tanstack/react-router": ">=1.43.2", "zod": "^3.23.8" } }, "sha512-AxvWKDnPbHUipUoxXe1TBdjSGicF7Ri1WwL68UVRryRNw8wxI4ZTSBtgqB5LuBXuFfwyZYydrngP0CnXeb/g3w=="], + "@tanstack/zod-adapter": ["@tanstack/zod-adapter@1.125.3", "", { "peerDependencies": { "@tanstack/react-router": ">=1.43.2", "zod": "^3.23.8" } }, "sha512-oQZPE0DUcPTFLGkub1tPA5uu7ZRFKV75nw0aXMsvdh7Ik74xhkNHa2cRSuKiGF9dJcN4ZWWCZiOPNAS6ASIzEw=="], "@testing-library/dom": ["@testing-library/dom@10.4.0", "", { "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", "@types/aria-query": "^5.0.1", "aria-query": "5.3.0", "chalk": "^4.1.0", "dom-accessibility-api": "^0.5.9", "lz-string": "^1.5.0", "pretty-format": "^27.0.2" } }, "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ=="], @@ -636,6 +661,8 @@ "@testing-library/user-event": ["@testing-library/user-event@14.6.1", "", { "peerDependencies": { "@testing-library/dom": ">=7.21.4" } }, "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw=="], + "@ts-morph/common": ["@ts-morph/common@0.19.0", "", { "dependencies": { "fast-glob": "^3.2.12", "minimatch": "^7.4.3", "mkdirp": "^2.1.6", "path-browserify": "^1.0.1" } }, "sha512-Unz/WHmd4pGax91rdIKWi51wnVUW11QttMEPpBiBgIewnc9UQIX7UDLxr5vRlqeByXCwhkF6VabSsI0raWcyAQ=="], + "@types/aria-query": ["@types/aria-query@5.0.4", "", {}, "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw=="], "@types/babel__code-frame": ["@types/babel__code-frame@7.0.6", "", {}, "sha512-Anitqkl3+KrzcW2k77lRlg/GfLZLWXBuNgbEcIOU6M92yw42vsd3xV/Z/yAHEj8m+KUjL6bWOVOFqX8PFPJ4LA=="], @@ -652,6 +679,8 @@ "@types/chai": ["@types/chai@5.2.2", "", { "dependencies": { "@types/deep-eql": "*" } }, "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg=="], + "@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="], + "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="], "@types/diff-match-patch": ["@types/diff-match-patch@1.0.36", "", {}, "sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg=="], @@ -678,6 +707,10 @@ "@types/stack-utils": ["@types/stack-utils@2.0.3", "", {}, "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="], + "@types/statuses": ["@types/statuses@2.0.6", "", {}, "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA=="], + + "@types/tough-cookie": ["@types/tough-cookie@4.0.5", "", {}, "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="], + "@types/triple-beam": ["@types/triple-beam@1.3.5", "", {}, "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw=="], "@types/yargs": ["@types/yargs@17.0.33", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA=="], @@ -752,6 +785,8 @@ "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + "ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="], + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], @@ -764,7 +799,7 @@ "archiver-utils": ["archiver-utils@5.0.2", "", { "dependencies": { "glob": "^10.0.0", "graceful-fs": "^4.2.0", "is-stream": "^2.0.1", "lazystream": "^1.0.0", "lodash": "^4.17.15", "normalize-path": "^3.0.0", "readable-stream": "^4.0.0" } }, "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA=="], - "argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="], @@ -796,6 +831,8 @@ "bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="], + "bl": ["bl@5.1.0", "", { "dependencies": { "buffer": "^6.0.3", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ=="], + "body-parser": ["body-parser@2.2.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.0", "http-errors": "^2.0.0", "iconv-lite": "^0.6.3", "on-finished": "^2.4.1", "qs": "^6.14.0", "raw-body": "^3.0.0", "type-is": "^2.0.0" } }, "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg=="], "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], @@ -828,6 +865,8 @@ "callsite": ["callsite@1.0.0", "", {}, "sha512-0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ=="], + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + "caniuse-lite": ["caniuse-lite@1.0.30001724", "", {}, "sha512-WqJo7p0TbHDOythNTqYujmaJTvtYRZrjpP8TCvH6Vb9CYJerJNKamKzIWOM4BkQatWj9H2lYulpdAQNBe7QhNA=="], "chai": ["chai@5.2.0", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw=="], @@ -850,16 +889,26 @@ "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="], + "cli-cursor": ["cli-cursor@4.0.0", "", { "dependencies": { "restore-cursor": "^4.0.0" } }, "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg=="], + + "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="], + + "cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="], + "clipboardy": ["clipboardy@4.0.0", "", { "dependencies": { "execa": "^8.0.1", "is-wsl": "^3.1.0", "is64bit": "^2.0.0" } }, "sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w=="], "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], + "clone": ["clone@1.0.4", "", {}, "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="], + "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], "cluster-key-slot": ["cluster-key-slot@1.1.2", "", {}, "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="], "cmdk": ["cmdk@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "^1.1.1", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-id": "^1.1.0", "@radix-ui/react-primitive": "^2.0.2" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "react-dom": "^18 || ^19 || ^19.0.0-rc" } }, "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg=="], + "code-block-writer": ["code-block-writer@12.0.0", "", {}, "sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w=="], + "color": ["color@3.2.1", "", { "dependencies": { "color-convert": "^1.9.3", "color-string": "^1.6.0" } }, "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA=="], "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], @@ -870,7 +919,7 @@ "colorspace": ["colorspace@1.1.4", "", { "dependencies": { "color": "^3.1.3", "text-hex": "1.0.x" } }, "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w=="], - "commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], + "commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], "common-path-prefix": ["common-path-prefix@3.0.0", "", {}, "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w=="], @@ -902,6 +951,8 @@ "cors": ["cors@2.8.5", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g=="], + "cosmiconfig": ["cosmiconfig@8.3.6", "", { "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0", "path-type": "^4.0.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA=="], + "crc-32": ["crc-32@1.2.2", "", { "bin": { "crc32": "bin/crc32.njs" } }, "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="], "crc32-stream": ["crc32-stream@6.0.0", "", { "dependencies": { "crc-32": "^1.2.0", "readable-stream": "^4.0.0" } }, "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g=="], @@ -942,6 +993,8 @@ "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], + "defaults": ["defaults@1.0.4", "", { "dependencies": { "clone": "^1.0.2" } }, "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A=="], + "define-lazy-prop": ["define-lazy-prop@2.0.0", "", {}, "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="], "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], @@ -978,7 +1031,7 @@ "devalue": ["devalue@5.1.1", "", {}, "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw=="], - "diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], + "diff": ["diff@5.2.0", "", {}, "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A=="], "diff-match-patch": ["diff-match-patch@1.0.5", "", {}, "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw=="], @@ -1006,7 +1059,7 @@ "electron-to-chromium": ["electron-to-chromium@1.5.171", "", {}, "sha512-scWpzXEJEMrGJa4Y6m/tVotb0WuvNmasv3wWVzUAeCgKU0ToFOhUW6Z+xWnRQANMYGxN4ngJXIThgBJOqzVPCQ=="], - "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "enabled": ["enabled@2.0.0", "", {}, "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="], @@ -1022,6 +1075,8 @@ "env-paths": ["env-paths@3.0.0", "", {}, "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A=="], + "error-ex": ["error-ex@1.3.2", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g=="], + "error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="], "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], @@ -1062,7 +1117,7 @@ "eventsource-parser": ["eventsource-parser@3.0.3", "", {}, "sha512-nVpZkTMM9rF6AQ9gPJpFsNAMt48wIzB5TQgiTLdHiuO8XEDhUgZEhqKlZWXbIzo9VmJ/HvysHqEaVeD5v9TPvA=="], - "execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="], + "execa": ["execa@7.2.0", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.1", "human-signals": "^4.3.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^3.0.7", "strip-final-newline": "^3.0.0" } }, "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA=="], "expect": ["expect@30.0.2", "", { "dependencies": { "@jest/expect-utils": "30.0.2", "@jest/get-type": "30.0.1", "jest-matcher-utils": "30.0.2", "jest-message-util": "30.0.2", "jest-mock": "30.0.2", "jest-util": "30.0.2" } }, "sha512-YN9Mgv2mtTWXVmifQq3QT+ixCL/uLuLJw+fdp8MOjKqu8K3XQh3o5aulMM1tn+O2DdrWNxLZTeJsCY/VofUA0A=="], @@ -1116,6 +1171,8 @@ "fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="], + "fs-extra": ["fs-extra@11.3.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew=="], + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], @@ -1130,11 +1187,13 @@ "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="], + "get-own-enumerable-keys": ["get-own-enumerable-keys@1.0.0", "", {}, "sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA=="], + "get-port-please": ["get-port-please@3.1.2", "", {}, "sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ=="], "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], - "get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="], + "get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="], "get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="], @@ -1158,6 +1217,8 @@ "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + "graphql": ["graphql@16.11.0", "", {}, "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw=="], + "gzip-size": ["gzip-size@7.0.0", "", { "dependencies": { "duplexer": "^0.1.2" } }, "sha512-O1Ld7Dr+nqPnmGpdhzLmMTQ4vAsD+rHwMm1NLUmoUFFymBOMKxCCrtDxqdBRYXdeEPEi3SyoR4TizJLQrnKBNA=="], "h3": ["h3@1.13.0", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": ">=0.2.0 <0.4.0", "defu": "^6.1.4", "destr": "^2.0.3", "iron-webcrypto": "^1.2.1", "ohash": "^1.1.4", "radix3": "^1.1.2", "ufo": "^1.5.4", "uncrypto": "^0.1.3", "unenv": "^1.10.0" } }, "sha512-vFEAu/yf8UMUcB4s43OaDaigcqpQd14yanmOsn+NcRX3/guSKncyE2rOYhq8RIchgJrPSs/QiIddnTTR1ddiAg=="], @@ -1168,6 +1229,8 @@ "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + "headers-polyfill": ["headers-polyfill@4.0.3", "", {}, "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ=="], + "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="], "hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w=="], @@ -1188,7 +1251,7 @@ "httpxy": ["httpxy@0.1.7", "", {}, "sha512-pXNx8gnANKAndgga5ahefxc++tJvNL87CXoRwxn1cJE2ZkWEojF3tNfQIEhZX/vfpt+wzeAzpUI4qkediX1MLQ=="], - "human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="], + "human-signals": ["human-signals@4.3.1", "", {}, "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ=="], "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], @@ -1196,6 +1259,8 @@ "ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], + "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], @@ -1210,7 +1275,7 @@ "iron-webcrypto": ["iron-webcrypto@1.2.1", "", {}, "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg=="], - "is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="], + "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], @@ -1228,10 +1293,16 @@ "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="], + "is-interactive": ["is-interactive@2.0.0", "", {}, "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="], + "is-module": ["is-module@1.0.0", "", {}, "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="], + "is-node-process": ["is-node-process@1.2.0", "", {}, "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw=="], + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + "is-obj": ["is-obj@3.0.0", "", {}, "sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ=="], + "is-path-inside": ["is-path-inside@4.0.0", "", {}, "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA=="], "is-plain-obj": ["is-plain-obj@2.1.0", "", {}, "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA=="], @@ -1242,7 +1313,11 @@ "is-reference": ["is-reference@1.2.1", "", { "dependencies": { "@types/estree": "*" } }, "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ=="], - "is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="], + "is-regexp": ["is-regexp@3.1.0", "", {}, "sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA=="], + + "is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="], + + "is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], "is-url": ["is-url@1.2.4", "", {}, "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww=="], @@ -1284,12 +1359,14 @@ "js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="], - "js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="], + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], "jsdom": ["jsdom@26.1.0", "", { "dependencies": { "cssstyle": "^4.2.1", "data-urls": "^5.0.0", "decimal.js": "^10.5.0", "html-encoding-sniffer": "^4.0.0", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.6", "is-potential-custom-element-name": "^1.0.1", "nwsapi": "^2.2.16", "parse5": "^7.2.1", "rrweb-cssom": "^0.8.0", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^5.1.1", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.1.1", "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, "peerDependencies": { "canvas": "^3.0.0" }, "optionalPeers": ["canvas"] }, "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg=="], "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], + "json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="], "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], @@ -1298,6 +1375,8 @@ "jsondiffpatch": ["jsondiffpatch@0.6.0", "", { "dependencies": { "@types/diff-match-patch": "^1.0.36", "chalk": "^5.3.0", "diff-match-patch": "^1.0.5" }, "bin": { "jsondiffpatch": "bin/jsondiffpatch.js" } }, "sha512-3QItJOXp2AP1uv7waBkao5nCvhEv+QmJAd38Ybq7wNI74Q+BBmnLn4EDKz6yI9xGAIQoUF87qHt+kc1IVxB4zQ=="], + "jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="], + "junk": ["junk@4.0.1", "", {}, "sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ=="], "jwt-decode": ["jwt-decode@4.0.0", "", {}, "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA=="], @@ -1336,6 +1415,8 @@ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="], + "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], + "listhen": ["listhen@1.9.0", "", { "dependencies": { "@parcel/watcher": "^2.4.1", "@parcel/watcher-wasm": "^2.4.1", "citty": "^0.1.6", "clipboardy": "^4.0.0", "consola": "^3.2.3", "crossws": ">=0.2.0 <0.4.0", "defu": "^6.1.4", "get-port-please": "^3.1.2", "h3": "^1.12.0", "http-shutdown": "^1.2.2", "jiti": "^2.1.2", "mlly": "^1.7.1", "node-forge": "^1.3.1", "pathe": "^1.1.2", "std-env": "^3.7.0", "ufo": "^1.5.4", "untun": "^0.1.3", "uqr": "^0.1.2" }, "bin": { "listen": "bin/listhen.mjs", "listhen": "bin/listhen.mjs" } }, "sha512-I8oW2+QL5KJo8zXNWX046M134WchxsXC7SawLPvRQpogCbkyQIaFxPE89A2HiwR7vAK2Dm2ERBAmyjTYGYEpBg=="], "local-pkg": ["local-pkg@1.1.1", "", { "dependencies": { "mlly": "^1.7.4", "pkg-types": "^2.0.1", "quansync": "^0.2.8" } }, "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg=="], @@ -1352,6 +1433,8 @@ "lodash.isarguments": ["lodash.isarguments@3.1.0", "", {}, "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="], + "log-symbols": ["log-symbols@5.1.0", "", { "dependencies": { "chalk": "^5.0.0", "is-unicode-supported": "^1.1.0" } }, "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA=="], + "logform": ["logform@2.7.0", "", { "dependencies": { "@colors/colors": "1.6.0", "@types/triple-beam": "^1.3.2", "fecha": "^4.2.0", "ms": "^2.1.1", "safe-stable-stringify": "^2.3.1", "triple-beam": "^1.3.0" } }, "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ=="], "loupe": ["loupe@3.1.4", "", {}, "sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg=="], @@ -1406,7 +1489,7 @@ "mitt": ["mitt@3.0.1", "", {}, "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="], - "mkdirp": ["mkdirp@3.0.1", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="], + "mkdirp": ["mkdirp@2.1.6", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A=="], "mlly": ["mlly@1.7.4", "", { "dependencies": { "acorn": "^8.14.0", "pathe": "^2.0.1", "pkg-types": "^1.3.0", "ufo": "^1.5.4" } }, "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw=="], @@ -1414,6 +1497,10 @@ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + "msw": ["msw@2.10.3", "", { "dependencies": { "@bundled-es-modules/cookie": "^2.0.1", "@bundled-es-modules/statuses": "^1.0.1", "@bundled-es-modules/tough-cookie": "^0.1.6", "@inquirer/confirm": "^5.0.0", "@mswjs/interceptors": "^0.39.1", "@open-draft/deferred-promise": "^2.2.0", "@open-draft/until": "^2.1.0", "@types/cookie": "^0.6.0", "@types/statuses": "^2.0.4", "graphql": "^16.8.1", "headers-polyfill": "^4.0.2", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", "strict-event-emitter": "^0.5.1", "type-fest": "^4.26.1", "yargs": "^17.7.2" }, "peerDependencies": { "typescript": ">= 4.8.x" }, "optionalPeers": ["typescript"], "bin": { "msw": "cli/index.js" } }, "sha512-rpqW4wIqISJlgDfu3tiqzuWC/d6jofSuMUsBu1rwepzSwX21aQoagsd+fjahJ8sewa6FwlYhu4no+jfGVQm2IA=="], + + "mute-stream": ["mute-stream@2.0.0", "", {}, "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA=="], + "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], @@ -1428,7 +1515,7 @@ "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], - "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + "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-fetch-native": ["node-fetch-native@1.6.6", "", {}, "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ=="], @@ -1476,6 +1563,10 @@ "open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="], + "ora": ["ora@6.3.1", "", { "dependencies": { "chalk": "^5.0.0", "cli-cursor": "^4.0.0", "cli-spinners": "^2.6.1", "is-interactive": "^2.0.0", "is-unicode-supported": "^1.1.0", "log-symbols": "^5.1.0", "stdin-discarder": "^0.1.0", "strip-ansi": "^7.0.1", "wcwidth": "^1.0.1" } }, "sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ=="], + + "outvariant": ["outvariant@1.4.3", "", {}, "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA=="], + "oxlint": ["oxlint@1.5.0", "", { "optionalDependencies": { "@oxlint/darwin-arm64": "1.5.0", "@oxlint/darwin-x64": "1.5.0", "@oxlint/linux-arm64-gnu": "1.5.0", "@oxlint/linux-arm64-musl": "1.5.0", "@oxlint/linux-x64-gnu": "1.5.0", "@oxlint/linux-x64-musl": "1.5.0", "@oxlint/win32-arm64": "1.5.0", "@oxlint/win32-x64": "1.5.0" }, "bin": { "oxlint": "bin/oxlint", "oxc_language_server": "bin/oxc_language_server" } }, "sha512-Oh48XZy6BY2jE9xKwN4DjwpK/l7LOUHfPJsZ/rUKudWN1RXHXBnJkubsgIHlfTwWJGYJU2LAlyXKZcE46mD4OQ=="], "p-event": ["p-event@6.0.1", "", { "dependencies": { "p-timeout": "^6.1.2" } }, "sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w=="], @@ -1492,9 +1583,11 @@ "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + "parse-gitignore": ["parse-gitignore@2.0.0", "", {}, "sha512-RmVuCHWsfu0QPNW+mraxh/xjQVw/lhUCUru8Zni3Ctq3AoMhpDTq0OVdKS6iesd6Kqb7viCV3isAL43dciOSog=="], - "parse-json": ["parse-json@8.3.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "index-to-position": "^1.1.0", "type-fest": "^4.39.1" } }, "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ=="], + "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], @@ -1504,6 +1597,8 @@ "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], + "path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="], + "path-exists": ["path-exists@5.0.0", "", {}, "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ=="], "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], @@ -1512,9 +1607,9 @@ "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - "path-to-regexp": ["path-to-regexp@8.2.0", "", {}, "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ=="], + "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="], - "path-type": ["path-type@6.0.0", "", {}, "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ=="], + "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], @@ -1548,8 +1643,12 @@ "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="], + "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="], + "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=="], + "psl": ["psl@1.15.0", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w=="], + "pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="], "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], @@ -1558,6 +1657,8 @@ "quansync": ["quansync@0.2.10", "", {}, "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A=="], + "querystringify": ["querystringify@2.2.0", "", {}, "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="], + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], "quote-unquote": ["quote-unquote@1.0.0", "", {}, "sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg=="], @@ -1594,7 +1695,7 @@ "read-pkg": ["read-pkg@9.0.1", "", { "dependencies": { "@types/normalize-package-data": "^2.4.3", "normalize-package-data": "^6.0.0", "parse-json": "^8.0.0", "type-fest": "^4.6.0", "unicorn-magic": "^0.1.0" } }, "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA=="], - "readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], + "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], "readdir-glob": ["readdir-glob@1.1.3", "", { "dependencies": { "minimatch": "^5.1.0" } }, "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA=="], @@ -1614,12 +1715,16 @@ "require-package-name": ["require-package-name@2.0.1", "", {}, "sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q=="], + "requires-port": ["requires-port@1.0.0", "", {}, "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="], + "resolve": ["resolve@1.22.10", "", { "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w=="], - "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], + "restore-cursor": ["restore-cursor@4.0.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg=="], + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], "rollup": ["rollup@4.44.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.44.0", "@rollup/rollup-android-arm64": "4.44.0", "@rollup/rollup-darwin-arm64": "4.44.0", "@rollup/rollup-darwin-x64": "4.44.0", "@rollup/rollup-freebsd-arm64": "4.44.0", "@rollup/rollup-freebsd-x64": "4.44.0", "@rollup/rollup-linux-arm-gnueabihf": "4.44.0", "@rollup/rollup-linux-arm-musleabihf": "4.44.0", "@rollup/rollup-linux-arm64-gnu": "4.44.0", "@rollup/rollup-linux-arm64-musl": "4.44.0", "@rollup/rollup-linux-loongarch64-gnu": "4.44.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.44.0", "@rollup/rollup-linux-riscv64-gnu": "4.44.0", "@rollup/rollup-linux-riscv64-musl": "4.44.0", "@rollup/rollup-linux-s390x-gnu": "4.44.0", "@rollup/rollup-linux-x64-gnu": "4.44.0", "@rollup/rollup-linux-x64-musl": "4.44.0", "@rollup/rollup-win32-arm64-msvc": "4.44.0", "@rollup/rollup-win32-ia32-msvc": "4.44.0", "@rollup/rollup-win32-x64-msvc": "4.44.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-qHcdEzLCiktQIfwBq420pn2dP+30uzqYxv9ETm91wdt2R9AFcWfjNAmje4NWlnCIQ5RMTzVf0ZyisOKqHR6RwA=="], @@ -1662,6 +1767,8 @@ "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], + "shadcn": ["shadcn@2.8.0-canary.1", "", { "dependencies": { "@antfu/ni": "^23.2.0", "@babel/core": "^7.22.1", "@babel/parser": "^7.22.6", "@babel/plugin-transform-typescript": "^7.22.5", "@modelcontextprotocol/sdk": "^1.10.2", "commander": "^10.0.0", "cosmiconfig": "^8.1.3", "deepmerge": "^4.3.1", "diff": "^5.1.0", "execa": "^7.0.0", "fast-glob": "^3.3.2", "fs-extra": "^11.1.0", "https-proxy-agent": "^6.2.0", "kleur": "^4.1.5", "msw": "^2.7.1", "node-fetch": "^3.3.0", "ora": "^6.1.2", "postcss": "^8.4.24", "prompts": "^2.4.2", "recast": "^0.23.2", "stringify-object": "^5.0.0", "ts-morph": "^18.0.0", "tsconfig-paths": "^4.2.0", "zod": "^3.20.2", "zod-to-json-schema": "^3.24.5" }, "bin": { "shadcn": "dist/index.js" } }, "sha512-fDetPbVFVdLq1hzKr/ZSDtFxMm4lHIMDyRuyTvdZ13A9uhkp0BYXyKcekOFsZSv83I0coIBbp77EX3of8eP/Pg=="], + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], @@ -1676,10 +1783,12 @@ "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], - "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], "simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="], + "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], + "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], "smob": ["smob@1.5.0", "", {}, "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig=="], @@ -1716,18 +1825,26 @@ "std-env": ["std-env@3.9.0", "", {}, "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw=="], + "stdin-discarder": ["stdin-discarder@0.1.0", "", { "dependencies": { "bl": "^5.0.0" } }, "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ=="], + "streamx": ["streamx@2.22.1", "", { "dependencies": { "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" }, "optionalDependencies": { "bare-events": "^2.2.0" } }, "sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA=="], - "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=="], + "strict-event-emitter": ["strict-event-emitter@0.5.1", "", {}, "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ=="], + + "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], + "stringify-object": ["stringify-object@5.0.0", "", { "dependencies": { "get-own-enumerable-keys": "^1.0.0", "is-obj": "^3.0.0", "is-regexp": "^3.1.0" } }, "sha512-zaJYxz2FtcMb4f+g60KsRNFOpVMUyuJgA51Zi5Z1DOTC3S59+OQiVOzE9GZt0x72uBGWKsQIuBKeF9iusmKFsg=="], + "strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], + "strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="], "strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="], @@ -1804,8 +1921,12 @@ "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], + "ts-morph": ["ts-morph@18.0.0", "", { "dependencies": { "@ts-morph/common": "~0.19.0", "code-block-writer": "^12.0.0" } }, "sha512-Kg5u0mk19PIIe4islUI/HWRvm9bC1lHejK4S0oh1zaZ77TMZAEmQC0sHQYiu2RgCQFZKXz1fMVi/7nOOeirznA=="], + "tsconfck": ["tsconfck@3.1.6", "", { "peerDependencies": { "typescript": "^5.0.0" }, "optionalPeers": ["typescript"], "bin": { "tsconfck": "bin/tsconfck.js" } }, "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w=="], + "tsconfig-paths": ["tsconfig-paths@4.2.0", "", { "dependencies": { "json5": "^2.2.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg=="], + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "tsx": ["tsx@4.20.3", "", { "dependencies": { "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ=="], @@ -1834,6 +1955,8 @@ "unimport": ["unimport@5.0.1", "", { "dependencies": { "acorn": "^8.14.1", "escape-string-regexp": "^5.0.0", "estree-walker": "^3.0.3", "local-pkg": "^1.1.1", "magic-string": "^0.30.17", "mlly": "^1.7.4", "pathe": "^2.0.3", "picomatch": "^4.0.2", "pkg-types": "^2.1.0", "scule": "^1.3.0", "strip-literal": "^3.0.0", "tinyglobby": "^0.2.13", "unplugin": "^2.3.2", "unplugin-utils": "^0.2.4" } }, "sha512-1YWzPj6wYhtwHE+9LxRlyqP4DiRrhGfJxdtH475im8ktyZXO3jHj/3PZ97zDdvkYoovFdi0K4SKl3a7l92v3sQ=="], + "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], + "unixify": ["unixify@1.0.0", "", { "dependencies": { "normalize-path": "^2.1.1" } }, "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg=="], "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], @@ -1856,6 +1979,8 @@ "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + "url-parse": ["url-parse@1.5.10", "", { "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ=="], + "urlpattern-polyfill": ["urlpattern-polyfill@8.0.2", "", {}, "sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ=="], "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], @@ -1882,6 +2007,8 @@ "w3c-xmlserializer": ["w3c-xmlserializer@5.0.0", "", { "dependencies": { "xml-name-validator": "^5.0.0" } }, "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA=="], + "wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="], + "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], "webidl-conversions": ["webidl-conversions@7.0.0", "", {}, "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="], @@ -1902,7 +2029,7 @@ "winston-transport": ["winston-transport@4.9.0", "", { "dependencies": { "logform": "^2.7.0", "readable-stream": "^3.6.2", "triple-beam": "^1.3.0" } }, "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A=="], - "wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + "wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], @@ -1930,13 +2057,15 @@ "yocto-queue": ["yocto-queue@1.2.1", "", {}, "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg=="], + "yoctocolors-cjs": ["yoctocolors-cjs@2.1.2", "", {}, "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA=="], + "youch": ["youch@4.1.0-beta.8", "", { "dependencies": { "@poppinss/colors": "^4.1.4", "@poppinss/dumper": "^0.6.3", "@speed-highlight/core": "^1.2.7", "cookie": "^1.0.2", "youch-core": "^0.3.1" } }, "sha512-rY2A2lSF7zC+l7HH9Mq+83D1dLlsPnEvy8jTouzaptDZM6geqZ3aJe/b7ULCwRURPtWV3vbDjA2DDMdoBol0HQ=="], "youch-core": ["youch-core@0.3.2", "", { "dependencies": { "@poppinss/exception": "^1.2.0", "error-stack-parser-es": "^1.0.5" } }, "sha512-fusrlIMLeRvTFYLUjJ9KzlGC3N+6MOPJ68HNj/yJv2nz7zq8t4HEviLms2gkdRPUS7F5rZ5n+pYx9r88m6IE1g=="], "zip-stream": ["zip-stream@6.0.1", "", { "dependencies": { "archiver-utils": "^5.0.0", "compress-commons": "^6.0.2", "readable-stream": "^4.0.0" } }, "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA=="], - "zod": ["zod@3.25.73", "", {}, "sha512-fuIKbQAWQl22Ba5d1quwEETQYjqnpKVyZIWAhbnnHgnDd3a+z4YgEfkI5SZ2xMELnLAXo/Flk2uXgysZNf0uaA=="], + "zod": ["zod@3.25.74", "", {}, "sha512-J8poo92VuhKjNknViHRAIuuN6li/EwFbAC8OedzI8uxpEPGiXHGQu9wemIAioIpqgfB4SySaJhdk0mH5Y4ICBg=="], "zod-to-json-schema": ["zod-to-json-schema@3.24.6", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg=="], @@ -1976,20 +2105,36 @@ "@babel/template/@babel/types": ["@babel/types@7.27.6", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q=="], + "@bundled-es-modules/tough-cookie/tough-cookie": ["tough-cookie@4.1.4", "", { "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", "universalify": "^0.2.0", "url-parse": "^1.5.3" } }, "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag=="], + "@cloudflare/kv-asset-handler/mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="], + "@inquirer/core/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "@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=="], + + "@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + "@jest/types/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "@mapbox/node-pre-gyp/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + "@mapbox/node-pre-gyp/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + "@modelcontextprotocol/sdk/zod": ["zod@3.25.73", "", {}, "sha512-fuIKbQAWQl22Ba5d1quwEETQYjqnpKVyZIWAhbnnHgnDd3a+z4YgEfkI5SZ2xMELnLAXo/Flk2uXgysZNf0uaA=="], + "@netlify/dev-utils/chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], + "@netlify/functions/is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="], + "@netlify/zip-it-and-ship-it/@babel/parser": ["@babel/parser@7.27.5", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg=="], "@netlify/zip-it-and-ship-it/@babel/types": ["@babel/types@7.27.6", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q=="], "@netlify/zip-it-and-ship-it/@netlify/serverless-functions-api": ["@netlify/serverless-functions-api@2.1.2", "", {}, "sha512-uEFA0LAcBGd3+fgDSLkTTsrgyooKqu8mN/qA+F/COS2A7NFWRcLFnjVKH/xZhxq+oQkrSa+XPS9qj2wgQosiQw=="], + "@netlify/zip-it-and-ship-it/execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="], + "@netlify/zip-it-and-ship-it/resolve": ["resolve@2.0.0-next.5", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA=="], "@netlify/zip-it-and-ship-it/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], @@ -2020,19 +2165,13 @@ "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "@tanstack/react-start-plugin/zod": ["zod@3.25.71", "", {}, "sha512-BsBc/NPk7h8WsUWYWYL+BajcJPY8YhjelaWu2NMLuzgraKAz4Lb4/6K11g9jpuDetjMiqhZ6YaexFLOC0Ogi3Q=="], - - "@tanstack/router-generator/zod": ["zod@3.25.67", "", {}, "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw=="], - - "@tanstack/router-plugin/zod": ["zod@3.25.67", "", {}, "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw=="], - "@tanstack/router-utils/@babel/core": ["@babel/core@7.27.4", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.27.3", "@babel/helpers": "^7.27.4", "@babel/parser": "^7.27.4", "@babel/template": "^7.27.2", "@babel/traverse": "^7.27.4", "@babel/types": "^7.27.3", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g=="], "@tanstack/router-utils/@babel/parser": ["@babel/parser@7.27.5", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg=="], - "@tanstack/start-plugin-core/@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="], + "@tanstack/router-utils/diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], - "@tanstack/start-plugin-core/zod": ["zod@3.25.71", "", {}, "sha512-BsBc/NPk7h8WsUWYWYL+BajcJPY8YhjelaWu2NMLuzgraKAz4Lb4/6K11g9jpuDetjMiqhZ6YaexFLOC0Ogi3Q=="], + "@tanstack/start-plugin-core/@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="], "@testing-library/dom/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], @@ -2040,6 +2179,8 @@ "@testing-library/dom/pretty-format": ["pretty-format@27.5.1", "", { "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" } }, "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ=="], + "@ts-morph/common/minimatch": ["minimatch@7.4.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw=="], + "@types/babel__core/@babel/parser": ["@babel/parser@7.27.5", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg=="], "@types/babel__core/@babel/types": ["@babel/types@7.27.6", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q=="], @@ -2056,6 +2197,8 @@ "@vercel/nft/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + "@vercel/nft/resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], + "@vitejs/plugin-react/@babel/core": ["@babel/core@7.27.4", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.27.3", "@babel/helpers": "^7.27.4", "@babel/parser": "^7.27.4", "@babel/template": "^7.27.2", "@babel/traverse": "^7.27.4", "@babel/types": "^7.27.3", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g=="], "@vue/compiler-core/@babel/parser": ["@babel/parser@7.27.5", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg=="], @@ -2070,10 +2213,16 @@ "@whatwg-node/fetch/urlpattern-polyfill": ["urlpattern-polyfill@10.1.0", "", {}, "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw=="], + "ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="], + "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "archiver/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], + "archiver-utils/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], + "archiver-utils/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], + "babel-dead-code-elimination/@babel/core": ["@babel/core@7.27.4", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.27.3", "@babel/helpers": "^7.27.4", "@babel/parser": "^7.27.4", "@babel/template": "^7.27.2", "@babel/traverse": "^7.27.4", "@babel/types": "^7.27.3", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g=="], "babel-dead-code-elimination/@babel/parser": ["@babel/parser@7.27.5", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg=="], @@ -2086,7 +2235,7 @@ "c12/ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], - "cliui/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "clipboardy/execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="], "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], @@ -2096,16 +2245,22 @@ "compress-commons/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], + "compress-commons/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], + + "crc32-stream/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], + "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], "escodegen/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - "execa/get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="], - - "execa/is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="], + "extract-zip/get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="], "find-up/unicorn-magic": ["unicorn-magic@0.1.0", "", {}, "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ=="], + "foreground-child/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "globby/path-type": ["path-type@6.0.0", "", {}, "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ=="], + "globby/slash": ["slash@5.1.0", "", {}, "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg=="], "hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], @@ -2124,14 +2279,14 @@ "jsondiffpatch/chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="], - "lambda-local/commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], - "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=="], "listhen/h3": ["h3@1.15.3", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.4", "defu": "^6.1.4", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.0", "radix3": "^1.1.2", "ufo": "^1.6.1", "uncrypto": "^0.1.3" } }, "sha512-z6GknHqyX0h9aQaTx22VZDf6QyZn+0Nh+Ym8O/u0SGSkyF5cuTJYKlc8MkzW3Nzf9LE1ivcpmYC3FUGpywhuUQ=="], "listhen/pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], + "log-symbols/chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="], + "lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], "magicast/@babel/parser": ["@babel/parser@7.27.5", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg=="], @@ -2144,8 +2299,6 @@ "mlly/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], - "netlify/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=="], - "nitropack/chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], "nitropack/cookie-es": ["cookie-es@2.0.0", "", {}, "sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg=="], @@ -2160,8 +2313,6 @@ "nitropack/unenv": ["unenv@2.0.0-rc.17", "", { "dependencies": { "defu": "^6.1.4", "exsolve": "^1.0.4", "ohash": "^2.0.11", "pathe": "^2.0.3", "ufo": "^1.6.1" } }, "sha512-B06u0wXkEd+o5gOCMl/ZHl5cfpYbDZKAT+HWTL+Hws6jWu7dCiqBBXXXzMFcFVJb8D4ytAnYmxJA83uwOQRSsg=="], - "node-fetch/whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], - "node-source-walk/@babel/parser": ["@babel/parser@7.27.5", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg=="], "normalize-package-data/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], @@ -2170,12 +2321,18 @@ "open/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], + "ora/chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="], + "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], "precinct/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], "pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], + "prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], + + "read-pkg/parse-json": ["parse-json@8.3.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "index-to-position": "^1.1.0", "type-fest": "^4.39.1" } }, "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ=="], + "read-pkg/unicorn-magic": ["unicorn-magic@0.1.0", "", {}, "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ=="], "readdir-glob/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], @@ -2184,14 +2341,26 @@ "recast/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + "restore-cursor/onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="], + + "router/path-to-regexp": ["path-to-regexp@8.2.0", "", {}, "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ=="], + + "shadcn/https-proxy-agent": ["https-proxy-agent@6.2.1", "", { "dependencies": { "agent-base": "^7.0.2", "debug": "4" } }, "sha512-ONsE3+yfZF2caH5+bJlcddtWqNI3Gvs5A38+ngvljxaBiRXRswym2c7yf8UAeFpRFKjFNHIFEHqR/OLAWJzyiA=="], + + "simple-swizzle/is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="], + "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], + "tar/mkdirp": ["mkdirp@3.0.1", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="], + + "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], + "unenv/mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="], "unenv/pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], @@ -2216,22 +2385,20 @@ "winston/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], - "winston/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], - - "winston-transport/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], - - "wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], - - "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "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=="], - "yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "write-file-atomic/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "xmlbuilder2/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="], "yauzl/buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="], "youch/cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="], + "zip-stream/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], + "@babel/helper-create-class-features-plugin/@babel/traverse/@babel/parser": ["@babel/parser@7.27.5", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg=="], "@babel/helper-create-class-features-plugin/@babel/traverse/@babel/types": ["@babel/types@7.27.6", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q=="], @@ -2250,8 +2417,22 @@ "@babel/helper-skip-transparent-expression-wrappers/@babel/traverse/@babel/parser": ["@babel/parser@7.27.5", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg=="], + "@bundled-es-modules/tough-cookie/tough-cookie/universalify": ["universalify@0.2.0", "", {}, "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg=="], + + "@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.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], + + "@mapbox/node-pre-gyp/node-fetch/whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], + "@netlify/dev-utils/chokidar/readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], + "@netlify/zip-it-and-ship-it/execa/get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="], + + "@netlify/zip-it-and-ship-it/execa/human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="], + + "@netlify/zip-it-and-ship-it/execa/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + "@tanstack/router-utils/@babel/core/@babel/traverse": ["@babel/traverse@7.27.4", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/parser": "^7.27.4", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA=="], "@tanstack/router-utils/@babel/core/@babel/types": ["@babel/types@7.27.6", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q=="], @@ -2276,7 +2457,11 @@ "c12/chokidar/readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], - "cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "clipboardy/execa/get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="], + + "clipboardy/execa/human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="], + + "clipboardy/execa/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], "color/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], @@ -2290,22 +2475,20 @@ "nitropack/h3/cookie-es": ["cookie-es@1.2.2", "", {}, "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg=="], - "node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], - - "node-fetch/whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], - "node-source-walk/@babel/parser/@babel/types": ["@babel/types@7.27.6", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q=="], + "restore-cursor/onetime/mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="], + "unstorage/chokidar/readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], "unwasm/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], "unwasm/pkg-types/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], - "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "xmlbuilder2/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], - "yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "@mapbox/node-pre-gyp/node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], - "yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "@mapbox/node-pre-gyp/node-fetch/whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], } } diff --git a/mcp/index.ts b/mcp/index.ts index 5a5b7fc..03bb6d7 100644 --- a/mcp/index.ts +++ b/mcp/index.ts @@ -3,7 +3,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js" import { z } from "zod"; import { readFileSync, readdirSync } from "fs"; import { join } from "path"; -import { type Tool } from "src/lib/types/tool-editor"; +import { type Tool } from "@/registry/commandly/lib/types/commandly"; const server = new McpServer({ name: "commandly", diff --git a/package.json b/package.json index 15bcebf..e5ec701 100644 --- a/package.json +++ b/package.json @@ -10,11 +10,13 @@ "start": "bun run ./.output/server/index.mjs", "build": "vite build", "lint": "oxlint", + "format": "prettier --write .", "test": "vitest run --config ./vitest.config.ts", "test:watch": "vitest --config ./vitest.config.ts", "test:ui": "vitest --ui", "coverage": "vitest run --coverage", - "build:specification": "bun run ./specification/generate.ts", + "specification:build": "bun run ./scripts/generate-specification.ts", + "registry:build": "shadcn build", "mcp": "bun run mcp/index.ts" }, "dependencies": { @@ -27,13 +29,13 @@ "@radix-ui/react-slot": "^1.2.3", "@tailwindcss/postcss": "^4.1.11", "@tailwindcss/vite": "^4.1.11", - "@tanstack/react-form": "^1.12.4", + "@tanstack/react-form": "^1.13.2", "@tanstack/react-pacer": "^0.8.0", "@tanstack/react-query": "^5.81.5", - "@tanstack/react-router": "^1.124.0", - "@tanstack/react-router-with-query": "^1.124.0", - "@tanstack/react-start": "^1.124.1", - "@tanstack/zod-adapter": "^1.124.0", + "@tanstack/react-router": "^1.125.3", + "@tanstack/react-router-with-query": "^1.125.3", + "@tanstack/react-start": "^1.125.3", + "@tanstack/zod-adapter": "^1.125.3", "ai": "^4.3.16", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", @@ -50,12 +52,12 @@ "tailwindcss-animate": "^1.0.7", "uuid": "^11.1.0", "vite": "^6.3.5", - "zod": "^3.25.73" + "zod": "^3.25.74" }, "devDependencies": { "@tanstack/react-query-devtools": "^5.81.5", - "@tanstack/react-router-devtools": "^1.124.0", - "@tanstack/router-plugin": "^1.124.0", + "@tanstack/react-router-devtools": "^1.125.3", + "@tanstack/router-plugin": "^1.125.3", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^14.6.1", @@ -67,6 +69,7 @@ "@vitest/coverage-v8": "3.2.4", "jsdom": "^26.1.0", "oxlint": "^1.5.0", + "shadcn": "^2.8.0-canary.1", "typescript": "^5.8.3", "vite-tsconfig-paths": "^5.1.4", "vitest": "^3.2.4" diff --git a/public/r/all.json b/public/r/all.json new file mode 100644 index 0000000..216d061 --- /dev/null +++ b/public/r/all.json @@ -0,0 +1,132 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "all", + "type": "registry:block", + "title": "All Components", + "description": "Complete Commandly registry with all components including core functionality and the comprehensive tool editor.", + "dependencies": [ + "react", + "zod", + "lucide-react", + "sonner", + "@tanstack/react-store" + ], + "registryDependencies": [ + "button", + "dialog", + "input", + "label", + "select", + "textarea", + "tabs", + "tooltip", + "scroll-area", + "hover-card" + ], + "files": [ + { + "path": "registry/commandly/generated-command.tsx", + "content": "import { useEffect, useState, useMemo } from \"react\";\nimport { TerminalIcon, CopyIcon, SaveIcon } from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { Button } from \"@/components/ui/button\";\nimport { getCommandPath } from \"@/registry/commandly/lib/utils/commandly\";\nimport {\n Parameter,\n ParameterValue,\n Tool,\n Command\n} from \"@/registry/commandly/lib/types/commandly\";\n\ninterface GeneratedCommandProps {\n tool: Tool;\n selectedCommand?: Command;\n parameterValues: Record;\n onSaveCommand?: (command: string) => void;\n}\n\nexport function GeneratedCommand({\n tool,\n selectedCommand,\n parameterValues,\n onSaveCommand\n}: GeneratedCommandProps) {\n selectedCommand = selectedCommand || tool.commands[0];\n const [generatedCommand, setGeneratedCommand] = useState(\"\");\n\n const globalParameters = useMemo(() => {\n return tool.parameters?.filter((p) => p.isGlobal) || [];\n }, [tool]);\n\n const currentParameters = useMemo(() => {\n return (\n tool?.parameters?.filter((p) => p.commandId === selectedCommand.id) || []\n );\n }, [tool, selectedCommand]);\n\n useEffect(() => {\n generateCommand();\n }, [tool, parameterValues, selectedCommand]);\n\n const generateCommand = () => {\n const commandPath = getCommandPath(selectedCommand, tool);\n let command =\n tool.name == commandPath ? tool.name : `${tool.name} ${commandPath}`;\n\n const parametersWithValues: Array<{\n param: Parameter;\n value: ParameterValue;\n }> = [];\n\n globalParameters.forEach((param) => {\n const value = parameterValues[param.id];\n if (value !== undefined && value !== \"\" && value !== false) {\n parametersWithValues.push({ param, value });\n }\n });\n\n currentParameters.forEach((param) => {\n const value = parameterValues[param.id];\n if (\n value !== undefined &&\n value !== \"\" &&\n value !== false &&\n !param.isGlobal\n ) {\n parametersWithValues.push({ param, value });\n }\n });\n\n const positionalParams = parametersWithValues\n .filter(({ param }) => param.parameterType === \"Argument\")\n .sort((a, b) => (a.param.position || 0) - (b.param.position || 0));\n\n parametersWithValues.forEach(({ param, value }) => {\n if (param.parameterType === \"Flag\") {\n if (value === true) {\n const flag = param.shortFlag || param.longFlag;\n if (flag) command += ` ${flag}`;\n }\n } else if (param.parameterType === \"Option\") {\n const flag = param.shortFlag || param.longFlag;\n if (flag) {\n const separator = param.keyValueSeparator ?? \" \";\n command += ` ${flag}${separator}${value}`;\n }\n } else if (param.parameterType === \"Argument\") {\n command += ` ${value}`;\n }\n });\n\n positionalParams.forEach(({ value }) => {\n command += ` ${value}`;\n });\n\n setGeneratedCommand(command);\n };\n\n const copyCommand = () => {\n navigator.clipboard.writeText(generatedCommand);\n toast(\"Command copied!\");\n };\n\n return (\n
\n {tool.commands.length === 0 ? (\n
\n \n

\n No commands available for this tool.\n

\n
\n ) : generatedCommand ? (\n
\n
\n {generatedCommand}\n
\n
\n \n {onSaveCommand && (\n onSaveCommand(generatedCommand)}\n variant=\"outline\"\n className=\"flex-1\"\n >\n \n Save Command\n \n )}\n
\n
\n ) : (\n
\n \n

\n Configure parameters to generate the command.\n

\n
\n )}\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/generated-command.tsx" + }, + { + "path": "registry/commandly/json-output.tsx", + "content": "import { useEffect, useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { CheckIcon, ChevronsUpDownIcon, CopyIcon } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger\n} from \"@/components/ui/popover\";\nimport {\n Command as UICommand,\n CommandGroup,\n CommandItem,\n CommandList\n} from \"@/components/ui/command\";\nimport {\n Card,\n CardAction,\n CardContent,\n CardHeader,\n CardTitle\n} from \"@/components/ui/card\";\nimport { exportToStructuredJSON } from \"@/registry/commandly/lib/utils/commandly\";\nimport { convertToNestedStructure } from \"@/registry/commandly/lib/utils/commandly-nested\";\nimport { Tool } from \"@/registry/commandly/lib/types/commandly\";\nimport { ScrollArea, ScrollBar } from \"@/components/ui/scroll-area\";\nimport { toast } from \"sonner\";\nimport { useQueryState } from \"nuqs\";\n\nconst jsonOptions = [\n { value: \"nested\", label: \"Nested\" },\n { value: \"flat\", label: \"Flat\" }\n];\n\ninterface JsonTypeComponentProps {\n tool: Tool;\n}\n\nexport function JsonOutput({ tool }: JsonTypeComponentProps) {\n const [open, setOpen] = useState(false);\n const [jsonString, setJsonString] = useState();\n const [jsonType, setJsonType] = useQueryState(\"output\", {\n defaultValue: \"flat\"\n });\n useEffect(() => {\n const config =\n jsonType === \"flat\"\n ? exportToStructuredJSON(tool)\n : convertToNestedStructure(tool);\n setJsonString(JSON.stringify(config, null, 2));\n }, [jsonType, tool]);\n\n return (\n \n \n \n Output type: \n \n \n \n {jsonOptions.find((option) => option.value === jsonType)?.label}\n \n \n \n \n \n \n \n {jsonOptions.map((option) => (\n {\n setJsonType(currentValue);\n setOpen(false);\n }}\n >\n {option.label}\n \n \n ))}\n \n \n \n \n \n \n {\n navigator.clipboard.writeText(jsonString!);\n toast(\"Copied!\");\n }}\n >\n \n \n \n \n [data-radix-scroll-area-viewport]]:max-h-[calc(100vh-320px)] max-w-full\"\n type=\"hover\"\n >\n
\n            {jsonString}\n          
\n \n \n \n
\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/json-output.tsx" + }, + { + "path": "registry/commandly/runtime-preview.tsx", + "content": "import { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\n\nimport { Badge } from \"@/components/ui/badge\";\nimport { Switch } from \"@/components/ui/switch\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue\n} from \"@/components/ui/select\";\nimport { InfoIcon } from \"lucide-react\";\nimport {\n Parameter,\n ParameterValue\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { Command, Tool } from \"@/registry/commandly/lib/types/commandly\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger\n} from \"@/components/ui/tooltip\";\nimport React from \"react\";\n\nconst findDefaultCommand = (tool: Tool): Command | null => {\n const defaultCommand = tool.commands.find((command) => command.isDefault);\n if (defaultCommand) return defaultCommand;\n\n const nameMatchCommand = tool.commands.find(\n (command) => command.name.toLowerCase() === tool.name.toLowerCase()\n );\n if (nameMatchCommand) return nameMatchCommand;\n\n return tool.commands.length > 0 ? tool.commands[0] : null;\n};\n\ninterface RuntimePreviewProps {\n selectedCommand?: Command | null;\n tool: Tool;\n parameterValues: Record;\n updateParameterValue: (parameterId: string, value: ParameterValue) => void;\n}\n\nexport function RuntimePreview({\n selectedCommand: providedCommand,\n tool,\n parameterValues,\n updateParameterValue\n}: RuntimePreviewProps) {\n const selectedCommand = providedCommand ?? findDefaultCommand(tool);\n\n const renderParameterInput = (parameter: Parameter) => {\n const value = parameterValues[parameter.id] || parameter.defaultValue || \"\";\n\n switch (parameter.parameterType) {\n case \"Flag\":\n return (\n
\n \n updateParameterValue(parameter.id, checked)\n }\n />\n \n {parameter.isGlobal && (\n \n global\n \n )}\n
\n );\n\n case \"Option\":\n if (parameter.dataType === \"Enum\") {\n return (\n
\n \n \n updateParameterValue(parameter.id, newValue)\n }\n >\n \n \n \n \n {parameter.enumValues.map((enumValue) => (\n \n {enumValue.displayName || enumValue.value}\n \n ))}\n \n \n
\n );\n } else if (parameter.dataType === \"Boolean\") {\n return (\n
\n \n updateParameterValue(parameter.id, checked.toString())\n }\n />\n \n {parameter.isGlobal && (\n \n global\n \n )}\n
\n );\n } else {\n return (\n
\n
\n \n {parameter.isGlobal && (\n \n global\n \n )}\n
\n \n updateParameterValue(parameter.id, e.target.value)\n }\n placeholder=\"Enter value\"\n />\n
\n );\n }\n\n case \"Argument\":\n return (\n
\n \n \n updateParameterValue(parameter.id, e.target.value)\n }\n placeholder=\"Enter value\"\n />\n
\n );\n\n default:\n return null;\n }\n };\n\n return (\n \n {selectedCommand && tool.commands.length === 0 ? (\n

\n No commands available for this tool.\n

\n ) : (\n
\n {tool.parameters.length > 0 ? (\n tool.parameters\n .filter(\n (param) =>\n param.commandId === selectedCommand?.id || param.isGlobal\n )\n .map(renderParameterInput)\n ) : (\n

\n No parameters available for this command.\n

\n )}\n
\n )}\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/runtime-preview.tsx" + }, + { + "path": "registry/commandly/tool-editor/tool-editor.tsx", + "content": "import { SavedCommand, Tool } from \"@/registry/commandly/lib/types/commandly\";\nimport { CommandTree } from \"./command-tree\";\nimport { ParameterList } from \"./parameter-list\";\nimport { ParameterDetailsDialog } from \"../tool-editor/dialogs/parameter-details-dialog\";\nimport { ExclusionGroupsDialog } from \"../tool-editor/dialogs/exclusion-groups-dialog\";\nimport { PreviewTabs } from \"./preview-tabs\";\nimport { ToolDetailsDialog } from \"../tool-editor/dialogs/tool-details-dialog\";\nimport { Button } from \"@/components/ui/button\";\nimport { SaveIcon, Edit2Icon, LayersIcon } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { toolBuilderActions, toolBuilderStore } from \"./tool-editor.store\";\nimport { toast } from \"sonner\";\nimport {\n getSavedCommandsFromStorage,\n removeSavedCommandFromStorage\n} from \"@/registry/commandly/lib/utils/commandly\";\nimport { SavedCommandsDialog } from \"./dialogs/saved-commands-dialog\";\n\ninterface ToolEditorProps {\n tool: Tool;\n onSave?: (tool: Tool) => void;\n}\n\nexport default function ToolEditor({\n tool: toolToEdit,\n onSave\n}: ToolEditorProps) {\n const tool = useStore(toolBuilderStore, (state) => state.tool);\n\n useEffect(() => {\n toolBuilderActions.initializeTool(toolToEdit);\n }, [toolToEdit]);\n\n const [savedCommands, setSavedCommands] = useState([]);\n\n const handleDeleteCommand = (commandId: string) => {\n const toolId = tool.id || tool.name;\n removeSavedCommandFromStorage(`saved-${toolId}`, commandId);\n setSavedCommands(savedCommands.filter((cmd) => cmd.id !== commandId));\n };\n\n return (\n
\n
\n
\n

Commands

\n
\n \n
\n\n {/* Main Content */}\n
\n
\n
\n
\n \n {tool.displayName\n ? `${tool.displayName} (${tool.name})`\n : `${tool.name}`}\n \n \n toolBuilderActions.setDialogOpen(\"editTool\", true)\n }\n >\n \n \n
\n
\n {onSave && (\n {\n onSave(toolBuilderStore.state.tool);\n toast(\"Tool saved successfully!\");\n }}\n >\n \n Save\n \n )}\n {\n const toolId = tool.id || tool.name;\n const commands = getSavedCommandsFromStorage(toolId);\n setSavedCommands(commands);\n toolBuilderActions.setDialogOpen(\"savedCommands\", true);\n }}\n >\n \n Saved Commands\n \n \n toolBuilderActions.setDialogOpen(\"exclusionGroups\", true)\n }\n >\n \n Exclusion Groups\n \n
\n
\n
\n\n
\n
\n \n \n
\n
\n \n
\n
\n
\n\n \n \n \n \n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/tool-editor.tsx" + }, + { + "path": "registry/commandly/tool-editor/tool-editor.store.ts", + "content": "import { Store } from \"@tanstack/react-store\";\nimport {\n Tool,\n Command,\n Parameter,\n ExclusionGroup,\n ParameterValue,\n SavedCommand\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { toast } from \"sonner\";\nimport {\n addSavedCommandToStorage,\n createNewCommand,\n defaultTool,\n getAllSubcommands,\n getSavedCommandsFromStorage,\n removeSavedCommandFromStorage\n} from \"@/registry/commandly/lib/utils/commandly\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport interface ToolBuilderState {\n tool: Tool;\n selectedCommand: Command;\n selectedParameter: Parameter | null;\n editingCommand: Command | null;\n parameterValues: Record;\n dialogs: {\n parameterDetails: boolean;\n editTool: boolean;\n savedCommands: boolean;\n exclusionGroups: boolean;\n };\n}\n\nexport const toolBuilderStore = new Store({\n tool: defaultTool(),\n selectedCommand: {} as Command,\n selectedParameter: null,\n editingCommand: null,\n parameterValues: {},\n dialogs: {\n parameterDetails: false,\n editTool: false,\n savedCommands: false,\n exclusionGroups: false\n }\n});\n\nexport const toolBuilderSelectors = {\n getParametersForCommand: (\n state: ToolBuilderState,\n commandId: string\n ): Parameter[] => {\n return state.tool.parameters.filter((param: Parameter) => {\n if (param.isGlobal) return false;\n return param.commandId === commandId;\n });\n },\n\n getGlobalParameters: (state: ToolBuilderState): Parameter[] => {\n return state.tool.parameters.filter((param: Parameter) => param.isGlobal);\n },\n\n getExclusionGroupsForCommand: (\n state: ToolBuilderState,\n commandId: string\n ): ExclusionGroup[] => {\n return state.tool.exclusionGroups.filter((group: ExclusionGroup) => {\n return group.commandId === commandId;\n });\n }\n};\n\nexport const toolBuilderActions = {\n initializeTool(tool: Tool) {\n toolBuilderStore.setState((state) => ({\n ...state,\n tool,\n selectedCommand: tool.commands[0]\n }));\n },\n\n updateTool(updates: Partial) {\n toolBuilderStore.setState((state) => ({\n ...state,\n tool: {\n ...state.tool,\n ...updates\n }\n }));\n },\n\n addSubcommand(parentId?: string) {\n const newCommand = createNewCommand(parentId);\n toolBuilderStore.setState((state) => ({\n ...state,\n tool: {\n ...state.tool,\n commands: [...state.tool.commands, newCommand]\n }\n }));\n\n toast(\"Command Added\", {\n description: \"New command has been created successfully.\"\n });\n },\n\n deleteCommand(commandId: string) {\n toolBuilderStore.setState((state) => {\n const subcommands = getAllSubcommands(commandId, state.tool.commands);\n const commandsToDelete = [commandId, ...subcommands.map((c) => c.id)];\n\n const newState = {\n ...state,\n tool: {\n ...state.tool,\n commands: state.tool.commands.filter(\n (cmd) => !commandsToDelete.includes(cmd.id)\n ),\n parameters: state.tool.parameters.filter(\n (param) => !commandsToDelete.includes(param.commandId || \"\")\n ),\n exclusionGroups: state.tool.exclusionGroups.filter(\n (group) => !commandsToDelete.includes(group.commandId || \"\")\n )\n }\n };\n\n if (state.selectedCommand?.id === commandId) {\n newState.selectedCommand = newState.tool.commands[0];\n }\n\n return newState;\n });\n\n toast(\"Command Deleted\", {\n description: \"Command and all its subcommands have been deleted.\"\n });\n },\n\n updateCommand(commandId: string, updates: Partial) {\n toolBuilderStore.setState((state) => ({\n ...state,\n tool: {\n ...state.tool,\n commands: state.tool.commands.map((cmd) => {\n let updatedCmd: Command;\n if (cmd.id === commandId) {\n updatedCmd = { ...cmd, ...updates };\n } else {\n if (!updates.isDefault) updatedCmd = cmd;\n else {\n updatedCmd = { ...cmd, isDefault: false };\n }\n }\n return updatedCmd;\n })\n }\n }));\n },\n\n removeParameter(parameterId: string) {\n toolBuilderStore.setState((state) => {\n const newState = {\n ...state,\n tool: {\n ...state.tool,\n parameters: state.tool.parameters.filter(\n (param) => param.id !== parameterId\n ),\n exclusionGroups: state.tool.exclusionGroups.map((group) => ({\n ...group,\n parameterIds: group.parameterIds.filter((id) => id !== parameterId)\n }))\n }\n };\n\n if (state.selectedParameter?.id === parameterId) {\n newState.selectedParameter = null;\n }\n\n return newState;\n });\n\n toast(\"Parameter Deleted\", {\n description: \"Parameter has been removed successfully.\"\n });\n },\n addSavedCommand(command: string) {\n const toolId =\n toolBuilderStore.state.tool.id || toolBuilderStore.state.tool.name;\n const existingCommands = getSavedCommandsFromStorage(toolId);\n if (existingCommands.some((cmd) => cmd.command === command)) {\n toast.error(\"Command already exists\", {\n description: \"This command has already been saved.\"\n });\n return;\n }\n const newSavedCommand: SavedCommand = {\n id: uuidv7(),\n command\n };\n\n addSavedCommandToStorage(`saved-${toolId}`, newSavedCommand);\n\n toast(\"Command Saved\", {\n description: \"Command has been saved successfully.\"\n });\n },\n\n removeSavedCommand(commandId: string) {\n toolBuilderStore.setState((state) => {\n const toolId = state.tool.id || state.tool.name;\n removeSavedCommandFromStorage(`saved-${toolId}`, commandId);\n return { ...state };\n });\n },\n\n addExclusionGroup(group: Omit) {\n toolBuilderStore.setState((state) => {\n const newGroup = {\n ...group,\n id: uuidv7(),\n commandId: state.selectedCommand?.id\n };\n\n return {\n ...state,\n tool: {\n ...state.tool,\n exclusionGroups: [...state.tool.exclusionGroups, newGroup]\n }\n };\n });\n\n toast(\"Group Added\", {\n description: \"New exclusion group has been created successfully.\"\n });\n },\n\n updateExclusionGroup(updatedGroup: ExclusionGroup) {\n toolBuilderStore.setState((state) => ({\n ...state,\n tool: {\n ...state.tool,\n exclusionGroups: state.tool.exclusionGroups.map((group) =>\n group.id === updatedGroup.id ? updatedGroup : group\n )\n }\n }));\n\n toast(\"Group Updated\", {\n description: \"Exclusion group has been updated successfully.\"\n });\n },\n\n removeExclusionGroup(groupId: string) {\n toolBuilderStore.setState((state) => ({\n ...state,\n tool: {\n ...state.tool,\n exclusionGroups: state.tool.exclusionGroups.filter(\n (group) => group.id !== groupId\n )\n }\n }));\n\n toast(\"Group Removed\", {\n description: \"Exclusion group has been removed successfully.\"\n });\n },\n\n setDialogOpen(\n dialog:\n | \"editTool\"\n | \"savedCommands\"\n | \"exclusionGroups\"\n | \"parameterDetails\",\n open: boolean\n ) {\n toolBuilderStore.setState((state) => ({\n ...state,\n dialogs: {\n ...state.dialogs,\n [dialog]: open\n }\n }));\n },\n\n setSelectedCommand(command: Command) {\n toolBuilderStore.setState((state) => ({\n ...state,\n selectedCommand: command\n }));\n },\n\n setSelectedParameter(parameter: Parameter | null) {\n toolBuilderStore.setState((state) => ({\n ...state,\n selectedParameter: parameter\n }));\n },\n\n setEditingCommand(command: Command | null) {\n toolBuilderStore.setState((state) => ({\n ...state,\n editingCommand: command\n }));\n },\n\n upsertParameter(parameter: Parameter) {\n toolBuilderStore.setState((state) => {\n const exists = state.tool.parameters.some((p) => p.id === parameter.id);\n let newParameters: Parameter[];\n if (exists) {\n newParameters = state.tool.parameters.map((param) => {\n if (param.id === parameter.id) {\n const updatedParam = {\n ...param,\n ...parameter,\n dependencies: parameter.dependencies || [],\n validations: parameter.validations || [],\n enumValues: parameter.enumValues || []\n };\n if (parameter.isGlobal && parameter.isGlobal !== param.isGlobal) {\n updatedParam.commandId = undefined;\n }\n if (parameter.isGlobal === false && param.isGlobal) {\n updatedParam.commandId = state.selectedCommand?.id;\n }\n return updatedParam;\n }\n return param;\n });\n toast(\"Parameter Updated\", {\n description: `Parameter has been updated successfully.`\n });\n } else {\n newParameters = [...state.tool.parameters, parameter];\n toast(\"Parameter Added\", {\n description: `New ${parameter.isGlobal ? \"global \" : \"\"}parameter has been created successfully.`\n });\n }\n return {\n ...state,\n tool: {\n ...state.tool,\n parameters: newParameters\n }\n };\n });\n }\n};\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/tool-editor.store.tsx" + }, + { + "path": "registry/commandly/tool-editor/command-tree.tsx", + "content": "import { useState, useEffect, ReactNode } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { ScrollArea } from \"@/components/ui/scroll-area\";\nimport { Command } from \"@/registry/commandly/lib/types/commandly\";\nimport {\n ChevronDownIcon,\n ChevronRightIcon,\n Edit2Icon,\n PlusIcon,\n Trash2Icon\n} from \"lucide-react\";\nimport { CommandDialog } from \"../tool-editor/dialogs/command-dialog\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { toolBuilderStore, toolBuilderActions } from \"./tool-editor.store\";\n\nexport function CommandTree() {\n const tool = useStore(toolBuilderStore, (state) => state.tool);\n const selectedCommand = useStore(\n toolBuilderStore,\n (state) => state.selectedCommand\n );\n const editingCommand = useStore(\n toolBuilderStore,\n (state) => state.editingCommand\n );\n\n const [expandedCommands, setExpandedCommands] = useState>(\n new Set([tool.commands[0]?.id])\n );\n const [isDialogOpen, setIsDialogOpen] = useState(false);\n const [lastAddedCommand, setLastAddedCommand] = useState<{\n id: string;\n parentId?: string;\n } | null>(null);\n\n const handleEditCommand = (command: Command | null) => {\n toolBuilderActions.setEditingCommand(command);\n };\n\n const toggleExpanded = (commandId: string) => {\n setExpandedCommands((prev) => {\n const newSet = new Set(prev);\n if (newSet.has(commandId)) {\n newSet.delete(commandId);\n } else {\n newSet.add(commandId);\n }\n return newSet;\n });\n };\n\n // Patch toolBuilderActions.addSubcommand to select and expand parent after add\n const handleAddSubcommand = (parentId?: string) => {\n const prevIds = new Set(tool.commands.map((cmd) => cmd.id));\n toolBuilderActions.addSubcommand(parentId);\n setTimeout(() => {\n const newCmd = toolBuilderStore.state.tool.commands.find(\n (cmd) => !prevIds.has(cmd.id)\n );\n if (newCmd) {\n setLastAddedCommand({ id: newCmd.id, parentId });\n }\n }, 0);\n };\n\n useEffect(() => {\n if (!lastAddedCommand) return;\n const { id, parentId } = lastAddedCommand;\n const newCmd = tool.commands.find((cmd) => cmd.id === id);\n if (newCmd) {\n toolBuilderActions.setSelectedCommand(newCmd);\n if (parentId) {\n setExpandedCommands((prev) => {\n const newSet = new Set(prev);\n newSet.add(parentId);\n return newSet;\n });\n }\n setLastAddedCommand(null);\n }\n }, [tool.commands, lastAddedCommand]);\n\n const renderCommandNode = (command: Command, level = 0): ReactNode => {\n const isExpanded = expandedCommands.has(command.id);\n const subcommands = tool.commands.filter(\n (cmd) => cmd.parentCommandId === command.id\n );\n const hasSubcommands = subcommands.length > 0;\n const isSelected = selectedCommand?.id === command.id;\n const isRoot = command.name == tool.name;\n\n return (\n
\n toolBuilderActions.setSelectedCommand(command)}\n >\n {hasSubcommands ? (\n {\n e.stopPropagation();\n toggleExpanded(command.id);\n }}\n >\n {isExpanded ? (\n \n ) : (\n \n )}\n \n ) : (\n
\n )}\n\n {command.name}\n {command.isDefault && (\n \n default\n \n )}\n {\n e.stopPropagation();\n handleEditCommand(command);\n setIsDialogOpen(true);\n }}\n >\n \n \n {\n e.stopPropagation();\n handleAddSubcommand(command.id);\n }}\n >\n \n \n {!isRoot && (\n {\n e.stopPropagation();\n toolBuilderActions.deleteCommand(command.id);\n }}\n >\n \n \n )}\n
\n\n {isExpanded && hasSubcommands && (\n <>\n
\n {subcommands.map((subcmd) =>\n renderCommandNode(subcmd, level + 1)\n )}\n
\n \n )}\n
\n );\n };\n\n const rootCommands = tool.commands.filter((cmd) => !cmd.parentCommandId);\n\n return (\n <>\n \n
\n {rootCommands.map((command) => renderCommandNode(command))}\n
\n
\n \n
\n
\n {editingCommand && (\n {\n setIsDialogOpen(open);\n handleEditCommand(null);\n }}\n />\n )}\n \n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/command-tree.tsx" + }, + { + "path": "registry/commandly/tool-editor/parameter-list.tsx", + "content": "import { Button } from \"@/components/ui/button\";\nimport { Badge } from \"@/components/ui/badge\";\nimport {\n ExclusionGroup,\n ParameterType\n} from \"@/registry/commandly/lib/types/commandly\";\nimport {\n CheckCircleIcon,\n FileTextIcon,\n FlagIcon,\n GlobeIcon,\n HashIcon,\n LayersIcon,\n PlusIcon,\n Trash2Icon,\n XCircleIcon\n} from \"lucide-react\";\nimport { useStore } from \"@tanstack/react-store\";\nimport {\n toolBuilderStore,\n toolBuilderActions,\n toolBuilderSelectors\n} from \"./tool-editor.store\";\nimport {\n createNewParameter,\n validateDefaultValue\n} from \"@/registry/commandly/lib/utils/commandly\";\n\ninterface ParameterListProps {\n title: string;\n isGlobal?: boolean;\n}\n\nexport function ParameterList({ title, isGlobal = false }: ParameterListProps) {\n const selectedCommand = useStore(\n toolBuilderStore,\n (state) => state.selectedCommand\n );\n const globalParameters = useStore(toolBuilderStore, (state) =>\n toolBuilderSelectors.getGlobalParameters(state)\n );\n const commandParameters = useStore(toolBuilderStore, (state) =>\n selectedCommand?.id\n ? toolBuilderSelectors.getParametersForCommand(state, selectedCommand.id)\n : []\n );\n const exclusionGroups = useStore(toolBuilderStore, (state) =>\n selectedCommand?.id\n ? toolBuilderSelectors.getExclusionGroupsForCommand(\n state,\n selectedCommand.id\n )\n : []\n );\n\n const parameters = isGlobal ? globalParameters : commandParameters;\n\n const getParameterIcon = (parameterType: ParameterType) => {\n switch (parameterType) {\n case \"Flag\":\n return ;\n case \"Option\":\n return ;\n case \"Argument\":\n return ;\n default:\n return ;\n }\n };\n\n const getParameterExclusionGroups = (\n parameterId: string\n ): ExclusionGroup[] => {\n return exclusionGroups.filter((group) =>\n group.parameterIds.includes(parameterId)\n );\n };\n\n return (\n
\n
\n

\n {isGlobal && }\n {title} ({parameters.length})\n

\n \n toolBuilderActions.setSelectedParameter(\n createNewParameter(isGlobal, selectedCommand?.id)\n )\n }\n size=\"sm\"\n >\n \n \n
\n\n
\n {parameters.map((parameter) => {\n const validation = validateDefaultValue(parameter);\n const paramGroups = getParameterExclusionGroups(parameter.id);\n\n return (\n toolBuilderActions.setSelectedParameter(parameter)}\n >\n
\n
\n {getParameterIcon(parameter.parameterType)}\n \n {parameter.name}\n {(parameter.longFlag || parameter.shortFlag) && (\n \n (\n {[parameter.longFlag, parameter.shortFlag]\n .filter(Boolean)\n .join(\", \")}\n )\n \n )}\n \n
\n {\n e.stopPropagation();\n toolBuilderActions.removeParameter(parameter.id);\n }}\n >\n \n \n
\n
\n {parameter.isRequired && (\n \n required\n \n )}\n \n {parameter.parameterType}\n \n \n {parameter.dataType}\n \n {isGlobal && (\n \n global\n \n )}\n {paramGroups.map((group) => (\n \n \n {group.name}\n \n ))}\n {!validation.isValid && (\n \n )}\n {validation.isValid && parameter.defaultValue && (\n \n )}\n
\n
\n );\n })}\n
\n \n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/parameter-list.tsx" + }, + { + "path": "registry/commandly/tool-editor/preview-tabs.tsx", + "content": "import { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\nimport { HelpMenu } from \"./help-menu\";\nimport { useQueryState } from \"nuqs\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { toolBuilderStore, toolBuilderActions } from \"./tool-editor.store\";\nimport { RuntimePreview } from \"../runtime-preview\";\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle\n} from \"@/components/ui/card\";\nimport { ParameterValue } from \"@/registry/commandly/lib/types/commandly\";\nimport { TerminalIcon } from \"lucide-react\";\nimport { JsonOutput } from \"../json-output\";\nimport { GeneratedCommand } from \"../generated-command\";\n\nexport function PreviewTabs() {\n const [currentTab, setActiveTab] = useQueryState(\"tab\", {\n defaultValue: \"ui\"\n });\n\n const selectedCommand = useStore(\n toolBuilderStore,\n (state) => state.selectedCommand\n );\n const tool = useStore(toolBuilderStore, (state) => state.tool);\n const parameterValues = useStore(\n toolBuilderStore,\n (state) => state.parameterValues\n );\n const updateParameterValue = (parameterId: string, value: ParameterValue) => {\n toolBuilderStore.setState((state) => ({\n ...state,\n parameterValues: {\n ...state.parameterValues,\n [parameterId]: value as ParameterValue\n }\n }));\n };\n\n const handleSaveCommand = (command: string) => {\n toolBuilderActions.addSavedCommand(command);\n };\n\n return (\n
\n \n \n Json\n Preview\n Help\n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n Generated Command\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/preview-tabs.tsx" + }, + { + "path": "registry/commandly/tool-editor/help-menu.tsx", + "content": "import { ScrollArea, ScrollBar } from \"@/components/ui/scroll-area\";\nimport { Command } from \"@/registry/commandly/lib/types/commandly\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { toolBuilderStore } from \"./tool-editor.store\";\n\nexport function HelpMenu() {\n const tool = useStore(toolBuilderStore, (state) => state.tool);\n\n const generateToolPreview = (): string => {\n const rootCommands = tool.commands.filter((cmd) => !cmd.parentCommandId);\n const globalParams = tool.parameters.filter((p) => p.isGlobal);\n\n let preview = `${tool.displayName}${tool.version ? ` v${tool.version}` : \"\"}\\n`;\n preview += `${tool.description}\\n\\n`;\n\n preview += `USAGE:\\n`;\n preview += ` ${tool.name} [GLOBAL OPTIONS] [OPTIONS] [ARGUMENTS]\\n\\n`;\n\n if (globalParams.length > 0) {\n preview += \"GLOBAL OPTIONS:\\n\";\n\n const globalFlags = globalParams.filter(\n (p) => p.parameterType === \"Flag\"\n );\n const globalOptions = globalParams.filter(\n (p) => p.parameterType === \"Option\"\n );\n\n globalFlags.forEach((flag) => {\n const shortFlag = flag.shortFlag ? `${flag.shortFlag}` : \"\";\n const longFlag = flag.longFlag ? `${flag.longFlag}` : \"\";\n const flagStr =\n shortFlag && longFlag\n ? `${shortFlag}, ${longFlag}`\n : shortFlag || longFlag;\n const required = flag.isRequired ? \"Required: \" : \"\";\n preview += ` ${flagStr.padEnd(20)} ${required}${flag.description}\\n`;\n });\n\n globalOptions.forEach((option) => {\n const shortFlag = option.shortFlag ? `${option.shortFlag}` : \"\";\n const longFlag = option.longFlag ? `${option.longFlag}` : \"\";\n const flagStr =\n shortFlag && longFlag\n ? `${shortFlag}, ${longFlag}`\n : shortFlag || longFlag;\n const valueType = option.dataType.includes(\"array\")\n ? ``\n : `<${option.dataType}>`;\n const required = option.isRequired ? \"Required: \" : \"\";\n preview += ` ${flagStr.padEnd(20)} ${required}${option.description}\\n`;\n preview += ` ${\" \".repeat(20)} Value: ${valueType}\\n`;\n });\n\n preview += \"\\n\";\n }\n\n preview += \"COMMANDS:\\n\";\n const printCommand = (command: Command, level = 0) => {\n const indent = \" \".repeat(level + 1);\n preview += `${indent}${command.name.padEnd(20 - level * 2)} ${\n command.description\n }\\n`;\n\n const commandParams = tool.parameters.filter(\n (p) => !p.isGlobal && p.commandId === command.name\n );\n\n const flags = commandParams.filter((p) => p.parameterType === \"Flag\");\n const options = commandParams.filter((p) => p.parameterType === \"Option\");\n const arguments_ = commandParams.filter(\n (p) => p.parameterType === \"Argument\"\n );\n\n if (flags.length > 0) {\n preview += `${indent} Flags:\\n`;\n flags.forEach((flag) => {\n const shortFlag = flag.shortFlag ? `${flag.shortFlag}` : \"\";\n const longFlag = flag.longFlag ? `${flag.longFlag}` : \"\";\n const flagStr =\n shortFlag && longFlag\n ? `${shortFlag}, ${longFlag}`\n : shortFlag || longFlag;\n const required = flag.isRequired ? \"Required: \" : \"\";\n preview += `${indent} ${flagStr.padEnd(18)} ${required}${\n flag.description\n }\\n`;\n });\n }\n\n if (options.length > 0) {\n preview += `${indent} Options:\\n`;\n options.forEach((option) => {\n const shortFlag = option.shortFlag ? `${option.shortFlag}` : \"\";\n const longFlag = option.longFlag ? `${option.longFlag}` : \"\";\n const flagStr =\n shortFlag && longFlag\n ? `${shortFlag}, ${longFlag}`\n : shortFlag || longFlag;\n const valueType = option.dataType.includes(\"array\")\n ? ``\n : `<${option.dataType}>`;\n const required = option.isRequired ? \"Required: \" : \"\";\n preview += `${indent} ${flagStr.padEnd(18)} ${required}${\n option.description\n }\\n`;\n preview += `${indent} ${\" \".repeat(18)} Value: ${valueType}\\n`;\n });\n }\n\n if (arguments_.length > 0) {\n preview += `${indent} Arguments:\\n`;\n arguments_.forEach((arg) => {\n const required = arg.isRequired ? \"Required: \" : \"\";\n preview += `${indent} ${arg.name.padEnd(18)} ${required}${\n arg.description\n }\\n`;\n if (arg.dataType === \"Enum\") {\n preview += `${indent} ${\" \".repeat(18)} Values: ${arg.enumValues\n .map((e) => e.value)\n .join(\", \")}\\n`;\n }\n });\n }\n\n const subcommands = tool.commands.filter(\n (cmd) => cmd.parentCommandId === command.id\n );\n if (subcommands.length > 0) {\n preview += `${indent} Subcommands:\\n`;\n subcommands.forEach((subcmd) => {\n printCommand(subcmd, level + 2);\n });\n }\n };\n\n rootCommands.forEach((cmd) => printCommand(cmd));\n\n return preview;\n };\n\n return (\n \n
\n        {generateToolPreview()}\n      
\n \n \n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/help-menu.tsx" + }, + { + "path": "registry/commandly/tool-editor/dialogs/parameter-details-dialog.tsx", + "content": "import { useEffect, useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Switch } from \"@/components/ui/switch\";\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter,\n DialogDescription\n} from \"@/components/ui/dialog\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue\n} from \"@/components/ui/select\";\nimport { Separator } from \"@/components/ui/separator\";\nimport {\n FileTextIcon,\n FlagIcon,\n HashIcon,\n LinkIcon,\n PlusIcon,\n ShieldIcon,\n Trash2Icon\n} from \"lucide-react\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { validateDefaultValue } from \"@/registry/commandly/lib/utils/commandly\";\nimport { v7 as uuidv7 } from \"uuid\";\nimport { TagsComponent } from \"@/registry/commandly/ui/tags\";\nimport { toolBuilderActions, toolBuilderStore } from \"../tool-editor.store\";\nimport {\n Parameter,\n ParameterDataType,\n ParameterDependency,\n ParameterDependencyType,\n ParameterEnumValue,\n ParameterType,\n ParameterValidation,\n ParameterValidationType\n} from \"@/registry/commandly/lib/types/commandly\";\n\nexport function ParameterDetailsDialog() {\n const selectedParameter = useStore(\n toolBuilderStore,\n (state) => state.selectedParameter\n );\n\n const commandId = useStore(\n toolBuilderStore,\n (state) => state.selectedCommand?.id\n );\n\n const availableParameters = useStore(toolBuilderStore, (state) => {\n if (!selectedParameter) return [];\n return state.tool.parameters.filter((p) => {\n if (p.id === selectedParameter.id) return false;\n if (selectedParameter.isGlobal) return p.isGlobal;\n return p.isGlobal || p.commandId === commandId;\n });\n });\n\n const [parameter, setParameter] = useState(selectedParameter!);\n const [hasChanges, setHasChanges] = useState(false);\n\n useEffect(() => {\n setParameter(selectedParameter!);\n setHasChanges(false);\n }, [selectedParameter]);\n\n const getParameterIcon = (parameterType: string) => {\n switch (parameterType) {\n case \"Flag\":\n return ;\n case \"Option\":\n return ;\n case \"Argument\":\n return ;\n default:\n return ;\n }\n };\n\n const isOpen = !!selectedParameter;\n\n const handleClose = () => {\n toolBuilderActions.setSelectedParameter(null);\n setHasChanges(false);\n };\n\n const handleSave = () => {\n if (parameter) {\n toolBuilderActions.upsertParameter(parameter);\n setHasChanges(false);\n handleClose();\n }\n };\n\n const updateParameter = (updates: Partial) => {\n setParameter((prev) => ({ ...prev, ...updates }));\n setHasChanges(true);\n };\n\n const addDependency = () => {\n if (!parameter || availableParameters.length === 0) return;\n\n const newDependency: ParameterDependency = {\n id: uuidv7(),\n parameterId: parameter.id,\n dependsOnParameterId: availableParameters[0].id,\n dependencyType: \"requires\"\n };\n\n updateParameter({\n dependencies: [...(parameter.dependencies || []), newDependency]\n });\n };\n\n const updateDependency = (\n dependencyId: string,\n updates: Partial\n ) => {\n if (!parameter) return;\n const updatedDependencies = parameter.dependencies?.map((dep) =>\n dep.id === dependencyId ? { ...dep, ...updates } : dep\n );\n updateParameter({ dependencies: updatedDependencies });\n };\n\n const removeDependency = (dependencyId: string) => {\n if (!parameter) return;\n const updatedDependencies = parameter.dependencies?.filter(\n (dep) => dep.id !== dependencyId\n );\n updateParameter({ dependencies: updatedDependencies });\n };\n\n const addValidation = () => {\n if (!parameter) return;\n const newValidation: ParameterValidation = {\n id: uuidv7(),\n parameterId: parameter.id,\n validationType: \"min_length\",\n validationValue: \"1\",\n errorMessage: \"Value is too short\"\n };\n\n updateParameter({\n validations: [...(parameter.validations || []), newValidation]\n });\n };\n\n const addEnumValue = () => {\n if (!parameter) return;\n const newEnumValue: ParameterEnumValue = {\n id: uuidv7(),\n parameterId: parameter.id,\n value: \"new-value\",\n displayName: \"New Value\",\n description: \"\",\n isDefault: false,\n sortOrder: 0\n };\n\n updateParameter({\n enumValues: [...parameter.enumValues, newEnumValue]\n });\n };\n\n if (!parameter) return null;\n\n const validation = validateDefaultValue(parameter);\n\n const canSaveChanges = () => {\n if (!hasChanges) return false;\n if (parameter.defaultValue && !validation.isValid) {\n return false;\n }\n\n if (!parameter.name.trim() || !parameter.longFlag.trim()) {\n return false;\n }\n if (\n availableParameters.some(\n (p) =>\n p.name.trim() === parameter.name.trim() ||\n parameter.longFlag == p.longFlag ||\n (parameter.shortFlag && parameter.shortFlag == p.shortFlag)\n )\n ) {\n return false;\n }\n\n return true;\n };\n\n return (\n \n \n \n \n {getParameterIcon(parameter.parameterType)}\n {parameter.name}\n {parameter.isGlobal && (\n \n global\n \n )}\n \n \n \n\n
\n {/* Basic Info */}\n
\n
\n \n updateParameter({ name: e.target.value })}\n />\n
\n
\n\n
\n
\n \n \n updateParameter({ parameterType: value })\n }\n >\n \n \n \n \n Flag\n Option\n Argument\n \n \n
\n
\n \n \n updateParameter({ dataType: value })\n }\n >\n \n \n \n \n String\n Number\n Boolean\n Enum\n \n \n
\n
\n \n updateParameter({ isGlobal: checked })\n }\n />\n \n
\n
\n\n {(parameter.parameterType === \"Flag\" ||\n parameter.parameterType === \"Option\") && (\n
\n
\n \n \n updateParameter({ shortFlag: e.target.value })\n }\n placeholder=\"-v\"\n />\n
\n
\n \n \n updateParameter({ longFlag: e.target.value })\n }\n placeholder=\"--verbose\"\n />\n
\n
\n )}\n\n {parameter.parameterType === \"Option\" && (\n
\n \n \n updateParameter({ keyValueSeparator: e.target.value })\n }\n placeholder=\"Default is single space\"\n />\n
\n )}\n\n {parameter.parameterType === \"Argument\" && (\n
\n \n \n updateParameter({\n position: Number.parseInt(e.target.value) || 0\n })\n }\n placeholder=\"0\"\n />\n
\n )}\n\n
\n \n updateParameter({ description: e.target.value })}\n rows={2}\n />\n
\n\n
\n
\n \n \n updateParameter({ defaultValue: e.target.value })\n }\n className={!validation.isValid ? \"border-destructive\" : \"\"}\n />\n {!validation.isValid && (\n

\n {validation.error}\n

\n )}\n
\n
\n
\n \n updateParameter({ isRequired: checked })\n }\n />\n \n
\n
\n \n updateParameter({ isRepeatable: checked })\n }\n />\n \n
\n
\n
\n\n {\n if (!onOpen) {\n updateParameter({ metadata: { tags } });\n }\n }}\n />\n\n \n\n {/* Dependencies Section */}\n
\n
\n \n \n Dependencies\n \n \n \n Add\n \n
\n
\n {parameter.dependencies &&\n parameter.dependencies.map((dependency) => (\n \n \n updateDependency(dependency.id, {\n dependencyType: value\n })\n }\n >\n \n \n \n \n Requires\n \n Conflicts\n \n \n \n \n updateDependency(dependency.id, {\n dependsOnParameterId: value\n })\n }\n >\n \n \n \n \n {availableParameters.map((param) => (\n \n {param.name}\n {param.isGlobal && \" (global)\"}\n \n ))}\n \n \n removeDependency(dependency.id)}\n >\n \n \n
\n ))}\n
\n
\n\n \n\n {/* Validations Section */}\n
\n
\n \n \n
\n
\n {parameter.validations &&\n parameter.validations.map((validation) => (\n \n {\n const updatedValidations = parameter.validations?.map(\n (v) =>\n v.id === validation.id\n ? { ...v, validationType: value }\n : v\n );\n updateParameter({\n validations: updatedValidations\n });\n }}\n >\n \n \n \n \n Min Length\n Max Length\n Min Value\n Max Value\n Regex\n \n \n {\n const updatedValidations = parameter.validations?.map(\n (v) =>\n v.id === validation.id\n ? { ...v, validationValue: e.target.value }\n : v\n );\n updateParameter({\n validations: updatedValidations\n });\n }}\n placeholder=\"Value\"\n className=\"flex-1\"\n />\n {\n const updatedValidations =\n parameter.validations?.filter(\n (v) => v.id !== validation.id\n );\n updateParameter({\n validations: updatedValidations\n });\n }}\n >\n \n \n
\n ))}\n
\n \n\n {/* Enum Values Section */}\n {parameter.dataType === \"Enum\" && (\n <>\n \n
\n
\n \n Enum Values\n \n \n
\n
\n {parameter.enumValues.map((enumValue) => (\n \n {\n const updatedEnumValues = parameter.enumValues.map(\n (ev) =>\n ev.id === enumValue.id\n ? { ...ev, value: e.target.value }\n : ev\n );\n updateParameter({\n enumValues: updatedEnumValues\n });\n }}\n placeholder=\"value\"\n className=\"flex-1\"\n />\n {\n const updatedEnumValues = parameter.enumValues.map(\n (ev) =>\n ev.id === enumValue.id\n ? { ...ev, displayName: e.target.value }\n : ev\n );\n updateParameter({\n enumValues: updatedEnumValues\n });\n }}\n placeholder=\"Display Name\"\n className=\"flex-1\"\n />\n {\n const updatedEnumValues = parameter.enumValues.map(\n (ev) =>\n ev.id === enumValue.id\n ? { ...ev, isDefault: checked }\n : ev\n );\n updateParameter({\n enumValues: updatedEnumValues\n });\n }}\n />\n {\n const updatedEnumValues = parameter.enumValues.filter(\n (ev) => ev.id !== enumValue.id\n );\n updateParameter({\n enumValues: updatedEnumValues\n });\n }}\n >\n \n \n
\n ))}\n
\n \n \n )}\n \n\n \n \n \n \n
\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/dialogs/parameter-details-dialog.tsx" + }, + { + "path": "registry/commandly/tool-editor/dialogs/exclusion-groups-dialog.tsx", + "content": "import { Button } from \"@/components/ui/button\";\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle\n} from \"@/components/ui/dialog\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue\n} from \"@/components/ui/select\";\nimport { ExclusionGroup } from \"@/registry/commandly/lib/types/commandly\";\nimport { PlusIcon, TrashIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useStore } from \"@tanstack/react-store\";\nimport {\n toolBuilderStore,\n toolBuilderActions,\n toolBuilderSelectors\n} from \"../tool-editor.store\";\n\nexport function ExclusionGroupsDialog() {\n const selectedCommand = useStore(\n toolBuilderStore,\n (state) => state.selectedCommand\n );\n const open = useStore(\n toolBuilderStore,\n (state) => state.dialogs.exclusionGroups\n );\n\n const exclusionGroups = useStore(toolBuilderStore, (state) => {\n const commandId = state.selectedCommand?.id;\n return commandId\n ? toolBuilderSelectors.getExclusionGroupsForCommand(state, commandId)\n : [];\n });\n const parameters = useStore(toolBuilderStore, (state) => {\n const commandId = state.selectedCommand?.id;\n return commandId\n ? toolBuilderSelectors.getParametersForCommand(state, commandId)\n : [];\n });\n\n const [editingGroup, setEditingGroup] = useState<\n Partial | undefined\n >();\n\n const handleAddGroup = () => {\n setEditingGroup({\n name: \"\",\n exclusionType: \"mutual_exclusive\",\n parameterIds: [],\n commandId: selectedCommand?.id\n });\n };\n\n const handleSaveGroup = () => {\n if (!editingGroup?.name || !editingGroup.exclusionType) return;\n\n if (editingGroup.id) {\n toolBuilderActions.updateExclusionGroup(editingGroup as ExclusionGroup);\n } else {\n toolBuilderActions.addExclusionGroup(\n editingGroup as Omit\n );\n }\n setEditingGroup(undefined);\n };\n\n return (\n \n toolBuilderActions.setDialogOpen(\"exclusionGroups\", open)\n }\n >\n \n \n Exclusion Groups\n \n\n
\n {exclusionGroups.map((group) => (\n \n
\n

{group.name}

\n
\n {group.parameterIds.map((id) => {\n const param = parameters.find((p) => p.id === id);\n return (\n param && (\n \n {param.name}\n \n )\n );\n })}\n
\n
\n
\n setEditingGroup(group)}\n >\n Edit\n \n \n toolBuilderActions.removeExclusionGroup(group.id!)\n }\n >\n \n \n
\n
\n ))}\n\n {!editingGroup && (\n \n )}\n\n {editingGroup && (\n
\n
\n \n \n setEditingGroup({ ...editingGroup, name: e.target.value })\n }\n placeholder=\"Group name\"\n />\n
\n\n
\n \n \n setEditingGroup({\n ...editingGroup,\n exclusionType: value as ExclusionGroup[\"exclusionType\"]\n })\n }\n >\n \n \n \n \n \n Mutually Exclusive\n \n \n Required One Of\n \n \n \n
\n\n
\n \n \n setEditingGroup({\n ...editingGroup,\n parameterIds: [\n ...(editingGroup.parameterIds || []),\n value\n ]\n })\n }\n >\n \n \n \n \n {parameters\n .filter((p) => !editingGroup.parameterIds?.includes(p.id))\n .map((param) => (\n \n {param.name}\n \n ))}\n \n \n\n
\n {editingGroup.parameterIds?.map((id) => {\n const param = parameters.find((p) => p.id === id);\n return (\n param && (\n \n {param.name}\n \n setEditingGroup({\n ...editingGroup,\n parameterIds: editingGroup.parameterIds?.filter(\n (pid) => pid !== id\n )\n })\n }\n >\n \n \n \n )\n );\n })}\n
\n
\n\n
\n setEditingGroup(undefined)}\n >\n Cancel\n \n \n
\n
\n )}\n \n
\n \n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/dialogs/exclusion-groups-dialog.tsx" + }, + { + "path": "registry/commandly/tool-editor/dialogs/tool-details-dialog.tsx", + "content": "import { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter\n} from \"@/components/ui/dialog\";\nimport { SettingsIcon } from \"lucide-react\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { MultiSelect } from \"@/components/ui/multi-select\";\nimport {\n SupportedToolInputType,\n SupportedToolOutputType\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { TagsComponent } from \"@/registry/commandly/ui/tags\";\nimport { toolBuilderActions, toolBuilderStore } from \"../tool-editor.store\";\n\nconst supportedInputOptions = [\n { value: \"StandardInput\", label: \"Standard Input\" },\n { value: \"Parameter\", label: \"Parameter\" }\n];\n\nconst supportedOutputOptions = [\n { value: \"StandardOutput\", label: \"Standard Output\" },\n { value: \"File\", label: \"File\" }\n];\n\nexport function ToolDetailsDialog() {\n const tool = useStore(toolBuilderStore, (state) => state.tool);\n\n const isOpen = useStore(toolBuilderStore, (state) => state.dialogs.editTool);\n return (\n \n toolBuilderActions.setDialogOpen(\"editTool\", open)\n }\n >\n \n \n \n \n Edit Tool Settings\n \n \n
\n
\n
\n \n {\n const newName = e.target.value;\n const prevName = tool.name;\n toolBuilderActions.updateTool({\n name: newName,\n commands: tool.commands.map((cmd) =>\n cmd.name === prevName ? { ...cmd, name: newName } : cmd\n )\n });\n }}\n />\n
\n
\n \n \n toolBuilderActions.updateTool({ displayName: e.target.value })\n }\n />\n
\n
\n
\n
\n \n \n toolBuilderActions.updateTool({ version: e.target.value })\n }\n />\n
\n
\n \n \n toolBuilderActions.updateTool({ category: e.target.value })\n }\n />\n
\n
\n
\n
\n \n \n toolBuilderActions.updateTool({\n supportedInput: value.map(\n (v) => v as SupportedToolInputType\n )\n })\n }\n defaultValue={tool.supportedInput}\n placeholder=\"Select input types\"\n variant=\"default\"\n maxCount={0}\n />\n
\n
\n \n \n toolBuilderActions.updateTool({\n supportedOutput: value.map(\n (v) => v as SupportedToolOutputType\n )\n })\n }\n defaultValue={tool.supportedOutput}\n placeholder=\"Select output types\"\n variant=\"default\"\n maxCount={0}\n />\n
\n
\n {\n if (!onOpen) {\n toolBuilderActions.updateTool({ tags });\n }\n }}\n />\n
\n \n \n toolBuilderActions.updateTool({ description: e.target.value })\n }\n rows={3}\n />\n
\n
\n \n toolBuilderActions.setDialogOpen(\"editTool\", false)}\n >\n Close\n \n \n
\n \n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/dialogs/tool-details-dialog.tsx" + }, + { + "path": "registry/commandly/tool-editor/dialogs/command-dialog.tsx", + "content": "import { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { Switch } from \"@/components/ui/switch\";\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter,\n DialogDescription\n} from \"@/components/ui/dialog\";\nimport { Command } from \"@/registry/commandly/lib/types/commandly\";\nimport { TerminalIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { toolBuilderActions, toolBuilderStore } from \"../tool-editor.store\";\n\ninterface CommandDialogProps {\n isOpen: boolean;\n onOpenChange: (open: boolean) => void;\n}\n\nexport function CommandDialog({ isOpen, onOpenChange }: CommandDialogProps) {\n const command = useStore(toolBuilderStore, (state) => state.editingCommand);\n const toolName = useStore(toolBuilderStore, (state) => state.tool.name);\n const [editCommand, setCommand] = useState(command!);\n\n return (\n \n \n \n \n \n Edit Command Settings\n \n \n Dialog for editing command details\n \n \n
\n
\n
\n \n \n setCommand((prev) => ({\n ...prev,\n name: e.target.value\n }))\n }\n />\n
\n
\n
\n
\n \n \n setCommand((prev) => ({\n ...prev,\n sortOrder: Number.parseInt(e.target.value) || 0\n }))\n }\n />\n
\n
\n {\n setCommand((prev) => ({\n ...prev,\n isDefault: checked\n }));\n }}\n />\n \n
\n
\n
\n \n \n setCommand((prev) => ({ ...prev, description: e.target.value }))\n }\n rows={3}\n />\n
\n
\n \n {\n toolBuilderActions.updateCommand(editCommand.id, editCommand);\n onOpenChange(false);\n }}\n >\n Save & Close\n \n \n
\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/dialogs/command-dialog.tsx" + }, + { + "path": "registry/commandly/tool-editor/dialogs/saved-commands-dialog.tsx", + "content": "import { Button } from \"@/components/ui/button\";\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter\n} from \"@/components/ui/dialog\";\nimport { SaveIcon, CopyIcon, Trash2Icon } from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { SavedCommand } from \"@/registry/commandly/lib/types/commandly\";\nimport { toolBuilderActions, toolBuilderStore } from \"../tool-editor.store\";\nimport { useStore } from \"@tanstack/react-store\";\n\ninterface SavedCommandsDialogProps {\n savedCommands: SavedCommand[];\n onDeleteCommand: (commandId: string) => void;\n}\n\nexport function SavedCommandsDialog({\n savedCommands,\n onDeleteCommand\n}: SavedCommandsDialogProps) {\n const copyCommand = (command: string) => {\n navigator.clipboard.writeText(command);\n toast(\"Command copied!\");\n };\n\n const deleteCommand = (commandId: string) => {\n onDeleteCommand(commandId);\n toast(\"Command Removed\", {\n description: \"Saved command has been removed successfully.\"\n });\n };\n\n const open = useStore(\n toolBuilderStore,\n (state) => state.dialogs.savedCommands\n );\n\n return (\n \n toolBuilderActions.setDialogOpen(\"savedCommands\", false)\n }\n >\n \n \n \n \n Saved Commands\n \n \n\n {savedCommands.length === 0 ? (\n
\n \n

\n No saved commands yet. Generate and save commands to see them\n here.\n

\n
\n ) : (\n
\n {savedCommands &&\n savedCommands.length > 0 &&\n savedCommands.map((savedCommand) => (\n \n
\n copyCommand(savedCommand.command)}\n >\n \n \n deleteCommand(savedCommand.id)}\n >\n \n \n
\n
\n                    {savedCommand.command}\n                  
\n
\n ))}\n \n )}\n\n \n \n toolBuilderActions.setDialogOpen(\"savedCommands\", false)\n }\n >\n Close\n \n \n
\n \n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/dialogs/saved-commands-dialog.tsx" + }, + { + "path": "registry/commandly/lib/types/commandly.ts", + "content": "import { z } from \"zod/v4\";\n\nexport const CommandSchema = z.object({\n id: z.uuidv7(),\n parentCommandId: z.uuidv7().optional(),\n name: z.string(),\n description: z.string(),\n isDefault: z.boolean(),\n sortOrder: z.number()\n});\nexport type Command = z.infer;\n\nexport const ParameterEnumValueSchema = z.object({\n id: z.uuidv7(),\n parameterId: z.uuidv7(),\n value: z.string(),\n displayName: z.string(),\n description: z.string(),\n isDefault: z.boolean(),\n sortOrder: z.number()\n});\nexport type ParameterEnumValue = z.infer;\n\nexport const ParameterValidationTypeSchema = z.enum([\n \"min_length\",\n \"max_length\",\n \"min_value\",\n \"max_value\",\n \"regex\"\n]);\nexport type ParameterValidationType = z.infer<\n typeof ParameterValidationTypeSchema\n>;\n\nexport const ParameterValidationSchema = z.object({\n id: z.string(),\n parameterId: z.string(),\n validationType: ParameterValidationTypeSchema,\n validationValue: z.string(),\n errorMessage: z.string()\n});\nexport type ParameterValidation = z.infer;\nexport const ParameterDependencyTypeSchema = z.enum([\n \"requires\",\n \"conflicts_with\"\n]);\nexport type ParameterDependencyType = z.infer<\n typeof ParameterDependencyTypeSchema\n>;\nexport const ParameterDependencySchema = z.object({\n id: z.string(),\n parameterId: z.string(),\n dependsOnParameterId: z.string(),\n dependencyType: ParameterDependencyTypeSchema,\n conditionValue: z.string().optional()\n});\n\nexport type ParameterValue = string | number | boolean;\n\nexport type ParameterDependency = z.infer;\n\nexport const ParameterMetadataSchema = z.object({\n tags: z.array(z.string()).optional()\n});\nexport type ParameterMetadata = z.infer;\nexport const ParameterTypeSchema = z.enum([\"Flag\", \"Option\", \"Argument\"]);\nexport type ParameterType = z.infer;\n\nexport const ParameterDataTypeSchema = z.enum([\n \"String\",\n \"Number\",\n \"Boolean\",\n \"Enum\"\n]);\nexport type ParameterDataType = z.infer;\n\nexport const ParameterSchema = z.object({\n id: z.string(),\n name: z.string(),\n commandId: z.uuidv7().optional(),\n description: z.string(),\n metadata: ParameterMetadataSchema.optional(),\n parameterType: ParameterTypeSchema,\n dataType: ParameterDataTypeSchema,\n isRequired: z.boolean(),\n isRepeatable: z.boolean(),\n isGlobal: z.boolean(),\n defaultValue: z.string().optional(),\n shortFlag: z.string().optional(),\n longFlag: z.string(),\n position: z.number().optional(),\n sortOrder: z.number().optional(),\n arraySeparator: z.string().optional(),\n keyValueSeparator: z.string().optional(),\n enumValues: z.array(ParameterEnumValueSchema),\n validations: z.array(ParameterValidationSchema).optional(),\n dependencies: z.array(ParameterDependencySchema).optional()\n});\nexport type Parameter = z.infer;\n\nexport const ExclusionTypeSchema = z.enum([\n \"mutual_exclusive\",\n \"required_one_of\"\n]);\nexport type ExclusionType = z.infer;\n\nexport const ExclusionGroupSchema = z.object({\n id: z.string().optional(),\n commandId: z.string().optional(),\n name: z.string(),\n exclusionType: ExclusionTypeSchema,\n parameterIds: z.array(z.string())\n});\nexport type ExclusionGroup = z.infer;\n\nexport const SavedCommandSchema = z.object({\n id: z.string(),\n command: z.string()\n});\nexport type SavedCommand = z.infer;\n\nexport const SupportedToolInputTypeSchema = z.enum([\n \"StandardInput\",\n \"Parameter\"\n]);\nexport type SupportedToolInputType = z.infer<\n typeof SupportedToolInputTypeSchema\n>;\n\nexport const SupportedToolOutputTypeSchema = z.enum([\n \"StandardOutput\",\n \"File\",\n \"Directory\"\n]);\nexport type SupportedToolOutputType = z.infer<\n typeof SupportedToolOutputTypeSchema\n>;\n\nexport const ToolSchema = z.object({\n id: z.string().optional(),\n name: z.string(),\n displayName: z.string(),\n description: z.string().optional(),\n version: z.string().optional(),\n category: z.string().optional(),\n tags: z.array(z.string()).optional(),\n url: z.url().optional(),\n commands: z.array(CommandSchema),\n parameters: z.array(ParameterSchema),\n exclusionGroups: z.array(ExclusionGroupSchema),\n supportedInput: z.array(SupportedToolInputTypeSchema),\n supportedOutput: z.array(SupportedToolOutputTypeSchema)\n});\nexport type Tool = z.infer;\n\nexport const AIParseRequestSchema = z.object({\n helpText: z.string(),\n toolName: z.string().optional()\n});\nexport type AIParseRequest = z.infer;\n\nexport const AIParseResponseSchema = z.object({\n success: z.boolean(),\n data: ToolSchema.optional(),\n error: z.string().optional()\n});\nexport type AIParseResponse = z.infer;\n\nexport const newToolSchema = z.object({\n displayName: z.string(),\n name: z.string(),\n version: z.string().optional(),\n description: z.string().optional(),\n url: z.url().optional()\n});\nexport type ManualNewTool = z.infer;\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/types/commandly-nested.ts", + "content": "import { ParameterValidation, ParameterDependencyType, ParameterType, ParameterDataType, ParameterMetadata, ExclusionType, SupportedToolInputType, SupportedToolOutputType } from \"../../types\";\n\nexport interface NestedCommand {\n name: string;\n description: string;\n isDefault: boolean;\n sortOrder: number;\n parameters: NestedParameter[];\n subcommands: NestedCommand[];\n}\n\nexport interface NestedParameterEnumValue {\n value: string;\n displayName: string;\n description: string;\n isDefault: boolean;\n sortOrder: number;\n}\n\nexport type NestedParameterValidation = Omit<\n ParameterValidation,\n \"id\" | \"parameterId\"\n>;\n\nexport interface NestedParameterDependency {\n dependsOnParameter: string;\n dependencyType: ParameterDependencyType;\n conditionValue?: string;\n}\n\nexport interface NestedParameter {\n name: string;\n description: string;\n parameterType: ParameterType;\n dataType: ParameterDataType;\n metadata?: ParameterMetadata;\n isRequired: boolean;\n isRepeatable: boolean;\n isGlobal: boolean;\n defaultValue?: string;\n shortFlag?: string;\n longFlag: string;\n position?: number;\n sortOrder?: number;\n arraySeparator?: string;\n keyValueSeparator?: string;\n enumValues: NestedParameterEnumValue[];\n validations: NestedParameterValidation[];\n dependencies: NestedParameterDependency[];\n}\n\nexport interface NestedExclusionGroup {\n name: string;\n exclusionType: ExclusionType;\n parameters: string[];\n}\n\nexport interface NestedTool {\n name: string;\n displayName: string;\n description?: string;\n version?: string;\n url?: string;\n globalParameters: NestedParameter[];\n commands: NestedCommand[];\n exclusionGroups: NestedExclusionGroup[];\n supportedInput: SupportedToolInputType[];\n supportedOutput: SupportedToolOutputType[];\n}\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly.ts", + "content": "import type {\n Command,\n Parameter,\n SavedCommand,\n Tool\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport const buildCommandHierarchy = (commands: Command[]): Command[] => {\n return commands.sort((a, b) => a.sortOrder - b.sortOrder);\n};\n\nexport const getCommandPath = (command: Command, tool: Tool): string => {\n const findCommandPath = (\n targetId: string,\n commands: Command[],\n path: string[] = []\n ): string[] | null => {\n for (const cmd of commands) {\n if (cmd.name === targetId) {\n return [...path, cmd.name];\n }\n\n const childCommands = commands.filter(\n (c) => c.parentCommandId === cmd.id\n );\n if (childCommands.length > 0) {\n const subPath = findCommandPath(targetId, childCommands, [\n ...path,\n cmd.name\n ]);\n if (subPath) {\n return subPath;\n }\n }\n }\n return null;\n };\n\n const rootCommands = tool.commands.filter((c) => !c.parentCommandId);\n const path = findCommandPath(command.name, rootCommands);\n\n if (!path) return command.name;\n\n if (command.name === tool.name && command.isDefault) {\n return tool.name;\n }\n\n const rootCommand = tool.commands.find((c) => c.name === tool.name);\n if (rootCommand?.isDefault && path[0] === tool.name) {\n path[0] = tool.name;\n }\n\n return path.join(\" \");\n};\n\nexport const getAllSubcommands = (\n commandId: string,\n commands: Command[]\n): Command[] => {\n const result: Command[] = [];\n\n const findSubcommands = (parentId: string) => {\n commands.forEach((cmd) => {\n if (cmd.parentCommandId === parentId) {\n result.push(cmd);\n findSubcommands(cmd.id);\n }\n });\n };\n\n findSubcommands(commandId);\n return result;\n};\n\nexport const exportToStructuredJSON = (tool: Tool) => {\n const flattenCommand = (cmd: Command) => {\n return { ...cmd };\n };\n\n return {\n name: tool.name,\n displayName: tool.displayName,\n description: tool.description,\n version: tool.version,\n commands: tool.commands.map(flattenCommand),\n parameters: tool.parameters,\n exclusionGroups: tool.exclusionGroups,\n supportedInput: tool.supportedInput,\n supportedOutput: tool.supportedOutput\n };\n};\n\nexport const flattenImportedData = (importedData: any): Tool => {\n const {\n name,\n displayName,\n parameters = [],\n commands = [],\n exclusionGroups = [],\n supportedInput = [],\n supportedOutput = []\n } = importedData;\n\n const allParameters: Parameter[] = [...parameters];\n\n const flattenCommandParameters = (\n command: any,\n parentId?: string\n ): Command[] => {\n const { parameters = [], subcommands = [], ...commandData } = command;\n\n parameters.forEach((param: any) => {\n allParameters.push({\n ...param,\n commandId: command.id,\n isGlobal: !command.name\n });\n });\n\n const flatCommand: Command = {\n ...commandData,\n parentCommandId: parentId\n };\n\n const flatCommands = [flatCommand];\n\n subcommands.forEach((subcmd: any) => {\n flatCommands.push(...flattenCommandParameters(subcmd, command.name));\n });\n\n return flatCommands;\n };\n\n const flatCommands: Command[] = [];\n commands.forEach((cmd: any) => {\n flatCommands.push(...flattenCommandParameters(cmd));\n });\n\n return {\n name: name,\n displayName: displayName || name,\n commands: flatCommands,\n parameters: allParameters,\n exclusionGroups,\n supportedInput: supportedInput,\n supportedOutput: supportedOutput\n };\n};\n\nexport const defaultTool = (toolName?: string, displayName?: string): Tool => {\n return {\n name: toolName || \"my-tool\",\n displayName: displayName || \"My Tool\",\n description: undefined,\n version: \"\",\n commands: [\n {\n id: uuidv7(),\n name: toolName || \"my-tool\",\n description: \"Main command\",\n isDefault: true,\n sortOrder: 0\n }\n ],\n parameters: [\n {\n id: \"--help\",\n name: \"Help\",\n description: \"Displays help menu of tool\",\n parameterType: \"Flag\",\n dataType: \"String\",\n isRequired: false,\n isGlobal: true,\n shortFlag: \"-h\",\n longFlag: \"--help\",\n isRepeatable: false,\n enumValues: [],\n validations: [],\n dependencies: []\n }\n ],\n exclusionGroups: [],\n supportedInput: [\"StandardInput\"],\n supportedOutput: [\"StandardOutput\"]\n };\n};\n\nexport const validateDefaultValue = (\n parameter: Parameter\n): { isValid: boolean; error?: string } => {\n const { defaultValue, validations, dataType } = parameter;\n\n if (!defaultValue || !validations) return { isValid: true };\n\n switch (dataType) {\n case \"Number\":\n if (!/^-?\\d+$/.test(defaultValue)) {\n return { isValid: false, error: \"Default value must be an integer\" };\n }\n break;\n case \"Boolean\":\n if (![\"true\", \"false\", \"1\", \"0\"].includes(defaultValue.toLowerCase())) {\n return {\n isValid: false,\n error: \"Default value must be true/false or 1/0\"\n };\n }\n break;\n }\n\n for (const validation of validations) {\n const value = dataType === \"Number\" ? Number(defaultValue) : defaultValue;\n\n switch (validation.validationType) {\n case \"min_length\":\n if (\n typeof value === \"string\" &&\n value.length < Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too short\"\n };\n }\n break;\n case \"max_length\":\n if (\n typeof value === \"string\" &&\n value.length > Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too long\"\n };\n }\n break;\n case \"min_value\":\n if (\n typeof value === \"number\" &&\n value < Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too small\"\n };\n }\n break;\n case \"max_value\":\n if (\n typeof value === \"number\" &&\n value > Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too large\"\n };\n }\n break;\n case \"regex\":\n if (\n typeof value === \"string\" &&\n !new RegExp(validation.validationValue).test(value)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value doesn't match pattern\"\n };\n }\n break;\n }\n }\n\n return { isValid: true };\n};\n\nexport const createNewCommand = (parentId?: string): Command => {\n return {\n id: uuidv7(),\n parentCommandId: parentId,\n name: randomCommandName(),\n description: \"\",\n isDefault: false,\n sortOrder: 1\n };\n};\n\nexport const createNewParameter = (\n isGlobal: boolean,\n commandId?: string\n): Parameter => {\n return {\n id: uuidv7(),\n name: \"\",\n commandId: isGlobal ? undefined : commandId,\n description: \"\",\n parameterType: \"Option\",\n dataType: \"String\",\n isRequired: false,\n isRepeatable: false,\n isGlobal,\n defaultValue: \"\",\n shortFlag: \"\",\n longFlag: \"\",\n sortOrder: 0,\n arraySeparator: \",\",\n keyValueSeparator: \" \",\n enumValues: [],\n validations: [],\n dependencies: []\n };\n};\n\nexport const getSavedCommandsFromStorage = (toolId: string): SavedCommand[] => {\n try {\n const saved = localStorage.getItem(`saved-${toolId}`);\n return saved ? JSON.parse(saved) : [];\n } catch {\n return [];\n }\n};\n\nexport const saveSavedCommandsToStorage = (\n toolId: string,\n commands: SavedCommand[]\n): void => {\n try {\n localStorage.setItem(toolId, JSON.stringify(commands));\n } catch (error) {\n console.error(\"Failed to save commands to localStorage:\", error);\n }\n};\n\nexport const addSavedCommandToStorage = (\n toolId: string,\n command: SavedCommand\n): void => {\n const existingCommands = getSavedCommandsFromStorage(toolId);\n const updatedCommands = [...existingCommands, command];\n saveSavedCommandsToStorage(toolId, updatedCommands);\n};\n\nexport const removeSavedCommandFromStorage = (\n toolId: string,\n commandId: string\n): void => {\n const existingCommands = getSavedCommandsFromStorage(toolId);\n const updatedCommands = existingCommands.filter(\n (cmd) => cmd.id !== commandId\n );\n saveSavedCommandsToStorage(toolId, updatedCommands);\n};\n\nexport const clearSavedCommandsFromStorage = (toolId: string): void => {\n localStorage.removeItem(toolId);\n};\n\nexport const randomCommandName = () => {\n const characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n let result = \"\";\n const charactersLength = characters.length;\n for (let i = 0; i < 7; i++) {\n result += characters.charAt(Math.floor(Math.random() * charactersLength));\n }\n return result;\n};\n\nexport function generateHashCode(s: string): string {\n let h = 0;\n for (let i = 0; i < s.length; i++)\n h = (Math.imul(31, h) + s.charCodeAt(i)) | 0;\n\n return h.toString();\n}\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly-nested.ts", + "content": "import type {\n Tool,\n Command,\n Parameter\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { NestedCommand, NestedExclusionGroup, NestedParameter, NestedTool } from \"../types/commandly-nested\";\n\n\nexport const convertToNestedStructure = (tool: Tool): NestedTool => {\n const globalParameters = tool.parameters.filter((p) => p.isGlobal);\n\n const convertParameter = (param: Parameter): NestedParameter => {\n const { id, commandId, ...rest } = param;\n return {\n ...rest,\n validations:\n param.validations?.map((v) => {\n return {\n validationType: v.validationType,\n validationValue: v.validationValue,\n errorMessage: v.errorMessage\n };\n }) || [],\n metadata: param.metadata,\n dataType: param.dataType,\n dependencies:\n param.dependencies?.map((dep) => {\n const dependsOnParam = tool.parameters.find(\n (p) => p.id === dep.dependsOnParameterId\n );\n return {\n dependsOnParameter: dependsOnParam?.longFlag || \"\",\n dependencyType: dep.dependencyType,\n conditionValue: dep.conditionValue\n };\n }) || []\n };\n };\n\n const buildNestedCommands = (\n commands: Command[],\n parentId?: string\n ): NestedCommand[] => {\n return commands\n .filter((cmd) => cmd.parentCommandId === parentId)\n .map((cmd) => {\n const commandParameters = tool.parameters.filter(\n (p) => p.commandId === cmd.id && !p.isGlobal\n );\n return {\n name: cmd.name,\n description: cmd.description,\n isDefault: cmd.isDefault,\n sortOrder: cmd.sortOrder,\n parameters: commandParameters.map(convertParameter),\n subcommands: buildNestedCommands(commands, cmd.id)\n };\n });\n };\n\n const nestedExclusionGroups: NestedExclusionGroup[] =\n tool.exclusionGroups.map((group) => {\n return {\n name: group.name,\n exclusionType: group.exclusionType,\n parameters: group.parameterIds.map((pid) => {\n const param = tool.parameters.find((p) => p.id === pid);\n return param?.longFlag || \"\";\n })\n };\n });\n\n return {\n name: tool.name,\n url: tool.url,\n displayName: tool.displayName,\n description: tool.description,\n version: tool.version,\n supportedInput: tool.supportedInput,\n supportedOutput: tool.supportedOutput,\n globalParameters: globalParameters.map(convertParameter),\n commands: buildNestedCommands(tool.commands),\n exclusionGroups: nestedExclusionGroups\n };\n};\n", + "type": "registry:lib" + } + ] +} diff --git a/public/r/commandly-types.json b/public/r/commandly-types.json new file mode 100644 index 0000000..ba13027 --- /dev/null +++ b/public/r/commandly-types.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "commandly-types", + "type": "registry:lib", + "title": "Commandly Types", + "description": "TypeScript type definitions for the Commandly tool editor system including schemas for tools, commands, and parameters.", + "dependencies": ["zod"], + "files": [ + { + "path": "registry/commandly/lib/types/commandly.ts", + "content": "import { z } from \"zod/v4\";\n\nexport const CommandSchema = z.object({\n id: z.uuidv7(),\n parentCommandId: z.uuidv7().optional(),\n name: z.string(),\n description: z.string(),\n isDefault: z.boolean(),\n sortOrder: z.number()\n});\nexport type Command = z.infer;\n\nexport const ParameterEnumValueSchema = z.object({\n id: z.uuidv7(),\n parameterId: z.uuidv7(),\n value: z.string(),\n displayName: z.string(),\n description: z.string(),\n isDefault: z.boolean(),\n sortOrder: z.number()\n});\nexport type ParameterEnumValue = z.infer;\n\nexport const ParameterValidationTypeSchema = z.enum([\n \"min_length\",\n \"max_length\",\n \"min_value\",\n \"max_value\",\n \"regex\"\n]);\nexport type ParameterValidationType = z.infer<\n typeof ParameterValidationTypeSchema\n>;\n\nexport const ParameterValidationSchema = z.object({\n id: z.string(),\n parameterId: z.string(),\n validationType: ParameterValidationTypeSchema,\n validationValue: z.string(),\n errorMessage: z.string()\n});\nexport type ParameterValidation = z.infer;\nexport const ParameterDependencyTypeSchema = z.enum([\n \"requires\",\n \"conflicts_with\"\n]);\nexport type ParameterDependencyType = z.infer<\n typeof ParameterDependencyTypeSchema\n>;\nexport const ParameterDependencySchema = z.object({\n id: z.string(),\n parameterId: z.string(),\n dependsOnParameterId: z.string(),\n dependencyType: ParameterDependencyTypeSchema,\n conditionValue: z.string().optional()\n});\n\nexport type ParameterValue = string | number | boolean;\n\nexport type ParameterDependency = z.infer;\n\nexport const ParameterMetadataSchema = z.object({\n tags: z.array(z.string()).optional()\n});\nexport type ParameterMetadata = z.infer;\nexport const ParameterTypeSchema = z.enum([\"Flag\", \"Option\", \"Argument\"]);\nexport type ParameterType = z.infer;\n\nexport const ParameterDataTypeSchema = z.enum([\n \"String\",\n \"Number\",\n \"Boolean\",\n \"Enum\"\n]);\nexport type ParameterDataType = z.infer;\n\nexport const ParameterSchema = z.object({\n id: z.string(),\n name: z.string(),\n commandId: z.uuidv7().optional(),\n description: z.string(),\n metadata: ParameterMetadataSchema.optional(),\n parameterType: ParameterTypeSchema,\n dataType: ParameterDataTypeSchema,\n isRequired: z.boolean(),\n isRepeatable: z.boolean(),\n isGlobal: z.boolean(),\n defaultValue: z.string().optional(),\n shortFlag: z.string().optional(),\n longFlag: z.string(),\n position: z.number().optional(),\n sortOrder: z.number().optional(),\n arraySeparator: z.string().optional(),\n keyValueSeparator: z.string().optional(),\n enumValues: z.array(ParameterEnumValueSchema),\n validations: z.array(ParameterValidationSchema).optional(),\n dependencies: z.array(ParameterDependencySchema).optional()\n});\nexport type Parameter = z.infer;\n\nexport const ExclusionTypeSchema = z.enum([\n \"mutual_exclusive\",\n \"required_one_of\"\n]);\nexport type ExclusionType = z.infer;\n\nexport const ExclusionGroupSchema = z.object({\n id: z.string().optional(),\n commandId: z.string().optional(),\n name: z.string(),\n exclusionType: ExclusionTypeSchema,\n parameterIds: z.array(z.string())\n});\nexport type ExclusionGroup = z.infer;\n\nexport const SavedCommandSchema = z.object({\n id: z.string(),\n command: z.string()\n});\nexport type SavedCommand = z.infer;\n\nexport const SupportedToolInputTypeSchema = z.enum([\n \"StandardInput\",\n \"Parameter\"\n]);\nexport type SupportedToolInputType = z.infer<\n typeof SupportedToolInputTypeSchema\n>;\n\nexport const SupportedToolOutputTypeSchema = z.enum([\n \"StandardOutput\",\n \"File\",\n \"Directory\"\n]);\nexport type SupportedToolOutputType = z.infer<\n typeof SupportedToolOutputTypeSchema\n>;\n\nexport const ToolSchema = z.object({\n id: z.string().optional(),\n name: z.string(),\n displayName: z.string(),\n description: z.string().optional(),\n version: z.string().optional(),\n category: z.string().optional(),\n tags: z.array(z.string()).optional(),\n url: z.url().optional(),\n commands: z.array(CommandSchema),\n parameters: z.array(ParameterSchema),\n exclusionGroups: z.array(ExclusionGroupSchema),\n supportedInput: z.array(SupportedToolInputTypeSchema),\n supportedOutput: z.array(SupportedToolOutputTypeSchema)\n});\nexport type Tool = z.infer;\n\nexport const AIParseRequestSchema = z.object({\n helpText: z.string(),\n toolName: z.string().optional()\n});\nexport type AIParseRequest = z.infer;\n\nexport const AIParseResponseSchema = z.object({\n success: z.boolean(),\n data: ToolSchema.optional(),\n error: z.string().optional()\n});\nexport type AIParseResponse = z.infer;\n\nexport const newToolSchema = z.object({\n displayName: z.string(),\n name: z.string(),\n version: z.string().optional(),\n description: z.string().optional(),\n url: z.url().optional()\n});\nexport type ManualNewTool = z.infer;\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/types/commandly-nested.ts", + "content": "import { ParameterValidation, ParameterDependencyType, ParameterType, ParameterDataType, ParameterMetadata, ExclusionType, SupportedToolInputType, SupportedToolOutputType } from \"../../types\";\n\nexport interface NestedCommand {\n name: string;\n description: string;\n isDefault: boolean;\n sortOrder: number;\n parameters: NestedParameter[];\n subcommands: NestedCommand[];\n}\n\nexport interface NestedParameterEnumValue {\n value: string;\n displayName: string;\n description: string;\n isDefault: boolean;\n sortOrder: number;\n}\n\nexport type NestedParameterValidation = Omit<\n ParameterValidation,\n \"id\" | \"parameterId\"\n>;\n\nexport interface NestedParameterDependency {\n dependsOnParameter: string;\n dependencyType: ParameterDependencyType;\n conditionValue?: string;\n}\n\nexport interface NestedParameter {\n name: string;\n description: string;\n parameterType: ParameterType;\n dataType: ParameterDataType;\n metadata?: ParameterMetadata;\n isRequired: boolean;\n isRepeatable: boolean;\n isGlobal: boolean;\n defaultValue?: string;\n shortFlag?: string;\n longFlag: string;\n position?: number;\n sortOrder?: number;\n arraySeparator?: string;\n keyValueSeparator?: string;\n enumValues: NestedParameterEnumValue[];\n validations: NestedParameterValidation[];\n dependencies: NestedParameterDependency[];\n}\n\nexport interface NestedExclusionGroup {\n name: string;\n exclusionType: ExclusionType;\n parameters: string[];\n}\n\nexport interface NestedTool {\n name: string;\n displayName: string;\n description?: string;\n version?: string;\n url?: string;\n globalParameters: NestedParameter[];\n commands: NestedCommand[];\n exclusionGroups: NestedExclusionGroup[];\n supportedInput: SupportedToolInputType[];\n supportedOutput: SupportedToolOutputType[];\n}\n", + "type": "registry:lib" + } + ] +} diff --git a/public/r/commandly-utils.json b/public/r/commandly-utils.json new file mode 100644 index 0000000..899c387 --- /dev/null +++ b/public/r/commandly-utils.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "commandly-utils", + "type": "registry:lib", + "title": "Commandly Utils", + "description": "Utility functions for the Commandly tool editor system including command generation and parameter handling.", + "dependencies": ["react"], + "registryDependencies": [], + "files": [ + { + "path": "registry/commandly/lib/utils/commandly.ts", + "content": "import type {\n Command,\n Parameter,\n SavedCommand,\n Tool\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport const buildCommandHierarchy = (commands: Command[]): Command[] => {\n return commands.sort((a, b) => a.sortOrder - b.sortOrder);\n};\n\nexport const getCommandPath = (command: Command, tool: Tool): string => {\n const findCommandPath = (\n targetId: string,\n commands: Command[],\n path: string[] = []\n ): string[] | null => {\n for (const cmd of commands) {\n if (cmd.name === targetId) {\n return [...path, cmd.name];\n }\n\n const childCommands = commands.filter(\n (c) => c.parentCommandId === cmd.id\n );\n if (childCommands.length > 0) {\n const subPath = findCommandPath(targetId, childCommands, [\n ...path,\n cmd.name\n ]);\n if (subPath) {\n return subPath;\n }\n }\n }\n return null;\n };\n\n const rootCommands = tool.commands.filter((c) => !c.parentCommandId);\n const path = findCommandPath(command.name, rootCommands);\n\n if (!path) return command.name;\n\n if (command.name === tool.name && command.isDefault) {\n return tool.name;\n }\n\n const rootCommand = tool.commands.find((c) => c.name === tool.name);\n if (rootCommand?.isDefault && path[0] === tool.name) {\n path[0] = tool.name;\n }\n\n return path.join(\" \");\n};\n\nexport const getAllSubcommands = (\n commandId: string,\n commands: Command[]\n): Command[] => {\n const result: Command[] = [];\n\n const findSubcommands = (parentId: string) => {\n commands.forEach((cmd) => {\n if (cmd.parentCommandId === parentId) {\n result.push(cmd);\n findSubcommands(cmd.id);\n }\n });\n };\n\n findSubcommands(commandId);\n return result;\n};\n\nexport const exportToStructuredJSON = (tool: Tool) => {\n const flattenCommand = (cmd: Command) => {\n return { ...cmd };\n };\n\n return {\n name: tool.name,\n displayName: tool.displayName,\n description: tool.description,\n version: tool.version,\n commands: tool.commands.map(flattenCommand),\n parameters: tool.parameters,\n exclusionGroups: tool.exclusionGroups,\n supportedInput: tool.supportedInput,\n supportedOutput: tool.supportedOutput\n };\n};\n\nexport const flattenImportedData = (importedData: any): Tool => {\n const {\n name,\n displayName,\n parameters = [],\n commands = [],\n exclusionGroups = [],\n supportedInput = [],\n supportedOutput = []\n } = importedData;\n\n const allParameters: Parameter[] = [...parameters];\n\n const flattenCommandParameters = (\n command: any,\n parentId?: string\n ): Command[] => {\n const { parameters = [], subcommands = [], ...commandData } = command;\n\n parameters.forEach((param: any) => {\n allParameters.push({\n ...param,\n commandId: command.id,\n isGlobal: !command.name\n });\n });\n\n const flatCommand: Command = {\n ...commandData,\n parentCommandId: parentId\n };\n\n const flatCommands = [flatCommand];\n\n subcommands.forEach((subcmd: any) => {\n flatCommands.push(...flattenCommandParameters(subcmd, command.name));\n });\n\n return flatCommands;\n };\n\n const flatCommands: Command[] = [];\n commands.forEach((cmd: any) => {\n flatCommands.push(...flattenCommandParameters(cmd));\n });\n\n return {\n name: name,\n displayName: displayName || name,\n commands: flatCommands,\n parameters: allParameters,\n exclusionGroups,\n supportedInput: supportedInput,\n supportedOutput: supportedOutput\n };\n};\n\nexport const defaultTool = (toolName?: string, displayName?: string): Tool => {\n return {\n name: toolName || \"my-tool\",\n displayName: displayName || \"My Tool\",\n description: undefined,\n version: \"\",\n commands: [\n {\n id: uuidv7(),\n name: toolName || \"my-tool\",\n description: \"Main command\",\n isDefault: true,\n sortOrder: 0\n }\n ],\n parameters: [\n {\n id: \"--help\",\n name: \"Help\",\n description: \"Displays help menu of tool\",\n parameterType: \"Flag\",\n dataType: \"String\",\n isRequired: false,\n isGlobal: true,\n shortFlag: \"-h\",\n longFlag: \"--help\",\n isRepeatable: false,\n enumValues: [],\n validations: [],\n dependencies: []\n }\n ],\n exclusionGroups: [],\n supportedInput: [\"StandardInput\"],\n supportedOutput: [\"StandardOutput\"]\n };\n};\n\nexport const validateDefaultValue = (\n parameter: Parameter\n): { isValid: boolean; error?: string } => {\n const { defaultValue, validations, dataType } = parameter;\n\n if (!defaultValue || !validations) return { isValid: true };\n\n switch (dataType) {\n case \"Number\":\n if (!/^-?\\d+$/.test(defaultValue)) {\n return { isValid: false, error: \"Default value must be an integer\" };\n }\n break;\n case \"Boolean\":\n if (![\"true\", \"false\", \"1\", \"0\"].includes(defaultValue.toLowerCase())) {\n return {\n isValid: false,\n error: \"Default value must be true/false or 1/0\"\n };\n }\n break;\n }\n\n for (const validation of validations) {\n const value = dataType === \"Number\" ? Number(defaultValue) : defaultValue;\n\n switch (validation.validationType) {\n case \"min_length\":\n if (\n typeof value === \"string\" &&\n value.length < Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too short\"\n };\n }\n break;\n case \"max_length\":\n if (\n typeof value === \"string\" &&\n value.length > Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too long\"\n };\n }\n break;\n case \"min_value\":\n if (\n typeof value === \"number\" &&\n value < Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too small\"\n };\n }\n break;\n case \"max_value\":\n if (\n typeof value === \"number\" &&\n value > Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too large\"\n };\n }\n break;\n case \"regex\":\n if (\n typeof value === \"string\" &&\n !new RegExp(validation.validationValue).test(value)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value doesn't match pattern\"\n };\n }\n break;\n }\n }\n\n return { isValid: true };\n};\n\nexport const createNewCommand = (parentId?: string): Command => {\n return {\n id: uuidv7(),\n parentCommandId: parentId,\n name: randomCommandName(),\n description: \"\",\n isDefault: false,\n sortOrder: 1\n };\n};\n\nexport const createNewParameter = (\n isGlobal: boolean,\n commandId?: string\n): Parameter => {\n return {\n id: uuidv7(),\n name: \"\",\n commandId: isGlobal ? undefined : commandId,\n description: \"\",\n parameterType: \"Option\",\n dataType: \"String\",\n isRequired: false,\n isRepeatable: false,\n isGlobal,\n defaultValue: \"\",\n shortFlag: \"\",\n longFlag: \"\",\n sortOrder: 0,\n arraySeparator: \",\",\n keyValueSeparator: \" \",\n enumValues: [],\n validations: [],\n dependencies: []\n };\n};\n\nexport const getSavedCommandsFromStorage = (toolId: string): SavedCommand[] => {\n try {\n const saved = localStorage.getItem(`saved-${toolId}`);\n return saved ? JSON.parse(saved) : [];\n } catch {\n return [];\n }\n};\n\nexport const saveSavedCommandsToStorage = (\n toolId: string,\n commands: SavedCommand[]\n): void => {\n try {\n localStorage.setItem(toolId, JSON.stringify(commands));\n } catch (error) {\n console.error(\"Failed to save commands to localStorage:\", error);\n }\n};\n\nexport const addSavedCommandToStorage = (\n toolId: string,\n command: SavedCommand\n): void => {\n const existingCommands = getSavedCommandsFromStorage(toolId);\n const updatedCommands = [...existingCommands, command];\n saveSavedCommandsToStorage(toolId, updatedCommands);\n};\n\nexport const removeSavedCommandFromStorage = (\n toolId: string,\n commandId: string\n): void => {\n const existingCommands = getSavedCommandsFromStorage(toolId);\n const updatedCommands = existingCommands.filter(\n (cmd) => cmd.id !== commandId\n );\n saveSavedCommandsToStorage(toolId, updatedCommands);\n};\n\nexport const clearSavedCommandsFromStorage = (toolId: string): void => {\n localStorage.removeItem(toolId);\n};\n\nexport const randomCommandName = () => {\n const characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n let result = \"\";\n const charactersLength = characters.length;\n for (let i = 0; i < 7; i++) {\n result += characters.charAt(Math.floor(Math.random() * charactersLength));\n }\n return result;\n};\n\nexport function generateHashCode(s: string): string {\n let h = 0;\n for (let i = 0; i < s.length; i++)\n h = (Math.imul(31, h) + s.charCodeAt(i)) | 0;\n\n return h.toString();\n}\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly-nested.ts", + "content": "import type {\n Tool,\n Command,\n Parameter\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { NestedCommand, NestedExclusionGroup, NestedParameter, NestedTool } from \"../types/commandly-nested\";\n\n\nexport const convertToNestedStructure = (tool: Tool): NestedTool => {\n const globalParameters = tool.parameters.filter((p) => p.isGlobal);\n\n const convertParameter = (param: Parameter): NestedParameter => {\n const { id, commandId, ...rest } = param;\n return {\n ...rest,\n validations:\n param.validations?.map((v) => {\n return {\n validationType: v.validationType,\n validationValue: v.validationValue,\n errorMessage: v.errorMessage\n };\n }) || [],\n metadata: param.metadata,\n dataType: param.dataType,\n dependencies:\n param.dependencies?.map((dep) => {\n const dependsOnParam = tool.parameters.find(\n (p) => p.id === dep.dependsOnParameterId\n );\n return {\n dependsOnParameter: dependsOnParam?.longFlag || \"\",\n dependencyType: dep.dependencyType,\n conditionValue: dep.conditionValue\n };\n }) || []\n };\n };\n\n const buildNestedCommands = (\n commands: Command[],\n parentId?: string\n ): NestedCommand[] => {\n return commands\n .filter((cmd) => cmd.parentCommandId === parentId)\n .map((cmd) => {\n const commandParameters = tool.parameters.filter(\n (p) => p.commandId === cmd.id && !p.isGlobal\n );\n return {\n name: cmd.name,\n description: cmd.description,\n isDefault: cmd.isDefault,\n sortOrder: cmd.sortOrder,\n parameters: commandParameters.map(convertParameter),\n subcommands: buildNestedCommands(commands, cmd.id)\n };\n });\n };\n\n const nestedExclusionGroups: NestedExclusionGroup[] =\n tool.exclusionGroups.map((group) => {\n return {\n name: group.name,\n exclusionType: group.exclusionType,\n parameters: group.parameterIds.map((pid) => {\n const param = tool.parameters.find((p) => p.id === pid);\n return param?.longFlag || \"\";\n })\n };\n });\n\n return {\n name: tool.name,\n url: tool.url,\n displayName: tool.displayName,\n description: tool.description,\n version: tool.version,\n supportedInput: tool.supportedInput,\n supportedOutput: tool.supportedOutput,\n globalParameters: globalParameters.map(convertParameter),\n commands: buildNestedCommands(tool.commands),\n exclusionGroups: nestedExclusionGroups\n };\n};\n", + "type": "registry:lib" + } + ] +} diff --git a/public/r/core.json b/public/r/core.json new file mode 100644 index 0000000..d0c6063 --- /dev/null +++ b/public/r/core.json @@ -0,0 +1,60 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "core", + "type": "registry:block", + "title": "Core", + "description": "Basic components to render previews, command generation, and tool management.", + "dependencies": ["react", "lucide-react", "sonner", "zod"], + "registryDependencies": [ + "button", + "dialog", + "input", + "label", + "select", + "textarea", + "tabs", + "tooltip", + "scroll-area", + "hover-card" + ], + "files": [ + { + "path": "registry/commandly/generated-command.tsx", + "content": "import { useEffect, useState, useMemo } from \"react\";\nimport { TerminalIcon, CopyIcon, SaveIcon } from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { Button } from \"@/components/ui/button\";\nimport { getCommandPath } from \"@/registry/commandly/lib/utils/commandly\";\nimport {\n Parameter,\n ParameterValue,\n Tool,\n Command\n} from \"@/registry/commandly/lib/types/commandly\";\n\ninterface GeneratedCommandProps {\n tool: Tool;\n selectedCommand?: Command;\n parameterValues: Record;\n onSaveCommand?: (command: string) => void;\n}\n\nexport function GeneratedCommand({\n tool,\n selectedCommand,\n parameterValues,\n onSaveCommand\n}: GeneratedCommandProps) {\n selectedCommand = selectedCommand || tool.commands[0];\n const [generatedCommand, setGeneratedCommand] = useState(\"\");\n\n const globalParameters = useMemo(() => {\n return tool.parameters?.filter((p) => p.isGlobal) || [];\n }, [tool]);\n\n const currentParameters = useMemo(() => {\n return (\n tool?.parameters?.filter((p) => p.commandId === selectedCommand.id) || []\n );\n }, [tool, selectedCommand]);\n\n useEffect(() => {\n generateCommand();\n }, [tool, parameterValues, selectedCommand]);\n\n const generateCommand = () => {\n const commandPath = getCommandPath(selectedCommand, tool);\n let command =\n tool.name == commandPath ? tool.name : `${tool.name} ${commandPath}`;\n\n const parametersWithValues: Array<{\n param: Parameter;\n value: ParameterValue;\n }> = [];\n\n globalParameters.forEach((param) => {\n const value = parameterValues[param.id];\n if (value !== undefined && value !== \"\" && value !== false) {\n parametersWithValues.push({ param, value });\n }\n });\n\n currentParameters.forEach((param) => {\n const value = parameterValues[param.id];\n if (\n value !== undefined &&\n value !== \"\" &&\n value !== false &&\n !param.isGlobal\n ) {\n parametersWithValues.push({ param, value });\n }\n });\n\n const positionalParams = parametersWithValues\n .filter(({ param }) => param.parameterType === \"Argument\")\n .sort((a, b) => (a.param.position || 0) - (b.param.position || 0));\n\n parametersWithValues.forEach(({ param, value }) => {\n if (param.parameterType === \"Flag\") {\n if (value === true) {\n const flag = param.shortFlag || param.longFlag;\n if (flag) command += ` ${flag}`;\n }\n } else if (param.parameterType === \"Option\") {\n const flag = param.shortFlag || param.longFlag;\n if (flag) {\n const separator = param.keyValueSeparator ?? \" \";\n command += ` ${flag}${separator}${value}`;\n }\n } else if (param.parameterType === \"Argument\") {\n command += ` ${value}`;\n }\n });\n\n positionalParams.forEach(({ value }) => {\n command += ` ${value}`;\n });\n\n setGeneratedCommand(command);\n };\n\n const copyCommand = () => {\n navigator.clipboard.writeText(generatedCommand);\n toast(\"Command copied!\");\n };\n\n return (\n
\n {tool.commands.length === 0 ? (\n
\n \n

\n No commands available for this tool.\n

\n
\n ) : generatedCommand ? (\n
\n
\n {generatedCommand}\n
\n
\n \n {onSaveCommand && (\n onSaveCommand(generatedCommand)}\n variant=\"outline\"\n className=\"flex-1\"\n >\n \n Save Command\n \n )}\n
\n
\n ) : (\n
\n \n

\n Configure parameters to generate the command.\n

\n
\n )}\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/generated-command.tsx" + }, + { + "path": "registry/commandly/json-output.tsx", + "content": "import { useEffect, useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { CheckIcon, ChevronsUpDownIcon, CopyIcon } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger\n} from \"@/components/ui/popover\";\nimport {\n Command as UICommand,\n CommandGroup,\n CommandItem,\n CommandList\n} from \"@/components/ui/command\";\nimport {\n Card,\n CardAction,\n CardContent,\n CardHeader,\n CardTitle\n} from \"@/components/ui/card\";\nimport { exportToStructuredJSON } from \"@/registry/commandly/lib/utils/commandly\";\nimport { convertToNestedStructure } from \"@/registry/commandly/lib/utils/commandly-nested\";\nimport { Tool } from \"@/registry/commandly/lib/types/commandly\";\nimport { ScrollArea, ScrollBar } from \"@/components/ui/scroll-area\";\nimport { toast } from \"sonner\";\nimport { useQueryState } from \"nuqs\";\n\nconst jsonOptions = [\n { value: \"nested\", label: \"Nested\" },\n { value: \"flat\", label: \"Flat\" }\n];\n\ninterface JsonTypeComponentProps {\n tool: Tool;\n}\n\nexport function JsonOutput({ tool }: JsonTypeComponentProps) {\n const [open, setOpen] = useState(false);\n const [jsonString, setJsonString] = useState();\n const [jsonType, setJsonType] = useQueryState(\"output\", {\n defaultValue: \"flat\"\n });\n useEffect(() => {\n const config =\n jsonType === \"flat\"\n ? exportToStructuredJSON(tool)\n : convertToNestedStructure(tool);\n setJsonString(JSON.stringify(config, null, 2));\n }, [jsonType, tool]);\n\n return (\n \n \n \n Output type: \n \n \n \n {jsonOptions.find((option) => option.value === jsonType)?.label}\n \n \n \n \n \n \n \n {jsonOptions.map((option) => (\n {\n setJsonType(currentValue);\n setOpen(false);\n }}\n >\n {option.label}\n \n \n ))}\n \n \n \n \n \n \n {\n navigator.clipboard.writeText(jsonString!);\n toast(\"Copied!\");\n }}\n >\n \n \n \n \n [data-radix-scroll-area-viewport]]:max-h-[calc(100vh-320px)] max-w-full\"\n type=\"hover\"\n >\n
\n            {jsonString}\n          
\n \n \n \n
\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/json-output.tsx" + }, + { + "path": "registry/commandly/runtime-preview.tsx", + "content": "import { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\n\nimport { Badge } from \"@/components/ui/badge\";\nimport { Switch } from \"@/components/ui/switch\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue\n} from \"@/components/ui/select\";\nimport { InfoIcon } from \"lucide-react\";\nimport {\n Parameter,\n ParameterValue\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { Command, Tool } from \"@/registry/commandly/lib/types/commandly\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger\n} from \"@/components/ui/tooltip\";\nimport React from \"react\";\n\nconst findDefaultCommand = (tool: Tool): Command | null => {\n const defaultCommand = tool.commands.find((command) => command.isDefault);\n if (defaultCommand) return defaultCommand;\n\n const nameMatchCommand = tool.commands.find(\n (command) => command.name.toLowerCase() === tool.name.toLowerCase()\n );\n if (nameMatchCommand) return nameMatchCommand;\n\n return tool.commands.length > 0 ? tool.commands[0] : null;\n};\n\ninterface RuntimePreviewProps {\n selectedCommand?: Command | null;\n tool: Tool;\n parameterValues: Record;\n updateParameterValue: (parameterId: string, value: ParameterValue) => void;\n}\n\nexport function RuntimePreview({\n selectedCommand: providedCommand,\n tool,\n parameterValues,\n updateParameterValue\n}: RuntimePreviewProps) {\n const selectedCommand = providedCommand ?? findDefaultCommand(tool);\n\n const renderParameterInput = (parameter: Parameter) => {\n const value = parameterValues[parameter.id] || parameter.defaultValue || \"\";\n\n switch (parameter.parameterType) {\n case \"Flag\":\n return (\n
\n \n updateParameterValue(parameter.id, checked)\n }\n />\n \n {parameter.isGlobal && (\n \n global\n \n )}\n
\n );\n\n case \"Option\":\n if (parameter.dataType === \"Enum\") {\n return (\n
\n \n \n updateParameterValue(parameter.id, newValue)\n }\n >\n \n \n \n \n {parameter.enumValues.map((enumValue) => (\n \n {enumValue.displayName || enumValue.value}\n \n ))}\n \n \n
\n );\n } else if (parameter.dataType === \"Boolean\") {\n return (\n
\n \n updateParameterValue(parameter.id, checked.toString())\n }\n />\n \n {parameter.isGlobal && (\n \n global\n \n )}\n
\n );\n } else {\n return (\n
\n
\n \n {parameter.isGlobal && (\n \n global\n \n )}\n
\n \n updateParameterValue(parameter.id, e.target.value)\n }\n placeholder=\"Enter value\"\n />\n
\n );\n }\n\n case \"Argument\":\n return (\n
\n \n \n updateParameterValue(parameter.id, e.target.value)\n }\n placeholder=\"Enter value\"\n />\n
\n );\n\n default:\n return null;\n }\n };\n\n return (\n \n {selectedCommand && tool.commands.length === 0 ? (\n

\n No commands available for this tool.\n

\n ) : (\n
\n {tool.parameters.length > 0 ? (\n tool.parameters\n .filter(\n (param) =>\n param.commandId === selectedCommand?.id || param.isGlobal\n )\n .map(renderParameterInput)\n ) : (\n

\n No parameters available for this command.\n

\n )}\n
\n )}\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/runtime-preview.tsx" + }, + { + "path": "registry/commandly/lib/types/commandly.ts", + "content": "import { z } from \"zod/v4\";\n\nexport const CommandSchema = z.object({\n id: z.uuidv7(),\n parentCommandId: z.uuidv7().optional(),\n name: z.string(),\n description: z.string(),\n isDefault: z.boolean(),\n sortOrder: z.number()\n});\nexport type Command = z.infer;\n\nexport const ParameterEnumValueSchema = z.object({\n id: z.uuidv7(),\n parameterId: z.uuidv7(),\n value: z.string(),\n displayName: z.string(),\n description: z.string(),\n isDefault: z.boolean(),\n sortOrder: z.number()\n});\nexport type ParameterEnumValue = z.infer;\n\nexport const ParameterValidationTypeSchema = z.enum([\n \"min_length\",\n \"max_length\",\n \"min_value\",\n \"max_value\",\n \"regex\"\n]);\nexport type ParameterValidationType = z.infer<\n typeof ParameterValidationTypeSchema\n>;\n\nexport const ParameterValidationSchema = z.object({\n id: z.string(),\n parameterId: z.string(),\n validationType: ParameterValidationTypeSchema,\n validationValue: z.string(),\n errorMessage: z.string()\n});\nexport type ParameterValidation = z.infer;\nexport const ParameterDependencyTypeSchema = z.enum([\n \"requires\",\n \"conflicts_with\"\n]);\nexport type ParameterDependencyType = z.infer<\n typeof ParameterDependencyTypeSchema\n>;\nexport const ParameterDependencySchema = z.object({\n id: z.string(),\n parameterId: z.string(),\n dependsOnParameterId: z.string(),\n dependencyType: ParameterDependencyTypeSchema,\n conditionValue: z.string().optional()\n});\n\nexport type ParameterValue = string | number | boolean;\n\nexport type ParameterDependency = z.infer;\n\nexport const ParameterMetadataSchema = z.object({\n tags: z.array(z.string()).optional()\n});\nexport type ParameterMetadata = z.infer;\nexport const ParameterTypeSchema = z.enum([\"Flag\", \"Option\", \"Argument\"]);\nexport type ParameterType = z.infer;\n\nexport const ParameterDataTypeSchema = z.enum([\n \"String\",\n \"Number\",\n \"Boolean\",\n \"Enum\"\n]);\nexport type ParameterDataType = z.infer;\n\nexport const ParameterSchema = z.object({\n id: z.string(),\n name: z.string(),\n commandId: z.uuidv7().optional(),\n description: z.string(),\n metadata: ParameterMetadataSchema.optional(),\n parameterType: ParameterTypeSchema,\n dataType: ParameterDataTypeSchema,\n isRequired: z.boolean(),\n isRepeatable: z.boolean(),\n isGlobal: z.boolean(),\n defaultValue: z.string().optional(),\n shortFlag: z.string().optional(),\n longFlag: z.string(),\n position: z.number().optional(),\n sortOrder: z.number().optional(),\n arraySeparator: z.string().optional(),\n keyValueSeparator: z.string().optional(),\n enumValues: z.array(ParameterEnumValueSchema),\n validations: z.array(ParameterValidationSchema).optional(),\n dependencies: z.array(ParameterDependencySchema).optional()\n});\nexport type Parameter = z.infer;\n\nexport const ExclusionTypeSchema = z.enum([\n \"mutual_exclusive\",\n \"required_one_of\"\n]);\nexport type ExclusionType = z.infer;\n\nexport const ExclusionGroupSchema = z.object({\n id: z.string().optional(),\n commandId: z.string().optional(),\n name: z.string(),\n exclusionType: ExclusionTypeSchema,\n parameterIds: z.array(z.string())\n});\nexport type ExclusionGroup = z.infer;\n\nexport const SavedCommandSchema = z.object({\n id: z.string(),\n command: z.string()\n});\nexport type SavedCommand = z.infer;\n\nexport const SupportedToolInputTypeSchema = z.enum([\n \"StandardInput\",\n \"Parameter\"\n]);\nexport type SupportedToolInputType = z.infer<\n typeof SupportedToolInputTypeSchema\n>;\n\nexport const SupportedToolOutputTypeSchema = z.enum([\n \"StandardOutput\",\n \"File\",\n \"Directory\"\n]);\nexport type SupportedToolOutputType = z.infer<\n typeof SupportedToolOutputTypeSchema\n>;\n\nexport const ToolSchema = z.object({\n id: z.string().optional(),\n name: z.string(),\n displayName: z.string(),\n description: z.string().optional(),\n version: z.string().optional(),\n category: z.string().optional(),\n tags: z.array(z.string()).optional(),\n url: z.url().optional(),\n commands: z.array(CommandSchema),\n parameters: z.array(ParameterSchema),\n exclusionGroups: z.array(ExclusionGroupSchema),\n supportedInput: z.array(SupportedToolInputTypeSchema),\n supportedOutput: z.array(SupportedToolOutputTypeSchema)\n});\nexport type Tool = z.infer;\n\nexport const AIParseRequestSchema = z.object({\n helpText: z.string(),\n toolName: z.string().optional()\n});\nexport type AIParseRequest = z.infer;\n\nexport const AIParseResponseSchema = z.object({\n success: z.boolean(),\n data: ToolSchema.optional(),\n error: z.string().optional()\n});\nexport type AIParseResponse = z.infer;\n\nexport const newToolSchema = z.object({\n displayName: z.string(),\n name: z.string(),\n version: z.string().optional(),\n description: z.string().optional(),\n url: z.url().optional()\n});\nexport type ManualNewTool = z.infer;\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/types/commandly-nested.ts", + "content": "import { ParameterValidation, ParameterDependencyType, ParameterType, ParameterDataType, ParameterMetadata, ExclusionType, SupportedToolInputType, SupportedToolOutputType } from \"../../types\";\n\nexport interface NestedCommand {\n name: string;\n description: string;\n isDefault: boolean;\n sortOrder: number;\n parameters: NestedParameter[];\n subcommands: NestedCommand[];\n}\n\nexport interface NestedParameterEnumValue {\n value: string;\n displayName: string;\n description: string;\n isDefault: boolean;\n sortOrder: number;\n}\n\nexport type NestedParameterValidation = Omit<\n ParameterValidation,\n \"id\" | \"parameterId\"\n>;\n\nexport interface NestedParameterDependency {\n dependsOnParameter: string;\n dependencyType: ParameterDependencyType;\n conditionValue?: string;\n}\n\nexport interface NestedParameter {\n name: string;\n description: string;\n parameterType: ParameterType;\n dataType: ParameterDataType;\n metadata?: ParameterMetadata;\n isRequired: boolean;\n isRepeatable: boolean;\n isGlobal: boolean;\n defaultValue?: string;\n shortFlag?: string;\n longFlag: string;\n position?: number;\n sortOrder?: number;\n arraySeparator?: string;\n keyValueSeparator?: string;\n enumValues: NestedParameterEnumValue[];\n validations: NestedParameterValidation[];\n dependencies: NestedParameterDependency[];\n}\n\nexport interface NestedExclusionGroup {\n name: string;\n exclusionType: ExclusionType;\n parameters: string[];\n}\n\nexport interface NestedTool {\n name: string;\n displayName: string;\n description?: string;\n version?: string;\n url?: string;\n globalParameters: NestedParameter[];\n commands: NestedCommand[];\n exclusionGroups: NestedExclusionGroup[];\n supportedInput: SupportedToolInputType[];\n supportedOutput: SupportedToolOutputType[];\n}\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly.ts", + "content": "import type {\n Command,\n Parameter,\n SavedCommand,\n Tool\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport const buildCommandHierarchy = (commands: Command[]): Command[] => {\n return commands.sort((a, b) => a.sortOrder - b.sortOrder);\n};\n\nexport const getCommandPath = (command: Command, tool: Tool): string => {\n const findCommandPath = (\n targetId: string,\n commands: Command[],\n path: string[] = []\n ): string[] | null => {\n for (const cmd of commands) {\n if (cmd.name === targetId) {\n return [...path, cmd.name];\n }\n\n const childCommands = commands.filter(\n (c) => c.parentCommandId === cmd.id\n );\n if (childCommands.length > 0) {\n const subPath = findCommandPath(targetId, childCommands, [\n ...path,\n cmd.name\n ]);\n if (subPath) {\n return subPath;\n }\n }\n }\n return null;\n };\n\n const rootCommands = tool.commands.filter((c) => !c.parentCommandId);\n const path = findCommandPath(command.name, rootCommands);\n\n if (!path) return command.name;\n\n if (command.name === tool.name && command.isDefault) {\n return tool.name;\n }\n\n const rootCommand = tool.commands.find((c) => c.name === tool.name);\n if (rootCommand?.isDefault && path[0] === tool.name) {\n path[0] = tool.name;\n }\n\n return path.join(\" \");\n};\n\nexport const getAllSubcommands = (\n commandId: string,\n commands: Command[]\n): Command[] => {\n const result: Command[] = [];\n\n const findSubcommands = (parentId: string) => {\n commands.forEach((cmd) => {\n if (cmd.parentCommandId === parentId) {\n result.push(cmd);\n findSubcommands(cmd.id);\n }\n });\n };\n\n findSubcommands(commandId);\n return result;\n};\n\nexport const exportToStructuredJSON = (tool: Tool) => {\n const flattenCommand = (cmd: Command) => {\n return { ...cmd };\n };\n\n return {\n name: tool.name,\n displayName: tool.displayName,\n description: tool.description,\n version: tool.version,\n commands: tool.commands.map(flattenCommand),\n parameters: tool.parameters,\n exclusionGroups: tool.exclusionGroups,\n supportedInput: tool.supportedInput,\n supportedOutput: tool.supportedOutput\n };\n};\n\nexport const flattenImportedData = (importedData: any): Tool => {\n const {\n name,\n displayName,\n parameters = [],\n commands = [],\n exclusionGroups = [],\n supportedInput = [],\n supportedOutput = []\n } = importedData;\n\n const allParameters: Parameter[] = [...parameters];\n\n const flattenCommandParameters = (\n command: any,\n parentId?: string\n ): Command[] => {\n const { parameters = [], subcommands = [], ...commandData } = command;\n\n parameters.forEach((param: any) => {\n allParameters.push({\n ...param,\n commandId: command.id,\n isGlobal: !command.name\n });\n });\n\n const flatCommand: Command = {\n ...commandData,\n parentCommandId: parentId\n };\n\n const flatCommands = [flatCommand];\n\n subcommands.forEach((subcmd: any) => {\n flatCommands.push(...flattenCommandParameters(subcmd, command.name));\n });\n\n return flatCommands;\n };\n\n const flatCommands: Command[] = [];\n commands.forEach((cmd: any) => {\n flatCommands.push(...flattenCommandParameters(cmd));\n });\n\n return {\n name: name,\n displayName: displayName || name,\n commands: flatCommands,\n parameters: allParameters,\n exclusionGroups,\n supportedInput: supportedInput,\n supportedOutput: supportedOutput\n };\n};\n\nexport const defaultTool = (toolName?: string, displayName?: string): Tool => {\n return {\n name: toolName || \"my-tool\",\n displayName: displayName || \"My Tool\",\n description: undefined,\n version: \"\",\n commands: [\n {\n id: uuidv7(),\n name: toolName || \"my-tool\",\n description: \"Main command\",\n isDefault: true,\n sortOrder: 0\n }\n ],\n parameters: [\n {\n id: \"--help\",\n name: \"Help\",\n description: \"Displays help menu of tool\",\n parameterType: \"Flag\",\n dataType: \"String\",\n isRequired: false,\n isGlobal: true,\n shortFlag: \"-h\",\n longFlag: \"--help\",\n isRepeatable: false,\n enumValues: [],\n validations: [],\n dependencies: []\n }\n ],\n exclusionGroups: [],\n supportedInput: [\"StandardInput\"],\n supportedOutput: [\"StandardOutput\"]\n };\n};\n\nexport const validateDefaultValue = (\n parameter: Parameter\n): { isValid: boolean; error?: string } => {\n const { defaultValue, validations, dataType } = parameter;\n\n if (!defaultValue || !validations) return { isValid: true };\n\n switch (dataType) {\n case \"Number\":\n if (!/^-?\\d+$/.test(defaultValue)) {\n return { isValid: false, error: \"Default value must be an integer\" };\n }\n break;\n case \"Boolean\":\n if (![\"true\", \"false\", \"1\", \"0\"].includes(defaultValue.toLowerCase())) {\n return {\n isValid: false,\n error: \"Default value must be true/false or 1/0\"\n };\n }\n break;\n }\n\n for (const validation of validations) {\n const value = dataType === \"Number\" ? Number(defaultValue) : defaultValue;\n\n switch (validation.validationType) {\n case \"min_length\":\n if (\n typeof value === \"string\" &&\n value.length < Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too short\"\n };\n }\n break;\n case \"max_length\":\n if (\n typeof value === \"string\" &&\n value.length > Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too long\"\n };\n }\n break;\n case \"min_value\":\n if (\n typeof value === \"number\" &&\n value < Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too small\"\n };\n }\n break;\n case \"max_value\":\n if (\n typeof value === \"number\" &&\n value > Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too large\"\n };\n }\n break;\n case \"regex\":\n if (\n typeof value === \"string\" &&\n !new RegExp(validation.validationValue).test(value)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value doesn't match pattern\"\n };\n }\n break;\n }\n }\n\n return { isValid: true };\n};\n\nexport const createNewCommand = (parentId?: string): Command => {\n return {\n id: uuidv7(),\n parentCommandId: parentId,\n name: randomCommandName(),\n description: \"\",\n isDefault: false,\n sortOrder: 1\n };\n};\n\nexport const createNewParameter = (\n isGlobal: boolean,\n commandId?: string\n): Parameter => {\n return {\n id: uuidv7(),\n name: \"\",\n commandId: isGlobal ? undefined : commandId,\n description: \"\",\n parameterType: \"Option\",\n dataType: \"String\",\n isRequired: false,\n isRepeatable: false,\n isGlobal,\n defaultValue: \"\",\n shortFlag: \"\",\n longFlag: \"\",\n sortOrder: 0,\n arraySeparator: \",\",\n keyValueSeparator: \" \",\n enumValues: [],\n validations: [],\n dependencies: []\n };\n};\n\nexport const getSavedCommandsFromStorage = (toolId: string): SavedCommand[] => {\n try {\n const saved = localStorage.getItem(`saved-${toolId}`);\n return saved ? JSON.parse(saved) : [];\n } catch {\n return [];\n }\n};\n\nexport const saveSavedCommandsToStorage = (\n toolId: string,\n commands: SavedCommand[]\n): void => {\n try {\n localStorage.setItem(toolId, JSON.stringify(commands));\n } catch (error) {\n console.error(\"Failed to save commands to localStorage:\", error);\n }\n};\n\nexport const addSavedCommandToStorage = (\n toolId: string,\n command: SavedCommand\n): void => {\n const existingCommands = getSavedCommandsFromStorage(toolId);\n const updatedCommands = [...existingCommands, command];\n saveSavedCommandsToStorage(toolId, updatedCommands);\n};\n\nexport const removeSavedCommandFromStorage = (\n toolId: string,\n commandId: string\n): void => {\n const existingCommands = getSavedCommandsFromStorage(toolId);\n const updatedCommands = existingCommands.filter(\n (cmd) => cmd.id !== commandId\n );\n saveSavedCommandsToStorage(toolId, updatedCommands);\n};\n\nexport const clearSavedCommandsFromStorage = (toolId: string): void => {\n localStorage.removeItem(toolId);\n};\n\nexport const randomCommandName = () => {\n const characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n let result = \"\";\n const charactersLength = characters.length;\n for (let i = 0; i < 7; i++) {\n result += characters.charAt(Math.floor(Math.random() * charactersLength));\n }\n return result;\n};\n\nexport function generateHashCode(s: string): string {\n let h = 0;\n for (let i = 0; i < s.length; i++)\n h = (Math.imul(31, h) + s.charCodeAt(i)) | 0;\n\n return h.toString();\n}\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly-nested.ts", + "content": "import type {\n Tool,\n Command,\n Parameter\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { NestedCommand, NestedExclusionGroup, NestedParameter, NestedTool } from \"../types/commandly-nested\";\n\n\nexport const convertToNestedStructure = (tool: Tool): NestedTool => {\n const globalParameters = tool.parameters.filter((p) => p.isGlobal);\n\n const convertParameter = (param: Parameter): NestedParameter => {\n const { id, commandId, ...rest } = param;\n return {\n ...rest,\n validations:\n param.validations?.map((v) => {\n return {\n validationType: v.validationType,\n validationValue: v.validationValue,\n errorMessage: v.errorMessage\n };\n }) || [],\n metadata: param.metadata,\n dataType: param.dataType,\n dependencies:\n param.dependencies?.map((dep) => {\n const dependsOnParam = tool.parameters.find(\n (p) => p.id === dep.dependsOnParameterId\n );\n return {\n dependsOnParameter: dependsOnParam?.longFlag || \"\",\n dependencyType: dep.dependencyType,\n conditionValue: dep.conditionValue\n };\n }) || []\n };\n };\n\n const buildNestedCommands = (\n commands: Command[],\n parentId?: string\n ): NestedCommand[] => {\n return commands\n .filter((cmd) => cmd.parentCommandId === parentId)\n .map((cmd) => {\n const commandParameters = tool.parameters.filter(\n (p) => p.commandId === cmd.id && !p.isGlobal\n );\n return {\n name: cmd.name,\n description: cmd.description,\n isDefault: cmd.isDefault,\n sortOrder: cmd.sortOrder,\n parameters: commandParameters.map(convertParameter),\n subcommands: buildNestedCommands(commands, cmd.id)\n };\n });\n };\n\n const nestedExclusionGroups: NestedExclusionGroup[] =\n tool.exclusionGroups.map((group) => {\n return {\n name: group.name,\n exclusionType: group.exclusionType,\n parameters: group.parameterIds.map((pid) => {\n const param = tool.parameters.find((p) => p.id === pid);\n return param?.longFlag || \"\";\n })\n };\n });\n\n return {\n name: tool.name,\n url: tool.url,\n displayName: tool.displayName,\n description: tool.description,\n version: tool.version,\n supportedInput: tool.supportedInput,\n supportedOutput: tool.supportedOutput,\n globalParameters: globalParameters.map(convertParameter),\n commands: buildNestedCommands(tool.commands),\n exclusionGroups: nestedExclusionGroups\n };\n};\n", + "type": "registry:lib" + } + ] +} diff --git a/public/r/generated-command.json b/public/r/generated-command.json new file mode 100644 index 0000000..30aa936 --- /dev/null +++ b/public/r/generated-command.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "generated-command", + "type": "registry:component", + "title": "Generated Command", + "description": "A component that generates CLI commands based on tool configuration and parameter values with copy and save functionality.", + "dependencies": ["react", "lucide-react", "sonner"], + "registryDependencies": ["button"], + "files": [ + { + "path": "registry/commandly/generated-command.tsx", + "content": "import { useEffect, useState, useMemo } from \"react\";\nimport { TerminalIcon, CopyIcon, SaveIcon } from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { Button } from \"@/components/ui/button\";\nimport { getCommandPath } from \"@/registry/commandly/lib/utils/commandly\";\nimport {\n Parameter,\n ParameterValue,\n Tool,\n Command\n} from \"@/registry/commandly/lib/types/commandly\";\n\ninterface GeneratedCommandProps {\n tool: Tool;\n selectedCommand?: Command;\n parameterValues: Record;\n onSaveCommand?: (command: string) => void;\n}\n\nexport function GeneratedCommand({\n tool,\n selectedCommand,\n parameterValues,\n onSaveCommand\n}: GeneratedCommandProps) {\n selectedCommand = selectedCommand || tool.commands[0];\n const [generatedCommand, setGeneratedCommand] = useState(\"\");\n\n const globalParameters = useMemo(() => {\n return tool.parameters?.filter((p) => p.isGlobal) || [];\n }, [tool]);\n\n const currentParameters = useMemo(() => {\n return (\n tool?.parameters?.filter((p) => p.commandId === selectedCommand.id) || []\n );\n }, [tool, selectedCommand]);\n\n useEffect(() => {\n generateCommand();\n }, [tool, parameterValues, selectedCommand]);\n\n const generateCommand = () => {\n const commandPath = getCommandPath(selectedCommand, tool);\n let command =\n tool.name == commandPath ? tool.name : `${tool.name} ${commandPath}`;\n\n const parametersWithValues: Array<{\n param: Parameter;\n value: ParameterValue;\n }> = [];\n\n globalParameters.forEach((param) => {\n const value = parameterValues[param.id];\n if (value !== undefined && value !== \"\" && value !== false) {\n parametersWithValues.push({ param, value });\n }\n });\n\n currentParameters.forEach((param) => {\n const value = parameterValues[param.id];\n if (\n value !== undefined &&\n value !== \"\" &&\n value !== false &&\n !param.isGlobal\n ) {\n parametersWithValues.push({ param, value });\n }\n });\n\n const positionalParams = parametersWithValues\n .filter(({ param }) => param.parameterType === \"Argument\")\n .sort((a, b) => (a.param.position || 0) - (b.param.position || 0));\n\n parametersWithValues.forEach(({ param, value }) => {\n if (param.parameterType === \"Flag\") {\n if (value === true) {\n const flag = param.shortFlag || param.longFlag;\n if (flag) command += ` ${flag}`;\n }\n } else if (param.parameterType === \"Option\") {\n const flag = param.shortFlag || param.longFlag;\n if (flag) {\n const separator = param.keyValueSeparator ?? \" \";\n command += ` ${flag}${separator}${value}`;\n }\n } else if (param.parameterType === \"Argument\") {\n command += ` ${value}`;\n }\n });\n\n positionalParams.forEach(({ value }) => {\n command += ` ${value}`;\n });\n\n setGeneratedCommand(command);\n };\n\n const copyCommand = () => {\n navigator.clipboard.writeText(generatedCommand);\n toast(\"Command copied!\");\n };\n\n return (\n
\n {tool.commands.length === 0 ? (\n
\n \n

\n No commands available for this tool.\n

\n
\n ) : generatedCommand ? (\n
\n
\n {generatedCommand}\n
\n
\n \n {onSaveCommand && (\n onSaveCommand(generatedCommand)}\n variant=\"outline\"\n className=\"flex-1\"\n >\n \n Save Command\n \n )}\n
\n
\n ) : (\n
\n \n

\n Configure parameters to generate the command.\n

\n
\n )}\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/generated-command.tsx" + }, + { + "path": "registry/commandly/lib/types/commandly.ts", + "content": "import { z } from \"zod/v4\";\n\nexport const CommandSchema = z.object({\n id: z.uuidv7(),\n parentCommandId: z.uuidv7().optional(),\n name: z.string(),\n description: z.string(),\n isDefault: z.boolean(),\n sortOrder: z.number()\n});\nexport type Command = z.infer;\n\nexport const ParameterEnumValueSchema = z.object({\n id: z.uuidv7(),\n parameterId: z.uuidv7(),\n value: z.string(),\n displayName: z.string(),\n description: z.string(),\n isDefault: z.boolean(),\n sortOrder: z.number()\n});\nexport type ParameterEnumValue = z.infer;\n\nexport const ParameterValidationTypeSchema = z.enum([\n \"min_length\",\n \"max_length\",\n \"min_value\",\n \"max_value\",\n \"regex\"\n]);\nexport type ParameterValidationType = z.infer<\n typeof ParameterValidationTypeSchema\n>;\n\nexport const ParameterValidationSchema = z.object({\n id: z.string(),\n parameterId: z.string(),\n validationType: ParameterValidationTypeSchema,\n validationValue: z.string(),\n errorMessage: z.string()\n});\nexport type ParameterValidation = z.infer;\nexport const ParameterDependencyTypeSchema = z.enum([\n \"requires\",\n \"conflicts_with\"\n]);\nexport type ParameterDependencyType = z.infer<\n typeof ParameterDependencyTypeSchema\n>;\nexport const ParameterDependencySchema = z.object({\n id: z.string(),\n parameterId: z.string(),\n dependsOnParameterId: z.string(),\n dependencyType: ParameterDependencyTypeSchema,\n conditionValue: z.string().optional()\n});\n\nexport type ParameterValue = string | number | boolean;\n\nexport type ParameterDependency = z.infer;\n\nexport const ParameterMetadataSchema = z.object({\n tags: z.array(z.string()).optional()\n});\nexport type ParameterMetadata = z.infer;\nexport const ParameterTypeSchema = z.enum([\"Flag\", \"Option\", \"Argument\"]);\nexport type ParameterType = z.infer;\n\nexport const ParameterDataTypeSchema = z.enum([\n \"String\",\n \"Number\",\n \"Boolean\",\n \"Enum\"\n]);\nexport type ParameterDataType = z.infer;\n\nexport const ParameterSchema = z.object({\n id: z.string(),\n name: z.string(),\n commandId: z.uuidv7().optional(),\n description: z.string(),\n metadata: ParameterMetadataSchema.optional(),\n parameterType: ParameterTypeSchema,\n dataType: ParameterDataTypeSchema,\n isRequired: z.boolean(),\n isRepeatable: z.boolean(),\n isGlobal: z.boolean(),\n defaultValue: z.string().optional(),\n shortFlag: z.string().optional(),\n longFlag: z.string(),\n position: z.number().optional(),\n sortOrder: z.number().optional(),\n arraySeparator: z.string().optional(),\n keyValueSeparator: z.string().optional(),\n enumValues: z.array(ParameterEnumValueSchema),\n validations: z.array(ParameterValidationSchema).optional(),\n dependencies: z.array(ParameterDependencySchema).optional()\n});\nexport type Parameter = z.infer;\n\nexport const ExclusionTypeSchema = z.enum([\n \"mutual_exclusive\",\n \"required_one_of\"\n]);\nexport type ExclusionType = z.infer;\n\nexport const ExclusionGroupSchema = z.object({\n id: z.string().optional(),\n commandId: z.string().optional(),\n name: z.string(),\n exclusionType: ExclusionTypeSchema,\n parameterIds: z.array(z.string())\n});\nexport type ExclusionGroup = z.infer;\n\nexport const SavedCommandSchema = z.object({\n id: z.string(),\n command: z.string()\n});\nexport type SavedCommand = z.infer;\n\nexport const SupportedToolInputTypeSchema = z.enum([\n \"StandardInput\",\n \"Parameter\"\n]);\nexport type SupportedToolInputType = z.infer<\n typeof SupportedToolInputTypeSchema\n>;\n\nexport const SupportedToolOutputTypeSchema = z.enum([\n \"StandardOutput\",\n \"File\",\n \"Directory\"\n]);\nexport type SupportedToolOutputType = z.infer<\n typeof SupportedToolOutputTypeSchema\n>;\n\nexport const ToolSchema = z.object({\n id: z.string().optional(),\n name: z.string(),\n displayName: z.string(),\n description: z.string().optional(),\n version: z.string().optional(),\n category: z.string().optional(),\n tags: z.array(z.string()).optional(),\n url: z.url().optional(),\n commands: z.array(CommandSchema),\n parameters: z.array(ParameterSchema),\n exclusionGroups: z.array(ExclusionGroupSchema),\n supportedInput: z.array(SupportedToolInputTypeSchema),\n supportedOutput: z.array(SupportedToolOutputTypeSchema)\n});\nexport type Tool = z.infer;\n\nexport const AIParseRequestSchema = z.object({\n helpText: z.string(),\n toolName: z.string().optional()\n});\nexport type AIParseRequest = z.infer;\n\nexport const AIParseResponseSchema = z.object({\n success: z.boolean(),\n data: ToolSchema.optional(),\n error: z.string().optional()\n});\nexport type AIParseResponse = z.infer;\n\nexport const newToolSchema = z.object({\n displayName: z.string(),\n name: z.string(),\n version: z.string().optional(),\n description: z.string().optional(),\n url: z.url().optional()\n});\nexport type ManualNewTool = z.infer;\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/types/commandly-nested.ts", + "content": "import { ParameterValidation, ParameterDependencyType, ParameterType, ParameterDataType, ParameterMetadata, ExclusionType, SupportedToolInputType, SupportedToolOutputType } from \"../../types\";\n\nexport interface NestedCommand {\n name: string;\n description: string;\n isDefault: boolean;\n sortOrder: number;\n parameters: NestedParameter[];\n subcommands: NestedCommand[];\n}\n\nexport interface NestedParameterEnumValue {\n value: string;\n displayName: string;\n description: string;\n isDefault: boolean;\n sortOrder: number;\n}\n\nexport type NestedParameterValidation = Omit<\n ParameterValidation,\n \"id\" | \"parameterId\"\n>;\n\nexport interface NestedParameterDependency {\n dependsOnParameter: string;\n dependencyType: ParameterDependencyType;\n conditionValue?: string;\n}\n\nexport interface NestedParameter {\n name: string;\n description: string;\n parameterType: ParameterType;\n dataType: ParameterDataType;\n metadata?: ParameterMetadata;\n isRequired: boolean;\n isRepeatable: boolean;\n isGlobal: boolean;\n defaultValue?: string;\n shortFlag?: string;\n longFlag: string;\n position?: number;\n sortOrder?: number;\n arraySeparator?: string;\n keyValueSeparator?: string;\n enumValues: NestedParameterEnumValue[];\n validations: NestedParameterValidation[];\n dependencies: NestedParameterDependency[];\n}\n\nexport interface NestedExclusionGroup {\n name: string;\n exclusionType: ExclusionType;\n parameters: string[];\n}\n\nexport interface NestedTool {\n name: string;\n displayName: string;\n description?: string;\n version?: string;\n url?: string;\n globalParameters: NestedParameter[];\n commands: NestedCommand[];\n exclusionGroups: NestedExclusionGroup[];\n supportedInput: SupportedToolInputType[];\n supportedOutput: SupportedToolOutputType[];\n}\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly.ts", + "content": "import type {\n Command,\n Parameter,\n SavedCommand,\n Tool\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport const buildCommandHierarchy = (commands: Command[]): Command[] => {\n return commands.sort((a, b) => a.sortOrder - b.sortOrder);\n};\n\nexport const getCommandPath = (command: Command, tool: Tool): string => {\n const findCommandPath = (\n targetId: string,\n commands: Command[],\n path: string[] = []\n ): string[] | null => {\n for (const cmd of commands) {\n if (cmd.name === targetId) {\n return [...path, cmd.name];\n }\n\n const childCommands = commands.filter(\n (c) => c.parentCommandId === cmd.id\n );\n if (childCommands.length > 0) {\n const subPath = findCommandPath(targetId, childCommands, [\n ...path,\n cmd.name\n ]);\n if (subPath) {\n return subPath;\n }\n }\n }\n return null;\n };\n\n const rootCommands = tool.commands.filter((c) => !c.parentCommandId);\n const path = findCommandPath(command.name, rootCommands);\n\n if (!path) return command.name;\n\n if (command.name === tool.name && command.isDefault) {\n return tool.name;\n }\n\n const rootCommand = tool.commands.find((c) => c.name === tool.name);\n if (rootCommand?.isDefault && path[0] === tool.name) {\n path[0] = tool.name;\n }\n\n return path.join(\" \");\n};\n\nexport const getAllSubcommands = (\n commandId: string,\n commands: Command[]\n): Command[] => {\n const result: Command[] = [];\n\n const findSubcommands = (parentId: string) => {\n commands.forEach((cmd) => {\n if (cmd.parentCommandId === parentId) {\n result.push(cmd);\n findSubcommands(cmd.id);\n }\n });\n };\n\n findSubcommands(commandId);\n return result;\n};\n\nexport const exportToStructuredJSON = (tool: Tool) => {\n const flattenCommand = (cmd: Command) => {\n return { ...cmd };\n };\n\n return {\n name: tool.name,\n displayName: tool.displayName,\n description: tool.description,\n version: tool.version,\n commands: tool.commands.map(flattenCommand),\n parameters: tool.parameters,\n exclusionGroups: tool.exclusionGroups,\n supportedInput: tool.supportedInput,\n supportedOutput: tool.supportedOutput\n };\n};\n\nexport const flattenImportedData = (importedData: any): Tool => {\n const {\n name,\n displayName,\n parameters = [],\n commands = [],\n exclusionGroups = [],\n supportedInput = [],\n supportedOutput = []\n } = importedData;\n\n const allParameters: Parameter[] = [...parameters];\n\n const flattenCommandParameters = (\n command: any,\n parentId?: string\n ): Command[] => {\n const { parameters = [], subcommands = [], ...commandData } = command;\n\n parameters.forEach((param: any) => {\n allParameters.push({\n ...param,\n commandId: command.id,\n isGlobal: !command.name\n });\n });\n\n const flatCommand: Command = {\n ...commandData,\n parentCommandId: parentId\n };\n\n const flatCommands = [flatCommand];\n\n subcommands.forEach((subcmd: any) => {\n flatCommands.push(...flattenCommandParameters(subcmd, command.name));\n });\n\n return flatCommands;\n };\n\n const flatCommands: Command[] = [];\n commands.forEach((cmd: any) => {\n flatCommands.push(...flattenCommandParameters(cmd));\n });\n\n return {\n name: name,\n displayName: displayName || name,\n commands: flatCommands,\n parameters: allParameters,\n exclusionGroups,\n supportedInput: supportedInput,\n supportedOutput: supportedOutput\n };\n};\n\nexport const defaultTool = (toolName?: string, displayName?: string): Tool => {\n return {\n name: toolName || \"my-tool\",\n displayName: displayName || \"My Tool\",\n description: undefined,\n version: \"\",\n commands: [\n {\n id: uuidv7(),\n name: toolName || \"my-tool\",\n description: \"Main command\",\n isDefault: true,\n sortOrder: 0\n }\n ],\n parameters: [\n {\n id: \"--help\",\n name: \"Help\",\n description: \"Displays help menu of tool\",\n parameterType: \"Flag\",\n dataType: \"String\",\n isRequired: false,\n isGlobal: true,\n shortFlag: \"-h\",\n longFlag: \"--help\",\n isRepeatable: false,\n enumValues: [],\n validations: [],\n dependencies: []\n }\n ],\n exclusionGroups: [],\n supportedInput: [\"StandardInput\"],\n supportedOutput: [\"StandardOutput\"]\n };\n};\n\nexport const validateDefaultValue = (\n parameter: Parameter\n): { isValid: boolean; error?: string } => {\n const { defaultValue, validations, dataType } = parameter;\n\n if (!defaultValue || !validations) return { isValid: true };\n\n switch (dataType) {\n case \"Number\":\n if (!/^-?\\d+$/.test(defaultValue)) {\n return { isValid: false, error: \"Default value must be an integer\" };\n }\n break;\n case \"Boolean\":\n if (![\"true\", \"false\", \"1\", \"0\"].includes(defaultValue.toLowerCase())) {\n return {\n isValid: false,\n error: \"Default value must be true/false or 1/0\"\n };\n }\n break;\n }\n\n for (const validation of validations) {\n const value = dataType === \"Number\" ? Number(defaultValue) : defaultValue;\n\n switch (validation.validationType) {\n case \"min_length\":\n if (\n typeof value === \"string\" &&\n value.length < Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too short\"\n };\n }\n break;\n case \"max_length\":\n if (\n typeof value === \"string\" &&\n value.length > Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too long\"\n };\n }\n break;\n case \"min_value\":\n if (\n typeof value === \"number\" &&\n value < Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too small\"\n };\n }\n break;\n case \"max_value\":\n if (\n typeof value === \"number\" &&\n value > Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too large\"\n };\n }\n break;\n case \"regex\":\n if (\n typeof value === \"string\" &&\n !new RegExp(validation.validationValue).test(value)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value doesn't match pattern\"\n };\n }\n break;\n }\n }\n\n return { isValid: true };\n};\n\nexport const createNewCommand = (parentId?: string): Command => {\n return {\n id: uuidv7(),\n parentCommandId: parentId,\n name: randomCommandName(),\n description: \"\",\n isDefault: false,\n sortOrder: 1\n };\n};\n\nexport const createNewParameter = (\n isGlobal: boolean,\n commandId?: string\n): Parameter => {\n return {\n id: uuidv7(),\n name: \"\",\n commandId: isGlobal ? undefined : commandId,\n description: \"\",\n parameterType: \"Option\",\n dataType: \"String\",\n isRequired: false,\n isRepeatable: false,\n isGlobal,\n defaultValue: \"\",\n shortFlag: \"\",\n longFlag: \"\",\n sortOrder: 0,\n arraySeparator: \",\",\n keyValueSeparator: \" \",\n enumValues: [],\n validations: [],\n dependencies: []\n };\n};\n\nexport const getSavedCommandsFromStorage = (toolId: string): SavedCommand[] => {\n try {\n const saved = localStorage.getItem(`saved-${toolId}`);\n return saved ? JSON.parse(saved) : [];\n } catch {\n return [];\n }\n};\n\nexport const saveSavedCommandsToStorage = (\n toolId: string,\n commands: SavedCommand[]\n): void => {\n try {\n localStorage.setItem(toolId, JSON.stringify(commands));\n } catch (error) {\n console.error(\"Failed to save commands to localStorage:\", error);\n }\n};\n\nexport const addSavedCommandToStorage = (\n toolId: string,\n command: SavedCommand\n): void => {\n const existingCommands = getSavedCommandsFromStorage(toolId);\n const updatedCommands = [...existingCommands, command];\n saveSavedCommandsToStorage(toolId, updatedCommands);\n};\n\nexport const removeSavedCommandFromStorage = (\n toolId: string,\n commandId: string\n): void => {\n const existingCommands = getSavedCommandsFromStorage(toolId);\n const updatedCommands = existingCommands.filter(\n (cmd) => cmd.id !== commandId\n );\n saveSavedCommandsToStorage(toolId, updatedCommands);\n};\n\nexport const clearSavedCommandsFromStorage = (toolId: string): void => {\n localStorage.removeItem(toolId);\n};\n\nexport const randomCommandName = () => {\n const characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n let result = \"\";\n const charactersLength = characters.length;\n for (let i = 0; i < 7; i++) {\n result += characters.charAt(Math.floor(Math.random() * charactersLength));\n }\n return result;\n};\n\nexport function generateHashCode(s: string): string {\n let h = 0;\n for (let i = 0; i < s.length; i++)\n h = (Math.imul(31, h) + s.charCodeAt(i)) | 0;\n\n return h.toString();\n}\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly-nested.ts", + "content": "import type {\n Tool,\n Command,\n Parameter\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { NestedCommand, NestedExclusionGroup, NestedParameter, NestedTool } from \"../types/commandly-nested\";\n\n\nexport const convertToNestedStructure = (tool: Tool): NestedTool => {\n const globalParameters = tool.parameters.filter((p) => p.isGlobal);\n\n const convertParameter = (param: Parameter): NestedParameter => {\n const { id, commandId, ...rest } = param;\n return {\n ...rest,\n validations:\n param.validations?.map((v) => {\n return {\n validationType: v.validationType,\n validationValue: v.validationValue,\n errorMessage: v.errorMessage\n };\n }) || [],\n metadata: param.metadata,\n dataType: param.dataType,\n dependencies:\n param.dependencies?.map((dep) => {\n const dependsOnParam = tool.parameters.find(\n (p) => p.id === dep.dependsOnParameterId\n );\n return {\n dependsOnParameter: dependsOnParam?.longFlag || \"\",\n dependencyType: dep.dependencyType,\n conditionValue: dep.conditionValue\n };\n }) || []\n };\n };\n\n const buildNestedCommands = (\n commands: Command[],\n parentId?: string\n ): NestedCommand[] => {\n return commands\n .filter((cmd) => cmd.parentCommandId === parentId)\n .map((cmd) => {\n const commandParameters = tool.parameters.filter(\n (p) => p.commandId === cmd.id && !p.isGlobal\n );\n return {\n name: cmd.name,\n description: cmd.description,\n isDefault: cmd.isDefault,\n sortOrder: cmd.sortOrder,\n parameters: commandParameters.map(convertParameter),\n subcommands: buildNestedCommands(commands, cmd.id)\n };\n });\n };\n\n const nestedExclusionGroups: NestedExclusionGroup[] =\n tool.exclusionGroups.map((group) => {\n return {\n name: group.name,\n exclusionType: group.exclusionType,\n parameters: group.parameterIds.map((pid) => {\n const param = tool.parameters.find((p) => p.id === pid);\n return param?.longFlag || \"\";\n })\n };\n });\n\n return {\n name: tool.name,\n url: tool.url,\n displayName: tool.displayName,\n description: tool.description,\n version: tool.version,\n supportedInput: tool.supportedInput,\n supportedOutput: tool.supportedOutput,\n globalParameters: globalParameters.map(convertParameter),\n commands: buildNestedCommands(tool.commands),\n exclusionGroups: nestedExclusionGroups\n };\n};\n", + "type": "registry:lib" + } + ] +} diff --git a/public/r/json-output.json b/public/r/json-output.json new file mode 100644 index 0000000..f8c9503 --- /dev/null +++ b/public/r/json-output.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "json-output", + "type": "registry:component", + "title": "JSON Output", + "description": "A component for displaying formatted JSON output with syntax highlighting and copy functionality.", + "dependencies": ["react"], + "registryDependencies": ["button", "scroll-area"], + "files": [ + { + "path": "registry/commandly/json-output.tsx", + "content": "import { useEffect, useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { CheckIcon, ChevronsUpDownIcon, CopyIcon } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger\n} from \"@/components/ui/popover\";\nimport {\n Command as UICommand,\n CommandGroup,\n CommandItem,\n CommandList\n} from \"@/components/ui/command\";\nimport {\n Card,\n CardAction,\n CardContent,\n CardHeader,\n CardTitle\n} from \"@/components/ui/card\";\nimport { exportToStructuredJSON } from \"@/registry/commandly/lib/utils/commandly\";\nimport { convertToNestedStructure } from \"@/registry/commandly/lib/utils/commandly-nested\";\nimport { Tool } from \"@/registry/commandly/lib/types/commandly\";\nimport { ScrollArea, ScrollBar } from \"@/components/ui/scroll-area\";\nimport { toast } from \"sonner\";\nimport { useQueryState } from \"nuqs\";\n\nconst jsonOptions = [\n { value: \"nested\", label: \"Nested\" },\n { value: \"flat\", label: \"Flat\" }\n];\n\ninterface JsonTypeComponentProps {\n tool: Tool;\n}\n\nexport function JsonOutput({ tool }: JsonTypeComponentProps) {\n const [open, setOpen] = useState(false);\n const [jsonString, setJsonString] = useState();\n const [jsonType, setJsonType] = useQueryState(\"output\", {\n defaultValue: \"flat\"\n });\n useEffect(() => {\n const config =\n jsonType === \"flat\"\n ? exportToStructuredJSON(tool)\n : convertToNestedStructure(tool);\n setJsonString(JSON.stringify(config, null, 2));\n }, [jsonType, tool]);\n\n return (\n \n \n \n Output type: \n \n \n \n {jsonOptions.find((option) => option.value === jsonType)?.label}\n \n \n \n \n \n \n \n {jsonOptions.map((option) => (\n {\n setJsonType(currentValue);\n setOpen(false);\n }}\n >\n {option.label}\n \n \n ))}\n \n \n \n \n \n \n {\n navigator.clipboard.writeText(jsonString!);\n toast(\"Copied!\");\n }}\n >\n \n \n \n \n [data-radix-scroll-area-viewport]]:max-h-[calc(100vh-320px)] max-w-full\"\n type=\"hover\"\n >\n
\n            {jsonString}\n          
\n \n \n \n
\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/json-output.tsx" + }, + { + "path": "registry/commandly/lib/types/commandly.ts", + "content": "import { z } from \"zod/v4\";\n\nexport const CommandSchema = z.object({\n id: z.uuidv7(),\n parentCommandId: z.uuidv7().optional(),\n name: z.string(),\n description: z.string(),\n isDefault: z.boolean(),\n sortOrder: z.number()\n});\nexport type Command = z.infer;\n\nexport const ParameterEnumValueSchema = z.object({\n id: z.uuidv7(),\n parameterId: z.uuidv7(),\n value: z.string(),\n displayName: z.string(),\n description: z.string(),\n isDefault: z.boolean(),\n sortOrder: z.number()\n});\nexport type ParameterEnumValue = z.infer;\n\nexport const ParameterValidationTypeSchema = z.enum([\n \"min_length\",\n \"max_length\",\n \"min_value\",\n \"max_value\",\n \"regex\"\n]);\nexport type ParameterValidationType = z.infer<\n typeof ParameterValidationTypeSchema\n>;\n\nexport const ParameterValidationSchema = z.object({\n id: z.string(),\n parameterId: z.string(),\n validationType: ParameterValidationTypeSchema,\n validationValue: z.string(),\n errorMessage: z.string()\n});\nexport type ParameterValidation = z.infer;\nexport const ParameterDependencyTypeSchema = z.enum([\n \"requires\",\n \"conflicts_with\"\n]);\nexport type ParameterDependencyType = z.infer<\n typeof ParameterDependencyTypeSchema\n>;\nexport const ParameterDependencySchema = z.object({\n id: z.string(),\n parameterId: z.string(),\n dependsOnParameterId: z.string(),\n dependencyType: ParameterDependencyTypeSchema,\n conditionValue: z.string().optional()\n});\n\nexport type ParameterValue = string | number | boolean;\n\nexport type ParameterDependency = z.infer;\n\nexport const ParameterMetadataSchema = z.object({\n tags: z.array(z.string()).optional()\n});\nexport type ParameterMetadata = z.infer;\nexport const ParameterTypeSchema = z.enum([\"Flag\", \"Option\", \"Argument\"]);\nexport type ParameterType = z.infer;\n\nexport const ParameterDataTypeSchema = z.enum([\n \"String\",\n \"Number\",\n \"Boolean\",\n \"Enum\"\n]);\nexport type ParameterDataType = z.infer;\n\nexport const ParameterSchema = z.object({\n id: z.string(),\n name: z.string(),\n commandId: z.uuidv7().optional(),\n description: z.string(),\n metadata: ParameterMetadataSchema.optional(),\n parameterType: ParameterTypeSchema,\n dataType: ParameterDataTypeSchema,\n isRequired: z.boolean(),\n isRepeatable: z.boolean(),\n isGlobal: z.boolean(),\n defaultValue: z.string().optional(),\n shortFlag: z.string().optional(),\n longFlag: z.string(),\n position: z.number().optional(),\n sortOrder: z.number().optional(),\n arraySeparator: z.string().optional(),\n keyValueSeparator: z.string().optional(),\n enumValues: z.array(ParameterEnumValueSchema),\n validations: z.array(ParameterValidationSchema).optional(),\n dependencies: z.array(ParameterDependencySchema).optional()\n});\nexport type Parameter = z.infer;\n\nexport const ExclusionTypeSchema = z.enum([\n \"mutual_exclusive\",\n \"required_one_of\"\n]);\nexport type ExclusionType = z.infer;\n\nexport const ExclusionGroupSchema = z.object({\n id: z.string().optional(),\n commandId: z.string().optional(),\n name: z.string(),\n exclusionType: ExclusionTypeSchema,\n parameterIds: z.array(z.string())\n});\nexport type ExclusionGroup = z.infer;\n\nexport const SavedCommandSchema = z.object({\n id: z.string(),\n command: z.string()\n});\nexport type SavedCommand = z.infer;\n\nexport const SupportedToolInputTypeSchema = z.enum([\n \"StandardInput\",\n \"Parameter\"\n]);\nexport type SupportedToolInputType = z.infer<\n typeof SupportedToolInputTypeSchema\n>;\n\nexport const SupportedToolOutputTypeSchema = z.enum([\n \"StandardOutput\",\n \"File\",\n \"Directory\"\n]);\nexport type SupportedToolOutputType = z.infer<\n typeof SupportedToolOutputTypeSchema\n>;\n\nexport const ToolSchema = z.object({\n id: z.string().optional(),\n name: z.string(),\n displayName: z.string(),\n description: z.string().optional(),\n version: z.string().optional(),\n category: z.string().optional(),\n tags: z.array(z.string()).optional(),\n url: z.url().optional(),\n commands: z.array(CommandSchema),\n parameters: z.array(ParameterSchema),\n exclusionGroups: z.array(ExclusionGroupSchema),\n supportedInput: z.array(SupportedToolInputTypeSchema),\n supportedOutput: z.array(SupportedToolOutputTypeSchema)\n});\nexport type Tool = z.infer;\n\nexport const AIParseRequestSchema = z.object({\n helpText: z.string(),\n toolName: z.string().optional()\n});\nexport type AIParseRequest = z.infer;\n\nexport const AIParseResponseSchema = z.object({\n success: z.boolean(),\n data: ToolSchema.optional(),\n error: z.string().optional()\n});\nexport type AIParseResponse = z.infer;\n\nexport const newToolSchema = z.object({\n displayName: z.string(),\n name: z.string(),\n version: z.string().optional(),\n description: z.string().optional(),\n url: z.url().optional()\n});\nexport type ManualNewTool = z.infer;\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/types/commandly-nested.ts", + "content": "import { ParameterValidation, ParameterDependencyType, ParameterType, ParameterDataType, ParameterMetadata, ExclusionType, SupportedToolInputType, SupportedToolOutputType } from \"../../types\";\n\nexport interface NestedCommand {\n name: string;\n description: string;\n isDefault: boolean;\n sortOrder: number;\n parameters: NestedParameter[];\n subcommands: NestedCommand[];\n}\n\nexport interface NestedParameterEnumValue {\n value: string;\n displayName: string;\n description: string;\n isDefault: boolean;\n sortOrder: number;\n}\n\nexport type NestedParameterValidation = Omit<\n ParameterValidation,\n \"id\" | \"parameterId\"\n>;\n\nexport interface NestedParameterDependency {\n dependsOnParameter: string;\n dependencyType: ParameterDependencyType;\n conditionValue?: string;\n}\n\nexport interface NestedParameter {\n name: string;\n description: string;\n parameterType: ParameterType;\n dataType: ParameterDataType;\n metadata?: ParameterMetadata;\n isRequired: boolean;\n isRepeatable: boolean;\n isGlobal: boolean;\n defaultValue?: string;\n shortFlag?: string;\n longFlag: string;\n position?: number;\n sortOrder?: number;\n arraySeparator?: string;\n keyValueSeparator?: string;\n enumValues: NestedParameterEnumValue[];\n validations: NestedParameterValidation[];\n dependencies: NestedParameterDependency[];\n}\n\nexport interface NestedExclusionGroup {\n name: string;\n exclusionType: ExclusionType;\n parameters: string[];\n}\n\nexport interface NestedTool {\n name: string;\n displayName: string;\n description?: string;\n version?: string;\n url?: string;\n globalParameters: NestedParameter[];\n commands: NestedCommand[];\n exclusionGroups: NestedExclusionGroup[];\n supportedInput: SupportedToolInputType[];\n supportedOutput: SupportedToolOutputType[];\n}\n", + "type": "registry:lib" + } + ] +} diff --git a/public/r/runtime-preview.json b/public/r/runtime-preview.json new file mode 100644 index 0000000..5782ba2 --- /dev/null +++ b/public/r/runtime-preview.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "runtime-preview", + "type": "registry:component", + "title": "Runtime Preview", + "description": "A component that provides real-time preview of CLI command execution and output.", + "dependencies": ["react"], + "registryDependencies": ["button", "scroll-area", "tabs"], + "files": [ + { + "path": "registry/commandly/runtime-preview.tsx", + "content": "import { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\n\nimport { Badge } from \"@/components/ui/badge\";\nimport { Switch } from \"@/components/ui/switch\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue\n} from \"@/components/ui/select\";\nimport { InfoIcon } from \"lucide-react\";\nimport {\n Parameter,\n ParameterValue\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { Command, Tool } from \"@/registry/commandly/lib/types/commandly\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger\n} from \"@/components/ui/tooltip\";\nimport React from \"react\";\n\nconst findDefaultCommand = (tool: Tool): Command | null => {\n const defaultCommand = tool.commands.find((command) => command.isDefault);\n if (defaultCommand) return defaultCommand;\n\n const nameMatchCommand = tool.commands.find(\n (command) => command.name.toLowerCase() === tool.name.toLowerCase()\n );\n if (nameMatchCommand) return nameMatchCommand;\n\n return tool.commands.length > 0 ? tool.commands[0] : null;\n};\n\ninterface RuntimePreviewProps {\n selectedCommand?: Command | null;\n tool: Tool;\n parameterValues: Record;\n updateParameterValue: (parameterId: string, value: ParameterValue) => void;\n}\n\nexport function RuntimePreview({\n selectedCommand: providedCommand,\n tool,\n parameterValues,\n updateParameterValue\n}: RuntimePreviewProps) {\n const selectedCommand = providedCommand ?? findDefaultCommand(tool);\n\n const renderParameterInput = (parameter: Parameter) => {\n const value = parameterValues[parameter.id] || parameter.defaultValue || \"\";\n\n switch (parameter.parameterType) {\n case \"Flag\":\n return (\n
\n \n updateParameterValue(parameter.id, checked)\n }\n />\n \n {parameter.isGlobal && (\n \n global\n \n )}\n
\n );\n\n case \"Option\":\n if (parameter.dataType === \"Enum\") {\n return (\n
\n \n \n updateParameterValue(parameter.id, newValue)\n }\n >\n \n \n \n \n {parameter.enumValues.map((enumValue) => (\n \n {enumValue.displayName || enumValue.value}\n \n ))}\n \n \n
\n );\n } else if (parameter.dataType === \"Boolean\") {\n return (\n
\n \n updateParameterValue(parameter.id, checked.toString())\n }\n />\n \n {parameter.isGlobal && (\n \n global\n \n )}\n
\n );\n } else {\n return (\n
\n
\n \n {parameter.isGlobal && (\n \n global\n \n )}\n
\n \n updateParameterValue(parameter.id, e.target.value)\n }\n placeholder=\"Enter value\"\n />\n
\n );\n }\n\n case \"Argument\":\n return (\n
\n \n \n updateParameterValue(parameter.id, e.target.value)\n }\n placeholder=\"Enter value\"\n />\n
\n );\n\n default:\n return null;\n }\n };\n\n return (\n \n {selectedCommand && tool.commands.length === 0 ? (\n

\n No commands available for this tool.\n

\n ) : (\n
\n {tool.parameters.length > 0 ? (\n tool.parameters\n .filter(\n (param) =>\n param.commandId === selectedCommand?.id || param.isGlobal\n )\n .map(renderParameterInput)\n ) : (\n

\n No parameters available for this command.\n

\n )}\n
\n )}\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/runtime-preview.tsx" + }, + { + "path": "registry/commandly/lib/types/commandly.ts", + "content": "import { z } from \"zod/v4\";\n\nexport const CommandSchema = z.object({\n id: z.uuidv7(),\n parentCommandId: z.uuidv7().optional(),\n name: z.string(),\n description: z.string(),\n isDefault: z.boolean(),\n sortOrder: z.number()\n});\nexport type Command = z.infer;\n\nexport const ParameterEnumValueSchema = z.object({\n id: z.uuidv7(),\n parameterId: z.uuidv7(),\n value: z.string(),\n displayName: z.string(),\n description: z.string(),\n isDefault: z.boolean(),\n sortOrder: z.number()\n});\nexport type ParameterEnumValue = z.infer;\n\nexport const ParameterValidationTypeSchema = z.enum([\n \"min_length\",\n \"max_length\",\n \"min_value\",\n \"max_value\",\n \"regex\"\n]);\nexport type ParameterValidationType = z.infer<\n typeof ParameterValidationTypeSchema\n>;\n\nexport const ParameterValidationSchema = z.object({\n id: z.string(),\n parameterId: z.string(),\n validationType: ParameterValidationTypeSchema,\n validationValue: z.string(),\n errorMessage: z.string()\n});\nexport type ParameterValidation = z.infer;\nexport const ParameterDependencyTypeSchema = z.enum([\n \"requires\",\n \"conflicts_with\"\n]);\nexport type ParameterDependencyType = z.infer<\n typeof ParameterDependencyTypeSchema\n>;\nexport const ParameterDependencySchema = z.object({\n id: z.string(),\n parameterId: z.string(),\n dependsOnParameterId: z.string(),\n dependencyType: ParameterDependencyTypeSchema,\n conditionValue: z.string().optional()\n});\n\nexport type ParameterValue = string | number | boolean;\n\nexport type ParameterDependency = z.infer;\n\nexport const ParameterMetadataSchema = z.object({\n tags: z.array(z.string()).optional()\n});\nexport type ParameterMetadata = z.infer;\nexport const ParameterTypeSchema = z.enum([\"Flag\", \"Option\", \"Argument\"]);\nexport type ParameterType = z.infer;\n\nexport const ParameterDataTypeSchema = z.enum([\n \"String\",\n \"Number\",\n \"Boolean\",\n \"Enum\"\n]);\nexport type ParameterDataType = z.infer;\n\nexport const ParameterSchema = z.object({\n id: z.string(),\n name: z.string(),\n commandId: z.uuidv7().optional(),\n description: z.string(),\n metadata: ParameterMetadataSchema.optional(),\n parameterType: ParameterTypeSchema,\n dataType: ParameterDataTypeSchema,\n isRequired: z.boolean(),\n isRepeatable: z.boolean(),\n isGlobal: z.boolean(),\n defaultValue: z.string().optional(),\n shortFlag: z.string().optional(),\n longFlag: z.string(),\n position: z.number().optional(),\n sortOrder: z.number().optional(),\n arraySeparator: z.string().optional(),\n keyValueSeparator: z.string().optional(),\n enumValues: z.array(ParameterEnumValueSchema),\n validations: z.array(ParameterValidationSchema).optional(),\n dependencies: z.array(ParameterDependencySchema).optional()\n});\nexport type Parameter = z.infer;\n\nexport const ExclusionTypeSchema = z.enum([\n \"mutual_exclusive\",\n \"required_one_of\"\n]);\nexport type ExclusionType = z.infer;\n\nexport const ExclusionGroupSchema = z.object({\n id: z.string().optional(),\n commandId: z.string().optional(),\n name: z.string(),\n exclusionType: ExclusionTypeSchema,\n parameterIds: z.array(z.string())\n});\nexport type ExclusionGroup = z.infer;\n\nexport const SavedCommandSchema = z.object({\n id: z.string(),\n command: z.string()\n});\nexport type SavedCommand = z.infer;\n\nexport const SupportedToolInputTypeSchema = z.enum([\n \"StandardInput\",\n \"Parameter\"\n]);\nexport type SupportedToolInputType = z.infer<\n typeof SupportedToolInputTypeSchema\n>;\n\nexport const SupportedToolOutputTypeSchema = z.enum([\n \"StandardOutput\",\n \"File\",\n \"Directory\"\n]);\nexport type SupportedToolOutputType = z.infer<\n typeof SupportedToolOutputTypeSchema\n>;\n\nexport const ToolSchema = z.object({\n id: z.string().optional(),\n name: z.string(),\n displayName: z.string(),\n description: z.string().optional(),\n version: z.string().optional(),\n category: z.string().optional(),\n tags: z.array(z.string()).optional(),\n url: z.url().optional(),\n commands: z.array(CommandSchema),\n parameters: z.array(ParameterSchema),\n exclusionGroups: z.array(ExclusionGroupSchema),\n supportedInput: z.array(SupportedToolInputTypeSchema),\n supportedOutput: z.array(SupportedToolOutputTypeSchema)\n});\nexport type Tool = z.infer;\n\nexport const AIParseRequestSchema = z.object({\n helpText: z.string(),\n toolName: z.string().optional()\n});\nexport type AIParseRequest = z.infer;\n\nexport const AIParseResponseSchema = z.object({\n success: z.boolean(),\n data: ToolSchema.optional(),\n error: z.string().optional()\n});\nexport type AIParseResponse = z.infer;\n\nexport const newToolSchema = z.object({\n displayName: z.string(),\n name: z.string(),\n version: z.string().optional(),\n description: z.string().optional(),\n url: z.url().optional()\n});\nexport type ManualNewTool = z.infer;\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/types/commandly-nested.ts", + "content": "import { ParameterValidation, ParameterDependencyType, ParameterType, ParameterDataType, ParameterMetadata, ExclusionType, SupportedToolInputType, SupportedToolOutputType } from \"../../types\";\n\nexport interface NestedCommand {\n name: string;\n description: string;\n isDefault: boolean;\n sortOrder: number;\n parameters: NestedParameter[];\n subcommands: NestedCommand[];\n}\n\nexport interface NestedParameterEnumValue {\n value: string;\n displayName: string;\n description: string;\n isDefault: boolean;\n sortOrder: number;\n}\n\nexport type NestedParameterValidation = Omit<\n ParameterValidation,\n \"id\" | \"parameterId\"\n>;\n\nexport interface NestedParameterDependency {\n dependsOnParameter: string;\n dependencyType: ParameterDependencyType;\n conditionValue?: string;\n}\n\nexport interface NestedParameter {\n name: string;\n description: string;\n parameterType: ParameterType;\n dataType: ParameterDataType;\n metadata?: ParameterMetadata;\n isRequired: boolean;\n isRepeatable: boolean;\n isGlobal: boolean;\n defaultValue?: string;\n shortFlag?: string;\n longFlag: string;\n position?: number;\n sortOrder?: number;\n arraySeparator?: string;\n keyValueSeparator?: string;\n enumValues: NestedParameterEnumValue[];\n validations: NestedParameterValidation[];\n dependencies: NestedParameterDependency[];\n}\n\nexport interface NestedExclusionGroup {\n name: string;\n exclusionType: ExclusionType;\n parameters: string[];\n}\n\nexport interface NestedTool {\n name: string;\n displayName: string;\n description?: string;\n version?: string;\n url?: string;\n globalParameters: NestedParameter[];\n commands: NestedCommand[];\n exclusionGroups: NestedExclusionGroup[];\n supportedInput: SupportedToolInputType[];\n supportedOutput: SupportedToolOutputType[];\n}\n", + "type": "registry:lib" + } + ] +} diff --git a/public/r/tool-editor.json b/public/r/tool-editor.json new file mode 100644 index 0000000..35e3879 --- /dev/null +++ b/public/r/tool-editor.json @@ -0,0 +1,133 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "tool-editor", + "type": "registry:block", + "title": "Tool Editor", + "description": "A comprehensive tool editor for creating and editing CLI tools with parameter management, command trees, and preview functionality.", + "dependencies": [ + "react", + "zod", + "lucide-react", + "sonner", + "@tanstack/react-store" + ], + "registryDependencies": [ + "button", + "dialog", + "input", + "label", + "select", + "textarea", + "tabs", + "tooltip", + "scroll-area", + "hover-card", + "https://shadcn-extension.vercel.app/registry/tags-input.json" + ], + "files": [ + { + "path": "registry/commandly/tool-editor/tool-editor.tsx", + "content": "import { SavedCommand, Tool } from \"@/registry/commandly/lib/types/commandly\";\nimport { CommandTree } from \"./command-tree\";\nimport { ParameterList } from \"./parameter-list\";\nimport { ParameterDetailsDialog } from \"../tool-editor/dialogs/parameter-details-dialog\";\nimport { ExclusionGroupsDialog } from \"../tool-editor/dialogs/exclusion-groups-dialog\";\nimport { PreviewTabs } from \"./preview-tabs\";\nimport { ToolDetailsDialog } from \"../tool-editor/dialogs/tool-details-dialog\";\nimport { Button } from \"@/components/ui/button\";\nimport { SaveIcon, Edit2Icon, LayersIcon } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { toolBuilderActions, toolBuilderStore } from \"./tool-editor.store\";\nimport { toast } from \"sonner\";\nimport {\n getSavedCommandsFromStorage,\n removeSavedCommandFromStorage\n} from \"@/registry/commandly/lib/utils/commandly\";\nimport { SavedCommandsDialog } from \"./dialogs/saved-commands-dialog\";\n\ninterface ToolEditorProps {\n tool: Tool;\n onSave?: (tool: Tool) => void;\n}\n\nexport default function ToolEditor({\n tool: toolToEdit,\n onSave\n}: ToolEditorProps) {\n const tool = useStore(toolBuilderStore, (state) => state.tool);\n\n useEffect(() => {\n toolBuilderActions.initializeTool(toolToEdit);\n }, [toolToEdit]);\n\n const [savedCommands, setSavedCommands] = useState([]);\n\n const handleDeleteCommand = (commandId: string) => {\n const toolId = tool.id || tool.name;\n removeSavedCommandFromStorage(`saved-${toolId}`, commandId);\n setSavedCommands(savedCommands.filter((cmd) => cmd.id !== commandId));\n };\n\n return (\n
\n
\n
\n

Commands

\n
\n \n
\n\n {/* Main Content */}\n
\n
\n
\n
\n \n {tool.displayName\n ? `${tool.displayName} (${tool.name})`\n : `${tool.name}`}\n \n \n toolBuilderActions.setDialogOpen(\"editTool\", true)\n }\n >\n \n \n
\n
\n {onSave && (\n {\n onSave(toolBuilderStore.state.tool);\n toast(\"Tool saved successfully!\");\n }}\n >\n \n Save\n \n )}\n {\n const toolId = tool.id || tool.name;\n const commands = getSavedCommandsFromStorage(toolId);\n setSavedCommands(commands);\n toolBuilderActions.setDialogOpen(\"savedCommands\", true);\n }}\n >\n \n Saved Commands\n \n \n toolBuilderActions.setDialogOpen(\"exclusionGroups\", true)\n }\n >\n \n Exclusion Groups\n \n
\n
\n
\n\n
\n
\n \n \n
\n
\n \n
\n
\n
\n\n \n \n \n \n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/tool-editor.tsx" + }, + { + "path": "registry/commandly/tool-editor/tool-editor.store.ts", + "content": "import { Store } from \"@tanstack/react-store\";\nimport {\n Tool,\n Command,\n Parameter,\n ExclusionGroup,\n ParameterValue,\n SavedCommand\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { toast } from \"sonner\";\nimport {\n addSavedCommandToStorage,\n createNewCommand,\n defaultTool,\n getAllSubcommands,\n getSavedCommandsFromStorage,\n removeSavedCommandFromStorage\n} from \"@/registry/commandly/lib/utils/commandly\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport interface ToolBuilderState {\n tool: Tool;\n selectedCommand: Command;\n selectedParameter: Parameter | null;\n editingCommand: Command | null;\n parameterValues: Record;\n dialogs: {\n parameterDetails: boolean;\n editTool: boolean;\n savedCommands: boolean;\n exclusionGroups: boolean;\n };\n}\n\nexport const toolBuilderStore = new Store({\n tool: defaultTool(),\n selectedCommand: {} as Command,\n selectedParameter: null,\n editingCommand: null,\n parameterValues: {},\n dialogs: {\n parameterDetails: false,\n editTool: false,\n savedCommands: false,\n exclusionGroups: false\n }\n});\n\nexport const toolBuilderSelectors = {\n getParametersForCommand: (\n state: ToolBuilderState,\n commandId: string\n ): Parameter[] => {\n return state.tool.parameters.filter((param: Parameter) => {\n if (param.isGlobal) return false;\n return param.commandId === commandId;\n });\n },\n\n getGlobalParameters: (state: ToolBuilderState): Parameter[] => {\n return state.tool.parameters.filter((param: Parameter) => param.isGlobal);\n },\n\n getExclusionGroupsForCommand: (\n state: ToolBuilderState,\n commandId: string\n ): ExclusionGroup[] => {\n return state.tool.exclusionGroups.filter((group: ExclusionGroup) => {\n return group.commandId === commandId;\n });\n }\n};\n\nexport const toolBuilderActions = {\n initializeTool(tool: Tool) {\n toolBuilderStore.setState((state) => ({\n ...state,\n tool,\n selectedCommand: tool.commands[0]\n }));\n },\n\n updateTool(updates: Partial) {\n toolBuilderStore.setState((state) => ({\n ...state,\n tool: {\n ...state.tool,\n ...updates\n }\n }));\n },\n\n addSubcommand(parentId?: string) {\n const newCommand = createNewCommand(parentId);\n toolBuilderStore.setState((state) => ({\n ...state,\n tool: {\n ...state.tool,\n commands: [...state.tool.commands, newCommand]\n }\n }));\n\n toast(\"Command Added\", {\n description: \"New command has been created successfully.\"\n });\n },\n\n deleteCommand(commandId: string) {\n toolBuilderStore.setState((state) => {\n const subcommands = getAllSubcommands(commandId, state.tool.commands);\n const commandsToDelete = [commandId, ...subcommands.map((c) => c.id)];\n\n const newState = {\n ...state,\n tool: {\n ...state.tool,\n commands: state.tool.commands.filter(\n (cmd) => !commandsToDelete.includes(cmd.id)\n ),\n parameters: state.tool.parameters.filter(\n (param) => !commandsToDelete.includes(param.commandId || \"\")\n ),\n exclusionGroups: state.tool.exclusionGroups.filter(\n (group) => !commandsToDelete.includes(group.commandId || \"\")\n )\n }\n };\n\n if (state.selectedCommand?.id === commandId) {\n newState.selectedCommand = newState.tool.commands[0];\n }\n\n return newState;\n });\n\n toast(\"Command Deleted\", {\n description: \"Command and all its subcommands have been deleted.\"\n });\n },\n\n updateCommand(commandId: string, updates: Partial) {\n toolBuilderStore.setState((state) => ({\n ...state,\n tool: {\n ...state.tool,\n commands: state.tool.commands.map((cmd) => {\n let updatedCmd: Command;\n if (cmd.id === commandId) {\n updatedCmd = { ...cmd, ...updates };\n } else {\n if (!updates.isDefault) updatedCmd = cmd;\n else {\n updatedCmd = { ...cmd, isDefault: false };\n }\n }\n return updatedCmd;\n })\n }\n }));\n },\n\n removeParameter(parameterId: string) {\n toolBuilderStore.setState((state) => {\n const newState = {\n ...state,\n tool: {\n ...state.tool,\n parameters: state.tool.parameters.filter(\n (param) => param.id !== parameterId\n ),\n exclusionGroups: state.tool.exclusionGroups.map((group) => ({\n ...group,\n parameterIds: group.parameterIds.filter((id) => id !== parameterId)\n }))\n }\n };\n\n if (state.selectedParameter?.id === parameterId) {\n newState.selectedParameter = null;\n }\n\n return newState;\n });\n\n toast(\"Parameter Deleted\", {\n description: \"Parameter has been removed successfully.\"\n });\n },\n addSavedCommand(command: string) {\n const toolId =\n toolBuilderStore.state.tool.id || toolBuilderStore.state.tool.name;\n const existingCommands = getSavedCommandsFromStorage(toolId);\n if (existingCommands.some((cmd) => cmd.command === command)) {\n toast.error(\"Command already exists\", {\n description: \"This command has already been saved.\"\n });\n return;\n }\n const newSavedCommand: SavedCommand = {\n id: uuidv7(),\n command\n };\n\n addSavedCommandToStorage(`saved-${toolId}`, newSavedCommand);\n\n toast(\"Command Saved\", {\n description: \"Command has been saved successfully.\"\n });\n },\n\n removeSavedCommand(commandId: string) {\n toolBuilderStore.setState((state) => {\n const toolId = state.tool.id || state.tool.name;\n removeSavedCommandFromStorage(`saved-${toolId}`, commandId);\n return { ...state };\n });\n },\n\n addExclusionGroup(group: Omit) {\n toolBuilderStore.setState((state) => {\n const newGroup = {\n ...group,\n id: uuidv7(),\n commandId: state.selectedCommand?.id\n };\n\n return {\n ...state,\n tool: {\n ...state.tool,\n exclusionGroups: [...state.tool.exclusionGroups, newGroup]\n }\n };\n });\n\n toast(\"Group Added\", {\n description: \"New exclusion group has been created successfully.\"\n });\n },\n\n updateExclusionGroup(updatedGroup: ExclusionGroup) {\n toolBuilderStore.setState((state) => ({\n ...state,\n tool: {\n ...state.tool,\n exclusionGroups: state.tool.exclusionGroups.map((group) =>\n group.id === updatedGroup.id ? updatedGroup : group\n )\n }\n }));\n\n toast(\"Group Updated\", {\n description: \"Exclusion group has been updated successfully.\"\n });\n },\n\n removeExclusionGroup(groupId: string) {\n toolBuilderStore.setState((state) => ({\n ...state,\n tool: {\n ...state.tool,\n exclusionGroups: state.tool.exclusionGroups.filter(\n (group) => group.id !== groupId\n )\n }\n }));\n\n toast(\"Group Removed\", {\n description: \"Exclusion group has been removed successfully.\"\n });\n },\n\n setDialogOpen(\n dialog:\n | \"editTool\"\n | \"savedCommands\"\n | \"exclusionGroups\"\n | \"parameterDetails\",\n open: boolean\n ) {\n toolBuilderStore.setState((state) => ({\n ...state,\n dialogs: {\n ...state.dialogs,\n [dialog]: open\n }\n }));\n },\n\n setSelectedCommand(command: Command) {\n toolBuilderStore.setState((state) => ({\n ...state,\n selectedCommand: command\n }));\n },\n\n setSelectedParameter(parameter: Parameter | null) {\n toolBuilderStore.setState((state) => ({\n ...state,\n selectedParameter: parameter\n }));\n },\n\n setEditingCommand(command: Command | null) {\n toolBuilderStore.setState((state) => ({\n ...state,\n editingCommand: command\n }));\n },\n\n upsertParameter(parameter: Parameter) {\n toolBuilderStore.setState((state) => {\n const exists = state.tool.parameters.some((p) => p.id === parameter.id);\n let newParameters: Parameter[];\n if (exists) {\n newParameters = state.tool.parameters.map((param) => {\n if (param.id === parameter.id) {\n const updatedParam = {\n ...param,\n ...parameter,\n dependencies: parameter.dependencies || [],\n validations: parameter.validations || [],\n enumValues: parameter.enumValues || []\n };\n if (parameter.isGlobal && parameter.isGlobal !== param.isGlobal) {\n updatedParam.commandId = undefined;\n }\n if (parameter.isGlobal === false && param.isGlobal) {\n updatedParam.commandId = state.selectedCommand?.id;\n }\n return updatedParam;\n }\n return param;\n });\n toast(\"Parameter Updated\", {\n description: `Parameter has been updated successfully.`\n });\n } else {\n newParameters = [...state.tool.parameters, parameter];\n toast(\"Parameter Added\", {\n description: `New ${parameter.isGlobal ? \"global \" : \"\"}parameter has been created successfully.`\n });\n }\n return {\n ...state,\n tool: {\n ...state.tool,\n parameters: newParameters\n }\n };\n });\n }\n};\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/tool-editor.store.tsx" + }, + { + "path": "registry/commandly/tool-editor/command-tree.tsx", + "content": "import { useState, useEffect, ReactNode } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { ScrollArea } from \"@/components/ui/scroll-area\";\nimport { Command } from \"@/registry/commandly/lib/types/commandly\";\nimport {\n ChevronDownIcon,\n ChevronRightIcon,\n Edit2Icon,\n PlusIcon,\n Trash2Icon\n} from \"lucide-react\";\nimport { CommandDialog } from \"../tool-editor/dialogs/command-dialog\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { toolBuilderStore, toolBuilderActions } from \"./tool-editor.store\";\n\nexport function CommandTree() {\n const tool = useStore(toolBuilderStore, (state) => state.tool);\n const selectedCommand = useStore(\n toolBuilderStore,\n (state) => state.selectedCommand\n );\n const editingCommand = useStore(\n toolBuilderStore,\n (state) => state.editingCommand\n );\n\n const [expandedCommands, setExpandedCommands] = useState>(\n new Set([tool.commands[0]?.id])\n );\n const [isDialogOpen, setIsDialogOpen] = useState(false);\n const [lastAddedCommand, setLastAddedCommand] = useState<{\n id: string;\n parentId?: string;\n } | null>(null);\n\n const handleEditCommand = (command: Command | null) => {\n toolBuilderActions.setEditingCommand(command);\n };\n\n const toggleExpanded = (commandId: string) => {\n setExpandedCommands((prev) => {\n const newSet = new Set(prev);\n if (newSet.has(commandId)) {\n newSet.delete(commandId);\n } else {\n newSet.add(commandId);\n }\n return newSet;\n });\n };\n\n // Patch toolBuilderActions.addSubcommand to select and expand parent after add\n const handleAddSubcommand = (parentId?: string) => {\n const prevIds = new Set(tool.commands.map((cmd) => cmd.id));\n toolBuilderActions.addSubcommand(parentId);\n setTimeout(() => {\n const newCmd = toolBuilderStore.state.tool.commands.find(\n (cmd) => !prevIds.has(cmd.id)\n );\n if (newCmd) {\n setLastAddedCommand({ id: newCmd.id, parentId });\n }\n }, 0);\n };\n\n useEffect(() => {\n if (!lastAddedCommand) return;\n const { id, parentId } = lastAddedCommand;\n const newCmd = tool.commands.find((cmd) => cmd.id === id);\n if (newCmd) {\n toolBuilderActions.setSelectedCommand(newCmd);\n if (parentId) {\n setExpandedCommands((prev) => {\n const newSet = new Set(prev);\n newSet.add(parentId);\n return newSet;\n });\n }\n setLastAddedCommand(null);\n }\n }, [tool.commands, lastAddedCommand]);\n\n const renderCommandNode = (command: Command, level = 0): ReactNode => {\n const isExpanded = expandedCommands.has(command.id);\n const subcommands = tool.commands.filter(\n (cmd) => cmd.parentCommandId === command.id\n );\n const hasSubcommands = subcommands.length > 0;\n const isSelected = selectedCommand?.id === command.id;\n const isRoot = command.name == tool.name;\n\n return (\n
\n toolBuilderActions.setSelectedCommand(command)}\n >\n {hasSubcommands ? (\n {\n e.stopPropagation();\n toggleExpanded(command.id);\n }}\n >\n {isExpanded ? (\n \n ) : (\n \n )}\n \n ) : (\n
\n )}\n\n {command.name}\n {command.isDefault && (\n \n default\n \n )}\n {\n e.stopPropagation();\n handleEditCommand(command);\n setIsDialogOpen(true);\n }}\n >\n \n \n {\n e.stopPropagation();\n handleAddSubcommand(command.id);\n }}\n >\n \n \n {!isRoot && (\n {\n e.stopPropagation();\n toolBuilderActions.deleteCommand(command.id);\n }}\n >\n \n \n )}\n
\n\n {isExpanded && hasSubcommands && (\n <>\n
\n {subcommands.map((subcmd) =>\n renderCommandNode(subcmd, level + 1)\n )}\n
\n \n )}\n
\n );\n };\n\n const rootCommands = tool.commands.filter((cmd) => !cmd.parentCommandId);\n\n return (\n <>\n \n
\n {rootCommands.map((command) => renderCommandNode(command))}\n
\n
\n \n
\n
\n {editingCommand && (\n {\n setIsDialogOpen(open);\n handleEditCommand(null);\n }}\n />\n )}\n \n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/command-tree.tsx" + }, + { + "path": "registry/commandly/tool-editor/parameter-list.tsx", + "content": "import { Button } from \"@/components/ui/button\";\nimport { Badge } from \"@/components/ui/badge\";\nimport {\n ExclusionGroup,\n ParameterType\n} from \"@/registry/commandly/lib/types/commandly\";\nimport {\n CheckCircleIcon,\n FileTextIcon,\n FlagIcon,\n GlobeIcon,\n HashIcon,\n LayersIcon,\n PlusIcon,\n Trash2Icon,\n XCircleIcon\n} from \"lucide-react\";\nimport { useStore } from \"@tanstack/react-store\";\nimport {\n toolBuilderStore,\n toolBuilderActions,\n toolBuilderSelectors\n} from \"./tool-editor.store\";\nimport {\n createNewParameter,\n validateDefaultValue\n} from \"@/registry/commandly/lib/utils/commandly\";\n\ninterface ParameterListProps {\n title: string;\n isGlobal?: boolean;\n}\n\nexport function ParameterList({ title, isGlobal = false }: ParameterListProps) {\n const selectedCommand = useStore(\n toolBuilderStore,\n (state) => state.selectedCommand\n );\n const globalParameters = useStore(toolBuilderStore, (state) =>\n toolBuilderSelectors.getGlobalParameters(state)\n );\n const commandParameters = useStore(toolBuilderStore, (state) =>\n selectedCommand?.id\n ? toolBuilderSelectors.getParametersForCommand(state, selectedCommand.id)\n : []\n );\n const exclusionGroups = useStore(toolBuilderStore, (state) =>\n selectedCommand?.id\n ? toolBuilderSelectors.getExclusionGroupsForCommand(\n state,\n selectedCommand.id\n )\n : []\n );\n\n const parameters = isGlobal ? globalParameters : commandParameters;\n\n const getParameterIcon = (parameterType: ParameterType) => {\n switch (parameterType) {\n case \"Flag\":\n return ;\n case \"Option\":\n return ;\n case \"Argument\":\n return ;\n default:\n return ;\n }\n };\n\n const getParameterExclusionGroups = (\n parameterId: string\n ): ExclusionGroup[] => {\n return exclusionGroups.filter((group) =>\n group.parameterIds.includes(parameterId)\n );\n };\n\n return (\n
\n
\n

\n {isGlobal && }\n {title} ({parameters.length})\n

\n \n toolBuilderActions.setSelectedParameter(\n createNewParameter(isGlobal, selectedCommand?.id)\n )\n }\n size=\"sm\"\n >\n \n \n
\n\n
\n {parameters.map((parameter) => {\n const validation = validateDefaultValue(parameter);\n const paramGroups = getParameterExclusionGroups(parameter.id);\n\n return (\n toolBuilderActions.setSelectedParameter(parameter)}\n >\n
\n
\n {getParameterIcon(parameter.parameterType)}\n \n {parameter.name}\n {(parameter.longFlag || parameter.shortFlag) && (\n \n (\n {[parameter.longFlag, parameter.shortFlag]\n .filter(Boolean)\n .join(\", \")}\n )\n \n )}\n \n
\n {\n e.stopPropagation();\n toolBuilderActions.removeParameter(parameter.id);\n }}\n >\n \n \n
\n
\n {parameter.isRequired && (\n \n required\n \n )}\n \n {parameter.parameterType}\n \n \n {parameter.dataType}\n \n {isGlobal && (\n \n global\n \n )}\n {paramGroups.map((group) => (\n \n \n {group.name}\n \n ))}\n {!validation.isValid && (\n \n )}\n {validation.isValid && parameter.defaultValue && (\n \n )}\n
\n
\n );\n })}\n
\n \n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/parameter-list.tsx" + }, + { + "path": "registry/commandly/tool-editor/preview-tabs.tsx", + "content": "import { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\nimport { HelpMenu } from \"./help-menu\";\nimport { useQueryState } from \"nuqs\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { toolBuilderStore, toolBuilderActions } from \"./tool-editor.store\";\nimport { RuntimePreview } from \"../runtime-preview\";\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle\n} from \"@/components/ui/card\";\nimport { ParameterValue } from \"@/registry/commandly/lib/types/commandly\";\nimport { TerminalIcon } from \"lucide-react\";\nimport { JsonOutput } from \"../json-output\";\nimport { GeneratedCommand } from \"../generated-command\";\n\nexport function PreviewTabs() {\n const [currentTab, setActiveTab] = useQueryState(\"tab\", {\n defaultValue: \"ui\"\n });\n\n const selectedCommand = useStore(\n toolBuilderStore,\n (state) => state.selectedCommand\n );\n const tool = useStore(toolBuilderStore, (state) => state.tool);\n const parameterValues = useStore(\n toolBuilderStore,\n (state) => state.parameterValues\n );\n const updateParameterValue = (parameterId: string, value: ParameterValue) => {\n toolBuilderStore.setState((state) => ({\n ...state,\n parameterValues: {\n ...state.parameterValues,\n [parameterId]: value as ParameterValue\n }\n }));\n };\n\n const handleSaveCommand = (command: string) => {\n toolBuilderActions.addSavedCommand(command);\n };\n\n return (\n
\n \n \n Json\n Preview\n Help\n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n Generated Command\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/preview-tabs.tsx" + }, + { + "path": "registry/commandly/tool-editor/help-menu.tsx", + "content": "import { ScrollArea, ScrollBar } from \"@/components/ui/scroll-area\";\nimport { Command } from \"@/registry/commandly/lib/types/commandly\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { toolBuilderStore } from \"./tool-editor.store\";\n\nexport function HelpMenu() {\n const tool = useStore(toolBuilderStore, (state) => state.tool);\n\n const generateToolPreview = (): string => {\n const rootCommands = tool.commands.filter((cmd) => !cmd.parentCommandId);\n const globalParams = tool.parameters.filter((p) => p.isGlobal);\n\n let preview = `${tool.displayName}${tool.version ? ` v${tool.version}` : \"\"}\\n`;\n preview += `${tool.description}\\n\\n`;\n\n preview += `USAGE:\\n`;\n preview += ` ${tool.name} [GLOBAL OPTIONS] [OPTIONS] [ARGUMENTS]\\n\\n`;\n\n if (globalParams.length > 0) {\n preview += \"GLOBAL OPTIONS:\\n\";\n\n const globalFlags = globalParams.filter(\n (p) => p.parameterType === \"Flag\"\n );\n const globalOptions = globalParams.filter(\n (p) => p.parameterType === \"Option\"\n );\n\n globalFlags.forEach((flag) => {\n const shortFlag = flag.shortFlag ? `${flag.shortFlag}` : \"\";\n const longFlag = flag.longFlag ? `${flag.longFlag}` : \"\";\n const flagStr =\n shortFlag && longFlag\n ? `${shortFlag}, ${longFlag}`\n : shortFlag || longFlag;\n const required = flag.isRequired ? \"Required: \" : \"\";\n preview += ` ${flagStr.padEnd(20)} ${required}${flag.description}\\n`;\n });\n\n globalOptions.forEach((option) => {\n const shortFlag = option.shortFlag ? `${option.shortFlag}` : \"\";\n const longFlag = option.longFlag ? `${option.longFlag}` : \"\";\n const flagStr =\n shortFlag && longFlag\n ? `${shortFlag}, ${longFlag}`\n : shortFlag || longFlag;\n const valueType = option.dataType.includes(\"array\")\n ? ``\n : `<${option.dataType}>`;\n const required = option.isRequired ? \"Required: \" : \"\";\n preview += ` ${flagStr.padEnd(20)} ${required}${option.description}\\n`;\n preview += ` ${\" \".repeat(20)} Value: ${valueType}\\n`;\n });\n\n preview += \"\\n\";\n }\n\n preview += \"COMMANDS:\\n\";\n const printCommand = (command: Command, level = 0) => {\n const indent = \" \".repeat(level + 1);\n preview += `${indent}${command.name.padEnd(20 - level * 2)} ${\n command.description\n }\\n`;\n\n const commandParams = tool.parameters.filter(\n (p) => !p.isGlobal && p.commandId === command.name\n );\n\n const flags = commandParams.filter((p) => p.parameterType === \"Flag\");\n const options = commandParams.filter((p) => p.parameterType === \"Option\");\n const arguments_ = commandParams.filter(\n (p) => p.parameterType === \"Argument\"\n );\n\n if (flags.length > 0) {\n preview += `${indent} Flags:\\n`;\n flags.forEach((flag) => {\n const shortFlag = flag.shortFlag ? `${flag.shortFlag}` : \"\";\n const longFlag = flag.longFlag ? `${flag.longFlag}` : \"\";\n const flagStr =\n shortFlag && longFlag\n ? `${shortFlag}, ${longFlag}`\n : shortFlag || longFlag;\n const required = flag.isRequired ? \"Required: \" : \"\";\n preview += `${indent} ${flagStr.padEnd(18)} ${required}${\n flag.description\n }\\n`;\n });\n }\n\n if (options.length > 0) {\n preview += `${indent} Options:\\n`;\n options.forEach((option) => {\n const shortFlag = option.shortFlag ? `${option.shortFlag}` : \"\";\n const longFlag = option.longFlag ? `${option.longFlag}` : \"\";\n const flagStr =\n shortFlag && longFlag\n ? `${shortFlag}, ${longFlag}`\n : shortFlag || longFlag;\n const valueType = option.dataType.includes(\"array\")\n ? ``\n : `<${option.dataType}>`;\n const required = option.isRequired ? \"Required: \" : \"\";\n preview += `${indent} ${flagStr.padEnd(18)} ${required}${\n option.description\n }\\n`;\n preview += `${indent} ${\" \".repeat(18)} Value: ${valueType}\\n`;\n });\n }\n\n if (arguments_.length > 0) {\n preview += `${indent} Arguments:\\n`;\n arguments_.forEach((arg) => {\n const required = arg.isRequired ? \"Required: \" : \"\";\n preview += `${indent} ${arg.name.padEnd(18)} ${required}${\n arg.description\n }\\n`;\n if (arg.dataType === \"Enum\") {\n preview += `${indent} ${\" \".repeat(18)} Values: ${arg.enumValues\n .map((e) => e.value)\n .join(\", \")}\\n`;\n }\n });\n }\n\n const subcommands = tool.commands.filter(\n (cmd) => cmd.parentCommandId === command.id\n );\n if (subcommands.length > 0) {\n preview += `${indent} Subcommands:\\n`;\n subcommands.forEach((subcmd) => {\n printCommand(subcmd, level + 2);\n });\n }\n };\n\n rootCommands.forEach((cmd) => printCommand(cmd));\n\n return preview;\n };\n\n return (\n \n
\n        {generateToolPreview()}\n      
\n \n \n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/help-menu.tsx" + }, + { + "path": "registry/commandly/tool-editor/dialogs/parameter-details-dialog.tsx", + "content": "import { useEffect, useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Switch } from \"@/components/ui/switch\";\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter,\n DialogDescription\n} from \"@/components/ui/dialog\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue\n} from \"@/components/ui/select\";\nimport { Separator } from \"@/components/ui/separator\";\nimport {\n FileTextIcon,\n FlagIcon,\n HashIcon,\n LinkIcon,\n PlusIcon,\n ShieldIcon,\n Trash2Icon\n} from \"lucide-react\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { validateDefaultValue } from \"@/registry/commandly/lib/utils/commandly\";\nimport { v7 as uuidv7 } from \"uuid\";\nimport { toolBuilderActions, toolBuilderStore } from \"../tool-editor.store\";\nimport {\n Parameter,\n ParameterDataType,\n ParameterDependency,\n ParameterDependencyType,\n ParameterEnumValue,\n ParameterType,\n ParameterValidation,\n ParameterValidationType\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { TagsInput } from \"@/registry/commandly/ui/tags-input\";\n\nexport function ParameterDetailsDialog() {\n const selectedParameter = useStore(\n toolBuilderStore,\n (state) => state.selectedParameter\n );\n\n const commandId = useStore(\n toolBuilderStore,\n (state) => state.selectedCommand?.id\n );\n\n const availableParameters = useStore(toolBuilderStore, (state) => {\n if (!selectedParameter) return [];\n return state.tool.parameters.filter((p) => {\n if (p.id === selectedParameter.id) return false;\n if (selectedParameter.isGlobal) return p.isGlobal;\n return p.isGlobal || p.commandId === commandId;\n });\n });\n\n const [parameter, setParameter] = useState(selectedParameter!);\n const [hasChanges, setHasChanges] = useState(false);\n\n useEffect(() => {\n setParameter(selectedParameter!);\n setHasChanges(false);\n }, [selectedParameter]);\n\n const getParameterIcon = (parameterType: string) => {\n switch (parameterType) {\n case \"Flag\":\n return ;\n case \"Option\":\n return ;\n case \"Argument\":\n return ;\n default:\n return ;\n }\n };\n\n const isOpen = !!selectedParameter;\n\n const handleClose = () => {\n toolBuilderActions.setSelectedParameter(null);\n setHasChanges(false);\n };\n\n const handleSave = () => {\n if (parameter) {\n toolBuilderActions.upsertParameter(parameter);\n setHasChanges(false);\n handleClose();\n }\n };\n\n const updateParameter = (updates: Partial) => {\n setParameter((prev) => ({ ...prev, ...updates }));\n setHasChanges(true);\n };\n\n const addDependency = () => {\n if (!parameter || availableParameters.length === 0) return;\n\n const newDependency: ParameterDependency = {\n id: uuidv7(),\n parameterId: parameter.id,\n dependsOnParameterId: availableParameters[0].id,\n dependencyType: \"requires\"\n };\n\n updateParameter({\n dependencies: [...(parameter.dependencies || []), newDependency]\n });\n };\n\n const updateDependency = (\n dependencyId: string,\n updates: Partial\n ) => {\n if (!parameter) return;\n const updatedDependencies = parameter.dependencies?.map((dep) =>\n dep.id === dependencyId ? { ...dep, ...updates } : dep\n );\n updateParameter({ dependencies: updatedDependencies });\n };\n\n const removeDependency = (dependencyId: string) => {\n if (!parameter) return;\n const updatedDependencies = parameter.dependencies?.filter(\n (dep) => dep.id !== dependencyId\n );\n updateParameter({ dependencies: updatedDependencies });\n };\n\n const addValidation = () => {\n if (!parameter) return;\n const newValidation: ParameterValidation = {\n id: uuidv7(),\n parameterId: parameter.id,\n validationType: \"min_length\",\n validationValue: \"1\",\n errorMessage: \"Value is too short\"\n };\n\n updateParameter({\n validations: [...(parameter.validations || []), newValidation]\n });\n };\n\n const addEnumValue = () => {\n if (!parameter) return;\n const newEnumValue: ParameterEnumValue = {\n id: uuidv7(),\n parameterId: parameter.id,\n value: \"new-value\",\n displayName: \"New Value\",\n description: \"\",\n isDefault: false,\n sortOrder: 0\n };\n\n updateParameter({\n enumValues: [...parameter.enumValues, newEnumValue]\n });\n };\n\n if (!parameter) return null;\n\n const validation = validateDefaultValue(parameter);\n\n const canSaveChanges = () => {\n if (!hasChanges) return false;\n if (parameter.defaultValue && !validation.isValid) {\n return false;\n }\n\n if (!parameter.name.trim() || !parameter.longFlag.trim()) {\n return false;\n }\n if (\n availableParameters.some(\n (p) =>\n p.name.trim() === parameter.name.trim() ||\n parameter.longFlag == p.longFlag ||\n (parameter.shortFlag && parameter.shortFlag == p.shortFlag)\n )\n ) {\n return false;\n }\n\n return true;\n };\n\n return (\n \n \n \n \n {getParameterIcon(parameter.parameterType)}\n {parameter.name}\n {parameter.isGlobal && (\n \n global\n \n )}\n \n \n \n\n
\n {/* Basic Info */}\n
\n
\n \n updateParameter({ name: e.target.value })}\n />\n
\n
\n\n
\n
\n \n \n updateParameter({ parameterType: value })\n }\n >\n \n \n \n \n Flag\n Option\n Argument\n \n \n
\n
\n \n \n updateParameter({ dataType: value })\n }\n >\n \n \n \n \n String\n Number\n Boolean\n Enum\n \n \n
\n
\n \n updateParameter({ isGlobal: checked })\n }\n />\n \n
\n
\n\n {(parameter.parameterType === \"Flag\" ||\n parameter.parameterType === \"Option\") && (\n
\n
\n \n \n updateParameter({ shortFlag: e.target.value })\n }\n placeholder=\"-v\"\n />\n
\n
\n \n \n updateParameter({ longFlag: e.target.value })\n }\n placeholder=\"--verbose\"\n />\n
\n
\n )}\n\n {parameter.parameterType === \"Option\" && (\n
\n \n \n updateParameter({ keyValueSeparator: e.target.value })\n }\n placeholder=\"Default is single space\"\n />\n
\n )}\n\n {parameter.parameterType === \"Argument\" && (\n
\n \n \n updateParameter({\n position: Number.parseInt(e.target.value) || 0\n })\n }\n placeholder=\"0\"\n />\n
\n )}\n\n
\n \n updateParameter({ description: e.target.value })}\n rows={2}\n />\n
\n\n
\n
\n \n \n updateParameter({ defaultValue: e.target.value })\n }\n className={!validation.isValid ? \"border-destructive\" : \"\"}\n />\n {!validation.isValid && (\n

\n {validation.error}\n

\n )}\n
\n
\n
\n \n updateParameter({ isRequired: checked })\n }\n />\n \n
\n
\n \n updateParameter({ isRepeatable: checked })\n }\n />\n \n
\n
\n
\n\n
\n \n {\n updateParameter({ metadata: { tags } });\n }}\n placeholder=\"Add tags\"\n />\n
\n\n \n\n {/* Dependencies Section */}\n
\n
\n \n \n Dependencies\n \n \n \n Add\n \n
\n
\n {parameter.dependencies &&\n parameter.dependencies.map((dependency) => (\n \n \n updateDependency(dependency.id, {\n dependencyType: value\n })\n }\n >\n \n \n \n \n Requires\n \n Conflicts\n \n \n \n \n updateDependency(dependency.id, {\n dependsOnParameterId: value\n })\n }\n >\n \n \n \n \n {availableParameters.map((param) => (\n \n {param.name}\n {param.isGlobal && \" (global)\"}\n \n ))}\n \n \n removeDependency(dependency.id)}\n >\n \n \n
\n ))}\n
\n
\n\n \n\n {/* Validations Section */}\n
\n
\n \n \n
\n
\n {parameter.validations &&\n parameter.validations.map((validation) => (\n \n {\n const updatedValidations = parameter.validations?.map(\n (v) =>\n v.id === validation.id\n ? { ...v, validationType: value }\n : v\n );\n updateParameter({\n validations: updatedValidations\n });\n }}\n >\n \n \n \n \n Min Length\n Max Length\n Min Value\n Max Value\n Regex\n \n \n {\n const updatedValidations = parameter.validations?.map(\n (v) =>\n v.id === validation.id\n ? { ...v, validationValue: e.target.value }\n : v\n );\n updateParameter({\n validations: updatedValidations\n });\n }}\n placeholder=\"Value\"\n className=\"flex-1\"\n />\n {\n const updatedValidations =\n parameter.validations?.filter(\n (v) => v.id !== validation.id\n );\n updateParameter({\n validations: updatedValidations\n });\n }}\n >\n \n \n
\n ))}\n
\n \n\n {/* Enum Values Section */}\n {parameter.dataType === \"Enum\" && (\n <>\n \n
\n
\n \n Enum Values\n \n \n
\n
\n {parameter.enumValues.map((enumValue) => (\n \n {\n const updatedEnumValues = parameter.enumValues.map(\n (ev) =>\n ev.id === enumValue.id\n ? { ...ev, value: e.target.value }\n : ev\n );\n updateParameter({\n enumValues: updatedEnumValues\n });\n }}\n placeholder=\"value\"\n className=\"flex-1\"\n />\n {\n const updatedEnumValues = parameter.enumValues.map(\n (ev) =>\n ev.id === enumValue.id\n ? { ...ev, displayName: e.target.value }\n : ev\n );\n updateParameter({\n enumValues: updatedEnumValues\n });\n }}\n placeholder=\"Display Name\"\n className=\"flex-1\"\n />\n {\n const updatedEnumValues = parameter.enumValues.map(\n (ev) =>\n ev.id === enumValue.id\n ? { ...ev, isDefault: checked }\n : ev\n );\n updateParameter({\n enumValues: updatedEnumValues\n });\n }}\n />\n {\n const updatedEnumValues = parameter.enumValues.filter(\n (ev) => ev.id !== enumValue.id\n );\n updateParameter({\n enumValues: updatedEnumValues\n });\n }}\n >\n \n \n
\n ))}\n
\n \n \n )}\n \n\n \n \n \n \n
\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/dialogs/parameter-details-dialog.tsx" + }, + { + "path": "registry/commandly/tool-editor/dialogs/exclusion-groups-dialog.tsx", + "content": "import { Button } from \"@/components/ui/button\";\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle\n} from \"@/components/ui/dialog\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue\n} from \"@/components/ui/select\";\nimport { ExclusionGroup } from \"@/registry/commandly/lib/types/commandly\";\nimport { PlusIcon, TrashIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useStore } from \"@tanstack/react-store\";\nimport {\n toolBuilderStore,\n toolBuilderActions,\n toolBuilderSelectors\n} from \"../tool-editor.store\";\n\nexport function ExclusionGroupsDialog() {\n const selectedCommand = useStore(\n toolBuilderStore,\n (state) => state.selectedCommand\n );\n const open = useStore(\n toolBuilderStore,\n (state) => state.dialogs.exclusionGroups\n );\n\n const exclusionGroups = useStore(toolBuilderStore, (state) => {\n const commandId = state.selectedCommand?.id;\n return commandId\n ? toolBuilderSelectors.getExclusionGroupsForCommand(state, commandId)\n : [];\n });\n const parameters = useStore(toolBuilderStore, (state) => {\n const commandId = state.selectedCommand?.id;\n return commandId\n ? toolBuilderSelectors.getParametersForCommand(state, commandId)\n : [];\n });\n\n const [editingGroup, setEditingGroup] = useState<\n Partial | undefined\n >();\n\n const handleAddGroup = () => {\n setEditingGroup({\n name: \"\",\n exclusionType: \"mutual_exclusive\",\n parameterIds: [],\n commandId: selectedCommand?.id\n });\n };\n\n const handleSaveGroup = () => {\n if (!editingGroup?.name || !editingGroup.exclusionType) return;\n\n if (editingGroup.id) {\n toolBuilderActions.updateExclusionGroup(editingGroup as ExclusionGroup);\n } else {\n toolBuilderActions.addExclusionGroup(\n editingGroup as Omit\n );\n }\n setEditingGroup(undefined);\n };\n\n return (\n \n toolBuilderActions.setDialogOpen(\"exclusionGroups\", open)\n }\n >\n \n \n Exclusion Groups\n \n\n
\n {exclusionGroups.map((group) => (\n \n
\n

{group.name}

\n
\n {group.parameterIds.map((id) => {\n const param = parameters.find((p) => p.id === id);\n return (\n param && (\n \n {param.name}\n \n )\n );\n })}\n
\n
\n
\n setEditingGroup(group)}\n >\n Edit\n \n \n toolBuilderActions.removeExclusionGroup(group.id!)\n }\n >\n \n \n
\n
\n ))}\n\n {!editingGroup && (\n \n )}\n\n {editingGroup && (\n
\n
\n \n \n setEditingGroup({ ...editingGroup, name: e.target.value })\n }\n placeholder=\"Group name\"\n />\n
\n\n
\n \n \n setEditingGroup({\n ...editingGroup,\n exclusionType: value as ExclusionGroup[\"exclusionType\"]\n })\n }\n >\n \n \n \n \n \n Mutually Exclusive\n \n \n Required One Of\n \n \n \n
\n\n
\n \n \n setEditingGroup({\n ...editingGroup,\n parameterIds: [\n ...(editingGroup.parameterIds || []),\n value\n ]\n })\n }\n >\n \n \n \n \n {parameters\n .filter((p) => !editingGroup.parameterIds?.includes(p.id))\n .map((param) => (\n \n {param.name}\n \n ))}\n \n \n\n
\n {editingGroup.parameterIds?.map((id) => {\n const param = parameters.find((p) => p.id === id);\n return (\n param && (\n \n {param.name}\n \n setEditingGroup({\n ...editingGroup,\n parameterIds: editingGroup.parameterIds?.filter(\n (pid) => pid !== id\n )\n })\n }\n >\n \n \n \n )\n );\n })}\n
\n
\n\n
\n setEditingGroup(undefined)}\n >\n Cancel\n \n \n
\n
\n )}\n \n
\n \n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/dialogs/exclusion-groups-dialog.tsx" + }, + { + "path": "registry/commandly/tool-editor/dialogs/tool-details-dialog.tsx", + "content": "import { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter\n} from \"@/components/ui/dialog\";\nimport { SettingsIcon } from \"lucide-react\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { MultiSelect } from \"@/components/ui/multi-select\";\nimport {\n SupportedToolInputType,\n SupportedToolOutputType\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { toolBuilderActions, toolBuilderStore } from \"../tool-editor.store\";\nimport { TagsInput } from \"@/registry/commandly/ui/tags-input\";\n\nconst supportedInputOptions = [\n { value: \"StandardInput\", label: \"Standard Input\" },\n { value: \"Parameter\", label: \"Parameter\" }\n];\n\nconst supportedOutputOptions = [\n { value: \"StandardOutput\", label: \"Standard Output\" },\n { value: \"File\", label: \"File\" }\n];\n\nexport function ToolDetailsDialog() {\n const tool = useStore(toolBuilderStore, (state) => state.tool);\n\n const isOpen = useStore(toolBuilderStore, (state) => state.dialogs.editTool);\n return (\n \n toolBuilderActions.setDialogOpen(\"editTool\", open)\n }\n >\n \n \n \n \n Edit Tool Settings\n \n \n
\n
\n
\n \n {\n const newName = e.target.value;\n const prevName = tool.name;\n toolBuilderActions.updateTool({\n name: newName,\n commands: tool.commands.map((cmd) =>\n cmd.name === prevName ? { ...cmd, name: newName } : cmd\n )\n });\n }}\n />\n
\n
\n \n \n toolBuilderActions.updateTool({ displayName: e.target.value })\n }\n />\n
\n
\n
\n
\n \n \n toolBuilderActions.updateTool({ version: e.target.value })\n }\n />\n
\n
\n \n \n toolBuilderActions.updateTool({ category: e.target.value })\n }\n />\n
\n
\n
\n
\n \n \n toolBuilderActions.updateTool({\n supportedInput: value.map(\n (v) => v as SupportedToolInputType\n )\n })\n }\n defaultValue={tool.supportedInput}\n placeholder=\"Select input types\"\n variant=\"default\"\n maxCount={0}\n />\n
\n
\n \n \n toolBuilderActions.updateTool({\n supportedOutput: value.map(\n (v) => v as SupportedToolOutputType\n )\n })\n }\n defaultValue={tool.supportedOutput}\n placeholder=\"Select output types\"\n variant=\"default\"\n maxCount={0}\n />\n
\n
\n\n
\n \n {\n toolBuilderActions.updateTool({ tags });\n }}\n placeholder=\"Add tags\"\n />\n
\n\n
\n \n \n toolBuilderActions.updateTool({ description: e.target.value })\n }\n rows={3}\n />\n
\n
\n \n toolBuilderActions.setDialogOpen(\"editTool\", false)}\n >\n Close\n \n \n
\n \n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/dialogs/tool-details-dialog.tsx" + }, + { + "path": "registry/commandly/tool-editor/dialogs/command-dialog.tsx", + "content": "import { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport { Switch } from \"@/components/ui/switch\";\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter,\n DialogDescription\n} from \"@/components/ui/dialog\";\nimport { Command } from \"@/registry/commandly/lib/types/commandly\";\nimport { TerminalIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { toolBuilderActions, toolBuilderStore } from \"../tool-editor.store\";\n\ninterface CommandDialogProps {\n isOpen: boolean;\n onOpenChange: (open: boolean) => void;\n}\n\nexport function CommandDialog({ isOpen, onOpenChange }: CommandDialogProps) {\n const command = useStore(toolBuilderStore, (state) => state.editingCommand);\n const toolName = useStore(toolBuilderStore, (state) => state.tool.name);\n const [editCommand, setCommand] = useState(command!);\n\n return (\n \n \n \n \n \n Edit Command Settings\n \n \n Dialog for editing command details\n \n \n
\n
\n
\n \n \n setCommand((prev) => ({\n ...prev,\n name: e.target.value\n }))\n }\n />\n
\n
\n
\n
\n \n \n setCommand((prev) => ({\n ...prev,\n sortOrder: Number.parseInt(e.target.value) || 0\n }))\n }\n />\n
\n
\n {\n setCommand((prev) => ({\n ...prev,\n isDefault: checked\n }));\n }}\n />\n \n
\n
\n
\n \n \n setCommand((prev) => ({ ...prev, description: e.target.value }))\n }\n rows={3}\n />\n
\n
\n \n {\n toolBuilderActions.updateCommand(editCommand.id, editCommand);\n onOpenChange(false);\n }}\n >\n Save & Close\n \n \n
\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/dialogs/command-dialog.tsx" + }, + { + "path": "registry/commandly/tool-editor/dialogs/saved-commands-dialog.tsx", + "content": "import { Button } from \"@/components/ui/button\";\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogFooter\n} from \"@/components/ui/dialog\";\nimport { SaveIcon, CopyIcon, Trash2Icon } from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { SavedCommand } from \"@/registry/commandly/lib/types/commandly\";\nimport { toolBuilderActions, toolBuilderStore } from \"../tool-editor.store\";\nimport { useStore } from \"@tanstack/react-store\";\n\ninterface SavedCommandsDialogProps {\n savedCommands: SavedCommand[];\n onDeleteCommand: (commandId: string) => void;\n}\n\nexport function SavedCommandsDialog({\n savedCommands,\n onDeleteCommand\n}: SavedCommandsDialogProps) {\n const copyCommand = (command: string) => {\n navigator.clipboard.writeText(command);\n toast(\"Command copied!\");\n };\n\n const deleteCommand = (commandId: string) => {\n onDeleteCommand(commandId);\n toast(\"Command Removed\", {\n description: \"Saved command has been removed successfully.\"\n });\n };\n\n const open = useStore(\n toolBuilderStore,\n (state) => state.dialogs.savedCommands\n );\n\n return (\n \n toolBuilderActions.setDialogOpen(\"savedCommands\", false)\n }\n >\n \n \n \n \n Saved Commands\n \n \n\n {savedCommands.length === 0 ? (\n
\n \n

\n No saved commands yet. Generate and save commands to see them\n here.\n

\n
\n ) : (\n
\n {savedCommands &&\n savedCommands.length > 0 &&\n savedCommands.map((savedCommand) => (\n \n
\n copyCommand(savedCommand.command)}\n >\n \n \n deleteCommand(savedCommand.id)}\n >\n \n \n
\n
\n                    {savedCommand.command}\n                  
\n
\n ))}\n \n )}\n\n \n \n toolBuilderActions.setDialogOpen(\"savedCommands\", false)\n }\n >\n Close\n \n \n
\n \n );\n}\n", + "type": "registry:component", + "target": "components/commandly/tool-editor/dialogs/saved-commands-dialog.tsx" + }, + { + "path": "registry/commandly/generated-command.tsx", + "content": "import { useEffect, useState, useMemo } from \"react\";\nimport { TerminalIcon, CopyIcon, SaveIcon } from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { Button } from \"@/components/ui/button\";\nimport { getCommandPath } from \"@/registry/commandly/lib/utils/commandly\";\nimport {\n Parameter,\n ParameterValue,\n Tool,\n Command\n} from \"@/registry/commandly/lib/types/commandly\";\n\ninterface GeneratedCommandProps {\n tool: Tool;\n selectedCommand?: Command;\n parameterValues: Record;\n onSaveCommand?: (command: string) => void;\n}\n\nexport function GeneratedCommand({\n tool,\n selectedCommand,\n parameterValues,\n onSaveCommand\n}: GeneratedCommandProps) {\n selectedCommand = selectedCommand || tool.commands[0];\n const [generatedCommand, setGeneratedCommand] = useState(\"\");\n\n const globalParameters = useMemo(() => {\n return tool.parameters?.filter((p) => p.isGlobal) || [];\n }, [tool]);\n\n const currentParameters = useMemo(() => {\n return (\n tool?.parameters?.filter((p) => p.commandId === selectedCommand.id) || []\n );\n }, [tool, selectedCommand]);\n\n useEffect(() => {\n generateCommand();\n }, [tool, parameterValues, selectedCommand]);\n\n const generateCommand = () => {\n const commandPath = getCommandPath(selectedCommand, tool);\n let command =\n tool.name == commandPath ? tool.name : `${tool.name} ${commandPath}`;\n\n const parametersWithValues: Array<{\n param: Parameter;\n value: ParameterValue;\n }> = [];\n\n globalParameters.forEach((param) => {\n const value = parameterValues[param.id];\n if (value !== undefined && value !== \"\" && value !== false) {\n parametersWithValues.push({ param, value });\n }\n });\n\n currentParameters.forEach((param) => {\n const value = parameterValues[param.id];\n if (\n value !== undefined &&\n value !== \"\" &&\n value !== false &&\n !param.isGlobal\n ) {\n parametersWithValues.push({ param, value });\n }\n });\n\n const positionalParams = parametersWithValues\n .filter(({ param }) => param.parameterType === \"Argument\")\n .sort((a, b) => (a.param.position || 0) - (b.param.position || 0));\n\n parametersWithValues.forEach(({ param, value }) => {\n if (param.parameterType === \"Flag\") {\n if (value === true) {\n const flag = param.shortFlag || param.longFlag;\n if (flag) command += ` ${flag}`;\n }\n } else if (param.parameterType === \"Option\") {\n const flag = param.shortFlag || param.longFlag;\n if (flag) {\n const separator = param.keyValueSeparator ?? \" \";\n command += ` ${flag}${separator}${value}`;\n }\n } else if (param.parameterType === \"Argument\") {\n command += ` ${value}`;\n }\n });\n\n positionalParams.forEach(({ value }) => {\n command += ` ${value}`;\n });\n\n setGeneratedCommand(command);\n };\n\n const copyCommand = () => {\n navigator.clipboard.writeText(generatedCommand);\n toast(\"Command copied!\");\n };\n\n return (\n
\n {tool.commands.length === 0 ? (\n
\n \n

\n No commands available for this tool.\n

\n
\n ) : generatedCommand ? (\n
\n
\n {generatedCommand}\n
\n
\n \n {onSaveCommand && (\n onSaveCommand(generatedCommand)}\n variant=\"outline\"\n className=\"flex-1\"\n >\n \n Save Command\n \n )}\n
\n
\n ) : (\n
\n \n

\n Configure parameters to generate the command.\n

\n
\n )}\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/generated-command.tsx" + }, + { + "path": "registry/commandly/runtime-preview.tsx", + "content": "import { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\n\nimport { Badge } from \"@/components/ui/badge\";\nimport { Switch } from \"@/components/ui/switch\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue\n} from \"@/components/ui/select\";\nimport { InfoIcon } from \"lucide-react\";\nimport {\n Parameter,\n ParameterValue\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { Command, Tool } from \"@/registry/commandly/lib/types/commandly\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger\n} from \"@/components/ui/tooltip\";\nimport React from \"react\";\n\nconst findDefaultCommand = (tool: Tool): Command | null => {\n const defaultCommand = tool.commands.find((command) => command.isDefault);\n if (defaultCommand) return defaultCommand;\n\n const nameMatchCommand = tool.commands.find(\n (command) => command.name.toLowerCase() === tool.name.toLowerCase()\n );\n if (nameMatchCommand) return nameMatchCommand;\n\n return tool.commands.length > 0 ? tool.commands[0] : null;\n};\n\ninterface RuntimePreviewProps {\n selectedCommand?: Command | null;\n tool: Tool;\n parameterValues: Record;\n updateParameterValue: (parameterId: string, value: ParameterValue) => void;\n}\n\nexport function RuntimePreview({\n selectedCommand: providedCommand,\n tool,\n parameterValues,\n updateParameterValue\n}: RuntimePreviewProps) {\n const selectedCommand = providedCommand ?? findDefaultCommand(tool);\n\n const renderParameterInput = (parameter: Parameter) => {\n const value = parameterValues[parameter.id] || parameter.defaultValue || \"\";\n\n switch (parameter.parameterType) {\n case \"Flag\":\n return (\n
\n \n updateParameterValue(parameter.id, checked)\n }\n />\n \n {parameter.isGlobal && (\n \n global\n \n )}\n
\n );\n\n case \"Option\":\n if (parameter.dataType === \"Enum\") {\n return (\n
\n \n \n updateParameterValue(parameter.id, newValue)\n }\n >\n \n \n \n \n {parameter.enumValues.map((enumValue) => (\n \n {enumValue.displayName || enumValue.value}\n \n ))}\n \n \n
\n );\n } else if (parameter.dataType === \"Boolean\") {\n return (\n
\n \n updateParameterValue(parameter.id, checked.toString())\n }\n />\n \n {parameter.isGlobal && (\n \n global\n \n )}\n
\n );\n } else {\n return (\n
\n
\n \n {parameter.isGlobal && (\n \n global\n \n )}\n
\n \n updateParameterValue(parameter.id, e.target.value)\n }\n placeholder=\"Enter value\"\n />\n
\n );\n }\n\n case \"Argument\":\n return (\n
\n \n \n updateParameterValue(parameter.id, e.target.value)\n }\n placeholder=\"Enter value\"\n />\n
\n );\n\n default:\n return null;\n }\n };\n\n return (\n \n {selectedCommand && tool.commands.length === 0 ? (\n

\n No commands available for this tool.\n

\n ) : (\n
\n {tool.parameters.length > 0 ? (\n tool.parameters\n .filter(\n (param) =>\n param.commandId === selectedCommand?.id || param.isGlobal\n )\n .map(renderParameterInput)\n ) : (\n

\n No parameters available for this command.\n

\n )}\n
\n )}\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/runtime-preview.tsx" + }, + { + "path": "registry/commandly/json-output.tsx", + "content": "import { useEffect, useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { CheckIcon, ChevronsUpDownIcon, CopyIcon } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger\n} from \"@/components/ui/popover\";\nimport {\n Command as UICommand,\n CommandGroup,\n CommandItem,\n CommandList\n} from \"@/components/ui/command\";\nimport {\n Card,\n CardAction,\n CardContent,\n CardHeader,\n CardTitle\n} from \"@/components/ui/card\";\nimport { exportToStructuredJSON } from \"@/registry/commandly/lib/utils/commandly\";\nimport { convertToNestedStructure } from \"@/registry/commandly/lib/utils/commandly-nested\";\nimport { Tool } from \"@/registry/commandly/lib/types/commandly\";\nimport { ScrollArea, ScrollBar } from \"@/components/ui/scroll-area\";\nimport { toast } from \"sonner\";\nimport { useQueryState } from \"nuqs\";\n\nconst jsonOptions = [\n { value: \"nested\", label: \"Nested\" },\n { value: \"flat\", label: \"Flat\" }\n];\n\ninterface JsonTypeComponentProps {\n tool: Tool;\n}\n\nexport function JsonOutput({ tool }: JsonTypeComponentProps) {\n const [open, setOpen] = useState(false);\n const [jsonString, setJsonString] = useState();\n const [jsonType, setJsonType] = useQueryState(\"output\", {\n defaultValue: \"flat\"\n });\n useEffect(() => {\n const config =\n jsonType === \"flat\"\n ? exportToStructuredJSON(tool)\n : convertToNestedStructure(tool);\n setJsonString(JSON.stringify(config, null, 2));\n }, [jsonType, tool]);\n\n return (\n \n \n \n Output type: \n \n \n \n {jsonOptions.find((option) => option.value === jsonType)?.label}\n \n \n \n \n \n \n \n {jsonOptions.map((option) => (\n {\n setJsonType(currentValue);\n setOpen(false);\n }}\n >\n {option.label}\n \n \n ))}\n \n \n \n \n \n \n {\n navigator.clipboard.writeText(jsonString!);\n toast(\"Copied!\");\n }}\n >\n \n \n \n \n [data-radix-scroll-area-viewport]]:max-h-[calc(100vh-320px)] max-w-full\"\n type=\"hover\"\n >\n
\n            {jsonString}\n          
\n \n \n \n
\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/json-output.tsx" + }, + { + "path": "registry/commandly/lib/types/commandly.ts", + "content": "import { z } from \"zod/v4\";\n\nexport const CommandSchema = z.object({\n id: z.uuidv7(),\n parentCommandId: z.uuidv7().optional(),\n name: z.string(),\n description: z.string(),\n isDefault: z.boolean(),\n sortOrder: z.number()\n});\nexport type Command = z.infer;\n\nexport const ParameterEnumValueSchema = z.object({\n id: z.uuidv7(),\n parameterId: z.uuidv7(),\n value: z.string(),\n displayName: z.string(),\n description: z.string(),\n isDefault: z.boolean(),\n sortOrder: z.number()\n});\nexport type ParameterEnumValue = z.infer;\n\nexport const ParameterValidationTypeSchema = z.enum([\n \"min_length\",\n \"max_length\",\n \"min_value\",\n \"max_value\",\n \"regex\"\n]);\nexport type ParameterValidationType = z.infer<\n typeof ParameterValidationTypeSchema\n>;\n\nexport const ParameterValidationSchema = z.object({\n id: z.string(),\n parameterId: z.string(),\n validationType: ParameterValidationTypeSchema,\n validationValue: z.string(),\n errorMessage: z.string()\n});\nexport type ParameterValidation = z.infer;\nexport const ParameterDependencyTypeSchema = z.enum([\n \"requires\",\n \"conflicts_with\"\n]);\nexport type ParameterDependencyType = z.infer<\n typeof ParameterDependencyTypeSchema\n>;\nexport const ParameterDependencySchema = z.object({\n id: z.string(),\n parameterId: z.string(),\n dependsOnParameterId: z.string(),\n dependencyType: ParameterDependencyTypeSchema,\n conditionValue: z.string().optional()\n});\n\nexport type ParameterValue = string | number | boolean;\n\nexport type ParameterDependency = z.infer;\n\nexport const ParameterMetadataSchema = z.object({\n tags: z.array(z.string()).optional()\n});\nexport type ParameterMetadata = z.infer;\nexport const ParameterTypeSchema = z.enum([\"Flag\", \"Option\", \"Argument\"]);\nexport type ParameterType = z.infer;\n\nexport const ParameterDataTypeSchema = z.enum([\n \"String\",\n \"Number\",\n \"Boolean\",\n \"Enum\"\n]);\nexport type ParameterDataType = z.infer;\n\nexport const ParameterSchema = z.object({\n id: z.string(),\n name: z.string(),\n commandId: z.uuidv7().optional(),\n description: z.string(),\n metadata: ParameterMetadataSchema.optional(),\n parameterType: ParameterTypeSchema,\n dataType: ParameterDataTypeSchema,\n isRequired: z.boolean(),\n isRepeatable: z.boolean(),\n isGlobal: z.boolean(),\n defaultValue: z.string().optional(),\n shortFlag: z.string().optional(),\n longFlag: z.string(),\n position: z.number().optional(),\n sortOrder: z.number().optional(),\n arraySeparator: z.string().optional(),\n keyValueSeparator: z.string().optional(),\n enumValues: z.array(ParameterEnumValueSchema),\n validations: z.array(ParameterValidationSchema).optional(),\n dependencies: z.array(ParameterDependencySchema).optional()\n});\nexport type Parameter = z.infer;\n\nexport const ExclusionTypeSchema = z.enum([\n \"mutual_exclusive\",\n \"required_one_of\"\n]);\nexport type ExclusionType = z.infer;\n\nexport const ExclusionGroupSchema = z.object({\n id: z.string().optional(),\n commandId: z.string().optional(),\n name: z.string(),\n exclusionType: ExclusionTypeSchema,\n parameterIds: z.array(z.string())\n});\nexport type ExclusionGroup = z.infer;\n\nexport const SavedCommandSchema = z.object({\n id: z.string(),\n command: z.string()\n});\nexport type SavedCommand = z.infer;\n\nexport const SupportedToolInputTypeSchema = z.enum([\n \"StandardInput\",\n \"Parameter\"\n]);\nexport type SupportedToolInputType = z.infer<\n typeof SupportedToolInputTypeSchema\n>;\n\nexport const SupportedToolOutputTypeSchema = z.enum([\n \"StandardOutput\",\n \"File\",\n \"Directory\"\n]);\nexport type SupportedToolOutputType = z.infer<\n typeof SupportedToolOutputTypeSchema\n>;\n\nexport const ToolSchema = z.object({\n id: z.string().optional(),\n name: z.string(),\n displayName: z.string(),\n description: z.string().optional(),\n version: z.string().optional(),\n category: z.string().optional(),\n tags: z.array(z.string()).optional(),\n url: z.url().optional(),\n commands: z.array(CommandSchema),\n parameters: z.array(ParameterSchema),\n exclusionGroups: z.array(ExclusionGroupSchema),\n supportedInput: z.array(SupportedToolInputTypeSchema),\n supportedOutput: z.array(SupportedToolOutputTypeSchema)\n});\nexport type Tool = z.infer;\n\nexport const AIParseRequestSchema = z.object({\n helpText: z.string(),\n toolName: z.string().optional()\n});\nexport type AIParseRequest = z.infer;\n\nexport const AIParseResponseSchema = z.object({\n success: z.boolean(),\n data: ToolSchema.optional(),\n error: z.string().optional()\n});\nexport type AIParseResponse = z.infer;\n\nexport const newToolSchema = z.object({\n displayName: z.string(),\n name: z.string(),\n version: z.string().optional(),\n description: z.string().optional(),\n url: z.url().optional()\n});\nexport type ManualNewTool = z.infer;\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/types/commandly-nested.ts", + "content": "import { ParameterValidation, ParameterDependencyType, ParameterType, ParameterDataType, ParameterMetadata, ExclusionType, SupportedToolInputType, SupportedToolOutputType } from \"../../types\";\n\nexport interface NestedCommand {\n name: string;\n description: string;\n isDefault: boolean;\n sortOrder: number;\n parameters: NestedParameter[];\n subcommands: NestedCommand[];\n}\n\nexport interface NestedParameterEnumValue {\n value: string;\n displayName: string;\n description: string;\n isDefault: boolean;\n sortOrder: number;\n}\n\nexport type NestedParameterValidation = Omit<\n ParameterValidation,\n \"id\" | \"parameterId\"\n>;\n\nexport interface NestedParameterDependency {\n dependsOnParameter: string;\n dependencyType: ParameterDependencyType;\n conditionValue?: string;\n}\n\nexport interface NestedParameter {\n name: string;\n description: string;\n parameterType: ParameterType;\n dataType: ParameterDataType;\n metadata?: ParameterMetadata;\n isRequired: boolean;\n isRepeatable: boolean;\n isGlobal: boolean;\n defaultValue?: string;\n shortFlag?: string;\n longFlag: string;\n position?: number;\n sortOrder?: number;\n arraySeparator?: string;\n keyValueSeparator?: string;\n enumValues: NestedParameterEnumValue[];\n validations: NestedParameterValidation[];\n dependencies: NestedParameterDependency[];\n}\n\nexport interface NestedExclusionGroup {\n name: string;\n exclusionType: ExclusionType;\n parameters: string[];\n}\n\nexport interface NestedTool {\n name: string;\n displayName: string;\n description?: string;\n version?: string;\n url?: string;\n globalParameters: NestedParameter[];\n commands: NestedCommand[];\n exclusionGroups: NestedExclusionGroup[];\n supportedInput: SupportedToolInputType[];\n supportedOutput: SupportedToolOutputType[];\n}\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly.ts", + "content": "import type {\n Command,\n Parameter,\n SavedCommand,\n Tool\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport const buildCommandHierarchy = (commands: Command[]): Command[] => {\n return commands.sort((a, b) => a.sortOrder - b.sortOrder);\n};\n\nexport const getCommandPath = (command: Command, tool: Tool): string => {\n const findCommandPath = (\n targetId: string,\n commands: Command[],\n path: string[] = []\n ): string[] | null => {\n for (const cmd of commands) {\n if (cmd.name === targetId) {\n return [...path, cmd.name];\n }\n\n const childCommands = commands.filter(\n (c) => c.parentCommandId === cmd.id\n );\n if (childCommands.length > 0) {\n const subPath = findCommandPath(targetId, childCommands, [\n ...path,\n cmd.name\n ]);\n if (subPath) {\n return subPath;\n }\n }\n }\n return null;\n };\n\n const rootCommands = tool.commands.filter((c) => !c.parentCommandId);\n const path = findCommandPath(command.name, rootCommands);\n\n if (!path) return command.name;\n\n if (command.name === tool.name && command.isDefault) {\n return tool.name;\n }\n\n const rootCommand = tool.commands.find((c) => c.name === tool.name);\n if (rootCommand?.isDefault && path[0] === tool.name) {\n path[0] = tool.name;\n }\n\n return path.join(\" \");\n};\n\nexport const getAllSubcommands = (\n commandId: string,\n commands: Command[]\n): Command[] => {\n const result: Command[] = [];\n\n const findSubcommands = (parentId: string) => {\n commands.forEach((cmd) => {\n if (cmd.parentCommandId === parentId) {\n result.push(cmd);\n findSubcommands(cmd.id);\n }\n });\n };\n\n findSubcommands(commandId);\n return result;\n};\n\nexport const exportToStructuredJSON = (tool: Tool) => {\n const flattenCommand = (cmd: Command) => {\n return { ...cmd };\n };\n\n return {\n name: tool.name,\n displayName: tool.displayName,\n description: tool.description,\n version: tool.version,\n commands: tool.commands.map(flattenCommand),\n parameters: tool.parameters,\n exclusionGroups: tool.exclusionGroups,\n supportedInput: tool.supportedInput,\n supportedOutput: tool.supportedOutput\n };\n};\n\nexport const flattenImportedData = (importedData: any): Tool => {\n const {\n name,\n displayName,\n parameters = [],\n commands = [],\n exclusionGroups = [],\n supportedInput = [],\n supportedOutput = []\n } = importedData;\n\n const allParameters: Parameter[] = [...parameters];\n\n const flattenCommandParameters = (\n command: any,\n parentId?: string\n ): Command[] => {\n const { parameters = [], subcommands = [], ...commandData } = command;\n\n parameters.forEach((param: any) => {\n allParameters.push({\n ...param,\n commandId: command.id,\n isGlobal: !command.name\n });\n });\n\n const flatCommand: Command = {\n ...commandData,\n parentCommandId: parentId\n };\n\n const flatCommands = [flatCommand];\n\n subcommands.forEach((subcmd: any) => {\n flatCommands.push(...flattenCommandParameters(subcmd, command.name));\n });\n\n return flatCommands;\n };\n\n const flatCommands: Command[] = [];\n commands.forEach((cmd: any) => {\n flatCommands.push(...flattenCommandParameters(cmd));\n });\n\n return {\n name: name,\n displayName: displayName || name,\n commands: flatCommands,\n parameters: allParameters,\n exclusionGroups,\n supportedInput: supportedInput,\n supportedOutput: supportedOutput\n };\n};\n\nexport const defaultTool = (toolName?: string, displayName?: string): Tool => {\n return {\n name: toolName || \"my-tool\",\n displayName: displayName || \"My Tool\",\n description: undefined,\n version: \"\",\n commands: [\n {\n id: uuidv7(),\n name: toolName || \"my-tool\",\n description: \"Main command\",\n isDefault: true,\n sortOrder: 0\n }\n ],\n parameters: [\n {\n id: \"--help\",\n name: \"Help\",\n description: \"Displays help menu of tool\",\n parameterType: \"Flag\",\n dataType: \"String\",\n isRequired: false,\n isGlobal: true,\n shortFlag: \"-h\",\n longFlag: \"--help\",\n isRepeatable: false,\n enumValues: [],\n validations: [],\n dependencies: []\n }\n ],\n exclusionGroups: [],\n supportedInput: [\"StandardInput\"],\n supportedOutput: [\"StandardOutput\"]\n };\n};\n\nexport const validateDefaultValue = (\n parameter: Parameter\n): { isValid: boolean; error?: string } => {\n const { defaultValue, validations, dataType } = parameter;\n\n if (!defaultValue || !validations) return { isValid: true };\n\n switch (dataType) {\n case \"Number\":\n if (!/^-?\\d+$/.test(defaultValue)) {\n return { isValid: false, error: \"Default value must be an integer\" };\n }\n break;\n case \"Boolean\":\n if (![\"true\", \"false\", \"1\", \"0\"].includes(defaultValue.toLowerCase())) {\n return {\n isValid: false,\n error: \"Default value must be true/false or 1/0\"\n };\n }\n break;\n }\n\n for (const validation of validations) {\n const value = dataType === \"Number\" ? Number(defaultValue) : defaultValue;\n\n switch (validation.validationType) {\n case \"min_length\":\n if (\n typeof value === \"string\" &&\n value.length < Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too short\"\n };\n }\n break;\n case \"max_length\":\n if (\n typeof value === \"string\" &&\n value.length > Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too long\"\n };\n }\n break;\n case \"min_value\":\n if (\n typeof value === \"number\" &&\n value < Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too small\"\n };\n }\n break;\n case \"max_value\":\n if (\n typeof value === \"number\" &&\n value > Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too large\"\n };\n }\n break;\n case \"regex\":\n if (\n typeof value === \"string\" &&\n !new RegExp(validation.validationValue).test(value)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value doesn't match pattern\"\n };\n }\n break;\n }\n }\n\n return { isValid: true };\n};\n\nexport const createNewCommand = (parentId?: string): Command => {\n return {\n id: uuidv7(),\n parentCommandId: parentId,\n name: randomCommandName(),\n description: \"\",\n isDefault: false,\n sortOrder: 1\n };\n};\n\nexport const createNewParameter = (\n isGlobal: boolean,\n commandId?: string\n): Parameter => {\n return {\n id: uuidv7(),\n name: \"\",\n commandId: isGlobal ? undefined : commandId,\n description: \"\",\n parameterType: \"Option\",\n dataType: \"String\",\n isRequired: false,\n isRepeatable: false,\n isGlobal,\n defaultValue: \"\",\n shortFlag: \"\",\n longFlag: \"\",\n sortOrder: 0,\n arraySeparator: \",\",\n keyValueSeparator: \" \",\n enumValues: [],\n validations: [],\n dependencies: []\n };\n};\n\nexport const getSavedCommandsFromStorage = (toolId: string): SavedCommand[] => {\n try {\n const saved = localStorage.getItem(`saved-${toolId}`);\n return saved ? JSON.parse(saved) : [];\n } catch {\n return [];\n }\n};\n\nexport const saveSavedCommandsToStorage = (\n toolId: string,\n commands: SavedCommand[]\n): void => {\n try {\n localStorage.setItem(toolId, JSON.stringify(commands));\n } catch (error) {\n console.error(\"Failed to save commands to localStorage:\", error);\n }\n};\n\nexport const addSavedCommandToStorage = (\n toolId: string,\n command: SavedCommand\n): void => {\n const existingCommands = getSavedCommandsFromStorage(toolId);\n const updatedCommands = [...existingCommands, command];\n saveSavedCommandsToStorage(toolId, updatedCommands);\n};\n\nexport const removeSavedCommandFromStorage = (\n toolId: string,\n commandId: string\n): void => {\n const existingCommands = getSavedCommandsFromStorage(toolId);\n const updatedCommands = existingCommands.filter(\n (cmd) => cmd.id !== commandId\n );\n saveSavedCommandsToStorage(toolId, updatedCommands);\n};\n\nexport const clearSavedCommandsFromStorage = (toolId: string): void => {\n localStorage.removeItem(toolId);\n};\n\nexport const randomCommandName = () => {\n const characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n let result = \"\";\n const charactersLength = characters.length;\n for (let i = 0; i < 7; i++) {\n result += characters.charAt(Math.floor(Math.random() * charactersLength));\n }\n return result;\n};\n\nexport function generateHashCode(s: string): string {\n let h = 0;\n for (let i = 0; i < s.length; i++)\n h = (Math.imul(31, h) + s.charCodeAt(i)) | 0;\n\n return h.toString();\n}\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly-nested.ts", + "content": "import type {\n Tool,\n Command,\n Parameter\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { NestedCommand, NestedExclusionGroup, NestedParameter, NestedTool } from \"../types/commandly-nested\";\n\n\nexport const convertToNestedStructure = (tool: Tool): NestedTool => {\n const globalParameters = tool.parameters.filter((p) => p.isGlobal);\n\n const convertParameter = (param: Parameter): NestedParameter => {\n const { id, commandId, ...rest } = param;\n return {\n ...rest,\n validations:\n param.validations?.map((v) => {\n return {\n validationType: v.validationType,\n validationValue: v.validationValue,\n errorMessage: v.errorMessage\n };\n }) || [],\n metadata: param.metadata,\n dataType: param.dataType,\n dependencies:\n param.dependencies?.map((dep) => {\n const dependsOnParam = tool.parameters.find(\n (p) => p.id === dep.dependsOnParameterId\n );\n return {\n dependsOnParameter: dependsOnParam?.longFlag || \"\",\n dependencyType: dep.dependencyType,\n conditionValue: dep.conditionValue\n };\n }) || []\n };\n };\n\n const buildNestedCommands = (\n commands: Command[],\n parentId?: string\n ): NestedCommand[] => {\n return commands\n .filter((cmd) => cmd.parentCommandId === parentId)\n .map((cmd) => {\n const commandParameters = tool.parameters.filter(\n (p) => p.commandId === cmd.id && !p.isGlobal\n );\n return {\n name: cmd.name,\n description: cmd.description,\n isDefault: cmd.isDefault,\n sortOrder: cmd.sortOrder,\n parameters: commandParameters.map(convertParameter),\n subcommands: buildNestedCommands(commands, cmd.id)\n };\n });\n };\n\n const nestedExclusionGroups: NestedExclusionGroup[] =\n tool.exclusionGroups.map((group) => {\n return {\n name: group.name,\n exclusionType: group.exclusionType,\n parameters: group.parameterIds.map((pid) => {\n const param = tool.parameters.find((p) => p.id === pid);\n return param?.longFlag || \"\";\n })\n };\n });\n\n return {\n name: tool.name,\n url: tool.url,\n displayName: tool.displayName,\n description: tool.description,\n version: tool.version,\n supportedInput: tool.supportedInput,\n supportedOutput: tool.supportedOutput,\n globalParameters: globalParameters.map(convertParameter),\n commands: buildNestedCommands(tool.commands),\n exclusionGroups: nestedExclusionGroups\n };\n};\n", + "type": "registry:lib" + } + ] +} diff --git a/public/r/ui.json b/public/r/ui.json new file mode 100644 index 0000000..d95823c --- /dev/null +++ b/public/r/ui.json @@ -0,0 +1,60 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "ui", + "type": "registry:block", + "title": "Basic UI", + "description": "Basic components to render previews, command generation and json output", + "dependencies": ["react", "lucide-react", "sonner", "zod"], + "registryDependencies": [ + "button", + "dialog", + "input", + "label", + "select", + "textarea", + "tabs", + "tooltip", + "scroll-area", + "hover-card" + ], + "files": [ + { + "path": "registry/commandly/generated-command.tsx", + "content": "import { useEffect, useState, useMemo } from \"react\";\nimport { TerminalIcon, CopyIcon, SaveIcon } from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { Button } from \"@/components/ui/button\";\nimport { getCommandPath } from \"@/registry/commandly/lib/utils/commandly\";\nimport {\n Parameter,\n ParameterValue,\n Tool,\n Command\n} from \"@/registry/commandly/lib/types/commandly\";\n\ninterface GeneratedCommandProps {\n tool: Tool;\n selectedCommand?: Command;\n parameterValues: Record;\n onSaveCommand?: (command: string) => void;\n}\n\nexport function GeneratedCommand({\n tool,\n selectedCommand,\n parameterValues,\n onSaveCommand\n}: GeneratedCommandProps) {\n selectedCommand = selectedCommand || tool.commands[0];\n const [generatedCommand, setGeneratedCommand] = useState(\"\");\n\n const globalParameters = useMemo(() => {\n return tool.parameters?.filter((p) => p.isGlobal) || [];\n }, [tool]);\n\n const currentParameters = useMemo(() => {\n return (\n tool?.parameters?.filter((p) => p.commandId === selectedCommand.id) || []\n );\n }, [tool, selectedCommand]);\n\n useEffect(() => {\n generateCommand();\n }, [tool, parameterValues, selectedCommand]);\n\n const generateCommand = () => {\n const commandPath = getCommandPath(selectedCommand, tool);\n let command =\n tool.name == commandPath ? tool.name : `${tool.name} ${commandPath}`;\n\n const parametersWithValues: Array<{\n param: Parameter;\n value: ParameterValue;\n }> = [];\n\n globalParameters.forEach((param) => {\n const value = parameterValues[param.id];\n if (value !== undefined && value !== \"\" && value !== false) {\n parametersWithValues.push({ param, value });\n }\n });\n\n currentParameters.forEach((param) => {\n const value = parameterValues[param.id];\n if (\n value !== undefined &&\n value !== \"\" &&\n value !== false &&\n !param.isGlobal\n ) {\n parametersWithValues.push({ param, value });\n }\n });\n\n const positionalParams = parametersWithValues\n .filter(({ param }) => param.parameterType === \"Argument\")\n .sort((a, b) => (a.param.position || 0) - (b.param.position || 0));\n\n parametersWithValues.forEach(({ param, value }) => {\n if (param.parameterType === \"Flag\") {\n if (value === true) {\n const flag = param.shortFlag || param.longFlag;\n if (flag) command += ` ${flag}`;\n }\n } else if (param.parameterType === \"Option\") {\n const flag = param.shortFlag || param.longFlag;\n if (flag) {\n const separator = param.keyValueSeparator ?? \" \";\n command += ` ${flag}${separator}${value}`;\n }\n } else if (param.parameterType === \"Argument\") {\n command += ` ${value}`;\n }\n });\n\n positionalParams.forEach(({ value }) => {\n command += ` ${value}`;\n });\n\n setGeneratedCommand(command);\n };\n\n const copyCommand = () => {\n navigator.clipboard.writeText(generatedCommand);\n toast(\"Command copied!\");\n };\n\n return (\n
\n {tool.commands.length === 0 ? (\n
\n \n

\n No commands available for this tool.\n

\n
\n ) : generatedCommand ? (\n
\n
\n {generatedCommand}\n
\n
\n \n {onSaveCommand && (\n onSaveCommand(generatedCommand)}\n variant=\"outline\"\n className=\"flex-1\"\n >\n \n Save Command\n \n )}\n
\n
\n ) : (\n
\n \n

\n Configure parameters to generate the command.\n

\n
\n )}\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/generated-command.tsx" + }, + { + "path": "registry/commandly/json-output.tsx", + "content": "import { useEffect, useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { CheckIcon, ChevronsUpDownIcon, CopyIcon } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger\n} from \"@/components/ui/popover\";\nimport {\n Command as UICommand,\n CommandGroup,\n CommandItem,\n CommandList\n} from \"@/components/ui/command\";\nimport {\n Card,\n CardAction,\n CardContent,\n CardHeader,\n CardTitle\n} from \"@/components/ui/card\";\nimport { exportToStructuredJSON } from \"@/registry/commandly/lib/utils/commandly\";\nimport { convertToNestedStructure } from \"@/registry/commandly/lib/utils/commandly-nested\";\nimport { Tool } from \"@/registry/commandly/lib/types/commandly\";\nimport { ScrollArea, ScrollBar } from \"@/components/ui/scroll-area\";\nimport { toast } from \"sonner\";\nimport { useQueryState } from \"nuqs\";\n\nconst jsonOptions = [\n { value: \"nested\", label: \"Nested\" },\n { value: \"flat\", label: \"Flat\" }\n];\n\ninterface JsonTypeComponentProps {\n tool: Tool;\n}\n\nexport function JsonOutput({ tool }: JsonTypeComponentProps) {\n const [open, setOpen] = useState(false);\n const [jsonString, setJsonString] = useState();\n const [jsonType, setJsonType] = useQueryState(\"output\", {\n defaultValue: \"flat\"\n });\n useEffect(() => {\n const config =\n jsonType === \"flat\"\n ? exportToStructuredJSON(tool)\n : convertToNestedStructure(tool);\n setJsonString(JSON.stringify(config, null, 2));\n }, [jsonType, tool]);\n\n return (\n \n \n \n Output type: \n \n \n \n {jsonOptions.find((option) => option.value === jsonType)?.label}\n \n \n \n \n \n \n \n {jsonOptions.map((option) => (\n {\n setJsonType(currentValue);\n setOpen(false);\n }}\n >\n {option.label}\n \n \n ))}\n \n \n \n \n \n \n {\n navigator.clipboard.writeText(jsonString!);\n toast(\"Copied!\");\n }}\n >\n \n \n \n \n [data-radix-scroll-area-viewport]]:max-h-[calc(100vh-320px)] max-w-full\"\n type=\"hover\"\n >\n
\n            {jsonString}\n          
\n \n \n \n
\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/json-output.tsx" + }, + { + "path": "registry/commandly/runtime-preview.tsx", + "content": "import { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\n\nimport { Badge } from \"@/components/ui/badge\";\nimport { Switch } from \"@/components/ui/switch\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue\n} from \"@/components/ui/select\";\nimport { InfoIcon } from \"lucide-react\";\nimport {\n Parameter,\n ParameterValue\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { Command, Tool } from \"@/registry/commandly/lib/types/commandly\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger\n} from \"@/components/ui/tooltip\";\nimport React from \"react\";\n\nconst findDefaultCommand = (tool: Tool): Command | null => {\n const defaultCommand = tool.commands.find((command) => command.isDefault);\n if (defaultCommand) return defaultCommand;\n\n const nameMatchCommand = tool.commands.find(\n (command) => command.name.toLowerCase() === tool.name.toLowerCase()\n );\n if (nameMatchCommand) return nameMatchCommand;\n\n return tool.commands.length > 0 ? tool.commands[0] : null;\n};\n\ninterface RuntimePreviewProps {\n selectedCommand?: Command | null;\n tool: Tool;\n parameterValues: Record;\n updateParameterValue: (parameterId: string, value: ParameterValue) => void;\n}\n\nexport function RuntimePreview({\n selectedCommand: providedCommand,\n tool,\n parameterValues,\n updateParameterValue\n}: RuntimePreviewProps) {\n const selectedCommand = providedCommand ?? findDefaultCommand(tool);\n\n const renderParameterInput = (parameter: Parameter) => {\n const value = parameterValues[parameter.id] || parameter.defaultValue || \"\";\n\n switch (parameter.parameterType) {\n case \"Flag\":\n return (\n
\n \n updateParameterValue(parameter.id, checked)\n }\n />\n \n {parameter.isGlobal && (\n \n global\n \n )}\n
\n );\n\n case \"Option\":\n if (parameter.dataType === \"Enum\") {\n return (\n
\n \n \n updateParameterValue(parameter.id, newValue)\n }\n >\n \n \n \n \n {parameter.enumValues.map((enumValue) => (\n \n {enumValue.displayName || enumValue.value}\n \n ))}\n \n \n
\n );\n } else if (parameter.dataType === \"Boolean\") {\n return (\n
\n \n updateParameterValue(parameter.id, checked.toString())\n }\n />\n \n {parameter.isGlobal && (\n \n global\n \n )}\n
\n );\n } else {\n return (\n
\n
\n \n {parameter.isGlobal && (\n \n global\n \n )}\n
\n \n updateParameterValue(parameter.id, e.target.value)\n }\n placeholder=\"Enter value\"\n />\n
\n );\n }\n\n case \"Argument\":\n return (\n
\n \n \n updateParameterValue(parameter.id, e.target.value)\n }\n placeholder=\"Enter value\"\n />\n
\n );\n\n default:\n return null;\n }\n };\n\n return (\n \n {selectedCommand && tool.commands.length === 0 ? (\n

\n No commands available for this tool.\n

\n ) : (\n
\n {tool.parameters.length > 0 ? (\n tool.parameters\n .filter(\n (param) =>\n param.commandId === selectedCommand?.id || param.isGlobal\n )\n .map(renderParameterInput)\n ) : (\n

\n No parameters available for this command.\n

\n )}\n
\n )}\n
\n );\n}\n", + "type": "registry:component", + "target": "components/commandly/runtime-preview.tsx" + }, + { + "path": "registry/commandly/lib/types/commandly.ts", + "content": "import { z } from \"zod/v4\";\n\nexport const CommandSchema = z.object({\n id: z.uuidv7(),\n parentCommandId: z.uuidv7().optional(),\n name: z.string(),\n description: z.string(),\n isDefault: z.boolean(),\n sortOrder: z.number()\n});\nexport type Command = z.infer;\n\nexport const ParameterEnumValueSchema = z.object({\n id: z.uuidv7(),\n parameterId: z.uuidv7(),\n value: z.string(),\n displayName: z.string(),\n description: z.string(),\n isDefault: z.boolean(),\n sortOrder: z.number()\n});\nexport type ParameterEnumValue = z.infer;\n\nexport const ParameterValidationTypeSchema = z.enum([\n \"min_length\",\n \"max_length\",\n \"min_value\",\n \"max_value\",\n \"regex\"\n]);\nexport type ParameterValidationType = z.infer<\n typeof ParameterValidationTypeSchema\n>;\n\nexport const ParameterValidationSchema = z.object({\n id: z.string(),\n parameterId: z.string(),\n validationType: ParameterValidationTypeSchema,\n validationValue: z.string(),\n errorMessage: z.string()\n});\nexport type ParameterValidation = z.infer;\nexport const ParameterDependencyTypeSchema = z.enum([\n \"requires\",\n \"conflicts_with\"\n]);\nexport type ParameterDependencyType = z.infer<\n typeof ParameterDependencyTypeSchema\n>;\nexport const ParameterDependencySchema = z.object({\n id: z.string(),\n parameterId: z.string(),\n dependsOnParameterId: z.string(),\n dependencyType: ParameterDependencyTypeSchema,\n conditionValue: z.string().optional()\n});\n\nexport type ParameterValue = string | number | boolean;\n\nexport type ParameterDependency = z.infer;\n\nexport const ParameterMetadataSchema = z.object({\n tags: z.array(z.string()).optional()\n});\nexport type ParameterMetadata = z.infer;\nexport const ParameterTypeSchema = z.enum([\"Flag\", \"Option\", \"Argument\"]);\nexport type ParameterType = z.infer;\n\nexport const ParameterDataTypeSchema = z.enum([\n \"String\",\n \"Number\",\n \"Boolean\",\n \"Enum\"\n]);\nexport type ParameterDataType = z.infer;\n\nexport const ParameterSchema = z.object({\n id: z.string(),\n name: z.string(),\n commandId: z.uuidv7().optional(),\n description: z.string(),\n metadata: ParameterMetadataSchema.optional(),\n parameterType: ParameterTypeSchema,\n dataType: ParameterDataTypeSchema,\n isRequired: z.boolean(),\n isRepeatable: z.boolean(),\n isGlobal: z.boolean(),\n defaultValue: z.string().optional(),\n shortFlag: z.string().optional(),\n longFlag: z.string(),\n position: z.number().optional(),\n sortOrder: z.number().optional(),\n arraySeparator: z.string().optional(),\n keyValueSeparator: z.string().optional(),\n enumValues: z.array(ParameterEnumValueSchema),\n validations: z.array(ParameterValidationSchema).optional(),\n dependencies: z.array(ParameterDependencySchema).optional()\n});\nexport type Parameter = z.infer;\n\nexport const ExclusionTypeSchema = z.enum([\n \"mutual_exclusive\",\n \"required_one_of\"\n]);\nexport type ExclusionType = z.infer;\n\nexport const ExclusionGroupSchema = z.object({\n id: z.string().optional(),\n commandId: z.string().optional(),\n name: z.string(),\n exclusionType: ExclusionTypeSchema,\n parameterIds: z.array(z.string())\n});\nexport type ExclusionGroup = z.infer;\n\nexport const SavedCommandSchema = z.object({\n id: z.string(),\n command: z.string()\n});\nexport type SavedCommand = z.infer;\n\nexport const SupportedToolInputTypeSchema = z.enum([\n \"StandardInput\",\n \"Parameter\"\n]);\nexport type SupportedToolInputType = z.infer<\n typeof SupportedToolInputTypeSchema\n>;\n\nexport const SupportedToolOutputTypeSchema = z.enum([\n \"StandardOutput\",\n \"File\",\n \"Directory\"\n]);\nexport type SupportedToolOutputType = z.infer<\n typeof SupportedToolOutputTypeSchema\n>;\n\nexport const ToolSchema = z.object({\n id: z.string().optional(),\n name: z.string(),\n displayName: z.string(),\n description: z.string().optional(),\n version: z.string().optional(),\n category: z.string().optional(),\n tags: z.array(z.string()).optional(),\n url: z.url().optional(),\n commands: z.array(CommandSchema),\n parameters: z.array(ParameterSchema),\n exclusionGroups: z.array(ExclusionGroupSchema),\n supportedInput: z.array(SupportedToolInputTypeSchema),\n supportedOutput: z.array(SupportedToolOutputTypeSchema)\n});\nexport type Tool = z.infer;\n\nexport const AIParseRequestSchema = z.object({\n helpText: z.string(),\n toolName: z.string().optional()\n});\nexport type AIParseRequest = z.infer;\n\nexport const AIParseResponseSchema = z.object({\n success: z.boolean(),\n data: ToolSchema.optional(),\n error: z.string().optional()\n});\nexport type AIParseResponse = z.infer;\n\nexport const newToolSchema = z.object({\n displayName: z.string(),\n name: z.string(),\n version: z.string().optional(),\n description: z.string().optional(),\n url: z.url().optional()\n});\nexport type ManualNewTool = z.infer;\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/types/commandly-nested.ts", + "content": "import { ParameterValidation, ParameterDependencyType, ParameterType, ParameterDataType, ParameterMetadata, ExclusionType, SupportedToolInputType, SupportedToolOutputType } from \"../../types\";\n\nexport interface NestedCommand {\n name: string;\n description: string;\n isDefault: boolean;\n sortOrder: number;\n parameters: NestedParameter[];\n subcommands: NestedCommand[];\n}\n\nexport interface NestedParameterEnumValue {\n value: string;\n displayName: string;\n description: string;\n isDefault: boolean;\n sortOrder: number;\n}\n\nexport type NestedParameterValidation = Omit<\n ParameterValidation,\n \"id\" | \"parameterId\"\n>;\n\nexport interface NestedParameterDependency {\n dependsOnParameter: string;\n dependencyType: ParameterDependencyType;\n conditionValue?: string;\n}\n\nexport interface NestedParameter {\n name: string;\n description: string;\n parameterType: ParameterType;\n dataType: ParameterDataType;\n metadata?: ParameterMetadata;\n isRequired: boolean;\n isRepeatable: boolean;\n isGlobal: boolean;\n defaultValue?: string;\n shortFlag?: string;\n longFlag: string;\n position?: number;\n sortOrder?: number;\n arraySeparator?: string;\n keyValueSeparator?: string;\n enumValues: NestedParameterEnumValue[];\n validations: NestedParameterValidation[];\n dependencies: NestedParameterDependency[];\n}\n\nexport interface NestedExclusionGroup {\n name: string;\n exclusionType: ExclusionType;\n parameters: string[];\n}\n\nexport interface NestedTool {\n name: string;\n displayName: string;\n description?: string;\n version?: string;\n url?: string;\n globalParameters: NestedParameter[];\n commands: NestedCommand[];\n exclusionGroups: NestedExclusionGroup[];\n supportedInput: SupportedToolInputType[];\n supportedOutput: SupportedToolOutputType[];\n}\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly.ts", + "content": "import type {\n Command,\n Parameter,\n SavedCommand,\n Tool\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport const buildCommandHierarchy = (commands: Command[]): Command[] => {\n return commands.sort((a, b) => a.sortOrder - b.sortOrder);\n};\n\nexport const getCommandPath = (command: Command, tool: Tool): string => {\n const findCommandPath = (\n targetId: string,\n commands: Command[],\n path: string[] = []\n ): string[] | null => {\n for (const cmd of commands) {\n if (cmd.name === targetId) {\n return [...path, cmd.name];\n }\n\n const childCommands = commands.filter(\n (c) => c.parentCommandId === cmd.id\n );\n if (childCommands.length > 0) {\n const subPath = findCommandPath(targetId, childCommands, [\n ...path,\n cmd.name\n ]);\n if (subPath) {\n return subPath;\n }\n }\n }\n return null;\n };\n\n const rootCommands = tool.commands.filter((c) => !c.parentCommandId);\n const path = findCommandPath(command.name, rootCommands);\n\n if (!path) return command.name;\n\n if (command.name === tool.name && command.isDefault) {\n return tool.name;\n }\n\n const rootCommand = tool.commands.find((c) => c.name === tool.name);\n if (rootCommand?.isDefault && path[0] === tool.name) {\n path[0] = tool.name;\n }\n\n return path.join(\" \");\n};\n\nexport const getAllSubcommands = (\n commandId: string,\n commands: Command[]\n): Command[] => {\n const result: Command[] = [];\n\n const findSubcommands = (parentId: string) => {\n commands.forEach((cmd) => {\n if (cmd.parentCommandId === parentId) {\n result.push(cmd);\n findSubcommands(cmd.id);\n }\n });\n };\n\n findSubcommands(commandId);\n return result;\n};\n\nexport const exportToStructuredJSON = (tool: Tool) => {\n const flattenCommand = (cmd: Command) => {\n return { ...cmd };\n };\n\n return {\n name: tool.name,\n displayName: tool.displayName,\n description: tool.description,\n version: tool.version,\n commands: tool.commands.map(flattenCommand),\n parameters: tool.parameters,\n exclusionGroups: tool.exclusionGroups,\n supportedInput: tool.supportedInput,\n supportedOutput: tool.supportedOutput\n };\n};\n\nexport const flattenImportedData = (importedData: any): Tool => {\n const {\n name,\n displayName,\n parameters = [],\n commands = [],\n exclusionGroups = [],\n supportedInput = [],\n supportedOutput = []\n } = importedData;\n\n const allParameters: Parameter[] = [...parameters];\n\n const flattenCommandParameters = (\n command: any,\n parentId?: string\n ): Command[] => {\n const { parameters = [], subcommands = [], ...commandData } = command;\n\n parameters.forEach((param: any) => {\n allParameters.push({\n ...param,\n commandId: command.id,\n isGlobal: !command.name\n });\n });\n\n const flatCommand: Command = {\n ...commandData,\n parentCommandId: parentId\n };\n\n const flatCommands = [flatCommand];\n\n subcommands.forEach((subcmd: any) => {\n flatCommands.push(...flattenCommandParameters(subcmd, command.name));\n });\n\n return flatCommands;\n };\n\n const flatCommands: Command[] = [];\n commands.forEach((cmd: any) => {\n flatCommands.push(...flattenCommandParameters(cmd));\n });\n\n return {\n name: name,\n displayName: displayName || name,\n commands: flatCommands,\n parameters: allParameters,\n exclusionGroups,\n supportedInput: supportedInput,\n supportedOutput: supportedOutput\n };\n};\n\nexport const defaultTool = (toolName?: string, displayName?: string): Tool => {\n return {\n name: toolName || \"my-tool\",\n displayName: displayName || \"My Tool\",\n description: undefined,\n version: \"\",\n commands: [\n {\n id: uuidv7(),\n name: toolName || \"my-tool\",\n description: \"Main command\",\n isDefault: true,\n sortOrder: 0\n }\n ],\n parameters: [\n {\n id: \"--help\",\n name: \"Help\",\n description: \"Displays help menu of tool\",\n parameterType: \"Flag\",\n dataType: \"String\",\n isRequired: false,\n isGlobal: true,\n shortFlag: \"-h\",\n longFlag: \"--help\",\n isRepeatable: false,\n enumValues: [],\n validations: [],\n dependencies: []\n }\n ],\n exclusionGroups: [],\n supportedInput: [\"StandardInput\"],\n supportedOutput: [\"StandardOutput\"]\n };\n};\n\nexport const validateDefaultValue = (\n parameter: Parameter\n): { isValid: boolean; error?: string } => {\n const { defaultValue, validations, dataType } = parameter;\n\n if (!defaultValue || !validations) return { isValid: true };\n\n switch (dataType) {\n case \"Number\":\n if (!/^-?\\d+$/.test(defaultValue)) {\n return { isValid: false, error: \"Default value must be an integer\" };\n }\n break;\n case \"Boolean\":\n if (![\"true\", \"false\", \"1\", \"0\"].includes(defaultValue.toLowerCase())) {\n return {\n isValid: false,\n error: \"Default value must be true/false or 1/0\"\n };\n }\n break;\n }\n\n for (const validation of validations) {\n const value = dataType === \"Number\" ? Number(defaultValue) : defaultValue;\n\n switch (validation.validationType) {\n case \"min_length\":\n if (\n typeof value === \"string\" &&\n value.length < Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too short\"\n };\n }\n break;\n case \"max_length\":\n if (\n typeof value === \"string\" &&\n value.length > Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too long\"\n };\n }\n break;\n case \"min_value\":\n if (\n typeof value === \"number\" &&\n value < Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too small\"\n };\n }\n break;\n case \"max_value\":\n if (\n typeof value === \"number\" &&\n value > Number(validation.validationValue)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value too large\"\n };\n }\n break;\n case \"regex\":\n if (\n typeof value === \"string\" &&\n !new RegExp(validation.validationValue).test(value)\n ) {\n return {\n isValid: false,\n error: validation.errorMessage || \"Value doesn't match pattern\"\n };\n }\n break;\n }\n }\n\n return { isValid: true };\n};\n\nexport const createNewCommand = (parentId?: string): Command => {\n return {\n id: uuidv7(),\n parentCommandId: parentId,\n name: randomCommandName(),\n description: \"\",\n isDefault: false,\n sortOrder: 1\n };\n};\n\nexport const createNewParameter = (\n isGlobal: boolean,\n commandId?: string\n): Parameter => {\n return {\n id: uuidv7(),\n name: \"\",\n commandId: isGlobal ? undefined : commandId,\n description: \"\",\n parameterType: \"Option\",\n dataType: \"String\",\n isRequired: false,\n isRepeatable: false,\n isGlobal,\n defaultValue: \"\",\n shortFlag: \"\",\n longFlag: \"\",\n sortOrder: 0,\n arraySeparator: \",\",\n keyValueSeparator: \" \",\n enumValues: [],\n validations: [],\n dependencies: []\n };\n};\n\nexport const getSavedCommandsFromStorage = (toolId: string): SavedCommand[] => {\n try {\n const saved = localStorage.getItem(`saved-${toolId}`);\n return saved ? JSON.parse(saved) : [];\n } catch {\n return [];\n }\n};\n\nexport const saveSavedCommandsToStorage = (\n toolId: string,\n commands: SavedCommand[]\n): void => {\n try {\n localStorage.setItem(toolId, JSON.stringify(commands));\n } catch (error) {\n console.error(\"Failed to save commands to localStorage:\", error);\n }\n};\n\nexport const addSavedCommandToStorage = (\n toolId: string,\n command: SavedCommand\n): void => {\n const existingCommands = getSavedCommandsFromStorage(toolId);\n const updatedCommands = [...existingCommands, command];\n saveSavedCommandsToStorage(toolId, updatedCommands);\n};\n\nexport const removeSavedCommandFromStorage = (\n toolId: string,\n commandId: string\n): void => {\n const existingCommands = getSavedCommandsFromStorage(toolId);\n const updatedCommands = existingCommands.filter(\n (cmd) => cmd.id !== commandId\n );\n saveSavedCommandsToStorage(toolId, updatedCommands);\n};\n\nexport const clearSavedCommandsFromStorage = (toolId: string): void => {\n localStorage.removeItem(toolId);\n};\n\nexport const randomCommandName = () => {\n const characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n let result = \"\";\n const charactersLength = characters.length;\n for (let i = 0; i < 7; i++) {\n result += characters.charAt(Math.floor(Math.random() * charactersLength));\n }\n return result;\n};\n\nexport function generateHashCode(s: string): string {\n let h = 0;\n for (let i = 0; i < s.length; i++)\n h = (Math.imul(31, h) + s.charCodeAt(i)) | 0;\n\n return h.toString();\n}\n", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly-nested.ts", + "content": "import type {\n Tool,\n Command,\n Parameter\n} from \"@/registry/commandly/lib/types/commandly\";\nimport { NestedCommand, NestedExclusionGroup, NestedParameter, NestedTool } from \"../types/commandly-nested\";\n\n\nexport const convertToNestedStructure = (tool: Tool): NestedTool => {\n const globalParameters = tool.parameters.filter((p) => p.isGlobal);\n\n const convertParameter = (param: Parameter): NestedParameter => {\n const { id, commandId, ...rest } = param;\n return {\n ...rest,\n validations:\n param.validations?.map((v) => {\n return {\n validationType: v.validationType,\n validationValue: v.validationValue,\n errorMessage: v.errorMessage\n };\n }) || [],\n metadata: param.metadata,\n dataType: param.dataType,\n dependencies:\n param.dependencies?.map((dep) => {\n const dependsOnParam = tool.parameters.find(\n (p) => p.id === dep.dependsOnParameterId\n );\n return {\n dependsOnParameter: dependsOnParam?.longFlag || \"\",\n dependencyType: dep.dependencyType,\n conditionValue: dep.conditionValue\n };\n }) || []\n };\n };\n\n const buildNestedCommands = (\n commands: Command[],\n parentId?: string\n ): NestedCommand[] => {\n return commands\n .filter((cmd) => cmd.parentCommandId === parentId)\n .map((cmd) => {\n const commandParameters = tool.parameters.filter(\n (p) => p.commandId === cmd.id && !p.isGlobal\n );\n return {\n name: cmd.name,\n description: cmd.description,\n isDefault: cmd.isDefault,\n sortOrder: cmd.sortOrder,\n parameters: commandParameters.map(convertParameter),\n subcommands: buildNestedCommands(commands, cmd.id)\n };\n });\n };\n\n const nestedExclusionGroups: NestedExclusionGroup[] =\n tool.exclusionGroups.map((group) => {\n return {\n name: group.name,\n exclusionType: group.exclusionType,\n parameters: group.parameterIds.map((pid) => {\n const param = tool.parameters.find((p) => p.id === pid);\n return param?.longFlag || \"\";\n })\n };\n });\n\n return {\n name: tool.name,\n url: tool.url,\n displayName: tool.displayName,\n description: tool.description,\n version: tool.version,\n supportedInput: tool.supportedInput,\n supportedOutput: tool.supportedOutput,\n globalParameters: globalParameters.map(convertParameter),\n commands: buildNestedCommands(tool.commands),\n exclusionGroups: nestedExclusionGroups\n };\n};\n", + "type": "registry:lib" + } + ] +} diff --git a/public/specification/flat.json b/public/specification/flat.json index 274889d..051be74 100644 --- a/public/specification/flat.json +++ b/public/specification/flat.json @@ -247,7 +247,6 @@ "required": [ "id", "name", - "commandId", "description", "parameterType", "dataType", diff --git a/public/tools-collection/shuffledns.json b/public/tools-collection/shuffledns.json index e1f2140..e345a9f 100644 --- a/public/tools-collection/shuffledns.json +++ b/public/tools-collection/shuffledns.json @@ -5,7 +5,7 @@ "commands": [ { "id": "11111111-1111-7aaa-8bbb-111111111111", - "name": "shuffleDNS", + "name": "shuffledns", "description": "shuffleDNS is a wrapper around massdns written in go that allows you to enumerate valid subdomains using active bruteforce as well as resolve subdomains with wildcard handling and easy input-output support.", "isDefault": true, "sortOrder": 1 diff --git a/registry.json b/registry.json new file mode 100644 index 0000000..918c93b --- /dev/null +++ b/registry.json @@ -0,0 +1,285 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry.json", + "name": "commandly", + "homepage": "https://commandly.divyeshio.in", + "items": [ + { + "name": "ui", + "type": "registry:block", + "title": "Basic UI", + "description": "Basic components to render previews, command generation and json output", + "dependencies": ["react", "lucide-react", "sonner", "zod"], + "registryDependencies": [ + "button", + "dialog", + "input", + "label", + "select", + "textarea", + "tabs", + "tooltip", + "scroll-area", + "hover-card" + ], + "files": [ + { + "path": "registry/commandly/generated-command.tsx", + "type": "registry:component", + "target": "components/commandly/generated-command.tsx" + }, + { + "path": "registry/commandly/json-output.tsx", + "type": "registry:component", + "target": "components/commandly/json-output.tsx" + }, + { + "path": "registry/commandly/runtime-preview.tsx", + "type": "registry:component", + "target": "components/commandly/runtime-preview.tsx" + }, + { + "path": "registry/commandly/lib/types/commandly.ts", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/types/commandly-nested.ts", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly.ts", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly-nested.ts", + "type": "registry:lib" + } + ] + }, + { + "name": "tool-editor", + "type": "registry:block", + "title": "Tool Editor", + "description": "A comprehensive tool editor for creating and editing CLI tools with parameter management, command trees, and preview functionality.", + "dependencies": [ + "react", + "zod", + "lucide-react", + "sonner", + "@tanstack/react-store" + ], + "registryDependencies": [ + "button", + "dialog", + "input", + "label", + "select", + "textarea", + "tabs", + "tooltip", + "scroll-area", + "hover-card", + "https://shadcn-extension.vercel.app/registry/tags-input.json" + ], + "files": [ + { + "path": "registry/commandly/tool-editor/tool-editor.tsx", + "type": "registry:component", + "target": "components/commandly/tool-editor/tool-editor.tsx" + }, + { + "path": "registry/commandly/tool-editor/tool-editor.store.ts", + "type": "registry:component", + "target": "components/commandly/tool-editor/tool-editor.store.tsx" + }, + { + "path": "registry/commandly/tool-editor/command-tree.tsx", + "type": "registry:component", + "target": "components/commandly/tool-editor/command-tree.tsx" + }, + { + "path": "registry/commandly/tool-editor/parameter-list.tsx", + "type": "registry:component", + "target": "components/commandly/tool-editor/parameter-list.tsx" + }, + { + "path": "registry/commandly/tool-editor/preview-tabs.tsx", + "type": "registry:component", + "target": "components/commandly/tool-editor/preview-tabs.tsx" + }, + { + "path": "registry/commandly/tool-editor/help-menu.tsx", + "type": "registry:component", + "target": "components/commandly/tool-editor/help-menu.tsx" + }, + { + "path": "registry/commandly/tool-editor/dialogs/parameter-details-dialog.tsx", + "type": "registry:component", + "target": "components/commandly/tool-editor/dialogs/parameter-details-dialog.tsx" + }, + { + "path": "registry/commandly/tool-editor/dialogs/exclusion-groups-dialog.tsx", + "type": "registry:component", + "target": "components/commandly/tool-editor/dialogs/exclusion-groups-dialog.tsx" + }, + { + "path": "registry/commandly/tool-editor/dialogs/tool-details-dialog.tsx", + "type": "registry:component", + "target": "components/commandly/tool-editor/dialogs/tool-details-dialog.tsx" + }, + { + "path": "registry/commandly/tool-editor/dialogs/command-dialog.tsx", + "type": "registry:component", + "target": "components/commandly/tool-editor/dialogs/command-dialog.tsx" + }, + { + "path": "registry/commandly/tool-editor/dialogs/saved-commands-dialog.tsx", + "type": "registry:component", + "target": "components/commandly/tool-editor/dialogs/saved-commands-dialog.tsx" + }, + { + "path": "registry/commandly/generated-command.tsx", + "type": "registry:component", + "target": "components/commandly/generated-command.tsx" + }, + { + "path": "registry/commandly/runtime-preview.tsx", + "type": "registry:component", + "target": "components/commandly/runtime-preview.tsx" + }, + { + "path": "registry/commandly/json-output.tsx", + "type": "registry:component", + "target": "components/commandly/json-output.tsx" + }, + { + "path": "registry/commandly/lib/types/commandly.ts", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/types/commandly-nested.ts", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly.ts", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly-nested.ts", + "type": "registry:lib" + } + ] + }, + { + "name": "generated-command", + "type": "registry:component", + "title": "Generated Command", + "description": "A component that generates CLI commands based on tool configuration and parameter values with copy and save functionality.", + "dependencies": ["react", "lucide-react", "sonner"], + "registryDependencies": ["button"], + "files": [ + { + "path": "registry/commandly/generated-command.tsx", + "type": "registry:component", + "target": "components/commandly/generated-command.tsx" + }, + { + "path": "registry/commandly/lib/types/commandly.ts", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/types/commandly-nested.ts", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly.ts", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly-nested.ts", + "type": "registry:lib" + } + ] + }, + { + "name": "json-output", + "type": "registry:component", + "title": "JSON Output", + "description": "A component for displaying formatted JSON output with syntax highlighting and copy functionality.", + "dependencies": ["react"], + "registryDependencies": ["button", "scroll-area"], + "files": [ + { + "path": "registry/commandly/json-output.tsx", + "type": "registry:component", + "target": "components/commandly/json-output.tsx" + }, + { + "path": "registry/commandly/lib/types/commandly.ts", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/types/commandly-nested.ts", + "type": "registry:lib" + } + ] + }, + { + "name": "runtime-preview", + "type": "registry:component", + "title": "Runtime Preview", + "description": "A component that provides real-time preview of CLI command execution and output.", + "dependencies": ["react"], + "registryDependencies": ["button", "scroll-area", "tabs"], + "files": [ + { + "path": "registry/commandly/runtime-preview.tsx", + "type": "registry:component", + "target": "components/commandly/runtime-preview.tsx" + }, + { + "path": "registry/commandly/lib/types/commandly.ts", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/types/commandly-nested.ts", + "type": "registry:lib" + } + ] + }, + { + "name": "commandly-types", + "type": "registry:lib", + "title": "Commandly Types", + "description": "TypeScript type definitions for the Commandly tool editor system including schemas for tools, commands, and parameters.", + "dependencies": ["zod"], + "files": [ + { + "path": "registry/commandly/lib/types/commandly.ts", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/types/commandly-nested.ts", + "type": "registry:lib" + } + ] + }, + { + "name": "commandly-utils", + "type": "registry:lib", + "title": "Commandly Utils", + "description": "Utility functions for the Commandly tool editor system including command generation and parameter handling.", + "dependencies": ["react"], + "registryDependencies": [], + "files": [ + { + "path": "registry/commandly/lib/utils/commandly.ts", + "type": "registry:lib" + }, + { + "path": "registry/commandly/lib/utils/commandly-nested.ts", + "type": "registry:lib" + } + ] + } + ] +} diff --git a/tests/components/tool-editor-ui/generated-command.test.tsx b/registry/commandly/__tests__/generated-command.test.tsx similarity index 79% rename from tests/components/tool-editor-ui/generated-command.test.tsx rename to registry/commandly/__tests__/generated-command.test.tsx index 14b5bac..49e26a6 100644 --- a/tests/components/tool-editor-ui/generated-command.test.tsx +++ b/registry/commandly/__tests__/generated-command.test.tsx @@ -1,7 +1,7 @@ -import { render, screen } from "@testing-library/react"; -import { GeneratedCommand } from "@/components/tool-editor-ui/generated-command"; +import { render } from "@testing-library/react"; import { vi } from "vitest"; -import { toolBuilderStore } from "@/components/tool-editor-ui/tool-editor.store"; +import { GeneratedCommand } from "../generated-command"; +import { toolBuilderStore } from "../tool-editor/tool-editor.store"; vi.mock("../tool-editor.store", () => ({ toolBuilderStore: { diff --git a/tests/components/tool-editor-ui/json-output.test.tsx b/registry/commandly/__tests__/json-output.test.tsx similarity index 80% rename from tests/components/tool-editor-ui/json-output.test.tsx rename to registry/commandly/__tests__/json-output.test.tsx index 85d11d3..7526fde 100644 --- a/tests/components/tool-editor-ui/json-output.test.tsx +++ b/registry/commandly/__tests__/json-output.test.tsx @@ -1,10 +1,10 @@ import { render, screen } from "@testing-library/react"; -import { JsonOutput } from "@/components/tool-editor-ui/json-output"; -import { defaultTool } from "@/lib/utils/tool-editor"; +import { defaultTool } from "@/registry/commandly/lib/utils/commandly"; import { OnUrlUpdateFunction, withNuqsTestingAdapter } from "nuqs/adapters/testing"; +import { JsonOutput } from "../json-output"; describe("JsonOutput", () => { it("renders output type label", () => { diff --git a/tests/components/tool-editor-ui/runtime-preview.test.tsx b/registry/commandly/__tests__/runtime-preview.test.tsx similarity index 50% rename from tests/components/tool-editor-ui/runtime-preview.test.tsx rename to registry/commandly/__tests__/runtime-preview.test.tsx index e336bbb..4d45e65 100644 --- a/tests/components/tool-editor-ui/runtime-preview.test.tsx +++ b/registry/commandly/__tests__/runtime-preview.test.tsx @@ -1,13 +1,14 @@ import { render, screen } from "@testing-library/react"; -import { RuntimePreview } from "@/components/tool-editor-ui/runtime-preview"; +import { RuntimePreview } from "../runtime-preview"; +import { defaultTool } from "@/registry/commandly/lib/utils/commandly"; describe("RuntimePreview", () => { it("renders no parameters message if none", () => { render( {}} /> ); expect(screen.getByText(/No parameters available/)).toBeInTheDocument(); diff --git a/tests/components/tool-editor-ui/command-tree.test.tsx b/registry/commandly/__tests__/tool-editor/command-tree.test.tsx similarity index 99% rename from tests/components/tool-editor-ui/command-tree.test.tsx rename to registry/commandly/__tests__/tool-editor/command-tree.test.tsx index eb7a557..cfc8dae 100644 --- a/tests/components/tool-editor-ui/command-tree.test.tsx +++ b/registry/commandly/__tests__/tool-editor/command-tree.test.tsx @@ -5,13 +5,14 @@ import { waitFor, act } from "@testing-library/react"; -import { CommandTree } from "@/components/tool-editor-ui/command-tree"; + +import { defaultTool } from "@/registry/commandly/lib/utils/commandly"; +import { Tool } from "@/registry/commandly/lib/types/commandly"; +import { CommandTree } from "../../tool-editor/command-tree"; import { ToolBuilderState, toolBuilderStore -} from "@/components/tool-editor-ui/tool-editor.store"; -import { defaultTool } from "@/lib/utils/tool-editor"; -import { Tool } from "@/lib/types/tool-editor"; +} from "../../tool-editor/tool-editor.store"; const createComplexTool = (): Tool => { return { diff --git a/tests/components/tool-editor-ui/dialogs/command-dialog.test.tsx b/registry/commandly/__tests__/tool-editor/dialogs/command-dialog.test.tsx similarity index 98% rename from tests/components/tool-editor-ui/dialogs/command-dialog.test.tsx rename to registry/commandly/__tests__/tool-editor/dialogs/command-dialog.test.tsx index 6f4d0f0..f3c28bd 100644 --- a/tests/components/tool-editor-ui/dialogs/command-dialog.test.tsx +++ b/registry/commandly/__tests__/tool-editor/dialogs/command-dialog.test.tsx @@ -1,12 +1,13 @@ import { render, screen, fireEvent } from "@testing-library/react"; -import { CommandDialog } from "@/components/tool-editor-ui/dialogs/command-dialog"; + +import { defaultTool } from "@/registry/commandly/lib/utils/commandly"; +import { Command } from "@/registry/commandly/lib/types/commandly"; import { ToolBuilderState, toolBuilderStore, toolBuilderActions -} from "@/components/tool-editor-ui/tool-editor.store"; -import { defaultTool } from "@/lib/utils/tool-editor"; -import { Command } from "@/lib/types/tool-editor"; +} from "@/registry/commandly/tool-editor/tool-editor.store"; +import { CommandDialog } from "@/registry/commandly/tool-editor/dialogs/command-dialog"; const createTestCommand = (overrides: Partial = {}): Command => ({ id: "01979f6d-f205-73e3-a176-4456d7bf7eb3", @@ -29,7 +30,8 @@ const createTestState = ( dialogs: { editTool: false, savedCommands: false, - exclusionGroups: false + exclusionGroups: false, + parameterDetails: false } }); diff --git a/tests/components/tool-editor-ui/dialogs/parameter-details-dialog.test.tsx b/registry/commandly/__tests__/tool-editor/dialogs/parameter-details-dialog.test.tsx similarity index 98% rename from tests/components/tool-editor-ui/dialogs/parameter-details-dialog.test.tsx rename to registry/commandly/__tests__/tool-editor/dialogs/parameter-details-dialog.test.tsx index 9fd1424..08de2c3 100644 --- a/tests/components/tool-editor-ui/dialogs/parameter-details-dialog.test.tsx +++ b/registry/commandly/__tests__/tool-editor/dialogs/parameter-details-dialog.test.tsx @@ -1,12 +1,13 @@ import { render, screen, fireEvent, act } from "@testing-library/react"; -import { ParameterDetailsDialog } from "@/components/tool-editor-ui/dialogs/parameter-details-dialog"; + +import { defaultTool } from "@/registry/commandly/lib/utils/commandly"; +import { Parameter, Command } from "@/registry/commandly/lib/types/commandly"; +import { ParameterDetailsDialog } from "@/registry/commandly/tool-editor/dialogs/parameter-details-dialog"; import { ToolBuilderState, toolBuilderStore, toolBuilderActions -} from "@/components/tool-editor-ui/tool-editor.store"; -import { defaultTool } from "@/lib/utils/tool-editor"; -import { Parameter, Command } from "@/lib/types/tool-editor"; +} from "@/registry/commandly/tool-editor/tool-editor.store"; const createTestParameter = ( overrides: Partial = {} diff --git a/tests/components/tool-editor-ui/help-menu.test.tsx b/registry/commandly/__tests__/tool-editor/help-menu.test.tsx similarity index 87% rename from tests/components/tool-editor-ui/help-menu.test.tsx rename to registry/commandly/__tests__/tool-editor/help-menu.test.tsx index f3aabee..8067653 100644 --- a/tests/components/tool-editor-ui/help-menu.test.tsx +++ b/registry/commandly/__tests__/tool-editor/help-menu.test.tsx @@ -1,6 +1,6 @@ import { render, screen } from "@testing-library/react"; -import { HelpMenu } from "@/components/tool-editor-ui/help-menu"; import { vi } from "vitest"; +import { HelpMenu } from "../../tool-editor/help-menu"; vi.mock("../tool-editor.store", () => ({ toolBuilderStore: { diff --git a/tests/components/tool-editor-ui/parameter-list.test.tsx b/registry/commandly/__tests__/tool-editor/parameter-list.test.tsx similarity index 96% rename from tests/components/tool-editor-ui/parameter-list.test.tsx rename to registry/commandly/__tests__/tool-editor/parameter-list.test.tsx index fd240fd..9fddd13 100644 --- a/tests/components/tool-editor-ui/parameter-list.test.tsx +++ b/registry/commandly/__tests__/tool-editor/parameter-list.test.tsx @@ -1,11 +1,15 @@ import { render, screen, fireEvent } from "@testing-library/react"; -import { ParameterList } from "@/components/tool-editor-ui/parameter-list"; + +import { defaultTool } from "@/registry/commandly/lib/utils/commandly"; +import { + Parameter, + ExclusionGroup +} from "@/registry/commandly/lib/types/commandly"; +import { ParameterList } from "../../tool-editor/parameter-list"; import { ToolBuilderState, toolBuilderStore -} from "@/components/tool-editor-ui/tool-editor.store"; -import { defaultTool } from "@/lib/utils/tool-editor"; -import { Parameter, ExclusionGroup } from "@/lib/types/tool-editor"; +} from "../../tool-editor/tool-editor.store"; const createTestParameter = ( overrides: Partial = {} @@ -606,19 +610,6 @@ describe("ParameterList - Rendering & Structure", () => { expect(paramCard?.textContent).not.toContain("("); }); - it("handles when selectedCommand is null", () => { - toolBuilderStore.setState((prev) => ({ - ...prev, - selectedCommand: null, - tool: { ...prev.tool, parameters: [] } - })); - - render(); - - expect(screen.getByText("Parameters (0)")).toBeInTheDocument(); - expect(screen.getByRole("button")).toBeInTheDocument(); - }); - it("handles when selectedParameter is null", () => { const parameter = createTestParameter(); toolBuilderStore.setState((prev) => ({ diff --git a/tests/components/tool-editor-ui/preview-tabs.test.tsx b/registry/commandly/__tests__/tool-editor/preview-tabs.test.tsx similarity index 93% rename from tests/components/tool-editor-ui/preview-tabs.test.tsx rename to registry/commandly/__tests__/tool-editor/preview-tabs.test.tsx index 021a367..16a86f5 100644 --- a/tests/components/tool-editor-ui/preview-tabs.test.tsx +++ b/registry/commandly/__tests__/tool-editor/preview-tabs.test.tsx @@ -1,10 +1,10 @@ import { render, screen } from "@testing-library/react"; -import { PreviewTabs } from "@/components/tool-editor-ui/preview-tabs"; import { vi } from "vitest"; import { OnUrlUpdateFunction, withNuqsTestingAdapter } from "nuqs/adapters/testing"; +import { PreviewTabs } from "../../tool-editor/preview-tabs"; vi.mock("../tool-editor.store", () => ({ toolBuilderStore: { diff --git a/tests/components/tool-editor-ui/tool-editor.test.tsx b/registry/commandly/__tests__/tool-editor/tool-editor.test.tsx similarity index 91% rename from tests/components/tool-editor-ui/tool-editor.test.tsx rename to registry/commandly/__tests__/tool-editor/tool-editor.test.tsx index df35f5e..ed62d61 100644 --- a/tests/components/tool-editor-ui/tool-editor.test.tsx +++ b/registry/commandly/__tests__/tool-editor/tool-editor.test.tsx @@ -1,11 +1,11 @@ import { render, screen } from "@testing-library/react"; -import ToolEditor from "@/components/tool-editor-ui/tool-editor"; import { vi } from "vitest"; -import { defaultTool } from "@/lib/utils/tool-editor"; +import { defaultTool } from "@/registry/commandly/lib/utils/commandly"; import { withNuqsTestingAdapter, type OnUrlUpdateFunction } from "nuqs/adapters/testing"; +import ToolEditor from "../../tool-editor/tool-editor"; vi.mock("../tool-editor.store", () => ({ toolBuilderStore: { diff --git a/src/components/tool-editor-ui/generated-command.tsx b/registry/commandly/generated-command.tsx similarity index 97% rename from src/components/tool-editor-ui/generated-command.tsx rename to registry/commandly/generated-command.tsx index fe49eeb..ab021a0 100644 --- a/src/components/tool-editor-ui/generated-command.tsx +++ b/registry/commandly/generated-command.tsx @@ -2,13 +2,13 @@ import { useEffect, useState, useMemo } from "react"; import { TerminalIcon, CopyIcon, SaveIcon } from "lucide-react"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; -import { getCommandPath } from "@/lib/utils/tool-editor"; +import { getCommandPath } from "@/registry/commandly/lib/utils/commandly"; import { Parameter, ParameterValue, Tool, Command -} from "@/lib/types/tool-editor"; +} from "@/registry/commandly/lib/types/commandly"; interface GeneratedCommandProps { tool: Tool; diff --git a/src/components/tool-editor-ui/json-output.tsx b/registry/commandly/json-output.tsx similarity index 83% rename from src/components/tool-editor-ui/json-output.tsx rename to registry/commandly/json-output.tsx index 4a48b4c..5b77e37 100644 --- a/src/components/tool-editor-ui/json-output.tsx +++ b/registry/commandly/json-output.tsx @@ -2,24 +2,28 @@ import { useEffect, useState } from "react"; import { Button } from "@/components/ui/button"; import { CheckIcon, ChevronsUpDownIcon, CopyIcon } from "lucide-react"; import { cn } from "@/lib/utils"; -import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover"; +import { + Popover, + PopoverContent, + PopoverTrigger +} from "@/components/ui/popover"; import { Command as UICommand, CommandGroup, CommandItem, CommandList -} from "../ui/command"; +} from "@/components/ui/command"; import { Card, CardAction, CardContent, CardHeader, CardTitle -} from "../ui/card"; -import { exportToStructuredJSON } from "@/lib/utils/tool-editor"; -import { convertToNestedStructure } from "@/lib/utils/tool-editor-nested"; -import { Tool } from "@/lib/types/tool-editor"; -import { ScrollArea, ScrollBar } from "../ui/scroll-area"; +} from "@/components/ui/card"; +import { exportToStructuredJSON } from "@/registry/commandly/lib/utils/commandly"; +import { convertToNestedStructure } from "@/registry/commandly/lib/utils/commandly-nested"; +import { Tool } from "@/registry/commandly/lib/types/commandly"; +import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"; import { toast } from "sonner"; import { useQueryState } from "nuqs"; @@ -104,8 +108,11 @@ export function JsonOutput({ tool }: JsonTypeComponentProps) { - -
+        
+          
             {jsonString}
           
diff --git a/src/lib/types/tool-editor-nested.ts b/registry/commandly/lib/types/commandly-nested.ts similarity index 97% rename from src/lib/types/tool-editor-nested.ts rename to registry/commandly/lib/types/commandly-nested.ts index c590404..878c88f 100644 --- a/src/lib/types/tool-editor-nested.ts +++ b/registry/commandly/lib/types/commandly-nested.ts @@ -1,13 +1,13 @@ -import type { +import { + ParameterValidation, ParameterDependencyType, - ExclusionType, + ParameterType, ParameterDataType, ParameterMetadata, - ParameterType, - ParameterValidation, + ExclusionType, SupportedToolInputType, SupportedToolOutputType -} from "./tool-editor"; +} from "../../types"; export interface NestedCommand { name: string; @@ -69,7 +69,7 @@ export interface NestedTool { displayName: string; description?: string; version?: string; - url: string; + url?: string; globalParameters: NestedParameter[]; commands: NestedCommand[]; exclusionGroups: NestedExclusionGroup[]; diff --git a/src/lib/types/tool-editor.ts b/registry/commandly/lib/types/commandly.ts similarity index 99% rename from src/lib/types/tool-editor.ts rename to registry/commandly/lib/types/commandly.ts index c9835c4..79a90ca 100644 --- a/src/lib/types/tool-editor.ts +++ b/registry/commandly/lib/types/commandly.ts @@ -77,7 +77,7 @@ export type ParameterDataType = z.infer; export const ParameterSchema = z.object({ id: z.string(), name: z.string(), - commandId: z.uuidv7(), + commandId: z.uuidv7().optional(), description: z.string(), metadata: ParameterMetadataSchema.optional(), parameterType: ParameterTypeSchema, diff --git a/src/lib/utils/tool-editor-nested.ts b/registry/commandly/lib/utils/commandly-nested.ts similarity index 92% rename from src/lib/utils/tool-editor-nested.ts rename to registry/commandly/lib/utils/commandly-nested.ts index 36e14e3..87d0a43 100644 --- a/src/lib/utils/tool-editor-nested.ts +++ b/registry/commandly/lib/utils/commandly-nested.ts @@ -1,10 +1,14 @@ -import type { Tool, Command, Parameter } from "@/lib/types/tool-editor"; import type { - NestedTool, + Tool, + Command, + Parameter +} from "@/registry/commandly/lib/types/commandly"; +import { NestedCommand, + NestedExclusionGroup, NestedParameter, - NestedExclusionGroup -} from "@/lib/types/tool-editor-nested"; + NestedTool +} from "../types/commandly-nested"; export const convertToNestedStructure = (tool: Tool): NestedTool => { const globalParameters = tool.parameters.filter((p) => p.isGlobal); @@ -72,6 +76,7 @@ export const convertToNestedStructure = (tool: Tool): NestedTool => { return { name: tool.name, + url: tool.url, displayName: tool.displayName, description: tool.description, version: tool.version, diff --git a/src/lib/utils/tool-editor.ts b/registry/commandly/lib/utils/commandly.ts similarity index 99% rename from src/lib/utils/tool-editor.ts rename to registry/commandly/lib/utils/commandly.ts index b2e1b47..f57b900 100644 --- a/src/lib/utils/tool-editor.ts +++ b/registry/commandly/lib/utils/commandly.ts @@ -3,7 +3,7 @@ import type { Parameter, SavedCommand, Tool -} from "@/lib/types/tool-editor"; +} from "@/registry/commandly/lib/types/commandly"; import { v7 as uuidv7 } from "uuid"; export const buildCommandHierarchy = (commands: Command[]): Command[] => { diff --git a/src/components/tool-editor-ui/runtime-preview.tsx b/registry/commandly/runtime-preview.tsx similarity index 97% rename from src/components/tool-editor-ui/runtime-preview.tsx rename to registry/commandly/runtime-preview.tsx index ed0e498..899fe27 100644 --- a/src/components/tool-editor-ui/runtime-preview.tsx +++ b/registry/commandly/runtime-preview.tsx @@ -1,4 +1,3 @@ -import { useEffect } from "react"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; @@ -12,9 +11,16 @@ import { SelectValue } from "@/components/ui/select"; import { InfoIcon } from "lucide-react"; -import { Parameter, ParameterValue } from "@/lib/types/tool-editor"; -import { Command, Tool } from "@/lib/types/tool-editor"; -import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip"; +import { + Parameter, + ParameterValue +} from "@/registry/commandly/lib/types/commandly"; +import { Command, Tool } from "@/registry/commandly/lib/types/commandly"; +import { + Tooltip, + TooltipContent, + TooltipTrigger +} from "@/components/ui/tooltip"; import React from "react"; const findDefaultCommand = (tool: Tool): Command | null => { diff --git a/src/components/tool-editor-ui/command-tree.tsx b/registry/commandly/tool-editor/command-tree.tsx similarity index 96% rename from src/components/tool-editor-ui/command-tree.tsx rename to registry/commandly/tool-editor/command-tree.tsx index 77fa348..2626933 100644 --- a/src/components/tool-editor-ui/command-tree.tsx +++ b/registry/commandly/tool-editor/command-tree.tsx @@ -2,7 +2,7 @@ import { useState, useEffect, ReactNode } from "react"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { ScrollArea } from "@/components/ui/scroll-area"; -import { Command } from "@/lib/types/tool-editor"; +import { Command } from "@/registry/commandly/lib/types/commandly"; import { ChevronDownIcon, ChevronRightIcon, @@ -10,12 +10,9 @@ import { PlusIcon, Trash2Icon } from "lucide-react"; -import { CommandDialog } from "./dialogs/command-dialog"; +import { CommandDialog } from "../tool-editor/dialogs/command-dialog"; import { useStore } from "@tanstack/react-store"; -import { - toolBuilderStore, - toolBuilderActions -} from "@/components/tool-editor-ui/tool-editor.store"; +import { toolBuilderStore, toolBuilderActions } from "./tool-editor.store"; export function CommandTree() { const tool = useStore(toolBuilderStore, (state) => state.tool); diff --git a/src/components/tool-editor-ui/dialogs/command-dialog.tsx b/registry/commandly/tool-editor/dialogs/command-dialog.tsx similarity index 95% rename from src/components/tool-editor-ui/dialogs/command-dialog.tsx rename to registry/commandly/tool-editor/dialogs/command-dialog.tsx index f1d515e..e0ce262 100644 --- a/src/components/tool-editor-ui/dialogs/command-dialog.tsx +++ b/registry/commandly/tool-editor/dialogs/command-dialog.tsx @@ -11,14 +11,11 @@ import { DialogFooter, DialogDescription } from "@/components/ui/dialog"; -import { Command } from "@/lib/types/tool-editor"; +import { Command } from "@/registry/commandly/lib/types/commandly"; import { TerminalIcon } from "lucide-react"; import { useState } from "react"; import { useStore } from "@tanstack/react-store"; -import { - toolBuilderActions, - toolBuilderStore -} from "@/components/tool-editor-ui/tool-editor.store"; +import { toolBuilderActions, toolBuilderStore } from "../tool-editor.store"; interface CommandDialogProps { isOpen: boolean; diff --git a/src/components/tool-editor-ui/dialogs/exclusion-groups-dialog.tsx b/registry/commandly/tool-editor/dialogs/exclusion-groups-dialog.tsx similarity index 98% rename from src/components/tool-editor-ui/dialogs/exclusion-groups-dialog.tsx rename to registry/commandly/tool-editor/dialogs/exclusion-groups-dialog.tsx index d595877..1ea6dfc 100644 --- a/src/components/tool-editor-ui/dialogs/exclusion-groups-dialog.tsx +++ b/registry/commandly/tool-editor/dialogs/exclusion-groups-dialog.tsx @@ -14,7 +14,7 @@ import { SelectTrigger, SelectValue } from "@/components/ui/select"; -import { ExclusionGroup } from "@/lib/types/tool-editor"; +import { ExclusionGroup } from "@/registry/commandly/lib/types/commandly"; import { PlusIcon, TrashIcon } from "lucide-react"; import { useState } from "react"; import { useStore } from "@tanstack/react-store"; @@ -22,7 +22,7 @@ import { toolBuilderStore, toolBuilderActions, toolBuilderSelectors -} from "@/components/tool-editor-ui/tool-editor.store"; +} from "../tool-editor.store"; export function ExclusionGroupsDialog() { const selectedCommand = useStore( diff --git a/src/components/tool-editor-ui/dialogs/parameter-details-dialog.tsx b/registry/commandly/tool-editor/dialogs/parameter-details-dialog.tsx similarity index 96% rename from src/components/tool-editor-ui/dialogs/parameter-details-dialog.tsx rename to registry/commandly/tool-editor/dialogs/parameter-details-dialog.tsx index 213d3e7..b9ac92e 100644 --- a/src/components/tool-editor-ui/dialogs/parameter-details-dialog.tsx +++ b/registry/commandly/tool-editor/dialogs/parameter-details-dialog.tsx @@ -21,16 +21,6 @@ import { SelectValue } from "@/components/ui/select"; import { Separator } from "@/components/ui/separator"; -import { - Parameter, - ParameterDependency, - ParameterValidation, - ParameterEnumValue, - ParameterType, - ParameterDataType, - ParameterDependencyType as DependencyType, - ParameterValidationType as ValidationType -} from "@/lib/types/tool-editor"; import { FileTextIcon, FlagIcon, @@ -41,13 +31,20 @@ import { Trash2Icon } from "lucide-react"; import { useStore } from "@tanstack/react-store"; -import { - toolBuilderStore, - toolBuilderActions -} from "@/components/tool-editor-ui/tool-editor.store"; -import { validateDefaultValue } from "@/lib/utils/tool-editor"; +import { validateDefaultValue } from "@/registry/commandly/lib/utils/commandly"; import { v7 as uuidv7 } from "uuid"; -import { TagsComponent } from "@/components/tags"; +import { toolBuilderActions, toolBuilderStore } from "../tool-editor.store"; +import { + Parameter, + ParameterDataType, + ParameterDependency, + ParameterDependencyType, + ParameterEnumValue, + ParameterType, + ParameterValidation, + ParameterValidationType +} from "@/registry/commandly/lib/types/commandly"; +import { TagsInput } from "@/registry/commandly/ui/tags-input"; export function ParameterDetailsDialog() { const selectedParameter = useStore( @@ -395,14 +392,16 @@ export function ParameterDetailsDialog() { - { - if (!onOpen) { +
+ + { updateParameter({ metadata: { tags } }); - } - }} - /> + }} + placeholder="Add tags" + /> +
@@ -435,7 +434,7 @@ export function ParameterDetailsDialog() { > { + onValueChange={(value: ParameterValidationType) => { const updatedValidations = parameter.validations?.map( (v) => v.id === validation.id diff --git a/registry/commandly/tool-editor/dialogs/saved-commands-dialog.tsx b/registry/commandly/tool-editor/dialogs/saved-commands-dialog.tsx new file mode 100644 index 0000000..02143a5 --- /dev/null +++ b/registry/commandly/tool-editor/dialogs/saved-commands-dialog.tsx @@ -0,0 +1,110 @@ +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogFooter +} from "@/components/ui/dialog"; +import { SaveIcon, CopyIcon, Trash2Icon } from "lucide-react"; +import { toast } from "sonner"; +import { SavedCommand } from "@/registry/commandly/lib/types/commandly"; +import { toolBuilderActions, toolBuilderStore } from "../tool-editor.store"; +import { useStore } from "@tanstack/react-store"; + +interface SavedCommandsDialogProps { + savedCommands: SavedCommand[]; + onDeleteCommand: (commandId: string) => void; +} + +export function SavedCommandsDialog({ + savedCommands, + onDeleteCommand +}: SavedCommandsDialogProps) { + const copyCommand = (command: string) => { + navigator.clipboard.writeText(command); + toast("Command copied!"); + }; + + const deleteCommand = (commandId: string) => { + onDeleteCommand(commandId); + toast("Command Removed", { + description: "Saved command has been removed successfully." + }); + }; + + const open = useStore( + toolBuilderStore, + (state) => state.dialogs.savedCommands + ); + + return ( + + toolBuilderActions.setDialogOpen("savedCommands", false) + } + > + + + + + Saved Commands + + + + {savedCommands.length === 0 ? ( +
+ +

+ No saved commands yet. Generate and save commands to see them + here. +

+
+ ) : ( +
+ {savedCommands && + savedCommands.length > 0 && + savedCommands.map((savedCommand) => ( +
+
+ + +
+
+                    {savedCommand.command}
+                  
+
+ ))} +
+ )} + + + + +
+
+ ); +} diff --git a/src/components/tool-editor-ui/dialogs/tool-details-dialog.tsx b/registry/commandly/tool-editor/dialogs/tool-details-dialog.tsx similarity index 92% rename from src/components/tool-editor-ui/dialogs/tool-details-dialog.tsx rename to registry/commandly/tool-editor/dialogs/tool-details-dialog.tsx index 3f7becf..57dfde5 100644 --- a/src/components/tool-editor-ui/dialogs/tool-details-dialog.tsx +++ b/registry/commandly/tool-editor/dialogs/tool-details-dialog.tsx @@ -11,16 +11,13 @@ import { } from "@/components/ui/dialog"; import { SettingsIcon } from "lucide-react"; import { useStore } from "@tanstack/react-store"; -import { - toolBuilderStore, - toolBuilderActions -} from "@/components/tool-editor-ui/tool-editor.store"; import { MultiSelect } from "@/components/ui/multi-select"; import { SupportedToolInputType, SupportedToolOutputType -} from "@/lib/types/tool-editor"; -import { TagsComponent } from "@/components/tags"; +} from "@/registry/commandly/lib/types/commandly"; +import { toolBuilderActions, toolBuilderStore } from "../tool-editor.store"; +import { TagsInput } from "@/registry/commandly/ui/tags-input"; const supportedInputOptions = [ { value: "StandardInput", label: "Standard Input" }, @@ -138,14 +135,18 @@ export function ToolDetailsDialog() { /> - { - if (!onOpen) { + +
+ + { toolBuilderActions.updateTool({ tags }); - } - }} - /> + }} + placeholder="Add tags" + /> +
+